home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / lpr / lpd / recvjob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-04  |  7.0 KB  |  304 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[] = "@(#)recvjob.c    5.15 (Berkeley) 5/4/91";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * Receive printer jobs from the network, queue them and
  40.  * start the printer daemon.
  41.  */
  42.  
  43. #include "lp.h"
  44. #include "pathnames.h"
  45. #include <sys/mount.h>
  46.  
  47. char    *sp = "";
  48. #define ack()    (void) write(1, sp, 1);
  49.  
  50. char    tfname[40];        /* tmp copy of cf before linking */
  51. char    dfname[40];        /* data files */
  52. int    minfree;        /* keep at least minfree blocks available */
  53.  
  54. void    rcleanup();
  55.  
  56. recvjob()
  57. {
  58.     struct stat stb;
  59.     char *bp = pbuf;
  60.     int status;
  61.  
  62.     /*
  63.      * Perform lookup for printer name or abbreviation
  64.      */
  65.     if ((status = pgetent(line, printer)) < 0)
  66.         frecverr("cannot open printer description file");
  67.     else if (status == 0)
  68.         frecverr("unknown printer %s", printer);
  69.     if ((LF = pgetstr("lf", &bp)) == NULL)
  70.         LF = _PATH_CONSOLE;
  71.     if ((SD = pgetstr("sd", &bp)) == NULL)
  72.         SD = _PATH_DEFSPOOL;
  73.     if ((LO = pgetstr("lo", &bp)) == NULL)
  74.         LO = DEFLOCK;
  75.  
  76.     (void) close(2);            /* set up log file */
  77.     if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
  78.         syslog(LOG_ERR, "%s: %m", LF);
  79.         (void) open(_PATH_DEVNULL, O_WRONLY);
  80.     }
  81.  
  82.     if (chdir(SD) < 0)
  83.         frecverr("%s: %s: %m", printer, SD);
  84.     if (stat(LO, &stb) == 0) {
  85.         if (stb.st_mode & 010) {
  86.             /* queue is disabled */
  87.             putchar('\1');        /* return error code */
  88.             exit(1);
  89.         }
  90.     } else if (stat(SD, &stb) < 0)
  91.         frecverr("%s: %s: %m", printer, SD);
  92.     minfree = 2 * read_number("minfree");    /* scale KB to 512 blocks */
  93.     signal(SIGTERM, rcleanup);
  94.     signal(SIGPIPE, rcleanup);
  95.  
  96.     if (readjob())
  97.         printjob();
  98. }
  99.  
  100. /*
  101.  * Read printer jobs sent by lpd and copy them to the spooling directory.
  102.  * Return the number of jobs successfully transfered.
  103.  */
  104. readjob()
  105. {
  106.     register int size, nfiles;
  107.     register char *cp;
  108.  
  109.     ack();
  110.     nfiles = 0;
  111.     for (;;) {
  112.         /*
  113.          * Read a command to tell us what to do
  114.          */
  115.         cp = line;
  116.         do {
  117.             if ((size = read(1, cp, 1)) != 1) {
  118.                 if (size < 0)
  119.                     frecverr("%s: Lost connection",printer);
  120.                 return(nfiles);
  121.             }
  122.         } while (*cp++ != '\n');
  123.         *--cp = '\0';
  124.         cp = line;
  125.         switch (*cp++) {
  126.         case '\1':    /* cleanup because data sent was bad */
  127.             rcleanup();
  128.             continue;
  129.  
  130.         case '\2':    /* read cf file */
  131.             size = 0;
  132.             while (*cp >= '0' && *cp <= '9')
  133.                 size = size * 10 + (*cp++ - '0');
  134.             if (*cp++ != ' ')
  135.                 break;
  136.             /*
  137.              * host name has been authenticated, we use our
  138.              * view of the host name since we may be passed
  139.              * something different than what gethostbyaddr()
  140.              * returns
  141.              */
  142.             strcpy(cp + 6, from);
  143.             strcpy(tfname, cp);
  144.             tfname[0] = 't';
  145.             if (!chksize(size)) {
  146.                 (void) write(1, "\2", 1);
  147.                 continue;
  148.             }
  149.             if (!readfile(tfname, size)) {
  150.                 rcleanup();
  151.                 continue;
  152.             }
  153.             if (link(tfname, cp) < 0)
  154.                 frecverr("%s: %m", tfname);
  155.             (void) unlink(tfname);
  156.             tfname[0] = '\0';
  157.             nfiles++;
  158.             continue;
  159.  
  160.         case '\3':    /* read df file */
  161.             size = 0;
  162.             while (*cp >= '0' && *cp <= '9')
  163.                 size = size * 10 + (*cp++ - '0');
  164.             if (*cp++ != ' ')
  165.                 break;
  166.             if (!chksize(size)) {
  167.                 (void) write(1, "\2", 1);
  168.                 continue;
  169.             }
  170.             (void) strcpy(dfname, cp);
  171.             if (index(dfname, '/'))
  172.                 frecverr("readjob: %s: illegal path name",
  173.                     dfname);
  174.             (void) readfile(dfname, size);
  175.             continue;
  176.         }
  177.         frecverr("protocol screwup");
  178.     }
  179. }
  180.  
  181. /*
  182.  * Read files send by lpd and copy them to the spooling directory.
  183.  */
  184. readfile(file, size)
  185.     char *file;
  186.     int size;
  187. {
  188.     register char *cp;
  189.     char buf[BUFSIZ];
  190.     register int i, j, amt;
  191.     int fd, err;
  192.  
  193.     fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD);
  194.     if (fd < 0)
  195.         frecverr("readfile: %s: illegal path name: %m", file);
  196.     ack();
  197.     err = 0;
  198.     for (i = 0; i < size; i += BUFSIZ) {
  199.         amt = BUFSIZ;
  200.         cp = buf;
  201.         if (i + amt > size)
  202.             amt = size - i;
  203.         do {
  204.             j = read(1, cp, amt);
  205.             if (j <= 0)
  206.                 frecverr("Lost connection");
  207.             amt -= j;
  208.             cp += j;
  209.         } while (amt > 0);
  210.         amt = BUFSIZ;
  211.         if (i + amt > size)
  212.             amt = size - i;
  213.         if (write(fd, buf, amt) != amt) {
  214.             err++;
  215.             break;
  216.         }
  217.     }
  218.     (void) close(fd);
  219.     if (err)
  220.         frecverr("%s: write error", file);
  221.     if (noresponse()) {        /* file sent had bad data in it */
  222.         (void) unlink(file);
  223.         return(0);
  224.     }
  225.     ack();
  226.     return(1);
  227. }
  228.  
  229. noresponse()
  230. {
  231.     char resp;
  232.  
  233.     if (read(1, &resp, 1) != 1)
  234.         frecverr("Lost connection");
  235.     if (resp == '\0')
  236.         return(0);
  237.     return(1);
  238. }
  239.  
  240. /*
  241.  * Check to see if there is enough space on the disk for size bytes.
  242.  * 1 == OK, 0 == Not OK.
  243.  */
  244. chksize(size)
  245.     int size;
  246. {
  247.     int spacefree;
  248.     struct statfs sfb;
  249.  
  250.     if (statfs(".", &sfb) < 0) {
  251.         syslog(LOG_ERR, "%s: %m", "statfs(\".\")");
  252.         return (1);
  253.     }
  254.     spacefree = sfb.f_bavail * (sfb.f_fsize / 512);
  255.     size = (size + 511) / 512;
  256.     if (minfree + size > spacefree)
  257.         return(0);
  258.     return(1);
  259. }
  260.  
  261. read_number(fn)
  262.     char *fn;
  263. {
  264.     char lin[80];
  265.     register FILE *fp;
  266.  
  267.     if ((fp = fopen(fn, "r")) == NULL)
  268.         return (0);
  269.     if (fgets(lin, 80, fp) == NULL) {
  270.         fclose(fp);
  271.         return (0);
  272.     }
  273.     fclose(fp);
  274.     return (atoi(lin));
  275. }
  276.  
  277. /*
  278.  * Remove all the files associated with the current job being transfered.
  279.  */
  280. void
  281. rcleanup()
  282. {
  283.  
  284.     if (tfname[0])
  285.         (void) unlink(tfname);
  286.     if (dfname[0])
  287.         do {
  288.             do
  289.                 (void) unlink(dfname);
  290.             while (dfname[2]-- != 'A');
  291.             dfname[2] = 'z';
  292.         } while (dfname[0]-- != 'd');
  293.     dfname[0] = '\0';
  294. }
  295.  
  296. frecverr(msg, a1, a2)
  297.     char *msg;
  298. {
  299.     rcleanup();
  300.     syslog(LOG_ERR, msg, a1, a2);
  301.     putchar('\1');        /* return error code */
  302.     exit(1);
  303. }
  304.