1*14f51593SDavid du Colombier #define _BSD_EXTENSION
2*14f51593SDavid du Colombier #define _NET_EXTENSION
3*14f51593SDavid du Colombier #define _POSIX_SOURCE
4*14f51593SDavid du Colombier
57dd7cddfSDavid du Colombier #include <stdio.h>
67dd7cddfSDavid du Colombier #include <stdlib.h>
7*14f51593SDavid du Colombier #include <unistd.h>
8*14f51593SDavid du Colombier #include <fcntl.h>
97dd7cddfSDavid du Colombier #include <string.h>
10*14f51593SDavid du Colombier #include <ctype.h>
117dd7cddfSDavid du Colombier #include <signal.h>
127dd7cddfSDavid du Colombier #include <errno.h>
13*14f51593SDavid du Colombier #include <select.h>
147dd7cddfSDavid du Colombier #include <sys/types.h>
157dd7cddfSDavid du Colombier #include <sys/time.h>
167dd7cddfSDavid du Colombier #include <sys/socket.h>
17*14f51593SDavid du Colombier #include <sys/wait.h>
187dd7cddfSDavid du Colombier
197dd7cddfSDavid du Colombier extern int dial_debug;
207dd7cddfSDavid du Colombier extern int dial(char*, char*, char*, int*);
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier /* debug = 0 for no debugging */
247dd7cddfSDavid du Colombier /* debug = 1 for readprinter debugging */
257dd7cddfSDavid du Colombier /* debug = 2 for sendprinter debugging */
267dd7cddfSDavid du Colombier /* debug = 3 for full debugging, its hard to read the messages */
277dd7cddfSDavid du Colombier
287dd7cddfSDavid du Colombier int debug = 0;
297dd7cddfSDavid du Colombier #define READTIMEOUT 300
307dd7cddfSDavid du Colombier #define RCVSELTIMEOUT 30
317dd7cddfSDavid du Colombier #define SNDSELTIMEOUT 300
327dd7cddfSDavid du Colombier
337dd7cddfSDavid du Colombier void
rdtmout(void)347dd7cddfSDavid du Colombier rdtmout(void) {
357dd7cddfSDavid du Colombier fprintf(stderr, "read timeout occurred, check printer\n");
367dd7cddfSDavid du Colombier }
377dd7cddfSDavid du Colombier
387dd7cddfSDavid du Colombier int
getline(int fd,char * buf,int len)397dd7cddfSDavid du Colombier getline(int fd, char *buf, int len) {
407dd7cddfSDavid du Colombier char *bp, c;
417dd7cddfSDavid du Colombier int i = 0, n;
427dd7cddfSDavid du Colombier
437dd7cddfSDavid du Colombier bp = buf;
447dd7cddfSDavid du Colombier while (alarm(READTIMEOUT),(n=read(fd, bp, 1)) == 1) {
457dd7cddfSDavid du Colombier alarm(0);
467dd7cddfSDavid du Colombier if (*bp == '\r') continue;
477dd7cddfSDavid du Colombier i += n;
487dd7cddfSDavid du Colombier
497dd7cddfSDavid du Colombier c = *bp++;
507dd7cddfSDavid du Colombier if (c == '\n' || c == '\004' || i >= len-1)
517dd7cddfSDavid du Colombier break;
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier alarm(0);
547dd7cddfSDavid du Colombier if (n < 0)
557dd7cddfSDavid du Colombier return(n);
567dd7cddfSDavid du Colombier *bp = '\0';
577dd7cddfSDavid du Colombier return(i);
587dd7cddfSDavid du Colombier }
597dd7cddfSDavid du Colombier
607dd7cddfSDavid du Colombier typedef struct {
617dd7cddfSDavid du Colombier char *state; /* printer's current status */
627dd7cddfSDavid du Colombier int val; /* value returned by getstatus() */
637dd7cddfSDavid du Colombier } Status;
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier /* printer states */
667dd7cddfSDavid du Colombier #define INITIALIZING 0
677dd7cddfSDavid du Colombier #define IDLE 1
687dd7cddfSDavid du Colombier #define BUSY 2
697dd7cddfSDavid du Colombier #define WAITING 3
707dd7cddfSDavid du Colombier #define PRINTING 4
717dd7cddfSDavid du Colombier #define PRINTERERROR 5
727dd7cddfSDavid du Colombier #define ERROR 6
737dd7cddfSDavid du Colombier #define FLUSHING 7
747dd7cddfSDavid du Colombier #define UNKNOWN 8
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier /* protocol requests and program states */
777dd7cddfSDavid du Colombier #define START 'S'
787dd7cddfSDavid du Colombier unsigned char Start[] = { START };
797dd7cddfSDavid du Colombier #define ID_LE 'L'
807dd7cddfSDavid du Colombier unsigned char Id_le[] = { ID_LE };
817dd7cddfSDavid du Colombier #define REQ_STAT 'T'
827dd7cddfSDavid du Colombier unsigned char Req_stat[] = { REQ_STAT };
837dd7cddfSDavid du Colombier #define SEND_DATA 'D'
847dd7cddfSDavid du Colombier unsigned char Send_data[] = { SEND_DATA };
857dd7cddfSDavid du Colombier #define SENT_DATA 'A'
867dd7cddfSDavid du Colombier unsigned char Sent_data[] = { SENT_DATA };
877dd7cddfSDavid du Colombier #define WAIT_FOR_EOJ 'W'
887dd7cddfSDavid du Colombier unsigned char Wait_for_eoj[] = { WAIT_FOR_EOJ };
897dd7cddfSDavid du Colombier #define END_OF_JOB 'E'
907dd7cddfSDavid du Colombier unsigned char End_of_job[] = { END_OF_JOB };
917dd7cddfSDavid du Colombier #define FATAL_ERROR 'F'
927dd7cddfSDavid du Colombier unsigned char Fatal_error[] = { FATAL_ERROR };
937dd7cddfSDavid du Colombier #define WAIT_FOR_IDLE 'I'
947dd7cddfSDavid du Colombier unsigned char Wait_for_idle[] = { WAIT_FOR_IDLE };
957dd7cddfSDavid du Colombier #define OVER_AND_OUT 'O'
967dd7cddfSDavid du Colombier unsigned char Over_and_out[] = { OVER_AND_OUT };
977dd7cddfSDavid du Colombier
987dd7cddfSDavid du Colombier Status statuslist[] = {
997dd7cddfSDavid du Colombier "initializing", INITIALIZING,
1007dd7cddfSDavid du Colombier "idle", IDLE,
1017dd7cddfSDavid du Colombier "busy", BUSY,
1027dd7cddfSDavid du Colombier "waiting", WAITING,
1037dd7cddfSDavid du Colombier "printing", PRINTING,
1047dd7cddfSDavid du Colombier "printererror", PRINTERERROR,
1057dd7cddfSDavid du Colombier "Error", ERROR,
1067dd7cddfSDavid du Colombier "flushing", FLUSHING,
1077dd7cddfSDavid du Colombier NULL, UNKNOWN
1087dd7cddfSDavid du Colombier };
1097dd7cddfSDavid du Colombier
1107dd7cddfSDavid du Colombier
1117dd7cddfSDavid du Colombier /* find returns a pointer to the location of string str2 in string str1,
1127dd7cddfSDavid du Colombier * if it exists. Otherwise, it points to the end of str1.
1137dd7cddfSDavid du Colombier */
1147dd7cddfSDavid du Colombier char *
find(char * str1,char * str2)1157dd7cddfSDavid du Colombier find(char *str1, char *str2) {
1167dd7cddfSDavid du Colombier char *s1, *s2;
1177dd7cddfSDavid du Colombier
1187dd7cddfSDavid du Colombier for (; *str1!='\0'; str1++) {
1197dd7cddfSDavid du Colombier for (s1=str1,s2=str2; *s2!='\0'&&*s1==*s2; s1++,s2++) ;
1207dd7cddfSDavid du Colombier if ( *s2 == '\0' )
1217dd7cddfSDavid du Colombier break;
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier return(str1);
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier
1277dd7cddfSDavid du Colombier #define MESGSIZE 16384
1287dd7cddfSDavid du Colombier int blocksize = 1920; /* 19200/10, with 1 sec delay between transfers
1297dd7cddfSDavid du Colombier * this keeps the queues from building up.
1307dd7cddfSDavid du Colombier */
1317dd7cddfSDavid du Colombier char mesg[MESGSIZE]; /* exactly what came back on ttyi */
1327dd7cddfSDavid du Colombier
1337dd7cddfSDavid du Colombier int
parsmesg(char * buf)1347dd7cddfSDavid du Colombier parsmesg(char *buf) {
1357dd7cddfSDavid du Colombier static char sbuf[MESGSIZE];
1367dd7cddfSDavid du Colombier char *s; /* start of printer messsage in mesg[] */
1377dd7cddfSDavid du Colombier char *e; /* end of printer message in mesg[] */
1387dd7cddfSDavid du Colombier char *key, *val; /* keyword/value strings in sbuf[] */
1397dd7cddfSDavid du Colombier char *p; /* for converting to lower case etc. */
1407dd7cddfSDavid du Colombier int i; /* where *key was found in statuslist[] */
1417dd7cddfSDavid du Colombier
1427dd7cddfSDavid du Colombier if (*(s=find(buf, "%[ "))!='\0' && *(e=find(s, " ]%"))!='\0') {
1437dd7cddfSDavid du Colombier strcpy(sbuf, s+3); /* don't change mesg[] */
1447dd7cddfSDavid du Colombier sbuf[e-(s+3)] = '\0'; /* ignore the trailing " ]%" */
1457dd7cddfSDavid du Colombier
1467dd7cddfSDavid du Colombier for (key=strtok(sbuf, " :"); key != NULL; key=strtok(NULL, " :")) {
1477dd7cddfSDavid du Colombier if (strcmp(key, "Error") == 0)
1487dd7cddfSDavid du Colombier return(ERROR);
1497dd7cddfSDavid du Colombier if ((val=strtok(NULL, ";")) != NULL && strcmp(key, "status") == 0)
1507dd7cddfSDavid du Colombier key = val;
1517dd7cddfSDavid du Colombier
1527dd7cddfSDavid du Colombier for (; *key == ' '; key++) ; /* skip any leading spaces */
1537dd7cddfSDavid du Colombier for (p = key; *p; p++) /* convert to lower case */
1547dd7cddfSDavid du Colombier if (*p == ':') {
1557dd7cddfSDavid du Colombier *p = '\0';
1567dd7cddfSDavid du Colombier break;
1577dd7cddfSDavid du Colombier } else if (isupper(*p)) *p = tolower(*p);
1587dd7cddfSDavid du Colombier
1597dd7cddfSDavid du Colombier for (i=0; statuslist[i].state != NULL; i++) {
1607dd7cddfSDavid du Colombier if (strcmp(statuslist[i].state, key) == 0)
1617dd7cddfSDavid du Colombier return(statuslist[i].val);
1627dd7cddfSDavid du Colombier }
1637dd7cddfSDavid du Colombier }
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier return(UNKNOWN);
1667dd7cddfSDavid du Colombier }
1677dd7cddfSDavid du Colombier
1687dd7cddfSDavid du Colombier char buf[MESGSIZE];
1697dd7cddfSDavid du Colombier fd_set readfds, writefds, exceptfds;
1707dd7cddfSDavid du Colombier struct timeval rcvtimeout = { RCVSELTIMEOUT, 0 };
1717dd7cddfSDavid du Colombier struct timeval sndtimeout = { SNDSELTIMEOUT, 0 };
1727dd7cddfSDavid du Colombier
1737dd7cddfSDavid du Colombier int
readprinter(int printerfd,int pipefd)1747dd7cddfSDavid du Colombier readprinter(int printerfd, int pipefd)
1757dd7cddfSDavid du Colombier {
1767dd7cddfSDavid du Colombier unsigned char proto;
1777dd7cddfSDavid du Colombier int progstate = START;
1787dd7cddfSDavid du Colombier int print_wait_msg = 0;
1797dd7cddfSDavid du Colombier int tocount = 0;
1807dd7cddfSDavid du Colombier int c, printstat, lastprintstat, n, nfds;
1817dd7cddfSDavid du Colombier
1827dd7cddfSDavid du Colombier
1837dd7cddfSDavid du Colombier nfds = ((pipefd>printerfd)?pipefd:printerfd) + 1;
1847dd7cddfSDavid du Colombier printstat = 0;
1857dd7cddfSDavid du Colombier signal(SIGALRM, rdtmout);
1867dd7cddfSDavid du Colombier do {
1877dd7cddfSDavid du Colombier
1887dd7cddfSDavid du Colombier reselect:
1897dd7cddfSDavid du Colombier /* ask sending process to request printer status */
1907dd7cddfSDavid du Colombier if (write(pipefd, Req_stat, 1) != 1) {
1917dd7cddfSDavid du Colombier fprintf(stderr, "request status failed\n");
1927dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
1937dd7cddfSDavid du Colombier continue;
1947dd7cddfSDavid du Colombier }
1957dd7cddfSDavid du Colombier FD_ZERO(&readfds); /* lets be anal */
1967dd7cddfSDavid du Colombier FD_SET(printerfd, &readfds);
1977dd7cddfSDavid du Colombier FD_SET(pipefd, &readfds);
1987dd7cddfSDavid du Colombier FD_ZERO(&exceptfds);
1997dd7cddfSDavid du Colombier FD_SET(printerfd, &exceptfds);
2007dd7cddfSDavid du Colombier FD_SET(pipefd, &exceptfds);
2017dd7cddfSDavid du Colombier n = select(nfds, &readfds, (fd_set *)0, &exceptfds, &rcvtimeout);
2027dd7cddfSDavid du Colombier if (debug&0x1) fprintf(stderr, "readprinter select returned %d\n", n);
2037dd7cddfSDavid du Colombier if (n == 0) {
2047dd7cddfSDavid du Colombier /* a timeout occurred */
2057dd7cddfSDavid du Colombier if (++tocount > 4) {
2067dd7cddfSDavid du Colombier fprintf(stderr, "printer appears to be offline.\nHP4m printers may be out of paper.\n");
2077dd7cddfSDavid du Colombier tocount = 0;
2087dd7cddfSDavid du Colombier }
2097dd7cddfSDavid du Colombier goto reselect;
2107dd7cddfSDavid du Colombier }
2117dd7cddfSDavid du Colombier if (n > 0 && FD_ISSET(printerfd, &exceptfds)) {
2127dd7cddfSDavid du Colombier /* printer problem */
2137dd7cddfSDavid du Colombier fprintf(stderr, "printer exception\n");
2147dd7cddfSDavid du Colombier if (write(pipefd, Fatal_error, 1) != 1) {
2157dd7cddfSDavid du Colombier fprintf(stderr, "'fatal error' write to pipe failed\n");
2167dd7cddfSDavid du Colombier }
2177dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
2187dd7cddfSDavid du Colombier continue;
2197dd7cddfSDavid du Colombier }
2207dd7cddfSDavid du Colombier if (n > 0 && FD_ISSET(pipefd, &exceptfds)) {
2217dd7cddfSDavid du Colombier /* pipe problem */
2227dd7cddfSDavid du Colombier fprintf(stderr, "pipe exception\n");
2237dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
2247dd7cddfSDavid du Colombier continue;
2257dd7cddfSDavid du Colombier }
2267dd7cddfSDavid du Colombier if (n > 0 && FD_ISSET(pipefd, &readfds)) {
2277dd7cddfSDavid du Colombier /* protocol pipe wants to be read */
2287dd7cddfSDavid du Colombier if (debug&0x1) fprintf(stderr, "pipe wants to be read\n");
2297dd7cddfSDavid du Colombier if (read(pipefd, &proto, 1) != 1) {
2307dd7cddfSDavid du Colombier fprintf(stderr, "read protocol pipe failed\n");
2317dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
2327dd7cddfSDavid du Colombier continue;
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier if (debug&0x1) fprintf(stderr, "readprinter: proto=%c\n", proto);
2357dd7cddfSDavid du Colombier /* change state? */
2367dd7cddfSDavid du Colombier switch (proto) {
2377dd7cddfSDavid du Colombier case SENT_DATA:
2387dd7cddfSDavid du Colombier break;
2397dd7cddfSDavid du Colombier case WAIT_FOR_EOJ:
2407dd7cddfSDavid du Colombier if (!print_wait_msg) {
2417dd7cddfSDavid du Colombier print_wait_msg = 1;
2427dd7cddfSDavid du Colombier fprintf(stderr, "waiting for end of job\n");
2437dd7cddfSDavid du Colombier }
2447dd7cddfSDavid du Colombier progstate = proto;
2457dd7cddfSDavid du Colombier break;
2467dd7cddfSDavid du Colombier default:
2477dd7cddfSDavid du Colombier fprintf(stderr, "received unknown protocol request <%c> from sendfile\n", proto);
2487dd7cddfSDavid du Colombier break;
2497dd7cddfSDavid du Colombier }
2507dd7cddfSDavid du Colombier n--;
2517dd7cddfSDavid du Colombier }
2527dd7cddfSDavid du Colombier if (n > 0 && FD_ISSET(printerfd, &readfds)) {
2537dd7cddfSDavid du Colombier /* printer wants to be read */
2547dd7cddfSDavid du Colombier if (debug&0x1) fprintf(stderr, "printer wants to be read\n");
2557dd7cddfSDavid du Colombier if ((c=getline(printerfd, buf, MESGSIZE)) < 0) {
2567dd7cddfSDavid du Colombier fprintf(stderr, "read printer failed\n");
2577dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
2587dd7cddfSDavid du Colombier continue;
2597dd7cddfSDavid du Colombier }
2607dd7cddfSDavid du Colombier if (debug&0x1) fprintf(stderr, "%s\n", buf);
2617dd7cddfSDavid du Colombier if (c==1 && *buf == '\004') {
2627dd7cddfSDavid du Colombier if (progstate == WAIT_FOR_EOJ) {
2637dd7cddfSDavid du Colombier if (debug&0x1) fprintf(stderr, "progstate=%c, ", progstate);
2647dd7cddfSDavid du Colombier fprintf(stderr, "%%[ status: endofjob ]%%\n");
2657dd7cddfSDavid du Colombier /* progstate = WAIT_FOR_IDLE; */
2667dd7cddfSDavid du Colombier progstate = OVER_AND_OUT;
2677dd7cddfSDavid du Colombier if (write(pipefd, Over_and_out, 1) != 1) {
2687dd7cddfSDavid du Colombier fprintf(stderr, "'fatal error' write to pipe failed\n");
2697dd7cddfSDavid du Colombier }
2707dd7cddfSDavid du Colombier continue;
2717dd7cddfSDavid du Colombier } else {
2727dd7cddfSDavid du Colombier if (printstat == ERROR) {
2737dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
2747dd7cddfSDavid du Colombier continue;
2757dd7cddfSDavid du Colombier }
2767dd7cddfSDavid du Colombier if (progstate != START && progstate != WAIT_FOR_IDLE)
2777dd7cddfSDavid du Colombier fprintf(stderr, "warning: EOF received; program status is '%c'\n", progstate);
2787dd7cddfSDavid du Colombier
2797dd7cddfSDavid du Colombier }
2807dd7cddfSDavid du Colombier continue;
2817dd7cddfSDavid du Colombier }
2827dd7cddfSDavid du Colombier
2837dd7cddfSDavid du Colombier /* figure out if it was a status line */
2847dd7cddfSDavid du Colombier lastprintstat = printstat;
2857dd7cddfSDavid du Colombier printstat = parsmesg(buf);
2867dd7cddfSDavid du Colombier if (printstat == UNKNOWN || printstat == ERROR
2877dd7cddfSDavid du Colombier || lastprintstat != printstat) {
2887dd7cddfSDavid du Colombier /* print whatever it is that was read */
2897dd7cddfSDavid du Colombier fprintf(stderr, buf);
2907dd7cddfSDavid du Colombier fflush(stderr);
2917dd7cddfSDavid du Colombier if (printstat == UNKNOWN) {
2927dd7cddfSDavid du Colombier printstat = lastprintstat;
2937dd7cddfSDavid du Colombier continue;
2947dd7cddfSDavid du Colombier }
2957dd7cddfSDavid du Colombier }
2967dd7cddfSDavid du Colombier switch (printstat) {
2977dd7cddfSDavid du Colombier case UNKNOWN:
2987dd7cddfSDavid du Colombier continue; /* shouldn't get here */
2997dd7cddfSDavid du Colombier case FLUSHING:
3007dd7cddfSDavid du Colombier case ERROR:
3017dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
3027dd7cddfSDavid du Colombier /* ask sending process to die */
3037dd7cddfSDavid du Colombier if (write(pipefd, Fatal_error, 1) != 1) {
3047dd7cddfSDavid du Colombier fprintf(stderr, "Fatal_error mesg write to pipe failed\n");
3057dd7cddfSDavid du Colombier }
3067dd7cddfSDavid du Colombier continue;
3077dd7cddfSDavid du Colombier case INITIALIZING:
3087dd7cddfSDavid du Colombier case PRINTERERROR:
3097dd7cddfSDavid du Colombier sleep(1);
3107dd7cddfSDavid du Colombier break;
3117dd7cddfSDavid du Colombier case IDLE:
3127dd7cddfSDavid du Colombier if (progstate == WAIT_FOR_IDLE) {
3137dd7cddfSDavid du Colombier progstate = OVER_AND_OUT;
3147dd7cddfSDavid du Colombier if (write(pipefd, Over_and_out, 1) != 1) {
3157dd7cddfSDavid du Colombier fprintf(stderr, "'fatal error' write to pipe failed\n");
3167dd7cddfSDavid du Colombier }
3177dd7cddfSDavid du Colombier continue;
3187dd7cddfSDavid du Colombier }
3197dd7cddfSDavid du Colombier progstate = SEND_DATA;
3207dd7cddfSDavid du Colombier
3217dd7cddfSDavid du Colombier goto dowait;
3227dd7cddfSDavid du Colombier case BUSY:
3237dd7cddfSDavid du Colombier case WAITING:
3247dd7cddfSDavid du Colombier default:
3257dd7cddfSDavid du Colombier sleep(1);
3267dd7cddfSDavid du Colombier dowait:
3277dd7cddfSDavid du Colombier switch (progstate) {
3287dd7cddfSDavid du Colombier case WAIT_FOR_IDLE:
3297dd7cddfSDavid du Colombier case WAIT_FOR_EOJ:
3307dd7cddfSDavid du Colombier case START:
3317dd7cddfSDavid du Colombier sleep(5);
3327dd7cddfSDavid du Colombier break;
3337dd7cddfSDavid du Colombier
3347dd7cddfSDavid du Colombier case SEND_DATA:
3357dd7cddfSDavid du Colombier if (write(pipefd, Send_data, 1) != 1) {
3367dd7cddfSDavid du Colombier fprintf(stderr, "send data write to pipe failed\n");
3377dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
3387dd7cddfSDavid du Colombier continue;
3397dd7cddfSDavid du Colombier }
3407dd7cddfSDavid du Colombier break;
3417dd7cddfSDavid du Colombier default:
3427dd7cddfSDavid du Colombier fprintf(stderr, "unexpected program state %c\n", progstate);
3437dd7cddfSDavid du Colombier exit(1);
3447dd7cddfSDavid du Colombier }
3457dd7cddfSDavid du Colombier break;
3467dd7cddfSDavid du Colombier }
3477dd7cddfSDavid du Colombier n--;
3487dd7cddfSDavid du Colombier }
3497dd7cddfSDavid du Colombier if (n > 0) {
3507dd7cddfSDavid du Colombier fprintf(stderr, "more fds selected than requested!\n");
3517dd7cddfSDavid du Colombier exit(1);
3527dd7cddfSDavid du Colombier };
3537dd7cddfSDavid du Colombier } while ((progstate != FATAL_ERROR) && (progstate != OVER_AND_OUT));
3547dd7cddfSDavid du Colombier
3557dd7cddfSDavid du Colombier if (progstate == FATAL_ERROR)
3567dd7cddfSDavid du Colombier return(1);
3577dd7cddfSDavid du Colombier else
3587dd7cddfSDavid du Colombier return(0);
3597dd7cddfSDavid du Colombier }
3607dd7cddfSDavid du Colombier
3617dd7cddfSDavid du Colombier int
sendfile(int infd,int printerfd,int pipefd)3627dd7cddfSDavid du Colombier sendfile(int infd, int printerfd, int pipefd)
3637dd7cddfSDavid du Colombier {
3647dd7cddfSDavid du Colombier unsigned char proto;
3657dd7cddfSDavid du Colombier int progstate = START;
3667dd7cddfSDavid du Colombier int i, n, nfds;
3677dd7cddfSDavid du Colombier int bytesread, bytesent = 0;
3687dd7cddfSDavid du Colombier
3697dd7cddfSDavid du Colombier nfds = ((pipefd>printerfd)?pipefd:printerfd) + 1;
3707dd7cddfSDavid du Colombier
3717dd7cddfSDavid du Colombier if (write(printerfd, "\004", 1)!=1) {
3727dd7cddfSDavid du Colombier perror("sendfile:write:");
3737dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
3747dd7cddfSDavid du Colombier }
3757dd7cddfSDavid du Colombier do {
3767dd7cddfSDavid du Colombier FD_ZERO(&readfds); /* lets be anal */
3777dd7cddfSDavid du Colombier FD_SET(pipefd, &readfds);
3787dd7cddfSDavid du Colombier n = select(nfds, &readfds, (fd_set *)0, (fd_set *)0, &sndtimeout);
3797dd7cddfSDavid du Colombier if (debug&02) fprintf(stderr, "sendfile select returned %d\n", n);
3807dd7cddfSDavid du Colombier if (n > 0 && FD_ISSET(pipefd, &readfds)) {
3817dd7cddfSDavid du Colombier /* protocol pipe wants to be read */
3827dd7cddfSDavid du Colombier if (read(pipefd, &proto, 1) != 1) {
3837dd7cddfSDavid du Colombier fprintf(stderr, "read protocol pipe failed\n");
3847dd7cddfSDavid du Colombier return(1);
3857dd7cddfSDavid du Colombier }
3867dd7cddfSDavid du Colombier /* change state? */
3877dd7cddfSDavid du Colombier if (debug&02) fprintf(stderr, "sendfile command - <%c>\n", proto);
3887dd7cddfSDavid du Colombier switch (proto) {
3897dd7cddfSDavid du Colombier case OVER_AND_OUT:
3907dd7cddfSDavid du Colombier case END_OF_JOB:
3917dd7cddfSDavid du Colombier progstate = proto;
3927dd7cddfSDavid du Colombier break;
3937dd7cddfSDavid du Colombier case SEND_DATA:
3947dd7cddfSDavid du Colombier bytesread = 0;
3957dd7cddfSDavid du Colombier do {
3967dd7cddfSDavid du Colombier i = read(infd, &buf[bytesread], blocksize-bytesread);
3977dd7cddfSDavid du Colombier if (debug&02) fprintf(stderr, "read %d bytes\n", i);
3987dd7cddfSDavid du Colombier if (i > 0)
3997dd7cddfSDavid du Colombier bytesread += i;
4007dd7cddfSDavid du Colombier } while((i > 0) && (bytesread < blocksize));
4017dd7cddfSDavid du Colombier if (i < 0) {
4027dd7cddfSDavid du Colombier fprintf(stderr, "input file read error\n");
4037dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
4047dd7cddfSDavid du Colombier break; /* from switch */
4057dd7cddfSDavid du Colombier }
4067dd7cddfSDavid du Colombier if (bytesread > 0) {
4077dd7cddfSDavid du Colombier if (debug&02) fprintf(stderr, "writing %d bytes\n", bytesread);
4087dd7cddfSDavid du Colombier if (write(printerfd, buf, bytesread)!=bytesread) {
4097dd7cddfSDavid du Colombier perror("sendfile:write:");
4107dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
4117dd7cddfSDavid du Colombier } else if (write(pipefd, Sent_data, 1)!=1) {
4127dd7cddfSDavid du Colombier perror("sendfile:write:");
4137dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
4147dd7cddfSDavid du Colombier } else {
4157dd7cddfSDavid du Colombier bytesent += bytesread;
4167dd7cddfSDavid du Colombier }
4177dd7cddfSDavid du Colombier fprintf(stderr, "%d sent\n", bytesent);
4187dd7cddfSDavid du Colombier fflush(stderr);
4197dd7cddfSDavid du Colombier
4207dd7cddfSDavid du Colombier /* we have reached the end of the input file */
4217dd7cddfSDavid du Colombier }
4227dd7cddfSDavid du Colombier if (i == 0) {
4237dd7cddfSDavid du Colombier if (progstate != WAIT_FOR_EOJ) {
4247dd7cddfSDavid du Colombier if (write(printerfd, "\004", 1)!=1) {
4257dd7cddfSDavid du Colombier perror("sendfile:write:");
4267dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
4277dd7cddfSDavid du Colombier } else if (write(pipefd, Wait_for_eoj, 1)!=1) {
4287dd7cddfSDavid du Colombier perror("sendfile:write:");
4297dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
4307dd7cddfSDavid du Colombier } else {
4317dd7cddfSDavid du Colombier progstate = WAIT_FOR_EOJ;
4327dd7cddfSDavid du Colombier }
4337dd7cddfSDavid du Colombier }
4347dd7cddfSDavid du Colombier }
4357dd7cddfSDavid du Colombier break;
4367dd7cddfSDavid du Colombier case REQ_STAT:
4377dd7cddfSDavid du Colombier if (write(printerfd, "\024", 1)!=1) {
4387dd7cddfSDavid du Colombier fprintf(stderr, "write to printer failed\n");
4397dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
4407dd7cddfSDavid du Colombier }
4417dd7cddfSDavid du Colombier if (debug&02) fprintf(stderr, "^T");
4427dd7cddfSDavid du Colombier break;
4437dd7cddfSDavid du Colombier case FATAL_ERROR:
4447dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
4457dd7cddfSDavid du Colombier }
4467dd7cddfSDavid du Colombier } else if (n < 0) {
4477dd7cddfSDavid du Colombier perror("sendfile:select:");
4487dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
4497dd7cddfSDavid du Colombier } else if (n == 0) {
4507dd7cddfSDavid du Colombier sleep(1);
4517dd7cddfSDavid du Colombier fprintf(stderr, "sendfile timeout\n");
4527dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
4537dd7cddfSDavid du Colombier }
4547dd7cddfSDavid du Colombier } while ((progstate != FATAL_ERROR) && (progstate != OVER_AND_OUT));
4557dd7cddfSDavid du Colombier if (write(printerfd, "\004", 1)!=1) {
4567dd7cddfSDavid du Colombier perror("sendfile:write:");
4577dd7cddfSDavid du Colombier progstate = FATAL_ERROR;
4587dd7cddfSDavid du Colombier }
4597dd7cddfSDavid du Colombier
4607dd7cddfSDavid du Colombier if (debug&02) fprintf(stderr, "%d bytes sent\n", bytesent);
4617dd7cddfSDavid du Colombier if (progstate == FATAL_ERROR)
4627dd7cddfSDavid du Colombier return(1);
4637dd7cddfSDavid du Colombier else
4647dd7cddfSDavid du Colombier return(0);
4657dd7cddfSDavid du Colombier }
4667dd7cddfSDavid du Colombier
main(int argc,char * argv[])4677dd7cddfSDavid du Colombier void main(int argc, char *argv[]) {
4687dd7cddfSDavid du Colombier int c, usgflg=0, infd, printerfd;
469*14f51593SDavid du Colombier int cpid, sprv;
4707dd7cddfSDavid du Colombier int pipefd[2];
4717dd7cddfSDavid du Colombier char *dialstr;
472*14f51593SDavid du Colombier unsigned long rprv;
4737dd7cddfSDavid du Colombier
4747dd7cddfSDavid du Colombier dialstr = 0;
4757dd7cddfSDavid du Colombier
4767dd7cddfSDavid du Colombier while ((c = getopt(argc, argv, "b:d:")) != -1)
4777dd7cddfSDavid du Colombier switch (c) {
4787dd7cddfSDavid du Colombier case 'b':
4797dd7cddfSDavid du Colombier blocksize = atoi(optarg)/10;
4807dd7cddfSDavid du Colombier if (blocksize > MESGSIZE || blocksize < 1)
4817dd7cddfSDavid du Colombier blocksize = MESGSIZE;
4827dd7cddfSDavid du Colombier break;
4837dd7cddfSDavid du Colombier case 'd':
4847dd7cddfSDavid du Colombier debug = atoi(optarg);
4857dd7cddfSDavid du Colombier dial_debug = debug;
4867dd7cddfSDavid du Colombier break;
4877dd7cddfSDavid du Colombier case '?':
4887dd7cddfSDavid du Colombier fprintf(stderr, "unknown option %c\n", c);
4897dd7cddfSDavid du Colombier usgflg++;
490*14f51593SDavid du Colombier break;
4917dd7cddfSDavid du Colombier }
4927dd7cddfSDavid du Colombier if (optind < argc)
4937dd7cddfSDavid du Colombier dialstr = argv[optind++];
494*14f51593SDavid du Colombier else
4957dd7cddfSDavid du Colombier usgflg++;
4967dd7cddfSDavid du Colombier if (usgflg) {
497*14f51593SDavid du Colombier fprintf(stderr, "usage: %s [-b baudrate] net!host!service [infile]\n",
498*14f51593SDavid du Colombier argv[0]);
4997dd7cddfSDavid du Colombier exit (2);
5007dd7cddfSDavid du Colombier }
5017dd7cddfSDavid du Colombier if (optind < argc) {
5027dd7cddfSDavid du Colombier infd = open(argv[optind], 0);
5037dd7cddfSDavid du Colombier if (infd < 0) {
5047dd7cddfSDavid du Colombier fprintf(stderr, "cannot open %s\n", argv[optind]);
5057dd7cddfSDavid du Colombier exit(1);
5067dd7cddfSDavid du Colombier }
5077dd7cddfSDavid du Colombier optind++;
5087dd7cddfSDavid du Colombier } else
5097dd7cddfSDavid du Colombier infd = 0;
5107dd7cddfSDavid du Colombier
511*14f51593SDavid du Colombier if (debug & 02)
512*14f51593SDavid du Colombier fprintf(stderr, "blocksize=%d\n", blocksize);
513*14f51593SDavid du Colombier if (debug)
514*14f51593SDavid du Colombier fprintf(stderr, "dialing address=%s\n", dialstr);
5157dd7cddfSDavid du Colombier printerfd = dial(dialstr, 0, 0, 0);
516*14f51593SDavid du Colombier if (printerfd < 0)
517*14f51593SDavid du Colombier exit(1);
5187dd7cddfSDavid du Colombier
5197dd7cddfSDavid du Colombier fprintf(stderr, "printer startup\n");
5207dd7cddfSDavid du Colombier
5217dd7cddfSDavid du Colombier if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipefd) < 0) {
5227dd7cddfSDavid du Colombier perror("socketpair");
5237dd7cddfSDavid du Colombier exit(1);
5247dd7cddfSDavid du Colombier }
5257dd7cddfSDavid du Colombier switch(cpid = fork()){
5267dd7cddfSDavid du Colombier case -1:
5277dd7cddfSDavid du Colombier perror("fork error");
5287dd7cddfSDavid du Colombier exit(1);
529*14f51593SDavid du Colombier case 0: /* child - to printer */
5307dd7cddfSDavid du Colombier close(pipefd[1]);
531*14f51593SDavid du Colombier sprv = sendfile(infd, printerfd, pipefd[0]);
532*14f51593SDavid du Colombier if (debug)
533*14f51593SDavid du Colombier fprintf(stderr, "to remote - exiting\n");
5347dd7cddfSDavid du Colombier exit(sprv);
535*14f51593SDavid du Colombier default: /* parent - from printer */
5367dd7cddfSDavid du Colombier close(pipefd[0]);
537*14f51593SDavid du Colombier rprv = readprinter(printerfd, pipefd[1]);
538*14f51593SDavid du Colombier if (debug)
539*14f51593SDavid du Colombier fprintf(stderr, "from remote - exiting\n");
540*14f51593SDavid du Colombier while(wait(&sprv) != cpid)
541*14f51593SDavid du Colombier ;
5427dd7cddfSDavid du Colombier exit(rprv|sprv);
5437dd7cddfSDavid du Colombier }
5447dd7cddfSDavid du Colombier }
545