1: /*	lpdrestart.c	1.3	81/10/21	*/
   2: 
   3: #include    "lp.local.h"
   4: #include    <sys/types.h>
   5: #include    <signal.h>
   6: #include    <stdio.h>
   7: #include    <ctype.h>
   8: #include    "local/uparm.h"
   9: #include    <sys/stat.h>
  10: #include    <whoami.h>
  11: #include    <errno.h>
  12: 
  13: /*
  14:  * Restart line printer daemons after a reboot
  15:  */
  16: 
  17: #define MAXHOP  32  /* max number of tc= indirections */
  18: 
  19: #define tgetent     pgetent
  20: #define tskip       pskip
  21: #define tgetstr     pgetstr
  22: #define tdecode     pdecode
  23: #define tgetnum     pgetnum
  24: #define tgetflag    pgetflag
  25: #define tdecode     pdecode
  26: #define tnchktc     pnchktc
  27: #define tnamatch    pnamatch
  28: #undef  E_TERMCAP
  29: #define E_TERMCAP   "/etc/printcap"
  30: 
  31: char    *DN;        /* daemon name */
  32: char    *LP;        /* printer device */
  33: char    *SD;        /* spooling directory */
  34: char    *LF;        /* log file */
  35: char    *name;      /* name of current printer being worked on */
  36: char    *rindex();  /* ZZZZZZZZZZZZZZZZZ */
  37: int DU;     /* we will need the daemon uid */
  38: int fd, i, cur_daemon;
  39: extern int errno;
  40: char    *LO;        /* use the lockfile name in /etc/printcap */
  41: 
  42: FILE    *lfd;       /* open file descriptor for LF */
  43: 
  44: char    *tskip();
  45: char    *tgetstr();
  46: char    *tdecode();
  47: 
  48: main(argc, argv)
  49:     char *argv[];
  50: {
  51:     char buf[BUFSIZ/2], b[BUFSIZ], *bp, lbuf[256];
  52:     register char *Bp;
  53:     char namebuf[30];
  54:     struct stat statb;
  55:     register int pid;
  56: 
  57:     while (getpr(b)) {
  58:         bp = buf;
  59:         if ((DN = pgetstr("dn", &bp)) == NULL)
  60:             DN = DEFDAEMON;
  61:         if ((LP = pgetstr("lp", &bp)) == NULL)
  62:             LP = DEFDEVLP;
  63:         if ((SD = pgetstr("sd", &bp)) == NULL)
  64:             SD = DEFSPOOL;
  65:         if ((LF = pgetstr("lf", &bp)) == NULL)
  66:             LF = DEFLOGF;
  67:         if ((LO = pgetstr("lo", &bp)) == NULL)
  68:             LO = DEFLOCK;
  69:         if ((DU = pgetnum("du", &bp)) == -1)
  70:             DU = DEFUID;
  71:         for (name = namebuf, Bp = b; *Bp && *Bp != ':' && *Bp != '|';)
  72:             *name++ = *Bp++;
  73:         *name = '\0';
  74:         name = namebuf;
  75:         if ((lfd = fopen(LF, "a")) == NULL)
  76:             lfd = stderr;       /* expected to be console? */
  77:         /*
  78: 		 * First check if device is down (mode 0)
  79: 		 */
  80:         if (stat(LP, (char *)&statb) < 0) {
  81:             log("%s: can't stat %s", name, LP);
  82:             continue;
  83:         }
  84:         if (statb.st_mode == 0) {
  85:             log("%s: printer marked down", name);
  86:             continue;
  87:         }
  88: 
  89:         /*
  90: 		 * Remove a lock file if it's present, then
  91: 		 *  restart the daemon
  92: 		 */
  93:         sprintf(lbuf, "%s/%s", SD, (bp = rindex(LO,'/')) ? bp+1 : LO);
  94:         if (stat(lbuf, (char *)&statb) >= 0) {
  95:             /*
  96: 		     * Unskilled people may be using this command
  97: 		     * and it would not be kind to allow two daemons
  98: 		     * to do battle in their midst
  99: 		     */
 100: 
 101:             if ((fd = open(lbuf, 0)) < 0) {
 102:             if (errno == EACCES)
 103:                 log("%s: can't access %s", name, lbuf);
 104:             } else {
 105:                 if (read(fd, (char *)&cur_daemon, sizeof(int)) != sizeof(int))
 106:                 fatal("bad lock file (daemon pid)");
 107:                 close(fd);
 108:                 setuid(DU);
 109:                 kill(cur_daemon,SIGTERM);   /* This could be bad... */
 110:             }
 111:             if (unlink(lbuf)) {
 112:             log("%s: can't unlink %s in %s", name, lbuf, SD);
 113:             continue;
 114:             }
 115:         }
 116:         if ((pid = fork()) < 0)
 117:             log("%s: can't fork", name);
 118:         else if (!pid) {
 119:             execl(DN, (bp = rindex(DN, '/')) ? bp+1 : DN, name, 0);
 120:             log("%s: can't execl %s", name, DN);
 121:             exit(1);
 122:         } else
 123:             fclose(lfd);
 124:     }
 125: }
 126: 
 127: /*VARARGS1*/
 128: log(message, a1, a2, a3)
 129: char *message;
 130: {
 131:     short console = isatty(fileno(lfd));
 132: 
 133:     fprintf(lfd, console ? "\r\n%s: " : "%s: ", name);
 134:     fprintf(lfd, message, a1, a2, a3);
 135:     if (console)
 136:         putc('\r', lfd);
 137:     putc('\n', lfd);
 138:     fclose(lfd);
 139: }
 140: 
 141: /*VARARGS*/
 142: fatal(fmt, arg)
 143:     char *fmt;
 144: {
 145:     fprintf(stderr, "lpdrestart: ");
 146:     fprintf(stderr, fmt, arg);
 147:     putc('\n', stderr);
 148:     exit(1);
 149: }
 150: 
 151: /*
 152:  * Routines to perform a sequential pass through the printer
 153:  *  data base.  Things are slightly complicated by interactions
 154:  *  with the printcap routines.
 155:  */
 156: 
 157: static int pfd = -1;        /* for reading from data base */
 158: static long nextloc = -1L;  /* seek offset */
 159: static char *tbuf;
 160: static int hopcount;
 161: 
 162: setpr()
 163: {
 164:     if ((pfd = open(E_TERMCAP, 0)) < 0)
 165:         fatal("can't open %s", E_TERMCAP);
 166:     nextloc = 0L;
 167: }
 168: 
 169: endpr()
 170: {
 171:     close(pfd);
 172:     nextloc = 0L;
 173: }
 174: 
 175: getpr(bp)
 176:     char *bp;
 177: {
 178:     register char *cp, *Bp;
 179:     register int i = 0, cnt = 0, c;
 180:     char ibuf[BUFSIZ];
 181: 
 182:     if (pfd < 0)
 183:         setpr();
 184:     else
 185:         lseek(pfd, nextloc, 0);     /* move sequentially */
 186:     /*
 187: 	 * This code is (for the most part) taken from tgetent()
 188: 	 */
 189:     tbuf = bp;
 190:     for (;;) {
 191:         cp = bp;
 192:         for (;;) {
 193:             if (i == cnt) {
 194:                 cnt = read(pfd, ibuf, BUFSIZ);
 195:                 if (cnt <= 0) {
 196:                     endpr();
 197:                     return(NULL);
 198:                 }
 199:                 i = 0;
 200:             }
 201:             c = ibuf[i++];
 202:             if (c == '\n') {
 203:                 if (cp > bp && cp[-1] == '\\') {
 204:                     cp--;
 205:                     continue;
 206:                 }
 207:                 break;
 208:             }
 209:             if (cp >= bp+BUFSIZ)
 210:                 fatal("printcap entry too long");
 211:             *cp++ = c;
 212:         }
 213:         *cp = 0;
 214:         /*
 215: 		 * Interpret the printer description and adjust
 216: 		 *  nextloc so that we'll start scanning again
 217: 		 *  after this record.
 218: 		 */
 219:         nextloc += i;       /* amount taken from read buffer */
 220:         Bp = tbuf;
 221:         if (*Bp != '#' && *Bp != '\0') {
 222:             /*
 223: 			 * For now, we won't support "tc" chaining
 224: 			 */
 225:             return(1);
 226:         }
 227:     }
 228: }
 229: 
 230: /*
 231:  * Skip to the next field.  Notice that this is very dumb, not
 232:  * knowing about \: escapes or any such.  If necessary, :'s can be put
 233:  * into the termcap file in octal.
 234:  */
 235: static char *
 236: tskip(bp)
 237:     register char *bp;
 238: {
 239: 
 240:     while (*bp && *bp != ':')
 241:         bp++;
 242:     if (*bp == ':')
 243:         bp++;
 244:     return (bp);
 245: }
 246: 
 247: /*
 248:  * Get a string valued option.
 249:  * These are given as
 250:  *	cl=^Z
 251:  * Much decoding is done on the strings, and the strings are
 252:  * placed in area, which is a ref parameter which is updated.
 253:  * No checking on area overflow.
 254:  */
 255: char *
 256: tgetstr(id, area)
 257:     char *id, **area;
 258: {
 259:     register char *bp = tbuf;
 260: 
 261:     for (;;) {
 262:         bp = tskip(bp);
 263:         if (!*bp)
 264:             return (0);
 265:         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
 266:             continue;
 267:         if (*bp == '@')
 268:             return(0);
 269:         if (*bp != '=')
 270:             continue;
 271:         bp++;
 272:         return (tdecode(bp, area));
 273:     }
 274: }
 275: 
 276: /*
 277:  * Tdecode does the grung work to decode the
 278:  * string capability escapes.
 279:  */
 280: static char *
 281: tdecode(str, area)
 282:     register char *str;
 283:     char **area;
 284: {
 285:     register char *cp;
 286:     register int c;
 287:     register char *dp;
 288:     int i;
 289: 
 290:     cp = *area;
 291:     while ((c = *str++) && c != ':') {
 292:         switch (c) {
 293: 
 294:         case '^':
 295:             c = *str++ & 037;
 296:             break;
 297: 
 298:         case '\\':
 299:             dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
 300:             c = *str++;
 301: nextc:
 302:             if (*dp++ == c) {
 303:                 c = *dp++;
 304:                 break;
 305:             }
 306:             dp++;
 307:             if (*dp)
 308:                 goto nextc;
 309:             if (isdigit(c)) {
 310:                 c -= '0', i = 2;
 311:                 do
 312:                     c <<= 3, c |= *str++ - '0';
 313:                 while (--i && isdigit(*str));
 314:             }
 315:             break;
 316:         }
 317:         *cp++ = c;
 318:     }
 319:     *cp++ = 0;
 320:     str = *area;
 321:     *area = cp;
 322:     return (str);
 323: }
 324: 
 325: /*
 326:  * Return the (numeric) option id.
 327:  * Numeric options look like
 328:  *	li#80
 329:  * i.e. the option string is separated from the numeric value by
 330:  * a # character.  If the option is not found we return -1.
 331:  * Note that we handle octal numbers beginning with 0.
 332:  */
 333: pgetnum(id)
 334:     char *id;
 335: {
 336:     register int i, base;
 337:     register char *bp = tbuf;
 338: 
 339:     for (;;) {
 340:         bp = tskip(bp);
 341:         if (*bp == 0)
 342:             return (-1);
 343:         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
 344:             continue;
 345:         if (*bp == '@')
 346:             return(-1);
 347:         if (*bp != '#')
 348:             continue;
 349:         bp++;
 350:         base = 10;
 351:         if (*bp == '0')
 352:             base = 8;
 353:         i = 0;
 354:         while (isdigit(*bp))
 355:             i *= base, i += *bp++ - '0';
 356:         return (i);
 357:     }
 358: }

