1 | /* |
---|
2 | * Copyright Milan Technology Corp. 1991, 1992 |
---|
3 | */ |
---|
4 | |
---|
5 | /* |
---|
6 | * fpfilter.c -- FastPort communications interface program. See man page for |
---|
7 | * complete set of options generates fpcomm for Adobe compatibility |
---|
8 | */ |
---|
9 | |
---|
10 | char *VERSION = "@(#)fpfilter.c 2.2 10/15/92"; |
---|
11 | |
---|
12 | #include "std.h" |
---|
13 | #include "dp.h" |
---|
14 | #include "errors.h" |
---|
15 | #include "udp.h" |
---|
16 | |
---|
17 | char *g_filter_name; /* The invocation name */ |
---|
18 | s_options g_opt; /* the options struct */ |
---|
19 | FILE *g_errorLog=0; /* log file for errors */ |
---|
20 | |
---|
21 | long fin_bytes; /* Total number of bytes */ |
---|
22 | long act_bytes_sent = 0; /* Number of bytes actually sent */ |
---|
23 | long int_bytes; /* Number of par bytes initially */ |
---|
24 | |
---|
25 | /* UDP Status packet type */ |
---|
26 | |
---|
27 | extern udp_status_packet udp_stat; |
---|
28 | |
---|
29 | int status_id = 0; |
---|
30 | |
---|
31 | /* SIGALARM interrupt handler. */ |
---|
32 | int g_alarmed = 0; |
---|
33 | #ifdef ANSI |
---|
34 | void |
---|
35 | to_alarm(int foo) |
---|
36 | #else |
---|
37 | void |
---|
38 | to_alarm(foo) |
---|
39 | int foo; |
---|
40 | #endif |
---|
41 | { |
---|
42 | #ifndef ESIX |
---|
43 | signal(SIGALRM, to_alarm); |
---|
44 | #endif |
---|
45 | g_alarmed = 1; |
---|
46 | } |
---|
47 | |
---|
48 | #ifdef ANSI |
---|
49 | void |
---|
50 | add_file(file_obj_ptr * flist, char *file_to_add) |
---|
51 | #else |
---|
52 | void |
---|
53 | add_file(flist, file_to_add) |
---|
54 | file_obj_ptr *flist; |
---|
55 | char *file_to_add; |
---|
56 | #endif |
---|
57 | { |
---|
58 | file_obj_ptr node, runner; |
---|
59 | node = (file_obj_ptr) malloc(sizeof(file_obj_t)); |
---|
60 | node->next = 0; |
---|
61 | strncpy(node->file_name, file_to_add, MAXNAMELEN); |
---|
62 | |
---|
63 | if (!*flist) |
---|
64 | *flist = node; |
---|
65 | else { |
---|
66 | runner = *flist; |
---|
67 | while (runner->next) |
---|
68 | runner = runner->next; |
---|
69 | runner->next = node; |
---|
70 | } |
---|
71 | } |
---|
72 | |
---|
73 | #ifdef ANSI |
---|
74 | int sendfile |
---|
75 | (int sock, char *file_to_send, int output_dest, int check_postscript, char *printer_name) |
---|
76 | #else |
---|
77 | int |
---|
78 | sendfile(sock, file_to_send, output_dest, check_postscript, printer_name) |
---|
79 | int sock; |
---|
80 | char *file_to_send; |
---|
81 | int output_dest; |
---|
82 | int check_postscript; |
---|
83 | char *printer_name; |
---|
84 | #endif |
---|
85 | { |
---|
86 | int fd; |
---|
87 | int numchars, num_sent, total_sent; |
---|
88 | int length, filetype; |
---|
89 | char inputbuffer[MAX_BUFFER]; |
---|
90 | char *databuffer; |
---|
91 | char ff = 12; |
---|
92 | char first_chars[MAX_MAGIC_HEADER]; |
---|
93 | char error_string[MAXSTRNGLEN]; |
---|
94 | int write_error_sent = 0; |
---|
95 | int i; |
---|
96 | |
---|
97 | pause(); |
---|
98 | if (strcmp(file_to_send, "STDIN")) { |
---|
99 | if ((fd = open(file_to_send, O_RDONLY, 0400)) < 0) |
---|
100 | return (1); |
---|
101 | } else |
---|
102 | fd = 0; |
---|
103 | |
---|
104 | while ((numchars = read(fd, inputbuffer, MAX_BUFFER)) > 0) { |
---|
105 | total_sent = 0; |
---|
106 | |
---|
107 | databuffer = (g_opt.mapflg) ? |
---|
108 | expand_buffer(inputbuffer, numchars, &numchars) : inputbuffer; |
---|
109 | #ifndef SLOWSCO |
---|
110 | /* Perform normal write operation */ |
---|
111 | write_buffer(sock, databuffer, numchars, printer_name, output_dest); |
---|
112 | check_input(sock, output_dest, 0); |
---|
113 | #ifdef SCO |
---|
114 | check_write(sock); |
---|
115 | #endif |
---|
116 | |
---|
117 | #else |
---|
118 | /* |
---|
119 | * write only one byte to avoid any flow control problem |
---|
120 | * which SCO seems to handle pretty badly |
---|
121 | */ |
---|
122 | for (i = 0; i < numchars; i++) { |
---|
123 | check_write(sock); |
---|
124 | write_buffer(sock, &databuffer[i], 1, printer_name, output_dest); |
---|
125 | } |
---|
126 | #endif |
---|
127 | } |
---|
128 | check_input(sock, output_dest, 2); |
---|
129 | if (g_opt.ff_flag) { |
---|
130 | write(sock, &ff, 1); |
---|
131 | act_bytes_sent += 1; |
---|
132 | } |
---|
133 | close(fd); |
---|
134 | return (numchars); |
---|
135 | } |
---|
136 | |
---|
137 | /* |
---|
138 | * write a buffer to the socket sock On blocks it checks to see what error |
---|
139 | * has occurred through both the data channel and udp status All alarms and |
---|
140 | * alarm logic are handled here. Note--the alarm handling routine re-arms the |
---|
141 | * timer alarm |
---|
142 | */ |
---|
143 | |
---|
144 | #ifdef ANSI |
---|
145 | void |
---|
146 | write_buffer(int sock, char *databuffer, int numchars, char *printer_name, int output_dest) |
---|
147 | #else |
---|
148 | void |
---|
149 | write_buffer(sock, databuffer, numchars, printer_name, output_dest) |
---|
150 | int sock; |
---|
151 | char *databuffer; |
---|
152 | int numchars; |
---|
153 | char *printer_name; |
---|
154 | int output_dest; |
---|
155 | #endif |
---|
156 | { |
---|
157 | char error_string[MAXSTRNGLEN]; |
---|
158 | int total_sent = 0; |
---|
159 | int num_sent; |
---|
160 | int orig_total; |
---|
161 | |
---|
162 | #ifndef ESIX |
---|
163 | signal(SIGALRM, to_alarm); |
---|
164 | #endif |
---|
165 | |
---|
166 | #ifdef BSD |
---|
167 | alarm(60); |
---|
168 | #endif |
---|
169 | orig_total = numchars; |
---|
170 | while ((num_sent = write(sock, databuffer + total_sent, numchars)) != numchars) { |
---|
171 | if (errno != EINTR && num_sent < 0) |
---|
172 | error_notify(ERR_WRITE, 0); |
---|
173 | |
---|
174 | if (errno == EINTR) { |
---|
175 | error_string[0] = 0; |
---|
176 | get_printer_status(printer_name, error_string, g_opt.dataport); |
---|
177 | #ifdef BSD |
---|
178 | update_status_file(error_string, status_id, CREATE); |
---|
179 | #endif |
---|
180 | error_notify(ERR_GENERIC, error_string); |
---|
181 | check_input(sock, output_dest, 0); |
---|
182 | continue; |
---|
183 | } |
---|
184 | check_input(sock, output_dest, 0); |
---|
185 | if (num_sent > 0) { |
---|
186 | numchars -= num_sent; |
---|
187 | total_sent += num_sent; |
---|
188 | } |
---|
189 | #ifdef BSD |
---|
190 | if (numchars == 0) { |
---|
191 | break; |
---|
192 | } else |
---|
193 | alarm(10); |
---|
194 | #endif |
---|
195 | } |
---|
196 | #ifdef BSD |
---|
197 | alarm(0); /* turn off the alarm after the write */ |
---|
198 | #endif |
---|
199 | |
---|
200 | /* Update # of characters sent so far */ |
---|
201 | |
---|
202 | act_bytes_sent += orig_total; |
---|
203 | } |
---|
204 | |
---|
205 | |
---|
206 | /* |
---|
207 | * simply checks the read side of sock to see if there is any data to read |
---|
208 | * back and writes it to output_dest |
---|
209 | */ |
---|
210 | |
---|
211 | #ifdef ANSI |
---|
212 | void |
---|
213 | check_input(int sock, int output_dest, int time_out) |
---|
214 | #else |
---|
215 | void |
---|
216 | check_input(sock, output_dest, time_out) |
---|
217 | int sock, output_dest, time_out; |
---|
218 | #endif |
---|
219 | { |
---|
220 | struct timeval timeout; |
---|
221 | fd_set readfd; |
---|
222 | char inchar; |
---|
223 | int num_chars; |
---|
224 | int sel_val; |
---|
225 | char buf[MAX_BUFFER]; |
---|
226 | char error_string[MAXSTRNGLEN]; |
---|
227 | int count = 0; |
---|
228 | |
---|
229 | FD_ZERO(&readfd); |
---|
230 | |
---|
231 | timeout.tv_sec = time_out; |
---|
232 | timeout.tv_usec = 0; |
---|
233 | FD_SET(sock, &readfd); |
---|
234 | while (sel_val = select(sock + 1, &readfd, 0, 0, &timeout)) { |
---|
235 | if (sel_val < 0) |
---|
236 | break; |
---|
237 | if (FD_ISSET(sock, &readfd)) { |
---|
238 | if ((num_chars = read(sock, &inchar, 1)) >= 0) { |
---|
239 | if (count < MAX_BUFFER - 1) |
---|
240 | buf[count++] = inchar; |
---|
241 | else { |
---|
242 | buf[count] = (char) 0; |
---|
243 | error_notify(ERR_GENERIC, buf); |
---|
244 | count = 0; |
---|
245 | } |
---|
246 | } else |
---|
247 | break; |
---|
248 | } |
---|
249 | } |
---|
250 | if (count > 0) { |
---|
251 | buf[count] = (char) 0; |
---|
252 | error_notify(ERR_GENERIC, buf); |
---|
253 | } |
---|
254 | } |
---|
255 | |
---|
256 | #ifdef ANSI |
---|
257 | void |
---|
258 | send_control_d(int sock) |
---|
259 | #else |
---|
260 | void |
---|
261 | send_control_d(sock) |
---|
262 | int sock; |
---|
263 | #endif |
---|
264 | { |
---|
265 | char dchar = 4; /* control-d if a postscript printer */ |
---|
266 | write(sock, &dchar, 1); |
---|
267 | |
---|
268 | /* Keep track of # of chars actually written so far */ |
---|
269 | |
---|
270 | act_bytes_sent += 1; |
---|
271 | } |
---|
272 | |
---|
273 | #ifdef ANSI |
---|
274 | char * |
---|
275 | expand_buffer(char *data, int length, int *retlength) |
---|
276 | #else |
---|
277 | char * |
---|
278 | expand_buffer(data, length, retlength) |
---|
279 | char *data; |
---|
280 | int length; |
---|
281 | int *retlength; |
---|
282 | #endif |
---|
283 | { |
---|
284 | static char return_buff[2 * MAX_BUFFER]; |
---|
285 | int temp, i; |
---|
286 | for (i = 0, temp = 0; i < length; i++) { |
---|
287 | if (data[i] == '\n') { |
---|
288 | return_buff[temp++] = '\r'; |
---|
289 | return_buff[temp++] = '\n'; |
---|
290 | } else { |
---|
291 | return_buff[temp++] = data[i]; |
---|
292 | } |
---|
293 | } |
---|
294 | *retlength = temp; |
---|
295 | return (return_buff); |
---|
296 | } |
---|
297 | |
---|
298 | /* |
---|
299 | * send_banner() we need this since transcript writes a file .banner that we |
---|
300 | * need to write to the printer |
---|
301 | * |
---|
302 | * ADOBE: assume that previous filters will handle BANNERPRO=file and write it |
---|
303 | * to .banner |
---|
304 | */ |
---|
305 | |
---|
306 | #ifdef ANSI |
---|
307 | void |
---|
308 | send_banner(int sock) |
---|
309 | #else |
---|
310 | void |
---|
311 | send_banner(sock) |
---|
312 | int sock; |
---|
313 | #endif |
---|
314 | { |
---|
315 | int bfile; |
---|
316 | char input_b[512]; |
---|
317 | int c_read, total = 0, num_sent = 0; |
---|
318 | |
---|
319 | if ((bfile = open(".banner", O_RDONLY, 0600)) < 0) |
---|
320 | return; |
---|
321 | while ((c_read = read(bfile, input_b, 512)) > 0) { |
---|
322 | act_bytes_sent += c_read; |
---|
323 | while ((num_sent = write(sock, input_b + total, c_read)) |
---|
324 | != c_read) { |
---|
325 | if (num_sent < 0) |
---|
326 | return; |
---|
327 | if (!num_sent) |
---|
328 | return; |
---|
329 | total += num_sent; |
---|
330 | c_read -= num_sent; |
---|
331 | } |
---|
332 | } |
---|
333 | unlink(".banner"); |
---|
334 | } |
---|
335 | |
---|
336 | /* |
---|
337 | * Get the next printer from the linked list of printers and return the |
---|
338 | * printer in first argument. Returns a zero if all OK, else returns -1. |
---|
339 | */ |
---|
340 | |
---|
341 | #ifdef ANSI |
---|
342 | int |
---|
343 | getNextPrinter(hsw_PCONFIG ** current_ptr, struct sockaddr_in * server) |
---|
344 | #else |
---|
345 | int |
---|
346 | getNextPrinter(current_ptr, server) |
---|
347 | hsw_PCONFIG **current_ptr; |
---|
348 | struct sockaddr_in *server; |
---|
349 | #endif |
---|
350 | { |
---|
351 | static int valid_host_name = 0; |
---|
352 | struct hostent *hp; |
---|
353 | if (!*current_ptr) |
---|
354 | *current_ptr = g_opt.prt_list; |
---|
355 | else { |
---|
356 | *current_ptr = (*current_ptr)->next_printer; |
---|
357 | if (!*current_ptr) |
---|
358 | *current_ptr = g_opt.prt_list; |
---|
359 | } |
---|
360 | |
---|
361 | while (*current_ptr) { |
---|
362 | if (hp = gethostbyname((*current_ptr)->printer_name)) { |
---|
363 | valid_host_name++; |
---|
364 | bcopy((char *) hp->h_addr, (char *) &server->sin_addr, hp->h_length); |
---|
365 | server->sin_port = htons((*current_ptr)->ptype); |
---|
366 | return (0); |
---|
367 | } else { |
---|
368 | char error_string[MAXSTRNGLEN]; |
---|
369 | sprintf(error_string, "host name lookup failed for %s", |
---|
370 | (*current_ptr)->printer_name); |
---|
371 | error_notify(ERR_GENERIC, error_string); |
---|
372 | if (!(*current_ptr)->next_printer) { |
---|
373 | if (!valid_host_name) { |
---|
374 | error_notify(ERR_GENERIC, "fpfilter: exit, no valid hosts specified"); |
---|
375 | exit(1); |
---|
376 | } |
---|
377 | } |
---|
378 | } |
---|
379 | *current_ptr = (*current_ptr)->next_printer; |
---|
380 | } |
---|
381 | if (valid_host_name) |
---|
382 | return(1); |
---|
383 | return(-1); |
---|
384 | } |
---|
385 | |
---|
386 | #ifdef ANSI |
---|
387 | main(int argc, char **argv) |
---|
388 | #else |
---|
389 | main(argc, argv) |
---|
390 | int argc; |
---|
391 | char **argv; |
---|
392 | #endif |
---|
393 | { |
---|
394 | struct sockaddr_in server; |
---|
395 | hsw_PCONFIG *current_ptr; /* Current printer */ |
---|
396 | char c, *name, *temp, *cp; |
---|
397 | char *Autoconfig; |
---|
398 | char error_string[MAXSTRNGLEN]; |
---|
399 | int val; |
---|
400 | int counter = 0; |
---|
401 | |
---|
402 | |
---|
403 | /* |
---|
404 | * set to stdout or stderr depending on from where the program is |
---|
405 | * called |
---|
406 | */ |
---|
407 | int output_dest; |
---|
408 | |
---|
409 | int sock, sockops, optval; |
---|
410 | int was_waiting_for_printer = 0; |
---|
411 | int got_status = 0; |
---|
412 | |
---|
413 | |
---|
414 | #ifndef HPOLD |
---|
415 | struct linger linger_struct; |
---|
416 | #else |
---|
417 | int lingerval = 1; |
---|
418 | #endif |
---|
419 | |
---|
420 | #ifdef DEBUG |
---|
421 | if (!access("/tmp/fpdebug", F_OK)) { |
---|
422 | syslog(LOG_ERR, "%s %d\n", argv[0], getpid()); |
---|
423 | pause(); |
---|
424 | } |
---|
425 | #endif |
---|
426 | |
---|
427 | #ifndef ESIX |
---|
428 | #ifdef BSD |
---|
429 | signal(SIGALRM, to_alarm); |
---|
430 | signal(SIGCLD, sig_child); |
---|
431 | #else |
---|
432 | signal(SIGCLD, SIG_IGN); |
---|
433 | sigignore(SIGPIPE); |
---|
434 | #endif |
---|
435 | #endif |
---|
436 | |
---|
437 | setDefaults(&g_opt); |
---|
438 | |
---|
439 | checkForCurrentDir(argc, argv); |
---|
440 | |
---|
441 | hsw_Getprinterconfig(); |
---|
442 | |
---|
443 | #ifdef BSD |
---|
444 | if (g_opt.acctg) |
---|
445 | do_acctg(argv[8]); |
---|
446 | #endif |
---|
447 | |
---|
448 | /* If an error file needs to be opened, do so */ |
---|
449 | if (g_opt.notify_type.file) |
---|
450 | if (!(g_errorLog = fopen(g_opt.notify_type.filename, "a"))) |
---|
451 | g_opt.notify_type.file = 0; |
---|
452 | |
---|
453 | /* override with command line options */ |
---|
454 | output_dest = parseCommandLineArgs(argc, argv); |
---|
455 | |
---|
456 | if (!g_opt.prt_list) { |
---|
457 | char printer_name[MAXNAMELEN]; |
---|
458 | get_printername(printer_name); |
---|
459 | g_opt.prt_list = |
---|
460 | form_printer_list(printer_name, |
---|
461 | g_opt.prt_list, g_opt.dataport, APPEND); |
---|
462 | } |
---|
463 | if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) |
---|
464 | error_notify(ERR_DOMAIN, 0); |
---|
465 | server.sin_family = AF_INET; |
---|
466 | |
---|
467 | current_ptr = 0; |
---|
468 | if (getNextPrinter(¤t_ptr, &server) == -1) |
---|
469 | error_notify(ERR_NORESPONSE, 0); |
---|
470 | g_alarmed = 0; |
---|
471 | for (;;) { /* loop as long as we don't get a fatal error |
---|
472 | * this allows engine errors to be ridden |
---|
473 | * through */ |
---|
474 | char status_message[MAXSTRNGLEN]; |
---|
475 | char temp_printer[MAXSTRNGLEN]; |
---|
476 | int connect_error_sent = 0; |
---|
477 | |
---|
478 | #ifdef BSD |
---|
479 | sprintf(status_message, "printing to %s port on %s\n", |
---|
480 | g_opt.dataport == PARALLEL ? "parallel" : "serial", |
---|
481 | current_ptr->printer_name); |
---|
482 | update_status_file(status_message, status_id++, CREATE); |
---|
483 | #endif |
---|
484 | |
---|
485 | strcpy(temp_printer, current_ptr->printer_name); |
---|
486 | |
---|
487 | #ifdef BSD |
---|
488 | alarm(30); |
---|
489 | #endif |
---|
490 | |
---|
491 | if (connect(sock, (struct sockaddr *) & server, sizeof(server)) < 0) { |
---|
492 | #ifdef BSD |
---|
493 | alarm(0); |
---|
494 | #endif |
---|
495 | close(sock); |
---|
496 | if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) |
---|
497 | error_notify(ERR_DOMAIN, 0); |
---|
498 | |
---|
499 | sprintf(error_string, "Error on connect (errno = %d)\nPrinter Status from Fastport:\n", errno); |
---|
500 | was_waiting_for_printer = 1; |
---|
501 | get_printer_status(current_ptr->printer_name, error_string, g_opt.dataport); |
---|
502 | #ifdef BSD |
---|
503 | update_status_file(error_string, status_id, APPEND); |
---|
504 | #endif |
---|
505 | |
---|
506 | #ifdef BSD |
---|
507 | if (!connect_error_sent) { |
---|
508 | connect_error_sent = 1; |
---|
509 | error_notify(ERR_GENERIC, error_string); |
---|
510 | } |
---|
511 | #else |
---|
512 | if (!connect_error_sent) { |
---|
513 | if (got_printer_error(error_string)) { |
---|
514 | connect_error_sent = 1; |
---|
515 | error_notify(ERR_GENERIC, error_string); |
---|
516 | } |
---|
517 | } |
---|
518 | #endif |
---|
519 | if (getNextPrinter(¤t_ptr, &server) == -1) { |
---|
520 | error_notify(ERR_NORESPONSE,0); |
---|
521 | exit(1); |
---|
522 | } |
---|
523 | } else |
---|
524 | break; |
---|
525 | } |
---|
526 | |
---|
527 | #ifdef BSD |
---|
528 | alarm(0); |
---|
529 | #endif |
---|
530 | |
---|
531 | status_id++; |
---|
532 | #ifdef BSD |
---|
533 | if (was_waiting_for_printer) { |
---|
534 | sprintf(error_string, "printing to %s port on %s\n", g_opt.dataport == PARALLEL ? "parallel" : "serial", |
---|
535 | current_ptr->printer_name); |
---|
536 | update_status_file(error_string, status_id, CREATE); |
---|
537 | } |
---|
538 | #endif |
---|
539 | |
---|
540 | if (g_opt.closewait) { |
---|
541 | /* |
---|
542 | * Now that you have connected to the printer, check the printer |
---|
543 | * status |
---|
544 | */ |
---|
545 | |
---|
546 | if (! get_printer_status(current_ptr->printer_name, error_string, g_opt.dataport)) |
---|
547 | got_status = 0; |
---|
548 | else { |
---|
549 | got_status = 1; |
---|
550 | /* Check the number of bytes written so far on the serial and |
---|
551 | * parallel port */ |
---|
552 | |
---|
553 | if (g_opt.dataport == PARALLEL) |
---|
554 | int_bytes = ntohl(udp_stat.parallel_bytes); /* Initial # of parallel |
---|
555 | * bytes */ |
---|
556 | if (g_opt.dataport == SERIAL) |
---|
557 | int_bytes = ntohl(udp_stat.serial_bytes); /* Initial # of serial |
---|
558 | * bytes */ |
---|
559 | } |
---|
560 | |
---|
561 | } |
---|
562 | |
---|
563 | #ifndef HPOLD |
---|
564 | linger_struct.l_onoff = 1; |
---|
565 | linger_struct.l_linger = LINGERVAL; |
---|
566 | |
---|
567 | #ifndef ATT |
---|
568 | #ifdef __STDC__ |
---|
569 | sockops = setsockopt(sock, SOL_SOCKET, SO_LINGER, |
---|
570 | (const char *)&linger_struct, |
---|
571 | sizeof(linger_struct)); |
---|
572 | #else |
---|
573 | sockops = setsockopt(sock, SOL_SOCKET, SO_LINGER, |
---|
574 | (char *)&linger_struct, |
---|
575 | sizeof(linger_struct)); |
---|
576 | #endif /* __STDC__ */ |
---|
577 | |
---|
578 | if (sockops < 0) |
---|
579 | fprintf(stderr, "setsockopt returned %d \n", sockops); |
---|
580 | #endif |
---|
581 | #else |
---|
582 | sockops = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &lingerval, |
---|
583 | sizeof(lingerval)); |
---|
584 | if (sockops < 0) |
---|
585 | fprintf(stderr, "setsockopt returned %d for keepalive\n", sockops); |
---|
586 | #endif |
---|
587 | |
---|
588 | optval = 1; |
---|
589 | #ifdef __STDC__ |
---|
590 | sockops = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, |
---|
591 | (const char *)&optval, |
---|
592 | sizeof(optval)); |
---|
593 | #else |
---|
594 | sockops = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, |
---|
595 | (char *)&optval, |
---|
596 | sizeof(optval)); |
---|
597 | #endif /* __STDC__ */ |
---|
598 | if (sockops < 0) |
---|
599 | fprintf(stderr, "setsockopt returned %d for keepalive\n", sockops); |
---|
600 | |
---|
601 | if (g_opt.start_string) { |
---|
602 | write(sock, g_opt.start_string, strlen(g_opt.start_string)); |
---|
603 | act_bytes_sent += strlen(g_opt.start_string); |
---|
604 | } |
---|
605 | if (g_opt.send_startfile) |
---|
606 | sendfile(sock, g_opt.start_file, output_dest, 0, current_ptr->printer_name); |
---|
607 | |
---|
608 | /* |
---|
609 | * postscript printers really like control-d's. So, if there was an |
---|
610 | * engine problem this first control d will resync. The last one |
---|
611 | * will leave it that way. |
---|
612 | */ |
---|
613 | if (g_opt.use_control_d) |
---|
614 | send_control_d(sock); |
---|
615 | /* |
---|
616 | * check to see if it should send a banner page |
---|
617 | */ |
---|
618 | if ((g_opt.real_filter || g_opt.dobanner) && g_opt.adobe.banner_first) |
---|
619 | send_banner(sock); |
---|
620 | /* |
---|
621 | * if we have a list of files just send them one at a time |
---|
622 | */ |
---|
623 | if (g_opt.file_list) { |
---|
624 | while (g_opt.file_list) { |
---|
625 | if (sendfile(sock, g_opt.file_list->file_name, |
---|
626 | output_dest, g_opt.check_postscript, current_ptr->printer_name)) |
---|
627 | error_notify(ERR_SNDFILE, 0); |
---|
628 | g_opt.file_list = g_opt.file_list->next; |
---|
629 | } |
---|
630 | if ((g_opt.real_filter || g_opt.dobanner) && g_opt.adobe.banner_last) |
---|
631 | send_banner(sock); |
---|
632 | if (g_opt.send_endfile) |
---|
633 | sendfile(sock, g_opt.end_file, output_dest, 0, current_ptr->printer_name); |
---|
634 | if (g_opt.end_string) { |
---|
635 | write(sock, g_opt.end_string, strlen(g_opt.end_string)); |
---|
636 | act_bytes_sent += strlen(g_opt.end_string); |
---|
637 | } |
---|
638 | if (g_opt.use_control_d) |
---|
639 | send_control_d(sock); |
---|
640 | } else { |
---|
641 | /* |
---|
642 | * Reading from standard input can either be through lpr or |
---|
643 | * just piping into the filter from the shell |
---|
644 | */ |
---|
645 | |
---|
646 | sendfile(sock, "STDIN", output_dest, g_opt.check_postscript, current_ptr->printer_name); |
---|
647 | if ((g_opt.real_filter || g_opt.dobanner) && g_opt.adobe.banner_last) |
---|
648 | send_banner(sock); |
---|
649 | |
---|
650 | if (g_opt.send_endfile) |
---|
651 | sendfile(sock, g_opt.end_file, output_dest, 0, current_ptr->printer_name); |
---|
652 | |
---|
653 | |
---|
654 | if (g_opt.end_string) { |
---|
655 | write(sock, g_opt.end_string, strlen(g_opt.end_string)); |
---|
656 | act_bytes_sent += strlen(g_opt.end_string); |
---|
657 | } |
---|
658 | if (g_opt.use_control_d) |
---|
659 | send_control_d(sock); |
---|
660 | } |
---|
661 | |
---|
662 | /* Now that you have finished printing, check the status again */ |
---|
663 | |
---|
664 | if (g_opt.closewait) { |
---|
665 | int sent_status = 0; |
---|
666 | if (! got_status ) { |
---|
667 | sleep(10); |
---|
668 | } else |
---|
669 | do { |
---|
670 | error_string[0] = 0; |
---|
671 | get_printer_status(current_ptr->printer_name, error_string, g_opt.dataport); |
---|
672 | if (counter > 0) { |
---|
673 | if ((! sent_status) && (g_opt.dataport == PARALLEL) ) { |
---|
674 | sent_status = 1; |
---|
675 | if (got_printer_error(error_string)) { |
---|
676 | error_notify(ERR_GENERIC, error_string); |
---|
677 | } |
---|
678 | } |
---|
679 | check_input(sock, output_dest, 0); |
---|
680 | sleep(1); |
---|
681 | } |
---|
682 | |
---|
683 | /* |
---|
684 | * Check the number of bytes written so far on the |
---|
685 | * serial and parallel port |
---|
686 | */ |
---|
687 | if (g_opt.dataport == PARALLEL) |
---|
688 | fin_bytes = ntohl(udp_stat.parallel_bytes); /* Final # of par bytes */ |
---|
689 | if (g_opt.dataport == SERIAL) |
---|
690 | fin_bytes = ntohl(udp_stat.serial_bytes); |
---|
691 | counter++; |
---|
692 | } |
---|
693 | while ((fin_bytes < (int_bytes + act_bytes_sent)) && (counter < 60)); |
---|
694 | |
---|
695 | } |
---|
696 | close(sock); |
---|
697 | if (g_opt.use_printer_classes) { |
---|
698 | char message[MAXSTRNGLEN]; |
---|
699 | sprintf(message, "The file was printed on %s \n", current_ptr->printer_name); |
---|
700 | error_notify(ERR_GENERIC, message); |
---|
701 | } |
---|
702 | if (g_errorLog) |
---|
703 | fclose(g_errorLog); |
---|
704 | exit(0); |
---|
705 | } |
---|
706 | |
---|
707 | #ifdef BSD |
---|
708 | void |
---|
709 | #ifdef ANSI |
---|
710 | update_status_file(char *message, int status_num, int style) |
---|
711 | #else |
---|
712 | update_status_file(message, status_num, style) |
---|
713 | char *message; |
---|
714 | int status_num; |
---|
715 | int style; |
---|
716 | #endif |
---|
717 | { |
---|
718 | int sf; |
---|
719 | static int last_id = -1; |
---|
720 | |
---|
721 | if (style == APPEND) |
---|
722 | style = O_APPEND; |
---|
723 | else |
---|
724 | style = 0; |
---|
725 | |
---|
726 | if ((sf = open("./status", O_RDWR | style, 0600)) >= 0) { |
---|
727 | if (style == CREATE) |
---|
728 | ftruncate(sf, 0); |
---|
729 | write(sf, message, strlen(message)); |
---|
730 | close(sf); |
---|
731 | } else { |
---|
732 | if (status_num != last_id) { |
---|
733 | error_notify(ERR_GENERIC, message); |
---|
734 | last_id = status_id; |
---|
735 | } |
---|
736 | } |
---|
737 | } |
---|
738 | |
---|
739 | #endif |
---|
740 | |
---|
741 | |
---|
742 | #ifdef SCO |
---|
743 | |
---|
744 | void |
---|
745 | check_write(sock) |
---|
746 | int sock; |
---|
747 | { |
---|
748 | |
---|
749 | struct timeval timeout; |
---|
750 | fd_set writefd; |
---|
751 | int sel_val; |
---|
752 | struct pollfd pollfds[20]; |
---|
753 | int i; |
---|
754 | |
---|
755 | for (i = 0; i < 20; i++) |
---|
756 | pollfds[i].events = 0; |
---|
757 | |
---|
758 | pollfds[sock].events = POLLOUT; |
---|
759 | pollfds[sock].fd = sock; |
---|
760 | |
---|
761 | while (1) { |
---|
762 | if (poll(pollfds, 20, -1) < 0) { |
---|
763 | perror("Poll failed"); |
---|
764 | exit(1); |
---|
765 | } |
---|
766 | if (pollfds[sock].revents == POLLOUT) |
---|
767 | return; |
---|
768 | } |
---|
769 | } |
---|
770 | |
---|
771 | #endif |
---|
772 | |
---|
773 | int |
---|
774 | #ifdef ANSI |
---|
775 | got_printer_error(char *error_string) |
---|
776 | #else |
---|
777 | got_printer_error(error_string) |
---|
778 | char *error_string; |
---|
779 | #endif |
---|
780 | { |
---|
781 | char *c_ptr; |
---|
782 | if (is_substring("OFFLINE", error_string)) |
---|
783 | return (1); |
---|
784 | if (is_substring("FAULT", error_string)) |
---|
785 | return (1); |
---|
786 | if (is_substring("PAPER", error_string)) |
---|
787 | return (1); |
---|
788 | return (0); |
---|
789 | } |
---|
790 | |
---|
791 | int |
---|
792 | #ifdef ANSI |
---|
793 | is_substring(char *sub, char *src) |
---|
794 | #else |
---|
795 | is_substring(sub, src) |
---|
796 | char *sub, *src; |
---|
797 | #endif |
---|
798 | { |
---|
799 | while (*src) { |
---|
800 | if (!strncmp(src, sub, strlen(sub))) |
---|
801 | return (1); |
---|
802 | src++; |
---|
803 | } |
---|
804 | return (0); |
---|
805 | } |
---|
806 | |
---|
807 | /* |
---|
808 | * This routine performs accounting. Here we look at the '.banner' file |
---|
809 | * generated by the output filter in the spool directory and append the |
---|
810 | * contents of this file to the accounting file whose name and path are |
---|
811 | * passed as the 8th argument to the filter program. This SHOULD be used only |
---|
812 | * when you are printing through 'lpr' command and only on BSD systems. |
---|
813 | */ |
---|
814 | |
---|
815 | #ifdef BSD |
---|
816 | void |
---|
817 | do_acctg(file) |
---|
818 | char *file; |
---|
819 | { |
---|
820 | FILE *acctg, *banner; |
---|
821 | char *str; |
---|
822 | |
---|
823 | str = (char *) malloc(80); |
---|
824 | |
---|
825 | if ((acctg = fopen(file, "a")) == NULL) { |
---|
826 | error_notify(ERR_GENERIC, "can not open accounting file"); |
---|
827 | return; |
---|
828 | } |
---|
829 | if ((banner = fopen("./.acct", "r")) == NULL){ |
---|
830 | error_notify(ERR_GENERIC, "can not perform accounting !"); |
---|
831 | return; |
---|
832 | } |
---|
833 | fgets(str, 80, banner); |
---|
834 | fputs(str, acctg); |
---|
835 | fclose(banner); |
---|
836 | fclose(acctg); |
---|
837 | } |
---|
838 | #endif |
---|