1 /* recvjob.c 4.2 83/05/16 */ 2 /* 3 * Receive printer jobs from the network, queue them and 4 * start the printer daemon. 5 */ 6 7 #include "lp.h" 8 9 char tfname[40]; /* tmp copy of cf before linking */ 10 char *dfname; /* data files */ 11 12 recvjob() 13 { 14 struct stat stb; 15 char *bp = pbuf; 16 int status; 17 18 /* 19 * Perform lookup for printer name or abbreviation 20 */ 21 if ((status = pgetent(line, printer)) < 0) 22 fatal("cannot open printer description file"); 23 else if (status == 0) 24 fatal("unknown printer"); 25 if ((LF = pgetstr("lf", &bp)) == NULL) 26 LF = DEFLOGF; 27 if ((SD = pgetstr("sd", &bp)) == NULL) 28 SD = DEFSPOOL; 29 if ((LO = pgetstr("lo", &bp)) == NULL) 30 LO = DEFLOCK; 31 32 (void) close(2); 33 (void) open(LF, FWRONLY|FAPPEND, 0); 34 if (chdir(SD) < 0) 35 fatal("cannot chdir to %s", SD); 36 if (stat(LO, &stb) == 0 && (stb.st_mode & 010)) { 37 /* queue is disabled */ 38 putchar('\1'); /* return error code */ 39 exit(1); 40 } 41 42 if (readjob()) 43 printjob(); 44 } 45 46 char *sp = ""; 47 #define ack() (void) write(1, sp, 1); 48 49 /* 50 * Read printer jobs sent by lpd and copy them to the spooling directory. 51 * Return the number of jobs successfully transfered. 52 */ 53 readjob(printer) 54 char *printer; 55 { 56 register int size, nfiles; 57 register char *cp; 58 59 ack(); 60 nfiles = 0; 61 for (;;) { 62 /* 63 * Read a command to tell us what to do 64 */ 65 cp = line; 66 do { 67 if ((size = read(1, cp, 1)) != 1) { 68 if (size < 0) 69 fatal("Lost connection"); 70 return(nfiles); 71 } 72 } while (*cp++ != '\n'); 73 *--cp = '\0'; 74 cp = line; 75 switch (*cp++) { 76 case '\1': /* cleanup because data sent was bad */ 77 cleanup(); 78 continue; 79 80 case '\2': /* read cf file */ 81 size = 0; 82 while (*cp >= '0' && *cp <= '9') 83 size = size * 10 + (*cp++ - '0'); 84 if (*cp++ != ' ') 85 break; 86 strcpy(tfname, cp); 87 tfname[0] = 't'; 88 if (!readfile(tfname, size)) { 89 cleanup(); 90 continue; 91 } 92 if (link(tfname, cp) < 0) 93 fatal("cannot rename %s", tfname); 94 (void) unlink(tfname); 95 tfname[0] = '\0'; 96 nfiles++; 97 continue; 98 99 case '\3': /* read df file */ 100 size = 0; 101 while (*cp >= '0' && *cp <= '9') 102 size = size * 10 + (*cp++ - '0'); 103 if (*cp++ != ' ') 104 break; 105 (void) readfile(dfname = cp, size); 106 continue; 107 } 108 fatal("protocol screwup"); 109 } 110 } 111 112 /* 113 * Read files send by lpd and copy them to the spooling directory. 114 */ 115 readfile(file, size) 116 char *file; 117 int size; 118 { 119 register char *cp; 120 char buf[BUFSIZ]; 121 register int i, j, amt; 122 int fd, err; 123 124 fd = open(file, FWRONLY|FCREATE, FILMOD); 125 if (fd < 0) 126 fatal("cannot create %s", file); 127 ack(); 128 err = 0; 129 for (i = 0; i < size; i += BUFSIZ) { 130 amt = BUFSIZ; 131 cp = buf; 132 if (i + amt > size) 133 amt = size - i; 134 do { 135 j = read(1, cp, amt); 136 if (j <= 0) 137 fatal("Lost connection"); 138 amt -= j; 139 cp += j; 140 } while (amt > 0); 141 amt = BUFSIZ; 142 if (i + amt > size) 143 amt = size - i; 144 if (err == 0 && write(fd, buf, amt) != amt) 145 err++; 146 } 147 (void) close(fd); 148 if (err) 149 fatal("%s: write error", file); 150 if (noresponse()) { /* file sent had bad data in it */ 151 (void) unlink(file); 152 return(0); 153 } 154 ack(); 155 return(1); 156 } 157 158 static 159 noresponse() 160 { 161 char resp; 162 163 if (read(1, &resp, 1) != 1) 164 fatal("Lost connection"); 165 if (resp == '\0') 166 return(0); 167 return(1); 168 } 169 170 /* 171 * Remove all the files associated with the current job being transfered. 172 */ 173 static 174 cleanup() 175 { 176 register int i; 177 178 if (tfname[0]) 179 (void) unlink(tfname); 180 if (dfname) 181 do { 182 do 183 (void) unlink(dfname); 184 while (dfname[i]-- != 'A'); 185 dfname[i] = 'z'; 186 } while (dfname[i-2]-- != 'd'); 187 } 188 189 static 190 fatal(msg, a1) 191 char *msg; 192 { 193 cleanup(); 194 log(msg, a1); 195 putchar('\1'); /* return error code */ 196 exit(1); 197 } 198