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