home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xntp3.zip / ntpq / ntpq_ops.c < prev    next >
C/C++ Source or Header  |  1992-08-19  |  32KB  |  1,585 lines

  1. /*
  2.  * ntpdc_ops.c - subroutines which are called to perform operations by xntpdc
  3.  */
  4. #include <stdio.h>
  5. #include <strings.h>
  6. #include <ctype.h>
  7. #include <sys/types.h>
  8. #include <sys/time.h>
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11. #include <netdb.h>
  12.  
  13. #include "ntp_fp.h"
  14. #include "ntp.h"
  15. #include "ntp_control.h"
  16. #include "ntpq.h"
  17.  
  18. extern char *    chosts[];
  19. extern char    currenthost[];
  20. extern int    numhosts;
  21. int        maxhostlen;
  22.  
  23. /*
  24.  * Declarations for command handlers in here
  25.  */
  26. void associations(), passociations();
  27. void lassociations(), lpassociations();
  28. void pstatus(), writevar(), readvar();
  29. void addvars(), rmvars(), clearvars();
  30. void showvars(), readlist(), writelist();
  31. void clockvar(), clocklist(), mreadlist();
  32. void mreadvar(), peers(), opeers();
  33. void lpeers(), lopeers();
  34.  
  35.  
  36. /*
  37.  * Commands we understand.  Ntpdc imports this.
  38.  */
  39. struct xcmd opcmds[] = {
  40.     { "associations", associations,    {  NO, NO, NO, NO },
  41.                     { "", "", "", "" },
  42.     "print list of association ID's and statuses for the server's peers" },
  43.     { "passociations", passociations,    {  NO, NO, NO, NO },
  44.                     { "", "", "", "" },
  45.     "print list of associations returned by last associations command" },
  46.     { "lassociations", lassociations,    {  NO, NO, NO, NO },
  47.                     { "", "", "", "" },
  48.     "print list of associations including all client information" },
  49.     { "lpassociations", lpassociations,    {  NO, NO, NO, NO },
  50.                     { "", "", "", "" },
  51. "print last obtained list of associations, including client information" },
  52.     { "addvars",    addvars,    { STR, NO, NO, NO },
  53.                     { "name[=value][,...]", "", "", "" },
  54.         "add variables to the variable list or change their values" },
  55.     { "rmvars",    rmvars,        { STR, NO, NO, NO },
  56.                     { "name[,...]", "", "", "" },
  57.                 "remove variables from the variable list" },
  58.     { "clearvars",    clearvars,    { NO, NO, NO, NO },
  59.                     { "", "", "", "" },
  60.                 "remove all variables from the variable list" },
  61.     { "showvars",    showvars,    { NO, NO, NO, NO },
  62.                     { "", "", "", "" },
  63.                 "print variables on the variable list" },
  64.     { "readlist",    readlist,    { OPT|UINT, NO, NO, NO },
  65.                     { "assocID", "", "", "" },
  66.     "read the system or peer variables included in the variable list" },
  67.     { "rl",        readlist,    { OPT|UINT, NO, NO, NO },
  68.                     { "assocID", "", "", "" },
  69.     "read the system or peer variables included in the variable list" },
  70.     { "writelist",    writelist,    { OPT|UINT, NO, NO, NO },
  71.                     { "assocID", "", "", "" },
  72.     "write the system or peer variables included in the variable list" },
  73.     { "readvar",    readvar,    { OPT|UINT, OPT|STR, NO, NO },
  74.                 { "assocID", "name=value[,...]", "", "" },
  75.             "read system or peer variables" },
  76.     { "rv",        readvar,    { OPT|UINT, OPT|STR, NO, NO },
  77.                 { "assocID", "name=value[,...]", "", "" },
  78.             "read system or peer variables" },
  79.     { "writevar",    writevar,    { UINT, STR, NO, NO },
  80.                 { "assocID", "name=value,[...]", "", "" },
  81.             "write system or peer variables" },
  82.     { "mreadlist",    mreadlist,    { UINT, UINT, NO, NO },
  83.                     { "assocID", "assocID", "", "" },
  84.     "read the peer variables in the variable list for multiple peers" },
  85.     { "mrl",    mreadlist,    { UINT, UINT, NO, NO },
  86.                     { "assocID", "assocID", "", "" },
  87.     "read the peer variables in the variable list for multiple peers" },
  88.     { "mreadvar",    mreadvar,    { UINT, UINT, OPT|STR, NO },
  89.             { "assocID", "assocID", "name=value[,...]", "" },
  90.             "read peer variables from multiple peers" },
  91.     { "mrv",    mreadvar,    { UINT, UINT, OPT|STR, NO },
  92.             { "assocID", "assocID", "name=value[,...]", "" },
  93.             "read peer variables from multiple peers" },
  94.     { "clocklist",    clocklist,    { OPT|UINT, NO, NO, NO },
  95.                     { "assocID", "", "", "" },
  96.     "read the clock variables included in the variable list" },
  97.     { "cl",        clocklist,    { OPT|UINT, NO, NO, NO },
  98.                     { "assocID", "", "", "" },
  99.     "read the clock variables included in the variable list" },
  100.     { "clockvar",    clockvar,    { OPT|UINT, OPT|STR, NO, NO },
  101.                 { "assocID", "name=value[,...]", "", "" },
  102.                 "read clock variables" },
  103.     { "cv",        clockvar,    { OPT|UINT, OPT|STR, NO, NO },
  104.                 { "assocID", "name=value[,...]", "", "" },
  105.                 "read clock variables" },
  106.     { "pstatus",    pstatus,    { UINT, NO, NO, NO },
  107.                     { "assocID", "", "", "" },
  108.             "print status information returned for a peer" },
  109.     { "peers",    peers,        { NO, NO, NO, NO },
  110.                     { "", "", "", "" },
  111.             "obtain and print a list of the server's peers" },
  112.     { "lpeers",    lpeers,        { NO, NO, NO, NO },
  113.                     { "", "", "", "" },
  114.             "obtain and print a list of all peers and clients" },
  115.     { "opeers",    opeers,        { NO, NO, NO, NO },
  116.                     { "", "", "", "" },
  117.     "print peer list the old way, with dstadr shown rather than refid" },
  118.     { "lopeers",    lopeers,    { NO, NO, NO, NO },
  119.                     { "", "", "", "" },
  120.     "obtain and print a list of all peers and clients showing dstadr" },
  121.     { 0,        0,        { NO, NO, NO, NO },
  122.                     { "", "", "", "" }, "" }
  123. };
  124.  
  125.  
  126. /*
  127.  * Variable list data space
  128.  */
  129. #define    MAXLIST        64    /* maximum number of variables in list */
  130. #define    LENHOSTNAME    256    /* host name is 256 characters long */
  131. /*
  132.  * Old CTL_PST defines for version 2.
  133.  */
  134. #define OLD_CTL_PST_CONFIG          0x80
  135. #define OLD_CTL_PST_AUTHENABLE      0x40
  136. #define OLD_CTL_PST_AUTHENTIC       0x20
  137. #define OLD_CTL_PST_REACH           0x10
  138. #define OLD_CTL_PST_SANE            0x08
  139. #define OLD_CTL_PST_DISP            0x04
  140. #define OLD_CTL_PST_SEL_REJECT      0
  141. #define OLD_CTL_PST_SEL_SELCAND     1
  142. #define OLD_CTL_PST_SEL_SYNCCAND    2
  143. #define OLD_CTL_PST_SEL_SYSPEER     3
  144.  
  145.  
  146. char flash2[] = " .+*    ";    /* flash decode for version 2 */
  147. char flash3[] = " x.-+#*o";    /* flash decode for peer status version 3 */
  148.  
  149. struct varlist {
  150.     char *name;
  151.     char *value;
  152. } varlist[MAXLIST] = { 0 };
  153.  
  154. /*
  155.  * Imported from ntpq.c
  156.  */
  157. extern int showhostnames;
  158. extern int rawmode;
  159. extern int debug;
  160. extern struct servent *server_entry;
  161. extern struct association assoc_cache[];
  162. extern int numassoc;
  163. extern u_char pktversion;
  164.  
  165. /*
  166.  * Subroutines in common use here
  167.  */
  168. extern void printvars();
  169. extern void asciize();
  170. extern char *lfptoms();
  171. extern char *nntohost();
  172. extern char *numtoa();
  173. extern char *statustoa();
  174. extern char *uinttoa();
  175.  
  176. /*
  177.  * For quick string comparisons
  178.  */
  179. #define    STREQ(a, b)    (*(a) == *(b) && strcmp((a), (b)) == 0)
  180.  
  181.  
  182. /*
  183.  * checkassocid - return the association ID, checking to see if it is valid
  184.  */
  185. int
  186. checkassocid(value)
  187.     u_long value;
  188. {
  189.     if (value == 0 || value >= 65536) {
  190.         (void) fprintf(stderr, "***Invalid association ID specified\n");
  191.         return 0;
  192.     }
  193.     return (int)value;
  194. }
  195.  
  196.  
  197. /*
  198.  * strsave - save a string
  199.  */
  200. char *strsave(str)
  201.     char *str;
  202. {
  203.     extern char *malloc();
  204.     char *cp;
  205.     u_int len;
  206.  
  207.     len = strlen(str) + 1;
  208.     if ((cp = malloc(len)) == NULL) {
  209.         (void) fprintf(stderr, "Malloc failed!!\n");
  210.         exit(1);
  211.     }
  212.  
  213.     bcopy(str, cp, len);
  214.     return cp;
  215. }
  216.  
  217.  
  218. /*
  219.  * findlistvar - look for the named variable in a list and return if found
  220.  */
  221. struct varlist *
  222. findlistvar(list, name)
  223.     struct varlist *list;
  224.     char *name;
  225. {
  226.     register struct varlist *vl;
  227.  
  228.     for (vl = list; vl < list + MAXLIST && vl->name != 0; vl++)
  229.         if (STREQ(name, vl->name))
  230.             return vl;
  231.     if (vl < list + MAXLIST)
  232.         return vl;
  233.     return (struct varlist *)0;
  234. }
  235.  
  236.  
  237. /*
  238.  * doaddvlist - add variable(s) to the variable list
  239.  */
  240. void
  241. doaddvlist(vlist, vars)
  242.     struct varlist *vlist;
  243.     char *vars;
  244. {
  245.     register struct varlist *vl;
  246.     int len;
  247.     char *name;
  248.     char *value;
  249.  
  250.     len = strlen(vars);
  251.     while (nextvar(&len, &vars, &name, &value)) {
  252.         vl = findlistvar(vlist, name);
  253.         if (vl == 0) {
  254.             (void) fprintf(stderr, "Variable list full\n");
  255.             return;
  256.         }
  257.  
  258.         if (vl->name == 0) {
  259.             vl->name = strsave(name);
  260.         } else if (vl->value != 0) {
  261.             (void) free(vl->value);
  262.             vl->value = 0;
  263.         }
  264.  
  265.         if (value != 0)
  266.             vl->value = strsave(value);
  267.     }
  268. }
  269.  
  270.  
  271. /*
  272.  * dormvlist - remove variable(s) from the variable list
  273.  */
  274. void
  275. dormvlist(vlist, vars)
  276.     struct varlist *vlist;
  277.     char *vars;
  278. {
  279.     register struct varlist *vl;
  280.     int len;
  281.     char *name;
  282.     char *value;
  283.  
  284.     len = strlen(vars);
  285.     while (nextvar(&len, &vars, &name, &value)) {
  286.         vl = findlistvar(vlist, name);
  287.         if (vl == 0 || vl->name == 0) {
  288.             (void) fprintf(stderr, "Variable `%s' not found\n",
  289.                 name);
  290.         } else {
  291.             (void) free(vl->name);
  292.             if (vl->value != 0)
  293.                 (void) free(vl->value);
  294.             for ( ; (vl+1) < (varlist+MAXLIST)
  295.                 && (vl+1)->name != 0; vl++) {
  296.                 vl->name = (vl+1)->name;
  297.                 vl->value = (vl+1)->value;
  298.             }
  299.             vl->name = vl->value = 0;
  300.         }
  301.     }
  302. }
  303.  
  304.  
  305. /*
  306.  * doclearvlist - clear a variable list
  307.  */
  308. void
  309. doclearvlist(vlist)
  310.     struct varlist *vlist;
  311. {
  312.     register struct varlist *vl;
  313.  
  314.     for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
  315.         (void) free(vl->name);
  316.         vl->name = 0;
  317.         if (vl->value != 0) {
  318.             (void) free(vl->value);
  319.             vl->value = 0;
  320.         }
  321.     }
  322. }
  323.  
  324.  
  325. /*
  326.  * makequerydata - form a data buffer to be included with a query
  327.  */
  328. void
  329. makequerydata(vlist, datalen, data)
  330.     struct varlist *vlist;
  331.     int *datalen;
  332.     char *data;
  333. {
  334.     register struct varlist *vl;
  335.     register char *cp, *cpend;
  336.     register int namelen, valuelen;
  337.     register int totallen;
  338.  
  339.     cp = data;
  340.     cpend = data + *datalen;
  341.  
  342.     for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
  343.         namelen = strlen(vl->name);
  344.         if (vl->value == 0)
  345.             valuelen = 0;
  346.         else
  347.             valuelen = strlen(vl->value);
  348.         totallen = namelen + valuelen + (valuelen != 0) + (cp != data);
  349.         if (cp + totallen > cpend)
  350.             break;
  351.         
  352.         if (cp != data)
  353.             *cp++ = ',';
  354.         bcopy(vl->name, cp, namelen);
  355.         cp += namelen;
  356.         if (valuelen != 0) {
  357.             *cp++ = '=';
  358.             bcopy(vl->value, cp, valuelen);
  359.             cp += valuelen;
  360.         }
  361.     }
  362.     *datalen = cp - data;
  363. }
  364.  
  365.  
  366. /*
  367.  * doquerylist - send a message including variables in a list
  368.  */
  369. int
  370. doquerylist(vlist, op, associd, auth, rstatus, dsize, datap)
  371.     struct varlist *vlist;
  372.     int op;
  373.     int associd;
  374.     int auth;
  375.     u_short *rstatus;
  376.     int *dsize;
  377.     char **datap;
  378. {
  379.     char data[CTL_MAX_DATA_LEN];
  380.     int datalen;
  381.  
  382.     datalen = sizeof(data);
  383.     makequerydata(vlist, &datalen, data);
  384.  
  385.     return doquery(op, associd, auth, datalen, data, rstatus,
  386.         dsize, datap);
  387. }
  388.  
  389.  
  390. /*
  391.  * doprintvlist - print the variables on a list
  392.  */
  393. void
  394. doprintvlist(vlist, fp)
  395.     struct varlist *vlist;
  396.     FILE *fp;
  397. {
  398.     register struct varlist *vl;
  399.  
  400.     if (vlist->name == 0) {
  401.         (void) fprintf(fp, "No variables on list\n");
  402.     } else {
  403.         for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
  404.             if (vl->value == 0) {
  405.                 (void) fprintf(fp, "%s\n", vl->name);
  406.             } else {
  407.                 (void) fprintf(fp, "%s=%s\n",
  408.                     vl->name, vl->value);
  409.             }
  410.         }
  411.     }
  412. }
  413.  
  414.  
  415. /*
  416.  * addvars - add variables to the variable list
  417.  */
  418. /*ARGSUSED*/
  419. void
  420. addvars(pcmd, fp)
  421.     struct parse *pcmd;
  422.     FILE *fp;
  423. {
  424.     doaddvlist(varlist, pcmd->argval[0].string);
  425. }
  426.  
  427.  
  428. /*
  429.  * rmvars - remove variables from the variable list
  430.  */
  431. /*ARGSUSED*/
  432. void
  433. rmvars(pcmd, fp)
  434.     struct parse *pcmd;
  435.     FILE *fp;
  436. {
  437.     dormvlist(varlist, pcmd->argval[0].string);
  438. }
  439.  
  440.  
  441. /*
  442.  * clearvars - clear the variable list
  443.  */
  444. /*ARGSUSED*/
  445. void
  446. clearvars(pcmd, fp)
  447.     struct parse *pcmd;
  448.     FILE *fp;
  449. {
  450.     doclearvlist(varlist);
  451. }
  452.  
  453.  
  454. /*
  455.  * showvars - show variables on the variable list
  456.  */
  457. /*ARGSUSED*/
  458. void
  459. showvars(pcmd, fp)
  460.     struct parse *pcmd;
  461.     FILE *fp;
  462. {
  463.     doprintvlist(varlist, fp);
  464. }
  465.  
  466.  
  467. /*
  468.  * dolist - send a request with the given list of variables
  469.  */
  470. int
  471. dolist(vlist, associd, op, type, fp)
  472.     struct varlist *vlist;
  473.     int associd;
  474.     int op;
  475.     int type;
  476.     FILE *fp;
  477. {
  478.     char *datap;
  479.     int res;
  480.     int dsize;
  481.     u_short rstatus;
  482.  
  483.     res = doquerylist(vlist, op, associd, 0, &rstatus, &dsize, &datap);
  484.  
  485.     if (res != 0)
  486.         return 0;
  487.  
  488.     if (dsize == 0) {
  489.         if (associd == 0)
  490.             (void) fprintf(fp, "No system%s variables returned\n",
  491.                 (type == TYPE_CLOCK) ? " clock" : "");
  492.         else
  493.             (void) fprintf(fp,
  494.                 "No information returned for%s association %u\n",
  495.                 (type == TYPE_CLOCK) ? " clock" : "", associd);
  496.         return 1;
  497.     }
  498.  
  499.     printvars(dsize, datap, (int)rstatus, type, fp);
  500.     return 1;
  501. }
  502.  
  503.  
  504. /*
  505.  * readlist - send a read variables request with the variables on the list
  506.  */
  507. void
  508. readlist(pcmd, fp)
  509.     struct parse *pcmd;
  510.     FILE *fp;
  511. {
  512.     int associd;
  513.  
  514.     if (pcmd->nargs == 0) {
  515.         associd = 0;
  516.     } else {
  517.         if (pcmd->argval[0].uval == 0)
  518.             associd = 0;
  519.         else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  520.             return;
  521.     }
  522.  
  523.     (void) dolist(varlist, associd, CTL_OP_READVAR,
  524.         (associd == 0) ? TYPE_SYS : TYPE_PEER, fp);
  525. }
  526.  
  527.  
  528. /*
  529.  * writelist - send a write variables request with the variables on the list
  530.  */
  531. void
  532. writelist(pcmd, fp)
  533.     struct parse *pcmd;
  534.     FILE *fp;
  535. {
  536.     char *datap;
  537.     int res;
  538.     int associd;
  539.     int dsize;
  540.     u_short rstatus;
  541.  
  542.     if (pcmd->nargs == 0) {
  543.         associd = 0;
  544.     } else {
  545.         if (pcmd->argval[0].uval == 0)
  546.             associd = 0;
  547.         else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  548.             return;
  549.     }
  550.  
  551.     res = doquerylist(varlist, CTL_OP_WRITEVAR, associd, 0, &rstatus,
  552.         &dsize, &datap);
  553.  
  554.     if (res != 0)
  555.         return;
  556.  
  557.     if (dsize == 0)
  558.         (void) fprintf(fp, "done! (no data returned)\n");
  559.     else
  560.         printvars(dsize, datap, (int)rstatus,
  561.             (associd != 0) ? TYPE_PEER : TYPE_SYS, fp);
  562.     return;
  563. }
  564.  
  565.  
  566. /*
  567.  * readvar - send a read variables request with the specified variables
  568.  */
  569. void
  570. readvar(pcmd, fp)
  571.     struct parse *pcmd;
  572.     FILE *fp;
  573. {
  574.     int associd;
  575.     struct varlist tmplist[MAXLIST];
  576.  
  577.     if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
  578.         associd = 0;
  579.     else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  580.         return;
  581.  
  582.     bzero((char *)tmplist, sizeof(tmplist));
  583.     if (pcmd->nargs >= 2)
  584.         doaddvlist(tmplist, pcmd->argval[1].string);
  585.  
  586.     (void) dolist(tmplist, associd, CTL_OP_READVAR,
  587.         (associd == 0) ? TYPE_SYS : TYPE_PEER, fp);
  588.  
  589.     doclearvlist(tmplist);
  590. }
  591.  
  592.  
  593. /*
  594.  * writevar - send a write variables request with the specified variables
  595.  */
  596. void
  597. writevar(pcmd, fp)
  598.     struct parse *pcmd;
  599.     FILE *fp;
  600. {
  601.     char *datap;
  602.     int res;
  603.     int associd;
  604.     int dsize;
  605.     u_short rstatus;
  606.     struct varlist tmplist[MAXLIST];
  607.  
  608.     if (pcmd->argval[0].uval == 0)
  609.         associd = 0;
  610.     else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  611.         return;
  612.  
  613.     bzero((char *)tmplist, sizeof(tmplist));
  614.     doaddvlist(tmplist, pcmd->argval[1].string);
  615.  
  616.     res = doquerylist(tmplist, CTL_OP_WRITEVAR, associd, 0, &rstatus,
  617.         &dsize, &datap);
  618.  
  619.     doclearvlist(tmplist);
  620.  
  621.     if (res != 0)
  622.         return;
  623.  
  624.     if (dsize == 0)
  625.         (void) fprintf(fp, "done! (no data returned)\n");
  626.     else
  627.         printvars(dsize, datap, (int)rstatus,
  628.             (associd != 0) ? TYPE_PEER : TYPE_SYS, fp);
  629.     return;
  630. }
  631.  
  632.  
  633. /*
  634.  * clocklist - send a clock variables request with the variables on the list
  635.  */
  636. void
  637. clocklist(pcmd, fp)
  638.     struct parse *pcmd;
  639.     FILE *fp;
  640. {
  641.     int associd;
  642.  
  643.     if (pcmd->nargs == 0) {
  644.         associd = 0;
  645.     } else {
  646.         if (pcmd->argval[0].uval == 0)
  647.             associd = 0;
  648.         else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  649.             return;
  650.     }
  651.  
  652.     (void) dolist(varlist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
  653. }
  654.  
  655.  
  656. /*
  657.  * clockvar - send a clock variables request with the specified variables
  658.  */
  659. void
  660. clockvar(pcmd, fp)
  661.     struct parse *pcmd;
  662.     FILE *fp;
  663. {
  664.     int associd;
  665.     struct varlist tmplist[MAXLIST];
  666.  
  667.     if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
  668.         associd = 0;
  669.     else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  670.         return;
  671.  
  672.     bzero((char *)tmplist, sizeof(tmplist));
  673.     if (pcmd->nargs >= 2)
  674.         doaddvlist(tmplist, pcmd->argval[1].string);
  675.  
  676.     (void) dolist(tmplist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
  677.  
  678.     doclearvlist(tmplist);
  679. }
  680.  
  681.  
  682. /*
  683.  * findassidrange - verify a range of association ID's
  684.  */
  685. int
  686. findassidrange(assid1, assid2, from, to)
  687.     u_long assid1;
  688.     u_long assid2;
  689.     int *from;
  690.     int *to;
  691. {
  692.     register int i;
  693.     int f, t;
  694.  
  695.     if (assid1 == 0 || assid1 > 65535) {
  696.         (void) fprintf(stderr,
  697.             "***Invalid association ID %lu specified\n", assid1);
  698.         return 0;
  699.     }
  700.  
  701.     if (assid2 == 0 || assid2 > 65535) {
  702.         (void) fprintf(stderr,
  703.             "***Invalid association ID %lu specified\n", assid2);
  704.         return 0;
  705.     }
  706.  
  707.     f = t = -1;
  708.     for (i = 0; i < numassoc; i++) {
  709.         if (assoc_cache[i].assid == assid1) {
  710.             f = i;
  711.             if (t != -1)
  712.                 break;
  713.         }
  714.         if (assoc_cache[i].assid == assid2) {
  715.             t = i;
  716.             if (f != -1)
  717.                 break;
  718.         }
  719.     }
  720.  
  721.     if (f == -1 || t == -1) {
  722.         (void) fprintf(stderr,
  723.             "***Association ID %lu not found in list\n",
  724.             (f == -1) ? assid1 : assid2);
  725.         return 0;
  726.     }
  727.  
  728.     if (f < t) {
  729.         *from = f;
  730.         *to = t;
  731.     } else {
  732.         *from = t;
  733.         *to = f;
  734.     }
  735.     return 1;
  736. }
  737.  
  738.  
  739.  
  740. /*
  741.  * mreadlist - send a read variables request for multiple associations
  742.  */
  743. void
  744. mreadlist(pcmd, fp)
  745.     struct parse *pcmd;
  746.     FILE *fp;
  747. {
  748.     int i;
  749.     int from;
  750.     int to;
  751.  
  752.     if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
  753.         &from, &to))
  754.         return;
  755.  
  756.     for (i = from; i <= to; i++) {
  757.         if (i != from)
  758.             (void) fprintf(fp, "\n");
  759.         if (!dolist(varlist, (int)assoc_cache[i].assid,
  760.             CTL_OP_READVAR, TYPE_PEER, fp))
  761.             return;
  762.     }
  763.     return;
  764. }
  765.  
  766.  
  767. /*
  768.  * mreadvar - send a read variables request for multiple associations
  769.  */
  770. void
  771. mreadvar(pcmd, fp)
  772.     struct parse *pcmd;
  773.     FILE *fp;
  774. {
  775.     int i;
  776.     int from;
  777.     int to;
  778.     struct varlist tmplist[MAXLIST];
  779.  
  780.     if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
  781.         &from, &to))
  782.         return;
  783.  
  784.     bzero((char *)tmplist, sizeof(tmplist));
  785.     if (pcmd->nargs >= 3)
  786.         doaddvlist(tmplist, pcmd->argval[2].string);
  787.  
  788.     for (i = from; i <= to; i++) {
  789.         if (i != from)
  790.             (void) fprintf(fp, "\n");
  791.         if (!dolist(varlist, (int)assoc_cache[i].assid,
  792.             CTL_OP_READVAR, TYPE_PEER, fp))
  793.             break;
  794.     }
  795.     doclearvlist(tmplist);
  796.     return;
  797. }
  798.  
  799.  
  800. /*
  801.  * dogetassoc - query the host for its list of associations
  802.  */
  803. int
  804. dogetassoc(fp)
  805.     FILE *fp;
  806. {
  807.     u_short *datap;
  808.     int res;
  809.     int dsize;
  810.     u_short rstatus;
  811.     extern void sortassoc();
  812.  
  813.     res = doquery(CTL_OP_READSTAT, 0, 0, 0, (char *)0, &rstatus,
  814.         &dsize, (char **)&datap);
  815.     
  816.     if (res != 0)
  817.         return 0;
  818.     
  819.     if (dsize == 0) {
  820.         (void) fprintf(fp, "No association ID's returned\n");
  821.         return 0;
  822.     }
  823.     
  824.     if (dsize & 0x3) {
  825.         (void) fprintf(stderr,
  826.         "***Server returned %d octets, should be multiple of 4\n",
  827.             dsize);
  828.         return 0;
  829.     }
  830.  
  831.     numassoc = 0;
  832.     while (dsize > 0) {
  833.         assoc_cache[numassoc].assid = ntohs(*datap);
  834.         datap++;
  835.         assoc_cache[numassoc].status = ntohs(*datap);
  836.         datap++;
  837.         if (++numassoc >= MAXASSOC)
  838.             break;
  839.         dsize -= sizeof(u_short) + sizeof(u_short);
  840.     }
  841.     sortassoc();
  842.     return 1;
  843. }
  844.  
  845.  
  846. /*
  847.  * printassoc - print the current list of associations
  848.  */
  849. void
  850. printassoc(showall, fp)
  851.     int showall;
  852.     FILE *fp;
  853. {
  854.     register char *bp;
  855.     int i;
  856.     u_char statval;
  857.     int event;
  858.     u_long event_count;
  859.     char *conf;
  860.     char *reach;
  861.     char *auth;
  862.     char *condition;
  863.     char *last_event;
  864.     char *cnt;
  865.     char buf[128];
  866.  
  867.     if (numassoc == 0) {
  868.         (void) fprintf(fp, "No association ID's in list\n");
  869.         return;
  870.     }
  871.  
  872.     /*
  873.      * Output a header
  874.      */
  875.     (void) fprintf(fp,
  876.     "ind assID status  conf reach auth condition  last_event cnt\n");
  877.     (void) fprintf(fp,
  878.     "===========================================================\n");
  879.     for (i = 0; i < numassoc; i++) {
  880.         statval = CTL_PEER_STATVAL(assoc_cache[i].status);
  881.         if (!showall && !(statval & (CTL_PST_CONFIG|CTL_PST_REACH)))
  882.             continue;
  883.         event = CTL_PEER_EVENT(assoc_cache[i].status);
  884.         event_count = CTL_PEER_NEVNT(assoc_cache[i].status);
  885.         if (statval & CTL_PST_CONFIG)
  886.             conf = "yes";
  887.         else
  888.             conf = "no";
  889.         if (statval & CTL_PST_REACH) {
  890.             reach = "yes";
  891.             if (statval & CTL_PST_AUTHENABLE) {
  892.                 if (statval & CTL_PST_AUTHENTIC)
  893.                     auth = "ok ";
  894.                 else
  895.                     auth = "bad";
  896.             } else
  897.                 auth = "none";
  898.  
  899.             if (pktversion == NTP_VERSION)
  900.                 switch (statval & 0x7) {
  901.                 case CTL_PST_SEL_REJECT:
  902.                     condition = "insane";
  903.                     break;
  904.                 case CTL_PST_SEL_SANE:
  905.                     condition = "falsetick";
  906.                     break;
  907.                 case CTL_PST_SEL_CORRECT:
  908.                     condition = "eliminate";
  909.                     break;
  910.                 case CTL_PST_SEL_SELCAND:
  911.                     condition = "outlyer";
  912.                     break;
  913.                 case CTL_PST_SEL_SYNCCAND:
  914.                     condition = "synchr.";
  915.                     break;
  916.                 case CTL_PST_SEL_DISTSYSPEER:
  917.                     condition = "dist.peer";
  918.                     break;
  919.                 case CTL_PST_SEL_SYSPEER:
  920.                     condition = "sys.peer";
  921.                     break;
  922.                 case CTL_PST_SEL_PPS:
  923.                     condition = "pps.peer";
  924.                     break;
  925.                 }
  926.             else
  927.                 switch (statval & 0x3) {
  928.                 case OLD_CTL_PST_SEL_REJECT:
  929.                     if (!(statval & OLD_CTL_PST_SANE))
  930.                         condition = "insane";
  931.                     else if (!(statval & OLD_CTL_PST_DISP))
  932.                         condition = "hi_disp";
  933.                            else
  934.                         condition = "";
  935.                     break;
  936.                 case OLD_CTL_PST_SEL_SELCAND:
  937.                     condition = "sel_cand";
  938.                     break;
  939.                 case OLD_CTL_PST_SEL_SYNCCAND:
  940.                     condition = "sync_cand";
  941.                     break;
  942.                 case OLD_CTL_PST_SEL_SYSPEER:
  943.                     condition = "sys.peer";
  944.                             break;
  945.                 }
  946.             
  947.         } else {
  948.             reach = "no";
  949.             auth = condition = "";
  950.         }
  951.  
  952.         switch (PEER_EVENT|event) {
  953.         case EVNT_PEERIPERR:
  954.             last_event = "IP error";
  955.             break;
  956.         case EVNT_PEERAUTH:
  957.             last_event = "auth fail";
  958.             break;
  959.         case EVNT_UNREACH:
  960.             last_event = "lost reach";
  961.             break;
  962.         case EVNT_REACH:
  963.             last_event = "reachable";
  964.             break;
  965.         case EVNT_PEERCLOCK:
  966.             last_event = "clock expt";
  967.             break;
  968. #if 0
  969.         case EVNT_PEERSTRAT:
  970.             last_event = "stratum chg";
  971.             break;
  972. #endif
  973.         default:
  974.             last_event = "";
  975.             break;
  976.         }
  977.  
  978.         if (event_count != 0)
  979.             cnt = uinttoa(event_count);
  980.         else
  981.             cnt = "";
  982.         (void) sprintf(buf,
  983.         "%3d %5u  %04x   %3.3s  %4s  %4.4s %9.9s %11s %2s",
  984.             i+1, assoc_cache[i].assid, assoc_cache[i].status,
  985.             conf, reach, auth, condition, last_event, cnt);
  986.         bp = &buf[strlen(buf)];
  987.         while (bp > buf && *(bp-1) == ' ')
  988.             *(--bp) = '\0';
  989.         (void) fprintf(fp, "%s\n", buf);
  990.     }
  991. }
  992.  
  993.  
  994.  
  995. /*
  996.  * associations - get, record and print a list of associations
  997.  */
  998. /*ARGSUSED*/
  999. void
  1000. associations(pcmd, fp)
  1001.     struct parse *pcmd;
  1002.     FILE *fp;
  1003. {
  1004.     if (dogetassoc(fp))
  1005.         printassoc(0, fp);
  1006. }
  1007.  
  1008.  
  1009. /*
  1010.  * lassociations - get, record and print a long list of associations
  1011.  */
  1012. /*ARGSUSED*/
  1013. void
  1014. lassociations(pcmd, fp)
  1015.     struct parse *pcmd;
  1016.     FILE *fp;
  1017. {
  1018.     if (dogetassoc(fp))
  1019.         printassoc(1, fp);
  1020. }
  1021.  
  1022.  
  1023. /*
  1024.  * passociations - print the association list
  1025.  */
  1026. /*ARGSUSED*/
  1027. void
  1028. passociations(pcmd, fp)
  1029.     struct parse *pcmd;
  1030.     FILE *fp;
  1031. {
  1032.     printassoc(0, fp);
  1033. }
  1034.  
  1035.  
  1036. /*
  1037.  * lpassociations - print the long association list
  1038.  */
  1039. /*ARGSUSED*/
  1040. void
  1041. lpassociations(pcmd, fp)
  1042.     struct parse *pcmd;
  1043.     FILE *fp;
  1044. {
  1045.     printassoc(1, fp);
  1046. }
  1047.  
  1048.  
  1049. /*
  1050.  * radiostatus - print the radio status returned by the server
  1051.  */
  1052. /*ARGSUSED*/
  1053. void
  1054. radiostatus(pcmd, fp)
  1055.     struct parse *pcmd;
  1056.     FILE *fp;
  1057. {
  1058.     char *datap;
  1059.     int res;
  1060.     int dsize;
  1061.     u_short rstatus;
  1062.  
  1063.     res = doquery(CTL_OP_READCLOCK, 0, 0, 0, (char *)0, &rstatus,
  1064.         &dsize, &datap);
  1065.  
  1066.     if (res != 0)
  1067.         return;
  1068.  
  1069.     if (dsize == 0) {
  1070.         (void) fprintf(fp, "No radio status string returned\n");
  1071.         return;
  1072.     }
  1073.  
  1074.     asciize(dsize, datap, fp);
  1075. }
  1076.  
  1077. /*
  1078.  * pstatus - print peer status returned by the server
  1079.  */
  1080. void
  1081. pstatus(pcmd, fp)
  1082.     struct parse *pcmd;
  1083.     FILE *fp;
  1084. {
  1085.     char *datap;
  1086.     int res;
  1087.     int associd;
  1088.     int dsize;
  1089.     u_short rstatus;
  1090.  
  1091.     if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  1092.         return;
  1093.  
  1094.     res = doquery(CTL_OP_READSTAT, associd, 0, 0, (char *)0, &rstatus,
  1095.         &dsize, &datap);
  1096.  
  1097.     if (res != 0)
  1098.         return;
  1099.  
  1100.     if (dsize == 0) {
  1101.         (void) fprintf(fp,
  1102.             "No information returned for association %u\n",
  1103.             associd);
  1104.         return;
  1105.     }
  1106.  
  1107.     printvars(dsize, datap, (int)rstatus, TYPE_PEER, fp);
  1108. }
  1109.  
  1110.  
  1111. /*
  1112.  * fixup - fix up a string so we don't get a hanging decimal after it
  1113.  */
  1114. char *
  1115. fixup(width, str)
  1116.     int width;
  1117.     char *str;
  1118. {
  1119.     if (str[width-1] == '.')
  1120.         str[width-1] = '\0';
  1121.     return str;
  1122. }
  1123.  
  1124.  
  1125. /*
  1126.  * when - print how long its been since his last packet arrived
  1127.  */
  1128. char *
  1129. when(ts, rec, reftime)
  1130.     l_fp *ts;
  1131.     l_fp *rec;
  1132.     l_fp *reftime;
  1133. {
  1134.     long diff;
  1135.     l_fp *lasttime;
  1136.     static char buf[20];
  1137.  
  1138.     if (rec->l_ui != 0)
  1139.         lasttime = rec;
  1140.     else if (reftime->l_ui != 0)
  1141.         lasttime = reftime;
  1142.     else
  1143.         return "-";
  1144.     
  1145.     diff = (long)(ts->l_ui - lasttime->l_ui);
  1146.     if (diff <= 0) {
  1147.         /*
  1148.          * Time warp?
  1149.          */
  1150.         diff = 1;
  1151.     }
  1152.  
  1153.     if (diff <= 2048) {
  1154.         (void) sprintf(buf, "%d", diff);
  1155.         return buf;
  1156.     }
  1157.  
  1158.     diff = (diff + 29) / 60;
  1159.     if (diff <= 300) {
  1160.         (void) sprintf(buf, "%dm", diff);
  1161.         return buf;
  1162.     }
  1163.  
  1164.     diff = (diff + 29) / 60;
  1165.     if (diff <= 96) {
  1166.         (void) sprintf(buf, "%dh", diff);
  1167.         return buf;
  1168.     }
  1169.  
  1170.     diff = (diff + 11) / 24;
  1171.     (void) sprintf(buf, "%dd", diff);
  1172.     return buf;
  1173. }
  1174.  
  1175.  
  1176.  
  1177. /*
  1178.  * A list of variables required by the peers command
  1179.  */
  1180. struct varlist opeervarlist[] = {
  1181.     { "srcadr",    0 },    /* 0 */
  1182.     { "dstadr",    0 },    /* 1 */
  1183.     { "stratum",    0 },    /* 2 */
  1184.     { "hpoll",    0 },    /* 3 */
  1185.     { "ppoll",    0 },    /* 4 */
  1186.     { "reach",    0 },    /* 5 */
  1187.     { "delay",    0 },    /* 6 */
  1188.     { "offset",    0 },    /* 7 */
  1189.     { "dispersion",    0 },    /* 8 */
  1190.     { "rec",    0 },    /* 9 */
  1191.     { "reftime",    0 },    /* 10 */
  1192.     { "srcport",    0 },    /* 11 */
  1193.     { 0,        0 }
  1194. };
  1195.  
  1196. struct varlist peervarlist[] = {
  1197.     { "srcadr",    0 },    /* 0 */
  1198.     { "refid",    0 },    /* 1 */
  1199.     { "stratum",    0 },    /* 2 */
  1200.     { "hpoll",    0 },    /* 3 */
  1201.     { "ppoll",    0 },    /* 4 */
  1202.     { "reach",    0 },    /* 5 */
  1203.     { "delay",    0 },    /* 6 */
  1204.     { "offset",    0 },    /* 7 */
  1205.     { "dispersion",    0 },    /* 8 */
  1206.     { "rec",    0 },    /* 9 */
  1207.     { "reftime",    0 },    /* 10 */
  1208.     { "srcport",    0 },    /* 11 */
  1209.     { 0,        0 }
  1210. };
  1211.  
  1212. #define    HAVE_SRCADR    0
  1213. #define    HAVE_DSTADR    1
  1214. #define    HAVE_REFID    1
  1215. #define    HAVE_STRATUM    2
  1216. #define    HAVE_HPOLL    3
  1217. #define    HAVE_PPOLL     4    
  1218. #define    HAVE_REACH    5
  1219. #define    HAVE_DELAY    6
  1220. #define    HAVE_OFFSET    7
  1221. #define    HAVE_DISPERSION    8
  1222. #define    HAVE_REC    9
  1223. #define    HAVE_REFTIME    10
  1224. #define    HAVE_SRCPORT    11
  1225. #define    MAXHAVE        12
  1226.  
  1227. /*
  1228.  * Decode an incoming data buffer and print a line in the peer list
  1229.  */
  1230. int
  1231. doprintpeers(pvl, associd, rstatus, datalen, data, fp)
  1232.     struct varlist *pvl;
  1233.     int associd;
  1234.     int rstatus;
  1235.     int datalen;
  1236.     char *data;
  1237.     FILE *fp;
  1238. {
  1239.     char *name;
  1240.     char *value;
  1241.     int i;
  1242.     int c;
  1243.  
  1244.     u_long srcadr;
  1245.     u_long dstadr;
  1246.     u_long srcport;
  1247.     char *dstadr_refid;
  1248.     u_long stratum;
  1249.     long ppoll;
  1250.     long hpoll;
  1251.     u_long reach;
  1252.     l_fp estdelay;
  1253.     l_fp estoffset;
  1254.     l_fp estdisp;
  1255.     l_fp rec;
  1256.     l_fp reftime;
  1257.     l_fp ts;
  1258.     u_char havevar[MAXHAVE];
  1259.     u_long poll;
  1260.     char refid_string[10];
  1261.  
  1262.     extern struct ctl_var peer_var[];
  1263.     extern int findvar();
  1264.     extern int decodetime();
  1265.     extern int decodets();
  1266.     extern void gettstamp();
  1267.  
  1268.     bzero(havevar, sizeof(havevar));
  1269.     gettstamp(&ts);
  1270.     
  1271.     while (nextvar(&datalen, &data, &name, &value)) {
  1272.         i = findvar(name, peer_var);
  1273.         if (i == 0)
  1274.             continue;    /* don't know this one */
  1275.         switch (i) {
  1276.         case CP_SRCADR:
  1277.             if (decodenetnum(value, &srcadr))
  1278.                 havevar[HAVE_SRCADR] = 1;
  1279.             break;
  1280.         case CP_DSTADR:
  1281.             if (pvl == opeervarlist) {
  1282.                 if (decodenetnum(value, &dstadr)) {
  1283.                     havevar[HAVE_DSTADR] = 1;
  1284.                     dstadr_refid = numtoa(dstadr);
  1285.                 }
  1286.             }
  1287.             break;
  1288.         case CP_REFID:
  1289.             if (pvl == peervarlist) {
  1290.                 havevar[HAVE_REFID] = 1;
  1291.                 if (*value == '\0') {
  1292.                     dstadr_refid = "0.0.0.0";
  1293.                 } else if (decodenetnum(value, &dstadr)) {
  1294.                     if (dstadr == 0)
  1295.                         dstadr_refid = "0.0.0.0";
  1296.                     else
  1297.                         dstadr_refid = nntohost(dstadr);
  1298.                 } else if (strlen(value) <= 4) {
  1299.                     refid_string[0] = '.';
  1300.                     (void) strcpy(&refid_string[1], value);
  1301.                     i = strlen(refid_string);
  1302.                     refid_string[i] = '.';
  1303.                     refid_string[i+1] = '\0';
  1304.                     dstadr_refid = refid_string;
  1305.                 } else {
  1306.                     havevar[HAVE_REFID] = 0;
  1307.                 }
  1308.             }
  1309.             break;
  1310.         case CP_STRATUM:
  1311.             if (decodeuint(value, &stratum))
  1312.                 havevar[HAVE_STRATUM] = 1;
  1313.             break;
  1314.         case CP_HPOLL:
  1315.             if (decodeint(value, &hpoll)) {
  1316.                 havevar[HAVE_HPOLL] = 1;
  1317.                 if (hpoll < 0)
  1318.                     hpoll = NTP_MINPOLL;
  1319.             }
  1320.             break;
  1321.         case CP_PPOLL:
  1322.             if (decodeint(value, &ppoll)) {
  1323.                 havevar[HAVE_PPOLL] = 1;
  1324.                 if (ppoll < 0)
  1325.                     ppoll = NTP_MINPOLL;
  1326.             }
  1327.             break;
  1328.         case CP_REACH:
  1329.             if (decodeuint(value, &reach))
  1330.                 havevar[HAVE_REACH] = 1;
  1331.             break;
  1332.         case CP_DELAY:
  1333.             if (decodetime(value, &estdelay))
  1334.                 havevar[HAVE_DELAY] = 1;
  1335.             break;
  1336.         case CP_OFFSET:
  1337.             if (decodetime(value, &estoffset))
  1338.                 havevar[HAVE_OFFSET] = 1;
  1339.             break;
  1340.         case CP_DISPERSION:
  1341.             if (decodetime(value, &estdisp))
  1342.                 havevar[HAVE_DISPERSION] = 1;
  1343.             break;
  1344.         case CP_REC:
  1345.             if (decodets(value, &rec))
  1346.                 havevar[HAVE_REC] = 1;
  1347.             break;
  1348.         case CP_SRCPORT:
  1349.             if (decodeuint(value, &srcport))
  1350.                 havevar[HAVE_SRCPORT] = 1;
  1351.             break;
  1352.         case CP_REFTIME:
  1353.             havevar[HAVE_REFTIME] = 1;
  1354.             if (!decodets(value, &reftime))
  1355.                 reftime.l_ui = reftime.l_uf = 0;
  1356.             break;
  1357.         default:
  1358.             break;
  1359.         }
  1360.     }
  1361.  
  1362.     /*
  1363.      * Check to see if the srcport is NTP's port.  If not this probably
  1364.      * isn't a valid peer association.
  1365.      */
  1366.     if (havevar[HAVE_SRCPORT] && srcport != NTP_PORT)
  1367.         return 1;
  1368.  
  1369.     /*
  1370.      * Check to see if we got all of them.  If not, return an
  1371.      * error.
  1372.      */
  1373.     for (i = 0; i < MAXHAVE; i++)
  1374.         if (!havevar[i]) {
  1375.             (void) fprintf(stderr,
  1376.         "***Remote host didn't return peer.%s for association %d\n",
  1377.                 pvl[i].name, associd);
  1378.             return 0;
  1379.         }
  1380.     
  1381.  
  1382.     /*
  1383.      * Got everything, format the line
  1384.      */
  1385.     poll = 1<<max(min3(ppoll, hpoll, NTP_MAXPOLL), NTP_MINPOLL);
  1386.     if (pktversion == NTP_VERSION)
  1387.          c = flash3[CTL_PEER_STATVAL(rstatus) & 0x7];
  1388.     else
  1389.          c = flash2[CTL_PEER_STATVAL(rstatus) & 0x3];
  1390.     if (numhosts > 1)
  1391.         (void) fprintf(fp, "%-*s ", maxhostlen, currenthost);
  1392.     (void) fprintf(fp,
  1393.         "%c%-15.15s %-15.15s %2d %4.4s %4d  %3o  %6.6s %7.7s %6.6s\n",
  1394.         c, nntohost(srcadr), dstadr_refid, stratum,
  1395.         when(&ts, &rec, &reftime),
  1396.         poll, reach, fixup(6, lfptoms(&estdelay, 1)),
  1397.         fixup(7, lfptoms(&estoffset, 2)),
  1398.         fixup(6, lfptoms(&estdisp, 1)));
  1399.     return 1;
  1400. }
  1401.  
  1402. #undef    HAVE_SRCADR
  1403. #undef    HAVE_DSTADR
  1404. #undef    HAVE_STRATUM
  1405. #undef    HAVE_PPOLL
  1406. #undef    HAVE_HPOLL
  1407. #undef    HAVE_REACH
  1408. #undef    HAVE_ESTDELAY
  1409. #undef    HAVE_ESTOFFSET
  1410. #undef    HAVE_ESTDISP
  1411. #undef    HAVE_REFID
  1412. #undef    HAVE_REC
  1413. #undef    HAVE_SRCPORT
  1414. #undef    HAVE_REFTIME
  1415. #undef    MAXHAVE    
  1416.  
  1417.  
  1418. /*
  1419.  * dogetpeers - given an association ID, read and print the spreadsheet
  1420.  *        peer variables.
  1421.  */
  1422. int
  1423. dogetpeers(pvl, associd, fp)
  1424.     struct varlist *pvl;
  1425.     int associd;
  1426.     FILE *fp;
  1427. {
  1428.     char *datap;
  1429.     int res;
  1430.     int dsize;
  1431.     u_short rstatus;
  1432.  
  1433. #ifdef notdef
  1434.     res = doquerylist(pvl, CTL_OP_READVAR, associd, 0, &rstatus,
  1435.         &dsize, &datap);
  1436. #else
  1437.     /*
  1438.      * Damn fuzzballs
  1439.      */
  1440.     res = doquery(CTL_OP_READVAR, associd, 0, 0, (char *)0, &rstatus,
  1441.         &dsize, &datap);
  1442. #endif
  1443.  
  1444.     if (res != 0)
  1445.         return 0;
  1446.  
  1447.     if (dsize == 0) {
  1448.         (void) fprintf(stderr,
  1449.             "***No information returned for association %d\n",
  1450.             associd);
  1451.         return 0;
  1452.     }
  1453.  
  1454.     
  1455.     return doprintpeers(pvl, associd, (int)rstatus, dsize, datap, fp);
  1456. }
  1457.  
  1458.  
  1459. /*
  1460.  * peers - print a peer spreadsheet
  1461.  */
  1462. void
  1463. dopeers(showall, fp)
  1464.     int showall;
  1465.     FILE *fp;
  1466. {
  1467.     register int i;
  1468.     extern int getnetnum();
  1469.     char fullname[LENHOSTNAME];
  1470.     u_long netnum;
  1471.  
  1472.  
  1473.     if (!dogetassoc(fp))
  1474.         return;
  1475.  
  1476.     for (i = 0; i < numhosts; ++i)
  1477.     { if(getnetnum(chosts[i],&netnum,fullname))
  1478.         if (strlen(fullname) > maxhostlen)
  1479.             maxhostlen = strlen(fullname);
  1480.     }
  1481.     if (numhosts > 1)
  1482.         (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "host");
  1483.     (void) fprintf(fp,
  1484. "     remote           refid      st when poll reach  delay  offset   disp\n");
  1485.     if (numhosts > 1)
  1486.         for (i = 0; i <= maxhostlen; ++i)
  1487.             (void) fprintf(fp, "=");
  1488.     (void) fprintf(fp,
  1489. "=========================================================================\n");
  1490.  
  1491.     for (i = 0; i < numassoc; i++) {
  1492.         if (!showall &&
  1493.             !(CTL_PEER_STATVAL(assoc_cache[i].status)
  1494.               & (CTL_PST_CONFIG|CTL_PST_REACH)))
  1495.             continue;
  1496.         if (!dogetpeers(peervarlist, (int)assoc_cache[i].assid, fp)) {
  1497.             return;
  1498.         }
  1499.     }
  1500.     return;
  1501. }
  1502.  
  1503.  
  1504. /*
  1505.  * peers - print a peer spreadsheet
  1506.  */
  1507. /*ARGSUSED*/
  1508. void
  1509. peers(pcmd, fp)
  1510.     struct parse *pcmd;
  1511.     FILE *fp;
  1512. {
  1513.     dopeers(0, fp);
  1514. }
  1515.  
  1516.  
  1517. /*
  1518.  * lpeers - print a peer spreadsheet including all fuzzball peers
  1519.  */
  1520. /*ARGSUSED*/
  1521. void
  1522. lpeers(pcmd, fp)
  1523.     struct parse *pcmd;
  1524.     FILE *fp;
  1525. {
  1526.     dopeers(1, fp);
  1527. }
  1528.  
  1529.  
  1530. /*
  1531.  * opeers - print a peer spreadsheet
  1532.  */
  1533. void
  1534. doopeers(showall, fp)
  1535.     int showall;
  1536.     FILE *fp;
  1537. {
  1538.     register int i;
  1539.  
  1540.     if (!dogetassoc(fp))
  1541.         return;
  1542.  
  1543.     (void) fprintf(fp,
  1544. "     remote           local      st when poll reach  delay  offset   disp\n");
  1545.     (void) fprintf(fp,
  1546. "=========================================================================\n");
  1547.  
  1548.     for (i = 0; i < numassoc; i++) {
  1549.         if (!showall &&
  1550.             !(CTL_PEER_STATVAL(assoc_cache[i].status)
  1551.               & (CTL_PST_CONFIG|CTL_PST_REACH)))
  1552.             continue;
  1553.         if (!dogetpeers(opeervarlist, (int)assoc_cache[i].assid, fp)) {
  1554.             return;
  1555.         }
  1556.     }
  1557.     return;
  1558. }
  1559.  
  1560.  
  1561. /*
  1562.  * opeers - print a peer spreadsheet the old way
  1563.  */
  1564. /*ARGSUSED*/
  1565. void
  1566. opeers(pcmd, fp)
  1567.     struct parse *pcmd;
  1568.     FILE *fp;
  1569. {
  1570.     doopeers(0, fp);
  1571. }
  1572.  
  1573.  
  1574. /*
  1575.  * lopeers - print a peer spreadsheet including all fuzzball peers
  1576.  */
  1577. /*ARGSUSED*/
  1578. void
  1579. lopeers(pcmd, fp)
  1580.     struct parse *pcmd;
  1581.     FILE *fp;
  1582. {
  1583.     doopeers(1, fp);
  1584. }
  1585.