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