|
|
1.1 root 1: /************************************************************************
2: * *
3: * dlpt - download a CCI POWERTERMINAL or POWERTERMINAL II *
4: * *
5: ************************************************************************/
6:
7: /************************************************************************
8: * Compilation Notes -- *
9: * *
10: * - The symbol V7 must be defined when compiling for Version 7 *
11: * or Berkeley 4.2. *
12: * - No flags are needed when compiling for S3. *
13: * - This file contains the changes to support the new Berkeley *
14: * 4.2 signaling mechanism that were present at one point, then *
15: * deleted, and were restored in version 2.3.1. These changes *
16: * are required to make timed-out reads work correctly. *
17: * Compile with NEWSEG set to get these changes. *
18: * *
19: ************************************************************************/
20:
21: /************************************************************************
22: Version 1.2.1 changes:
23:
24: MDS 3/13/84 Implemented logic to circumvent 5/20 CPU port
25: problem. CPU port loses input characters
26: transmitted by the terminal at 9600 baud.
27: Therefore, if this program receives an invalid
28: DA response and it is talking to a cpu port,
29: then act as if a valid ROM DA response was
30: received.
31: Implemented "force" option. If specicified at
32: execution time the receipt of an invalid DA
33: response will be treated as a valid ROM DA
34: response.
35:
36: *************************************************************************
37:
38: Version 2.0.0 changes:
39:
40: MDS 11/6/84 Implemented logic to support CCI POWERTERMINAL II.
41:
42: *************************************************************************
43:
44: Version 2.1.0 changes:
45:
46: Version 2.1 is an interim version of dlpt created
47: by OSG.
48:
49: *************************************************************************
50:
51: Version 2.2.0 changes:
52:
53: SP & BM @osg
54: MDS 2/20/85 1) -a prompt came up twice on PT1 when 'n'
55: given. Fixed.
56: 2) If tty is tty01 or console, and dlpt
57: cannot determine terminal type, message is
58: given for user to manually 'dlpt -f[12]'.
59: 3) Added argument check to -t option to prevent
60: core dump if no arguments given with -t.
61: 4) In function whoisit() changed fputs to write.
62: Fputs did not work on PERPOS-S.
63: 5) Removed CR1 from ttyinit() for System 3.
64: CR1 caused a NULL,ACK to be output after CR
65: in Terminal loaded message.
66: 6) Added XOFF/XON recognition to download by
67: adding IXON to ttyinit().
68: 7) Changed source to default compile for S3
69: instead of V7. For V7 need to set V7 flag.
70:
71: *************************************************************************
72:
73: Version 2.3.0 changes:
74:
75: BJM @osg
76: BJM 3/6/85 Added XON/XOFF recognition to download for
77: Version 7 and Berkeley 4.2 version by setting
78: port to CBREAK mode for 'normal' download and
79: RAW mode for download in reliability mode.
80:
81: Added conditional compilation statements for
82: 19.2K baud.
83:
84: *************************************************************************
85:
86: Version 2.3.1 changes:
87:
88: woe@ccicpg
89: WOE 6/17/85 Restored changes for new Berkeley 4.2 signalling
90: mechanisms under the compile-time define NEWSIG.
91: Timed-out reads require these changes since the
92: read system call is "automatically" retried when
93: interrupted by a SIGALRM (or any other handled/
94: ignored signal).
95:
96: *************************************************************************/
97:
98:
99: /************************************************************************
100: * *
101: * Include files. *
102: * *
103: ************************************************************************/
104:
105: #include "stdio.h"
106: #include "signal.h"
107:
108: #ifdef V7 /********* if Version 7 *********/
109:
110: #include "sgtty.h"
111:
112: #else /********* else assume System 3 *********/
113:
114: #include "termio.h"
115:
116: #endif /********* end of System 3 *********/
117:
118: #ifdef NEWSIG /* new signal mechanism */
119: #include <setjmp.h>
120: #endif
121:
122: /************************************************************************
123: * *
124: * Defines. *
125: * *
126: ************************************************************************/
127:
128: #define VERSION "2.3.1" /* version to be displayed by -v option */
129:
130: typedef int BOOL;
131:
132: #define PT1_DEFLD "/lib/pt/DEFAULT.LD" /* default download file */
133: #define PT2_DEFLD "/lib/pt/PT2DEF.LD" /* default download file */
134: #define TTY_PREFIX "/dev/" /* appended to -t field */
135:
136: #define STX 0x02 /* cntrl b */
137: #define ENQ 0x05 /* cntrl e */
138: #define ACK 0x06 /* cntrl f */
139: #define CAN 0x18 /* cntrl x */
140: #define BELL 0x07 /* cntrl g */
141:
142: #define INVRESP 0 /* signal no valid DA response from tty */
143: #define PT1ROM 1 /* signal that PT1 ROM responded to DA */
144: #define PT1RAM 2 /* signal that PT1 RAM responded to DA */
145: #define PT2ROM 3 /* signal that PT2 ROM responded to DA */
146: #define PT2RAM 4 /* signal that PT2 RAM responded to DA */
147:
148: #define TRUE 1
149: #define FALSE 0
150:
151: #define STX_TIMES 3 /* Number of times to send STX block */
152: #define NRETRIES 10 /* Number of retries for load block */
153: #define LD_TIMEOUT 2 /* Loading timeout period */
154:
155: /************************************************************************
156: * *
157: * Local functions and variables. *
158: * *
159: ************************************************************************/
160:
161: #ifdef NEWSIG /* new signal mechanism */
162: jmp_buf jb;
163: #else
164: #define timoread read
165: #define timowrite write
166: #endif
167:
168: char stxrec [] = {STX,STX,STX,STX,STX,STX,STX,STX,STX,STX};
169: char nulls [15];
170: char can = CAN;
171: char enq = ENQ;
172: char ack = ACK;
173: char devname[25] = TTY_PREFIX;
174:
175: int nullcnt = 14;
176: int timout;
177: int bailout();
178: int toterm; /* to terminal file descriptor */
179: int fromterm; /* from terminal file descriptor */
180:
181:
182: #ifdef V7 /********* if Version 7 *********/
183:
184: char baudrate; /* baudrate , set by ttysave or main */
185:
186: #else /********* else assume System 3 *********/
187:
188: unsigned short baudrate; /* baudrate , set by ttysave or main */
189:
190: #endif /********* end of System 3 *********/
191:
192:
193: char *myname; /* name of this program */
194:
195: BOOL rflag = FALSE; /* reliability mode */
196: char fflag = 0; /* force mode (used if inv DA response */
197: char *intro[] = {
198: "\n",
199: "DO YOU WANT A TERMINAL LOAD SEQUENCE?",
200: " ",
201: " If you do not answer within 15 seconds,",
202: " the terminal load sequence will begin.",
203: " ",
204: "ENTER: y <return> or <return> to load ",
205: " n <return> to avoid load :",
206: NULL
207: };
208:
209: char *wrong[] = { "INVALID ANSWER",
210: NULL
211: };
212:
213: char *loading[]={
214: "\n",
215: "Terminal load in progress",
216: NULL
217: };
218:
219:
220: /************************************************************************
221: * *
222: * main - Do it. *
223: * *
224: ************************************************************************/
225:
226: int
227: main (argc, argv)
228: int argc;
229: char **argv;
230: {
231: char *pt1file;
232: char *pt2file;
233: int who; /* who is responding */
234: char *ttyname();
235: BOOL aflag = FALSE; /* TRUE if inquire wanted before load */
236:
237: myname = *argv++; /* get the name of this program */
238: --argc;
239:
240: ttysave(); /* save ioctl params and init default baudrate */
241:
242: pt1file = PT1_DEFLD; /* set default hex file for load */
243: pt2file = PT2_DEFLD; /* set default hex file for load */
244:
245: while( argc-- ) /* while there are arguments to process */
246: {
247: if( **argv == '-' ) /* while flags left */
248: {
249: char *fptr = *argv; /* get ptr to flags */
250:
251: while( *++fptr ) /* while flags left */
252: {
253: char atobaud();
254:
255: switch( *fptr ) /* process a flag */
256: {
257:
258: case 'a': /* ask if load wanted */
259: aflag = TRUE;
260: break;
261:
262: case 'b': /* specific baud rate */
263: if( fptr[1] != '\0' )
264: {
265: baudrate = atobaud(++fptr);
266: if(baudrate == (char) -1 )
267: {
268: fprintf(stderr,
269: "%s: %s - invalid baud\n",
270: myname, fptr);
271: usage();
272: }
273: fptr = "x"; /* fake out */
274: break;
275: }
276: else
277: {
278: if( argc < 1 )
279: usage();
280: baudrate = atobaud(*++argv);
281: --argc;
282: if(baudrate == (char) -1 )
283: {
284: fprintf(stderr,
285: "%s: %s - invalid baud\n",
286: myname, *argv);
287: usage();
288: }
289: }
290: break;
291:
292: case 'f': /* force mode *
293: * to force load if *
294: * invalid DA response */
295: /* get type '1' or '2' for *
296: * PT1 or PT2 */
297: fflag = *++fptr;
298: break;
299:
300: case 'r': /*reliability mode */
301: rflag = TRUE;
302: break;
303:
304: case 't': /* specific port */
305: if( fptr[1] != 0 )
306: {
307: strcat(devname,++fptr);
308: fptr = "x"; /* fake out */
309: }
310: else
311: {
312: if( argc < 1 )
313: usage();
314: strcat(devname, *++argv);
315: --argc;
316: }
317: if(freopen(devname,"w",stdout) ==
318: (FILE *)NULL)
319: {
320: fprintf(stderr,
321: "%s: cannot open port for write - %s\n",
322: myname,devname);
323: usage();
324: }
325: if(freopen(devname,"r",stdin) ==
326: (FILE *)NULL)
327: {
328: fprintf(stderr,
329: "%s: cannot open port for read - %s\n",
330: myname,devname);
331: usage();
332: }
333: break;
334:
335: case 'v': /* display version */
336: printf("%s: Version %s\n",myname,
337: VERSION);
338: exit(0);
339: break;
340:
341: default:
342: fprintf(stderr,
343: "%s: %c - unknown flag\n",
344: myname, *fptr);
345: usage();
346: break;
347: }
348: }
349: }
350: else
351: {
352: pt1file = *argv;
353: pt2file = *argv;
354: }
355: ++argv;
356: }
357:
358: signal (SIGALRM, bailout);
359: toterm = 1; /* standard output */
360: fromterm = 0; /* standard input */
361:
362: who = whoisit(); /* find out who is there */
363:
364: if( who == INVRESP ) /* if an invalid or no response */
365: switch( fflag ) { /* check for force wanted */
366: case '1': /* if PT1 force wanted */
367: who = PT1ROM; /* force a PT1 download */
368: break;
369:
370: case '2': /* if PT2 force wanted */
371: who = PT2ROM; /* force a PT2 download */
372: break;
373:
374: default: { /* else no force */
375: char *devwho;
376: devwho = ttyname(toterm); /* get name of port */
377: if ((strcmp(devwho,"/dev/console") == 0) ||
378: (strcmp(devwho,"/dev/tty01") == 0)) {
379: printf(
380: "%s: from console or tty01, enter 'dlpt -f#'\n-f1 for PT1, -f2 for PT2\n", myname);
381: ttyrestore();
382: exit(0);
383: }
384: break;
385: }
386: }
387:
388: switch( who ) /* depending on who responded */
389: {
390: case PT1RAM: /* is a downloaded PT1 ( CT ) */
391: case PT2RAM: /* is a downloaded PT2 */
392: ttytalk();
393: printf("\r\nTerminal loaded\r\n");
394: break;
395:
396: case PT1ROM: /* is a non-downloaded PT1 */
397: if((!aflag) || ((aflag) && (wantptload())))
398: {
399: ttytalk();
400: putmsg(loading, 0);
401: dlpt1(pt1file); /* load terminal */
402:
403: /************************************************
404: * NOTE: If terminal DTR is tied to CPU DCD *
405: * AND the terminal firmware re-initializes *
406: * the 8251 I/O chip, DCD is dropped which *
407: * causes this program to get killed at this *
408: * point. This is the case for the PT *
409: * terminal as of 10/25/83. *
410: ************************************************/
411:
412: sleep(3); /* wait for terminal to initialize */
413: printf("Terminal download complete\r\n");
414: }
415: break;
416:
417: case PT2ROM: /* is a non-downloaded PT2 */
418: if((!aflag) || ((aflag) && (wantptload())))
419: {
420: ttytalk();
421: putmsg(loading, 0);
422: dlpt2(pt2file); /* load terminal */
423: sleep(3); /* wait for terminal to initialize */
424: printf("Terminal download complete\r\n");
425: }
426: break;
427:
428: default:
429: break;
430: }
431: ttyrestore();
432: }
433:
434: /************************************************************************
435: * *
436: * usage - print usage statement and abort *
437: * *
438: ************************************************************************/
439:
440: usage()
441: {
442: fprintf(stderr,
443: "Usage: %s [-a] [-fTermNo] [-r] [-b BaudRate] [-t ttyXX] [load file]\n",
444: myname);
445: exit(1);
446: }
447:
448:
449: /************************************************************************
450: * *
451: * PT down-load rtn *
452: * *
453: ************************************************************************/
454: dlpt1(hexfile)
455:
456: char * hexfile;
457:
458: {
459:
460: FILE * in; /* input file */
461: int i; /* counter */
462: int rs; /* record size */
463: char record [524]; /* record */
464: int cs; /* checksum */
465: char * rp; /* record pointer */
466: char csum [2]; /* received checksum */
467:
468: in = stdin;
469: timout = 0; /* Alarm time-out flag */
470:
471: if ((in = fopen (hexfile, "r")) == (FILE *)NULL)
472: fatal ("Can't open input file.");
473:
474: ttyinit(); /* set up port for load */
475:
476: for (i = STX_TIMES ; i > 0 ; i--)
477: if (write (toterm, stxrec, sizeof(stxrec)) != sizeof(stxrec))
478: fatal ("1. Can't write STX to terminal.");
479:
480: while ((rs = getrec1 (in, record)) > 0)
481: {
482: for (cs = 0, i = rs, rp = record ; i > 0 ; i--)
483: cs += *rp++;
484:
485: for (i = NRETRIES ; i > 0 ; i--)
486: {
487: if (write (toterm, record, rs) != rs)
488: derror ("3. Can't write record to terminal.");
489:
490: if (write (toterm, nulls, nullcnt) != nullcnt)
491: derror ("4. Can't write NULLS to terminal.");
492:
493: if(rflag==TRUE)
494: {
495: alarm(LD_TIMEOUT); /* time limit */
496: timout = 0;
497: if (timowrite (toterm, &ack, 1) != 1 || (timout))
498: {
499: derror ("6. Can't write ACK to terminal.");
500: continue;
501: }
502:
503: alarm(LD_TIMEOUT); /* time limit */
504: timout = 0;
505: if (timoread (fromterm, csum, 1) != 1 || (timout))
506: {
507: derror ("7. Can't read ACK from terminal.");
508: continue;
509: }
510:
511: alarm(LD_TIMEOUT); /* time limit */
512: timout = 0;
513: if (timoread (fromterm, csum + 1, 1) != 1 || (timout))
514: {
515: derror ("8. Can't read csum count from terminal.");
516: continue;
517: }
518:
519: if (csum [0] != ACK)
520: {
521: derror ("9. Protocol violation not ACK.");
522: continue;
523: }
524:
525: if (((cs & 0x3f)+0x20) == csum[1])
526: break;
527:
528: } /* end of reliabilaty logic */
529:
530: else
531: break;
532:
533: } /* end of for loop */
534:
535: if (i == 0)
536: fatal ("10. Number of retries exceeded.");
537:
538: if (rs == 11) /* Last record */
539: return;
540:
541: }
542:
543: if (rs == 0)
544: fatal ("11. End of file reached before end-of-load record.");
545: else
546: fatal ("12. Bad record read.");
547:
548: }
549:
550: /************************************************************************
551: * *
552: * TITLE: dlpt2 - down load CCI POWERTERMINAL II *
553: * *
554: * RETURNS: nothing *
555: * *
556: ************************************************************************/
557: dlpt2( hexfile )
558:
559: char *hexfile;
560:
561: {
562: FILE * in; /* input file */
563: int i; /* counter */
564: int rs; /* record size */
565: char record [524]; /* record */
566:
567: in = stdin;
568: timout = 0; /* Alarm time-out flag */
569:
570: if ((in = fopen (hexfile, "r")) == (FILE *)NULL)
571: fatal ("Can't open input file.");
572:
573: ttyinit(); /* set up port for load */
574:
575: ttyflush(); /* flush port before attempting com */
576:
577: for (i = STX_TIMES ; i > 0 ; i--)
578: if (write (toterm, stxrec, sizeof(stxrec)) != sizeof(stxrec))
579: fatal ("1. Can't write STX to terminal.");
580:
581: if( rflag == TRUE ) /* if rel mode wanted - tell PT2 */
582: {
583: if( write( toterm, &enq, 1 ) != 1 )
584: {
585: d2error ("16. Can't write ENQ to terminal.");
586: }
587: }
588:
589: while( ( rs = getrec2(in, record) ) > 0 )
590: {
591: for( i = NRETRIES ; i > 0 ; i-- )
592: {
593: if( write ( toterm, record, rs ) != rs )
594: d2error ("3. Can't write record to terminal.");
595:
596: /*
597: if( write ( toterm, nulls, nullcnt ) != nullcnt )
598: d2error ("4. Can't write NULLS to terminal.");
599: */
600:
601: if( rflag == TRUE )
602: {
603: char resp; /* resp char */
604:
605: alarm(LD_TIMEOUT); /* time limit */
606: timout = 0;
607: if( (timoread( fromterm, &resp, 1 ) != 1 ) || (timout))
608: {
609: d2error ("17. Can't read ACK from terminal.");
610: continue;
611: }
612: if( resp == ACK )
613: break; /* get txmit next char */
614:
615: d2error ("19. Protocol violation not ACK.");
616: continue;
617:
618: } /* end of reliabilaty logic */
619:
620: else
621: break; /* no verification wanted */
622:
623: } /* end of error retry loop */
624:
625: if( i == 0 )
626: fatal ("20. Number of retries exceeded.");
627:
628: /* a complete record has been transmitted */
629: /* check if it was the last record */
630:
631: if( record[ 1 ] == '8' ) /* was it an S8 record? */
632: return; /* if so, done !! */
633:
634: }
635:
636: if( rs == 0 )
637: fatal ("21. End of file reached before end-of-load record.");
638: else
639: fatal ("22. Bad record read.");
640:
641: }
642:
643: /************************************************************************
644: * *
645: * derror - have an error handle and return *
646: * *
647: ************************************************************************/
648:
649: int
650: derror (s)
651:
652: char * s;
653:
654: {
655:
656: alarm(0); /* cancel alarms */
657: write (toterm,&can,sizeof(can)); /* cancel */
658: write (toterm,nulls,nullcnt); /* pad for next write */
659: fputs(s, stderr);
660: fputs("\r\n", stderr);
661: return;
662:
663: }
664:
665: /************************************************************************
666: * *
667: * d2error - have an error handle and return *
668: * *
669: ************************************************************************/
670:
671: int
672: d2error (s)
673:
674: char *s;
675:
676: {
677: alarm(0); /* cancel alarms */
678: fputs(s, stderr);
679: fputs("\r\n", stderr);
680: return;
681: }
682:
683: /************************************************************************
684: * *
685: * getrec1 - Get a PT1 (CT) record to transmit. *
686: * *
687: * Returns: *
688: * -1 Error in file format. *
689: * 0 End of file reached. *
690: * > 0 Size of record to transmit. *
691: * *
692: ************************************************************************/
693: int
694: getrec1(fd, rp)
695:
696: FILE * fd;
697: char * rp;
698:
699: {
700:
701: int c;
702: int nc; /* number of characters */
703: int l; /* length of record bytes */
704: int cc; /* checksum */
705: int i; /* counter */
706: int a; /* address piece */
707:
708: while ((c = getc (fd)) != ':') /* Look for start of record */
709: if (c == EOF)
710: return 0; /* End of file */
711:
712: /***** Start record off. */
713:
714: /*%%% printf("At record start\n");/*%%*/
715: *rp++ = ':';
716: nc = 1;
717:
718: /***** Get number of hex bytes in record. */
719:
720: if ((l = getxb (fd, rp)) < 0)
721: return -1;
722:
723: /*%%% printf("%d data bytes\n", l);/*%%*/
724: cc = l; /* Start checksum */
725: rp += 2; /* Past two characters */
726: nc += 2; /* Two more characters */
727:
728: /***** Get address portion of data record. */
729:
730: for (i = 2 ; i > 0 ; i--) /* Two hex bytes */
731: {
732: if ((a = getxb (fd, rp)) < 0)
733: return -1;
734:
735: cc += a; /* Figure address into checksum */
736: rp += 2; /* Past two characters */
737: nc += 2; /* Two more characters */
738: }
739:
740: /***** Read type byte, which should be zero. */
741:
742: if ((i = getxb (fd, rp)) != 0)
743: return -1;
744:
745: cc += i; /* Figure type into checksum */
746: rp += 2; /* Past two characters */
747: nc += 2; /* Two more characters */
748:
749: /***** Read in the data record. */
750:
751: while (l-- > 0) /* Count down */
752: {
753: if ((i = getxb (fd, rp)) < 0)
754: return -1;
755:
756: /*%%% printf ("Read %d\n", i);/*%%*/
757: cc += i; /* Checksum */
758: rp += 2; /* Pointer */
759: nc += 2; /* Number of characters */
760: }
761:
762: cc = (-cc) & 0377; /* Two's complement byte */
763:
764: /*%%% printf ("Checksum = %x\n", cc);/*%%*/
765: *rp = cc >> 4;
766: *rp += *rp < 10 ? '0' : 'A' - 10;
767: *++rp = cc & 0xF;
768: *rp += *rp < 10 ? '0' : 'A' - 10;
769:
770: /*%%% printf ("record size = %d\n", nc + 2);/*%%*/
771: return nc + 2;
772:
773: }
774:
775: /************************************************************************
776: * *
777: * TITLE: getrec2 - Get a POWERTERMINAL II record to transmit *
778: * *
779: * RETURNS: *
780: * -1 Error in file format. *
781: * 0 End of file reached. *
782: * > 0 Size of record to transmit. *
783: * *
784: ************************************************************************/
785: int
786: getrec2 (fd, rp)
787:
788: FILE *fd;
789: char *rp;
790:
791: {
792: register char *rrp; /* register copy of record ptr */
793: char c; /* temp store of read char */
794: int nc; /* number of characters */
795: int l; /* length of record bytes */
796:
797: rrp = rp; /* get addr in a register */
798:
799: while(( c = getc( fd )) != 'S') /* Look for start of record */
800: if( c == EOF )
801: return( 0 ); /* End of file */
802:
803: *rrp++ = c ; /* put first char of record */
804: nc = 1; /* start the char counter */
805:
806: if( ( *rrp++ = getc( fd ) ) < 0 ) /* get S-record type */
807: return( -1 ); /* if EOF, return */
808: nc++; /* incre num of chars */
809:
810: if( ( l = getxb(fd, rrp) ) < 0) /* get num of bytes */
811: return -1;
812: rrp += 2; /* Past two characters */
813: nc += 2; /* Two more characters */
814:
815: /* get address, data, and checksum fields */
816:
817: l <<= 1 ; /* chg to num nibbles (times 2) */
818:
819: while( l-- > 0 ) { /* l now contains num of nibbles*/
820: if ( ( *rrp++ = getc( fd ) ) < 0)
821: return( -1 );
822: nc++; /* bump char counter */
823: }
824:
825: return( nc ); /* return num of chars in rec */
826:
827: }
828:
829: /************************************************************************
830: * *
831: * getxb - Get a hex byte. *
832: * *
833: * Returns: *
834: * -1 Error in file format or end of file reached. *
835: * >= 0 Integer value of byte. *
836: * *
837: ************************************************************************/
838:
839: int
840: getxb (fd, sp)
841:
842: FILE * fd;
843: char * sp;
844:
845: {
846:
847: register int i, j;
848:
849: if ((i = getxn (fd, sp++)) < 0 || (j = getxn (fd, sp)) < 0)
850: return -1;
851:
852: return (i << 4) | j;
853:
854: }
855:
856: /************************************************************************
857: * *
858: * getxn - Get a hex nibble. *
859: * *
860: * Returns: *
861: * -1 Error in file format or end of file reached. *
862: * >= 0 Integer value of nibble. *
863: * *
864: ************************************************************************/
865:
866: int
867: getxn (fd, sp)
868:
869: FILE * fd;
870: char * sp;
871:
872: {
873:
874: register int c;
875:
876: *sp = c = getc (fd);
877:
878: if (c >= '0' && c <= '9')
879: return c - '0';
880: else if (c >= 'A' && c <= 'F')
881: return c - 'A' + 10;
882: else if (c >= 'a' && c <= 'f')
883: return c - 'a' + 10;
884:
885: return -1;
886:
887: }
888:
889:
890: #ifdef NEWSIG /* new signal mechanism */
891:
892: /************************************************************************
893: * *
894: * timoread/timowrite - read/write with timeout *
895: * *
896: ************************************************************************/
897:
898: timoread(fd, ptr, size)
899: char *ptr;
900: {
901: if(setjmp(jb) == 0)
902: return read(fd, ptr, size);
903: return -1;
904: }
905: timowrite(fd, ptr, size)
906: char *ptr;
907: {
908: if(setjmp(jb) == 0)
909: return write(fd, ptr, size);
910: return -1;
911: }
912: #endif
913:
914:
915: /************************************************************************
916: * *
917: * fatal - display error message and abort *
918: * *
919: ************************************************************************/
920:
921: int
922: fatal (s)
923:
924: char * s;
925:
926: {
927:
928: write(toterm,&can,sizeof(can)); /* write cancel to terminal */
929: write(toterm,nulls,nullcnt);
930: fputs(s, stderr);
931: fputs("\r\n", stderr);
932: ttyrestore(); /* put terminal back to orig state */
933: exit(1);
934:
935: }
936:
937: /************************************************************************
938: * *
939: * wantptload - inquire if the user wants a download *
940: * *
941: ************************************************************************/
942:
943: #define BUFSIZE 80 /* size of answer buffers */
944: #define WANT_WAIT 15 /* time to wait for answer */
945:
946: wantptload ()
947: {
948: char answer[BUFSIZE];
949:
950: ttytalk(); /* talk slow - do not lose chars */
951: while (1)
952: {
953: sleep(1); /* allow time to prevent truncation */
954: putmsg(intro, 0); /* output msg, 0 pad null per line */
955: alarm(WANT_WAIT);
956: timout=0;
957: *answer = '\0';
958: timoread(0, answer, sizeof answer);
959: if(timout)
960: return(TRUE);
961: else
962: {
963: alarm(0); /* reset the alarm */
964: switch (*answer)
965: {
966: case 'y':
967: case 'Y':
968: case '\n':
969: return(TRUE);
970:
971: case 'n':
972: case 'N':
973: return(FALSE);
974:
975: default:
976: putmsg(wrong, 0);
977: }
978: }
979: }
980: }
981:
982: /************************************************************************
983: * *
984: * putmsg - put a msg to terminal with null padding at end of line *
985: * *
986: ************************************************************************/
987:
988: putmsg(text,pad)
989: char **text; /* pointer to list of string pointers */
990: int pad; /* number of nulls to output after each line */
991: {
992: while( *text != NULL )
993: {
994: register int i;
995: char *ptr = *text;
996:
997: while( *ptr )
998: {
999: putchar(*ptr++);
1000: }
1001: putchar('\n');
1002: for( i = 0; i < pad; i++)
1003: putchar('\0');
1004: text++;
1005: }
1006: }
1007:
1008: /************************************************************************
1009: * *
1010: * whoisit - Determine if the PT terminal is already downloaded *
1011: * *
1012: * returns PT1ROM if ROM responds to DA command *
1013: * returns PT1RAM if RAM responds to DA command *
1014: * returns INVRESP if no or invalid response received *
1015: * *
1016: ************************************************************************/
1017:
1018: #define DA "\033[c" /* ANSI DA ESC seq to send to terminal */
1019:
1020: /* Note that in the following expected DA response sequences, only the
1021: first 7 chars are used to match. This allows for future
1022: changes in the software version number without having to change
1023: this program. (The PT ROM & RAM respond with version number(s)
1024: in addition to the following characters.)
1025: */
1026:
1027: #define RAM1RSP "\033[=0;1;" /* ANSI DA ESC response from PT (CT) RAM */
1028: #define ROM1RSP "\033[=0;0;" /* ANSI DA ESC response from PT (CT) ROM */
1029: #define RAM2RSP "\033[=1;1;" /* ANSI DA ESC response from PT2 RAM */
1030: #define ROM2RSP "\033[=1;0;" /* ANSI DA ESC response from PT2 ROM */
1031: #define DATERM 'c' /* ANSI DA ESC sequence terminator */
1032:
1033: #define ASK_WAIT 3 /* time to wait for ESC response */
1034: #define ASK_TIMES 3 /* number of times to send DA req block */
1035: #define MAX_WRONG_CHARS 30 /* max number of chars to wait for ESC */
1036:
1037: whoisit ()
1038:
1039: {
1040: char response[MAX_WRONG_CHARS+1];
1041: int i,j;
1042:
1043: ttyinit(); /* make port raw for ESC sequence */
1044:
1045: for( j=0 ; j < ASK_TIMES ; j++ ) /* allow retries */
1046: {
1047: ttyflush(); /* flush port before attempting com */
1048:
1049: /* send DA cmd, is terminal loaded ? */
1050: write (toterm,DA,sizeof(DA)-1);
1051:
1052: alarm(ASK_WAIT);
1053: timout = 0;
1054: response[0] = '\0';
1055:
1056: /* Synchronize on first character of expected response */
1057:
1058: while (response[0] != *ROM1RSP)
1059: {
1060: if(timoread(0,&response[0],sizeof(char)) != sizeof(char))
1061: {
1062: if(timout)
1063: break;
1064: alarm(0);
1065: puts("\n\rDA ESC char read error\n\r");
1066: return(FALSE);
1067: }
1068: }
1069:
1070: if(timout) /* time-out here means no good response */
1071: continue; /* try again */
1072:
1073: alarm(0); /* make sure alarm is cleared */
1074:
1075: /* At this point we have the first char of expected
1076: response. Now get the rest of it. */
1077:
1078: for( i=1 ; ((response[i-1] != DATERM) &&
1079: (i < MAX_WRONG_CHARS-1)) ; i++ )
1080: {
1081: alarm(ASK_WAIT);
1082: timout=0;
1083: if(timoread(0,&response[i],sizeof(char)) != sizeof(char))
1084: {
1085: if(timout)
1086: break;
1087: alarm(0);
1088: puts("\n\rDA string read error\n\r");
1089: return(FALSE);
1090: }
1091: alarm(0); /* make sure alarm is cleared */
1092: }
1093: if(timout) /* if time-out, did not get enough chars*/
1094: continue; /* retry DA command */
1095:
1096: /* At this point we have at least a matching first char
1097: in response. Now compare the complete string read in
1098: with the expected response. */
1099:
1100: if(strncmp(ROM1RSP,response,sizeof(ROM1RSP)-1) == 0)
1101: return(PT1ROM);
1102: if(strncmp(RAM1RSP,response,sizeof(RAM1RSP)-1) == 0)
1103: return(PT1RAM);
1104: if(strncmp(ROM2RSP,response,sizeof(ROM2RSP)-1) == 0)
1105: return(PT2ROM);
1106: if(strncmp(RAM2RSP,response,sizeof(RAM2RSP)-1) == 0)
1107: return(PT2RAM);
1108: }
1109: return(INVRESP);
1110: }
1111:
1112: /************************************************************************
1113: * *
1114: * atobaud - convert an ascii number to a baud rate ala B50, B1200, ... *
1115: * returns -1 if invalid baud rate is specified. *
1116: * *
1117: ************************************************************************/
1118:
1119: struct baud {
1120: char *abaud; /* name of baud rate */
1121: char ibaud; /* baud rate for ioclt(2) */
1122: };
1123:
1124: struct baud baudtbl[] = {
1125: { "110", B110 },
1126: { "300", B300 },
1127: { "600", B600 },
1128: { "1200", B1200 },
1129: { "2400", B2400 },
1130: { "4800", B4800 },
1131: { "9600", B9600 },
1132: #ifdef B19200
1133: { "19200", B19200 },
1134: #endif
1135: { NULL, 0 }
1136: };
1137:
1138: char
1139: atobaud(string)
1140: char *string;
1141: {
1142: struct baud *bptr = baudtbl; /* index in baud rate table */
1143:
1144: while( bptr->abaud != NULL )
1145: {
1146: if( strcmp( bptr->abaud, string) == 0)
1147: {
1148: switch (atoi(string))
1149: {
1150: case 19200: nullcnt=14;break;
1151: case 9600: nullcnt= 9;break;
1152: case 4800: nullcnt= 8;break;
1153: case 2400: nullcnt= 6;break;
1154: case 1200: nullcnt= 5;break;
1155: case 300:
1156: case 110: nullcnt= 3;break;
1157: default: nullcnt=14;break;
1158: }
1159: return( bptr->ibaud );
1160: }
1161: ++bptr;
1162: }
1163: return( (char) -1 );
1164: }
1165:
1166: /************************************************************************
1167: * *
1168: * bailout - alarm interrupt handler *
1169: * *
1170: ************************************************************************/
1171:
1172:
1173: bailout ()
1174: {
1175: #ifdef NEWSIG /* new signal mechanism */
1176: timout = 1;
1177: longjmp(jb, 1);
1178: #else
1179: signal(SIGALRM,bailout);
1180: timout = 1;
1181: return;
1182: #endif
1183: }
1184:
1185: /************************************************************************
1186: * *
1187: * tty utilities for performing get & put ioctl's *
1188: * *
1189: ************************************************************************/
1190:
1191: #define IOC_DELAY 1 /* Delay is needed after ioctl to allow baud-
1192: rate change to take effect. This requirement
1193: discovered on 2/21/84 when xmit of the DA
1194: seq would result in the first DA attempt to
1195: be sent at 9600 baud (irregardless of
1196: intended setting) and the second DA to go
1197: out at the intended (set by ioctl) rate. */
1198:
1199: #ifdef V7 /********* if Version 7 tty routines *********/
1200:
1201: struct sgttyb tp_new;
1202: struct sgttyb tp_orig;
1203: struct tchars tc_new = { '\177', '\034', '\021', '\023', '\004', '\377' };
1204: struct tchars tc_orig;
1205:
1206: ttysave ()
1207: {
1208: ioctl(0, TIOCGETP, &tp_orig);
1209: ioctl(0, TIOCGETC, &tc_orig);
1210: baudrate = tp_orig.sg_ospeed;
1211: }
1212:
1213: ttyrestore ()
1214: {
1215: ioctl(0, TIOCSETP, &tp_orig);
1216: ioctl(0, TIOCSETC, &tc_orig);
1217: sleep(IOC_DELAY); /* allow baud to settle */
1218: }
1219:
1220: ttyinit ()
1221: {
1222: /*
1223: * Use CBREAK mode for 'normal' download so that the Dow Jones
1224: * mux which generates XON/XOFF will be happy. XON/XOFF appears
1225: * to screw up reliability mode, however, so stick with RAW
1226: * mode for that.
1227: */
1228: ttysetup((short) ANYP + ((rflag) ? RAW : CBREAK));
1229: }
1230:
1231: ttytalk ()
1232: {
1233: ttysetup((short)ANYP+ECHO+CRMOD);
1234: }
1235:
1236: ttysetup (flags)
1237: short flags;
1238: {
1239:
1240: tp_new.sg_flags = flags;
1241: tp_new.sg_ispeed = baudrate;
1242: tp_new.sg_ospeed = baudrate;
1243: tp_new.sg_stopbits = tp_orig.sg_stopbits;
1244: ioctl(0, TIOCSETP, &tp_new);
1245: ioctl(0, TIOCSETC, &tc_new);
1246: sleep(IOC_DELAY); /* allow baud to settle */
1247:
1248: }
1249:
1250: ttyflush()
1251: {
1252: ioctl(0,TIOCFLUSH,0);
1253: }
1254:
1255: #else /********* else assume System 3 tty routines *********/
1256:
1257: struct termio term_orig; /* save area for orig port state */
1258: struct termio term_new; /* new port state */
1259:
1260: int count; /* used for 19200 baud delay */
1261:
1262: ttysave()
1263: {
1264: ioctl(0, TCGETA, &term_orig); /* save the initial port state */
1265: baudrate = term_orig.c_cflag & CBAUD; /* get orig baud */
1266: }
1267:
1268: ttyrestore()
1269: {
1270: ioctl(0, TCSETAF, &term_orig); /* restore saved port state */
1271: sleep(IOC_DELAY); /* allow baud to settle */
1272: }
1273:
1274: ttyinit()
1275: {
1276: term_new.c_iflag = ICRNL|ISTRIP|IXON;
1277: term_new.c_oflag = ONLRET|OPOST;
1278: term_new.c_cflag = baudrate|CREAD|CS8;
1279: term_new.c_lflag = 0;
1280: term_new.c_line = 0;
1281: term_new.c_cc[VINTR] = CINTR;
1282: term_new.c_cc[VQUIT] = CQUIT;
1283: term_new.c_cc[VERASE] = 0x08;
1284: term_new.c_cc[VKILL] = CKILL;
1285: term_new.c_cc[VMIN] = 1;
1286: term_new.c_cc[VTIME] = 1;
1287:
1288: ioctl( 0, TCSETAF, &term_new );
1289: sleep(IOC_DELAY); /* allow baud to settle */
1290:
1291: }
1292:
1293: ttytalk()
1294: {
1295: term_new.c_iflag = ICRNL|IXON;
1296: term_new.c_oflag = ONLCR|OPOST;
1297: term_new.c_cflag = baudrate|CREAD|CS8;
1298: term_new.c_lflag = ECHO|ECHOE|ECHOK|ICANON|ISIG;
1299:
1300: ioctl( 0, TCSETAF, &term_new );
1301: sleep(IOC_DELAY); /* allow baud to settle */
1302:
1303: }
1304:
1305: ttyflush()
1306: {
1307: ioctl( 0, TCFLSH, 2 ); /* flush input & output queues */
1308: }
1309:
1310: #endif /********* end of System 3 tty routines *********/
1311:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.