Blob


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>
13 #define REDIALTIMEOUT 15
14 #define TIMEOUT 600
16 char tmpfilename[L_tmpnam+1];
17 int alarmstate = 0;
18 int debugflag = 0;
19 int killflag = 0;
20 int statflag = 0;
22 void
23 cleanup(void) {
24 unlink(tmpfilename);
25 }
27 #define SBSIZE 8192
28 unsigned char sendbuf[SBSIZE];
30 void
31 debug(char *str) {
32 if (debugflag)
33 fprintf(stderr, "%s", str);
34 }
36 void
37 alarmhandler(int sig) {
38 fprintf(stderr, "timeout occurred, check printer.\n");
39 exit(2);
40 }
42 /* send a message after each WARNPC percent of data sent */
43 #define WARNPC 5
45 int
46 copyfile(int in, int out, long tosend) {
47 int n;
48 int sent = 0;
49 int percent = 0;
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 }
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;
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);
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);
108 copyfile(printerfd, 2, 0L);
111 void
112 checkqueue(int printerfd) {
113 int strlength;
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);
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);
129 */
132 void
133 getack(int printerfd, int as) {
134 char resp;
135 int rv;
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);
143 alarm(0);
146 /* send control file */
147 void
148 sendctrl(int printerfd) {
149 char cntrlstrbuf[256];
150 int strlength, cntrlen;
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);
160 getack(printerfd, 3);
161 if (write(printerfd, cntrlstrbuf, cntrlen) != cntrlen) {
162 fprintf(stderr, "write(printer) error\n");
163 exit(1);
165 if (write(printerfd, "\0", 1) != 1) {
166 fprintf(stderr, "write(printer) error\n");
167 exit(1);
169 getack(printerfd, 4);
172 /* send data file */
173 void
174 senddata(int inputfd, int printerfd, long size) {
175 int strlength;
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);
183 getack(printerfd, 5);
184 if (!copyfile(inputfd, printerfd, size)) {
185 fprintf(stderr, "failed to send file to printer\n");
186 exit(1);
188 if (write(printerfd, "\0", 1) != 1) {
189 fprintf(stderr, "write(printer) error\n");
190 exit(1);
192 fprintf(stderr, "%ld bytes sent, status: waiting for end of job\n", size);
193 getack(printerfd, 6);
196 void
197 sendjob(int inputfd, int printerfd) {
198 struct stat statbuf;
199 int strlength;
201 if (fstat(inputfd, &statbuf) < 0) {
202 fprintf(stderr, "fstat(%s) failed\n", inputname);
203 exit(1);
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);
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);
219 /*
220 * make an address, add the defaults
221 */
222 char *
223 netmkaddr(char *linear, char *defnet, char *defsrv)
225 static char addr[512];
226 char *cp;
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);
239 else {
240 if(defsrv)
241 sprintf(addr, "%s!%s!%s", defnet, linear, defsrv);
242 else
243 sprintf(addr, "%s!%s", defnet, linear);
245 return addr;
248 /*
249 * if there is already a service, use it
250 */
251 cp = strchr(cp+1, '!');
252 if(cp)
253 return linear;
255 /*
256 * add default service
257 */
258 if(defsrv == 0)
259 return linear;
260 sprintf(addr, "%s!%s", linear, defsrv);
262 return addr;
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];
274 desthostname = nil;
275 if (signal(SIGALRM, alarmhandler) == SIG_ERR) {
276 fprintf(stderr, "failed to set alarm handler\n");
277 exit(1);
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);
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);
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;
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++;
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);
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);
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);
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);
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);
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;
399 fprintf(stderr, "failed\n");
400 sleep(REDIALTIMEOUT);
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);
409 /* hostname[8] = '\0'; */
410 #ifndef PLAN9
411 if (gethostname(hostname, sizeof(hostname)) < 0) {
412 perror("gethostname");
413 exit(1);
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);
427 exit(0);