void recvjob(void) { struct stat stb; int status; /* * Perform lookup for printer name or abbreviation */ if ((status = cgetent(&bp, printcapdb, printer)) == -2) frecverr("cannot open printer description file"); else if (status == -1) frecverr("unknown printer %s", printer); else if (status == -3) fatal("potential reference loop detected in printcap file"); if (cgetstr(bp, "lf", &LF) == -1) LF = _PATH_CONSOLE; if (cgetstr(bp, "sd", &SD) == -1) SD = _PATH_DEFSPOOL; if (cgetstr(bp, "lo", &LO) == -1) LO = DEFLOCK; (void)close(2); /* set up log file */ PRIV_START; if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { syslog(LOG_ERR, "%s: %m", LF); (void)open(_PATH_DEVNULL, O_WRONLY); } PRIV_END; if (chdir(SD) < 0) frecverr("%s: %s: %m", printer, SD); if (stat(LO, &stb) == 0) { if (stb.st_mode & 010) { /* queue is disabled */ putchar('\1'); /* return error code */ exit(1); } } else if (stat(SD, &stb) < 0) frecverr("%s: %s: %m", printer, SD); minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */ signal(SIGTERM, rcleanup); signal(SIGPIPE, rcleanup); if (readjob()) printjob(); }
recvjob() { struct stat stb; char *bp = pbuf; int status, rcleanup(); /* * Perform lookup for printer name or abbreviation */ if ((status = pgetent(line, printer)) < 0) frecverr("cannot open printer description file"); else if (status == 0) frecverr("unknown printer %s", printer); if ((LF = pgetstr("lf", &bp)) == NULL) LF = DEFLOGF; if ((SD = pgetstr("sd", &bp)) == NULL) SD = DEFSPOOL; if ((LO = pgetstr("lo", &bp)) == NULL) LO = DEFLOCK; (void) close(2); /* set up log file */ if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { syslog(LOG_ERR, "%s: %m", LF); (void) open("/dev/null", O_WRONLY); } if (chdir(SD) < 0) frecverr("%s: %s: %m", printer, SD); if (stat(LO, &stb) == 0) { if (stb.st_mode & 010) { /* queue is disabled */ putchar('\1'); /* return error code */ exit(1); } } else if (stat(SD, &stb) < 0) frecverr("%s: %s: %m", printer, SD); minfree = read_number("minfree"); ddev = find_dev(stb.st_dev, S_IFBLK); if ((dfd = open(ddev, O_RDONLY)) < 0) syslog(LOG_WARNING, "%s: %s: %m", printer, ddev); signal(SIGTERM, rcleanup); signal(SIGPIPE, rcleanup); if (readjob()) printjob(); }
/* * Read files send by lpd and copy them to the spooling directory. */ static int readfile(char *file, int size) { char *cp; char buf[BUFSIZ]; int i, j, amt; int fd, err; if ((fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD)) < 0) frecverr("readfile: %s: illegal path name: %m", file); ack(); err = 0; for (i = 0; i < size; i += BUFSIZ) { amt = BUFSIZ; cp = buf; if (i + amt > size) amt = size - i; do { j = read(STDOUT_FILENO, cp, amt); if (j <= 0) frecverr("Lost connection"); amt -= j; cp += j; } while (amt > 0); amt = BUFSIZ; if (i + amt > size) amt = size - i; if (write(fd, buf, amt) != amt) { err++; break; } } (void)close(fd); if (err) frecverr("%s: write error", file); if (noresponse()) { /* file sent had bad data in it */ if (strchr(file, '/') == NULL) (void)unlink(file); return(0); } ack(); return(1); }
static int noresponse(void) { char resp; if (read(STDOUT_FILENO, &resp, 1) != 1) frecverr("Lost connection"); if (resp == '\0') return(0); return(1); }
/* * Read printer jobs sent by lpd and copy them to the spooling directory. * Return the number of jobs successfully transfered. */ static int readjob() { register int size, nfiles; register char *cp; ack(); nfiles = 0; for (;;) { /* * Read a command to tell us what to do */ cp = line; do { if ((size = read(1, cp, 1)) != 1) { if (size < 0) frecverr("%s: Lost connection",printer); return(nfiles); } } while (*cp++ != '\n'); *--cp = '\0'; cp = line; switch (*cp++) { case '\1': /* cleanup because data sent was bad */ rcleanup(0); continue; case '\2': /* read cf file */ size = 0; while (*cp >= '0' && *cp <= '9') size = size * 10 + (*cp++ - '0'); if (*cp++ != ' ') break; /* * host name has been authenticated, we use our * view of the host name since we may be passed * something different than what gethostbyaddr() * returns */ strcpy(cp + 6, from); strcpy(tfname, cp); tfname[0] = 't'; if (!chksize(size)) { (void) write(1, "\2", 1); continue; } if (!readfile(tfname, size)) { rcleanup(0); continue; } if (link(tfname, cp) < 0) frecverr("%s: %m", tfname); (void) unlink(tfname); tfname[0] = '\0'; nfiles++; continue; case '\3': /* read df file */ size = 0; while (*cp >= '0' && *cp <= '9') size = size * 10 + (*cp++ - '0'); if (*cp++ != ' ') break; if (!chksize(size)) { (void) write(1, "\2", 1); continue; } (void) strcpy(dfname, cp); if (index(dfname, '/')) frecverr("readjob: %s: illegal path name", dfname); (void) readfile(dfname, size); continue; } frecverr("protocol screwup: %s", line); } }
/* * Read printer jobs sent by lpd and copy them to the spooling directory. * Return the number of jobs successfully transferred. */ static int readjob(void) { int size, nfiles; char *cp; ack(); nfiles = 0; for (;;) { /* * Read a command to tell us what to do */ cp = line; do { if ((size = read(STDOUT_FILENO, cp, 1)) != 1) { if (size < 0) frecverr("%s: Lost connection", printer); return(nfiles); } } while (*cp++ != '\n' && (cp - line + 1) < sizeof(line)); if (cp - line + 1 >= sizeof(line)) frecverr("readjob overflow"); *--cp = '\0'; cp = line; switch (*cp++) { case '\1': /* cleanup because data sent was bad */ rcleanup(0); continue; case '\2': /* read cf file */ size = 0; while (*cp >= '0' && *cp <= '9') size = size * 10 + (*cp++ - '0'); if (*cp++ != ' ') break; /* * host name has been authenticated, we use our * view of the host name since we may be passed * something different than what gethostbyaddr() * returns */ strlcpy(cp + 6, from, sizeof(line) + line - cp - 6); if (strchr(cp, '/')) frecverr("readjob: %s: illegal path name", cp); strlcpy(tfname, cp, sizeof(tfname)); tfname[0] = 't'; if (!chksize(size)) { (void)write(STDOUT_FILENO, "\2", 1); continue; } /* * XXX * We blindly believe what the remote host puts * for the path to the df file. In general this * is OK since we don't allow paths with '/' in * them. Still, it would be better to sanity * check the cf file sent to us and make the * df name match the cf name we used. That way * we avoid any possible collisions. */ if (!readfile(tfname, size)) { rcleanup(0); continue; } if (link(tfname, cp) < 0) frecverr("link %s %s: %m", tfname, cp); (void)unlink(tfname); tfname[0] = '\0'; nfiles++; continue; case '\3': /* read df file */ size = 0; while (*cp >= '0' && *cp <= '9') size = size * 10 + (*cp++ - '0'); if (*cp++ != ' ') break; if (strchr(cp, '/')) frecverr("readjob: %s: illegal path name", cp); if (!chksize(size)) { (void)write(STDOUT_FILENO, "\2", 1); continue; } (void)strlcpy(dfname, cp, sizeof(dfname)); (void)readfile(dfname, size); continue; } frecverr("protocol screwup: %s", line); } }