BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.sbin / lpr / lpd / lpd.c
index 5f33c15..edfda93 100644 (file)
@@ -1,6 +1,45 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)lpd.c      4.10 (Berkeley) %G%";
-#endif
+char copyright[] =
+"@(#) Copyright (c) 1983 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)lpd.c      5.12 (Berkeley) 3/7/91";
+#endif /* not lint */
 
 /*
  * lpd -- line printer daemon.
 
 /*
  * lpd -- line printer daemon.
@@ -17,12 +56,6 @@ static char sccsid[] = "@(#)lpd.c    4.10 (Berkeley) %G%";
  *             return the current state of the queue (long form).
  *     \5printer person [users ...] [jobs ...]\n
  *             remove jobs from the queue.
  *             return the current state of the queue (long form).
  *     \5printer person [users ...] [jobs ...]\n
  *             remove jobs from the queue.
- *     \6printer\n
- *             enable queuing on the specified printer queue.
- *     \7printer\n
- *             disable queuing on the specified printer queue.
- *     \8printer\n
- *             return the queue status (queuing enabled or disabled).
  *
  * Strategy to maintain protected spooling area:
  *     1. Spooling area is writable only by daemon and spooling group
  *
  * Strategy to maintain protected spooling area:
  *     1. Spooling area is writable only by daemon and spooling group
@@ -38,18 +71,18 @@ static char sccsid[] = "@(#)lpd.c   4.10 (Berkeley) %G%";
  */
 
 #include "lp.h"
  */
 
 #include "lp.h"
+#include "pathnames.h"
 
 
-static int     lflag;                          /* log requests flag */
-static char    *logfile = DEFLOGF;
+int    lflag;                          /* log requests flag */
+int    from_remote;                    /* from remote socket */
 
 
-int    reapchild();
-int    cleanup();
+void mcleanup(), reapchild();
 
 main(argc, argv)
        int argc;
        char **argv;
 {
 
 main(argc, argv)
        int argc;
        char **argv;
 {
-       int f, funix, finet, options, defreadfds, fromlen;
+       int f, funix, finet, options = 0, defreadfds, fromlen;
        struct sockaddr_un sun, fromunix;
        struct sockaddr_in sin, frominet;
        int omask, lfd;
        struct sockaddr_un sun, fromunix;
        struct sockaddr_in sin, frominet;
        int omask, lfd;
@@ -67,10 +100,6 @@ main(argc, argv)
                        case 'l':
                                lflag++;
                                break;
                        case 'l':
                                lflag++;
                                break;
-                       case 'L':
-                               argc--;
-                               logfile = *++argv;
-                               break;
                        }
        }
 
                        }
        }
 
@@ -78,30 +107,20 @@ main(argc, argv)
        /*
         * Set up standard environment by detaching from the parent.
         */
        /*
         * Set up standard environment by detaching from the parent.
         */
-       if (fork())
-               exit(0);
-       for (f = 0; f < 3; f++)
-               (void) close(f);
-       (void) open("/dev/null", O_RDONLY);
-       (void) open("/dev/null", O_WRONLY);
-       (void) open(logfile, O_WRONLY|O_APPEND);
-       f = open("/dev/tty", O_RDWR);
-       if (f > 0) {
-               ioctl(f, TIOCNOTTY, 0);
-               (void) close(f);
-       }
+       daemon(0, 0);
 #endif
 
 #endif
 
+       openlog("lpd", LOG_PID, LOG_LPR);
        (void) umask(0);
        (void) umask(0);
-       lfd = open(MASTERLOCK, O_WRONLY|O_CREAT, 0644);
+       lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT, 0644);
        if (lfd < 0) {
        if (lfd < 0) {
-               log("cannot create %s", MASTERLOCK);
+               syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
                exit(1);
        }
        if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
                if (errno == EWOULDBLOCK)       /* active deamon present */
                        exit(0);
                exit(1);
        }
        if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
                if (errno == EWOULDBLOCK)       /* active deamon present */
                        exit(0);
-               log("cannot lock %s", MASTERLOCK);
+               syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
                exit(1);
        }
        ftruncate(lfd, 0);
                exit(1);
        }
        ftruncate(lfd, 0);
@@ -111,7 +130,7 @@ main(argc, argv)
        sprintf(line, "%u\n", getpid());
        f = strlen(line);
        if (write(lfd, line, f) != f) {
        sprintf(line, "%u\n", getpid());
        f = strlen(line);
        if (write(lfd, line, f) != f) {
-               log("cannot write daemon pid");
+               syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
                exit(1);
        }
        signal(SIGCHLD, reapchild);
                exit(1);
        }
        signal(SIGCHLD, reapchild);
