plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }