BSD 4_3_Net_2 development
[unix-history] / usr / src / contrib / isode / snmp / snmpi.c
CommitLineData
b62cce74
C
1/* snmpi.c - really minimal SNMP initiator */
2
3#ifndef lint
4static char *rcsid = "$Header: /f/osi/snmp/RCS/snmpi.c,v 7.28 91/03/09 11:57:50 mrose Exp $";
5#endif
6
7/*
8 * $Header: /f/osi/snmp/RCS/snmpi.c,v 7.28 91/03/09 11:57:50 mrose Exp $
9 *
10 * Contributed by NYSERNet Inc. This work was partially supported by the
11 * U.S. Defense Advanced Research Projects Agency and the Rome Air Development
12 * Center of the U.S. Air Force Systems Command under contract number
13 * F30602-88-C-0016.
14 *
15 *
16 * $Log: snmpi.c,v $
17 * Revision 7.28 91/03/09 11:57:50 mrose
18 * update
19 *
20 * Revision 7.27 91/02/22 09:44:34 mrose
21 * Interim 6.8
22 *
23 * Revision 7.26 91/01/11 15:35:28 mrose
24 * sets
25 *
26 * Revision 7.25 91/01/07 12:41:08 mrose
27 * update
28 *
29 * Revision 7.24 90/10/23 20:37:09 mrose
30 * update
31 *
32 * Revision 7.23 90/09/26 19:23:02 mrose
33 * new-mibs
34 *
35 * Revision 7.22 90/09/26 18:47:18 mrose
36 * more-compile
37 *
38 * Revision 7.21 90/09/26 14:57:48 mrose
39 * compile -f
40 *
41 * Revision 7.20 90/09/07 11:11:39 mrose
42 * update
43 *
44 * Revision 7.19 90/09/03 12:58:04 mrose
45 * update
46 *
47 * Revision 7.18 90/08/30 15:11:11 mrose
48 * ho-hum
49 *
50 * Revision 7.17 90/08/30 01:32:05 mrose
51 * update
52 *
53 * Revision 7.16 90/08/20 21:25:52 mrose
54 * touch-up
55 *
56 * Revision 7.15 90/08/16 17:01:13 mrose
57 * touch-up
58 *
59 * Revision 7.14 90/08/08 14:01:31 mrose
60 * stuff
61 *
62 * Revision 7.13 90/07/09 14:49:34 mrose
63 * sync
64 *
65 * Revision 7.12 90/06/23 18:25:14 mrose
66 * now
67 *
68 * Revision 7.11 90/06/23 17:01:55 mrose
69 * update
70 *
71 * Revision 7.10 90/05/12 17:02:09 mrose
72 * sync
73 *
74 * Revision 7.9 90/02/23 17:47:59 mrose
75 * update
76 *
77 * Revision 7.8 90/02/19 19:17:05 mrose
78 * again
79 *
80 * Revision 7.7 90/01/27 08:22:04 mrose
81 * touch-up
82 *
83 * Revision 7.6 90/01/11 18:34:43 mrose
84 * real-sync
85 *
86 * Revision 7.5 89/12/19 17:57:56 mrose
87 * touch-up
88 *
89 * Revision 7.4 89/12/19 16:18:26 mrose
90 * dgram
91 *
92 * Revision 7.3 89/12/12 16:13:47 mrose
93 * touch-up
94 *
95 * Revision 7.2 89/12/11 16:22:33 mrose
96 * more clts
97 *
98 * Revision 7.1 89/12/01 10:42:18 mrose
99 * clts
100 *
101 * Revision 7.0 89/11/23 22:23:30 mrose
102 * Release 6.0
103 *
104 */
105
106/*
107 * NOTICE
108 *
109 * Acquisition, use, and distribution of this module and related
110 * materials are subject to the restrictions of a license agreement.
111 * Consult the Preface in the User's Manual for the full terms of
112 * this agreement.
113 *
114 */
115
116
117#include <setjmp.h>
118#include <signal.h>
119#include <stdio.h>
120#include <varargs.h>
121#include "SNMP-types.h"
122#include "objects.h"
123#include <sys/ioctl.h>
124#include "tailor.h"
125
126#include "dgram.h"
127#include "tsap.h"
128#ifdef TCP
129#include "internet.h"
130#endif
131#ifdef X25
132#include "x25.h"
133#define COTS
134#endif
135#ifdef TP4
136#include "tp4.h"
137#if !defined(CLTS) && !defined(COTS)
138#define COTS
139#endif
140#endif
141
142/* \f DATA */
143
144int debug = 0;
145static int verbose = 0;
146int watch = 0;
147
148static char *myname = "snmp";
149
150static char **op = NULLVP;
151
152static int ontty;
153static int armed;
154static jmp_buf intrenv;
155static int interrupted;
156
157static SFP istat;
158
159SFD intrser ();
160
161
162static char *defs = NULLCP;
163
164static PS ps;
165static char *community = "public";
166
167static int sd;
168static struct TSAPaddr snmp_ta;
169
170char *snmp_error ();
171struct type_SNMP_Message *new_message ();
172
173
174void adios (), advise ();
175
176/* \f */
177
178struct dispatch {
179 char *ds_name; /* command name */
180 IFP ds_fnx; /* dispatch */
181
182 char *ds_help; /* help string */
183};
184struct dispatch *getds ();
185
186
187int f_audit ();
188#ifdef BSD42
189int f_bulk ();
190#endif
191int f_compile (), f_dump ();
192int f_get (), f_get_next (), f_set ();
193int f_help (), f_quit (), f_status ();
194
195static struct dispatch dispatches[] = {
196 "audit", f_audit, "audit traps",
197
198#ifdef BSD42
199 "bulk", f_bulk, "bulk retrieve colums from a table",
200#endif
201
202 "compile", f_compile, "write compiled objects file",
203
204 "dump", f_dump, "dump a portion of the MIB",
205
206 "get", f_get, "perform get operation",
207
208 "help", f_help, "print help information",
209
210 "next", f_get_next, "perform powerful get-next operation",
211
212 "quit", f_quit, "terminate program",
213
214 "set", f_set, "perform set operation",
215
216 "status", f_status, "report status",
217
218 NULL
219};
220
221
222static int helpwidth;
223
224
225#ifndef SYS5
226long random ();
227#endif
228long time ();
229
230/* \f MAIN */
231
232/* ARGSUSED */
233
234main (argc, argv, envp)
235int argc;
236char **argv,
237 **envp;
238{
239 int eof,
240 status,
241 vecp;
242 char buffer[BUFSIZ],
243 *vec[NVEC + 1];
244
245 arginit (argv);
246
247 status = 0;
248 if (op) {
249 vecp = 0;
250 while (*op)
251 vec[vecp++] = *op++;
252 vec[vecp] = NULL;
253
254 if (snmploop (vec, NOTOK) == NOTOK)
255 status = 1;
256
257 goto were_out_of_here;
258 }
259
260 istat = signal (SIGINT, intrser);
261
262 eof = 0;
263 for (interrupted = 0;; interrupted = 0) {
264 if (getline ("%s> ", buffer) == NOTOK) {
265 if (eof)
266 break;
267
268 eof = 1;
269 continue;
270 }
271 eof = 0;
272
273 bzero ((char *) vec, sizeof vec);
274 if ((vecp = str2vec (buffer, vec)) < 1)
275 continue;
276
277 switch (snmploop (vec, OK)) {
278 case NOTOK:
279 status = 1;
280 break;
281
282 case OK:
283 default:
284 continue;
285
286 case DONE:
287 status = 0;
288 break;
289 }
290 break;
291 }
292
293 (void) signal (SIGINT, istat);
294
295were_out_of_here: ;
296#ifdef COTS
297 if (snmp_ta.ta_addrs -> na_stack != NA_TCP) {
298 struct TSAPdisconnect tds;
299
300#ifdef CLTS
301 if (snmp_ta.ta_addrs -> na_stack != NA_NSAP)
302#endif
303 (void) TDiscRequest (sd, NULLCP, 0, &tds);
304 }
305#endif
306
307 exit (status); /* NOTREACHED */
308}
309
310/* \f */
311
312static int snmploop (vec, error)
313char **vec;
314int error;
315{
316 register struct dispatch *ds;
317
318 if ((ds = getds (strcmp (*vec, "?") ? *vec : "help")) == NULL)
319 return error;
320 switch ((*ds -> ds_fnx) (vec)) {
321 case NOTOK:
322 return error;
323
324 case OK:
325 default:
326 return OK;
327
328 case DONE:
329 return DONE;
330 }
331}
332
333/* \f */
334
335static struct dispatch *getds (name)
336char *name;
337{
338 register int longest,
339 nmatches;
340 register char *p,
341 *q;
342 char buffer[BUFSIZ];
343 register struct dispatch *ds,
344 *fs;
345
346 longest = nmatches = 0;
347 for (ds = dispatches; p = ds -> ds_name; ds++) {
348 for (q = name; *q == *p++; q++)
349 if (*q == NULL)
350 return ds;
351
352 if (*q == NULL)
353 if (q - name > longest) {
354 longest = q - name;
355 nmatches = 1;
356 fs = ds;
357 }
358 else
359 if (q - name == longest)
360 nmatches++;
361 }
362
363 switch (nmatches) {
364 case 0:
365 advise (NULLCP, "unknown operation \"%s\"", name);
366 return NULL;
367
368 case 1:
369 return fs;
370
371 default:
372 for (ds = dispatches, p = buffer; q = ds -> ds_name; ds++)
373 if (strncmp (q, name, longest) == 0) {
374 (void) sprintf (p, "%s \"%s\"", p != buffer ? "," : "", q);
375 p += strlen (p);
376 }
377 advise (NULLCP, "ambiguous operation, it could be one of:%s",
378 buffer);
379 return NULL;
380 }
381}
382
383/* \f OPERATIONS */
384
385static int f_audit (vec)
386char **vec;
387{
388 int follow,
389 forever,
390 i;
391 long longtimeago,
392 now;
393 char *cp,
394 *file;
395 PE pe,
396 p;
397 PS ps2;
398 struct type_SNMP_Audit *au;
399 FILE *fp;
400
401 file = "snmp.traps";
402 if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
403 printf ("audit [-f | -N | +N] [file]\n");
404 printf (" audit trap sink\n");
405 printf (" -f: endless loop\n");
406 printf (" -N: last N traps\n");
407 printf (" +N: first N traps\n");
408 printf (" file: trap file (default %s)\n", file);
409
410 return OK;
411 }
412
413 follow = forever = 0;
414 for (; cp = *vec; vec++)
415 switch (*cp) {
416 case '-':
417 if (strcmp (cp, "-f") == 0)
418 forever++, follow = 0;
419 else
420 follow = -atoi (++cp), forever = 0;
421 break;
422
423 case '+':
424 follow = atoi (++cp), forever = 0;
425 break;
426
427 default:
428 file = cp;
429 break;
430 }
431
432 file = _isodefile (isodelogpath, file);
433 if ((fp = fopen (file, "r")) == NULL) {
434 advise (file, "unable to read");
435 return OK;
436 }
437
438 pe = p = NULLPE, au = NULL;
439 if ((ps2 = ps_alloc (std_open)) == NULLPS) {
440 advise (NULLCP, "ps_alloc(std_open): you lose");
441 goto out;
442 }
443 if (std_setup (ps2, fp) == NOTOK) {
444 advise (NULLCP, "std_setup: %s", ps_error (ps2 -> ps_errno));
445 goto out;
446 }
447
448 (void) time (&now);
449 longtimeago = now - 6L * 30L * 24L * 60L * 60L;
450
451 if (follow < 0) {
452 register long offset,
453 *lp,
454 *ep;
455 long *opp;
456
457 follow = -follow;
458 if ((opp = (long *) calloc ((unsigned) follow, sizeof *opp)) == NULL)
459 adios (NULLCP, "out of memory");
460 offset = ftell (fp);
461 for (ep = (lp = opp) + follow; lp < ep; lp++)
462 *lp = offset;
463 lp = opp;
464
465 for (;;) {
466 if ((pe = ps2pe (ps2)) == NULLPE)
467 break;
468 if (decode_SNMP_Audit (pe, 1, NULLIP, NULLVP, &au) == NOTOK)
469 goto bad_audit;
470
471 fseek (fp, (long) au -> sizeOfEncodingWhichFollows, 1);
472
473 free_SNMP_Audit (au);
474
475 *lp++ = offset;
476 if (lp >= ep)
477 lp = opp;
478 offset = ftell (fp);
479 }
480
481 fseek (fp, *lp, 0);
482 free ((char *) opp);
483 follow = 0;
484 }
485
486 for (i = 1;; i++) {
487 long mtime;
488 UTC ut;
489
490 if (follow > 0 && i > follow)
491 break;
492
493 if ((pe = ps2pe (ps2)) == NULLPE) {
494 if (ps2 -> ps_errno)
495 advise (NULLCP, "ps2pe: %s", ps_error (ps2 -> ps_errno));
496 else
497 if (forever) {
498 clearerr (fp);
499 ps2 -> ps_errno = PS_ERR_NONE;
500 sleep (1);
501 continue;
502 }
503 break;
504 }
505 if (decode_SNMP_Audit (pe, 1, NULLIP, NULLVP, &au) == NOTOK) {
506bad_audit: ;
507 advise (NULLCP, "decode_SNMP_Audit: %s", PY_pepy);
508 break;
509 }
510
511 if ((cp = qb2str (au -> dateAndTime)) == NULL) {
512no_mem: ;
513 advise (NULLCP, "qb2str: out of memory");
514 break;
515 }
516 ut = str2gent (cp, strlen (cp));
517 free (cp);
518 if (ut == NULL) {
519 advise (NULLCP, "str2gent: you lose");
520 break;
521 }
522 mtime = gtime (ut2tm (ut));
523 cp = ctime (&mtime);
524 if (forever)
525 (void) time (&now);
526 if (mtime < longtimeago || mtime > now)
527 printf ("%-7.7s %-4.4s ", cp + 4, cp + 20);
528 else
529 printf ("%-12.12s ", cp + 4);
530
531 if ((cp = qb2str (au -> source)) == NULL)
532 goto no_mem;
533 printf ("%s\n", cp);
534 free (cp);
535
536 if ((p = ps2pe (ps2)) == NULLPE) {
537 if (ps2 -> ps_errno)
538 advise (NULLCP, "ps2pe: %s", ps_error (ps2 -> ps_errno));
539 break;
540 }
541 if (print_SNMP_Message (p, 1, NULLIP, NULLVP, NULLCP) == NOTOK)
542 printf ("\n");
543
544 free_SNMP_Audit (au), au = NULL;
545 }
546
547out: ;
548 (void) fclose (fp);
549 if (ps2)
550 ps_free (ps2);
551 if (pe)
552 pe_free (pe);
553 if (p)
554 pe_free (p);
555 if (au)
556 free_SNMP_Audit (au);
557
558 return OK;
559}
560
561/* \f */
562
563#ifdef BSD42
564int bulk1 (), bulk2 ();
565
566static int f_bulk (vec)
567char **vec;
568{
569 int result;
570 IFP fnx = bulk1;
571 register struct type_SNMP_VarBindList **vp;
572 struct type_SNMP_VarBindList *vb;
573 OT et = NULL;
574
575 if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
576 printf ("bulk [-alg1 | -alg2] columns...\n");
577 printf (" with arguments, bulk retrieves columns from a table\n");
578
579 return OK;
580 }
581 while (*vec) {
582 if (strcmp (*vec, "-alg1") == 0) {
583 fnx = bulk1;
584 vec++;
585 continue;
586 }
587 if (strcmp (*vec, "-alg2") == 0) {
588 fnx = bulk2;
589 vec++;
590 continue;
591 }
592 break;
593 }
594 if (*vec == NULL)
595 return OK;
596
597#ifdef COTS
598 if (snmp_ta.ta_addrs -> na_stack != NA_TCP) {
599#ifdef CLTS
600 if (snmp_ta.ta_addrs -> na_stack != NA_NSAP) {
601#endif
602 advise (NULLCP, "bulk requires CL-mode transport!");
603 return NOTOK;
604#ifdef CLTS
605 }
606#endif
607 }
608#endif
609
610 vp = &vb, vb = NULL;
611 for (result = NOTOK; *vec; vec++) {
612 register struct type_SNMP_VarBindList *bind;
613 register struct type_SNMP_VarBind *v;
614 OT ot;
615
616 if ((ot = text2obj (*vec)) == NULL) {
617 advise (NULLCP, "unknown object \"%s\"", *vec);
618 goto out;
619 }
620
621 if (et) {
622 register OID eid = et -> ot_name,
623 oid = ot -> ot_name;
624
625 if (eid -> oid_nelem != oid -> oid_nelem - 1
626 || bcmp ((char *) eid -> oid_elements,
627 (char *) oid -> oid_elements,
628 eid -> oid_nelem
629 * sizeof (eid -> oid_elements[0])) != 0) {
630 advise (NULLCP, "%s not in same table as previous arguments",
631 ot -> ot_text);
632 goto out;
633 }
634 }
635 else {
636/* int i; */
637
638 ot -> ot_name -> oid_nelem--;
639 et = name2obj (ot -> ot_name);
640 ot -> ot_name -> oid_nelem++;
641
642 if (et == NULL) {
643 advise (NULLCP, "unable to find row object for %s",
644 ot -> ot_text);
645 goto out;
646 }
647 if (et -> ot_syntax
648 /* || (i = strlen (et -> ot_text)) <= 5
649 || strcmp (et -> ot_text + i - 5, "Entry")*/) {
650 advise (NULLCP, "%s is not a column object", ot -> ot_text);
651 goto out;
652 }
653 }
654
655 if ((bind = (struct type_SNMP_VarBindList *) calloc (1, sizeof *bind))
656 == NULL)
657 adios (NULLCP, "out of memory");
658 *vp = bind, vp = &bind -> next;
659
660 if ((v = (struct type_SNMP_VarBind *) calloc (1, sizeof *v)) == NULL)
661 adios (NULLCP, "out of memory");
662 bind -> VarBind = v;
663
664 if ((v -> name = oid_cpy (ot -> ot_name)) == NULLOID
665 || (v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM,
666 PE_PRIM_NULL)) == NULLPE)
667 adios (NULLCP, "out of memory");
668 }
669
670 (*fnx) (ps, sd, vb, community);
671 result = OK;
672
673out: ;
674 free_SNMP_VarBindList (vb);
675 return result;
676}
677#endif
678
679/* \f */
680
681static char *access_t[] = { "not-accessible",
682 "read-only",
683 "write-only",
684 "read-write"};
685
686static char *status_t[] = { "obsolete",
687 "mandatory",
688 "optional",
689 "deprecated" };
690
691
692static int f_compile (vec)
693char **vec;
694{
695 register int i;
696 int fast;
697 char *cp,
698 *file;
699 register OS os;
700 register OT ot;
701 FILE *fp;
702
703 fast = 0;
704 file = defs ? defs : "./objects.defs";
705 if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
706 printf ("compile [-f] [file]\n");
707 printf (" -f: brief output (default to stdout)\n");
708 printf (" file: output file (default %s)\n", file);
709
710 return OK;
711 }
712 while (cp = *vec++) {
713 if (strcmp (cp, "-f") == 0) {
714 fast = 1, file = NULLCP;
715 continue;
716 }
717
718 file = cp;
719 }
720
721 if (file) {
722 if ((fp = fopen (file, "w")) == NULL) {
723 advise (file, "unable to write");
724 return OK;
725 }
726 if (!fast) {
727 register int j,
728 k;
729
730 i = j = k = 0;
731 for (ot = text2obj ("ccitt"); ot; ot = ot -> ot_next) {
732 i++;
733 j += strlen (ot -> ot_text)
734 + strlen (sprintoid (ot -> ot_name));
735 k += ot -> ot_name -> oid_nelem;
736 }
737 j += i << 1, k += i;
738 fprintf (fp, "--* compiled %d %d %d\n", i, j, k);
739 }
740 }
741 else
742 fp = stdout;
743
744 for (ot = text2obj ("ccitt"); ot; ot = ot -> ot_next) {
745 if (fast) {
746 fprintf (fp, "%s=%s\n", ot -> ot_text, sprintoid (ot -> ot_name));
747 continue;
748 }
749
750 fprintf (fp, "%-20s %-20s", ot -> ot_text, sprintoid (ot -> ot_name));
751 if ((os = ot -> ot_syntax) || ot -> ot_status)
752 fprintf (fp, " %-15s %-15s %s",
753 os ? os -> os_name : "Aggregate",
754 access_t[ot -> ot_access & OT_RDWRITE],
755 status_t[ot -> ot_status & OT_DEPRECATED]);
756 fprintf (fp, "\n");
757 }
758
759 if (file)
760 (void) fclose (fp);
761
762 if (!fast)
763 advise (NULLCP, "%d objects written to %s", i, file);
764
765 return OK;
766}
767
768/* \f */
769
770static int f_dump (vec)
771char **vec;
772{
773 int request_id,
774 rows,
775 timing = 0;
776 char *nvec[3];
777 OID oid;
778 PE pe;
779 struct type_SNMP_Message *msg;
780 register struct type_SNMP_PDU *parm;
781 register struct type_SNMP_VarBindList *vp;
782 struct timeval tvs,
783 now;
784
785 if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
786 printf ("dump [object]\n");
787 printf (" with no arguments, dump entire MIB\n");
788 printf (" with an argument, dump a portion of the MIB\n");
789
790 return OK;
791 }
792 if (*vec && strcmp (*vec, "-time") == 0) {
793 timing++;
794 (void) gettimeofday (&tvs, (struct timezone *) 0);
795 vec++;
796 }
797
798 nvec[0] = "dump";
799 nvec[1] = *vec ? *vec : "0.0";
800 nvec[2] = NULL;
801
802 if ((msg = new_message (type_SNMP_PDUs_get__next__request, nvec)) == NULL)
803 return OK;
804
805 request_id = msg -> data -> un.get__response -> request__id = 0;
806
807 if (*vec) {
808 if ((oid = oid_cpy (msg -> data -> un.get__next__request ->
809 variable__bindings -> VarBind -> name)) == NULLOID)
810 adios (NULLCP, "out of memory");
811 }
812 else
813 oid = NULLOID;
814 rows = 0;
815
816again: ;
817 pe = NULLPE;
818
819 if (encode_SNMP_Message (&pe, 1, 0, NULLCP, msg) != NOTOK) {
820 if (watch)
821 (void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);
822
823 if (pe2ps (ps, pe) == NOTOK) {
824 advise (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno));
825 goto out;
826 }
827 }
828 else
829 advise (NULLCP, "encode_SNMP_Message: %s", PY_pepy);
830
831try_again: ;
832 if (pe)
833 pe_free (pe);
834 pe = NULLPE;
835
836 free_SNMP_Message (msg);
837 msg = NULL;
838
839 if ((pe = ps2pe (ps)) == NULLPE) {
840 advise (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno));
841 goto out;
842 }
843
844 if (decode_SNMP_Message (pe, 1, NULLIP, NULLVP, &msg) == NOTOK) {
845 advise (NULLCP, "decode_SNMP_Message: %s", PY_pepy);
846 goto out;
847 }
848
849 if (watch)
850 (void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);
851
852 if (msg -> data -> offset != type_SNMP_PDUs_get__response) {
853 advise (NULLCP, "unexpected message type %d",
854 msg -> data -> offset);
855 goto out;
856 }
857
858 if ((parm = msg -> data -> un.get__response) -> request__id
859 != request_id) {
860 fprintf (stderr, "request-id mismatch (got %d, wanted %d)\n",
861 parm -> request__id, request_id);
862 goto try_again;
863 }
864
865 if (parm -> error__status != int_SNMP_error__status_noError) {
866 if (parm -> error__status != int_SNMP_error__status_noSuchName)
867 fprintf (stderr, "%s at position %d\n",
868 snmp_error (parm -> error__status), parm -> error__index);
869 goto out;
870 }
871
872 for (vp = parm -> variable__bindings; vp; vp = vp -> next) {
873 caddr_t value;
874 register OI oi;
875 register OS os;
876 register struct type_SNMP_VarBind *v = vp -> VarBind;
877
878 if (oid
879 && (oid -> oid_nelem > v -> name -> oid_nelem
880 || bcmp ((char *) oid -> oid_elements,
881 (char *) v -> name -> oid_elements,
882 oid -> oid_nelem
883 * sizeof oid -> oid_elements[0])))
884 goto out;
885
886 if (timing)
887 continue;
888
889 printf ("%s=", oid2ode (vp -> VarBind -> name));
890 if ((oi = name2inst (v -> name)) == NULL
891 || (os = oi -> oi_type -> ot_syntax) == NULL
892 || (*os -> os_decode) (&value, v -> value) == NOTOK)
893 vunknown (v -> value);
894 else {
895 (*os -> os_print) (value, os);
896 printf ("\n");
897
898 (*os -> os_free) (value);
899 }
900 }
901 rows++;
902
903 if (pe)
904 pe_free (pe);
905 msg -> data -> offset = type_SNMP_PDUs_get__next__request;
906 request_id = ++parm -> request__id;
907 goto again;
908
909out: ;
910 if (oid)
911 oid_free (oid);
912 if (pe)
913 pe_free (pe);
914 if (msg)
915 free_SNMP_Message (msg);
916
917 if (timing) {
918 (void) gettimeofday (&now, (struct timezone *) 0);
919 now.tv_sec -= tvs.tv_sec;
920 if ((now.tv_usec -= tvs.tv_usec) < 0)
921 now.tv_sec--, now.tv_usec += 1000000;
922 advise (NULLCP,
923 "%d entr%s retrieved in %d.%06d seconds",
924 rows, rows != 1 ? "ies" : "y", now.tv_sec, now.tv_usec);
925 }
926
927 return OK;
928}
929
930/* \f */
931
932static int f_get (vec)
933char **vec;
934{
935 (void) process (new_message (type_SNMP_PDUs_get__request, vec));
936}
937
938/* \f */
939
940static int f_get_next (vec)
941char **vec;
942{
943 (void) process (new_message (type_SNMP_PDUs_get__next__request, vec));
944}
945
946/* \f */
947
948static int f_set (vec)
949char **vec;
950{
951 (void) process (new_message (type_SNMP_PDUs_set__request, vec));
952}
953
954/* \f */
955
956static char *errors[] = {
957 "noError", "tooBig", "noSuchName", "badValue", "readOnly", "genErr"
958};
959
960
961char *snmp_error (i)
962integer i;
963{
964 static char buffer[BUFSIZ];
965
966 if (0 < i && i < sizeof errors / sizeof errors[0])
967 return errors[i];
968 (void) sprintf (buffer, "error %d", i);
969
970 return buffer;
971}
972
973/* \f */
974
975static struct type_SNMP_Message *new_message (offset, vec)
976int offset;
977char **vec;
978{
979 register struct type_SNMP_Message *msg;
980 register struct type_SNMP_PDUs *pdu;
981 register struct type_SNMP_PDU *parm;
982 register struct type_SNMP_VarBindList **vp;
983
984 if ((msg = (struct type_SNMP_Message *) calloc (1, sizeof *msg)) == NULL)
985 adios (NULLCP, "out of memory");
986
987 msg -> version = int_SNMP_version_version__1;
988
989 if ((msg -> community = str2qb (community, strlen (community), 1)) == NULL)
990 adios (NULLCP, "out of memory");
991
992 if ((pdu = (struct type_SNMP_PDUs *) calloc (1, sizeof *pdu)) == NULL)
993 adios (NULLCP, "out of memory");
994 msg -> data = pdu;
995
996 pdu -> offset = offset;
997
998/* for now, always a PDU... */
999
1000 if ((parm = (struct type_SNMP_PDU *) calloc (1, sizeof *parm)) == NULL)
1001 adios (NULLCP, "out of memory");
1002 pdu -> un.get__request = parm;
1003
1004#ifndef SYS5
1005 parm -> request__id = ((int) random ()) & 0x7fffffff;
1006#else
1007 parm -> request__id = ((int) rand ()) & 0x7fffffff;
1008#endif
1009
1010 vp = &parm -> variable__bindings;
1011 for (vec++; *vec; vec++) {
1012 register struct type_SNMP_VarBindList *bind;
1013 register struct type_SNMP_VarBind *v;
1014
1015 if ((bind = (struct type_SNMP_VarBindList *) calloc (1, sizeof *bind))
1016 == NULL)
1017 adios (NULLCP, "out of memory");
1018 *vp = bind, vp = &bind -> next;
1019
1020 if ((v = (struct type_SNMP_VarBind *) calloc (1, sizeof *v)) == NULL)
1021 adios (NULLCP, "out of memory");
1022 bind -> VarBind = v;
1023
1024 if (get_ava (v, *vec, offset) == NOTOK) {
1025 free_SNMP_Message (msg);
1026 return NULL;
1027 }
1028 }
1029
1030 return msg;
1031}
1032
1033/* \f */
1034
1035static int get_ava (v, ava, offset)
1036register struct type_SNMP_VarBind *v;
1037char *ava;
1038int offset;
1039{
1040 int result;
1041 caddr_t value;
1042 register char *cp;
1043 register OI oi;
1044 register OT ot;
1045 register OS os;
1046 OID oid;
1047
1048 if (cp = index (ava, '=')) {
1049 if (offset != type_SNMP_PDUs_set__request)
1050 advise (NULLCP, "value unnecessary for get operation");
1051 *cp++ = NULL;
1052 }
1053 else
1054 if (offset == type_SNMP_PDUs_set__request) {
1055 advise (NULLCP, "need variable=value for set operation");
1056 return NOTOK;
1057 }
1058
1059 if ((oi = text2inst (ava)) == NULL) {
1060 if (cp || (oid = text2oid (ava)) == NULL) {
1061 advise (NULLCP, "unknown variable \"%s\"", ava);
1062 return NOTOK;
1063 }
1064
1065 ot = NULLOT;
1066 }
1067 else
1068 ot = oi -> oi_type;
1069
1070 if ((v -> name = oid_cpy (oi ? oi -> oi_name : oid)) == NULLOID)
1071 adios (NULLCP, "out of memory");
1072
1073 if (cp == NULL) {
1074 if ((v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL))
1075 == NULLPE)
1076 adios (NULLCP, "out of memory");
1077 }
1078 else {
1079 if ((os = ot -> ot_syntax) == NULL) {
1080 advise (NULLCP, "no syntax defined for object \"%s\"", ava);
1081 return NOTOK;
1082 }
1083
1084 if ((*os -> os_parse) (&value, cp) == NOTOK) {
1085 advise (NULLCP, "invalid value for variable \"%s\": \"%s\"",
1086 ava, cp);
1087 return NOTOK;
1088 }
1089 result = (*os -> os_encode) (value, &v -> value);
1090 (*os -> os_free) (value);
1091
1092 if (result == NOTOK) {
1093 advise (NULLCP, "encoding error for variable \"%s\"", ava);
1094 return NOTOK;
1095 }
1096 }
1097
1098 if (oi == NULL)
1099 oid_free (oid);
1100
1101 return OK;
1102}
1103
1104/* \f */
1105
1106static int process (msg)
1107struct type_SNMP_Message *msg;
1108{
1109 int request_id;
1110 PE pe;
1111 register struct type_SNMP_PDU *parm;
1112 register struct type_SNMP_VarBindList *vp;
1113
1114 if (msg == NULL)
1115 return OK;
1116
1117 request_id = msg -> data -> un.get__request -> request__id;
1118 if (encode_SNMP_Message (&pe, 1, 0, NULLCP, msg) != NOTOK) {
1119 if (watch)
1120 (void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);
1121
1122 if (pe2ps (ps, pe) == NOTOK) {
1123 advise (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno));
1124 goto out;
1125 }
1126 }
1127 else
1128 advise (NULLCP, "encode_SNMP_Message: %s", PY_pepy);
1129
1130try_again: ;
1131 if (pe)
1132 pe_free (pe);
1133 pe = NULLPE;
1134
1135 free_SNMP_Message (msg);
1136 msg = NULL;
1137
1138 if ((pe = ps2pe (ps)) == NULLPE) {
1139 advise (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno));
1140 goto out;
1141 }
1142
1143 if (decode_SNMP_Message (pe, 1, NULLIP, NULLVP, &msg) == NOTOK) {
1144 advise (NULLCP, "decode_SNMP_Message: %s", PY_pepy);
1145 goto out;
1146 }
1147
1148 if (watch)
1149 (void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);
1150
1151 if (msg -> data -> offset != type_SNMP_PDUs_get__response) {
1152 advise (NULLCP, "unexpected message type %d",
1153 msg -> data -> offset);
1154 goto out;
1155 }
1156
1157 if ((parm = msg -> data -> un.get__response) -> request__id
1158 != request_id) {
1159 fprintf (stderr, "request-id mismatch (got %d, wanted %d)\n",
1160 parm -> request__id, request_id);
1161 goto try_again;
1162 }
1163
1164 if (parm -> error__status != int_SNMP_error__status_noError) {
1165 fprintf (stderr, "%s at position %d\n",
1166 snmp_error (parm -> error__status), parm -> error__index);
1167 goto out;
1168 }
1169
1170 for (vp = parm -> variable__bindings; vp; vp = vp -> next) {
1171 caddr_t value;
1172 register OI oi;
1173 register OS os;
1174 register struct type_SNMP_VarBind *v = vp -> VarBind;
1175
1176 if ((oi = name2inst (v -> name)) == NULL) {
1177 advise (NULLCP, "unknown variable \"%s\"", oid2ode (v -> name));
1178no_dice: ;
1179 printf ("%s=", oid2ode (v -> name));
1180 vunknown (v -> value);
1181 continue;
1182 }
1183 if ((os = oi -> oi_type -> ot_syntax) == NULL) {
1184 advise (NULLCP, "unknown syntax for object \"%s\"",
1185 oi -> oi_type -> ot_text);
1186 goto no_dice;
1187 }
1188 if ((*os -> os_decode) (&value, v -> value) == NOTOK) {
1189 advise (NULLCP, "decode error for variable \"%s\"",
1190 oid2ode (v -> name));
1191 goto no_dice;
1192 }
1193
1194 printf ("%s=", oid2ode (v -> name));
1195 (*os -> os_print) (value, os);
1196 printf ("\n");
1197
1198 (*os -> os_free) (value);
1199 }
1200
1201 out: ;
1202 if (pe)
1203 pe_free (pe);
1204 if (msg)
1205 free_SNMP_Message (msg);
1206
1207 return OK;
1208}
1209
1210/* \f */
1211
1212static int f_help (vec)
1213char **vec;
1214{
1215 register int i,
1216 j,
1217 w;
1218 int columns,
1219 width,
1220 lines;
1221 register struct dispatch *ds,
1222 *es;
1223
1224 for (es = dispatches; es -> ds_name; es++)
1225 continue;
1226 width = helpwidth;
1227
1228 if (*++vec == NULL) {
1229 if ((columns = ncols (stdout) / (width = (width + 8) & ~7)) == 0)
1230 columns = 1;
1231 lines = ((es - dispatches) + columns - 1) / columns;
1232
1233 printf ("Operations:\n");
1234 for (i = 0; i < lines; i++)
1235 for (j = 0; j < columns; j++) {
1236 ds = dispatches + j * lines + i;
1237 printf ("%s", ds -> ds_name);
1238 if (ds + lines >= es) {
1239 printf ("\n");
1240 break;
1241 }
1242 for (w = strlen (ds -> ds_name); w < width; w = (w + 8) & ~7)
1243 (void) putchar ('\t');
1244 }
1245 printf ("\n");
1246
1247 return OK;
1248 }
1249
1250 if (strcmp (*vec, "-help") == 0) {
1251 printf ("help [commands ...]\n");
1252 printf (" with no arguments, lists operations which may be invoked\n");
1253 printf (" otherwise prints help for each operation given\n");
1254
1255 return OK;
1256 }
1257
1258 for (; *vec; vec++)
1259 if (strcmp (*vec, "?") == 0) {
1260 for (ds = dispatches; ds -> ds_name; ds++)
1261 printf ("%-*s\t- %s\n", width, ds -> ds_name, ds -> ds_help);
1262
1263 break;
1264 }
1265 else
1266 if (ds = getds (*vec))
1267 printf ("%-*s\t- %s\n", width, ds -> ds_name, ds -> ds_help);
1268
1269 return OK;
1270}
1271
1272/* \f */
1273
1274static int f_quit (vec)
1275char **vec;
1276{
1277 if (vec && *++vec != NULL && strcmp (*vec, "-help") == 0) {
1278 printf ("quit\n");
1279 printf (" terminate fred\n");
1280
1281 return OK;
1282 }
1283
1284 return DONE;
1285}
1286
1287/* \f */
1288
1289static int f_status (vec)
1290char **vec;
1291{
1292 if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
1293 printf ("status\n");
1294 printf (" report status\n");
1295
1296 return OK;
1297 }
1298
1299 printf ("Connected to %s using community \"%s\"\n",
1300 taddr2str (&snmp_ta), community);
1301
1302 return OK;
1303}
1304
1305/* \f SYNTAX */
1306
1307static char *ifType[] = {
1308 "other", "regular1822", "hdh1822", "ddn-x25", "rfc877-x25",
1309 "ethernet-csmacd", "iso88023-csmacd", "iso88024-tokenBus",
1310 "iso88025-tokenRing", "iso88026-man", "starLan", "proteon-10Mbit",
1311 "proteon-80Mbit", "hyperchannel", "fddi", "lapb", "sdlc", "t1-carrier",
1312 "cept", "basicISDN", "primaryISDN", "propPointToPointSerial",
1313 "ppp", "softwareLoopback", "eon", "ethernet-3Mbit",
1314 "nsip", "slip"
1315};
1316
1317static char *ifStatus[] = {
1318 "up", "down", "testing"
1319};
1320
1321static char *ipForwarding[] = {
1322 "gateway", "host"
1323};
1324
1325static char *routeType[] = {
1326 "other", "invalid", "direct", "remote"
1327};
1328
1329static char *ipRouteProto[] = {
1330 "other", "local", "netmgmt", "icmp", "egp", "ggp", "hello", "rip", "is-is",
1331 "es-is", "ciscoIgrp", "bbnSpfIgp", "ospf", "bgp"
1332};
1333
1334static char *netToMediaType[] = {
1335 "other", "invalid", "dynamic", "static"
1336};
1337
1338static char *tcpRtoAlgorithm[] = {
1339 "other", "constant", "rsre", "vanj"
1340};
1341
1342static char *tcpConnState[] = {
1343 "closed", "listen", "synSent", "synReceived", "established", "finWait1",
1344 "finWait2", "closeWait", "lastAck", "closing", "timewait"
1345};
1346
1347static char *egpNeighState[] = {
1348 "idle", "acquisition", "down", "up", "cease"
1349};
1350
1351static char *egpNeighMode[] = {
1352 "active", "passive"
1353};
1354
1355static char *egpNeighEventTrigger[] = {
1356 "start", "stop"
1357};
1358
1359static char *enabled[] = {
1360 "enabled", "disabled"
1361};
1362
1363
1364static char *status[] = {
1365 "valid", "invalid"
1366};
1367
1368static char *smuxPstatus[] = {
1369 "valid", "invalid", "connecting"
1370};
1371
1372
1373static struct ivar {
1374 char *iv_object;
1375
1376 char **iv_values;
1377 int iv_nvalue;
1378} ivars[] = {
1379 "ifType", ifType,
1380 sizeof ifType / sizeof ifType[0],
1381
1382 "ifAdminStatus", ifStatus,
1383 sizeof ifStatus / sizeof ifStatus[0],
1384
1385 "ifOperStatus", ifStatus,
1386 sizeof ifStatus / sizeof ifStatus[0],
1387
1388 "ipForwarding", ipForwarding,
1389 sizeof ipForwarding / sizeof ipForwarding[0],
1390
1391 "ipRouteType", routeType,
1392 sizeof routeType / sizeof routeType[0],
1393
1394 "ipRouteProto", ipRouteProto,
1395 sizeof ipRouteProto / sizeof ipRouteProto[0],
1396
1397 "ipNetToMediaType", netToMediaType,
1398 sizeof netToMediaType / sizeof netToMediaType[0],
1399
1400 "tcpRtoAlgorithm", tcpRtoAlgorithm,
1401 sizeof tcpRtoAlgorithm / sizeof tcpRtoAlgorithm[0],
1402
1403 "tcpConnState", tcpConnState,
1404 sizeof tcpConnState / sizeof tcpConnState[0],
1405
1406 "egpNeighState", egpNeighState,
1407 sizeof egpNeighState / sizeof egpNeighState[0],
1408
1409 "egpNeighMode", egpNeighMode,
1410 sizeof egpNeighMode / sizeof egpNeighMode[0],
1411
1412 "egpNeighEventTrigger", egpNeighEventTrigger,
1413 sizeof egpNeighEventTrigger / sizeof egpNeighEventTrigger[0],
1414
1415 "snmpEnableAuthenTraps", enabled,
1416 sizeof enabled / sizeof enabled[0],
1417
1418 "smuxPstatus", smuxPstatus,
1419 sizeof smuxPstatus / sizeof smuxPstatus[0],
1420
1421 "smuxTstatus", status,
1422 sizeof status / sizeof status[0],
1423
1424 "unixNetstat", enabled,
1425 sizeof enabled / sizeof enabled[0],
1426
1427 NULL
1428};
1429
1430/* \f */
1431
1432static int enum_print (x, os)
1433integer *x;
1434OS os;
1435{
1436 int i = *x;
1437
1438 if (i <= 0 || i > os -> os_data2)
1439 printf ("unknown(%d)", i);
1440 else
1441 printf ("%s(%d)", os -> os_data1[i - 1], i);
1442}
1443
1444
1445static moresyntax () {
1446 register struct ivar *iv;
1447 register OT ot;
1448 register OS os;
1449
1450 for (iv = ivars; iv -> iv_object; iv++)
1451 if (ot = text2obj (iv -> iv_object)) {
1452 char *name;
1453
1454 if ((os = ot -> ot_syntax) == NULL) {
1455 advise (NULLCP, "no syntax defined for object \"%s\"",
1456 iv -> iv_object);
1457 continue;
1458 }
1459 name = os -> os_name;
1460
1461 (void) add_syntax (iv -> iv_object, os -> os_encode,
1462 os -> os_decode, os -> os_free, os -> os_parse,
1463 enum_print);
1464 if ((os = text2syn (iv -> iv_object)) == NULL)
1465 adios (NULLCP, "lost syntax for object \"%s\"",
1466 iv -> iv_object);
1467 ot -> ot_syntax = os;
1468 os -> os_name = name;
1469 os -> os_data1 = iv -> iv_values;
1470 os -> os_data2 = iv -> iv_nvalue;
1471 }
1472 else
1473 advise (NULLCP, "no \"%s\" object", iv -> iv_object);
1474}
1475
1476/* \f MISCELLANY */
1477
1478static arginit (vec)
1479char **vec;
1480{
1481 int w;
1482 register char *ap,
1483 *pp;
1484 register struct dispatch *ds;
1485#ifdef TCP
1486 int port;
1487 struct sockaddr_in in_socket;
1488 register struct sockaddr_in *isock = &in_socket;
1489 register struct hostent *hp;
1490 register struct servent *sp;
1491#endif
1492 register struct TSAPaddr *ta = &snmp_ta,
1493 *tz;
1494 register struct NSAPaddr *na = ta -> ta_addrs;
1495
1496 if (myname = rindex (*vec, '/'))
1497 myname++;
1498 if (myname == NULL || *myname == NULL)
1499 myname = *vec;
1500
1501 isodetailor (myname, 1);
1502
1503 if (ontty = isatty (fileno (stdin)))
1504 verbose++;
1505
1506 if ((sp = getservbyname ("snmp", "udp")) == NULL)
1507 advise (NULLCP, "udp/snmp: unknown service");
1508
1509 bzero ((char *) ta, sizeof *ta);
1510#ifdef TCP
1511 na -> na_stack = NA_TCP;
1512 na -> na_community = ts_comm_tcp_default;
1513 (void) strncpy (na -> na_domain, getlocalhost (),
1514 sizeof na -> na_domain - 1);
1515 na -> na_port = sp ? sp -> s_port : htons ((u_short) 161);
1516 na -> na_tset = NA_TSET_UDP;
1517 ta -> ta_naddr = 1;
1518#endif
1519
1520 for (vec++; ap = *vec; vec++) {
1521 if (*ap == '-') {
1522 while (*++ap)
1523 switch (*ap) {
1524 case 'a': /* e.g., NS+0504030201 */
1525 if ((pp = *++vec) == NULL || *pp == '-')
1526 adios (NULLCP, "usage: %s -a agent", myname);
1527#ifdef TCP
1528 if (hp = gethostbystring (pp)) {
1529 if (na -> na_stack != NA_TCP)
1530 adios (NULLCP, "use -a at most once...");
1531 inaddr_copy (hp, isock);
1532 (void) strncpy (na -> na_domain,
1533 inet_ntoa (isock -> sin_addr),
1534 sizeof na -> na_domain - 1);
1535 }
1536 else
1537#endif
1538 if ((tz = str2taddr (pp)) && tz -> ta_naddr > 0) {
1539 *ta = *tz; /* struct copy */
1540 if (na -> na_stack == NA_TCP) {
1541 if (na -> na_port == 0)
1542 na -> na_port = sp ? sp -> s_port
1543 : htons ((u_short) 161);
1544 na -> na_tset = NA_TSET_UDP;
1545 }
1546 }
1547 else
1548 adios (NULLCP, "%s: unknown host", pp);
1549 break;
1550
1551#ifdef TCP
1552 case 'p':
1553 if ((pp = *++vec) == NULL
1554 || *pp == '-'
1555 || (port = atoi (pp)) <= 0)
1556 adios (NULLCP, "usage: %s -p portno", myname);
1557 if (na -> na_stack != NA_TCP)
1558 adios (NULLCP, "-p not allowed with %s",
1559 taddr2str (ta));
1560 na -> na_port = htons ((u_short) port);
1561 break;
1562#endif
1563
1564 case 'c':
1565 if ((pp = *++vec) == NULL || *pp == '-')
1566 adios (NULLCP, "usage: %s -c community", myname);
1567 community = pp;
1568 break;
1569
1570 case 'd':
1571 debug++;
1572 break;
1573
1574 case 'v':
1575 verbose++;
1576 break;
1577
1578 case 'w':
1579 watch++;
1580 break;
1581
1582 case 'f':
1583 if ((pp = *++vec) == NULL || *pp == '-')
1584 adios (NULLCP, "usage: %s -f file", myname);
1585 defs = pp;
1586 break;
1587
1588 default:
1589 adios (NULLCP, "unknown switch -%c", *ap);
1590 }
1591 continue;
1592 }
1593 if (op == NULL) {
1594 op = vec;
1595 break;
1596 }
1597 }
1598
1599 helpwidth = 0;
1600 for (ds = dispatches; ds -> ds_name; ds++)
1601 if ((w = strlen (ds -> ds_name)) > helpwidth)
1602 helpwidth = w;
1603
1604 if (ta -> ta_naddr == 0)
1605 adios (NULLCP, "usage: %s -a string", myname);
1606 switch (na -> na_stack) {
1607 case NA_TCP:
1608#ifdef TCP
1609 {
1610 struct sockaddr_in lo_socket;
1611 register struct sockaddr_in *lsock = &lo_socket;
1612
1613 bzero ((char *) lsock, sizeof *lsock);
1614 if ((hp = gethostbystring (pp = getlocalhost ())) == NULL)
1615 adios (NULLCP, "%s: unknown host", pp);
1616 lsock -> sin_family = hp -> h_addrtype;
1617 inaddr_copy (hp, lsock);
1618 /* If the request is being sent out on the loopback interface,
1619 make sure it appears to have originated from the loopback
1620 interface, rather than the interface used as the default
1621 hostname. If the interface used as the default hostname
1622 is a serial link, responses to requests with this origin
1623 may be undeliverable. (EJP) */
1624#define LOOPBACK ((127 << 24) + 1)
1625 if (isock -> sin_addr.s_addr == LOOPBACK)
1626 lsock -> sin_addr.s_addr = LOOPBACK;
1627#undef LOOPBACK
1628 if ((sd = start_udp_client (lsock, 0, 0, 0)) == NOTOK)
1629 adios ("failed", "start_udp_client");
1630
1631 bzero ((char *) isock, sizeof *isock);
1632 if ((hp = gethostbystring (na -> na_domain)) == NULL)
1633 adios (NULLCP, "%s: unknown host", na -> na_domain);
1634 isock -> sin_family = hp -> h_addrtype;
1635 isock -> sin_port = na -> na_port;
1636 inaddr_copy (hp, isock);
1637
1638 if (join_udp_server (sd, isock) == NOTOK)
1639 adios ("failed", "join_udp_server");
1640
1641 if ((ps = ps_alloc (dg_open)) == NULLPS
1642 || dg_setup (ps, sd, MAXDGRAM, read_udp_socket,
1643 write_udp_socket, check_udp_socket)
1644 == NOTOK) {
1645 if (ps == NULLPS)
1646 adios (NULLCP, "ps_alloc: out of memory");
1647 else
1648 adios (NULLCP, "dg_setup: %s",
1649 ps_error (ps -> ps_errno));
1650 }
1651 }
1652 break;
1653#else
1654 adios (NULLCP, "UDP support not configured");
1655#endif
1656
1657 case NA_X25:
1658#ifdef X25
1659 goto cots;
1660#else
1661 adios (NULLCP, "X.25 support not configured");
1662#endif
1663
1664 case NA_NSAP:
1665#ifdef CLTS
1666 {
1667 union sockaddr_osi lo_socket;
1668 register union sockaddr_osi *lsock = &lo_socket;
1669
1670 bzero ((char *) lsock, sizeof *lsock);
1671 if ((sd = start_clts_client (lsock, 0, 0, 0)) == NOTOK)
1672 adios ("failed", "start_clts_client");
1673
1674 (void) gen2tp4 (ta, lsock);
1675 if (join_clts_server (sd, lsock) == NOTOK)
1676 adios ("failed", "join_udp_server");
1677
1678 if ((ps = ps_alloc (dg_open)) == NULLPS
1679 || dg_setup (ps, sd, MAXDGRAM, read_clts_socket,
1680 write_clts_socket, check_clts_socket)
1681 == NOTOK) {
1682 if (ps == NULLPS)
1683 adios (NULLCP, "ps_alloc: out of memory");
1684 else
1685 adios (NULLCP, "dg_setup: %s",
1686 ps_error (ps -> ps_errno));
1687 }
1688 }
1689 break;
1690#else
1691#ifdef TP4
1692 goto cots;
1693#else
1694 adios (NULLCP, "TP4 support not configured");
1695#endif
1696#endif
1697
1698 default:
1699 adios (NULLCP, "unknown network type 0x%x", na -> na_stack);
1700 /* NOT REACHED */
1701
1702#ifdef COTS
1703cots: ;
1704 {
1705 struct TSAPconnect tcs;
1706 register struct TSAPconnect *tc = &tcs;
1707 struct TSAPdisconnect tds;
1708 register struct TSAPdisconnect *td = &tds;
1709
1710 if (verbose) {
1711 fprintf (stderr, "%s... ", taddr2str (ta));
1712 (void) fflush (stderr);
1713 }
1714 if (TConnRequest (NULLTA, ta, 0, NULLCP, 0, NULLQOS, tc, td)
1715 == NOTOK) {
1716 if (verbose)
1717 fprintf (stderr," failed\n");
1718 adios (NULLCP, td -> td_cc > 0
1719 ? "T-CONNECT.REQUEST: [%s] %*.*s"
1720 : "T-CONNECT.REQUEST: [%s]",
1721 TErrString (td -> td_reason),
1722 td -> td_cc, td -> td_cc, td -> td_data);
1723 }
1724 fprintf (stderr, "connected\n");
1725
1726 if ((ps = ps_alloc (dg_open)) == NULLPS
1727 || dg_setup (ps, sd = tc -> tc_sd, MAXDGRAM, ts_read,
1728 ts_write, NULLIFP) == NOTOK) {
1729 if (ps == NULLPS)
1730 adios (NULLCP, "ps_alloc: out of memory");
1731 else
1732 adios (NULLCP, "dg_setup: %s",
1733 ps_error (ps -> ps_errno));
1734 }
1735 }
1736 break;
1737#endif
1738 }
1739
1740#ifdef SYS5
1741 (void) srand ((unsigned int) time ((long *) 0));
1742#else
1743 (void) srandom ((int) time ((long *) 0));
1744#endif
1745
1746 ps_len_strategy = PS_LEN_LONG;
1747
1748 if (readobjects (defs) == NOTOK)
1749 adios (NULLCP, "readobjects: %s", PY_pepy);
1750 moresyntax ();
1751}
1752
1753/* \f INTERACTIVE */
1754
1755static int getline (prompt, buffer)
1756char *prompt,
1757 *buffer;
1758{
1759 register int i;
1760 register char *cp,
1761 *ep;
1762 static int sticky = 0;
1763
1764 if (interrupted) {
1765 interrupted = 0;
1766 return NOTOK;
1767 }
1768
1769 if (sticky) {
1770 sticky = 0;
1771 return NOTOK;
1772 }
1773
1774 switch (setjmp (intrenv)) {
1775 case OK:
1776 armed++;
1777 break;
1778
1779 case NOTOK:
1780 if (ontty)
1781 printf ("\n"); /* and fall */
1782 default:
1783 armed = 0;
1784 return NOTOK;
1785 }
1786
1787 if (ontty) {
1788 printf (prompt, myname);
1789 (void) fflush (stdout);
1790 }
1791
1792 for (ep = (cp = buffer) + BUFSIZ - 1; (i = getchar ()) != '\n';) {
1793 if (i == EOF) {
1794 if (ontty)
1795 printf ("\n");
1796 clearerr (stdin);
1797 if (cp == buffer)
1798 longjmp (intrenv, DONE);
1799
1800 sticky++;
1801 break;
1802 }
1803
1804 if (cp < ep)
1805 *cp++ = i;
1806 }
1807 *cp = NULL;
1808
1809 armed = 0;
1810
1811 return OK;
1812}
1813
1814/* \f */
1815
1816/* ARGSUSED */
1817
1818static SFD intrser (sig)
1819int sig;
1820{
1821#ifndef BSDSIGS
1822 (void) signal (SIGINT, intrser);
1823#endif
1824
1825 if (armed)
1826 longjmp (intrenv, NOTOK);
1827
1828 interrupted++;
1829}
1830
1831/* \f */
1832
1833#ifndef TIOCGWINSZ
1834/* ARGSUSED */
1835#endif
1836
1837static int ncols (fp)
1838FILE *fp;
1839{
1840#ifdef TIOCGWINSZ
1841 int i;
1842 struct winsize ws;
1843
1844 if (ioctl (fileno (fp), TIOCGWINSZ, (char *) &ws) != NOTOK
1845 && (i = ws.ws_col) > 0)
1846 return i;
1847#endif
1848
1849 return 80;
1850}
1851
1852/* \f ERRORS */
1853
1854#ifndef lint
1855void _advise ();
1856
1857
1858void adios (va_alist)
1859va_dcl
1860{
1861 va_list ap;
1862
1863 va_start (ap);
1864
1865 _advise (ap);
1866
1867 va_end (ap);
1868
1869 _exit (1);
1870}
1871#else
1872/* VARARGS */
1873
1874void adios (what, fmt)
1875char *what,
1876 *fmt;
1877{
1878 adios (what, fmt);
1879}
1880#endif
1881
1882
1883#ifndef lint
1884void advise (va_alist)
1885va_dcl
1886{
1887 va_list ap;
1888
1889 va_start (ap);
1890
1891 _advise (ap);
1892
1893 va_end (ap);
1894}
1895
1896
1897static void _advise (ap)
1898va_list ap;
1899{
1900 char buffer[BUFSIZ];
1901
1902 asprintf (buffer, ap);
1903
1904 (void) fflush (stdout);
1905
1906 fprintf (stderr, "%s: ", myname);
1907 (void) fputs (buffer, stderr);
1908 (void) fputc ('\n', stderr);
1909
1910 (void) fflush (stderr);
1911}
1912#else
1913/* VARARGS */
1914
1915void advise (what, fmt)
1916char *what,
1917 *fmt;
1918{
1919 advise (what, fmt);
1920}
1921#endif