@@ -119,22 +138,23 @@ main(argc, argv)
         * Restart all the printers.
         */
        startup();
         * Restart all the printers.
         */
        startup();
-       (void) unlink(SOCKETNAME);
+       (void) unlink(_PATH_SOCKETNAME);
        funix = socket(AF_UNIX, SOCK_STREAM, 0);
        if (funix < 0) {
        funix = socket(AF_UNIX, SOCK_STREAM, 0);
        if (funix < 0) {
-               logerr("socket");
+               syslog(LOG_ERR, "socket: %m");
                exit(1);
        }
 #define        mask(s) (1 << ((s) - 1))
        omask = sigblock(mask(SIGHUP)|mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
                exit(1);
        }
 #define        mask(s) (1 << ((s) - 1))
        omask = sigblock(mask(SIGHUP)|mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
-       signal(SIGHUP, cleanup);
-       signal(SIGINT, cleanup);
-       signal(SIGQUIT, cleanup);
-       signal(SIGTERM, cleanup);
+       signal(SIGHUP, mcleanup);
+       signal(SIGINT, mcleanup);
+       signal(SIGQUIT, mcleanup);
+       signal(SIGTERM, mcleanup);
        sun.sun_family = AF_UNIX;
        sun.sun_family = AF_UNIX;
-       strcpy(sun.sun_path, SOCKETNAME);
-       if (bind(funix, &sun, strlen(sun.sun_path) + 2) < 0) {
-               logerr("unix domain bind");
+       strcpy(sun.sun_path, _PATH_SOCKETNAME);
+       if (bind(funix,
+            (struct sockaddr *)&sun, strlen(sun.sun_path) + 2) < 0) {
+               syslog(LOG_ERR, "ubind: %m");
                exit(1);
        }
        sigsetmask(omask);
                exit(1);
        }
        sigsetmask(omask);
@@ -146,19 +166,19 @@ main(argc, argv)
 
                if (options & SO_DEBUG)
                        if (setsockopt(finet, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) {
 
                if (options & SO_DEBUG)
                        if (setsockopt(finet, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) {
-                               logerr("setsockopt (SO_DEBUG)");
-                               cleanup();
+                               syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
+                               mcleanup();
                        }
                sp = getservbyname("printer", "tcp");
                if (sp == NULL) {
                        }
                sp = getservbyname("printer", "tcp");
                if (sp == NULL) {
-                       log("printer/tcp: unknown service");
-                       cleanup();
+                       syslog(LOG_ERR, "printer/tcp: unknown service");
+                       mcleanup();
                }
                sin.sin_family = AF_INET;
                sin.sin_port = sp->s_port;
                }
                sin.sin_family = AF_INET;
                sin.sin_port = sp->s_port;
-               if (bind(finet, &sin, sizeof(sin), 0) < 0) {
-                       logerr("internet domain bind");
-                       cleanup();
+               if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+                       syslog(LOG_ERR, "bind: %m");
+                       mcleanup();
                }
                defreadfds |= 1 << finet;
                listen(finet, 5);
                }
                defreadfds |= 1 << finet;
                listen(finet, 5);
@@ -171,25 +191,23 @@ main(argc, argv)
 
                nfds = select(20, &readfds, 0, 0, 0);
                if (nfds <= 0) {
 
                nfds = select(20, &readfds, 0, 0, 0);
                if (nfds <= 0) {
-                       if (nfds < 0 && errno != EINTR) {
-                               logerr("select");
-                               cleanup();
-                               /*NOTREACHED*/
-                       }
+                       if (nfds < 0 && errno != EINTR)
+                               syslog(LOG_WARNING, "select: %m");
                        continue;
                }
                if (readfds & (1 << funix)) {
                        domain = AF_UNIX, fromlen = sizeof(fromunix);
                        continue;
                }
                if (readfds & (1 << funix)) {
                        domain = AF_UNIX, fromlen = sizeof(fromunix);
-                       s = accept(funix, &fromunix, &fromlen);
+                       s = accept(funix,
+                           (struct sockaddr *)&fromunix, &fromlen);
                } else if (readfds & (1 << finet)) {
                        domain = AF_INET, fromlen = sizeof(frominet);
                } else if (readfds & (1 << finet)) {
                        domain = AF_INET, fromlen = sizeof(frominet);
-                       s = accept(finet, &frominet, &fromlen);
+                       s = accept(finet,
+                           (struct sockaddr *)&frominet, &fromlen);
                }
                if (s < 0) {
                }
                if (s < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       logerr("accept");
-                       cleanup();
+                       if (errno != EINTR)
+                               syslog(LOG_WARNING, "accept: %m");
+                       continue;
                }
                if (fork() == 0) {
                        signal(SIGCHLD, SIG_IGN);
                }
                if (fork() == 0) {
                        signal(SIGCHLD, SIG_IGN);
@@ -201,8 +219,11 @@ main(argc, argv)
                        (void) close(finet);
                        dup2(s, 1);
                        (void) close(s);
                        (void) close(finet);
                        dup2(s, 1);
                        (void) close(s);
-                       if (domain == AF_INET)
+                       if (domain == AF_INET) {
+                               from_remote = 1;
                                chkhost(&frominet);
                                chkhost(&frominet);
+                       } else
+                               from_remote = 0;
                        doit();
                        exit(0);
                }
                        doit();
                        exit(0);
                }
@@ -210,21 +231,21 @@ main(argc, argv)
        }
 }
 
        }
 }
 
