On a 'console server' (hooked up to the (serial) consoles of multiple
other servers) I'm using script(1) to capture the console outputs; the
typescript files end up being the console logs.

In order to allow newsyslog to rotate those typescripts, I added an
option (-P) to script(1) which causes it to write a pidfile.

I'm not asking for this to be merged into NetBSD, but I also wouldn't
mind.  Maybe somebody finds it useful.


diff a/usr.bin/script/script.1 b/usr.bin/script/script.1
--- a/usr.bin/script/script.1
+++ b/usr.bin/script/script.1
@@ -39,6 +39,7 @@
 .Nm
 .Op Fl adefpqr
 .Op Fl c Ar command
+.Op Fl P Ar pidfile
 .Op Ar file
 .Sh DESCRIPTION
 .Nm
@@ -86,6 +87,9 @@ This is useful for watching the script output in real time.
 Play back a session recorded with the
 .Fl r
 flag in real time.
+.It Fl P Ar pidfile
+Write the PID of the writing subprocess into
+.Ar pidfile .
 .It Fl q
 Be quiet, and don't output started and ended lines.
 .It Fl r
@@ -131,6 +135,10 @@ is not set, the Bourne shell
 is assumed.
 (Most shells set this variable automatically).
 .El
+.Sh SIGNALS
+Upon receipt of SIGUSR1, the typescript will be re-opened,
+so as to allow rotating long-term typescripts e.g. via
+newsyslog(8).
 .Sh SEE ALSO
 .Xr csh 1
 (for the
diff a/usr.bin/script/script.c b/usr.bin/script/script.c
--- a/usr.bin/script/script.c
+++ b/usr.bin/script/script.c
@@ -80,6 +80,8 @@ static size_t outcc;
 static int     usesleep, rawout;
 static int     quiet, flush;
 static const char *fname;
+static const char *fmode;
+static char    *pfile;
 
 static volatile        sig_atomic_t die = 0;   /* exit if 1 */
 static int     cstat = EXIT_SUCCESS;   /* cmd. exit status */
@@ -94,6 +96,7 @@ static sig_t  xsignal(int, sig_t);
 __dead static void     dooutput(void);
 static void    finish(int);
 static void    scriptflush(int);
+static void    scriptreopen(int);
 static void    record(FILE *, char *, size_t, int);
 static void    consume(FILE *, off_t, char *, int);
 __dead static void     playback(FILE *);
@@ -116,13 +119,13 @@ main(int argc, char *argv[])
        quiet = 0;
        flush = 0;
        command = NULL;
-       while ((ch = getopt(argc, argv, "ac:defpqr")) != -1)
+       while ((ch = getopt(argc, argv, "ac:defpP:qr")) != -1)
                switch(ch) {
                case 'a':
                        aflg = 1;
                        break;
                case 'c':
-                       command = optarg;
+                       command = strdup(optarg);
                        break;
                case 'd':
                        usesleep = 0;
@@ -136,6 +139,9 @@ main(int argc, char *argv[])
                case 'p':
                        pflg = 1;
                        break;
+               case 'P':
+                       pfile = strdup(optarg);
+                       break;
                case 'q':
                        quiet = 1;
                        break;
@@ -145,7 +151,7 @@ main(int argc, char *argv[])
                case '?':
                default:
                        (void)fprintf(stderr,
-                           "Usage: %s [-c <command>][-adefpqr] [file]\n",
+                           "Usage: %s [-c <command>][-P <pidfile>][-adefpqr] 
[file]\n",
                            getprogname());
                        exit(EXIT_FAILURE);
                }
@@ -157,7 +163,8 @@ main(int argc, char *argv[])
        else
                fname = "typescript";
 
-       if ((fscript = fopen(fname, pflg ? "r" : aflg ? "a" : "w")) == NULL)
+       fmode = pflg ? "r" : aflg ? "a" : "w";
+       if ((fscript = fopen(fname, fmode)) == NULL)
                err(EXIT_FAILURE, "fopen %s", fname);
 
        if (pflg)
@@ -185,6 +192,7 @@ main(int argc, char *argv[])
                (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
        }
 
+       (void)signal(SIGUSR1, SIG_IGN);
        (void)xsignal(SIGCHLD, finish);
        child = fork();
        if (child == -1) {
@@ -278,6 +286,18 @@ dooutput(void)
        value.it_interval.tv_usec = 0;
        value.it_value = value.it_interval;
        (void)setitimer(ITIMER_REAL, &value, NULL);
+       if (pfile) {
+               FILE *pf = fopen(pfile, "w");
+               if (pf) {
+                       fprintf(pf, "%d\n", (int)getpid());
+                       fclose(pf);
+               } else {
+                       warn("fopen %s", pfile);
+                       free(pfile);
+                       pfile = NULL;
+               }
+       }
+       (void)signal(SIGUSR1, scriptreopen);
        for (;;) {
                scc = read(master, obuf, sizeof(obuf));
                if (scc <= 0)
@@ -295,6 +315,18 @@ dooutput(void)
        done(cstat);
 }
 
+static void
+scriptreopen(int signo)
+{
+       (void)fclose(fscript);
+       outcc = 0;
+       fscript = fopen(fname, fmode);
+       if (outcc) {
+               (void)fflush(fscript);
+               outcc = 0;
+       }
+}
+
 static void
 scriptflush(int signo)
 {
@@ -357,6 +389,8 @@ done(int status)
                if (!quiet)
                        (void)printf("Script done, output file is %s\n", fname);
        }
+       if (pfile)
+               unlink(pfile);
        exit(status);
 }
 

Reply via email to