static char sccsid[] = "@(#)29 1.3 src/bos/usr/lib/lpd/plotlbe/plotbkl.c, cmdplot, bos411, 9428A410j 2/22/93 19:04:03"; /* * COMPONENT_NAME: (CMDPLOT) ported RT plotter code * * FUNCTIONS: * * ORIGINS: 27 * * IBM CONFIDENTIAL -- (IBM Confidential Restricted when * combined with the aggregated modules for this product) * SOURCE MATERIALS * (C) COPYRIGHT International Business Machines Corp. 1989 * All Rights Reserved * * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /*********************************************************************/ /* */ /* Module Name : PLOTBKL */ /* */ /* Copyright 1985, IBM Corporation */ /* */ /* Date: 09/03/85 */ /* */ /* Description: */ /* PLOTBKL is the BACKEND PROGRAM which provides support for */ /* plotters attached to a SAILBOAT in a SOLO environment. */ /* Module 'opens' the tty port passed as a parameter by */ /* the qdaemon, verifies any parameters entered with PRINT */ /* command. Plotter id, memory size and options is gathered */ /* and saved in the options structure. The current status of */ /* plotter is then checked. A message is issued to user if */ /* plotter is not ready and module waits for corrective */ /* action. The ENQ/ACK handshake is created from information */ /* gathered and sent to plotter. ORGPLOT is called to set */ /* the origin of the plotter to top left(plotter files must */ /* use positive offsets only). The plotter file is 'opened' */ /* and plotter commands read into a buffer. The ENQ */ /* character is placed at end of buffer and buffer sent to */ /* plotter. Module then waits for ACK before sending another */ /* buffer of data. */ /* */ /* SUBROUTINES: */ /* WR_PLOT - Writes a string of data to the tty port. */ /* RD_PLOT - Reads data from RS232 port into a buffer */ /* GET_OPT - Obtains plotter information(options and id) */ /* PORT_DEF - Saves current tty settings and sets them to */ /* to support plotters */ /* DRIVE_PLOT - Reads plotter commands from a file and writes */ /* them to the tty port, waits for ack */ /* FIND_NR - Search for NR plotter command */ /* END_PLOT - Ends plotting by moving media to next sheet if */ /* roll feed installed otherwise places plotter */ /* in VIEW state or waits for operator to remove */ /* media(small plotters only). */ /* CK_STATUS - Resets RS232 errors and waits(10 seconds) for */ /* plotter to respond */ /* CK_PLOT - Checks the current state of the plotter and */ /* issues a message to user if plotter is not ready */ /* TIME_OUT - Issues a message to operator if plotter fails */ /* to respond whitin 10 seconds */ /* NO_RESPONSE - Issues a message to operator after 60 seconds */ /* have elapsed and plotter has not sent an */ /* acknowledgement while plotting a file */ /* DIE - Catches cancel signal and sends a message indicating */ /* job is being canceled */ /* */ /* Include File: */ /* PLOT_ORG.C: Sets the orgin of the plotter */ /* PLOT_MSG.C: formulates and issues message to user or for qdaemon*/ /* PLOT_DEF.H: defines for plotter support */ /* */ /* Modifications: */ /* */ /* 03/20/91 CM - init nm_index to 2 because AIX V3 qdaemon */ /* no longer passes -statusfile parameter */ /* - remove '-fr=x' case statement to allow for */ /* up to 9 long-axis frames, also add check */ /* for -fr=0 */ /* - no longer terminate for unrecognized parms, */ /* issue message and continue */ /* - change all fprintf(ter_fp) and log_message */ /* calls to telluser(), delete first parm from */ /* all plot_msg calls (this was ter_fp) */ /* - for 6182 plotter re-send esc.@ to allow for */ /* correct handshaking */ /* - in end_plot : add support for 6182 */ /* autofeed (PG; command) */ /* - in drive_plot : don't issue continue msg */ /* if 6182 in autofeed and multi-page plot */ /* - in ck_status : fix esc.E return code checking */ /* */ /*********************************************************************/ #include #include #include #include #include #include "plot_def.h" #include #include #include #define Xoff 0x36 #define Xon 0x35 #define RUNNING 2 #define WAITING 3 int fd_tty = 0; int fd = 0; int file_index = 3; int logm = 0; int cancel = 0; char *list[20]; struct { char model[4]; int memsize; char plot_size; char roll_feed; char pen_select; char arc_circle; char poly_fill; char u_ram; } options; struct termio olddef; struct termio portdef; char *buf; struct { unsigned nr_fnd : 1; unsigned nonr_fnd : 1; unsigned eof : 1; } flags; main(argc,arglist) int argc; char *arglist[]; { int no_response(); int die(); int ct,i,j,nm_indx,fr,frcnt,bufcnt; short noinit; char bufsz[4]; char dev[20]; char init[4]; ct = 0; noinit = 0; flags.nr_fnd = FALSE; flags.nonr_fnd = FALSE; /* 03/91 set nm_indx to 2 because AIX V3 qdaemon doesn't pass */ /* -statusfile parm */ nm_indx = 2; fr = 1; options.model[0] = ' '; for(i=0; i 1)) { plot_msg(BAD_FR); error_exit(EXITBAD); } for (i=nm_indx; i 255)) options.plot_size = 'l'; else options.plot_size = 's'; break; default : break; } drive_plot(bufcnt,fr,frcnt,dev,noinit); if (flags.nonr_fnd == FALSE) end_plot(frcnt,dev); close(fd); } } free(buf); ioctl(fd_tty,TCSETAF,&olddef); close(fd_tty); } /********************************************************************/ /* find_nr */ /* */ /* Search for the NR plotter command */ /* */ /********************************************************************/ char * find_nr() { char *n_ptr; if (((n_ptr = (char *)strchr(buf,'n')) != NULL) || ((n_ptr = (char *)strchr(buf,'N')) != NULL)) { if (((strncmp(n_ptr,"nr;",3)) == 0) || ((strncmp(n_ptr,"NR;",3)) == 0)) return(n_ptr); } return(NULL); } /********************************************************************/ /* drive_plot */ /* */ /* Gets files status to obtain file size in bytes. Reads from the */ /* file into the buffer provided. Searches the buffer for the */ /* letter 'N' indicating end of plot but not necessarily end of file*/ /* Adjusts the file pointer to point beyond the NR;. Places ENQ */ /* character at end of buffer and writes the buffer to the tty port.*/ /* Waits for acknowledgement. If not acknowledgement for 60 seconds */ /* issue a message to operator to check device. Update progress and */ /* call end_plot routine if end of file or plot detected. */ /********************************************************************/ int drive_plot(bufcnt,fr,frcnt,dev,noinit) char dev[]; int bufcnt,fr,frcnt; short noinit; { int no_response(); double bytes_done; int percent, tot_bytes, rd_cnt, dif, ct; struct stat filestat; char *fnd, ack; ack = 0x00; if ((fstat(fd,&filestat)) == -1) { plot_msg(STAT_ERR,list[1]); error_exit(EXITBAD); } tot_bytes = filestat.st_size; while((rd_cnt = read(fd,buf,bufcnt)) > 0) { dif = 0; buf[rd_cnt] = 0x00; if ((fnd = (char *)find_nr()) != NULL) { *fnd = 0x05; dif = rd_cnt - ((fnd - buf) +3); rd_cnt = fnd - buf; filestat.st_size -= rd_cnt +3; if (filestat.st_size < 10) flags.eof = TRUE; else lseek(fd,-dif,1); flags.nr_fnd = TRUE; } else { filestat.st_size -= rd_cnt; buf[rd_cnt] = 0x05; } if ((ct = write(fd_tty,buf,rd_cnt+1)) > 0) ; else { plot_msg(WR_PORT,list[1]); error_exit(EXITBAD); } /* set alarm and wait for acknowledgement */ ack = 0x00; signal(SIGALRM,no_response); alarm(180); ct = 0; do { if (((ct = read(fd_tty,&ack,1)) == -1) && (errno == 4)) ct = 0; } while (ct == 0); if (ct > 0) { if (ack == 0x0a) signal(SIGALRM,SIG_IGN); else { plot_msg(BAD_ACK,list[1],ack); error_exit(EXITBAD); } } else { plot_msg(RD_FILE,list[1]); error_exit(EXITBAD); } /* update percent of file done */ percent = ((bytes_done += rd_cnt) / tot_bytes) * 100; log_progress(1,percent); /* end plotting if end of figure detected */ if (flags.nr_fnd == TRUE) { end_plot(frcnt,dev); flags.nonr_fnd = TRUE; if ((options.plot_size == 's') && (flags.eof == FALSE)) /* 03/91 for 6182 in autofeed mode, don't issue message */ if (!(((strncmp(options.model,"6182",4) == 0) || (strncmp(options.model,"7550",4) == 0)) && ((options.roll_feed == '1') || (options.roll_feed == '3')))) { plot_msg(CONTINUE,list[1]); logm = 1; while ((ck_plot()) != 0) { log_status(WAITING); sleep(5); log_status(RUNNING); } logm = 0; } if ((cancel == 0) && (flags.eof == FALSE)) { if ((plot_org(fd_tty,noinit,fr)) == -1) { plot_msg(ORG_ERR,list[1]); error_exit(EXITBAD); } } flags.nr_fnd = FALSE; } } } /********************************************************************/ /* wr_plot */ /* */ /* write a string terminated by a null character to a tty port */ /* */ /********************************************************************/ int wr_plot(str) char *str; { if (write(fd_tty,str,strlen(str)) == -1) { plot_msg(WR_PORT,list[1]); return(-1); } return(0); } /********************************************************************/ /* port_def */ /* */ /* saves the current settings of the port and sets up port */ /* parameters to support a plotter */ /* */ /********************************************************************/ int port_def() { int speed; if (ioctl(fd_tty,TCGETA,&olddef) == -1) { telluser("Unable to get port parameters for %s - errno = %d\n", list[1],errno); error_exit(EXITBAD); } speed = olddef.c_cflag & CBAUD; portdef.c_iflag = 0; portdef.c_oflag = 0; portdef.c_cflag = PARENB + CS7 + CLOCAL + CREAD + speed; portdef.c_lflag = ICANON; portdef.c_cc[4] = 010; portdef.c_cc[5] = 015; if (ioctl(fd_tty,TCSETAF,&portdef) == -1) { telluser("Unable to set port parameters for %s - errno = %d\n", list[1],errno); error_exit(EXITBAD); } } /********************************************************************/ /* get_opt */ /* */ /* get installed plotter options and plotter identification. Save */ /* information in 'options' structure. */ /* */ /********************************************************************/ int get_opt(dev) char dev[]; { int i; sprintf(dev,"OO;"); if ((wr_plot(dev)) == -1) error_exit(EXITBAD); if ((rd_plot(dev,20)) == -1) error_exit(EXITBAD); options.roll_feed = dev[0]; options.pen_select = dev[2]; options.arc_circle = dev[8]; options.poly_fill = dev[10]; options.u_ram = dev[14]; for (i=0; i<20; i++) dev[i] = 0x00; sprintf(dev,"OI;"); if ((wr_plot(dev)) == -1) return(-1); if ((rd_plot(dev,20)) == -1) return(-1); strncpy(options.model,dev,4); return(0); } /********************************************************************/ /* end_plot */ /* */ /* called when a file has been processed and places plotter in */ /* a state to accept the next file or waits for operator assist */ /* */ /********************************************************************/ int end_plot(frcnt,dev) int frcnt; char dev[]; { if (options.plot_size == 'l') { if (frcnt == 1) { if ((options.roll_feed == '1') || (options.roll_feed == '3')) { sprintf(dev,"SP0;EC;AF;OE;"); wr_plot(dev); rd_plot(dev,20); } else { sprintf(dev,"SP0;NR;"); wr_plot(dev); if (cancel == 0) { logm = 1; log_status(WAITING); while ((ck_plot()) != VIEW) sleep(2); logm = 0; log_status(RUNNING); } } } else { sprintf(dev,"FR;"); frcnt -= 1; wr_plot(dev); } } else /* small plotters start here */ { /* 03/91 add PG support for 6182 autofeed plotter */ if (((strncmp(options.model,"6182",4) == 0) || (strncmp(options.model,"7550",4) == 0)) && ((options.roll_feed == '1') || (options.roll_feed == '3'))) { sprintf(dev,"SP0;PG;OE;"); wr_plot(dev); /* wait for response from OE before ending */ rd_plot(dev,20); } else { sprintf(dev,"SP0;PU0,7200;OE;"); wr_plot(dev); rd_plot(dev,20); plot_msg(REMOVE_PAPER,list[1],dev); logm = 1; log_status(WAITING); while ((ck_plot()) == 0) sleep(2); logm = 0; } } } /********************************************************************/ /* ck_status */ /* */ /* check for RS232 error conditions */ /* time out in 10 seconds if plotter fails to respond */ /* */ /********************************************************************/ int ck_status() { int time_out(); int code; char stat_buf[10]; signal(SIGALRM,time_out); alarm(10); sprintf(stat_buf,"%c.J%c.K%c.E",0x1b,0x1b,0x1b); if ((wr_plot(stat_buf)) == -1) return(-1); if ((rd_plot(stat_buf,10)) == -1) return(-1); signal(SIGALRM,SIG_IGN); alarm(0); /* 03/91 following statement was incorrect, atoi expects ptr */ /* code = atoi(stat_buf[0]); */ code = atoi(&stat_buf[0]); if (code != 0) { stat_buf[2] = 0x00; plot_msg(RS232_ERROR,list[1],stat_buf); return(-1); } return(0); } /***********************************************************/ /* ck_plot */ /* */ /* Check condition of plotter and issue message to user */ /* if plotter is not ready */ /* */ /***********************************************************/ int ck_plot () { char ck_buf[30]; int err_cd,msgnum; typedef struct x { unsigned resv: 9; unsigned fld6: 1; unsigned fld5: 1; unsigned fld4: 1; unsigned fld3: 1; unsigned fld2: 1; unsigned fld1: 1; unsigned fld0: 1; }; struct x status_byte; short int *stptr; sprintf(ck_buf,"%c.O",0x1b); if ((wr_plot(ck_buf)) == -1) return(-1); if ((rd_plot(ck_buf,10)) == -1) return(-1); err_cd = atoi(ck_buf); stptr = (short int *)&status_byte; *stptr = err_cd; msgnum = 0; if (status_byte.fld4 == 1) msgnum = VIEW; if (status_byte.fld5 == 1) msgnum = NOPAPER; if (status_byte.fld6 == 1) msgnum = CLOSE; if (msgnum == CLOSE && status_byte.fld5 == 1) msgnum = NOPAPER_CLOSE; if (msgnum == CLOSE && status_byte.fld4 == 1) msgnum = CLOSE_VIEW; if (msgnum == 0) logm = 1; if (logm == 0) plot_msg(msgnum,list[1],&err_cd); return(msgnum); } /********************************************************************/ /* rd_plot */ /* */ /* read plotter information into buffer provided */ /* */ /********************************************************************/ int rd_plot(rbuf,ln) char *rbuf; int ln; { int cnt ,i; if ((cnt = read(fd_tty,rbuf,ln)) < 0) { plot_msg(RD_PORT,list[1]); return(-1); } /* telluser("read count = %d, tty data =",cnt); */ /* for (i=0; i