-static
+void
 reapchild()
 {
        union wait status;
 
 reapchild()
 {
        union wait status;
 
-       while (wait3(&status, WNOHANG, 0) > 0)
+       while (wait3((int *)&status, WNOHANG, 0) > 0)
                ;
 }
 
                ;
 }
 
-static
-cleanup()
+void
+mcleanup()
 {
        if (lflag)
 {
        if (lflag)
-               log("cleanup()");
-       unlink(SOCKETNAME);
+               syslog(LOG_INFO, "exiting");
+       unlink(_PATH_SOCKETNAME);
        exit(0);
 }
 
        exit(0);
 }
 
@@ -237,9 +258,9 @@ int requ[MAXREQUESTS];      /* job number of spool entries */
 int    requests;               /* # of spool requests */
 char   *person;                /* name of person doing lprm */
 
 int    requests;               /* # of spool requests */
 char   *person;                /* name of person doing lprm */
 
-static char    fromb[32];      /* buffer for client's machine name */
-static char    cbuf[BUFSIZ];   /* command line buffer */
-static char    *cmdnames[] = {
+char   fromb[32];      /* buffer for client's machine name */
+char   cbuf[BUFSIZ];   /* command line buffer */
+char   *cmdnames[] = {
        "null",
        "printjob",
        "recvjob",
        "null",
        "printjob",
        "recvjob",
@@ -248,7 +269,6 @@ static char *cmdnames[] = {
        "rmjob"
 };
 
        "rmjob"
 };
 
-static
 doit()
 {
        register char *cp;
 doit()
 {
        register char *cp;
@@ -267,9 +287,13 @@ doit()
                } while (*cp++ != '\n');
                *--cp = '\0';
                cp = cbuf;
                } while (*cp++ != '\n');
                *--cp = '\0';
                cp = cbuf;
-               if (lflag && *cp >= '\1' && *cp <= '\5') {
-                       printer = NULL;
-                       log("%s requests %s %s", from, cmdnames[*cp], cp+1);
+               if (lflag) {
+                       if (*cp >= '\1' && *cp <= '\5')
+                               syslog(LOG_INFO, "%s requests %s %s",
+                                       from, cmdnames[*cp], cp+1);
+                       else
+                               syslog(LOG_INFO, "bad request (%d) from %s",
+                                       *cp, from);
                }
                switch (*cp++) {
                case '\1':      /* check the queue and print any jobs there */
                }
                switch (*cp++) {
                case '\1':      /* check the queue and print any jobs there */
@@ -277,6 +301,10 @@ doit()
                        printjob();
                        break;
                case '\2':      /* receive files to be queued */
                        printjob();
                        break;
                case '\2':      /* receive files to be queued */
+                       if (!from_remote) {
+                               syslog(LOG_INFO, "illegal request (%d)", *cp);
+                               exit(1);
+                       }
                        printer = cp;
                        recvjob();
                        break;
                        printer = cp;
                        recvjob();
                        break;
@@ -306,6 +334,10 @@ doit()
                        displayq(cbuf[0] - '\3');
                        exit(0);
                case '\5':      /* remove a job from the queue */
                        displayq(cbuf[0] - '\3');
                        exit(0);
                case '\5':      /* remove a job from the queue */
+                       if (!from_remote) {
+                               syslog(LOG_INFO, "illegal request (%d)", *cp);
+                               exit(1);
+                       }
                        printer = cp;
                        while (*cp && *cp != ' ')
                                cp++;
                        printer = cp;
                        while (*cp && *cp != ' ')
                                cp++;
@@ -344,7 +376,6 @@ doit()
  * Make a pass through the printcap database and start printing any
  * files left from the last time the machine went down.
  */
  * Make a pass through the printcap database and start printing any
  * files left from the last time the machine went down.
  */
-static
 startup()
 {
        char buf[BUFSIZ];
 startup()
 {
        char buf[BUFSIZ];
@@ -363,8 +394,8 @@ startup()
                                break;
                        }
                if ((pid = fork()) < 0) {
                                break;
                        }
                if ((pid = fork()) < 0) {
-                       log("startup: cannot fork");
-                       cleanup();
+                       syslog(LOG_WARNING, "startup: cannot fork");
+                       mcleanup();
                }
                if (!pid) {
                        endprent();
                }
                if (!pid) {
                        endprent();
@@ -373,23 +404,27 @@ startup()
        }
 }
 
        }
 }
 
+#define DUMMY ":nobody::"
+
 /*
  * Check to see if the from host has access to the line printer.
  */
 /*
  * Check to see if the from host has access to the line printer.
  */
-static
 chkhost(f)
        struct sockaddr_in *f;
 {
        register struct hostent *hp;
        register FILE *hostf;
 chkhost(f)
        struct sockaddr_in *f;
 {
        register struct hostent *hp;
        register FILE *hostf;
-       register char *cp;
+       register char *cp, *sp;
        char ahost[50];
        char ahost[50];
+       int first = 1;
        extern char *inet_ntoa();
        extern char *inet_ntoa();
+       int baselen = -1;
 
        f->sin_port = ntohs(f->sin_port);
        if (f->sin_family != AF_INET || f->sin_port >= IPPORT_RESERVED)
                fatal("Malformed from address");
 
        f->sin_port = ntohs(f->sin_port);
        if (f->sin_family != AF_INET || f->sin_port >= IPPORT_RESERVED)
                fatal("Malformed from address");
-       hp = gethostbyaddr(&f->sin_addr, sizeof(struct in_addr), f->sin_family);
+       hp = gethostbyaddr((char *)&f->sin_addr,
+           sizeof(struct in_addr), f->sin_family);
        if (hp == 0)
                fatal("Host name for your address (%s) unknown",
                        inet_ntoa(f->sin_addr));
        if (hp == 0)
                fatal("Host name for your address (%s) unknown",
                        inet_ntoa(f->sin_addr));
@@ -399,50 +434,31 @@ chkhost(f)
        if (!strcmp(from, host))
                return;
 
        if (!strcmp(from, host))
                return;
 
-       hostf = fopen("/etc/hosts.equiv", "r");
-       while (fgets(ahost, sizeof(ahost), hostf)) {
-               if (cp = index(ahost, '\n'))
-                       *cp = '\0';
-               cp = index(ahost, ' ');
-               if (!strcmp(from, ahost) && cp == NULL) {
+       sp = fromb;
+       cp = ahost;
+       while (*sp) {
+               if (*sp == '.') {
+                       if (baselen == -1)
+                               baselen = sp - fromb;
+                       *cp++ = *sp++;
+               } else {
+                       *cp++ = isupper(*sp) ? tolower(*sp++) : *sp++;
+               }
+       }
+       *cp = '\0';
+       hostf = fopen(_PATH_HOSTSEQUIV, "r");
+again:
+       if (hostf) {
+               if (!_validuser(hostf, ahost, DUMMY, DUMMY, baselen)) {
                        (void) fclose(hostf);
                        return;
                }
                        (void) fclose(hostf);
                        return;
                }
+               (void) fclose(hostf);
+       }
+       if (first == 1) {
+               first = 0;
+               hostf = fopen(_PATH_HOSTSLPD, "r");
+               goto again;
        }
        fatal("Your host does not have line printer access");
 }
        }
        fatal("Your host does not have line printer access");
 }
-
-/*VARARGS1*/
-log(msg, a1, a2, a3)
-       char *msg;
-{
-       short console = isatty(fileno(stderr));
-
-       fprintf(stderr, console ? "\r\n%s: " : "%s: ", name);
-       if (printer)
-               fprintf(stderr, "%s: ", printer);
-       fprintf(stderr, msg, a1, a2, a3);
-       if (console)
-               putc('\r', stderr);
-       putc('\n', stderr);
-       fflush(stderr);
-}
-
-static
-logerr(msg)
-       char *msg;
-{
-       register int err = errno;
-       short console = isatty(fileno(stderr));
-       extern int sys_nerr;
-       extern char *sys_errlist[];
-
-       fprintf(stderr, console ? "\r\n%s: " : "%s: ", name);
-       if (msg)
-               fprintf(stderr, "%s: ", msg);
-       fputs(err < sys_nerr ? sys_errlist[err] : "Unknown error" , stderr);
-       if (console)
-               putc('\r', stderr);
-       putc('\n', stderr);
-       fflush(stderr);
-}