1c0b746e5SOllivier Robert /* 2c0b746e5SOllivier Robert * ntpdc - control and monitor your ntpd daemon 3c0b746e5SOllivier Robert */ 4224ba2bdSOllivier Robert 5c0b746e5SOllivier Robert #include <stdio.h> 6224ba2bdSOllivier Robert 7224ba2bdSOllivier Robert #include "ntpdc.h" 8224ba2bdSOllivier Robert #include "ntp_select.h" 9224ba2bdSOllivier Robert #include "ntp_io.h" 10224ba2bdSOllivier Robert #include "ntp_stdlib.h" 11224ba2bdSOllivier Robert 12c0b746e5SOllivier Robert #include <ctype.h> 13c0b746e5SOllivier Robert #include <signal.h> 14c0b746e5SOllivier Robert #include <setjmp.h> 15c0b746e5SOllivier Robert #include <netdb.h> 16c0b746e5SOllivier Robert 17c0b746e5SOllivier Robert #ifdef SYS_WINNT 18c0b746e5SOllivier Robert # include <io.h> 19c0b746e5SOllivier Robert #else 20c0b746e5SOllivier Robert # define closesocket close 21c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 22c0b746e5SOllivier Robert 23224ba2bdSOllivier Robert #ifdef HAVE_LIBREADLINE 24224ba2bdSOllivier Robert # include <readline/readline.h> 25224ba2bdSOllivier Robert # include <readline/history.h> 26224ba2bdSOllivier Robert #endif /* HAVE_LIBREADLINE */ 27c0b746e5SOllivier Robert 28c0b746e5SOllivier Robert #ifdef SYS_VXWORKS 29c0b746e5SOllivier Robert /* vxWorks needs mode flag -casey*/ 30c0b746e5SOllivier Robert #define open(name, flags) open(name, flags, 0777) 31c0b746e5SOllivier Robert #define SERVER_PORT_NUM 123 32c0b746e5SOllivier Robert #endif 33c0b746e5SOllivier Robert 34c0b746e5SOllivier Robert /* 35c0b746e5SOllivier Robert * Because we now potentially understand a lot of commands (and 36c0b746e5SOllivier Robert * it requires a lot of commands to talk to ntpd) we will run 37c0b746e5SOllivier Robert * interactive if connected to a terminal. 38c0b746e5SOllivier Robert */ 39c0b746e5SOllivier Robert static int interactive = 0; /* set to 1 when we should prompt */ 40c0b746e5SOllivier Robert static const char * prompt = "ntpdc> "; /* prompt to ask him about */ 41c0b746e5SOllivier Robert 42c0b746e5SOllivier Robert /* 43c0b746e5SOllivier Robert * Keyid used for authenticated requests. Obtained on the fly. 44c0b746e5SOllivier Robert */ 45c0b746e5SOllivier Robert static u_long info_auth_keyid; 46c0b746e5SOllivier Robert 47c0b746e5SOllivier Robert /* 48c0b746e5SOllivier Robert * Type of key md5 or des 49c0b746e5SOllivier Robert */ 50c0b746e5SOllivier Robert #define KEY_TYPE_DES 3 51c0b746e5SOllivier Robert #define KEY_TYPE_MD5 4 52c0b746e5SOllivier Robert 53c0b746e5SOllivier Robert static int info_auth_keytype = KEY_TYPE_MD5; /* MD5*/ 54c0b746e5SOllivier Robert u_long current_time; /* needed by authkeys; not used */ 55c0b746e5SOllivier Robert 56c0b746e5SOllivier Robert int ntpdcmain P((int, char **)); 57c0b746e5SOllivier Robert /* 58c0b746e5SOllivier Robert * Built in command handler declarations 59c0b746e5SOllivier Robert */ 60c0b746e5SOllivier Robert static int openhost P((const char *)); 61c0b746e5SOllivier Robert static int sendpkt P((char *, int)); 62c0b746e5SOllivier Robert static void growpktdata P((void)); 63c0b746e5SOllivier Robert static int getresponse P((int, int, int *, int *, char **)); 64c0b746e5SOllivier Robert static int sendrequest P((int, int, int, int, int, char *)); 65c0b746e5SOllivier Robert static void getcmds P((void)); 66c0b746e5SOllivier Robert static RETSIGTYPE abortcmd P((int)); 67c0b746e5SOllivier Robert static void docmd P((const char *)); 68c0b746e5SOllivier Robert static void tokenize P((const char *, char **, int *)); 69c0b746e5SOllivier Robert static int findcmd P((char *, struct xcmd *, struct xcmd *, struct xcmd **)); 70c0b746e5SOllivier Robert static int getarg P((char *, int, arg_v *)); 71c0b746e5SOllivier Robert static int getnetnum P((const char *, u_int32 *, char *)); 72c0b746e5SOllivier Robert static void help P((struct parse *, FILE *)); 73c0b746e5SOllivier Robert #ifdef QSORT_USES_VOID_P 74c0b746e5SOllivier Robert static int helpsort P((const void *, const void *)); 75c0b746e5SOllivier Robert #else 76c0b746e5SOllivier Robert static int helpsort P((char **, char **)); 77c0b746e5SOllivier Robert #endif 78c0b746e5SOllivier Robert static void printusage P((struct xcmd *, FILE *)); 79c0b746e5SOllivier Robert static void timeout P((struct parse *, FILE *)); 80c0b746e5SOllivier Robert static void my_delay P((struct parse *, FILE *)); 81c0b746e5SOllivier Robert static void host P((struct parse *, FILE *)); 82c0b746e5SOllivier Robert static void keyid P((struct parse *, FILE *)); 83c0b746e5SOllivier Robert static void keytype P((struct parse *, FILE *)); 84c0b746e5SOllivier Robert static void passwd P((struct parse *, FILE *)); 85c0b746e5SOllivier Robert static void hostnames P((struct parse *, FILE *)); 86c0b746e5SOllivier Robert static void setdebug P((struct parse *, FILE *)); 87c0b746e5SOllivier Robert static void quit P((struct parse *, FILE *)); 88c0b746e5SOllivier Robert static void version P((struct parse *, FILE *)); 89c0b746e5SOllivier Robert static void warning P((const char *, const char *, const char *)); 90c0b746e5SOllivier Robert static void error P((const char *, const char *, const char *)); 91c0b746e5SOllivier Robert static u_long getkeyid P((const char *)); 92c0b746e5SOllivier Robert 93c0b746e5SOllivier Robert 94c0b746e5SOllivier Robert 95c0b746e5SOllivier Robert /* 96c0b746e5SOllivier Robert * Built-in commands we understand 97c0b746e5SOllivier Robert */ 98c0b746e5SOllivier Robert static struct xcmd builtins[] = { 99c0b746e5SOllivier Robert { "?", help, { OPT|NTP_STR, NO, NO, NO }, 100c0b746e5SOllivier Robert { "command", "", "", "" }, 101c0b746e5SOllivier Robert "tell the use and syntax of commands" }, 102c0b746e5SOllivier Robert { "help", help, { OPT|NTP_STR, NO, NO, NO }, 103c0b746e5SOllivier Robert { "command", "", "", "" }, 104c0b746e5SOllivier Robert "tell the use and syntax of commands" }, 105c0b746e5SOllivier Robert { "timeout", timeout, { OPT|UINT, NO, NO, NO }, 106c0b746e5SOllivier Robert { "msec", "", "", "" }, 107c0b746e5SOllivier Robert "set the primary receive time out" }, 108c0b746e5SOllivier Robert { "delay", my_delay, { OPT|INT, NO, NO, NO }, 109c0b746e5SOllivier Robert { "msec", "", "", "" }, 110c0b746e5SOllivier Robert "set the delay added to encryption time stamps" }, 111c0b746e5SOllivier Robert { "host", host, { OPT|NTP_STR, NO, NO, NO }, 112c0b746e5SOllivier Robert { "hostname", "", "", "" }, 113c0b746e5SOllivier Robert "specify the host whose NTP server we talk to" }, 114c0b746e5SOllivier Robert { "passwd", passwd, { OPT|NTP_STR, NO, NO, NO }, 115c0b746e5SOllivier Robert { "", "", "", "" }, 116c0b746e5SOllivier Robert "specify a password to use for authenticated requests"}, 117c0b746e5SOllivier Robert { "hostnames", hostnames, { OPT|NTP_STR, NO, NO, NO }, 118c0b746e5SOllivier Robert { "yes|no", "", "", "" }, 119c0b746e5SOllivier Robert "specify whether hostnames or net numbers are printed"}, 120c0b746e5SOllivier Robert { "debug", setdebug, { OPT|NTP_STR, NO, NO, NO }, 121c0b746e5SOllivier Robert { "no|more|less", "", "", "" }, 122c0b746e5SOllivier Robert "set/change debugging level" }, 123c0b746e5SOllivier Robert { "quit", quit, { NO, NO, NO, NO }, 124c0b746e5SOllivier Robert { "", "", "", "" }, 125c0b746e5SOllivier Robert "exit ntpdc" }, 126c0b746e5SOllivier Robert { "exit", quit, { NO, NO, NO, NO }, 127c0b746e5SOllivier Robert { "", "", "", "" }, 128c0b746e5SOllivier Robert "exit ntpdc" }, 129c0b746e5SOllivier Robert { "keyid", keyid, { OPT|UINT, NO, NO, NO }, 130c0b746e5SOllivier Robert { "key#", "", "", "" }, 131c0b746e5SOllivier Robert "set/show keyid to use for authenticated requests" }, 132c0b746e5SOllivier Robert { "keytype", keytype, { OPT|NTP_STR, NO, NO, NO }, 133c0b746e5SOllivier Robert { "(md5|des)", "", "", "" }, 134c0b746e5SOllivier Robert "set/show key authentication type for authenticated requests (des|md5)" }, 135c0b746e5SOllivier Robert { "version", version, { NO, NO, NO, NO }, 136c0b746e5SOllivier Robert { "", "", "", "" }, 137c0b746e5SOllivier Robert "print version number" }, 138c0b746e5SOllivier Robert { 0, 0, { NO, NO, NO, NO }, 139c0b746e5SOllivier Robert { "", "", "", "" }, "" } 140c0b746e5SOllivier Robert }; 141c0b746e5SOllivier Robert 142c0b746e5SOllivier Robert 143c0b746e5SOllivier Robert /* 144c0b746e5SOllivier Robert * Default values we use. 145c0b746e5SOllivier Robert */ 146c0b746e5SOllivier Robert #define DEFTIMEOUT (5) /* 5 second time out */ 147c0b746e5SOllivier Robert #define DEFSTIMEOUT (2) /* 2 second time out after first */ 148c0b746e5SOllivier Robert #define DEFDELAY 0x51EB852 /* 20 milliseconds, l_fp fraction */ 149c0b746e5SOllivier Robert #define DEFHOST "localhost" /* default host name */ 150c0b746e5SOllivier Robert #define LENHOSTNAME 256 /* host name is 256 characters long */ 151c0b746e5SOllivier Robert #define MAXCMDS 100 /* maximum commands on cmd line */ 152c0b746e5SOllivier Robert #define MAXHOSTS 200 /* maximum hosts on cmd line */ 153c0b746e5SOllivier Robert #define MAXLINE 512 /* maximum line length */ 154c0b746e5SOllivier Robert #define MAXTOKENS (1+MAXARGS+2) /* maximum number of usable tokens */ 155c0b746e5SOllivier Robert 156c0b746e5SOllivier Robert /* 157c0b746e5SOllivier Robert * Some variables used and manipulated locally 158c0b746e5SOllivier Robert */ 159c0b746e5SOllivier Robert static struct timeval tvout = { DEFTIMEOUT, 0 }; /* time out for reads */ 160c0b746e5SOllivier Robert static struct timeval tvsout = { DEFSTIMEOUT, 0 }; /* secondary time out */ 161c0b746e5SOllivier Robert static l_fp delay_time; /* delay time */ 162c0b746e5SOllivier Robert static char currenthost[LENHOSTNAME]; /* current host name */ 163c0b746e5SOllivier Robert static struct sockaddr_in hostaddr = { 0 }; /* host address */ 164c0b746e5SOllivier Robert static int showhostnames = 1; /* show host names by default */ 165c0b746e5SOllivier Robert 166c0b746e5SOllivier Robert static int sockfd; /* fd socket is openned on */ 167c0b746e5SOllivier Robert static int havehost = 0; /* set to 1 when host open */ 168c0b746e5SOllivier Robert struct servent *server_entry = NULL; /* server entry for ntp */ 169c0b746e5SOllivier Robert 170c0b746e5SOllivier Robert #if defined (SYS_WINNT) || defined (SYS_VXWORKS) 171c0b746e5SOllivier Robert char password[9]; 172c0b746e5SOllivier Robert #endif /* SYS_WINNT || SYS_VXWORKS */ 173c0b746e5SOllivier Robert 174c0b746e5SOllivier Robert #ifdef SYS_WINNT 175c0b746e5SOllivier Robert WORD wVersionRequested; 176c0b746e5SOllivier Robert WSADATA wsaData; 177c0b746e5SOllivier Robert DWORD NumberOfBytesWritten; 178c0b746e5SOllivier Robert 179c0b746e5SOllivier Robert HANDLE TimerThreadHandle = NULL; /* 1998/06/03 - Used in ntplib/machines.c */ 180c0b746e5SOllivier Robert void timer(void) { ; }; /* 1998/06/03 - Used in ntplib/machines.c */ 181c0b746e5SOllivier Robert 182c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 183c0b746e5SOllivier Robert 184c0b746e5SOllivier Robert /* 185c0b746e5SOllivier Robert * Holds data returned from queries. We allocate INITDATASIZE 186c0b746e5SOllivier Robert * octets to begin with, increasing this as we need to. 187c0b746e5SOllivier Robert */ 188c0b746e5SOllivier Robert #define INITDATASIZE (sizeof(struct resp_pkt) * 16) 189c0b746e5SOllivier Robert #define INCDATASIZE (sizeof(struct resp_pkt) * 8) 190c0b746e5SOllivier Robert 191c0b746e5SOllivier Robert static char *pktdata; 192c0b746e5SOllivier Robert static int pktdatasize; 193c0b746e5SOllivier Robert 194c0b746e5SOllivier Robert /* 195c0b746e5SOllivier Robert * For commands typed on the command line (with the -c option) 196c0b746e5SOllivier Robert */ 197c0b746e5SOllivier Robert static int numcmds = 0; 198c0b746e5SOllivier Robert static const char *ccmds[MAXCMDS]; 199c0b746e5SOllivier Robert #define ADDCMD(cp) if (numcmds < MAXCMDS) ccmds[numcmds++] = (cp) 200c0b746e5SOllivier Robert 201c0b746e5SOllivier Robert /* 202c0b746e5SOllivier Robert * When multiple hosts are specified. 203c0b746e5SOllivier Robert */ 204c0b746e5SOllivier Robert static int numhosts = 0; 205c0b746e5SOllivier Robert static const char *chosts[MAXHOSTS]; 206c0b746e5SOllivier Robert #define ADDHOST(cp) if (numhosts < MAXHOSTS) chosts[numhosts++] = (cp) 207c0b746e5SOllivier Robert 208c0b746e5SOllivier Robert /* 209c0b746e5SOllivier Robert * Error codes for internal use 210c0b746e5SOllivier Robert */ 211c0b746e5SOllivier Robert #define ERR_INCOMPLETE 16 212c0b746e5SOllivier Robert #define ERR_TIMEOUT 17 213c0b746e5SOllivier Robert 214c0b746e5SOllivier Robert /* 215c0b746e5SOllivier Robert * Macro definitions we use 216c0b746e5SOllivier Robert */ 217c0b746e5SOllivier Robert #define ISSPACE(c) ((c) == ' ' || (c) == '\t') 218c0b746e5SOllivier Robert #define ISEOL(c) ((c) == '\n' || (c) == '\r' || (c) == '\0') 219c0b746e5SOllivier Robert #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) 220c0b746e5SOllivier Robert 221c0b746e5SOllivier Robert /* 222c0b746e5SOllivier Robert * For converting time stamps to dates 223c0b746e5SOllivier Robert */ 224c0b746e5SOllivier Robert #define JAN_1970 2208988800 /* 1970 - 1900 in seconds */ 225c0b746e5SOllivier Robert 226c0b746e5SOllivier Robert /* 227c0b746e5SOllivier Robert * Jump buffer for longjumping back to the command level 228c0b746e5SOllivier Robert */ 229c0b746e5SOllivier Robert static jmp_buf interrupt_buf; 230c0b746e5SOllivier Robert static volatile int jump = 0; 231c0b746e5SOllivier Robert 232c0b746e5SOllivier Robert /* 233c0b746e5SOllivier Robert * Pointer to current output unit 234c0b746e5SOllivier Robert */ 235c0b746e5SOllivier Robert static FILE *current_output; 236c0b746e5SOllivier Robert 237c0b746e5SOllivier Robert /* 238c0b746e5SOllivier Robert * Command table imported from ntpdc_ops.c 239c0b746e5SOllivier Robert */ 240c0b746e5SOllivier Robert extern struct xcmd opcmds[]; 241c0b746e5SOllivier Robert 242c0b746e5SOllivier Robert char *progname; 243c0b746e5SOllivier Robert volatile int debug; 244c0b746e5SOllivier Robert 245c0b746e5SOllivier Robert #ifdef NO_MAIN_ALLOWED 246c0b746e5SOllivier Robert CALL(ntpdc,"ntpdc",ntpdcmain); 247c0b746e5SOllivier Robert #else 248c0b746e5SOllivier Robert int 249c0b746e5SOllivier Robert main( 250c0b746e5SOllivier Robert int argc, 251c0b746e5SOllivier Robert char *argv[] 252c0b746e5SOllivier Robert ) 253c0b746e5SOllivier Robert { 254c0b746e5SOllivier Robert return ntpdcmain(argc, argv); 255c0b746e5SOllivier Robert } 256c0b746e5SOllivier Robert #endif 257c0b746e5SOllivier Robert 258c0b746e5SOllivier Robert #ifdef SYS_VXWORKS 259c0b746e5SOllivier Robert void clear_globals(void) 260c0b746e5SOllivier Robert { 261c0b746e5SOllivier Robert extern int ntp_optind; 262c0b746e5SOllivier Robert extern char *ntp_optarg; 263c0b746e5SOllivier Robert showhostnames = 0; /* show host names by default */ 264c0b746e5SOllivier Robert ntp_optind = 0; 265c0b746e5SOllivier Robert ntp_optarg = 0; 266c0b746e5SOllivier Robert server_entry = NULL; /* server entry for ntp */ 267c0b746e5SOllivier Robert havehost = 0; /* set to 1 when host open */ 268c0b746e5SOllivier Robert numcmds = 0; 269c0b746e5SOllivier Robert numhosts = 0; 270c0b746e5SOllivier Robert } 271c0b746e5SOllivier Robert #endif 272c0b746e5SOllivier Robert 273c0b746e5SOllivier Robert /* 274c0b746e5SOllivier Robert * main - parse arguments and handle options 275c0b746e5SOllivier Robert */ 276c0b746e5SOllivier Robert int 277c0b746e5SOllivier Robert ntpdcmain( 278c0b746e5SOllivier Robert int argc, 279c0b746e5SOllivier Robert char *argv[] 280c0b746e5SOllivier Robert ) 281c0b746e5SOllivier Robert { 282c0b746e5SOllivier Robert int c; 283c0b746e5SOllivier Robert int errflg = 0; 284c0b746e5SOllivier Robert extern int ntp_optind; 285c0b746e5SOllivier Robert extern char *ntp_optarg; 286c0b746e5SOllivier Robert 287c0b746e5SOllivier Robert delay_time.l_ui = 0; 288c0b746e5SOllivier Robert delay_time.l_uf = DEFDELAY; 289c0b746e5SOllivier Robert 290c0b746e5SOllivier Robert #ifdef SYS_VXWORKS 291c0b746e5SOllivier Robert clear_globals(); 292c0b746e5SOllivier Robert taskPrioritySet(taskIdSelf(), 100 ); 293c0b746e5SOllivier Robert #endif 294c0b746e5SOllivier Robert 295c0b746e5SOllivier Robert progname = argv[0]; 296c0b746e5SOllivier Robert while ((c = ntp_getopt(argc, argv, "c:dilnps")) != EOF) 297c0b746e5SOllivier Robert switch (c) { 298c0b746e5SOllivier Robert case 'c': 299c0b746e5SOllivier Robert ADDCMD(ntp_optarg); 300c0b746e5SOllivier Robert break; 301c0b746e5SOllivier Robert case 'd': 302c0b746e5SOllivier Robert ++debug; 303c0b746e5SOllivier Robert break; 304c0b746e5SOllivier Robert case 'i': 305c0b746e5SOllivier Robert interactive = 1; 306c0b746e5SOllivier Robert break; 307c0b746e5SOllivier Robert case 'l': 308c0b746e5SOllivier Robert ADDCMD("listpeers"); 309c0b746e5SOllivier Robert break; 310c0b746e5SOllivier Robert case 'n': 311c0b746e5SOllivier Robert showhostnames = 0; 312c0b746e5SOllivier Robert break; 313c0b746e5SOllivier Robert case 'p': 314c0b746e5SOllivier Robert ADDCMD("peers"); 315c0b746e5SOllivier Robert break; 316c0b746e5SOllivier Robert case 's': 317c0b746e5SOllivier Robert ADDCMD("dmpeers"); 318c0b746e5SOllivier Robert break; 319c0b746e5SOllivier Robert default: 320c0b746e5SOllivier Robert errflg++; 321c0b746e5SOllivier Robert break; 322c0b746e5SOllivier Robert } 323c0b746e5SOllivier Robert if (errflg) { 324c0b746e5SOllivier Robert (void) fprintf(stderr, 325c0b746e5SOllivier Robert "usage: %s [-dilnps] [-c cmd] host ...\n", 326c0b746e5SOllivier Robert progname); 327c0b746e5SOllivier Robert exit(2); 328c0b746e5SOllivier Robert } 329c0b746e5SOllivier Robert if (ntp_optind == argc) { 330c0b746e5SOllivier Robert ADDHOST(DEFHOST); 331c0b746e5SOllivier Robert } else { 332c0b746e5SOllivier Robert for (; ntp_optind < argc; ntp_optind++) 333c0b746e5SOllivier Robert ADDHOST(argv[ntp_optind]); 334c0b746e5SOllivier Robert } 335c0b746e5SOllivier Robert 336c0b746e5SOllivier Robert if (numcmds == 0 && interactive == 0 337c0b746e5SOllivier Robert && isatty(fileno(stdin)) && isatty(fileno(stderr))) { 338c0b746e5SOllivier Robert interactive = 1; 339c0b746e5SOllivier Robert } 340c0b746e5SOllivier Robert 341c0b746e5SOllivier Robert #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */ 342c0b746e5SOllivier Robert if (interactive) 343c0b746e5SOllivier Robert (void) signal_no_reset(SIGINT, abortcmd); 344c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 345c0b746e5SOllivier Robert 346c0b746e5SOllivier Robert /* 347c0b746e5SOllivier Robert * Initialize the packet data buffer 348c0b746e5SOllivier Robert */ 349c0b746e5SOllivier Robert pktdata = (char *)malloc(INITDATASIZE); 350c0b746e5SOllivier Robert if (pktdata == NULL) { 351c0b746e5SOllivier Robert (void) fprintf(stderr, "%s: malloc() failed!\n", progname); 352c0b746e5SOllivier Robert exit(1); 353c0b746e5SOllivier Robert } 354c0b746e5SOllivier Robert pktdatasize = INITDATASIZE; 355c0b746e5SOllivier Robert 356c0b746e5SOllivier Robert #ifdef SYS_WINNT 357c0b746e5SOllivier Robert wVersionRequested = MAKEWORD(1,1); 358c0b746e5SOllivier Robert if (WSAStartup(wVersionRequested, &wsaData)) { 359c0b746e5SOllivier Robert fprintf(stderr, "No useable winsock.dll"); 360c0b746e5SOllivier Robert exit(1); 361c0b746e5SOllivier Robert } 362c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 363c0b746e5SOllivier Robert 364c0b746e5SOllivier Robert if (numcmds == 0) { 365c0b746e5SOllivier Robert (void) openhost(chosts[0]); 366c0b746e5SOllivier Robert getcmds(); 367c0b746e5SOllivier Robert } else { 368c0b746e5SOllivier Robert int ihost; 369c0b746e5SOllivier Robert int icmd; 370c0b746e5SOllivier Robert 371c0b746e5SOllivier Robert for (ihost = 0; ihost < numhosts; ihost++) { 372c0b746e5SOllivier Robert if (openhost(chosts[ihost])) 373c0b746e5SOllivier Robert for (icmd = 0; icmd < numcmds; icmd++) { 374c0b746e5SOllivier Robert if (numhosts > 1) 375c0b746e5SOllivier Robert printf ("--- %s ---\n",chosts[ihost]); 376c0b746e5SOllivier Robert docmd(ccmds[icmd]); 377c0b746e5SOllivier Robert } 378c0b746e5SOllivier Robert } 379c0b746e5SOllivier Robert } 380c0b746e5SOllivier Robert #ifdef SYS_WINNT 381c0b746e5SOllivier Robert WSACleanup(); 382c0b746e5SOllivier Robert #endif 383c0b746e5SOllivier Robert return(0); 384c0b746e5SOllivier Robert } /* main end */ 385c0b746e5SOllivier Robert 386c0b746e5SOllivier Robert 387c0b746e5SOllivier Robert /* 388c0b746e5SOllivier Robert * openhost - open a socket to a host 389c0b746e5SOllivier Robert */ 390c0b746e5SOllivier Robert static int 391c0b746e5SOllivier Robert openhost( 392c0b746e5SOllivier Robert const char *hname 393c0b746e5SOllivier Robert ) 394c0b746e5SOllivier Robert { 395c0b746e5SOllivier Robert u_int32 netnum; 396c0b746e5SOllivier Robert char temphost[LENHOSTNAME]; 397c0b746e5SOllivier Robert 398c0b746e5SOllivier Robert if (server_entry == NULL) { 399c0b746e5SOllivier Robert server_entry = getservbyname("ntp", "udp"); 400c0b746e5SOllivier Robert if (server_entry == NULL) { 401c0b746e5SOllivier Robert #ifdef VMS /* UCX getservbyname() doesn't work [yet], but we do know better */ 402c0b746e5SOllivier Robert server_entry = (struct servent *) 403c0b746e5SOllivier Robert malloc(sizeof(struct servent)); 404c0b746e5SOllivier Robert server_entry->s_port = htons(NTP_PORT); 405c0b746e5SOllivier Robert #else 406c0b746e5SOllivier Robert (void) fprintf(stderr, "%s: ntp/udp: unknown service\n", 407c0b746e5SOllivier Robert progname); 408c0b746e5SOllivier Robert exit(1); 409c0b746e5SOllivier Robert #endif /* VMS & UCX */ 410c0b746e5SOllivier Robert } 411c0b746e5SOllivier Robert if (debug > 2) 412c0b746e5SOllivier Robert printf("Got ntp/udp service entry\n"); 413c0b746e5SOllivier Robert } 414c0b746e5SOllivier Robert 415c0b746e5SOllivier Robert if (!getnetnum(hname, &netnum, temphost)) 416c0b746e5SOllivier Robert return 0; 417c0b746e5SOllivier Robert 418c0b746e5SOllivier Robert if (debug > 2) 419c0b746e5SOllivier Robert printf("Opening host %s\n", temphost); 420c0b746e5SOllivier Robert 421c0b746e5SOllivier Robert if (havehost == 1) { 422c0b746e5SOllivier Robert if (debug > 2) 423c0b746e5SOllivier Robert printf("Closing old host %s\n", currenthost); 424c0b746e5SOllivier Robert (void) closesocket(sockfd); 425c0b746e5SOllivier Robert havehost = 0; 426c0b746e5SOllivier Robert } 427c0b746e5SOllivier Robert (void) strcpy(currenthost, temphost); 428c0b746e5SOllivier Robert 429c0b746e5SOllivier Robert hostaddr.sin_family = AF_INET; 430c0b746e5SOllivier Robert #ifndef SYS_VXWORKS 431c0b746e5SOllivier Robert hostaddr.sin_port = server_entry->s_port; 432c0b746e5SOllivier Robert #else 433c0b746e5SOllivier Robert hostaddr.sin_port = htons(SERVER_PORT_NUM); 434c0b746e5SOllivier Robert #endif 435c0b746e5SOllivier Robert hostaddr.sin_addr.s_addr = netnum; 436c0b746e5SOllivier Robert 437c0b746e5SOllivier Robert #ifdef SYS_WINNT 438c0b746e5SOllivier Robert { 439c0b746e5SOllivier Robert int optionValue = SO_SYNCHRONOUS_NONALERT; 440c0b746e5SOllivier Robert int err; 441c0b746e5SOllivier Robert err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&optionValue, sizeof(optionValue)); 442c0b746e5SOllivier Robert if (err != NO_ERROR) { 443c0b746e5SOllivier Robert (void) fprintf(stderr, "cannot open nonoverlapped sockets\n"); 444c0b746e5SOllivier Robert exit(1); 445c0b746e5SOllivier Robert } 446c0b746e5SOllivier Robert } 447c0b746e5SOllivier Robert 448c0b746e5SOllivier Robert sockfd = socket(AF_INET, SOCK_DGRAM, 0); 449c0b746e5SOllivier Robert if (sockfd == INVALID_SOCKET) { 450c0b746e5SOllivier Robert error("socket", "", ""); 451c0b746e5SOllivier Robert exit(-1); 452c0b746e5SOllivier Robert } 453c0b746e5SOllivier Robert #else 454c0b746e5SOllivier Robert sockfd = socket(AF_INET, SOCK_DGRAM, 0); 455c0b746e5SOllivier Robert if (sockfd == -1) 456c0b746e5SOllivier Robert error("socket", "", ""); 457c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 458c0b746e5SOllivier Robert 459c0b746e5SOllivier Robert 460c0b746e5SOllivier Robert #ifdef NEED_RCVBUF_SLOP 461c0b746e5SOllivier Robert # ifdef SO_RCVBUF 462c0b746e5SOllivier Robert { 463c0b746e5SOllivier Robert int rbufsize = INITDATASIZE + 2048; /* 2K for slop */ 464c0b746e5SOllivier Robert 465c0b746e5SOllivier Robert if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, 466c0b746e5SOllivier Robert &rbufsize, sizeof(int)) == -1) 467c0b746e5SOllivier Robert error("setsockopt", "", ""); 468c0b746e5SOllivier Robert } 469c0b746e5SOllivier Robert # endif 470c0b746e5SOllivier Robert #endif 471c0b746e5SOllivier Robert 472c0b746e5SOllivier Robert if (connect(sockfd, (struct sockaddr *)&hostaddr, 473c0b746e5SOllivier Robert sizeof(hostaddr)) == -1) 474c0b746e5SOllivier Robert error("connect", "", ""); 475c0b746e5SOllivier Robert 476c0b746e5SOllivier Robert havehost = 1; 477c0b746e5SOllivier Robert return 1; 478c0b746e5SOllivier Robert } 479c0b746e5SOllivier Robert 480c0b746e5SOllivier Robert 481c0b746e5SOllivier Robert /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */ 482c0b746e5SOllivier Robert /* 483c0b746e5SOllivier Robert * sendpkt - send a packet to the remote host 484c0b746e5SOllivier Robert */ 485c0b746e5SOllivier Robert static int 486c0b746e5SOllivier Robert sendpkt( 487c0b746e5SOllivier Robert char *xdata, 488c0b746e5SOllivier Robert int xdatalen 489c0b746e5SOllivier Robert ) 490c0b746e5SOllivier Robert { 491224ba2bdSOllivier Robert if (send(sockfd, xdata, (size_t)xdatalen, 0) == -1) { 492c0b746e5SOllivier Robert warning("write to %s failed", currenthost, ""); 493c0b746e5SOllivier Robert return -1; 494c0b746e5SOllivier Robert } 495c0b746e5SOllivier Robert 496c0b746e5SOllivier Robert return 0; 497c0b746e5SOllivier Robert } 498c0b746e5SOllivier Robert 499c0b746e5SOllivier Robert 500c0b746e5SOllivier Robert /* 501c0b746e5SOllivier Robert * growpktdata - grow the packet data area 502c0b746e5SOllivier Robert */ 503c0b746e5SOllivier Robert static void 504c0b746e5SOllivier Robert growpktdata(void) 505c0b746e5SOllivier Robert { 506c0b746e5SOllivier Robert pktdatasize += INCDATASIZE; 507c0b746e5SOllivier Robert pktdata = (char *)realloc(pktdata, (unsigned)pktdatasize); 508c0b746e5SOllivier Robert if (pktdata == 0) { 509c0b746e5SOllivier Robert (void) fprintf(stderr, "%s: realloc() failed!\n", progname); 510c0b746e5SOllivier Robert exit(1); 511c0b746e5SOllivier Robert } 512c0b746e5SOllivier Robert } 513c0b746e5SOllivier Robert 514c0b746e5SOllivier Robert 515c0b746e5SOllivier Robert /* 516c0b746e5SOllivier Robert * getresponse - get a (series of) response packet(s) and return the data 517c0b746e5SOllivier Robert */ 518c0b746e5SOllivier Robert static int 519c0b746e5SOllivier Robert getresponse( 520c0b746e5SOllivier Robert int implcode, 521c0b746e5SOllivier Robert int reqcode, 522c0b746e5SOllivier Robert int *ritems, 523c0b746e5SOllivier Robert int *rsize, 524c0b746e5SOllivier Robert char **rdata 525c0b746e5SOllivier Robert ) 526c0b746e5SOllivier Robert { 527c0b746e5SOllivier Robert struct resp_pkt rpkt; 528c0b746e5SOllivier Robert struct timeval tvo; 529c0b746e5SOllivier Robert int items; 530c0b746e5SOllivier Robert int size; 531c0b746e5SOllivier Robert int datasize; 532c0b746e5SOllivier Robert char *datap; 533c0b746e5SOllivier Robert char haveseq[MAXSEQ+1]; 534c0b746e5SOllivier Robert int firstpkt; 535c0b746e5SOllivier Robert int lastseq; 536c0b746e5SOllivier Robert int numrecv; 537c0b746e5SOllivier Robert int seq; 538c0b746e5SOllivier Robert fd_set fds; 539c0b746e5SOllivier Robert int n; 540c0b746e5SOllivier Robert 541c0b746e5SOllivier Robert /* 542c0b746e5SOllivier Robert * This is pretty tricky. We may get between 1 and many packets 543c0b746e5SOllivier Robert * back in response to the request. We peel the data out of 544c0b746e5SOllivier Robert * each packet and collect it in one long block. When the last 545c0b746e5SOllivier Robert * packet in the sequence is received we'll know how many we 546c0b746e5SOllivier Robert * should have had. Note we use one long time out, should reconsider. 547c0b746e5SOllivier Robert */ 548c0b746e5SOllivier Robert *ritems = 0; 549c0b746e5SOllivier Robert *rsize = 0; 550c0b746e5SOllivier Robert firstpkt = 1; 551c0b746e5SOllivier Robert numrecv = 0; 552c0b746e5SOllivier Robert *rdata = datap = pktdata; 553c0b746e5SOllivier Robert lastseq = 999; /* too big to be a sequence number */ 554c0b746e5SOllivier Robert memset(haveseq, 0, sizeof(haveseq)); 555c0b746e5SOllivier Robert FD_ZERO(&fds); 556c0b746e5SOllivier Robert 557c0b746e5SOllivier Robert again: 558c0b746e5SOllivier Robert if (firstpkt) 559c0b746e5SOllivier Robert tvo = tvout; 560c0b746e5SOllivier Robert else 561c0b746e5SOllivier Robert tvo = tvsout; 562c0b746e5SOllivier Robert 563c0b746e5SOllivier Robert FD_SET(sockfd, &fds); 564c0b746e5SOllivier Robert n = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvo); 565c0b746e5SOllivier Robert 566c0b746e5SOllivier Robert if (n == -1) { 567c0b746e5SOllivier Robert warning("select fails", "", ""); 568c0b746e5SOllivier Robert return -1; 569c0b746e5SOllivier Robert } 570c0b746e5SOllivier Robert if (n == 0) { 571c0b746e5SOllivier Robert /* 572c0b746e5SOllivier Robert * Timed out. Return what we have 573c0b746e5SOllivier Robert */ 574c0b746e5SOllivier Robert if (firstpkt) { 575c0b746e5SOllivier Robert (void) fprintf(stderr, 576c0b746e5SOllivier Robert "%s: timed out, nothing received\n", currenthost); 577c0b746e5SOllivier Robert return ERR_TIMEOUT; 578c0b746e5SOllivier Robert } else { 579c0b746e5SOllivier Robert (void) fprintf(stderr, 580c0b746e5SOllivier Robert "%s: timed out with incomplete data\n", 581c0b746e5SOllivier Robert currenthost); 582c0b746e5SOllivier Robert if (debug) { 583c0b746e5SOllivier Robert printf("Received sequence numbers"); 584c0b746e5SOllivier Robert for (n = 0; n <= MAXSEQ; n++) 585c0b746e5SOllivier Robert if (haveseq[n]) 586c0b746e5SOllivier Robert printf(" %d,", n); 587c0b746e5SOllivier Robert if (lastseq != 999) 588c0b746e5SOllivier Robert printf(" last frame received\n"); 589c0b746e5SOllivier Robert else 590c0b746e5SOllivier Robert printf(" last frame not received\n"); 591c0b746e5SOllivier Robert } 592c0b746e5SOllivier Robert return ERR_INCOMPLETE; 593c0b746e5SOllivier Robert } 594c0b746e5SOllivier Robert } 595c0b746e5SOllivier Robert 596c0b746e5SOllivier Robert n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0); 597c0b746e5SOllivier Robert if (n == -1) { 598c0b746e5SOllivier Robert warning("read", "", ""); 599c0b746e5SOllivier Robert return -1; 600c0b746e5SOllivier Robert } 601c0b746e5SOllivier Robert 602c0b746e5SOllivier Robert 603c0b746e5SOllivier Robert /* 604c0b746e5SOllivier Robert * Check for format errors. Bug proofing. 605c0b746e5SOllivier Robert */ 606c0b746e5SOllivier Robert if (n < RESP_HEADER_SIZE) { 607c0b746e5SOllivier Robert if (debug) 608c0b746e5SOllivier Robert printf("Short (%d byte) packet received\n", n); 609c0b746e5SOllivier Robert goto again; 610c0b746e5SOllivier Robert } 611c0b746e5SOllivier Robert if (INFO_VERSION(rpkt.rm_vn_mode) > NTP_VERSION || 612c0b746e5SOllivier Robert INFO_VERSION(rpkt.rm_vn_mode) < NTP_OLDVERSION) { 613c0b746e5SOllivier Robert if (debug) 614c0b746e5SOllivier Robert printf("Packet received with version %d\n", 615c0b746e5SOllivier Robert INFO_VERSION(rpkt.rm_vn_mode)); 616c0b746e5SOllivier Robert goto again; 617c0b746e5SOllivier Robert } 618c0b746e5SOllivier Robert if (INFO_MODE(rpkt.rm_vn_mode) != MODE_PRIVATE) { 619c0b746e5SOllivier Robert if (debug) 620c0b746e5SOllivier Robert printf("Packet received with mode %d\n", 621c0b746e5SOllivier Robert INFO_MODE(rpkt.rm_vn_mode)); 622c0b746e5SOllivier Robert goto again; 623c0b746e5SOllivier Robert } 624c0b746e5SOllivier Robert if (INFO_IS_AUTH(rpkt.auth_seq)) { 625c0b746e5SOllivier Robert if (debug) 626c0b746e5SOllivier Robert printf("Encrypted packet received\n"); 627c0b746e5SOllivier Robert goto again; 628c0b746e5SOllivier Robert } 629c0b746e5SOllivier Robert if (!ISRESPONSE(rpkt.rm_vn_mode)) { 630c0b746e5SOllivier Robert if (debug) 631c0b746e5SOllivier Robert printf("Received request packet, wanted response\n"); 632c0b746e5SOllivier Robert goto again; 633c0b746e5SOllivier Robert } 634c0b746e5SOllivier Robert if (INFO_MBZ(rpkt.mbz_itemsize) != 0) { 635c0b746e5SOllivier Robert if (debug) 636c0b746e5SOllivier Robert printf("Received packet with nonzero MBZ field!\n"); 637c0b746e5SOllivier Robert goto again; 638c0b746e5SOllivier Robert } 639c0b746e5SOllivier Robert 640c0b746e5SOllivier Robert /* 641c0b746e5SOllivier Robert * Check implementation/request. Could be old data getting to us. 642c0b746e5SOllivier Robert */ 643c0b746e5SOllivier Robert if (rpkt.implementation != implcode || rpkt.request != reqcode) { 644c0b746e5SOllivier Robert if (debug) 645c0b746e5SOllivier Robert printf( 646c0b746e5SOllivier Robert "Received implementation/request of %d/%d, wanted %d/%d", 647c0b746e5SOllivier Robert rpkt.implementation, rpkt.request, 648c0b746e5SOllivier Robert implcode, reqcode); 649c0b746e5SOllivier Robert goto again; 650c0b746e5SOllivier Robert } 651c0b746e5SOllivier Robert 652c0b746e5SOllivier Robert /* 653c0b746e5SOllivier Robert * Check the error code. If non-zero, return it. 654c0b746e5SOllivier Robert */ 655c0b746e5SOllivier Robert if (INFO_ERR(rpkt.err_nitems) != INFO_OKAY) { 656c0b746e5SOllivier Robert if (debug && ISMORE(rpkt.rm_vn_mode)) { 657c0b746e5SOllivier Robert printf("Error code %d received on not-final packet\n", 658c0b746e5SOllivier Robert INFO_ERR(rpkt.err_nitems)); 659c0b746e5SOllivier Robert } 660c0b746e5SOllivier Robert return (int)INFO_ERR(rpkt.err_nitems); 661c0b746e5SOllivier Robert } 662c0b746e5SOllivier Robert 663c0b746e5SOllivier Robert 664c0b746e5SOllivier Robert /* 665c0b746e5SOllivier Robert * Collect items and size. Make sure they make sense. 666c0b746e5SOllivier Robert */ 667c0b746e5SOllivier Robert items = INFO_NITEMS(rpkt.err_nitems); 668c0b746e5SOllivier Robert size = INFO_ITEMSIZE(rpkt.mbz_itemsize); 669c0b746e5SOllivier Robert 670c0b746e5SOllivier Robert if ((datasize = items*size) > (n-RESP_HEADER_SIZE)) { 671c0b746e5SOllivier Robert if (debug) 672c0b746e5SOllivier Robert printf( 673c0b746e5SOllivier Robert "Received items %d, size %d (total %d), data in packet is %d\n", 674c0b746e5SOllivier Robert items, size, datasize, n-RESP_HEADER_SIZE); 675c0b746e5SOllivier Robert goto again; 676c0b746e5SOllivier Robert } 677c0b746e5SOllivier Robert 678c0b746e5SOllivier Robert /* 679c0b746e5SOllivier Robert * If this isn't our first packet, make sure the size matches 680c0b746e5SOllivier Robert * the other ones. 681c0b746e5SOllivier Robert */ 682c0b746e5SOllivier Robert if (!firstpkt && size != *rsize) { 683c0b746e5SOllivier Robert if (debug) 684c0b746e5SOllivier Robert printf("Received itemsize %d, previous %d\n", 685c0b746e5SOllivier Robert size, *rsize); 686c0b746e5SOllivier Robert goto again; 687c0b746e5SOllivier Robert } 688c0b746e5SOllivier Robert 689c0b746e5SOllivier Robert /* 690c0b746e5SOllivier Robert * If we've received this before, toss it 691c0b746e5SOllivier Robert */ 692c0b746e5SOllivier Robert seq = INFO_SEQ(rpkt.auth_seq); 693c0b746e5SOllivier Robert if (haveseq[seq]) { 694c0b746e5SOllivier Robert if (debug) 695c0b746e5SOllivier Robert printf("Received duplicate sequence number %d\n", seq); 696c0b746e5SOllivier Robert goto again; 697c0b746e5SOllivier Robert } 698c0b746e5SOllivier Robert haveseq[seq] = 1; 699c0b746e5SOllivier Robert 700c0b746e5SOllivier Robert /* 701c0b746e5SOllivier Robert * If this is the last in the sequence, record that. 702c0b746e5SOllivier Robert */ 703c0b746e5SOllivier Robert if (!ISMORE(rpkt.rm_vn_mode)) { 704c0b746e5SOllivier Robert if (lastseq != 999) { 705c0b746e5SOllivier Robert printf("Received second end sequence packet\n"); 706c0b746e5SOllivier Robert goto again; 707c0b746e5SOllivier Robert } 708c0b746e5SOllivier Robert lastseq = seq; 709c0b746e5SOllivier Robert } 710c0b746e5SOllivier Robert 711c0b746e5SOllivier Robert /* 712c0b746e5SOllivier Robert * So far, so good. Copy this data into the output array. 713c0b746e5SOllivier Robert */ 714c0b746e5SOllivier Robert if ((datap + datasize) > (pktdata + pktdatasize)) { 715c0b746e5SOllivier Robert int offset = datap - pktdata; 716c0b746e5SOllivier Robert growpktdata(); 717c0b746e5SOllivier Robert *rdata = pktdata; /* might have been realloced ! */ 718c0b746e5SOllivier Robert datap = pktdata + offset; 719c0b746e5SOllivier Robert } 720c0b746e5SOllivier Robert memmove(datap, (char *)rpkt.data, (unsigned)datasize); 721c0b746e5SOllivier Robert datap += datasize; 722c0b746e5SOllivier Robert if (firstpkt) { 723c0b746e5SOllivier Robert firstpkt = 0; 724c0b746e5SOllivier Robert *rsize = size; 725c0b746e5SOllivier Robert } 726c0b746e5SOllivier Robert *ritems += items; 727c0b746e5SOllivier Robert 728c0b746e5SOllivier Robert /* 729c0b746e5SOllivier Robert * Finally, check the count of received packets. If we've got them 730c0b746e5SOllivier Robert * all, return 731c0b746e5SOllivier Robert */ 732c0b746e5SOllivier Robert ++numrecv; 733c0b746e5SOllivier Robert if (numrecv <= lastseq) 734c0b746e5SOllivier Robert goto again; 735c0b746e5SOllivier Robert return INFO_OKAY; 736c0b746e5SOllivier Robert } 737c0b746e5SOllivier Robert 738c0b746e5SOllivier Robert 739c0b746e5SOllivier Robert /* 740c0b746e5SOllivier Robert * sendrequest - format and send a request packet 741c0b746e5SOllivier Robert */ 742c0b746e5SOllivier Robert static int 743c0b746e5SOllivier Robert sendrequest( 744c0b746e5SOllivier Robert int implcode, 745c0b746e5SOllivier Robert int reqcode, 746c0b746e5SOllivier Robert int auth, 747c0b746e5SOllivier Robert int qitems, 748c0b746e5SOllivier Robert int qsize, 749c0b746e5SOllivier Robert char *qdata 750c0b746e5SOllivier Robert ) 751c0b746e5SOllivier Robert { 752c0b746e5SOllivier Robert struct req_pkt qpkt; 753c0b746e5SOllivier Robert int datasize; 754c0b746e5SOllivier Robert 755c0b746e5SOllivier Robert memset((char *)&qpkt, 0, sizeof qpkt); 756c0b746e5SOllivier Robert 757c0b746e5SOllivier Robert qpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0); 758c0b746e5SOllivier Robert qpkt.implementation = (u_char)implcode; 759c0b746e5SOllivier Robert qpkt.request = (u_char)reqcode; 760c0b746e5SOllivier Robert 761c0b746e5SOllivier Robert datasize = qitems * qsize; 762c0b746e5SOllivier Robert if (datasize != 0 && qdata != NULL) { 763c0b746e5SOllivier Robert memmove((char *)qpkt.data, qdata, (unsigned)datasize); 764c0b746e5SOllivier Robert qpkt.err_nitems = ERR_NITEMS(0, qitems); 765c0b746e5SOllivier Robert qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize); 766c0b746e5SOllivier Robert } else { 767c0b746e5SOllivier Robert qpkt.err_nitems = ERR_NITEMS(0, 0); 768c0b746e5SOllivier Robert qpkt.mbz_itemsize = MBZ_ITEMSIZE(0); 769c0b746e5SOllivier Robert } 770c0b746e5SOllivier Robert 771c0b746e5SOllivier Robert if (!auth) { 772c0b746e5SOllivier Robert qpkt.auth_seq = AUTH_SEQ(0, 0); 773c0b746e5SOllivier Robert return sendpkt((char *)&qpkt, REQ_LEN_NOMAC); 774c0b746e5SOllivier Robert } else { 775c0b746e5SOllivier Robert l_fp ts; 776c0b746e5SOllivier Robert int maclen = 0; 777c0b746e5SOllivier Robert const char *pass = "\0"; 778c0b746e5SOllivier Robert 779c0b746e5SOllivier Robert if (info_auth_keyid == 0) { 780c0b746e5SOllivier Robert maclen = getkeyid("Keyid: "); 781c0b746e5SOllivier Robert if (maclen == 0) { 782c0b746e5SOllivier Robert (void) fprintf(stderr, 783c0b746e5SOllivier Robert "Invalid key identifier\n"); 784c0b746e5SOllivier Robert return 1; 785c0b746e5SOllivier Robert } 786c0b746e5SOllivier Robert info_auth_keyid = maclen; 787c0b746e5SOllivier Robert } 788c0b746e5SOllivier Robert if (!authistrusted(info_auth_keyid)) { 789c0b746e5SOllivier Robert pass = getpass((info_auth_keytype == KEY_TYPE_DES) 790c0b746e5SOllivier Robert ? "DES Password: " : "MD5 Password: "); 791c0b746e5SOllivier Robert if (*pass == '\0') { 792c0b746e5SOllivier Robert (void) fprintf(stderr, 793c0b746e5SOllivier Robert "Invalid password\n"); 794c0b746e5SOllivier Robert return (1); 795c0b746e5SOllivier Robert } 796c0b746e5SOllivier Robert } 797c0b746e5SOllivier Robert authusekey(info_auth_keyid, info_auth_keytype, (const u_char *)pass); 798c0b746e5SOllivier Robert authtrust(info_auth_keyid, 1); 799c0b746e5SOllivier Robert qpkt.auth_seq = AUTH_SEQ(1, 0); 800c0b746e5SOllivier Robert qpkt.keyid = htonl(info_auth_keyid); 801c0b746e5SOllivier Robert get_systime(&ts); 802c0b746e5SOllivier Robert L_ADD(&ts, &delay_time); 803c0b746e5SOllivier Robert HTONL_FP(&ts, &qpkt.tstamp); 804c0b746e5SOllivier Robert maclen = authencrypt(info_auth_keyid, (u_int32 *)&qpkt, 805c0b746e5SOllivier Robert REQ_LEN_NOMAC); 806c0b746e5SOllivier Robert if (maclen == 0) { 807c0b746e5SOllivier Robert (void) fprintf(stderr, "Key not found\n"); 808c0b746e5SOllivier Robert return (1); 809c0b746e5SOllivier Robert } 810c0b746e5SOllivier Robert return sendpkt((char *)&qpkt, (int)(REQ_LEN_NOMAC + maclen)); 811c0b746e5SOllivier Robert } 812c0b746e5SOllivier Robert /*NOTREACHED*/ 813c0b746e5SOllivier Robert } 814c0b746e5SOllivier Robert 815c0b746e5SOllivier Robert 816c0b746e5SOllivier Robert /* 817c0b746e5SOllivier Robert * doquery - send a request and process the response 818c0b746e5SOllivier Robert */ 819c0b746e5SOllivier Robert int 820c0b746e5SOllivier Robert doquery( 821c0b746e5SOllivier Robert int implcode, 822c0b746e5SOllivier Robert int reqcode, 823c0b746e5SOllivier Robert int auth, 824c0b746e5SOllivier Robert int qitems, 825c0b746e5SOllivier Robert int qsize, 826c0b746e5SOllivier Robert char *qdata, 827c0b746e5SOllivier Robert int *ritems, 828c0b746e5SOllivier Robert int *rsize, 829c0b746e5SOllivier Robert char **rdata, 830c0b746e5SOllivier Robert int quiet_mask 831c0b746e5SOllivier Robert ) 832c0b746e5SOllivier Robert { 833c0b746e5SOllivier Robert int res; 834c0b746e5SOllivier Robert char junk[512]; 835c0b746e5SOllivier Robert fd_set fds; 836c0b746e5SOllivier Robert struct timeval tvzero; 837c0b746e5SOllivier Robert 838c0b746e5SOllivier Robert /* 839c0b746e5SOllivier Robert * Check to make sure host is open 840c0b746e5SOllivier Robert */ 841c0b746e5SOllivier Robert if (!havehost) { 842c0b746e5SOllivier Robert (void) fprintf(stderr, "***No host open, use `host' command\n"); 843c0b746e5SOllivier Robert return -1; 844c0b746e5SOllivier Robert } 845c0b746e5SOllivier Robert 846c0b746e5SOllivier Robert /* 847c0b746e5SOllivier Robert * Poll the socket and clear out any pending data 848c0b746e5SOllivier Robert */ 849c0b746e5SOllivier Robert do { 850c0b746e5SOllivier Robert tvzero.tv_sec = tvzero.tv_usec = 0; 851c0b746e5SOllivier Robert FD_ZERO(&fds); 852c0b746e5SOllivier Robert FD_SET(sockfd, &fds); 853c0b746e5SOllivier Robert res = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero); 854c0b746e5SOllivier Robert 855c0b746e5SOllivier Robert if (res == -1) { 856c0b746e5SOllivier Robert warning("polling select", "", ""); 857c0b746e5SOllivier Robert return -1; 858c0b746e5SOllivier Robert } else if (res > 0) 859c0b746e5SOllivier Robert 860c0b746e5SOllivier Robert (void) recv(sockfd, junk, sizeof junk, 0); 861c0b746e5SOllivier Robert } while (res > 0); 862c0b746e5SOllivier Robert 863c0b746e5SOllivier Robert 864c0b746e5SOllivier Robert /* 865c0b746e5SOllivier Robert * send a request 866c0b746e5SOllivier Robert */ 867c0b746e5SOllivier Robert res = sendrequest(implcode, reqcode, auth, qitems, qsize, qdata); 868c0b746e5SOllivier Robert if (res != 0) 869c0b746e5SOllivier Robert return res; 870c0b746e5SOllivier Robert 871c0b746e5SOllivier Robert /* 872c0b746e5SOllivier Robert * Get the response. If we got a standard error, print a message 873c0b746e5SOllivier Robert */ 874c0b746e5SOllivier Robert res = getresponse(implcode, reqcode, ritems, rsize, rdata); 875c0b746e5SOllivier Robert 876c0b746e5SOllivier Robert /* log error message if not told to be quiet */ 877c0b746e5SOllivier Robert if ((res > 0) && (((1 << res) & quiet_mask) == 0)) { 878c0b746e5SOllivier Robert switch(res) { 879c0b746e5SOllivier Robert case INFO_ERR_IMPL: 880c0b746e5SOllivier Robert (void) fprintf(stderr, 881c0b746e5SOllivier Robert "***Server implementation incompatable with our own\n"); 882c0b746e5SOllivier Robert break; 883c0b746e5SOllivier Robert case INFO_ERR_REQ: 884c0b746e5SOllivier Robert (void) fprintf(stderr, 885c0b746e5SOllivier Robert "***Server doesn't implement this request\n"); 886c0b746e5SOllivier Robert break; 887c0b746e5SOllivier Robert case INFO_ERR_FMT: 888c0b746e5SOllivier Robert (void) fprintf(stderr, 889c0b746e5SOllivier Robert "***Server reports a format error in the received packet (shouldn't happen)\n"); 890c0b746e5SOllivier Robert break; 891c0b746e5SOllivier Robert case INFO_ERR_NODATA: 892c0b746e5SOllivier Robert (void) fprintf(stderr, 893c0b746e5SOllivier Robert "***Server reports data not found\n"); 894c0b746e5SOllivier Robert break; 895c0b746e5SOllivier Robert case INFO_ERR_AUTH: 896c0b746e5SOllivier Robert (void) fprintf(stderr, "***Permission denied\n"); 897c0b746e5SOllivier Robert break; 898c0b746e5SOllivier Robert case ERR_TIMEOUT: 899c0b746e5SOllivier Robert (void) fprintf(stderr, "***Request timed out\n"); 900c0b746e5SOllivier Robert break; 901c0b746e5SOllivier Robert case ERR_INCOMPLETE: 902c0b746e5SOllivier Robert (void) fprintf(stderr, 903c0b746e5SOllivier Robert "***Response from server was incomplete\n"); 904c0b746e5SOllivier Robert break; 905c0b746e5SOllivier Robert default: 906c0b746e5SOllivier Robert (void) fprintf(stderr, 907c0b746e5SOllivier Robert "***Server returns unknown error code %d\n", res); 908c0b746e5SOllivier Robert break; 909c0b746e5SOllivier Robert } 910c0b746e5SOllivier Robert } 911c0b746e5SOllivier Robert return res; 912c0b746e5SOllivier Robert } 913c0b746e5SOllivier Robert 914c0b746e5SOllivier Robert 915c0b746e5SOllivier Robert /* 916c0b746e5SOllivier Robert * getcmds - read commands from the standard input and execute them 917c0b746e5SOllivier Robert */ 918c0b746e5SOllivier Robert static void 919c0b746e5SOllivier Robert getcmds(void) 920c0b746e5SOllivier Robert { 921224ba2bdSOllivier Robert #ifdef HAVE_LIBREADLINE 922224ba2bdSOllivier Robert char *line; 923224ba2bdSOllivier Robert 924224ba2bdSOllivier Robert for (;;) { 925224ba2bdSOllivier Robert if ((line = readline(interactive?prompt:"")) == NULL) return; 926224ba2bdSOllivier Robert if (*line) add_history(line); 927224ba2bdSOllivier Robert docmd(line); 928224ba2bdSOllivier Robert free(line); 929224ba2bdSOllivier Robert } 930224ba2bdSOllivier Robert #else /* not HAVE_LIBREADLINE */ 931c0b746e5SOllivier Robert char line[MAXLINE]; 932c0b746e5SOllivier Robert 933c0b746e5SOllivier Robert for (;;) { 934c0b746e5SOllivier Robert if (interactive) { 935c0b746e5SOllivier Robert #ifdef VMS /* work around a problem with mixing stdout & stderr */ 936c0b746e5SOllivier Robert fputs("",stdout); 937c0b746e5SOllivier Robert #endif 938c0b746e5SOllivier Robert (void) fputs(prompt, stderr); 939c0b746e5SOllivier Robert (void) fflush(stderr); 940c0b746e5SOllivier Robert } 941c0b746e5SOllivier Robert 942c0b746e5SOllivier Robert if (fgets(line, sizeof line, stdin) == NULL) 943c0b746e5SOllivier Robert return; 944c0b746e5SOllivier Robert 945c0b746e5SOllivier Robert docmd(line); 946c0b746e5SOllivier Robert } 947224ba2bdSOllivier Robert #endif /* not HAVE_LIBREADLINE */ 948c0b746e5SOllivier Robert } 949c0b746e5SOllivier Robert 950c0b746e5SOllivier Robert 951c0b746e5SOllivier Robert /* 952c0b746e5SOllivier Robert * abortcmd - catch interrupts and abort the current command 953c0b746e5SOllivier Robert */ 954c0b746e5SOllivier Robert static RETSIGTYPE 955c0b746e5SOllivier Robert abortcmd( 956c0b746e5SOllivier Robert int sig 957c0b746e5SOllivier Robert ) 958c0b746e5SOllivier Robert { 959c0b746e5SOllivier Robert 960c0b746e5SOllivier Robert if (current_output == stdout) 961c0b746e5SOllivier Robert (void) fflush(stdout); 962c0b746e5SOllivier Robert putc('\n', stderr); 963c0b746e5SOllivier Robert (void) fflush(stderr); 964c0b746e5SOllivier Robert if (jump) longjmp(interrupt_buf, 1); 965c0b746e5SOllivier Robert } 966c0b746e5SOllivier Robert 967c0b746e5SOllivier Robert 968c0b746e5SOllivier Robert /* 969c0b746e5SOllivier Robert * docmd - decode the command line and execute a command 970c0b746e5SOllivier Robert */ 971c0b746e5SOllivier Robert static void 972c0b746e5SOllivier Robert docmd( 973c0b746e5SOllivier Robert const char *cmdline 974c0b746e5SOllivier Robert ) 975c0b746e5SOllivier Robert { 976c0b746e5SOllivier Robert char *tokens[1+MAXARGS+2]; 977c0b746e5SOllivier Robert struct parse pcmd; 978c0b746e5SOllivier Robert int ntok; 979c0b746e5SOllivier Robert static int i; 980c0b746e5SOllivier Robert struct xcmd *xcmd; 981c0b746e5SOllivier Robert 982c0b746e5SOllivier Robert /* 983c0b746e5SOllivier Robert * Tokenize the command line. If nothing on it, return. 984c0b746e5SOllivier Robert */ 985c0b746e5SOllivier Robert tokenize(cmdline, tokens, &ntok); 986c0b746e5SOllivier Robert if (ntok == 0) 987c0b746e5SOllivier Robert return; 988c0b746e5SOllivier Robert 989c0b746e5SOllivier Robert /* 990c0b746e5SOllivier Robert * Find the appropriate command description. 991c0b746e5SOllivier Robert */ 992c0b746e5SOllivier Robert i = findcmd(tokens[0], builtins, opcmds, &xcmd); 993c0b746e5SOllivier Robert if (i == 0) { 994c0b746e5SOllivier Robert (void) fprintf(stderr, "***Command `%s' unknown\n", 995c0b746e5SOllivier Robert tokens[0]); 996c0b746e5SOllivier Robert return; 997c0b746e5SOllivier Robert } else if (i >= 2) { 998c0b746e5SOllivier Robert (void) fprintf(stderr, "***Command `%s' ambiguous\n", 999c0b746e5SOllivier Robert tokens[0]); 1000c0b746e5SOllivier Robert return; 1001c0b746e5SOllivier Robert } 1002c0b746e5SOllivier Robert 1003c0b746e5SOllivier Robert /* 1004c0b746e5SOllivier Robert * Save the keyword, then walk through the arguments, interpreting 1005c0b746e5SOllivier Robert * as we go. 1006c0b746e5SOllivier Robert */ 1007c0b746e5SOllivier Robert pcmd.keyword = tokens[0]; 1008c0b746e5SOllivier Robert pcmd.nargs = 0; 1009c0b746e5SOllivier Robert for (i = 0; i < MAXARGS && xcmd->arg[i] != NO; i++) { 1010c0b746e5SOllivier Robert if ((i+1) >= ntok) { 1011c0b746e5SOllivier Robert if (!(xcmd->arg[i] & OPT)) { 1012c0b746e5SOllivier Robert printusage(xcmd, stderr); 1013c0b746e5SOllivier Robert return; 1014c0b746e5SOllivier Robert } 1015c0b746e5SOllivier Robert break; 1016c0b746e5SOllivier Robert } 1017c0b746e5SOllivier Robert if ((xcmd->arg[i] & OPT) && (*tokens[i+1] == '>')) 1018c0b746e5SOllivier Robert break; 1019c0b746e5SOllivier Robert if (!getarg(tokens[i+1], (int)xcmd->arg[i], &pcmd.argval[i])) 1020c0b746e5SOllivier Robert return; 1021c0b746e5SOllivier Robert pcmd.nargs++; 1022c0b746e5SOllivier Robert } 1023c0b746e5SOllivier Robert 1024c0b746e5SOllivier Robert i++; 1025c0b746e5SOllivier Robert if (i < ntok && *tokens[i] == '>') { 1026c0b746e5SOllivier Robert char *fname; 1027c0b746e5SOllivier Robert 1028c0b746e5SOllivier Robert if (*(tokens[i]+1) != '\0') 1029c0b746e5SOllivier Robert fname = tokens[i]+1; 1030c0b746e5SOllivier Robert else if ((i+1) < ntok) 1031c0b746e5SOllivier Robert fname = tokens[i+1]; 1032c0b746e5SOllivier Robert else { 1033c0b746e5SOllivier Robert (void) fprintf(stderr, "***No file for redirect\n"); 1034c0b746e5SOllivier Robert return; 1035c0b746e5SOllivier Robert } 1036c0b746e5SOllivier Robert 1037c0b746e5SOllivier Robert current_output = fopen(fname, "w"); 1038c0b746e5SOllivier Robert if (current_output == NULL) { 1039c0b746e5SOllivier Robert (void) fprintf(stderr, "***Error opening %s: ", fname); 1040c0b746e5SOllivier Robert perror(""); 1041c0b746e5SOllivier Robert return; 1042c0b746e5SOllivier Robert } 1043c0b746e5SOllivier Robert i = 1; /* flag we need a close */ 1044c0b746e5SOllivier Robert } else { 1045c0b746e5SOllivier Robert current_output = stdout; 1046c0b746e5SOllivier Robert i = 0; /* flag no close */ 1047c0b746e5SOllivier Robert } 1048c0b746e5SOllivier Robert 1049c0b746e5SOllivier Robert if (interactive && setjmp(interrupt_buf)) { 1050c0b746e5SOllivier Robert return; 1051c0b746e5SOllivier Robert } else { 1052c0b746e5SOllivier Robert jump = 1; 1053c0b746e5SOllivier Robert (xcmd->handler)(&pcmd, current_output); 1054c0b746e5SOllivier Robert jump = 0; 1055c0b746e5SOllivier Robert if (i) (void) fclose(current_output); 1056c0b746e5SOllivier Robert } 1057c0b746e5SOllivier Robert } 1058c0b746e5SOllivier Robert 1059c0b746e5SOllivier Robert 1060c0b746e5SOllivier Robert /* 1061c0b746e5SOllivier Robert * tokenize - turn a command line into tokens 1062c0b746e5SOllivier Robert */ 1063c0b746e5SOllivier Robert static void 1064c0b746e5SOllivier Robert tokenize( 1065c0b746e5SOllivier Robert const char *line, 1066c0b746e5SOllivier Robert char **tokens, 1067c0b746e5SOllivier Robert int *ntok 1068c0b746e5SOllivier Robert ) 1069c0b746e5SOllivier Robert { 1070c0b746e5SOllivier Robert register const char *cp; 1071c0b746e5SOllivier Robert register char *sp; 1072c0b746e5SOllivier Robert static char tspace[MAXLINE]; 1073c0b746e5SOllivier Robert 1074c0b746e5SOllivier Robert sp = tspace; 1075c0b746e5SOllivier Robert cp = line; 1076c0b746e5SOllivier Robert for (*ntok = 0; *ntok < MAXTOKENS; (*ntok)++) { 1077c0b746e5SOllivier Robert tokens[*ntok] = sp; 1078c0b746e5SOllivier Robert while (ISSPACE(*cp)) 1079c0b746e5SOllivier Robert cp++; 1080c0b746e5SOllivier Robert if (ISEOL(*cp)) 1081c0b746e5SOllivier Robert break; 1082c0b746e5SOllivier Robert do { 1083c0b746e5SOllivier Robert *sp++ = *cp++; 1084c0b746e5SOllivier Robert } while (!ISSPACE(*cp) && !ISEOL(*cp)); 1085c0b746e5SOllivier Robert 1086c0b746e5SOllivier Robert *sp++ = '\0'; 1087c0b746e5SOllivier Robert } 1088c0b746e5SOllivier Robert } 1089c0b746e5SOllivier Robert 1090c0b746e5SOllivier Robert 1091c0b746e5SOllivier Robert 1092c0b746e5SOllivier Robert /* 1093c0b746e5SOllivier Robert * findcmd - find a command in a command description table 1094c0b746e5SOllivier Robert */ 1095c0b746e5SOllivier Robert static int 1096c0b746e5SOllivier Robert findcmd( 1097c0b746e5SOllivier Robert register char *str, 1098c0b746e5SOllivier Robert struct xcmd *clist1, 1099c0b746e5SOllivier Robert struct xcmd *clist2, 1100c0b746e5SOllivier Robert struct xcmd **cmd 1101c0b746e5SOllivier Robert ) 1102c0b746e5SOllivier Robert { 1103c0b746e5SOllivier Robert register struct xcmd *cl; 1104c0b746e5SOllivier Robert register int clen; 1105c0b746e5SOllivier Robert int nmatch; 1106c0b746e5SOllivier Robert struct xcmd *nearmatch = NULL; 1107c0b746e5SOllivier Robert struct xcmd *clist; 1108c0b746e5SOllivier Robert 1109c0b746e5SOllivier Robert clen = strlen(str); 1110c0b746e5SOllivier Robert nmatch = 0; 1111c0b746e5SOllivier Robert if (clist1 != 0) 1112c0b746e5SOllivier Robert clist = clist1; 1113c0b746e5SOllivier Robert else if (clist2 != 0) 1114c0b746e5SOllivier Robert clist = clist2; 1115c0b746e5SOllivier Robert else 1116c0b746e5SOllivier Robert return 0; 1117c0b746e5SOllivier Robert 1118c0b746e5SOllivier Robert again: 1119c0b746e5SOllivier Robert for (cl = clist; cl->keyword != 0; cl++) { 1120c0b746e5SOllivier Robert /* do a first character check, for efficiency */ 1121c0b746e5SOllivier Robert if (*str != *(cl->keyword)) 1122c0b746e5SOllivier Robert continue; 1123c0b746e5SOllivier Robert if (strncmp(str, cl->keyword, (unsigned)clen) == 0) { 1124c0b746e5SOllivier Robert /* 1125c0b746e5SOllivier Robert * Could be extact match, could be approximate. 1126c0b746e5SOllivier Robert * Is exact if the length of the keyword is the 1127c0b746e5SOllivier Robert * same as the str. 1128c0b746e5SOllivier Robert */ 1129c0b746e5SOllivier Robert if (*((cl->keyword) + clen) == '\0') { 1130c0b746e5SOllivier Robert *cmd = cl; 1131c0b746e5SOllivier Robert return 1; 1132c0b746e5SOllivier Robert } 1133c0b746e5SOllivier Robert nmatch++; 1134c0b746e5SOllivier Robert nearmatch = cl; 1135c0b746e5SOllivier Robert } 1136c0b746e5SOllivier Robert } 1137c0b746e5SOllivier Robert 1138c0b746e5SOllivier Robert /* 1139c0b746e5SOllivier Robert * See if there is more to do. If so, go again. Sorry about the 1140c0b746e5SOllivier Robert * goto, too much looking at BSD sources... 1141c0b746e5SOllivier Robert */ 1142c0b746e5SOllivier Robert if (clist == clist1 && clist2 != 0) { 1143c0b746e5SOllivier Robert clist = clist2; 1144c0b746e5SOllivier Robert goto again; 1145c0b746e5SOllivier Robert } 1146c0b746e5SOllivier Robert 1147c0b746e5SOllivier Robert /* 1148c0b746e5SOllivier Robert * If we got extactly 1 near match, use it, else return number 1149c0b746e5SOllivier Robert * of matches. 1150c0b746e5SOllivier Robert */ 1151c0b746e5SOllivier Robert if (nmatch == 1) { 1152c0b746e5SOllivier Robert *cmd = nearmatch; 1153c0b746e5SOllivier Robert return 1; 1154c0b746e5SOllivier Robert } 1155c0b746e5SOllivier Robert return nmatch; 1156c0b746e5SOllivier Robert } 1157c0b746e5SOllivier Robert 1158c0b746e5SOllivier Robert 1159c0b746e5SOllivier Robert /* 1160c0b746e5SOllivier Robert * getarg - interpret an argument token 1161c0b746e5SOllivier Robert */ 1162c0b746e5SOllivier Robert static int 1163c0b746e5SOllivier Robert getarg( 1164c0b746e5SOllivier Robert char *str, 1165c0b746e5SOllivier Robert int code, 1166c0b746e5SOllivier Robert arg_v *argp 1167c0b746e5SOllivier Robert ) 1168c0b746e5SOllivier Robert { 1169c0b746e5SOllivier Robert int isneg; 1170c0b746e5SOllivier Robert char *cp, *np; 1171c0b746e5SOllivier Robert static const char *digits = "0123456789"; 1172c0b746e5SOllivier Robert 1173c0b746e5SOllivier Robert switch (code & ~OPT) { 1174c0b746e5SOllivier Robert case NTP_STR: 1175c0b746e5SOllivier Robert argp->string = str; 1176c0b746e5SOllivier Robert break; 1177c0b746e5SOllivier Robert case ADD: 1178c0b746e5SOllivier Robert if (!getnetnum(str, &(argp->netnum), (char *)0)) { 1179c0b746e5SOllivier Robert return 0; 1180c0b746e5SOllivier Robert } 1181c0b746e5SOllivier Robert break; 1182c0b746e5SOllivier Robert case INT: 1183c0b746e5SOllivier Robert case UINT: 1184c0b746e5SOllivier Robert isneg = 0; 1185c0b746e5SOllivier Robert np = str; 1186c0b746e5SOllivier Robert if (*np == '-') { 1187c0b746e5SOllivier Robert np++; 1188c0b746e5SOllivier Robert isneg = 1; 1189c0b746e5SOllivier Robert } 1190c0b746e5SOllivier Robert 1191c0b746e5SOllivier Robert argp->uval = 0; 1192c0b746e5SOllivier Robert do { 1193c0b746e5SOllivier Robert cp = strchr(digits, *np); 1194c0b746e5SOllivier Robert if (cp == NULL) { 1195c0b746e5SOllivier Robert (void) fprintf(stderr, 1196c0b746e5SOllivier Robert "***Illegal integer value %s\n", str); 1197c0b746e5SOllivier Robert return 0; 1198c0b746e5SOllivier Robert } 1199c0b746e5SOllivier Robert argp->uval *= 10; 1200c0b746e5SOllivier Robert argp->uval += (cp - digits); 1201c0b746e5SOllivier Robert } while (*(++np) != '\0'); 1202c0b746e5SOllivier Robert 1203c0b746e5SOllivier Robert if (isneg) { 1204c0b746e5SOllivier Robert if ((code & ~OPT) == UINT) { 1205c0b746e5SOllivier Robert (void) fprintf(stderr, 1206c0b746e5SOllivier Robert "***Value %s should be unsigned\n", str); 1207c0b746e5SOllivier Robert return 0; 1208c0b746e5SOllivier Robert } 1209c0b746e5SOllivier Robert argp->ival = -argp->ival; 1210c0b746e5SOllivier Robert } 1211c0b746e5SOllivier Robert break; 1212c0b746e5SOllivier Robert } 1213c0b746e5SOllivier Robert 1214c0b746e5SOllivier Robert return 1; 1215c0b746e5SOllivier Robert } 1216c0b746e5SOllivier Robert 1217c0b746e5SOllivier Robert 1218c0b746e5SOllivier Robert /* 1219c0b746e5SOllivier Robert * getnetnum - given a host name, return its net number 1220c0b746e5SOllivier Robert * and (optional) full name 1221c0b746e5SOllivier Robert */ 1222c0b746e5SOllivier Robert static int 1223c0b746e5SOllivier Robert getnetnum( 1224c0b746e5SOllivier Robert const char *hname, 1225c0b746e5SOllivier Robert u_int32 *num, 1226c0b746e5SOllivier Robert char *fullhost 1227c0b746e5SOllivier Robert ) 1228c0b746e5SOllivier Robert { 1229c0b746e5SOllivier Robert struct hostent *hp; 1230c0b746e5SOllivier Robert 1231c0b746e5SOllivier Robert if (decodenetnum(hname, num)) { 1232c0b746e5SOllivier Robert if (fullhost != 0) { 1233c0b746e5SOllivier Robert (void) sprintf(fullhost, 1234c0b746e5SOllivier Robert "%u.%u.%u.%u", (u_int)((htonl(*num)>>24)&0xff), 1235c0b746e5SOllivier Robert (u_int)((htonl(*num)>>16)&0xff), (u_int)((htonl(*num)>>8)&0xff), 1236c0b746e5SOllivier Robert (u_int)(htonl(*num)&0xff)); 1237c0b746e5SOllivier Robert } 1238c0b746e5SOllivier Robert return 1; 1239c0b746e5SOllivier Robert } else if ((hp = gethostbyname(hname)) != 0) { 1240c0b746e5SOllivier Robert memmove((char *)num, hp->h_addr, sizeof(u_int32)); 1241c0b746e5SOllivier Robert if (fullhost != 0) 1242c0b746e5SOllivier Robert (void) strcpy(fullhost, hp->h_name); 1243c0b746e5SOllivier Robert return 1; 1244c0b746e5SOllivier Robert } else { 1245c0b746e5SOllivier Robert (void) fprintf(stderr, "***Can't find host %s\n", hname); 1246c0b746e5SOllivier Robert return 0; 1247c0b746e5SOllivier Robert } 1248c0b746e5SOllivier Robert /*NOTREACHED*/ 1249c0b746e5SOllivier Robert } 1250c0b746e5SOllivier Robert 1251c0b746e5SOllivier Robert /* 1252c0b746e5SOllivier Robert * nntohost - convert network number to host name. This routine enforces 1253c0b746e5SOllivier Robert * the showhostnames setting. 1254c0b746e5SOllivier Robert */ 1255c0b746e5SOllivier Robert char * 1256c0b746e5SOllivier Robert nntohost( 1257c0b746e5SOllivier Robert u_int32 netnum 1258c0b746e5SOllivier Robert ) 1259c0b746e5SOllivier Robert { 1260c0b746e5SOllivier Robert if (!showhostnames) 1261c0b746e5SOllivier Robert return numtoa(netnum); 1262c0b746e5SOllivier Robert if ((ntohl(netnum) & REFCLOCK_MASK) == REFCLOCK_ADDR) 1263c0b746e5SOllivier Robert return refnumtoa(netnum); 1264c0b746e5SOllivier Robert return numtohost(netnum); 1265c0b746e5SOllivier Robert } 1266c0b746e5SOllivier Robert 1267c0b746e5SOllivier Robert 1268c0b746e5SOllivier Robert /* 1269c0b746e5SOllivier Robert * Finally, the built in command handlers 1270c0b746e5SOllivier Robert */ 1271c0b746e5SOllivier Robert 1272c0b746e5SOllivier Robert /* 1273c0b746e5SOllivier Robert * help - tell about commands, or details of a particular command 1274c0b746e5SOllivier Robert */ 1275c0b746e5SOllivier Robert static void 1276c0b746e5SOllivier Robert help( 1277c0b746e5SOllivier Robert struct parse *pcmd, 1278c0b746e5SOllivier Robert FILE *fp 1279c0b746e5SOllivier Robert ) 1280c0b746e5SOllivier Robert { 1281c0b746e5SOllivier Robert int i; 1282c0b746e5SOllivier Robert int n; 1283c0b746e5SOllivier Robert struct xcmd *xcp; 1284c0b746e5SOllivier Robert char *cmd; 1285c0b746e5SOllivier Robert const char *cmdsort[100]; 1286c0b746e5SOllivier Robert int length[100]; 1287c0b746e5SOllivier Robert int maxlength; 1288c0b746e5SOllivier Robert int numperline; 1289c0b746e5SOllivier Robert static const char *spaces = " "; /* 20 spaces */ 1290c0b746e5SOllivier Robert 1291c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1292c0b746e5SOllivier Robert n = 0; 1293c0b746e5SOllivier Robert for (xcp = builtins; xcp->keyword != 0; xcp++) { 1294c0b746e5SOllivier Robert if (*(xcp->keyword) != '?') 1295c0b746e5SOllivier Robert cmdsort[n++] = xcp->keyword; 1296c0b746e5SOllivier Robert } 1297c0b746e5SOllivier Robert for (xcp = opcmds; xcp->keyword != 0; xcp++) 1298c0b746e5SOllivier Robert cmdsort[n++] = xcp->keyword; 1299c0b746e5SOllivier Robert 1300c0b746e5SOllivier Robert #ifdef QSORT_USES_VOID_P 1301224ba2bdSOllivier Robert qsort(cmdsort, (size_t)n, sizeof(char *), helpsort); 1302c0b746e5SOllivier Robert #else 1303224ba2bdSOllivier Robert qsort((char *)cmdsort, (size_t)n, sizeof(char *), helpsort); 1304c0b746e5SOllivier Robert #endif 1305c0b746e5SOllivier Robert 1306c0b746e5SOllivier Robert maxlength = 0; 1307c0b746e5SOllivier Robert for (i = 0; i < n; i++) { 1308c0b746e5SOllivier Robert length[i] = strlen(cmdsort[i]); 1309c0b746e5SOllivier Robert if (length[i] > maxlength) 1310c0b746e5SOllivier Robert maxlength = length[i]; 1311c0b746e5SOllivier Robert } 1312c0b746e5SOllivier Robert maxlength++; 1313c0b746e5SOllivier Robert numperline = 76 / maxlength; 1314c0b746e5SOllivier Robert 1315c0b746e5SOllivier Robert (void) fprintf(fp, "Commands available:\n"); 1316c0b746e5SOllivier Robert for (i = 0; i < n; i++) { 1317c0b746e5SOllivier Robert if ((i % numperline) == (numperline-1) 1318c0b746e5SOllivier Robert || i == (n-1)) 1319c0b746e5SOllivier Robert (void) fprintf(fp, "%s\n", cmdsort[i]); 1320c0b746e5SOllivier Robert else 1321c0b746e5SOllivier Robert (void) fprintf(fp, "%s%s", cmdsort[i], 1322c0b746e5SOllivier Robert spaces+20-maxlength+length[i]); 1323c0b746e5SOllivier Robert } 1324c0b746e5SOllivier Robert } else { 1325c0b746e5SOllivier Robert cmd = pcmd->argval[0].string; 1326c0b746e5SOllivier Robert n = findcmd(cmd, builtins, opcmds, &xcp); 1327c0b746e5SOllivier Robert if (n == 0) { 1328c0b746e5SOllivier Robert (void) fprintf(stderr, 1329c0b746e5SOllivier Robert "Command `%s' is unknown\n", cmd); 1330c0b746e5SOllivier Robert return; 1331c0b746e5SOllivier Robert } else if (n >= 2) { 1332c0b746e5SOllivier Robert (void) fprintf(stderr, 1333c0b746e5SOllivier Robert "Command `%s' is ambiguous\n", cmd); 1334c0b746e5SOllivier Robert return; 1335c0b746e5SOllivier Robert } 1336c0b746e5SOllivier Robert (void) fprintf(fp, "function: %s\n", xcp->comment); 1337c0b746e5SOllivier Robert printusage(xcp, fp); 1338c0b746e5SOllivier Robert } 1339c0b746e5SOllivier Robert } 1340c0b746e5SOllivier Robert 1341c0b746e5SOllivier Robert 1342c0b746e5SOllivier Robert /* 1343c0b746e5SOllivier Robert * helpsort - do hostname qsort comparisons 1344c0b746e5SOllivier Robert */ 1345c0b746e5SOllivier Robert #ifdef QSORT_USES_VOID_P 1346c0b746e5SOllivier Robert static int 1347c0b746e5SOllivier Robert helpsort( 1348c0b746e5SOllivier Robert const void *t1, 1349c0b746e5SOllivier Robert const void *t2 1350c0b746e5SOllivier Robert ) 1351c0b746e5SOllivier Robert { 1352c0b746e5SOllivier Robert const char **name1 = (const char **)t1; 1353c0b746e5SOllivier Robert const char **name2 = (const char **)t2; 1354c0b746e5SOllivier Robert 1355c0b746e5SOllivier Robert return strcmp(*name1, *name2); 1356c0b746e5SOllivier Robert } 1357c0b746e5SOllivier Robert #else 1358c0b746e5SOllivier Robert static int 1359c0b746e5SOllivier Robert helpsort( 1360c0b746e5SOllivier Robert char **name1, 1361c0b746e5SOllivier Robert char **name2 1362c0b746e5SOllivier Robert ) 1363c0b746e5SOllivier Robert { 1364c0b746e5SOllivier Robert return strcmp(*name1, *name2); 1365c0b746e5SOllivier Robert } 1366c0b746e5SOllivier Robert #endif 1367c0b746e5SOllivier Robert 1368c0b746e5SOllivier Robert 1369c0b746e5SOllivier Robert /* 1370c0b746e5SOllivier Robert * printusage - print usage information for a command 1371c0b746e5SOllivier Robert */ 1372c0b746e5SOllivier Robert static void 1373c0b746e5SOllivier Robert printusage( 1374c0b746e5SOllivier Robert struct xcmd *xcp, 1375c0b746e5SOllivier Robert FILE *fp 1376c0b746e5SOllivier Robert ) 1377c0b746e5SOllivier Robert { 1378c0b746e5SOllivier Robert register int i; 1379c0b746e5SOllivier Robert 1380c0b746e5SOllivier Robert (void) fprintf(fp, "usage: %s", xcp->keyword); 1381c0b746e5SOllivier Robert for (i = 0; i < MAXARGS && xcp->arg[i] != NO; i++) { 1382c0b746e5SOllivier Robert if (xcp->arg[i] & OPT) 1383c0b746e5SOllivier Robert (void) fprintf(fp, " [ %s ]", xcp->desc[i]); 1384c0b746e5SOllivier Robert else 1385c0b746e5SOllivier Robert (void) fprintf(fp, " %s", xcp->desc[i]); 1386c0b746e5SOllivier Robert } 1387c0b746e5SOllivier Robert (void) fprintf(fp, "\n"); 1388c0b746e5SOllivier Robert } 1389c0b746e5SOllivier Robert 1390c0b746e5SOllivier Robert 1391c0b746e5SOllivier Robert /* 1392c0b746e5SOllivier Robert * timeout - set time out time 1393c0b746e5SOllivier Robert */ 1394c0b746e5SOllivier Robert static void 1395c0b746e5SOllivier Robert timeout( 1396c0b746e5SOllivier Robert struct parse *pcmd, 1397c0b746e5SOllivier Robert FILE *fp 1398c0b746e5SOllivier Robert ) 1399c0b746e5SOllivier Robert { 1400c0b746e5SOllivier Robert int val; 1401c0b746e5SOllivier Robert 1402c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1403c0b746e5SOllivier Robert val = tvout.tv_sec * 1000 + tvout.tv_usec / 1000; 1404c0b746e5SOllivier Robert (void) fprintf(fp, "primary timeout %d ms\n", val); 1405c0b746e5SOllivier Robert } else { 1406c0b746e5SOllivier Robert tvout.tv_sec = pcmd->argval[0].uval / 1000; 1407c0b746e5SOllivier Robert tvout.tv_usec = (pcmd->argval[0].uval - (tvout.tv_sec * 1000)) 1408c0b746e5SOllivier Robert * 1000; 1409c0b746e5SOllivier Robert } 1410c0b746e5SOllivier Robert } 1411c0b746e5SOllivier Robert 1412c0b746e5SOllivier Robert 1413c0b746e5SOllivier Robert /* 1414c0b746e5SOllivier Robert * my_delay - set delay for auth requests 1415c0b746e5SOllivier Robert */ 1416c0b746e5SOllivier Robert static void 1417c0b746e5SOllivier Robert my_delay( 1418c0b746e5SOllivier Robert struct parse *pcmd, 1419c0b746e5SOllivier Robert FILE *fp 1420c0b746e5SOllivier Robert ) 1421c0b746e5SOllivier Robert { 1422c0b746e5SOllivier Robert int isneg; 1423c0b746e5SOllivier Robert u_long val; 1424c0b746e5SOllivier Robert 1425c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1426c0b746e5SOllivier Robert val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967; 1427c0b746e5SOllivier Robert (void) fprintf(fp, "delay %lu ms\n", val); 1428c0b746e5SOllivier Robert } else { 1429c0b746e5SOllivier Robert if (pcmd->argval[0].ival < 0) { 1430c0b746e5SOllivier Robert isneg = 1; 1431c0b746e5SOllivier Robert val = (u_long)(-pcmd->argval[0].ival); 1432c0b746e5SOllivier Robert } else { 1433c0b746e5SOllivier Robert isneg = 0; 1434c0b746e5SOllivier Robert val = (u_long)pcmd->argval[0].ival; 1435c0b746e5SOllivier Robert } 1436c0b746e5SOllivier Robert 1437c0b746e5SOllivier Robert delay_time.l_ui = val / 1000; 1438c0b746e5SOllivier Robert val %= 1000; 1439c0b746e5SOllivier Robert delay_time.l_uf = val * 4294967; /* 2**32/1000 */ 1440c0b746e5SOllivier Robert 1441c0b746e5SOllivier Robert if (isneg) 1442c0b746e5SOllivier Robert L_NEG(&delay_time); 1443c0b746e5SOllivier Robert } 1444c0b746e5SOllivier Robert } 1445c0b746e5SOllivier Robert 1446c0b746e5SOllivier Robert 1447c0b746e5SOllivier Robert /* 1448c0b746e5SOllivier Robert * host - set the host we are dealing with. 1449c0b746e5SOllivier Robert */ 1450c0b746e5SOllivier Robert static void 1451c0b746e5SOllivier Robert host( 1452c0b746e5SOllivier Robert struct parse *pcmd, 1453c0b746e5SOllivier Robert FILE *fp 1454c0b746e5SOllivier Robert ) 1455c0b746e5SOllivier Robert { 1456c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1457c0b746e5SOllivier Robert if (havehost) 1458c0b746e5SOllivier Robert (void) fprintf(fp, "current host is %s\n", currenthost); 1459c0b746e5SOllivier Robert else 1460c0b746e5SOllivier Robert (void) fprintf(fp, "no current host\n"); 1461c0b746e5SOllivier Robert } else if (openhost(pcmd->argval[0].string)) { 1462c0b746e5SOllivier Robert (void) fprintf(fp, "current host set to %s\n", currenthost); 1463c0b746e5SOllivier Robert } else { 1464c0b746e5SOllivier Robert if (havehost) 1465c0b746e5SOllivier Robert (void) fprintf(fp, 1466c0b746e5SOllivier Robert "current host remains %s\n", currenthost); 1467c0b746e5SOllivier Robert else 1468c0b746e5SOllivier Robert (void) fprintf(fp, "still no current host\n"); 1469c0b746e5SOllivier Robert } 1470c0b746e5SOllivier Robert } 1471c0b746e5SOllivier Robert 1472c0b746e5SOllivier Robert 1473c0b746e5SOllivier Robert /* 1474c0b746e5SOllivier Robert * keyid - get a keyid to use for authenticating requests 1475c0b746e5SOllivier Robert */ 1476c0b746e5SOllivier Robert static void 1477c0b746e5SOllivier Robert keyid( 1478c0b746e5SOllivier Robert struct parse *pcmd, 1479c0b746e5SOllivier Robert FILE *fp 1480c0b746e5SOllivier Robert ) 1481c0b746e5SOllivier Robert { 1482c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1483c0b746e5SOllivier Robert if (info_auth_keyid == 0) 1484c0b746e5SOllivier Robert (void) fprintf(fp, "no keyid defined\n"); 1485c0b746e5SOllivier Robert else 1486c0b746e5SOllivier Robert (void) fprintf(fp, "keyid is %lu\n", (u_long)info_auth_keyid); 1487c0b746e5SOllivier Robert } else { 1488c0b746e5SOllivier Robert info_auth_keyid = pcmd->argval[0].uval; 1489c0b746e5SOllivier Robert } 1490c0b746e5SOllivier Robert } 1491c0b746e5SOllivier Robert 1492c0b746e5SOllivier Robert 1493c0b746e5SOllivier Robert /* 1494c0b746e5SOllivier Robert * keytype - get type of key to use for authenticating requests 1495c0b746e5SOllivier Robert */ 1496c0b746e5SOllivier Robert static void 1497c0b746e5SOllivier Robert keytype( 1498c0b746e5SOllivier Robert struct parse *pcmd, 1499c0b746e5SOllivier Robert FILE *fp 1500c0b746e5SOllivier Robert ) 1501c0b746e5SOllivier Robert { 1502c0b746e5SOllivier Robert if (pcmd->nargs == 0) 1503c0b746e5SOllivier Robert fprintf(fp, "keytype is %s\n", 1504c0b746e5SOllivier Robert (info_auth_keytype == KEY_TYPE_MD5) ? "MD5" : "DES"); 1505c0b746e5SOllivier Robert else 1506c0b746e5SOllivier Robert switch (*(pcmd->argval[0].string)) { 1507c0b746e5SOllivier Robert case 'm': 1508c0b746e5SOllivier Robert case 'M': 1509c0b746e5SOllivier Robert info_auth_keytype = KEY_TYPE_MD5; 1510c0b746e5SOllivier Robert break; 1511c0b746e5SOllivier Robert 1512c0b746e5SOllivier Robert case 'd': 1513c0b746e5SOllivier Robert case 'D': 1514c0b746e5SOllivier Robert info_auth_keytype = KEY_TYPE_DES; 1515c0b746e5SOllivier Robert break; 1516c0b746e5SOllivier Robert 1517c0b746e5SOllivier Robert default: 1518c0b746e5SOllivier Robert fprintf(fp, "keytype must be 'md5' or 'des'\n"); 1519c0b746e5SOllivier Robert } 1520c0b746e5SOllivier Robert } 1521c0b746e5SOllivier Robert 1522c0b746e5SOllivier Robert 1523c0b746e5SOllivier Robert 1524c0b746e5SOllivier Robert /* 1525c0b746e5SOllivier Robert * passwd - get an authentication key 1526c0b746e5SOllivier Robert */ 1527c0b746e5SOllivier Robert /*ARGSUSED*/ 1528c0b746e5SOllivier Robert static void 1529c0b746e5SOllivier Robert passwd( 1530c0b746e5SOllivier Robert struct parse *pcmd, 1531c0b746e5SOllivier Robert FILE *fp 1532c0b746e5SOllivier Robert ) 1533c0b746e5SOllivier Robert { 1534c0b746e5SOllivier Robert char *pass; 1535c0b746e5SOllivier Robert 1536c0b746e5SOllivier Robert if (info_auth_keyid == 0) { 1537c0b746e5SOllivier Robert info_auth_keyid = getkeyid("Keyid: "); 1538c0b746e5SOllivier Robert if (info_auth_keyid == 0) { 1539c0b746e5SOllivier Robert (void)fprintf(fp, "Keyid must be defined\n"); 1540c0b746e5SOllivier Robert return; 1541c0b746e5SOllivier Robert } 1542c0b746e5SOllivier Robert } 1543c0b746e5SOllivier Robert if (!interactive) { 1544c0b746e5SOllivier Robert authusekey(info_auth_keyid, info_auth_keytype, 1545c0b746e5SOllivier Robert (u_char *)pcmd->argval[0].string); 1546224ba2bdSOllivier Robert authtrust(info_auth_keyid, 1); 1547c0b746e5SOllivier Robert } else { 1548c0b746e5SOllivier Robert pass = getpass((info_auth_keytype == KEY_TYPE_DES) 1549c0b746e5SOllivier Robert ? "DES Password: " 1550c0b746e5SOllivier Robert : "MD5 Password: " 1551c0b746e5SOllivier Robert ); 1552c0b746e5SOllivier Robert if (*pass == '\0') 1553c0b746e5SOllivier Robert (void) fprintf(fp, "Password unchanged\n"); 1554224ba2bdSOllivier Robert else { 1555c0b746e5SOllivier Robert authusekey(info_auth_keyid, info_auth_keytype, 1556c0b746e5SOllivier Robert (u_char *)pass); 1557224ba2bdSOllivier Robert authtrust(info_auth_keyid, 1); 1558224ba2bdSOllivier Robert } 1559c0b746e5SOllivier Robert } 1560c0b746e5SOllivier Robert } 1561c0b746e5SOllivier Robert 1562c0b746e5SOllivier Robert 1563c0b746e5SOllivier Robert /* 1564c0b746e5SOllivier Robert * hostnames - set the showhostnames flag 1565c0b746e5SOllivier Robert */ 1566c0b746e5SOllivier Robert static void 1567c0b746e5SOllivier Robert hostnames( 1568c0b746e5SOllivier Robert struct parse *pcmd, 1569c0b746e5SOllivier Robert FILE *fp 1570c0b746e5SOllivier Robert ) 1571c0b746e5SOllivier Robert { 1572c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1573c0b746e5SOllivier Robert if (showhostnames) 1574c0b746e5SOllivier Robert (void) fprintf(fp, "hostnames being shown\n"); 1575c0b746e5SOllivier Robert else 1576c0b746e5SOllivier Robert (void) fprintf(fp, "hostnames not being shown\n"); 1577c0b746e5SOllivier Robert } else { 1578c0b746e5SOllivier Robert if (STREQ(pcmd->argval[0].string, "yes")) 1579c0b746e5SOllivier Robert showhostnames = 1; 1580c0b746e5SOllivier Robert else if (STREQ(pcmd->argval[0].string, "no")) 1581c0b746e5SOllivier Robert showhostnames = 0; 1582c0b746e5SOllivier Robert else 1583c0b746e5SOllivier Robert (void)fprintf(stderr, "What?\n"); 1584c0b746e5SOllivier Robert } 1585c0b746e5SOllivier Robert } 1586c0b746e5SOllivier Robert 1587c0b746e5SOllivier Robert 1588c0b746e5SOllivier Robert /* 1589c0b746e5SOllivier Robert * setdebug - set/change debugging level 1590c0b746e5SOllivier Robert */ 1591c0b746e5SOllivier Robert static void 1592c0b746e5SOllivier Robert setdebug( 1593c0b746e5SOllivier Robert struct parse *pcmd, 1594c0b746e5SOllivier Robert FILE *fp 1595c0b746e5SOllivier Robert ) 1596c0b746e5SOllivier Robert { 1597c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1598c0b746e5SOllivier Robert (void) fprintf(fp, "debug level is %d\n", debug); 1599c0b746e5SOllivier Robert return; 1600c0b746e5SOllivier Robert } else if (STREQ(pcmd->argval[0].string, "no")) { 1601c0b746e5SOllivier Robert debug = 0; 1602c0b746e5SOllivier Robert } else if (STREQ(pcmd->argval[0].string, "more")) { 1603c0b746e5SOllivier Robert debug++; 1604c0b746e5SOllivier Robert } else if (STREQ(pcmd->argval[0].string, "less")) { 1605c0b746e5SOllivier Robert debug--; 1606c0b746e5SOllivier Robert } else { 1607c0b746e5SOllivier Robert (void) fprintf(fp, "What?\n"); 1608c0b746e5SOllivier Robert return; 1609c0b746e5SOllivier Robert } 1610c0b746e5SOllivier Robert (void) fprintf(fp, "debug level set to %d\n", debug); 1611c0b746e5SOllivier Robert } 1612c0b746e5SOllivier Robert 1613c0b746e5SOllivier Robert 1614c0b746e5SOllivier Robert /* 1615c0b746e5SOllivier Robert * quit - stop this nonsense 1616c0b746e5SOllivier Robert */ 1617c0b746e5SOllivier Robert /*ARGSUSED*/ 1618c0b746e5SOllivier Robert static void 1619c0b746e5SOllivier Robert quit( 1620c0b746e5SOllivier Robert struct parse *pcmd, 1621c0b746e5SOllivier Robert FILE *fp 1622c0b746e5SOllivier Robert ) 1623c0b746e5SOllivier Robert { 1624c0b746e5SOllivier Robert if (havehost) 1625c0b746e5SOllivier Robert closesocket(sockfd); 1626c0b746e5SOllivier Robert exit(0); 1627c0b746e5SOllivier Robert } 1628c0b746e5SOllivier Robert 1629c0b746e5SOllivier Robert 1630c0b746e5SOllivier Robert /* 1631c0b746e5SOllivier Robert * version - print the current version number 1632c0b746e5SOllivier Robert */ 1633c0b746e5SOllivier Robert /*ARGSUSED*/ 1634c0b746e5SOllivier Robert static void 1635c0b746e5SOllivier Robert version( 1636c0b746e5SOllivier Robert struct parse *pcmd, 1637c0b746e5SOllivier Robert FILE *fp 1638c0b746e5SOllivier Robert ) 1639c0b746e5SOllivier Robert { 1640c0b746e5SOllivier Robert 1641c0b746e5SOllivier Robert (void) fprintf(fp, "%s\n", Version); 1642c0b746e5SOllivier Robert return; 1643c0b746e5SOllivier Robert } 1644c0b746e5SOllivier Robert 1645c0b746e5SOllivier Robert 1646c0b746e5SOllivier Robert /* 1647c0b746e5SOllivier Robert * warning - print a warning message 1648c0b746e5SOllivier Robert */ 1649c0b746e5SOllivier Robert static void 1650c0b746e5SOllivier Robert warning( 1651c0b746e5SOllivier Robert const char *fmt, 1652c0b746e5SOllivier Robert const char *st1, 1653c0b746e5SOllivier Robert const char *st2 1654c0b746e5SOllivier Robert ) 1655c0b746e5SOllivier Robert { 1656c0b746e5SOllivier Robert (void) fprintf(stderr, "%s: ", progname); 1657c0b746e5SOllivier Robert (void) fprintf(stderr, fmt, st1, st2); 1658c0b746e5SOllivier Robert (void) fprintf(stderr, ": "); 1659c0b746e5SOllivier Robert perror(""); 1660c0b746e5SOllivier Robert } 1661c0b746e5SOllivier Robert 1662c0b746e5SOllivier Robert 1663c0b746e5SOllivier Robert /* 1664c0b746e5SOllivier Robert * error - print a message and exit 1665c0b746e5SOllivier Robert */ 1666c0b746e5SOllivier Robert static void 1667c0b746e5SOllivier Robert error( 1668c0b746e5SOllivier Robert const char *fmt, 1669c0b746e5SOllivier Robert const char *st1, 1670c0b746e5SOllivier Robert const char *st2 1671c0b746e5SOllivier Robert ) 1672c0b746e5SOllivier Robert { 1673c0b746e5SOllivier Robert warning(fmt, st1, st2); 1674c0b746e5SOllivier Robert exit(1); 1675c0b746e5SOllivier Robert } 1676c0b746e5SOllivier Robert 1677c0b746e5SOllivier Robert /* 1678c0b746e5SOllivier Robert * getkeyid - prompt the user for a keyid to use 1679c0b746e5SOllivier Robert */ 1680c0b746e5SOllivier Robert static u_long 1681c0b746e5SOllivier Robert getkeyid( 1682c0b746e5SOllivier Robert const char *keyprompt 1683c0b746e5SOllivier Robert ) 1684c0b746e5SOllivier Robert { 1685c0b746e5SOllivier Robert register char *p; 1686c0b746e5SOllivier Robert register int c; 1687c0b746e5SOllivier Robert FILE *fi; 1688c0b746e5SOllivier Robert char pbuf[20]; 1689c0b746e5SOllivier Robert 1690c0b746e5SOllivier Robert #ifndef SYS_WINNT 1691c0b746e5SOllivier Robert if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL) 1692c0b746e5SOllivier Robert #else 1693c0b746e5SOllivier Robert if ((fi = _fdopen((int)GetStdHandle(STD_INPUT_HANDLE), "r")) == NULL) 1694c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1695c0b746e5SOllivier Robert fi = stdin; 1696c0b746e5SOllivier Robert else 1697c0b746e5SOllivier Robert setbuf(fi, (char *)NULL); 1698c0b746e5SOllivier Robert fprintf(stderr, "%s", keyprompt); fflush(stderr); 1699c0b746e5SOllivier Robert for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) { 1700c0b746e5SOllivier Robert if (p < &pbuf[18]) 1701c0b746e5SOllivier Robert *p++ = c; 1702c0b746e5SOllivier Robert } 1703c0b746e5SOllivier Robert *p = '\0'; 1704c0b746e5SOllivier Robert if (fi != stdin) 1705c0b746e5SOllivier Robert fclose(fi); 1706c0b746e5SOllivier Robert return (u_int32)atoi(pbuf); 1707c0b746e5SOllivier Robert } 1708