Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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