add new '-c' option which runs a command instead of an interactive shell
authorjasper <jasper@openbsd.org>
Sun, 21 Jan 2018 20:18:20 +0000 (20:18 +0000)
committerjasper <jasper@openbsd.org>
Sun, 21 Jan 2018 20:18:20 +0000 (20:18 +0000)
from Paul de Weerd
ok ian@ job@; manpage bits are ok jmc@

usr.bin/script/script.1
usr.bin/script/script.c

index 3887a77..f10ec2d 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: script.1,v 1.14 2012/01/15 20:06:40 schwarze Exp $
+.\"    $OpenBSD: script.1,v 1.15 2018/01/21 20:18:20 jasper Exp $
 .\"    $NetBSD: script.1,v 1.3 1994/12/21 08:55:41 jtc Exp $
 .\"
 .\" Copyright (c) 1980, 1990, 1993
@@ -30,7 +30,7 @@
 .\"
 .\"    @(#)script.1    8.1 (Berkeley) 6/6/93
 .\"
-.Dd $Mdocdate: January 15 2012 $
+.Dd $Mdocdate: January 21 2018 $
 .Dt SCRIPT 1
 .Os
 .Sh NAME
@@ -39,6 +39,7 @@
 .Sh SYNOPSIS
 .Nm script
 .Op Fl a
+.Op Fl c Ar command
 .Op Ar file
 .Sh DESCRIPTION
 .Nm
@@ -65,9 +66,14 @@ Append the output to
 or
 .Pa typescript ,
 retaining the prior contents.
+.It Fl c Ar command
+Run
+.Ar command
+instead of an interactive shell.
+To run a command with arguments, enclose both in quotes.
 .El
 .Pp
-The script ends when the forked shell exits (a control-D
+The script ends when the forked program exits (a control-D
 .Pq Ql ^D
 to exit
 the Bourne shell
@@ -102,6 +108,11 @@ Name of the shell to be forked by
 If not set, the Bourne shell is assumed.
 (Most shells set this variable automatically.)
 .El
+.Sh EXAMPLES
+Start a virtual machine and log all console output to a file:
+.Bd -literal -offset indent
+$ script -c "vmctl start myvm -c" myvm.typescript
+.Ed
 .Sh HISTORY
 A predecessor called
 .Nm dribble
index 9dea1f1..2e41739 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: script.c,v 1.33 2017/04/12 14:49:05 deraadt Exp $     */
+/*     $OpenBSD: script.c,v 1.34 2018/01/21 20:18:20 jasper Exp $      */
 /*     $NetBSD: script.c,v 1.3 1994/12/21 08:55:43 jtc Exp $   */
 
 /*
@@ -89,7 +89,7 @@ int           istty;
 
 __dead void done(int);
 void dooutput(void);
-void doshell(void);
+void doshell(char *);
 void fail(void);
 void finish(int);
 void scriptflush(int);
@@ -102,17 +102,23 @@ main(int argc, char *argv[])
        struct sigaction sa;
        struct winsize win;
        char ibuf[BUFSIZ];
+       char *cmd;
        ssize_t cc, off;
        int aflg, ch;
 
+       cmd = NULL;
        aflg = 0;
-       while ((ch = getopt(argc, argv, "a")) != -1)
+       while ((ch = getopt(argc, argv, "ac:")) != -1)
                switch(ch) {
                case 'a':
                        aflg = 1;
                        break;
+               case 'c':
+                       cmd = optarg;
+                       break;
                default:
-                       fprintf(stderr, "usage: %s [-a] [file]\n", __progname);
+                       fprintf(stderr, "usage: %s [-a] [-c command] [file]\n",
+                           __progname);
                        exit(1);
                }
        argc -= optind;
@@ -163,7 +169,7 @@ main(int argc, char *argv[])
                if (child)
                        dooutput();
                else
-                       doshell();
+                       doshell(cmd);
        }
 
        bzero(&sa, sizeof sa);
@@ -196,7 +202,6 @@ main(int argc, char *argv[])
        done(sigdeadstatus);
 }
 
-/* ARGSUSED */
 void
 finish(int signo)
 {
@@ -215,7 +220,6 @@ finish(int signo)
        errno = save_errno;
 }
 
-/* ARGSUSED */
 void
 handlesigwinch(int signo)
 {
@@ -294,7 +298,6 @@ dooutput(void)
        done(0);
 }
 
-/* ARGSUSED */
 void
 scriptflush(int signo)
 {
@@ -302,9 +305,10 @@ scriptflush(int signo)
 }
 
 void
-doshell(void)
+doshell(char *cmd)
 {
        char *shell;
+       char *argp[] = {"sh", "-c", NULL, NULL};
 
        shell = getenv("SHELL");
        if (shell == NULL)
@@ -313,8 +317,15 @@ doshell(void)
        (void)close(master);
        (void)fclose(fscript);
        login_tty(slave);
-       execl(shell, shell, "-i", (char *)NULL);
-       warn("%s", shell);
+
+       if (cmd != NULL) {
+               argp[2] = cmd;
+               execv(_PATH_BSHELL, argp);
+               warn("unable to execute %s", _PATH_BSHELL);
+       } else {
+               execl(shell, shell, "-i", (char *)NULL);
+               warn("%s", shell);
+       }
        fail();
 }