[9089] | 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 |
---|