updates from Mike to make messages more media independent;
[unix-history] / usr / src / sbin / dump / optr.c
index 136cc5b..e6a33e1 100644 (file)
@@ -1,21 +1,26 @@
-static char *sccsid = "@(#)optr.c      1.3 (Berkeley) %G%";
-#include "dump.h"
-
 /*
 /*
- *     This is from /usr/include/grp.h
- *     That defined struct group, which conflicts
- *     with the struct group defined in param.h
+ * Copyright (c) 1980, 1988 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
  */
  */
-struct Group { /* see getgrent(3) */
-       char    *gr_name;
-       char    *gr_passwd;
-       int     gr_gid;
-       char    **gr_mem;
-};
-struct Group *getgrnam();
+
+#ifndef lint
+static char sccsid[] = "@(#)optr.c     5.4 (Berkeley) %G%";
+#endif /* not lint */
+
+#include "dump.h"
+#include <sys/wait.h>
+#include <errno.h>
+#include <grp.h>
+#include <varargs.h>
+#include "pathnames.h"
+
+static void alarmcatch();
+static void sendmes();
+
 /*
 /*
- *     Query the operator; This fascist piece of code requires
- *     an exact response.
+ *     Query the operator; This previously-fascist piece of code
+ *     no longer requires an exact response.
  *     It is intended to protect dump aborting by inquisitive
  *     people banging on the console terminal to see what is
  *     happening which might cause dump to croak, destroying
  *     It is intended to protect dump aborting by inquisitive
  *     people banging on the console terminal to see what is
  *     happening which might cause dump to croak, destroying
@@ -25,41 +30,40 @@ struct      Group *getgrnam();
  *     that dump needs attention.
  */
 int    timeout;
  *     that dump needs attention.
  */
 int    timeout;
-char   *attnmessage;           /* attemtion message */
+char   *attnmessage;           /* attention message */
+
+int
 query(question)
        char    *question;
 {
        char    replybuffer[64];
 query(question)
        char    *question;
 {
        char    replybuffer[64];
-       int     back;
+       int     back, errcount;
        FILE    *mytty;
 
        FILE    *mytty;
 
-       if ( (mytty = fopen("/dev/tty", "r")) == NULL){
-               msg("fopen on /dev/tty fails\n");
-               abort();
-       }
+       if ((mytty = fopen(_PATH_TTY, "r")) == NULL)
+               quit("fopen on %s fails: %s\n", _PATH_TTY, strerror(errno));
        attnmessage = question;
        timeout = 0;
        alarmcatch();
        attnmessage = question;
        timeout = 0;
        alarmcatch();
-       for(;;){
-               if ( fgets(replybuffer, 63, mytty) == NULL){
-                       if (ferror(mytty)){
-                               clearerr(mytty);
-                               continue;
-                       }
-               } else if ( (strcmp(replybuffer, "yes\n") == 0) ||
-                           (strcmp(replybuffer, "Yes\n") == 0)){
-                               back = 1;
-                               goto done;
-               } else if ( (strcmp(replybuffer, "no\n") == 0) ||
-                           (strcmp(replybuffer, "No\n") == 0)){
-                               back = 0;
-                               goto done;
+       back = -1;
+       errcount = 0;
+       do {
+               if (fgets(replybuffer, 63, mytty) == NULL) {
+                       clearerr(mytty);
+                       if (++errcount > 30)    /* XXX  ugly */
+                               quit("excessive operator query failures\n");
+               } else if (replybuffer[0] == 'y' || replybuffer[0] == 'Y') {
+                       back = 1;
+               } else if (replybuffer[0] == 'n' || replybuffer[0] == 'N') {
+                       back = 0;
                } else {
                } else {
-                       msg("\"Yes\" or \"No\" ONLY!\n");
-                       alarmcatch();
+                       (void) fprintf(stderr,
+                           "  DUMP: \"Yes\" or \"No\"?\n");
+                       (void) fprintf(stderr,
+                           "  DUMP: %s: (\"yes\" or \"no\") ", question);
                }
                }
-       }
-    done:
+       } while (back < 0);
+
        /*
         *      Turn off the alarm, and reset the signal to trap out..
         */
        /*
         *      Turn off the alarm, and reset the signal to trap out..
         */
@@ -69,29 +73,45 @@ query(question)
        fclose(mytty);
        return(back);
 }
        fclose(mytty);
        return(back);
 }
