1 /* recvjob.c 4.4 83/06/15 */ 2 /* 3 * Receive printer jobs from the network, queue them and 4 * start the printer daemon. 5 */ 6 7 #include "lp.h" 8 9 static char tfname[40]; /* tmp copy of cf before linking */ 10 static 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, O_WRONLY|O_APPEND); 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 static 54 readjob(printer) 55 char *printer; 56 { 57 register int size, nfiles; 58 register char *cp; 59 60 ack(); 61 nfiles = 0; 62 for (;;) { 63 /* 64 * Read a command to tell us what to do 65 */ 66 cp = line; 67 do { 68 if ((size = read(1, cp, 1)) != 1) { 69 if (size < 0) 70 fatal("Lost connection"); 71 return(nfiles); 72 } 73 } while (*cp++ != '\n'); 74 *--cp = '\0'; 75 cp = line; 76 switch (*cp++) { 77 case '\1': /* cleanup because data sent was bad */ 78 cleanup(); 79 continue; 80 81 case '\2': /* read cf file */ 82 size = 0; 83 while (*cp >= '0' && *cp <= '9') 84 size = size * 10 + (*cp++ - '0'); 85 if (*cp++ != ' ') 86 break; 87 strcpy(tfname, cp); 88 tfname[0] = 't'; 89 if (!readfile(tfname, size)) { 90 cleanup(); 91 continue; 92 } 93 if (link(tfname, cp) < 0) 94 fatal("cannot rename %s", tfname); 95 (void) unlink(tfname); 96 tfname[0] = '\0'; 97 nfiles++; 98 continue; 99 100 case '\3': /* read df file */ 101 size = 0; 102 while (*cp >= '0' && *cp <= '9') 103 size = size * 10 + (*cp++ - '0'); 104 if (*cp++ != ' ') 105 break; 106 (void) readfile(dfname = cp, size); 107 continue; 108 } 109 fatal("protocol screwup"); 110 } 111 } 112 113 /* 114 * Read files send by lpd and copy them to the spooling directory. 115 */ 116 static 117 readfile(file, size) 118 char *file; 119 int size; 120 { 121 register char *cp; 122 char buf[BUFSIZ]; 123 register int i, j, amt; 124 int fd, err; 125 126 fd = open(file, O_WRONLY|O_CREAT, FILMOD); 127 if (fd < 0) 128 fatal("cannot create %s", file); 129 ack(); 130 err = 0; 131 for (i = 0; i < size; i += BUFSIZ) { 132 amt = BUFSIZ; 133 cp = buf; 134 if (i + amt > size) 135 amt = size - i; 136 do { 137 j = read(1, cp, amt); 138 if (j <= 0) 139 fatal("Lost connection"); 140 amt -= j; 141 cp += j; 142 } while (amt > 0); 143 amt = BUFSIZ; 144 if (i + amt > size) 145 amt = size - i; 146 if (err == 0 && write(fd, buf, amt) != amt) 147 err++; 148 } 149 (void) close(fd); 150 if (err) 151 fatal("%s: write error", file); 152 if (noresponse()) { /* file sent had bad data in it */ 153 (void) unlink(file); 154 return(0); 155 } 156 ack(); 157 return(1); 158 } 159 160 static 161 noresponse() 162 { 163 char resp; 164 165 if (read(1, &resp, 1) != 1) 166 fatal("Lost connection"); 167 if (resp == '\0') 168 return(0); 169 return(1); 170 } 171 172 /* 173 * Remove all the files associated with the current job being transfered. 174 */ 175 static 176 cleanup() 177 { 178 register int i; 179 180 if (tfname[0]) 181 (void) unlink(tfname); 182 if (dfname) 183 do { 184 do 185 (void) unlink(dfname); 186 while (dfname[i]-- != 'A'); 187 dfname[i] = 'z'; 188 } while (dfname[i-2]-- != 'd'); 189 } 190 191 static 192 fatal(msg, a1) 193 char *msg; 194 { 195 cleanup(); 196 log(msg, a1); 197 putchar('\1'); /* return error code */ 198 exit(1); 199 } 200