|
|
1.1 root 1: /* vt.c - VT initiator */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/vt/RCS/vt.c,v 7.2 90/01/11 18:38:13 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/vt/RCS/vt.c,v 7.2 90/01/11 18:38:13 mrose Exp $
9: *
10: *
11: * $Log: vt.c,v $
12: * Revision 7.2 90/01/11 18:38:13 mrose
13: * real-sync
14: *
15: * Revision 7.1 89/11/30 23:51:38 mrose
16: * pa2str
17: *
18: * Revision 7.0 89/11/23 22:31:49 mrose
19: * Release 6.0
20: *
21: */
22:
23: /*
24: * NOTICE
25: *
26: * Acquisition, use, and distribution of this module and related
27: * materials are subject to the restrictions of a license agreement.
28: * Consult the Preface in the User's Manual for the full terms of
29: * this agreement.
30: *
31: */
32:
33:
34: #include <signal.h>
35: #include "vtpm.h"
36: #include "sector1.h"
37: #include "tailor.h"
38:
39: #include <sys/ioctl.h>
40: #ifdef BSD44
41: #include <sys/termios.h>
42: #endif
43: #include <ctype.h>
44: #include <setjmp.h>
45: #include <varargs.h>
46:
47: #define strip(x) ((x)&0177)
48: #define TBUFSIZ 1024
49:
50: char ttyobuf[TBUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf;
51: char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
52:
53: int connected;
54: int net;
55: int showoptions = 0;
56: int options;
57: int debug = 0;
58: int crmod = 0;
59: char escape = ']' & 037;
60: static char *escapestr = "^]";
61:
62: VT_PROFILE vtp_profile;
63: int rflag = 0;
64: char erase_char; /*Unix Erase*/
65: char erase_line; /*Unix Kill*/
66: char intr_char; /*Unix Interrupt*/
67: char *my_displayobj = "K"; /*Initiator's Display Object Name*/
68: char *my_echo_obj = "NI"; /*Initiator's Negotiation Control Object*/
69: char *my_signal_obj = "KB"; /*Initiator's Signal Control Object*/
70: char *his_echo_obj = "NA"; /*Acceptor's Negotiation Control Object*/
71: char *his_signal_obj = "DI"; /*Acceptor's Signal Control Object*/
72: int my_right = INITIATOR;
73: char kb_image; /*KB Control Object Image*/
74: char di_image; /*DI Control Image*/
75: char ni_image; /*NI Control Object Image*/
76: char na_image; /*NA Control Object Image*/
77: char nego_state; /*Current state of NI affected options*/
78: char sync_image; /*SY Control Object*/
79: char ga_image;
80: int transparent = 0; /*Transparent Repertoire switch*/
81: int telnet_profile = 1;
82: int do_break = 1; /*If VT-BREAK Functional Unit agreed to*/
83: char *myhostname;
84: char peerhost[BUFSIZ];
85: struct PSAPaddr ts_bound;
86: int pty; /*Kludge for single map.c (sorry)*/
87:
88: char line[BUFSIZ];
89:
90: jmp_buf toplevel;
91: jmp_buf peerdied;
92:
93: extern int errno;
94:
95:
96: struct dispatch {
97: char *ds_name;
98: IFP ds_fnx;
99:
100: int ds_flags;
101: #define DS_NULL 0x00
102: #define DS_OPEN 0x01 /* association required */
103: #define DS_CLOSE 0x02 /* association avoided */
104:
105: char *ds_help;
106: };
107:
108: struct dispatch *getds ();
109:
110:
111: int vt_open (), vt_close (), vt_quit (), vt_status (), vt_suspend ();
112: int vt_ayt (), vt_break (), vt_escape ();
113: int vt_set (), vt_help ();
114:
115:
116: static struct dispatch dispatches[] = {
117: "ayt", vt_ayt, DS_OPEN,
118: "send \"are you there?\"",
119:
120: "break", vt_break, DS_OPEN,
121: "send break",
122:
123: "close", vt_close, DS_OPEN,
124: "release association with terminal service",
125:
126: "escape", vt_escape, DS_NULL,
127: "set escape character (depreciated)",
128:
129: "help", vt_help, DS_NULL,
130: "print help information",
131:
132: "open", vt_open, DS_CLOSE,
133: "associate with terminal service",
134:
135: "quit", vt_quit, DS_NULL,
136: "release association with terminal service and exit",
137:
138: "set", vt_set, DS_NULL,
139: "display or change variables",
140:
141: "status", vt_status, DS_OPEN,
142: "show current status",
143:
144: "suspend", vt_suspend, DS_OPEN,
145: "suspend vtp",
146:
147: NULL
148: };
149:
150:
151: SFD intr(), deadpeer();
152: char *control(), *strdup ();
153:
154: #ifdef BSD44
155: struct termios oterm;
156: #else
157: struct tchars otc;
158: struct ltchars oltc;
159: struct sgttyb ottyb;
160: #endif
161:
162: static int runcom = 0;
163: char *myname;
164: static char *myhome;
165: int tmode();
166:
167: LLog _vt_log = {
168: "./vt.log", NULLCP, NULLCP,
169: LLOG_NONE, LLOG_NONE, -1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK
170: };
171: LLog *vt_log = &_vt_log;
172:
173: main(argc, argv)
174: int argc;
175: char *argv[];
176: {
177: int i,
178: fflag;
179: char *logname,
180: buffer[BUFSIZ],
181: *vec[NVEC + 1];
182: FILE *fp;
183:
184: if (myname = rindex (*argv, '/'))
185: myname++;
186: if (myname == NULL || *myname == NULL)
187: myname = *argv;
188:
189: isodetailor (myname, 1);
190:
191: ll_hdinit (vt_log, myname);
192:
193: fflag = 0;
194: logname = 0;
195: myhostname = PLocalHostName ();
196: peerhost[0] = NULL;
197: acc = &accs;
198: acr = &acrs;
199: aci = &acis;
200:
201: #ifdef BSD44
202: if (tcgetattr(0, &oterm) == -1)
203: perror("tcgetattr");
204: erase_char = oterm.c_cc[VERASE];
205: erase_line = oterm.c_cc[VKILL];
206: intr_char = oterm.c_cc[VINTR];
207: #else
208: if (ioctl(0, TIOCGETP, (char *)&ottyb) == -1) {
209: perror("ioctl");
210: adios(NULLCP, "ioctl failed");
211: }
212: if (ioctl(0, TIOCGETC, (char *)&otc) == -1) {
213: perror("ioctl");
214: adios(NULLCP, "ioctl failed");
215: }
216: if (ioctl(0, TIOCGLTC, (char *)&oltc) == -1) {
217: perror("ioctl");
218: adios(NULLCP, "ioctl failed");
219: }
220: erase_char = ottyb.sg_erase;
221: erase_line = ottyb.sg_kill;
222: intr_char = otc.t_intrc;
223: #endif
224:
225:
226: setbuf(stdin, NULLCP);
227: setbuf(stdout, NULLCP);
228:
229: bzero ((char *) &vtp_profile, sizeof vtp_profile);
230: vtp_profile.profile_name = "telnet";
231: vtp_profile.arg_val.tel_arg_list.x_window = ncols (stdin);
232: vtp_profile.arg_val.tel_arg_list.full_ascii = 1;
233:
234: for(i=1; i<argc; i++)
235: {
236: if (peerhost[0] == NULL && (*argv[i] != '-'))
237: {
238: (void) strcpy(peerhost,argv[i]);
239: }
240: else if(!strcmp(argv[i], "-g"))
241: {
242: vtp_profile.arg_val.tel_arg_list.full_ascii = 0;
243: advise(LLOG_DEBUG,NULLCP,"using ASCII GO repertoire");
244: }
245: else if(!strcmp(argv[i], "-D"))
246: {
247: vtp_profile.profile_name = "default";
248: telnet_profile = 0;
249: my_displayobj = "DISPLAY-OBJECT-2";
250: advise(LLOG_DEBUG,NULLCP,"using default profile");
251: }
252: else if(!strcmp(argv[i],"-B"))
253: {
254: advise(LLOG_DEBUG,NULLCP,"VT-BREAK not chosen");
255: do_break = 0;
256: }
257: else if(!strcmp(argv[i], "-f"))
258: fflag++;
259: else if(!strcmp(argv[i], "-F"))
260: {
261: if ((logname = argv[++i]) == NULL || *logname == '-')
262: adios (NULLCP, "usage: %s -F logfile", myname);
263: vt_log -> ll_file = logname;
264: (void) ll_close (vt_log);
265: advise(LLOG_DEBUG,NULLCP, "logging to %s",logname);
266: }
267: else
268: adios("usage: %s [-g] [-D] [-B] [-f] [-F logfile] [hostname]",
269: myname);
270: }
271:
272:
273: runcom = 1;
274:
275: rcinit ();
276: (void) sprintf (buffer, "%s/.vtrc", myhome);
277: if (!fflag && (fp = fopen (buffer, "r"))) {
278: register char *bp;
279:
280: while (fgets (buffer, sizeof buffer, fp)) {
281: if (bp = index (buffer, '\n'))
282: *bp = NULL;
283:
284: bzero ((char *) vec, sizeof vec);
285: if (str2vec (buffer, vec) < 1)
286: continue;
287:
288: if (vtploop (vec, NOTOK) == NOTOK && peerhost[0])
289: exit (1);
290: }
291:
292: (void) fclose (fp);
293: }
294:
295: runcom = 0;
296:
297: if (peerhost[0] != NULL) {
298: if (setjmp(toplevel) != 0)
299: exit(0);
300: do_vt();
301: }
302: (void) setjmp(toplevel);
303: for (;;)
304: command(1);
305: }
306:
307: /* DISPATCH */
308:
309: command(top)
310: int top;
311: {
312: int eof,oldmode;
313: char *vec[NVEC + 1];
314:
315: oldmode = tmode(0);
316: if (!top)
317: (void) putchar('\n');
318: else
319: (void) signal (SIGINT, SIG_DFL);
320: eof = 0;
321: for (;;) {
322: if (getline ("%s> ", line) == NOTOK) {
323: if (eof) {
324: if (!connected)
325: exit (0);
326: (void) vt_status (NULLVP);
327: break;
328: }
329:
330: eof = 1;
331: continue;
332: }
333: eof = 0;
334:
335: bzero ((char *) vec, sizeof vec);
336: if (str2vec (line, vec) < 1)
337: break;
338:
339: if (vtploop (vec, NOTOK) != DONE)
340: break;
341: }
342: if (!top) {
343: if (!connected)
344: longjmp(toplevel, 1);
345: (void) fflush (stdout);
346: (void) fflush (stderr);
347: (void) tmode(oldmode);
348: }
349: }
350:
351: /* */
352:
353: static int vtploop (vec, error)
354: char **vec;
355: int error;
356: {
357: register struct dispatch *ds;
358:
359: if ((ds = getds (strcmp (*vec, "?") ? *vec : "help")) == NULL)
360: return error;
361:
362: if (!connected) {
363: if (ds -> ds_flags & DS_OPEN) {
364: advise (LLOG_NOTICE,NULLCP, "not associated with terminal service");
365: return error;
366: }
367: }
368: else
369: if (ds -> ds_flags & DS_CLOSE) {
370: advise (LLOG_NOTICE,NULLCP,
371: "already associated with terminal service");
372: return error;
373: }
374:
375: switch ((*ds -> ds_fnx) (vec)) {
376: case NOTOK:
377: return error;
378:
379: case OK:
380: default:
381: return OK;
382:
383: case DONE:
384: return DONE;
385: }
386: }
387:
388: /* */
389:
390: int getline (prompt, buffer)
391: char *prompt,
392: *buffer;
393: {
394: register int i;
395: register char *cp,
396: *ep;
397: static int sticky = 0;
398:
399: if (sticky) {
400: sticky = 0;
401: return NOTOK;
402: }
403:
404: (void)printf (prompt, connected ? peerhost : myname);
405: (void) fflush (stdout);
406:
407: for (ep = (cp = buffer) + BUFSIZ - 1; (i = getchar ()) != '\n';) {
408: if (i == EOF) {
409: (void)printf ("\n");
410: clearerr (stdin);
411: if (cp == buffer)
412: return NOTOK;
413:
414: sticky++;
415: break;
416: }
417:
418: if (cp < ep)
419: *cp++ = i;
420: }
421: *cp = NULL;
422:
423: return OK;
424: }
425:
426: /* */
427:
428: struct dispatch *getds (name)
429: register char *name;
430: {
431: register int longest,
432: nmatches;
433: register char *p,
434: *q;
435: char buffer[BUFSIZ];
436: register struct dispatch *ds,
437: *fs;
438:
439: longest = nmatches = 0;
440: for (ds = dispatches; p = ds -> ds_name; ds++) {
441: for (q = name; *q == *p++; q++)
442: if (*q == NULL)
443: return ds;
444: if (*q == NULL)
445: if (q - name > longest) {
446: longest = q - name;
447: nmatches = 1;
448: fs = ds;
449: }
450: else
451: if (q - name == longest)
452: nmatches++;
453: }
454:
455: switch (nmatches) {
456: case 0:
457: advise (LLOG_NOTICE,NULLCP, "unknown operation \"%s\"", name);
458: return NULL;
459:
460: case 1:
461: return fs;
462:
463: default:
464: for (ds = dispatches, p = buffer; q = ds -> ds_name; ds++)
465: if (strncmp (q, name, longest) == 0) {
466: (void) sprintf (p, "%s \"%s\"", p != buffer ? "," : "", q);
467: p += strlen (p);
468: }
469: advise (LLOG_NOTICE,NULLCP,
470: "ambiguous operation, it could be one of:%s",
471: buffer);
472: return NULL;
473: }
474: }
475:
476: /* OPERATIONS */
477:
478: static int vt_open (vec)
479: char **vec;
480: {
481: if (*++vec == NULL) {
482: if (getline ("host: ", line) == NOTOK || str2vec (line, vec) < 1)
483: return NOTOK;
484: }
485:
486: (void) strcpy (peerhost, *vec);
487: do_vt ();
488:
489: return OK;
490: }
491:
492:
493: do_vt()
494: {
495: (void) signal(SIGINT, intr);
496: (void) signal(SIGPIPE, deadpeer);
497: (void)printf("Trying...\n");
498: (void)fflush(stdout);
499:
500: if ((fd = con_req()) < 0)
501: return;
502:
503: connected++;
504: (void) vt_status (NULLVP);
505: (void)printf ("escape character is '%s'\n", escapestr);
506: if (setjmp(peerdied) == 0)
507: vt(fd);
508: adios (NULLCP, "association terminated by peer");
509: }
510:
511: /* */
512:
513: /* ARGSUSED */
514:
515: static int vt_close (vec)
516: char **vec;
517: {
518: (void) tmode(0);
519: vrelreq();
520: if (getch () >= -1) {
521: advise (LLOG_DEBUG,NULLCP, "flushing input queue...");
522: while (getch () >= -1)
523: continue;
524: }
525:
526: /* read network events until the release sequence reached
527: the point where the other side shuts down
528: */
529:
530: (void)printf ("association released\n");
531: (void)fflush (stdout);
532: connected = 0;
533: /* reset his options */
534:
535: return OK;
536: }
537:
538: /* */
539:
540: /* ARGSUSED */
541:
542: static int vt_quit (vec)
543: char *vec;
544: {
545: if (connected)
546: (void) vt_close (NULLVP);
547:
548: exit(0); /* NOTREACHED */
549: }
550:
551: /* */
552:
553: /* ARGSUSED */
554:
555: static int vt_status (vec)
556: char **vec;
557: {
558: (void) printf ("associated with terminal service on \"%s\"\n at %s\n",
559: peerhost, pa2str (&ts_bound));
560: (void) printf (" using %s profile\n", vtp_profile.profile_name);
561:
562: return OK;
563: }
564:
565: /* */
566:
567: /* ARGSUSED */
568:
569: static int vt_suspend (vec)
570: char **vec;
571: {
572: register int save;
573:
574: save = tmode(0);
575: (void)kill(0, SIGTSTP);
576:
577: /* reget parameters in case they were changed */
578: #ifdef BSD44
579: if (tcgetattr(0, &oterm) == -1)
580: perror("tcgetattr");
581: #else
582: if (ioctl(0, TIOCGETP, (char *)&ottyb) == -1) {
583: perror("ioctl");
584: adios(NULLCP, "ioctl failed");
585: }
586: if (ioctl(0, TIOCGETC, (char *)&otc) == -1) {
587: perror("ioctl");
588: adios(NULLCP, "ioctl failed");
589: }
590: if (ioctl(0, TIOCGLTC, (char *)&oltc) == -1) {
591: perror("ioctl");
592: adios(NULLCP, "ioctl failed");
593: }
594: #endif
595: (void) tmode(save);
596:
597: return OK;
598: }
599:
600: /* */
601:
602: static int vt_escape (vec)
603: char **vec;
604: {
605: char c;
606:
607: if (*++vec == NULL) {
608: if (getline ("new escape character: ", line) == NOTOK
609: || str2vec (line, vec) < 1)
610: return NOTOK;
611: }
612:
613: if ((c = *vec[0]) != NULL) {
614: char *cp = control (escape = c);
615:
616: free (escapestr);
617: escapestr = strdup (cp);
618: }
619: (void)printf ("escape character is '%s'\n", escapestr);
620:
621: return OK;
622: }
623:
624: /* VARIABLES */
625:
626: static char *debug_val[] = {
627: "0", "1", "2", "3", "4", "5", "6", "7", NULL
628: };
629:
630: static char *bool[] = {
631: "off", "on", NULL
632: };
633:
634: static char *emodes[] = {
635: "local", "remote", NULL
636: };
637:
638: static char *rmodes[] = {
639: "ascii", "transparent", NULL
640: };
641:
642: static char *xsaplevels[] = {
643: "none", "fatal", "exceptions", "notice", "pdus", "trace", "debug", NULL
644: };
645:
646:
647: struct var {
648: char *v_name;
649: IP v_value;
650:
651: char *v_dname;
652: char **v_dvalue;
653: char *v_mask;
654:
655: IFP v_hook;
656: };
657:
658: struct var *getvar ();
659:
660:
661: static int echo = 0;
662: static int repertoire = 0;
663: static int verbose = 0;
664:
665: int set_debug (), set_echo (), set_escape (), set_repertoire ();
666:
667:
668: static struct var vars[] = {
669: "acsaplevel", &_acsap_log.ll_events, "ACSAP logging", xsaplevels,
670: LLOG_MASK, NULLIFP,
671: "acsapfile", NULLIP, "ACSAP trace file", &_acsap_log.ll_file, NULLCP,
672: NULLIFP,
673:
674: "addrlevel", &_addr_log.ll_events, "address logging", xsaplevels,
675: LLOG_MASK, NULLIFP,
676: "addrfile", NULLIP, "address trace file", &_addr_log.ll_file, NULLCP,
677: NULLIFP,
678:
679: "compatlevel", &_compat_log.ll_events, "COMPAT logging", xsaplevels,
680: LLOG_MASK, NULLIFP,
681: "compatfile", NULLIP, "COMPAT trace file", &_compat_log.ll_file, NULLCP,
682: NULLIFP,
683:
684: "crmod", &crmod, "map CR on output", bool, NULLCP, NULLIFP,
685:
686: "debug", &debug, "debug VT", debug_val, NULLCP, set_debug,
687:
688: "echo", &echo, "local or remote echoing", emodes, NULLCP, set_echo,
689:
690: "escape", NULLIP, "escape character", &escapestr, NULLCP, set_escape,
691:
692: "options", &showoptions, "show option processing", bool, NULLCP, NULLIFP,
693:
694: "psaplevel", &_psap_log.ll_events, "PSAP logging", xsaplevels,
695: LLOG_MASK, NULLIFP,
696: "psapfile", NULLIP, "PSAP trace file", &_psap_log.ll_file, NULLCP,
697: NULLIFP,
698:
699: "psap2level", &_psap2_log.ll_events, "PSAP2 logging", xsaplevels,
700: LLOG_MASK, NULLIFP,
701: "psap2file", NULLIP, "PSAP2 trace file", &_psap2_log.ll_file, NULLCP,
702: NULLIFP,
703:
704: "repertoire", &repertoire, "terminal repertoire", rmodes, NULLCP,
705: set_repertoire,
706:
707: "ssaplevel", &_ssap_log.ll_events, "SSAP logging", xsaplevels,
708: LLOG_MASK, NULLIFP,
709: "ssapfile", NULLIP, "SSAP trace file", &_ssap_log.ll_file, NULLCP,
710: NULLIFP,
711:
712: "tracelevel", &_vt_log.ll_events, "VT logging", xsaplevels,
713: LLOG_MASK, NULLIFP,
714: "tracefile", NULLIP, "VT trace file", &_vt_log.ll_file, NULLCP,
715: NULLIFP,
716:
717: "tsaplevel", &_tsap_log.ll_events, "TSAP logging", xsaplevels,
718: LLOG_MASK, NULLIFP,
719: "tsapfile", NULLIP, "TSAP trace file", &_tsap_log.ll_file, NULLCP,
720: NULLIFP,
721:
722: "verbose", &verbose, "verbose interaction", bool, NULLCP, NULLIFP,
723:
724: NULL
725: };
726:
727:
728: static int varwidth1;
729: static int varwidth2;
730:
731: char **getval ();
732:
733: /* */
734:
735: static int vt_set (vec)
736: char **vec;
737: {
738: register int i,
739: j;
740: int value,
741: vflag;
742: register char **cp,
743: *dp;
744: register struct var *v;
745:
746: if (*++vec == NULL) {
747: register int w;
748: int columns,
749: width,
750: lines;
751: register struct var *u;
752:
753: for (u = vars; u -> v_name; u++)
754: continue;
755: width = varwidth1;
756:
757: if ((columns = ncols (stdout) / (width = (width + 8) & ~7)) == 0)
758: columns = 1;
759: lines = ((u - vars) + columns - 1) / columns;
760:
761: (void)printf ("Variables:\n");
762: for (i = 0; i < lines; i++)
763: for (j = 0; j < columns; j++) {
764: v = vars + j * lines + i;
765: (void)printf ("%s", v -> v_name);
766: if (v + lines >= u) {
767: (void)printf ("\n");
768: break;
769: }
770: for (w = strlen (v -> v_name); w < width; w = (w + 8) & ~7)
771: (void) putchar ('\t');
772: }
773:
774: return DONE;
775: }
776:
777: echo = (nego_state & ECHO_OBJ) ? 1 : 0;
778: repertoire = transparent ? 1 : 0;
779:
780: if (strcmp (*vec, "?") == 0) {
781: for (v = vars; v -> v_name; v++)
782: printvar (v);
783:
784: return DONE;
785: }
786:
787: if ((v = getvar (*vec)) == NULL)
788: return DONE;
789:
790: if (*++vec == NULL) {
791: printvar (v);
792:
793: return DONE;
794: }
795:
796: if (strcmp (*vec, "?") == 0) {
797: if (v -> v_value && (cp = v -> v_dvalue)) {
798: printf ("use %s of:", v -> v_mask ? "any" : "one");
799: for (i = 0; *cp; cp++)
800: printf ("%s \"%s\"", i++ ? "," : "", *cp);
801: if (v -> v_mask)
802: printf (";\n\tor \"all\";\n\tor a hexadecimal number from 0 to 0x%x\n",
803: (1 << (i - 1)) - 1);
804: else
805: printf (";\n\tor a number from 0 to %d\n",
806: cp - v -> v_dvalue - 1);
807: }
808: else
809: (void)printf ("use any %s value\n",
810: v -> v_value ? "integer" : "string");
811:
812: return DONE;
813: }
814:
815: if (v -> v_value == NULLIP) {
816: register int w;
817:
818: if (*v -> v_dvalue)
819: free (*v -> v_dvalue);
820: *v -> v_dvalue = strdup (*vec);
821: if ((w = strlen (*v -> v_dvalue) + 2) > varwidth2)
822: varwidth2 = w;
823: if (v -> v_hook)
824: (*v -> v_hook) (v);
825: if (verbose)
826: printvar (v);
827: return DONE;
828: }
829:
830: if (v -> v_mask) {
831: if (strcmp (dp = *vec, "all") == 0 && (cp = v -> v_dvalue)) {
832: i = 1;
833: while (*++cp)
834: i <<= 1;
835: value = i - 1;
836: j = 1;
837: }
838: else {
839: if (strncmp (dp = *vec, "0x", 2) == 0)
840: dp += 2;
841: for (j = sscanf (dp, "%x", &value); *dp; dp++)
842: if (!isxdigit (*dp)) {
843: j = 0;
844: break;
845: }
846: }
847: }
848: else
849: j = sscanf (*vec, "%d", &value);
850:
851: if (j == 1) {
852: if (cp = v -> v_dvalue) {
853: if (v -> v_mask) {
854: i = 1;
855: while (*++cp)
856: i <<= 1;
857: if (value >= i)
858: goto out_of_range;
859: }
860: else {
861: for (; *cp; cp++)
862: continue;
863: if (value >= cp - v -> v_dvalue) {
864: out_of_range: ;
865: advise (LLOG_NOTICE,NULLCP,
866: "value out of range \"%s\"", *vec);
867:
868: return DONE;
869: }
870: }
871: }
872:
873: vflag = verbose;
874: *v -> v_value = value;
875: if (v -> v_hook)
876: (*v -> v_hook) (v);
877: if (vflag)
878: printvar (v);
879:
880: return DONE;
881: }
882:
883: if (v -> v_mask) {
884: i = 0;
885: for (; *vec; vec++) {
886: if (!(cp = getval (*vec, v -> v_dvalue))) {
887: advise (LLOG_NOTICE,NULLCP, "bad value \"%s\"", *vec);
888:
889: return DONE;
890: }
891: if ((j = cp - v -> v_dvalue) <= 0)
892: continue;
893:
894: i |= 1 << (j - 1);
895: }
896:
897: vflag = verbose;
898: *v -> v_value = i;
899: if (v -> v_hook)
900: (*v -> v_hook) (v);
901: if (vflag)
902: printvar (v);
903:
904: return DONE;
905: }
906:
907: if (v -> v_dvalue && (cp = getval (*vec, v -> v_dvalue))) {
908: vflag = verbose;
909: *v -> v_value = cp - v -> v_dvalue;
910: if (v -> v_hook)
911: (*v -> v_hook) (v);
912: if (vflag)
913: printvar (v);
914: }
915: else
916: if (!v -> v_dvalue)
917: advise (LLOG_NOTICE,NULLCP, "bad value \"%s\"", *vec);
918:
919: return DONE;
920: }
921:
922: /* */
923:
924: static printvar (v)
925: register struct var *v;
926: {
927: int i;
928: char buffer[BUFSIZ];
929:
930: if (runcom)
931: return;
932:
933: (void)printf ("%-*s = ", varwidth1, v -> v_name);
934: if (v -> v_value) {
935: i = *v -> v_value;
936:
937: if (v -> v_mask) {
938: if (v -> v_dvalue) {
939: if (i == 0)
940: (void)printf ("%-*s", varwidth2, v -> v_dvalue[i]);
941: else {
942: (void) strcpy (buffer, sprintb (i, v -> v_mask));
943: if (strlen (buffer) <= varwidth2)
944: (void)printf ("%-*s", varwidth2, buffer);
945: else
946: (void)printf ("%s\n%*s", buffer, varwidth1 + varwidth2 + 3,
947: "");
948: }
949: }
950: else
951: (void)printf ("0x%-*x", varwidth2 - 2, i);
952: }
953: else {
954: if (v -> v_dvalue)
955: (void)printf ("%-*s", varwidth2, v -> v_dvalue[i]);
956: else
957: (void)printf ("%-*d", varwidth2, i);
958: }
959: }
960: else
961: if (*v -> v_dvalue) {
962: (void) sprintf (buffer, "\"%s\"", *v -> v_dvalue);
963: (void)printf ("%-*s", varwidth2, buffer);
964: }
965: (void)printf (" - %s\n", v -> v_dname);
966: }
967:
968: /* */
969:
970: /* ARGSUSED */
971:
972: static int set_debug (v)
973: struct var *v;
974: {
975: if (debug)
976: ll_dbinit (vt_log, myname);
977: else
978: vt_log -> ll_stat &= ~LLOGTTY;
979: }
980:
981:
982: /* ARGSUSED */
983:
984: static int set_echo (v)
985: struct var *v;
986: {
987: if (!connected) {
988: advise (LLOG_NOTICE,NULLCP, "not associated with terminal service");
989: return;
990: }
991:
992: vt_echo (echo);
993: }
994:
995:
996: /* ARGSUSED */
997:
998: static int set_escape (v)
999: struct var *v;
1000: {
1001: if (*escapestr) {
1002: char *cp = control (escape = *escapestr);
1003:
1004: free (escapestr);
1005: escapestr = strdup (cp);
1006: }
1007: }
1008:
1009:
1010: /* ARGSUSED */
1011:
1012: static int set_repertoire (v)
1013: struct var *v;
1014: {
1015: if (!connected) {
1016: advise (LLOG_NOTICE,NULLCP, "not associated with terminal service");
1017: return;
1018: }
1019:
1020: vt_repertoire (repertoire);
1021: }
1022:
1023: /* */
1024:
1025: static char **getval (name, choices)
1026: register char *name;
1027: char **choices;
1028: {
1029: register int longest,
1030: nmatches;
1031: register char *p,
1032: *q,
1033: **cp,
1034: **fp;
1035: char buffer[BUFSIZ];
1036:
1037: longest = nmatches = 0;
1038: for (cp = choices; p = *cp; cp++) {
1039: for (q = name; *q == *p++; q++)
1040: if (*q == NULL)
1041: return cp;
1042: if (*q == NULL)
1043: if (q - name > longest) {
1044: longest = q - name;
1045: nmatches = 1;
1046: fp = cp;
1047: }
1048: else
1049: if (q - name == longest)
1050: nmatches++;
1051: }
1052:
1053: switch (nmatches) {
1054: case 0:
1055: advise (LLOG_NOTICE,NULLCP, "unknown value \"%s\"", name);
1056: return NULL;
1057:
1058: case 1:
1059: return fp;
1060:
1061: default:
1062: for (cp = choices, p = buffer; q = *cp; cp++)
1063: if (strncmp (q, name, longest) == 0) {
1064: (void) sprintf (p, "%s \"%s\"", p != buffer ? "," : "", q);
1065: p += strlen (p);
1066: }
1067: advise (LLOG_NOTICE,NULLCP, "ambiguous value, it could be one of:%s",
1068: buffer);
1069: return NULL;
1070: }
1071: }
1072:
1073: /* */
1074:
1075: static struct var *getvar (name)
1076: register char *name;
1077: {
1078: register int longest,
1079: nmatches;
1080: register char *p,
1081: *q;
1082: char buffer[BUFSIZ];
1083: register struct var *v,
1084: *f;
1085:
1086: longest = nmatches = 0;
1087: for (v = vars; p = v -> v_name; v++) {
1088: for (q = name; *q == *p++; q++)
1089: if (*q == NULL)
1090: return v;
1091: if (*q == NULL)
1092: if (q - name > longest) {
1093: longest = q - name;
1094: nmatches = 1;
1095: f = v;
1096: }
1097: else
1098: if (q - name == longest)
1099: nmatches++;
1100: }
1101:
1102: switch (nmatches) {
1103: case 0:
1104: advise (LLOG_NOTICE,NULLCP, "unknown variable \"%s\"", name);
1105: return NULL;
1106:
1107: case 1:
1108: return f;
1109:
1110: default:
1111: for (v = vars, p = buffer; q = v -> v_name; v++)
1112: if (strncmp (q, name, longest) == 0) {
1113: (void) sprintf (p, "%s \"%s\"", p != buffer ? "," : "", q);
1114: p += strlen (p);
1115: }
1116: advise (LLOG_NOTICE,NULLCP,
1117: "ambiguous variable, it could be one of:%s", buffer);
1118: return NULL;
1119: }
1120: }
1121:
1122: /* HELP */
1123:
1124: static int helpwidth = 0;
1125:
1126:
1127: static int vt_help (vec)
1128: char **vec;
1129: {
1130: register int i,
1131: j,
1132: w;
1133: int columns,
1134: width,
1135: lines;
1136: register struct dispatch *ds,
1137: *es;
1138:
1139: for (es = dispatches; es -> ds_name; es++)
1140: continue;
1141: width = helpwidth;
1142:
1143: if (*++vec == NULL) {
1144: if ((columns = ncols (stdout) / (width = (width + 8) & ~7)) == 0)
1145: columns = 1;
1146: lines = ((es - dispatches) + columns - 1) / columns;
1147:
1148: (void)printf ("Operations:\n");
1149: for (i = 0; i < lines; i++)
1150: for (j = 0; j < columns; j++) {
1151: ds = dispatches + j * lines + i;
1152: (void)printf ("%s", ds -> ds_name);
1153: if (ds + lines >= es) {
1154: (void)printf ("\n");
1155: break;
1156: }
1157: for (w = strlen (ds -> ds_name); w < width; w = (w + 8) & ~7)
1158: (void) putchar ('\t');
1159: }
1160:
1161: (void)printf ("\n");
1162:
1163: return DONE;
1164: }
1165:
1166: for (; *vec; vec++)
1167: if (strcmp (*vec, "?") == 0) {
1168: for (ds = dispatches; ds -> ds_name; ds++)
1169: (void)printf ("%-*s\t- %s\n", width, ds -> ds_name, ds -> ds_help);
1170:
1171: break;
1172: }
1173: else
1174: if (ds = getds (*vec))
1175: (void)printf ("%-*s\t- %s\n", width, ds -> ds_name, ds -> ds_help);
1176:
1177: return DONE;
1178: }
1179:
1180:
1181: #ifndef TIOCGWINSZ
1182: /* ARGSUSED */
1183: #endif
1184:
1185: static int ncols (fp)
1186: FILE *fp;
1187: {
1188: #ifdef TIOCGWINSZ
1189: int i;
1190: struct winsize win;
1191:
1192: if (ioctl (fileno (fp), TIOCGWINSZ, (char *) &win) != NOTOK
1193: && (i = win.ws_col) > 0)
1194: return i;
1195: #endif
1196:
1197: return 80;
1198: }
1199:
1200: /* */
1201:
1202: char *strdup (s)
1203: char *s;
1204: {
1205: char *p;
1206:
1207: if ((p = malloc((unsigned) (strlen (s) + 1))) == NULL)
1208: adios (NULLCP, "out of memory");
1209:
1210: (void) strcpy (p, s);
1211:
1212: return p;
1213: }
1214:
1215: /* */
1216:
1217: static rcinit ()
1218: {
1219: register int w;
1220: register char **cp;
1221: register struct dispatch *ds;
1222: register struct var *v;
1223:
1224: if ((myhome = getenv ("HOME")) == NULL)
1225: myhome = "."; /* could do passwd search... */
1226:
1227: escapestr = strdup (control (escape));
1228: for (ds = dispatches, helpwidth = 0; ds -> ds_name; ds++)
1229: if ((w = strlen (ds -> ds_name)) > helpwidth)
1230: helpwidth = w;
1231:
1232: for (v = vars, varwidth1 = 0; v -> v_name; v++) {
1233: if ((w = strlen (v -> v_name)) > varwidth1)
1234: varwidth1 = w;
1235:
1236: if (v -> v_value) {
1237: if (cp = v -> v_dvalue) {
1238: if (v -> v_mask) {
1239: #ifdef notdef
1240: w = 1;
1241: while (*++cp)
1242: w <<= 1;
1243: w--;
1244: if ((w = strlen (sprintb (w, v -> v_mask))) > varwidth2)
1245: varwidth2 = w;
1246: #endif
1247: }
1248: else
1249: for (; *cp; cp++)
1250: if ((w = strlen (*cp)) > varwidth2)
1251: varwidth2 = w;
1252: }
1253: }
1254: else
1255: if (*v -> v_dvalue) {
1256: *v -> v_dvalue = strdup (*v -> v_dvalue);
1257: if ((w = strlen (*v -> v_dvalue) + 2) > varwidth2)
1258: varwidth2 = w;
1259: }
1260: }
1261: }
1262:
1263: char sibuf[BUFSIZ << 3], *sbp;
1264: char tibuf[BUFSIZ], *tbp;
1265: int tcc;
1266:
1267: /*
1268: * Select from tty and network...
1269: */
1270: vt(s)
1271: int s;
1272: {
1273: register int c;
1274: int tin = fileno(stdin), tout = fileno(stdout);
1275: int nfds, result;
1276:
1277: if ((nfds = (tin > tout ? tin : tout)) < s)
1278: nfds = s;
1279: nfds++;
1280:
1281: nego_state = 0;
1282: if(telnet_profile)
1283: {
1284: (void) tmode(2);
1285: vt_rem_echo(&ni_image); /*Request Remote Echo*/
1286: vt_sup_ga(&ni_image); /*Request Suppress Go Ahead*/
1287: repertoire = 1;
1288: vt_repertoire(repertoire);
1289: }
1290: else (void) tmode(1);
1291:
1292: for (;;) {
1293: fd_set ibits, obits;
1294:
1295: FD_ZERO (&ibits);
1296:
1297: FD_ZERO (&obits);
1298: FD_SET (tout, &obits);
1299: FD_SET (s, &obits);
1300:
1301: if (nfrontp - nbackp)
1302: FD_SET (s, &obits);
1303: else
1304: FD_SET (tin, &ibits);
1305:
1306: if (tfrontp - tbackp)
1307: FD_SET (tout, &obits);
1308: else
1309: FD_SET (s, &ibits);
1310: if (FD_ISSET (s, &ibits) && data_pending()) {
1311: FD_CLR (s, &ibits);
1312: result = xselect(nfds, &ibits, &obits,
1313: (fd_set *)NULL, OK);
1314: if (result == -1)
1315: adios ("failed", "xselect");
1316: FD_SET (s, &ibits);
1317: }
1318: else {
1319: result = xselect(nfds, &ibits, &obits,
1320: (fd_set *)NULL, NOTOK);
1321: if (result == -1)
1322: adios ("failed", "xselect");
1323: }
1324: if (!FD_ISSET (s, &ibits)
1325: && !FD_ISSET (tin, &ibits)
1326: && !FD_ISSET (s, &obits)
1327: && !FD_ISSET (tout, &obits)) {
1328: sleep(5);
1329: continue;
1330: }
1331:
1332: /*
1333: * Something to read from the network...
1334: */
1335: if (FD_ISSET (s, &ibits)) {
1336:
1337: while ( (c = getch()) > 0){
1338: *tfrontp++ = c;
1339: if(tfrontp >= &ttyobuf[TBUFSIZ-1]) break;
1340: }
1341:
1342: if (c == E_EOF) {
1343: break;
1344: }
1345: }
1346:
1347: /*
1348: * Something to read from the tty...
1349: */
1350: if (FD_ISSET (tin, &ibits)) {
1351: tcc = read(tin, tibuf, sizeof (tibuf));
1352: if (tcc < 0 && errno == EWOULDBLOCK)
1353: tcc = 0;
1354: else {
1355: if (tcc <= 0) {
1356: advise(LLOG_NOTICE,NULLCP, "error: read from terminal returned %d", tcc);
1357: break;
1358: }
1359: tbp = tibuf;
1360: }
1361: }
1362:
1363: while (tcc > 0) {
1364: register int ch;
1365:
1366: if ((&netobuf[BUFSIZ] - nfrontp) < 2)
1367: break;
1368: ch = *tbp++ & 0377, tcc--;
1369: if (strip(ch) == escape) {
1370: command(0);
1371: tcc = 0;
1372: break;
1373: }
1374: *nfrontp++ = ch;
1375: }
1376: if (FD_ISSET (s, &obits) && (nfrontp - nbackp) > 0)
1377: netflush(s);
1378: if (FD_ISSET (tout, &obits) && (tfrontp - tbackp) > 0)
1379: ttyflush(tout);
1380: }
1381: (void) tmode(0);
1382: }
1383:
1384: /*
1385: * Construct a control character sequence
1386: * for a special character.
1387: */
1388: char *
1389: control(c)
1390: register int c;
1391: {
1392: static char buf[3];
1393:
1394: if (c == 0177)
1395: return ("^?");
1396: if (c >= 040) {
1397: buf[0] = c;
1398: buf[1] = 0;
1399: } else {
1400: buf[0] = '^';
1401: buf[1] = '@'+c;
1402: buf[2] = 0;
1403: }
1404: return (buf);
1405: }
1406:
1407: SFD deadpeer()
1408: {
1409: (void) tmode(0);
1410: longjmp(peerdied, -1);
1411: }
1412:
1413: SFD intr()
1414: {
1415: (void) tmode(0);
1416: longjmp(toplevel, -1);
1417: }
1418:
1419: ttyflush(dd)
1420: int dd;
1421: {
1422: int n;
1423:
1424: if ((n = tfrontp - tbackp) > 0) {
1425:
1426: n = write(dd, tbackp, n);
1427:
1428: }
1429: if (n < 0)
1430: {
1431: advise(LLOG_NOTICE,NULLCP, "ttyflush(): Negative returned from write");
1432: return;
1433: }
1434: tbackp += n;
1435: if (tbackp == tfrontp)
1436: tbackp = tfrontp = ttyobuf;
1437: }
1438:
1439: netflush(dd)
1440: int dd;
1441: {
1442: register char *cp;
1443: int n, i, j;
1444: int nl_flag; /*If current PDU includes newline, follow it
1445: with a Deliver Request*/
1446:
1447: nl_flag = 0;
1448: if ((n = nfrontp - nbackp) > 0) {
1449: if(transparent)
1450: {
1451: if (vt_text(nbackp,n) != OK)
1452: advise(LLOG_NOTICE,NULLCP, "vt_text failed");
1453: vtsend();
1454: cp = nbackp;
1455: for(i=0; i<n; i++)
1456: {
1457: if( (*cp == '\r') ||
1458: (*cp == '\n') )
1459: {
1460: vdelreq(FALSE);
1461: break;
1462: }
1463: ++cp;
1464: }
1465: nbackp += n;
1466: }
1467: else
1468: {
1469: cp = nbackp;
1470: for(i=0,j=0; i<n; i++)
1471: {
1472: if(*cp == '\r')
1473: {
1474: if(j)
1475: if (vt_text(nbackp,j) != OK)
1476: advise(LLOG_NOTICE,NULLCP, "vt_text failed");
1477: nbackp += (j+1);
1478: cp = nbackp;
1479: j = 0;
1480: rflag = 1;
1481: vt_newline();
1482: ++nl_flag;
1483: }
1484: else if(*cp == '\n')
1485: {
1486: if(!rflag) /*If preceeding char was not CR*/
1487: {
1488: if(j)
1489: if (vt_text(nbackp,j) != OK)
1490: advise(LLOG_NOTICE,NULLCP, "vt_text failed");
1491: nbackp += (j+1);
1492: cp = nbackp;
1493: j = 0;
1494: vt_newline();
1495: ++nl_flag;
1496: }
1497: else /*Preceeding char was CR so already sent
1498: the Update. Remove this LF from buffer*/
1499: {
1500: ++nbackp;
1501: ++cp;
1502: rflag = 0;
1503: }
1504: }
1505: else if(telnet_profile)
1506: {
1507: rflag = 0;
1508: if(*cp == erase_char)
1509: {
1510: if(j)
1511: if (vt_text(nbackp,j) != OK)
1512: advise(LLOG_NOTICE,NULLCP, "vt_text failed");
1513: nbackp += (j+1);
1514: cp = nbackp;
1515: j = 0;
1516: vt_char_erase();
1517: }
1518: else if(*cp == erase_line)
1519: {
1520: if(j)
1521: if (vt_text(nbackp,j) != OK)
1522: advise(LLOG_NOTICE,NULLCP, "vt_text failed");
1523: nbackp += (j+1);
1524: cp = nbackp;
1525: j = 0;
1526: vt_line_erase();
1527: }
1528: else if(*cp == intr_char)
1529: {
1530: if(j)
1531: if (vt_text(nbackp,j) != OK)
1532: advise(LLOG_NOTICE,NULLCP, "vt_text failed");
1533: nbackp += (j+1);
1534: cp = nbackp;
1535: j = 0;
1536: vt_interrupt();
1537: }
1538: else if(!vtp_profile.arg_val.tel_arg_list.full_ascii)
1539: /*If ASCII GO, dump ctrl chars*/
1540: {
1541: if((*cp < 0x20) || (*cp > 0x7e))
1542: {
1543: if(j)
1544: if (vt_text(nbackp,j) != OK)
1545: advise(LLOG_NOTICE,NULLCP, "vt_text failed");
1546: nbackp += (j+1);
1547: cp = nbackp;
1548: j = 0;
1549: }
1550: else
1551: {
1552: ++j;
1553: ++cp;
1554: }
1555: }
1556: else
1557: {
1558: ++j;
1559: ++cp;
1560: }
1561: }
1562: else /*Else Default Profile*/
1563: {
1564: if((*cp < 0x20) || (*cp > 0x7e))
1565: {
1566: if(j)
1567: if (vt_text(nbackp,j) != OK)
1568: advise(LLOG_NOTICE,NULLCP, "vt_text failed");
1569: nbackp += (j+1);
1570: cp = nbackp;
1571: j = 0;
1572: }
1573: else
1574: {
1575: ++j; ++cp;
1576: }
1577: }
1578: } /*End for loop*/
1579: if(j)
1580: if (vt_text(nbackp,j) != OK) /*Load anything left if CR or LF
1581: wasn't last char in buffer*/
1582: advise(LLOG_NOTICE,NULLCP, "vt_text failed");
1583: nbackp += j;
1584: vtsend(); /*Send the whole NDQ*/
1585: if(nl_flag && telnet_profile) vdelreq(FALSE);
1586: rflag = 0;
1587: }
1588:
1589: }
1590: if (n < 0) {
1591: if (errno != ENOBUFS && errno != EWOULDBLOCK) {
1592: (void) tmode(0);
1593: perror(peerhost);
1594: (void)close(dd);
1595: longjmp(peerdied, -1);
1596: /*NOTREACHED*/
1597: }
1598: n = 0;
1599: }
1600: if (nbackp == nfrontp)
1601: nbackp = nfrontp = netobuf;
1602: }
1603:
1604: flushbufs()
1605: {
1606: tcc = 0;
1607: tbp = tibuf;
1608: nfrontp = nbackp = netobuf;
1609: while (getch() > 0)
1610: continue;
1611: tfrontp = tbackp = ttyobuf;
1612: }
1613:
1614: /* ERRORS */
1615:
1616: void finalbye ()
1617: {
1618: (void) tmode (0);
1619: }
1620:
1621:
1622: #ifndef lint
1623: void adios (va_alist)
1624: va_dcl
1625: {
1626: int code;
1627: va_list ap;
1628: static int latched = 0;
1629:
1630: va_start (ap);
1631:
1632: code = va_arg (ap, int);
1633:
1634: (void) _ll_log (vt_log, code, ap);
1635:
1636: va_end (ap);
1637:
1638: if (connected && latched++ == 0)
1639: (void) vt_close (NULLVP);
1640:
1641: _exit (1);
1642: }
1643: #else
1644: /* VARARGS2 */
1645:
1646: void adios (what, fmt)
1647: char *what,
1648: *fmt;
1649: {
1650: adios (what, fmt);
1651: }
1652: #endif
1653:
1654:
1655: #ifndef lint
1656: void advise (va_alist)
1657: va_dcl
1658: {
1659: int code,
1660: flags;
1661: char buffer[BUFSIZ];
1662: va_list ap;
1663:
1664: va_start (ap);
1665:
1666: code = va_arg (ap, int);
1667:
1668: asprintf (buffer, ap);
1669:
1670: flags = vt_log -> ll_stat;
1671:
1672: if (code & (LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE)) {
1673: (void) fflush (stdout);
1674:
1675: fprintf (stderr, "%s: ", myname);
1676: (void) fputs (buffer, stderr);
1677: (void) fputc ('\n', stderr);
1678:
1679: (void) fflush (stderr);
1680:
1681: vt_log -> ll_stat &= ~LLOGTTY;
1682: }
1683:
1684: (void) ll_log (vt_log, code, NULLCP, "%s", buffer);
1685:
1686: vt_log -> ll_stat = flags;
1687:
1688: va_end (ap);
1689: }
1690: #else
1691: /* VARARGS3 */
1692:
1693: void advise (code, what, fmt)
1694: int code;
1695: char *what,
1696: *fmt;
1697: {
1698: advise (code, what, fmt);
1699: }
1700: #endif
1701:
1702: /* XXX -- why is this stubbed ? */
1703: #ifdef BSD44
1704: ptyecho(on)
1705: {
1706: }
1707: #else
1708: /*ARGSUSED*/
1709: setmode(on, off)
1710: {
1711: }
1712: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.