+
+char lastmsg[100];
+
 /*
  *     Alert the console operator, and enable the alarm clock to
  *     sleep for 2 minutes in case nobody comes to satisfy dump
  */
 /*
  *     Alert the console operator, and enable the alarm clock to
  *     sleep for 2 minutes in case nobody comes to satisfy dump
  */
+static void
 alarmcatch()
 {
 alarmcatch()
 {
-       if (timeout)
-               msgtail("\n");
-       msg("NEEDS ATTENTION: %s: (\"yes\" or \"no\") ",
-               attnmessage);
+       if (notify == 0) {
+               if (timeout == 0)
+                       (void) fprintf(stderr,
+                           "  DUMP: %s: (\"yes\" or \"no\") ",
+                           attnmessage);
+               else
+                       msgtail("\7\7");
+       } else {
+               if (timeout) {
+                       msgtail("\n");
+                       broadcast("");          /* just print last msg */
+               }
+               (void) fprintf(stderr,"  DUMP: %s: (\"yes\" or \"no\") ",
+                   attnmessage);
+       }
        signal(SIGALRM, alarmcatch);
        alarm(120);
        timeout = 1;
 }
        signal(SIGALRM, alarmcatch);
        alarm(120);
        timeout = 1;
 }
+
 /*
  *     Here if an inquisitive operator interrupts the dump program
  */
 /*
  *     Here if an inquisitive operator interrupts the dump program
  */
