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