Defined functions

endpr defined in line 169; used 1 times
fatal defined in line 142; used 3 times
getpr defined in line 175; used 1 times
  • in line 57
log defined in line 128; used 6 times
main defined in line 48; never used
pgetnum defined in line 333; used 12 times
setpr defined in line 162; used 1 times
tdecode defined in line 280; never used
tgetstr defined in line 255; never used
tskip defined in line 235; never used

Defined variables

DN defined in line 31; used 6 times
DU defined in line 37; used 3 times
LF defined in line 34; used 3 times
LO defined in line 40; used 4 times
LP defined in line 32; used 4 times
SD defined in line 33; used 4 times
cur_daemon defined in line 38; used 2 times
fd defined in line 38; used 3 times
hopcount defined in line 160; never used
i defined in line 38; used 13 times
name defined in line 35; used 12 times
nextloc defined in line 158; used 4 times
pfd defined in line 157; used 5 times
tbuf defined in line 159; used 4 times

Defined macros

E_TERMCAP defined in line 29; used 3 times
MAXHOP defined in line 17; never used
tdecode defined in line 25; used 2 times
tgetent defined in line 19; never used
tgetflag defined in line 24; never used
tgetnum defined in line 23; never used
tgetstr defined in line 21; used 1 times
  • in line 45
tnamatch defined in line 27; never used
tnchktc defined in line 26; never used
tskip defined in line 20; used 3 times
Last modified: 1983-12-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1191
Valid CSS Valid XHTML 1.0 Strict