+void
 interrupt()
 {
 interrupt()
 {
-       msg("Interrupt received. Do >>>YOU<<< know what are you doing?\n");
-       if (query("Do you really want to abort dump?"))
+       msg("Interrupt received.\n");
+       if (query("Do you want to abort dump?"))
                dumpabort();
                dumpabort();
-       signal(SIGINT, interrupt);
 }
 
 /*
 }
 
 /*
@@ -99,20 +119,20 @@ interrupt()
  *     operators to the status of dump.
  *     This works much like wall(1) does.
  */
  *     operators to the status of dump.
  *     This works much like wall(1) does.
  */
-struct Group *gp;
+struct group *gp;
 
 /*
  *     Get the names from the group entry "operator" to notify.
  */    
 
 /*
  *     Get the names from the group entry "operator" to notify.
  */    
+void
 set_operators()
 {
        if (!notify)            /*not going to notify*/
                return;
        gp = getgrnam(OPGRENT);
        endgrent();
 set_operators()
 {
        if (!notify)            /*not going to notify*/
                return;
        gp = getgrnam(OPGRENT);
        endgrent();
-       if (gp == (struct Group *)0){
-               msg("No entry in /etc/group for %s.\n",
-                       OPGRENT);
+       if (gp == NULL) {
+               msg("No group entry for %s.\n", OPGRENT);
                notify = 0;
                return;
        }
                notify = 0;
                return;
        }
@@ -125,6 +145,7 @@ struct tm *localclock;
  *     We fork a child to do the actual broadcasting, so
  *     that the process control groups are not messed up
  */
  *     We fork a child to do the actual broadcasting, so
  *     that the process control groups are not messed up
  */
+void
 broadcast(message)
        char    *message;
 {
 broadcast(message)
        char    *message;
 {
@@ -135,6 +156,9 @@ broadcast(message)
        char    **np;
        int     pid, s;
 
        char    **np;
        int     pid, s;
 
+       if (!notify || gp == NULL)
+               return;
+
        switch (pid = fork()) {
        case -1:
                return;
        switch (pid = fork()) {
        case -1:
                return;
@@ -146,24 +170,22 @@ broadcast(message)
                return;
        }
 
                return;
        }
 
-       if (!notify || gp == 0)
-               return;
        clock = time(0);
        localclock = localtime(&clock);
 
        clock = time(0);
        localclock = localtime(&clock);
 
-       if((f_utmp = fopen("/etc/utmp", "r")) == NULL) {
-               msg("Cannot open /etc/utmp\n");
+       if ((f_utmp = fopen(_PATH_UTMP, "r")) == NULL) {
+               msg("Cannot open %s: %s\n", _PATH_UTMP, strerror(errno));
                return;
        }
 
        nusers = 0;
                return;
        }
 
        nusers = 0;
-       while (!feof(f_utmp)){
+       while (!feof(f_utmp)) {
                if (fread(&utmp, sizeof (struct utmp), 1, f_utmp) != 1)
                        break;
                if (utmp.ut_name[0] == 0)
                        continue;
                nusers++;
                if (fread(&utmp, sizeof (struct utmp), 1, f_utmp) != 1)
                        break;
                if (utmp.ut_name[0] == 0)
                        continue;
                nusers++;
-               for (np = gp->gr_mem; *np; np++){
+               for (np = gp->gr_mem; *np; np++) {
                        if (strncmp(*np, utmp.ut_name, sizeof(utmp.ut_name)) != 0)
                                continue;
                        /*
                        if (strncmp(*np, utmp.ut_name, sizeof(utmp.ut_name)) != 0)
                                continue;
                        /*
@@ -172,42 +194,50 @@ broadcast(message)
                        if (strncmp(utmp.ut_line, DIALUP, strlen(DIALUP)) == 0)
                                continue;
 #ifdef DEBUG
                        if (strncmp(utmp.ut_line, DIALUP, strlen(DIALUP)) == 0)
                                continue;
 #ifdef DEBUG
-                       msg("Message to %s at %s\n",
-                               utmp.ut_name, utmp.ut_line);
-#endif DEBUG
+                       msg("Message to %s at %s\n", *np, utmp.ut_line);
+#endif
                        sendmes(utmp.ut_line, message);
                }
        }
                        sendmes(utmp.ut_line, message);
                }
        }
-       fclose(f_utmp);
+       (void) fclose(f_utmp);
        Exit(0);        /* the wait in this same routine will catch this */
        /* NOTREACHED */
 }
 
        Exit(0);        /* the wait in this same routine will catch this */
        /* NOTREACHED */
 }
 
+static void
 sendmes(tty, message)
 sendmes(tty, message)
-char *tty, *message;
+       char *tty, *message;
 {
        char t[50], buf[BUFSIZ];
        register char *cp;
 {
        char t[50], buf[BUFSIZ];
        register char *cp;
-       register int c, ch;
-       int     msize;
+       int lmsg = 1;
        FILE *f_tty;
 
        FILE *f_tty;
 
-       msize = strlen(message);
-       strcpy(t, "/dev/");
-       strcat(t, tty);
+       (void) strcpy(t, _PATH_DEV);
+       (void) strcat(t, tty);
 
 
-       if((f_tty = fopen(t, "w")) != NULL) {
+       if ((f_tty = fopen(t, "w")) != NULL) {
                setbuf(f_tty, buf);
                setbuf(f_tty, buf);
-               fprintf(f_tty, "\n\a\a\aMessage from the dump program to all operators at %d:%02d ...\r\n\n"
-                      ,localclock->tm_hour
-                      ,localclock->tm_min);
-               for (cp = message, c = msize; c-- > 0; cp++) {
-                       ch = *cp;
-                       if (ch == '\n')
-                               putc('\r', f_tty);
-                       putc(ch, f_tty);
+               (void) fprintf(f_tty,
+                   "\n\
+\7\7\7Message from the dump program to all operators at %d:%02d ...\r\n\n\
+DUMP: NEEDS ATTENTION: ",
+                   localclock->tm_hour, localclock->tm_min);
+               for (cp = lastmsg; ; cp++) {
+                       if (*cp == '\0') {
+                               if (lmsg) {
+                                       cp = message;
+                                       if (*cp == '\0')
+                                               break;
+                                       lmsg = 0;
+                               } else
+                                       break;
+                       }
+                       if (*cp == '\n')
+                               (void) putc('\r', f_tty);
+                       (void) putc(*cp, f_tty);
                }
                }
-               fclose(f_tty);
+               (void) fclose(f_tty);
        }
 }
 
        }
 }
 
@@ -217,12 +247,13 @@ char *tty, *message;
 
 time_t tschedule = 0;
 
 
 time_t tschedule = 0;
 
+void
 timeest()
 {
        time_t  tnow, deltat;
 
        time (&tnow);
 timeest()
 {
        time_t  tnow, deltat;
 
        time (&tnow);
-       if (tnow >= tschedule){
+       if (tnow >= tschedule) {
                tschedule = tnow + 300;
                if (blockswritten < 500)
                        return; 
                tschedule = tnow + 300;
                if (blockswritten < 500)
                        return; 
@@ -234,7 +265,8 @@ timeest()
        }
 }
 
        }
 }
 
-int blocksontape()
+int
+blocksontape()
 {
        /*
         *      esize: total number of blocks estimated over all reels
 {
        /*
         *      esize: total number of blocks estimated over all reels
@@ -246,104 +278,178 @@ int blocksontape()
         *      tapeno: number of tapes written so far
         */
        if (tapeno == etapes)
         *      tapeno: number of tapes written so far
         */
        if (tapeno == etapes)
-               return(esize - (etapes - 1)*tsize);
-       return(tsize);
+               return (esize - (etapes - 1)*tsize);
+       return (tsize);
 }
 
 }
 
-       /* VARARGS1 */
-       /* ARGSUSED */
-msg(fmt, a1, a2, a3, a4, a5)
-       char    *fmt;
+#ifdef lint
+
+/* VARARGS1 */
+void msg(fmt) char *fmt; { strcpy(lastmsg, fmt); }
+
+/* VARARGS1 */
+void msgtail(fmt) char *fmt; { fmt = fmt; }
+
+void quit(fmt) char *fmt; { msg(fmt); dumpabort(); }
+
+#else /* lint */
+
+void
+msg(va_alist)
+       va_dcl
 {
 {
-       fprintf(stderr,"  DUMP: ");
+       va_list ap;
+       char *fmt;
+
+       (void) fprintf(stderr,"  DUMP: ");
 #ifdef TDEBUG
 #ifdef TDEBUG
-       fprintf(stderr,"pid=%d ", getpid());
+       (void) fprintf(stderr, "pid=%d ", getpid());
 #endif
 #endif
-       fprintf(stderr, fmt, a1, a2, a3, a4, a5);
-       fflush(stdout);
-       fflush(stderr);
+       va_start(ap);
+       fmt = va_arg(ap, char *);
+       (void) vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       (void) fflush(stdout);
+       (void) fflush(stderr);
+       va_start(ap);
+       fmt = va_arg(ap, char *);
+       (void) vsprintf(lastmsg, fmt, ap);
+       va_end(ap);
 }
 
 }
 
-       /* VARARGS1 */
-       /* ARGSUSED */
-msgtail(fmt, a1, a2, a3, a4, a5)
-       char    *fmt;
+void
+msgtail(va_alist)
+       va_dcl
 {
 {
-       fprintf(stderr, fmt, a1, a2, a3, a4, a5);
+       va_list ap;
+       char *fmt;
+
+       va_start(ap);
+       fmt = va_arg(ap, char *);
+       (void) vfprintf(stderr, fmt, ap);
+       va_end(ap);
 }
 }
+
+void
+quit(va_alist)
+       va_dcl
+{
+       va_list ap;
+       char *fmt;
+
+       (void) fprintf(stderr,"  DUMP: ");
+#ifdef TDEBUG
+       (void) fprintf(stderr, "pid=%d ", getpid());
+#endif
+       va_start(ap);
+       fmt = va_arg(ap, char *);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       (void) fflush(stdout);
+       (void) fflush(stderr);
+       dumpabort();
+}
+
+#endif /* lint */
+
 /*
  *     Tell the operator what has to be done;
  *     we don't actually do it
  */
 
 /*
  *     Tell the operator what has to be done;
  *     we don't actually do it
  */
 
+struct fstab *
+allocfsent(fs)
+       register struct fstab *fs;
+{
+       register struct fstab *new;
+
+       new = (struct fstab *)malloc(sizeof (*fs));
+       if (new == NULL ||
+           (new->fs_file = strdup(fs->fs_file)) == NULL ||
+           (new->fs_type = strdup(fs->fs_type)) == NULL ||
+           (new->fs_spec = strdup(fs->fs_spec)) == NULL)
+               quit("%s\n", strerror(errno));
+       new->fs_passno = fs->fs_passno;
+       new->fs_freq = fs->fs_freq;
+       return (new);
+}
+
+struct pfstab {
+       struct  pfstab *pf_next;
+       struct  fstab *pf_fstab;
+};
+
+static struct pfstab *table;
+
+void
 getfstab()
 {
 getfstab()
 {
-       register        struct  fstab   *dt;
-                       struct  fstab   *fsp;
+       register struct fstab *fs;
+       register struct pfstab *pf;
 
 
-       nfstab = 0;
        if (setfsent() == 0) {
        if (setfsent() == 0) {
-               msg("Can't open %s for dump table information.\n", FSTAB);
-       } else {
-               for (nfstab = 0, dt = fstab; nfstab < MAXFSTAB;){
-                       if ( (fsp = getfsent()) == 0)
-                               break;
-                       if (   (strcmp(fsp->fs_type, FSTAB_RW) == 0)
-                           || (strcmp(fsp->fs_type, FSTAB_RO) == 0) ){
-                               *dt = *fsp;
-                               nfstab++; 
-                               dt++;
-                       }
-               }
-               endfsent();
+               msg("Can't open %s for dump table information: %s\n",
+                   _PATH_FSTAB, strerror(errno));
+               return;
+       }
+       while (fs = getfsent()) {
+               if (strcmp(fs->fs_type, FSTAB_RW) &&
+                   strcmp(fs->fs_type, FSTAB_RO) &&
+                   strcmp(fs->fs_type, FSTAB_RQ))
+                       continue;
+               fs = allocfsent(fs);
+               if ((pf = (struct pfstab *)malloc(sizeof (*pf))) == NULL)
+                       quit("%s\n", strerror(errno));
+               pf->pf_fstab = fs;
+               pf->pf_next = table;
+               table = pf;
        }
        }
+       endfsent();
 }
 
 /*
 }
 
 /*
- *     Search in the fstab for a file name.
- *     This file name can be either the special or the path file name.
+ * Search in the fstab for a file name.
+ * This file name can be either the special or the path file name.
  *
  *
- *     The entries in the fstab are the BLOCK special names, not the
- *     character special names.
- *     The caller of fstabsearch assures that the character device
- *     is dumped (that is much faster)
+ * The entries in the fstab are the BLOCK special names, not the
+ * character special names.
+ * The caller of fstabsearch assures that the character device
+ * is dumped (that is much faster)
  *
  *
- *     The file name can omit the leading '/'.
+ * The file name can omit the leading '/'.
  */
  */
-struct fstab   *fstabsearch(key)
-       char    *key;
+struct fstab *
+fstabsearch(key)
+       char *key;
 {
 {
-       register        struct  fstab *dt;
-                       int     i;
-                       int     keylength;
-                       char    *rawname();
-
-       keylength = min(strlen(key), sizeof (dt->fs_file));
-       for (i = 0, dt = fstab; i < nfstab; i++, dt++){
-               if (strncmp(dt->fs_file, key, keylength) == 0)
-                       return(dt);
-               if (strncmp(dt->fs_spec, key, keylength) == 0)
-                       return(dt);
-               if (strncmp(rawname(dt->fs_spec), key, keylength) == 0)
-                       return(dt);
-
-               if (key[0] != '/'){
-                       if (   (dt->fs_spec[0] == '/')
-                           && (strncmp(dt->fs_spec+1, key, keylength) == 0))
-                               return(dt);
-                       if (   (dt->fs_file[0] == '/')
-                           && (strncmp(dt->fs_file+1, key, keylength) == 0))
-                               return(dt);
+       register struct pfstab *pf;
+       register struct fstab *fs;
+       char *rawname();
+
+       for (pf = table; pf != NULL; pf = pf->pf_next) {
+               fs = pf->pf_fstab;
+               if (strcmp(fs->fs_file, key) == 0 ||
+                   strcmp(fs->fs_spec, key) == 0 ||
+                   strcmp(rawname(fs->fs_spec), key) == 0)
+                       return (fs);
+               if (key[0] != '/') {
+                       if (*fs->fs_spec == '/' &&
+                           strcmp(fs->fs_spec + 1, key) == 0)
+                               return (fs);
+                       if (*fs->fs_file == '/' &&
+                           strcmp(fs->fs_file + 1, key) == 0)
+                               return (fs);
                }
        }
                }
        }
-       return(0);
+       return (NULL);
 }
 
 /*
  *     Tell the operator what to do
  */
 }
 
 /*
  *     Tell the operator what to do
  */
+void
 lastdump(arg)
 lastdump(arg)
-       char    arg;            /* w ==> just what to do; W ==> most recent dumps */
+       char    arg;    /* w ==> just what to do; W ==> most recent dumps */
 {
                        char    *lastname;
                        char    *date;
 {
                        char    *lastname;
                        char    *date;
@@ -361,48 +467,51 @@ lastdump(arg)
        qsort(idatev, nidates, sizeof(struct idates *), idatesort);
 
        if (arg == 'w')
        qsort(idatev, nidates, sizeof(struct idates *), idatesort);
 
        if (arg == 'w')
-               fprintf(stdout, "Dump these file systems:\n");
+               (void) printf("Dump these file systems:\n");
        else
        else
-               fprintf(stdout, "Last dump(s) done (Dump '>' file systems):\n");
+               (void) printf("Last dump(s) done (Dump '>' file systems):\n");
        lastname = "??";
        lastname = "??";
-       ITITERATE(i, itwalk){
+       ITITERATE(i, itwalk) {
                if (strncmp(lastname, itwalk->id_name, sizeof(itwalk->id_name)) == 0)
                        continue;
                date = (char *)ctime(&itwalk->id_ddate);
                if (strncmp(lastname, itwalk->id_name, sizeof(itwalk->id_name)) == 0)
                        continue;
                date = (char *)ctime(&itwalk->id_ddate);
-               date[16] = '\0';                /* blast away seconds and year */
+               date[16] = '\0';        /* blast away seconds and year */
                lastname = itwalk->id_name;
                dt = fstabsearch(itwalk->id_name);
                lastname = itwalk->id_name;
                dt = fstabsearch(itwalk->id_name);
-               dumpme = (  (dt != 0)
-                        && (dt->fs_freq != 0)
-                        && (itwalk->id_ddate < tnow - (dt->fs_freq*DAY)));
-               if ( (arg != 'w') || dumpme)
-                 fprintf(stdout,"%c %8s\t(%6s) Last dump: Level %c, Date %s\n",
-                       dumpme && (arg != 'w') ? '>' : ' ',
-                       itwalk->id_name,
-                       dt ? dt->fs_file : 0,
-                       itwalk->id_incno,
-                       date
-                   );
+               dumpme = (dt != NULL &&
+                   dt->fs_freq != 0 &&
+                   itwalk->id_ddate < tnow - (dt->fs_freq * DAY));
+               if (arg != 'w' || dumpme)
+                       (void) printf(
+                           "%c %8s\t(%6s) Last dump: Level %c, Date %s\n",
+                           dumpme && (arg != 'w') ? '>' : ' ',
+                           itwalk->id_name,
+                           dt ? dt->fs_file : "",
+                           itwalk->id_incno,
+                           date);
        }
 }
 
        }
 }
 
-int    idatesort(p1, p2)
-       struct  idates  **p1, **p2;
+int    idatesort(a1, a2)
+       void *a1, *a2;
 {
 {
-       int     diff;
+       struct idates *d1 = *(struct idates **)a1, *d2 = *(struct idates **)a2;
+       int diff;
 
 
-       diff = strncmp((*p1)->id_name, (*p2)->id_name, sizeof((*p1)->id_name));
+       diff = strncmp(d1->id_name, d2->id_name, sizeof(d1->id_name));
        if (diff == 0)
        if (diff == 0)
-               return ((*p2)->id_ddate - (*p1)->id_ddate);
+               return (d2->id_ddate - d1->id_ddate);
        else
                return (diff);
 }
 
        else
                return (diff);
 }
 
-int max(a,b)
+int max(a, b)
+       int a, b;
 {
 {
-       return(a>b?a:b);
+       return (a > b ? a : b);
 }
 }
-int min(a,b)
+int min(a, b)
+       int a, b;
 {
 {
-       return(a<b?a:b);
+       return (a < b ? a : b);
 }
 }