home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / lpr / lpc / cmds.c next >
Encoding:
C/C++ Source or Header  |  1991-04-19  |  21.5 KB  |  1,017 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)cmds.c    5.7 (Berkeley) 6/1/90";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * lpc -- line printer control program -- commands:
  40.  */
  41.  
  42. #include "lp.h"
  43. #include <sys/time.h>
  44. #include "pathnames.h"
  45.  
  46. /*
  47.  * kill an existing daemon and disable printing.
  48.  */
  49. abort(argc, argv)
  50.     char *argv[];
  51. {
  52.     register int c, status;
  53.     register char *cp1, *cp2;
  54.     char prbuf[100];
  55.  
  56.     if (argc == 1) {
  57.         printf("Usage: abort {all | printer ...}\n");
  58.         return;
  59.     }
  60.     if (argc == 2 && !strcmp(argv[1], "all")) {
  61.         printer = prbuf;
  62.         while (getprent(line) > 0) {
  63.             cp1 = prbuf;
  64.             cp2 = line;
  65.             while ((c = *cp2++) && c != '|' && c != ':')
  66.                 *cp1++ = c;
  67.             *cp1 = '\0';
  68.             abortpr(1);
  69.         }
  70.         return;
  71.     }
  72.     while (--argc) {
  73.         printer = *++argv;
  74.         if ((status = pgetent(line, printer)) < 0) {
  75.             printf("cannot open printer description file\n");
  76.             continue;
  77.         } else if (status == 0) {
  78.             printf("unknown printer %s\n", printer);
  79.             continue;
  80.         }
  81.         abortpr(1);
  82.     }
  83. }
  84.  
  85. abortpr(dis)
  86. {
  87.     register FILE *fp;
  88.     struct stat stbuf;
  89.     int pid, fd;
  90.  
  91.     bp = pbuf;
  92.     if ((SD = pgetstr("sd", &bp)) == NULL)
  93.         SD = _PATH_DEFSPOOL;
  94.     if ((LO = pgetstr("lo", &bp)) == NULL)
  95.         LO = DEFLOCK;
  96.     (void) sprintf(line, "%s/%s", SD, LO);
  97.     printf("%s:\n", printer);
  98.  
  99.     /*
  100.      * Turn on the owner execute bit of the lock file to disable printing.
  101.      */
  102.     if (dis) {
  103.         if (stat(line, &stbuf) >= 0) {
  104.             if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
  105.                 printf("\tcannot disable printing\n");
  106.             else {
  107.                 upstat("printing disabled\n");
  108.                 printf("\tprinting disabled\n");
  109.             }
  110.         } else if (errno == ENOENT) {
  111.             if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
  112.                 printf("\tcannot create lock file\n");
  113.             else {
  114.                 (void) close(fd);
  115.                 upstat("printing disabled\n");
  116.                 printf("\tprinting disabled\n");
  117.                 printf("\tno daemon to abort\n");
  118.             }
  119.             return;
  120.         } else {
  121.             printf("\tcannot stat lock file\n");
  122.             return;
  123.         }
  124.     }
  125.     /*
  126.      * Kill the current daemon to stop printing now.
  127.      */
  128.     if ((fp = fopen(line, "r")) == NULL) {
  129.         printf("\tcannot open lock file\n");
  130.         return;
  131.     }
  132.     if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) {
  133.         (void) fclose(fp);    /* unlocks as well */
  134.         printf("\tno daemon to abort\n");
  135.         return;
  136.     }
  137.     (void) fclose(fp);
  138.     if (kill(pid = atoi(line), SIGTERM) < 0)
  139.         printf("\tWarning: daemon (pid %d) not killed\n", pid);
  140.     else
  141.         printf("\tdaemon (pid %d) killed\n", pid);
  142. }
  143.  
  144. /*
  145.  * Write a message into the status file.
  146.  */
  147. upstat(msg)
  148.     char *msg;
  149. {
  150.     register int fd;
  151.     char statfile[BUFSIZ];
  152.  
  153.     bp = pbuf;
  154.     if ((ST = pgetstr("st", &bp)) == NULL)
  155.         ST = DEFSTAT;
  156.     (void) sprintf(statfile, "%s/%s", SD, ST);
  157.     umask(0);
  158.     fd = open(statfile, O_WRONLY|O_CREAT, 0664);
  159.     if (fd < 0 || flock(fd, LOCK_EX) < 0) {
  160.         printf("\tcannot create status file\n");
  161.         return;
  162.     }
  163.     (void) ftruncate(fd, 0);
  164.     if (msg == (char *)NULL)
  165.         (void) write(fd, "\n", 1);
  166.     else
  167.         (void) write(fd, msg, strlen(msg));
  168.     (void) close(fd);
  169. }
  170.  
  171. /*
  172.  * Remove all spool files and temporaries from the spooling area.
  173.  */
  174. clean(argc, argv)
  175.     char *argv[];
  176. {
  177.     register int c, status;
  178.     register char *cp1, *cp2;
  179.     char prbuf[100];
  180.  
  181.     if (argc == 1) {
  182.         printf("Usage: clean {all | printer ...}\n");
  183.         return;
  184.     }
  185.     if (argc == 2 && !strcmp(argv[1], "all")) {
  186.         printer = prbuf;
  187.         while (getprent(line) > 0) {
  188.             cp1 = prbuf;
  189.             cp2 = line;
  190.             while ((c = *cp2++) && c != '|' && c != ':')
  191.                 *cp1++ = c;
  192.             *cp1 = '\0';
  193.             cleanpr();
  194.         }
  195.         return;
  196.     }
  197.     while (--argc) {
  198.         printer = *++argv;
  199.         if ((status = pgetent(line, printer)) < 0) {
  200.             printf("cannot open printer description file\n");
  201.             continue;
  202.         } else if (status == 0) {
  203.             printf("unknown printer %s\n", printer);
  204.             continue;
  205.         }
  206.         cleanpr();
  207.     }
  208. }
  209.  
  210. select(d)
  211. struct direct *d;
  212. {
  213.     int c = d->d_name[0];
  214.  
  215.     if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f')
  216.         return(1);
  217.     return(0);
  218. }
  219.  
  220. /*
  221.  * Comparison routine for scandir. Sort by job number and machine, then
  222.  * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z.
  223.  */
  224. sortq(d1, d2)
  225. struct direct **d1, **d2;
  226. {
  227.     int c1, c2;
  228.  
  229.     if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3))
  230.         return(c1);
  231.     c1 = (*d1)->d_name[0];
  232.     c2 = (*d2)->d_name[0];
  233.     if (c1 == c2)
  234.         return((*d1)->d_name[2] - (*d2)->d_name[2]);
  235.     if (c1 == 'c')
  236.         return(-1);
  237.     if (c1 == 'd' || c2 == 'c')
  238.         return(1);
  239.     return(-1);
  240. }
  241.  
  242. /*
  243.  * Remove incomplete jobs from spooling area.
  244.  */
  245. cleanpr()
  246. {
  247.     register int i, n;
  248.     register char *cp, *cp1, *lp;
  249.     struct direct **queue;
  250.     int nitems;
  251.  
  252.     bp = pbuf;
  253.     if ((SD = pgetstr("sd", &bp)) == NULL)
  254.         SD = _PATH_DEFSPOOL;
  255.     printf("%s:\n", printer);
  256.  
  257.     for (lp = line, cp = SD; *lp++ = *cp++; )
  258.         ;
  259.     lp[-1] = '/';
  260.  
  261.     nitems = scandir(SD, &queue, select, sortq);
  262.     if (nitems < 0) {
  263.         printf("\tcannot examine spool directory\n");
  264.         return;
  265.     }
  266.     if (nitems == 0)
  267.         return;
  268.     i = 0;
  269.     do {
  270.         cp = queue[i]->d_name;
  271.         if (*cp == 'c') {
  272.             n = 0;
  273.             while (i + 1 < nitems) {
  274.                 cp1 = queue[i + 1]->d_name;
  275.                 if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3))
  276.                     break;
  277.                 i++;
  278.                 n++;
  279.             }
  280.             if (n == 0) {
  281.                 strcpy(lp, cp);
  282.                 unlinkf(line);
  283.             }
  284.         } else {
  285.             /*
  286.              * Must be a df with no cf (otherwise, it would have
  287.              * been skipped above) or a tf file (which can always
  288.              * be removed).
  289.              */
  290.             strcpy(lp, cp);
  291.             unlinkf(line);
  292.         }
  293.          } while (++i < nitems);
  294. }
  295.  
  296. unlinkf(name)
  297.     char    *name;
  298. {
  299.     if (unlink(name) < 0)
  300.         printf("\tcannot remove %s\n", name);
  301.     else
  302.         printf("\tremoved %s\n", name);
  303. }
  304.  
  305. /*
  306.  * Enable queuing to the printer (allow lpr's).
  307.  */
  308. enable(argc, argv)
  309.     char *argv[];
  310. {
  311.     register int c, status;
  312.     register char *cp1, *cp2;
  313.     char prbuf[100];
  314.  
  315.     if (argc == 1) {
  316.         printf("Usage: enable {all | printer ...}\n");
  317.         return;
  318.     }
  319.     if (argc == 2 && !strcmp(argv[1], "all")) {
  320.         printer = prbuf;
  321.         while (getprent(line) > 0) {
  322.             cp1 = prbuf;
  323.             cp2 = line;
  324.             while ((c = *cp2++) && c != '|' && c != ':')
  325.                 *cp1++ = c;
  326.             *cp1 = '\0';
  327.             enablepr();
  328.         }
  329.         return;
  330.     }
  331.     while (--argc) {
  332.         printer = *++argv;
  333.         if ((status = pgetent(line, printer)) < 0) {
  334.             printf("cannot open printer description file\n");
  335.             continue;
  336.         } else if (status == 0) {
  337.             printf("unknown printer %s\n", printer);
  338.             continue;
  339.         }
  340.         enablepr();
  341.     }
  342. }
  343.  
  344. enablepr()
  345. {
  346.     struct stat stbuf;
  347.  
  348.     bp = pbuf;
  349.     if ((SD = pgetstr("sd", &bp)) == NULL)
  350.         SD = _PATH_DEFSPOOL;
  351.     if ((LO = pgetstr("lo", &bp)) == NULL)
  352.         LO = DEFLOCK;
  353.     (void) sprintf(line, "%s/%s", SD, LO);
  354.     printf("%s:\n", printer);
  355.  
  356.     /*
  357.      * Turn off the group execute bit of the lock file to enable queuing.
  358.      */
  359.     if (stat(line, &stbuf) >= 0) {
  360.         if (chmod(line, stbuf.st_mode & 0767) < 0)
  361.             printf("\tcannot enable queuing\n");
  362.         else
  363.             printf("\tqueuing enabled\n");
  364.     }
  365. }
  366.  
  367. /*
  368.  * Disable queuing.
  369.  */
  370. disable(argc, argv)
  371.     char *argv[];
  372. {
  373.     register int c, status;
  374.     register char *cp1, *cp2;
  375.     char prbuf[100];
  376.  
  377.     if (argc == 1) {
  378.         printf("Usage: disable {all | printer ...}\n");
  379.         return;
  380.     }
  381.     if (argc == 2 && !strcmp(argv[1], "all")) {
  382.         printer = prbuf;
  383.         while (getprent(line) > 0) {
  384.             cp1 = prbuf;
  385.             cp2 = line;
  386.             while ((c = *cp2++) && c != '|' && c != ':')
  387.                 *cp1++ = c;
  388.             *cp1 = '\0';
  389.             disablepr();
  390.         }
  391.         return;
  392.     }
  393.     while (--argc) {
  394.         printer = *++argv;
  395.         if ((status = pgetent(line, printer)) < 0) {
  396.             printf("cannot open printer description file\n");
  397.             continue;
  398.         } else if (status == 0) {
  399.             printf("unknown printer %s\n", printer);
  400.             continue;
  401.         }
  402.         disablepr();
  403.     }
  404. }
  405.  
  406. disablepr()
  407. {
  408.     register int fd;
  409.     struct stat stbuf;
  410.  
  411.     bp = pbuf;
  412.     if ((SD = pgetstr("sd", &bp)) == NULL)
  413.         SD = _PATH_DEFSPOOL;
  414.     if ((LO = pgetstr("lo", &bp)) == NULL)
  415.         LO = DEFLOCK;
  416.     (void) sprintf(line, "%s/%s", SD, LO);
  417.     printf("%s:\n", printer);
  418.     /*
  419.      * Turn on the group execute bit of the lock file to disable queuing.
  420.      */
  421.     if (stat(line, &stbuf) >= 0) {
  422.         if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0)
  423.             printf("\tcannot disable queuing\n");
  424.         else
  425.             printf("\tqueuing disabled\n");
  426.     } else if (errno == ENOENT) {
  427.         if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0)
  428.             printf("\tcannot create lock file\n");
  429.         else {
  430.             (void) close(fd);
  431.             printf("\tqueuing disabled\n");
  432.         }
  433.         return;
  434.     } else
  435.         printf("\tcannot stat lock file\n");
  436. }
  437.  
  438. /*
  439.  * Disable queuing and printing and put a message into the status file
  440.  * (reason for being down).
  441.  */
  442. down(argc, argv)
  443.     char *argv[];
  444. {
  445.     register int c, status;
  446.     register char *cp1, *cp2;
  447.     char prbuf[100];
  448.  
  449.     if (argc == 1) {
  450.         printf("Usage: down {all | printer} [message ...]\n");
  451.         return;
  452.     }
  453.     if (!strcmp(argv[1], "all")) {
  454.         printer = prbuf;
  455.         while (getprent(line) > 0) {
  456.             cp1 = prbuf;
  457.             cp2 = line;
  458.             while ((c = *cp2++) && c != '|' && c != ':')
  459.                 *cp1++ = c;
  460.             *cp1 = '\0';
  461.             putmsg(argc - 2, argv + 2);
  462.         }
  463.         return;
  464.     }
  465.     printer = argv[1];
  466.     if ((status = pgetent(line, printer)) < 0) {
  467.         printf("cannot open printer description file\n");
  468.         return;
  469.     } else if (status == 0) {
  470.         printf("unknown printer %s\n", printer);
  471.         return;
  472.     }
  473.     putmsg(argc - 2, argv + 2);
  474. }
  475.  
  476. putmsg(argc, argv)
  477.     char **argv;
  478. {
  479.     register int fd;
  480.     register char *cp1, *cp2;
  481.     char buf[1024];
  482.     struct stat stbuf;
  483.  
  484.     bp = pbuf;
  485.     if ((SD = pgetstr("sd", &bp)) == NULL)
  486.         SD = _PATH_DEFSPOOL;
  487.     if ((LO = pgetstr("lo", &bp)) == NULL)
  488.         LO = DEFLOCK;
  489.     if ((ST = pgetstr("st", &bp)) == NULL)
  490.         ST = DEFSTAT;
  491.     printf("%s:\n", printer);
  492.     /*
  493.      * Turn on the group execute bit of the lock file to disable queuing and
  494.      * turn on the owner execute bit of the lock file to disable printing.
  495.      */
  496.     (void) sprintf(line, "%s/%s", SD, LO);
  497.     if (stat(line, &stbuf) >= 0) {
  498.         if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0)
  499.             printf("\tcannot disable queuing\n");
  500.         else
  501.             printf("\tprinter and queuing disabled\n");
  502.     } else if (errno == ENOENT) {
  503.         if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0)
  504.             printf("\tcannot create lock file\n");
  505.         else {
  506.             (void) close(fd);
  507.             printf("\tprinter and queuing disabled\n");
  508.         }
  509.         return;
  510.     } else
  511.         printf("\tcannot stat lock file\n");
  512.     /*
  513.      * Write the message into the status file.
  514.      */
  515.     (void) sprintf(line, "%s/%s", SD, ST);
  516.     fd = open(line, O_WRONLY|O_CREAT, 0664);
  517.     if (fd < 0 || flock(fd, LOCK_EX) < 0) {
  518.         printf("\tcannot create status file\n");
  519.         return;
  520.     }
  521.     (void) ftruncate(fd, 0);
  522.     if (argc <= 0) {
  523.         (void) write(fd, "\n", 1);
  524.         (void) close(fd);
  525.         return;
  526.     }
  527.     cp1 = buf;
  528.     while (--argc >= 0) {
  529.         cp2 = *argv++;
  530.         while (*cp1++ = *cp2++)
  531.             ;
  532.         cp1[-1] = ' ';
  533.     }
  534.     cp1[-1] = '\n';
  535.     *cp1 = '\0';
  536.     (void) write(fd, buf, strlen(buf));
  537.     (void) close(fd);
  538. }
  539.  
  540. /*
  541.  * Exit lpc
  542.  */
  543. quit(argc, argv)
  544.     char *argv[];
  545. {
  546.     exit(0);
  547. }
  548.  
  549. /*
  550.  * Kill and restart the daemon.
  551.  */
  552. restart(argc, argv)
  553.     char *argv[];
  554. {
  555.     register int c, status;
  556.     register char *cp1, *cp2;
  557.     char prbuf[100];
  558.  
  559.     if (argc == 1) {
  560.         printf("Usage: restart {all | printer ...}\n");
  561.         return;
  562.     }
  563.     if (argc == 2 && !strcmp(argv[1], "all")) {
  564.         printer = prbuf;
  565.         while (getprent(line) > 0) {
  566.             cp1 = prbuf;
  567.             cp2 = line;
  568.             while ((c = *cp2++) && c != '|' && c != ':')
  569.                 *cp1++ = c;
  570.             *cp1 = '\0';
  571.             abortpr(0);
  572.             startpr(0);
  573.         }
  574.         return;
  575.     }
  576.     while (--argc) {
  577.         printer = *++argv;
  578.         if ((status = pgetent(line, printer)) < 0) {
  579.             printf("cannot open printer description file\n");
  580.             continue;
  581.         } else if (status == 0) {
  582.             printf("unknown printer %s\n", printer);
  583.             continue;
  584.         }
  585.         abortpr(0);
  586.         startpr(0);
  587.     }
  588. }
  589.  
  590. /*
  591.  * Enable printing on the specified printer and startup the daemon.
  592.  */
  593. start(argc, argv)
  594.     char *argv[];
  595. {
  596.     register int c, status;
  597.     register char *cp1, *cp2;
  598.     char prbuf[100];
  599.  
  600.     if (argc == 1) {
  601.         printf("Usage: start {all | printer ...}\n");
  602.         return;
  603.     }
  604.     if (argc == 2 && !strcmp(argv[1], "all")) {
  605.         printer = prbuf;
  606.         while (getprent(line) > 0) {
  607.             cp1 = prbuf;
  608.             cp2 = line;
  609.             while ((c = *cp2++) && c != '|' && c != ':')
  610.                 *cp1++ = c;
  611.             *cp1 = '\0';
  612.             startpr(1);
  613.         }
  614.         return;
  615.     }
  616.     while (--argc) {
  617.         printer = *++argv;
  618.         if ((status = pgetent(line, printer)) < 0) {
  619.             printf("cannot open printer description file\n");
  620.             continue;
  621.         } else if (status == 0) {
  622.             printf("unknown printer %s\n", printer);
  623.             continue;
  624.         }
  625.         startpr(1);
  626.     }
  627. }
  628.  
  629. startpr(enable)
  630. {
  631.     struct stat stbuf;
  632.  
  633.     bp = pbuf;
  634.     if ((SD = pgetstr("sd", &bp)) == NULL)
  635.         SD = _PATH_DEFSPOOL;
  636.     if ((LO = pgetstr("lo", &bp)) == NULL)
  637.         LO = DEFLOCK;
  638.     (void) sprintf(line, "%s/%s", SD, LO);
  639.     printf("%s:\n", printer);
  640.  
  641.     /*
  642.      * Turn off the owner execute bit of the lock file to enable printing.
  643.      */
  644.     if (enable && stat(line, &stbuf) >= 0) {
  645.         if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0)
  646.             printf("\tcannot enable printing\n");
  647.         else
  648.             printf("\tprinting enabled\n");
  649.     }
  650.     if (!startdaemon(printer))
  651.         printf("\tcouldn't start daemon\n");
  652.     else
  653.         printf("\tdaemon started\n");
  654. }
  655.  
  656. /*
  657.  * Print the status of each queue listed or all the queues.
  658.  */
  659. status(argc, argv)
  660.     char *argv[];
  661. {
  662.     register int c, status;
  663.     register char *cp1, *cp2;
  664.     char prbuf[100];
  665.  
  666.     if (argc == 1) {
  667.         printer = prbuf;
  668.         while (getprent(line) > 0) {
  669.             cp1 = prbuf;
  670.             cp2 = line;
  671.             while ((c = *cp2++) && c != '|' && c != ':')
  672.                 *cp1++ = c;
  673.             *cp1 = '\0';
  674.             prstat();
  675.         }
  676.         return;
  677.     }
  678.     while (--argc) {
  679.         printer = *++argv;
  680.         if ((status = pgetent(line, printer)) < 0) {
  681.             printf("cannot open printer description file\n");
  682.             continue;
  683.         } else if (status == 0) {
  684.             printf("unknown printer %s\n", printer);
  685.             continue;
  686.         }
  687.         prstat();
  688.     }
  689. }
  690.  
  691. /*
  692.  * Print the status of the printer queue.
  693.  */
  694. prstat()
  695. {
  696.     struct stat stbuf;
  697.     register int fd, i;
  698.     register struct direct *dp;
  699.     DIR *dirp;
  700.  
  701.     bp = pbuf;
  702.     if ((SD = pgetstr("sd", &bp)) == NULL)
  703.         SD = _PATH_DEFSPOOL;
  704.     if ((LO = pgetstr("lo", &bp)) == NULL)
  705.         LO = DEFLOCK;
  706.     if ((ST = pgetstr("st", &bp)) == NULL)
  707.         ST = DEFSTAT;
  708.     printf("%s:\n", printer);
  709.     (void) sprintf(line, "%s/%s", SD, LO);
  710.     if (stat(line, &stbuf) >= 0) {
  711.         printf("\tqueuing is %s\n",
  712.             (stbuf.st_mode & 010) ? "disabled" : "enabled");
  713.         printf("\tprinting is %s\n",
  714.             (stbuf.st_mode & 0100) ? "disabled" : "enabled");
  715.     } else {
  716.         printf("\tqueuing is enabled\n");
  717.         printf("\tprinting is enabled\n");
  718.     }
  719.     if ((dirp = opendir(SD)) == NULL) {
  720.         printf("\tcannot examine spool directory\n");
  721.         return;
  722.     }
  723.     i = 0;
  724.     while ((dp = readdir(dirp)) != NULL) {
  725.         if (*dp->d_name == 'c' && dp->d_name[1] == 'f')
  726.             i++;
  727.     }
  728.     closedir(dirp);
  729.     if (i == 0)
  730.         printf("\tno entries\n");
  731.     else if (i == 1)
  732.         printf("\t1 entry in spool area\n");
  733.     else
  734.         printf("\t%d entries in spool area\n", i);
  735.     fd = open(line, O_RDONLY);
  736.     if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
  737.         (void) close(fd);    /* unlocks as well */
  738.         printf("\tno daemon present\n");
  739.         return;
  740.     }
  741.     (void) close(fd);
  742.     putchar('\t');
  743.     (void) sprintf(line, "%s/%s", SD, ST);
  744.     fd = open(line, O_RDONLY);
  745.     if (fd >= 0) {
  746.         (void) flock(fd, LOCK_SH);
  747.         while ((i = read(fd, line, sizeof(line))) > 0)
  748.             (void) fwrite(line, 1, i, stdout);
  749.         (void) close(fd);    /* unlocks as well */
  750.     }
  751. }
  752.  
  753. /*
  754.  * Stop the specified daemon after completing the current job and disable
  755.  * printing.
  756.  */
  757. stop(argc, argv)
  758.     char *argv[];
  759. {
  760.     register int c, status;
  761.     register char *cp1, *cp2;
  762.     char prbuf[100];
  763.  
  764.     if (argc == 1) {
  765.         printf("Usage: stop {all | printer ...}\n");
  766.         return;
  767.     }
  768.     if (argc == 2 && !strcmp(argv[1], "all")) {
  769.         printer = prbuf;
  770.         while (getprent(line) > 0) {
  771.             cp1 = prbuf;
  772.             cp2 = line;
  773.             while ((c = *cp2++) && c != '|' && c != ':')
  774.                 *cp1++ = c;
  775.             *cp1 = '\0';
  776.             stoppr();
  777.         }
  778.         return;
  779.     }
  780.     while (--argc) {
  781.         printer = *++argv;
  782.         if ((status = pgetent(line, printer)) < 0) {
  783.             printf("cannot open printer description file\n");
  784.             continue;
  785.         } else if (status == 0) {
  786.             printf("unknown printer %s\n", printer);
  787.             continue;
  788.         }
  789.         stoppr();
  790.     }
  791. }
  792.  
  793. stoppr()
  794. {
  795.     register int fd;
  796.     struct stat stbuf;
  797.  
  798.     bp = pbuf;
  799.     if ((SD = pgetstr("sd", &bp)) == NULL)
  800.         SD = _PATH_DEFSPOOL;
  801.     if ((LO = pgetstr("lo", &bp)) == NULL)
  802.         LO = DEFLOCK;
  803.     (void) sprintf(line, "%s/%s", SD, LO);
  804.     printf("%s:\n", printer);
  805.  
  806.     /*
  807.      * Turn on the owner execute bit of the lock file to disable printing.
  808.      */
  809.     if (stat(line, &stbuf) >= 0) {
  810.         if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
  811.             printf("\tcannot disable printing\n");
  812.         else {
  813.             upstat("printing disabled\n");
  814.             printf("\tprinting disabled\n");
  815.         }
  816.     } else if (errno == ENOENT) {
  817.         if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
  818.             printf("\tcannot create lock file\n");
  819.         else {
  820.             (void) close(fd);
  821.             upstat("printing disabled\n");
  822.             printf("\tprinting disabled\n");
  823.         }
  824.     } else
  825.         printf("\tcannot stat lock file\n");
  826. }
  827.  
  828. struct    queue **queue;
  829. int    nitems;
  830. time_t    mtime;
  831.  
  832. /*
  833.  * Put the specified jobs at the top of printer queue.
  834.  */
  835. topq(argc, argv)
  836.     char *argv[];
  837. {
  838.     register int n, i;
  839.     struct stat stbuf;
  840.     register char *cfname;
  841.     int status, changed;
  842.  
  843.     if (argc < 3) {
  844.         printf("Usage: topq printer [jobnum ...] [user ...]\n");
  845.         return;
  846.     }
  847.  
  848.     --argc;
  849.     printer = *++argv;
  850.     status = pgetent(line, printer);
  851.     if (status < 0) {
  852.         printf("cannot open printer description file\n");
  853.         return;
  854.     } else if (status == 0) {
  855.         printf("%s: unknown printer\n", printer);
  856.         return;
  857.     }
  858.     bp = pbuf;
  859.     if ((SD = pgetstr("sd", &bp)) == NULL)
  860.         SD = _PATH_DEFSPOOL;
  861.     if ((LO = pgetstr("lo", &bp)) == NULL)
  862.         LO = DEFLOCK;
  863.     printf("%s:\n", printer);
  864.  
  865.     if (chdir(SD) < 0) {
  866.         printf("\tcannot chdir to %s\n", SD);
  867.         return;
  868.     }
  869.     nitems = getq(&queue);
  870.     if (nitems == 0)
  871.         return;
  872.     changed = 0;
  873.     mtime = queue[0]->q_time;
  874.     for (i = argc; --i; ) {
  875.         if (doarg(argv[i]) == 0) {
  876.             printf("\tjob %s is not in the queue\n", argv[i]);
  877.             continue;
  878.         } else
  879.             changed++;
  880.     }
  881.     for (i = 0; i < nitems; i++)
  882.         free(queue[i]);
  883.     free(queue);
  884.     if (!changed) {
  885.         printf("\tqueue order unchanged\n");
  886.         return;
  887.     }
  888.     /*
  889.      * Turn on the public execute bit of the lock file to
  890.      * get lpd to rebuild the queue after the current job.
  891.      */
  892.     if (changed && stat(LO, &stbuf) >= 0)
  893.         (void) chmod(LO, (stbuf.st_mode & 0777) | 01);
  894.  
  895. /*
  896.  * Reposition the job by changing the modification time of
  897.  * the control file.
  898.  */
  899. touch(q)
  900.     struct queue *q;
  901. {
  902.     struct timeval tvp[2];
  903.  
  904.     tvp[0].tv_sec = tvp[1].tv_sec = --mtime;
  905.     tvp[0].tv_usec = tvp[1].tv_usec = 0;
  906.     return(utimes(q->q_name, tvp));
  907. }
  908.  
  909. /*
  910.  * Checks if specified job name is in the printer's queue.
  911.  * Returns:  negative (-1) if argument name is not in the queue.
  912.  */
  913. doarg(job)
  914.     char *job;
  915. {
  916.     register struct queue **qq;
  917.     register int jobnum, n;
  918.     register char *cp, *machine;
  919.     int cnt = 0;
  920.     FILE *fp;
  921.  
  922.     /*
  923.      * Look for a job item consisting of system name, colon, number 
  924.      * (example: ucbarpa:114)  
  925.      */
  926.     if ((cp = index(job, ':')) != NULL) {
  927.         machine = job;
  928.         *cp++ = '\0';
  929.         job = cp;
  930.     } else
  931.         machine = NULL;
  932.  
  933.     /*
  934.      * Check for job specified by number (example: 112 or 235ucbarpa).
  935.      */
  936.     if (isdigit(*job)) {
  937.         jobnum = 0;
  938.         do
  939.             jobnum = jobnum * 10 + (*job++ - '0');
  940.         while (isdigit(*job));
  941.         for (qq = queue + nitems; --qq >= queue; ) {
  942.             n = 0;
  943.             for (cp = (*qq)->q_name+3; isdigit(*cp); )
  944.                 n = n * 10 + (*cp++ - '0');
  945.             if (jobnum != n)
  946.                 continue;
  947.             if (*job && strcmp(job, cp) != 0)
  948.                 continue;
  949.             if (machine != NULL && strcmp(machine, cp) != 0)
  950.                 continue;
  951.             if (touch(*qq) == 0) {
  952.                 printf("\tmoved %s\n", (*qq)->q_name);
  953.                 cnt++;
  954.             }
  955.         }
  956.         return(cnt);
  957.     }
  958.     /*
  959.      * Process item consisting of owner's name (example: henry).
  960.      */
  961.     for (qq = queue + nitems; --qq >= queue; ) {
  962.         if ((fp = fopen((*qq)->q_name, "r")) == NULL)
  963.             continue;
  964.         while (getline(fp) > 0)
  965.             if (line[0] == 'P')
  966.                 break;
  967.         (void) fclose(fp);
  968.         if (line[0] != 'P' || strcmp(job, line+1) != 0)
  969.             continue;
  970.         if (touch(*qq) == 0) {
  971.             printf("\tmoved %s\n", (*qq)->q_name);
  972.             cnt++;
  973.         }
  974.     }
  975.     return(cnt);
  976. }
  977.  
  978. /*
  979.  * Enable everything and start printer (undo `down').
  980.  */
  981. up(argc, argv)
  982.     char *argv[];
  983. {
  984.     register int c, status;
  985.     register char *cp1, *cp2;
  986.     char prbuf[100];
  987.  
  988.     if (argc == 1) {
  989.         printf("Usage: up {all | printer ...}\n");
  990.         return;
  991.     }
  992.     if (argc == 2 && !strcmp(argv[1], "all")) {
  993.         printer = prbuf;
  994.         while (getprent(line) > 0) {
  995.             cp1 = prbuf;
  996.             cp2 = line;
  997.             while ((c = *cp2++) && c != '|' && c != ':')
  998.                 *cp1++ = c;
  999.             *cp1 = '\0';
  1000.             startpr(2);
  1001.         }
  1002.         return;
  1003.     }
  1004.     while (--argc) {
  1005.         printer = *++argv;
  1006.         if ((status = pgetent(line, printer)) < 0) {
  1007.             printf("cannot open printer description file\n");
  1008.             continue;
  1009.         } else if (status == 0) {
  1010.             printf("unknown printer %s\n", printer);
  1011.             continue;
  1012.         }
  1013.         startpr(2);
  1014.     }
  1015. }
  1016.