lpdsend.c (9564B)
1 #include <u.h> 2 #include <sys/types.h> 3 #include <unistd.h> 4 #include <sys/stat.h> 5 #include <sys/param.h> 6 #include <stdlib.h> 7 #include <fcntl.h> 8 #include <stdio.h> 9 #include <string.h> 10 #include <signal.h> 11 #include <libc.h> 12 13 #define REDIALTIMEOUT 15 14 #define TIMEOUT 600 15 16 char tmpfilename[L_tmpnam+1]; 17 int alarmstate = 0; 18 int debugflag = 0; 19 int killflag = 0; 20 int statflag = 0; 21 22 void 23 cleanup(void) { 24 unlink(tmpfilename); 25 } 26 27 #define SBSIZE 8192 28 unsigned char sendbuf[SBSIZE]; 29 30 void 31 debug(char *str) { 32 if (debugflag) 33 fprintf(stderr, "%s", str); 34 } 35 36 void 37 alarmhandler(int sig) { 38 fprintf(stderr, "timeout occurred, check printer.\n"); 39 exit(2); 40 } 41 42 /* send a message after each WARNPC percent of data sent */ 43 #define WARNPC 5 44 45 int 46 copyfile(int in, int out, long tosend) { 47 int n; 48 int sent = 0; 49 int percent = 0; 50 51 if (debugflag) 52 fprintf(stderr, "lpdsend: copyfile(%d,%d,%ld)\n", 53 in, out, tosend); 54 while ((n=read(in, sendbuf, SBSIZE)) > 0) { 55 if (debugflag) 56 fprintf(stderr, "lpdsend: copyfile read %d bytes from %d\n", 57 n, in); 58 alarm(TIMEOUT); alarmstate = 1; 59 if (write(out, sendbuf, n) != n) { 60 alarm(0); 61 fprintf(stderr, "write to fd %d failed\n", out); 62 return(0); 63 } 64 alarm(0); 65 if (debugflag) 66 fprintf(stderr, "lpdsend: copyfile wrote %d bytes to %d\n", 67 n, out); 68 sent += n; 69 if (tosend && ((sent*100/tosend)>=(percent+WARNPC))) { 70 percent += WARNPC; 71 fprintf(stderr, ": %5.2f%% sent\n", sent*100.0/tosend); 72 } 73 } 74 if (debugflag) 75 fprintf(stderr, "lpdsend: copyfile read %d bytes from %d\n", 76 n, in); 77 return(!n); 78 } 79 80 char strbuf[120]; 81 char hostname[MAXHOSTNAMELEN], *username, *printername, *killarg; 82 char *inputname; 83 char filetype = 'o'; /* 'o' is for PostScript */ 84 int seqno = 0; 85 char *seqfilename; 86 87 void 88 killjob(int printerfd) { 89 int strlength; 90 if (printername==0) { 91 fprintf(stderr, "no printer name\n"); 92 exit(1); 93 } 94 if (username==0) { 95 fprintf(stderr, "no user name given\n"); 96 exit(1); 97 } 98 if (killarg==0) { 99 fprintf(stderr, "no job to kill\n"); 100 exit(1); 101 } 102 sprintf(strbuf, "%c%s %s %s\n", '\5', printername, username, killarg); 103 strlength = strlen(strbuf); 104 if (write(printerfd, strbuf, strlength) != strlength) { 105 fprintf(stderr, "write(printer) error\n"); 106 exit(1); 107 } 108 copyfile(printerfd, 2, 0L); 109 } 110 111 void 112 checkqueue(int printerfd) { 113 int strlength; 114 115 sprintf(strbuf, "%c%s\n", '\4', printername); 116 strlength = strlen(strbuf); 117 if (write(printerfd, strbuf, strlength) != strlength) { 118 fprintf(stderr, "write(printer) error\n"); 119 exit(1); 120 } 121 copyfile(printerfd, 2, 0L); 122 /* 123 { int n; 124 unsigned char sendbuf[1]; 125 while ((n=read(printerfd, sendbuf, 1)) > 0) { 126 write(2, sendbuf, n); 127 } 128 } 129 */ 130 } 131 132 void 133 getack(int printerfd, int as) { 134 char resp; 135 int rv; 136 137 alarm(TIMEOUT); alarmstate = as; 138 if ((rv=read(printerfd, &resp, 1)) != 1 || resp != '\0') { 139 fprintf(stderr, "getack failed: read returned %d, read value (if any) %d, alarmstate=%d\n", 140 rv, resp, alarmstate); 141 exit(1); 142 } 143 alarm(0); 144 } 145 146 /* send control file */ 147 void 148 sendctrl(int printerfd) { 149 char cntrlstrbuf[256]; 150 int strlength, cntrlen; 151 152 sprintf(cntrlstrbuf, "H%s\nP%s\n%cdfA%3.3d%s\n", hostname, username, filetype, seqno, hostname); 153 cntrlen = strlen(cntrlstrbuf); 154 sprintf(strbuf, "%c%d cfA%3.3d%s\n", '\2', cntrlen, seqno, hostname); 155 strlength = strlen(strbuf); 156 if (write(printerfd, strbuf, strlength) != strlength) { 157 fprintf(stderr, "write(printer) error\n"); 158 exit(1); 159 } 160 getack(printerfd, 3); 161 if (write(printerfd, cntrlstrbuf, cntrlen) != cntrlen) { 162 fprintf(stderr, "write(printer) error\n"); 163 exit(1); 164 } 165 if (write(printerfd, "\0", 1) != 1) { 166 fprintf(stderr, "write(printer) error\n"); 167 exit(1); 168 } 169 getack(printerfd, 4); 170 } 171 172 /* send data file */ 173 void 174 senddata(int inputfd, int printerfd, long size) { 175 int strlength; 176 177 sprintf(strbuf, "%c%ld dfA%3.3d%s\n", '\3', size, seqno, hostname); 178 strlength = strlen(strbuf); 179 if (write(printerfd, strbuf, strlength) != strlength) { 180 fprintf(stderr, "write(printer) error\n"); 181 exit(1); 182 } 183 getack(printerfd, 5); 184 if (!copyfile(inputfd, printerfd, size)) { 185 fprintf(stderr, "failed to send file to printer\n"); 186 exit(1); 187 } 188 if (write(printerfd, "\0", 1) != 1) { 189 fprintf(stderr, "write(printer) error\n"); 190 exit(1); 191 } 192 fprintf(stderr, "%ld bytes sent, status: waiting for end of job\n", size); 193 getack(printerfd, 6); 194 } 195 196 void 197 sendjob(int inputfd, int printerfd) { 198 struct stat statbuf; 199 int strlength; 200 201 if (fstat(inputfd, &statbuf) < 0) { 202 fprintf(stderr, "fstat(%s) failed\n", inputname); 203 exit(1); 204 } 205 sprintf(strbuf, "%c%s\n", '\2', printername); 206 strlength = strlen(strbuf); 207 if (write(printerfd, strbuf, strlength) != strlength) { 208 fprintf(stderr, "write(printer) error\n"); 209 exit(1); 210 } 211 getack(printerfd, 2); 212 debug("send data\n"); 213 senddata(inputfd, printerfd, statbuf.st_size); 214 debug("send control info\n"); 215 sendctrl(printerfd); 216 fprintf(stderr, "%ld bytes sent, status: end of job\n", (long)statbuf.st_size); 217 } 218 219 /* 220 * make an address, add the defaults 221 */ 222 char * 223 netmkaddr(char *linear, char *defnet, char *defsrv) 224 { 225 static char addr[512]; 226 char *cp; 227 228 /* 229 * dump network name 230 */ 231 cp = strchr(linear, '!'); 232 if(cp == 0){ 233 if(defnet==0){ 234 if(defsrv) 235 sprintf(addr, "net!%s!%s", linear, defsrv); 236 else 237 sprintf(addr, "net!%s", linear); 238 } 239 else { 240 if(defsrv) 241 sprintf(addr, "%s!%s!%s", defnet, linear, defsrv); 242 else 243 sprintf(addr, "%s!%s", defnet, linear); 244 } 245 return addr; 246 } 247 248 /* 249 * if there is already a service, use it 250 */ 251 cp = strchr(cp+1, '!'); 252 if(cp) 253 return linear; 254 255 /* 256 * add default service 257 */ 258 if(defsrv == 0) 259 return linear; 260 sprintf(addr, "%s!%s", linear, defsrv); 261 262 return addr; 263 } 264 265 void 266 main(int argc, char *argv[]) { 267 int c, usgflg = 0; 268 char *desthostname; 269 int printerfd; 270 int inputfd; 271 int sendport; 272 char portstr[4]; 273 274 desthostname = nil; 275 if (signal(SIGALRM, alarmhandler) == SIG_ERR) { 276 fprintf(stderr, "failed to set alarm handler\n"); 277 exit(1); 278 } 279 while ((c = getopt(argc, argv, "Dd:k:qs:t:H:P:")) != -1) 280 switch (c) { 281 case 'D': 282 debugflag = 1; 283 debug("debugging on\n"); 284 break; 285 case 'd': 286 printername = optarg; 287 break; 288 case 'k': 289 if (statflag) { 290 fprintf(stderr, "cannot have both -k and -q flags\n"); 291 exit(1); 292 } 293 killflag = 1; 294 killarg = optarg; 295 break; 296 case 'q': 297 if (killflag) { 298 fprintf(stderr, "cannot have both -q and -k flags\n"); 299 exit(1); 300 } 301 statflag = 1; 302 break; 303 case 's': 304 seqno = strtol(optarg, NULL, 10); 305 if (seqno < 0 || seqno > 999) 306 seqno = 0; 307 break; 308 case 't': 309 switch (filetype) { 310 case 'c': 311 case 'd': 312 case 'f': 313 case 'g': 314 case 'l': 315 case 'n': 316 case 'o': 317 case 'p': 318 case 'r': 319 case 't': 320 case 'v': 321 case 'z': 322 filetype = optarg[0]; 323 break; 324 default: 325 usgflg++; 326 break; 327 } 328 break; 329 case 'H': 330 strncpy(hostname, optarg, MAXHOSTNAMELEN); 331 break; 332 case 'P': 333 username = optarg; 334 break; 335 default: 336 case '?': 337 fprintf(stderr, "unknown option %c\n", c); 338 usgflg++; 339 } 340 if (argc < 2) usgflg++; 341 if (optind < argc) { 342 desthostname = argv[optind++]; 343 } else 344 usgflg++; 345 if (usgflg) { 346 fprintf(stderr, "usage: to send a job - %s -d printer -H hostname -P username [-s seqno] [-t[cdfgklnoprtvz]] desthost [filename]\n", argv[0]); 347 fprintf(stderr, " to check status - %s -d printer -q desthost\n", argv[0]); 348 fprintf(stderr, " to kill a job - %s -d printer -P username -k jobname desthost\n", argv[0]); 349 exit(1); 350 } 351 352 /* make sure the file to send is here and ready 353 * otherwise the TCP connection times out. 354 */ 355 inputfd = -1; 356 if (!statflag && !killflag) { 357 if (optind < argc) { 358 inputname = argv[optind++]; 359 debug("open("); debug(inputname); debug(")\n"); 360 inputfd = open(inputname, O_RDONLY); 361 if (inputfd < 0) { 362 fprintf(stderr, "open(%s) failed\n", inputname); 363 exit(1); 364 } 365 } else { 366 inputname = "stdin"; 367 tmpnam(tmpfilename); 368 debug("using stdin\n"); 369 if ((inputfd = create(tmpfilename, ORDWR, 0600)) < 0) { 370 fprintf(stderr, "open(%s) failed\n", tmpfilename); 371 exit(1); 372 } 373 atexit(cleanup); 374 debug("copy input to temp file "); 375 debug(tmpfilename); 376 debug("\n"); 377 if (!copyfile(0, inputfd, 0L)) { 378 fprintf(stderr, "failed to copy file to temporary file\n"); 379 exit(1); 380 } 381 if (lseek(inputfd, 0L, 0) < 0) { 382 fprintf(stderr, "failed to seek back to the beginning of the temporary file\n"); 383 exit(1); 384 } 385 } 386 } 387 388 sprintf(strbuf, "%s", netmkaddr(desthostname, "tcp", "printer")); 389 fprintf(stderr, "connecting to %s\n", strbuf); 390 for (sendport=721; sendport<=731; sendport++) { 391 sprintf(portstr, "%3.3d", sendport); 392 fprintf(stderr, " trying from port %s...", portstr); 393 debug(" dial("); debug(strbuf); debug(", "); debug(portstr); debug(", 0, 0) ..."); 394 printerfd = dial(strbuf, portstr, 0, 0); 395 if (printerfd >= 0) { 396 fprintf(stderr, "connected\n"); 397 break; 398 } 399 fprintf(stderr, "failed\n"); 400 sleep(REDIALTIMEOUT); 401 } 402 if (printerfd < 0) { 403 fprintf(stderr, "Cannot open a valid port!\n"); 404 fprintf(stderr, "- All source ports [721-731] may be busy.\n"); 405 fprintf(stderr, "- Is recipient ready and online?\n"); 406 fprintf(stderr, "- If all else fails, cycle the power!\n"); 407 exit(1); 408 } 409 /* hostname[8] = '\0'; */ 410 #ifndef PLAN9 411 if (gethostname(hostname, sizeof(hostname)) < 0) { 412 perror("gethostname"); 413 exit(1); 414 } 415 #endif 416 /* char *hnend; 417 if ((hnend = strchr(hostname, '.')) != NULL) 418 *hnend = '\0'; 419 */ 420 if (statflag) { 421 checkqueue(printerfd); 422 } else if (killflag) { 423 killjob(printerfd); 424 } else { 425 sendjob(inputfd, printerfd); 426 } 427 exit(0); 428 }