home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / lpr / lpc / cmds.c,v next >
Encoding:
Text File  |  1994-05-23  |  21.7 KB  |  1,043 lines

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