command.c revision 27346
1/*
2 *		PPP User command processing module
3 *
4 *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc.  The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id: command.c,v 1.65 1997/06/30 03:03:29 brian Exp $
21 *
22 */
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <ctype.h>
26#include <termios.h>
27#include <sys/wait.h>
28#include <time.h>
29#include <netdb.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <arpa/inet.h>
33#include <net/route.h>
34#include <paths.h>
35#include <alias.h>
36#include <fcntl.h>
37#include <errno.h>
38#include "fsm.h"
39#include "phase.h"
40#include "lcp.h"
41#include "ipcp.h"
42#include "modem.h"
43#include "filter.h"
44#include "command.h"
45#include "alias_cmd.h"
46#include "hdlc.h"
47#include "loadalias.h"
48#include "vars.h"
49#include "systems.h"
50#include "chat.h"
51#include "os.h"
52#include "timeout.h"
53#include "server.h"
54
55extern void Cleanup(), TtyTermMode(), PacketMode();
56extern int  EnableCommand(), DisableCommand(), DisplayCommand();
57extern int  AcceptCommand(), DenyCommand();
58static int  AliasCommand();
59extern int  LocalAuthCommand();
60extern int  LoadCommand(), SaveCommand();
61extern int  ChangeParity(char *);
62extern int  SelectSystem();
63extern int  ShowRoute();
64extern void TtyOldMode(), TtyCommandMode();
65extern struct pppvars pppVars;
66extern struct cmdtab const SetCommands[];
67
68extern char *IfDevName;
69
70struct in_addr ifnetmask;
71int randinit;
72
73static int ShowCommand(), TerminalCommand(), QuitCommand();
74static int CloseCommand(), DialCommand(), DownCommand();
75static int SetCommand(), AddCommand(), DeleteCommand();
76static int ShellCommand();
77
78static int
79HelpCommand(list, argc, argv, plist)
80struct cmdtab *list;
81int argc;
82char **argv;
83struct cmdtab *plist;
84{
85  struct cmdtab *cmd;
86  int n;
87
88  if (!VarTerm)
89    return 0;
90
91  if (argc > 0) {
92    for (cmd = plist; cmd->name; cmd++)
93      if (strcasecmp(cmd->name, *argv) == 0 && (cmd->lauth & VarLocalAuth)) {
94        fprintf(VarTerm, "%s\n", cmd->syntax);
95        return 0;
96      }
97
98    return -1;
99  }
100
101  n = 0;
102  for (cmd = plist; cmd->func; cmd++)
103    if (cmd->name && (cmd->lauth & VarLocalAuth)) {
104      fprintf(VarTerm, "  %-9s: %-20s\n", cmd->name, cmd->helpmes);
105      n++;
106    }
107
108  if (n & 1)
109    fprintf(VarTerm, "\n");
110
111  return 0;
112}
113
114int
115IsInteractive()
116{
117  char *mes = NULL;
118
119  if (mode & MODE_DDIAL)
120    mes = "Working in dedicated dial mode.";
121  else if (mode & MODE_BACKGROUND)
122    mes = "Working in background mode.";
123  else if (mode & MODE_AUTO)
124    mes = "Working in auto mode.";
125  else if (mode & MODE_DIRECT)
126    mes = "Working in direct mode.";
127  else if (mode & MODE_DEDICATED)
128    mes = "Working in dedicated mode.";
129  if (mes) {
130    if (VarTerm)
131      fprintf(VarTerm, "%s\n", mes);
132    return 0;
133  }
134  return 1;
135}
136
137static int
138DialCommand(cmdlist, argc, argv)
139struct cmdtab *cmdlist;
140int argc;
141char **argv;
142{
143  int tries;
144  int res;
145
146  if (LcpFsm.state > ST_CLOSED) {
147    if (VarTerm)
148      fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
149    return 0;
150  }
151
152  if (!IsInteractive())
153    return(1);
154
155  if (argc > 0) {
156    if (SelectSystem(*argv, CONFFILE) < 0) {
157      if (VarTerm)
158        fprintf(VarTerm, "%s: not found.\n", *argv);
159      return -1;
160    }
161  }
162
163  tries = 0;
164  do {
165    if (VarTerm)
166      fprintf(VarTerm, "Dial attempt %u of %d\n", ++tries, VarDialTries);
167    modem = OpenModem(mode);
168    if (modem < 0) {
169      if (VarTerm)
170        fprintf(VarTerm, "Failed to open modem.\n");
171      break;
172    }
173    if ((res = DialModem()) == EX_DONE) {
174      sleep(1);
175      ModemTimeout();
176      PacketMode();
177      break;
178    } else if (res == EX_SIG)
179      return 1;
180  } while (VarDialTries == 0 || tries < VarDialTries);
181
182  return 0;
183}
184
185static int
186ShellCommand(cmdlist, argc, argv)
187struct cmdtab *cmdlist;
188int argc;
189char **argv;
190{
191  const char *shell;
192  pid_t shpid;
193  FILE *oVarTerm;
194
195#ifdef SHELL_ONLY_INTERACTIVELY
196  /* we're only allowed to shell when we run ppp interactively */
197  if (mode != MODE_INTER) {
198    LogPrintf(LogWARN, "Can only start a shell in interactive mode\n");
199    return 1;
200  }
201#endif
202#ifdef NO_SHELL_IN_AUTO_INTERACTIVE
203  /*
204   * we want to stop shell commands when we've got a telnet connection
205   * to an auto mode ppp
206   */
207  if ((mode & (MODE_AUTO|MODE_INTER)) == (MODE_AUTO|MODE_INTER)) {
208    LogPrintf(LogWARN,  "Shell is not allowed interactively in auto mode\n");
209    return 1;
210  }
211#endif
212
213  if(argc == 0 && !(mode & MODE_INTER)) {
214    LogPrintf(LogWARN, "Can only start an interactive shell in"
215	      " interactive mode\n");
216    return 1;
217  }
218
219  if((shell = getenv("SHELL")) == 0)
220    shell = _PATH_BSHELL;
221
222  if((shpid = fork()) == 0) {
223     int dtablesize, i, fd;
224
225     if (VarTerm)
226       fd = fileno(VarTerm);
227     else if ((fd = open("/dev/null", O_RDWR)) == -1) {
228       LogPrintf(LogALERT, "Failed to open /dev/null: %s\n", strerror(errno));
229       exit(1);
230     }
231
232     for (i = 0; i < 3; i++)
233       dup2(fd, i);
234
235     if (fd > 2)
236       if (VarTerm) {
237	 oVarTerm = VarTerm;
238	 VarTerm = 0;
239         if (oVarTerm && oVarTerm != stdout)
240           fclose(oVarTerm);
241       } else
242         close(fd);
243
244     for (dtablesize = getdtablesize(), i = 3; i < dtablesize; i++)
245	(void)close(i);
246
247     /*
248      * We are running setuid, we should change to
249      * real user for avoiding security problems.
250      */
251     if (setgid(getgid()) < 0) {
252        LogPrintf(LogERROR, "setgid: %s\n", strerror(errno));
253	exit(1);
254     }
255     if (setuid(getuid()) < 0) {
256        LogPrintf(LogERROR, "setuid: %s\n", strerror(errno));
257	exit(1);
258     }
259     TtyOldMode();
260     if(argc > 0) {
261       /* substitute pseudo args */
262       for (i=1; i<argc; i++)
263         if (strcasecmp(argv[i], "HISADDR") == 0)
264           argv[i] = strdup(inet_ntoa(IpcpInfo.his_ipaddr));
265         else if (strcasecmp(argv[i], "INTERFACE") == 0)
266           argv[i] = strdup(IfDevName);
267         else if (strcasecmp(argv[i], "MYADDR") == 0)
268           argv[i] = strdup(inet_ntoa(IpcpInfo.want_ipaddr));
269       (void)execvp(argv[0], argv);
270     }
271     else
272       (void)execl(shell, shell, NULL);
273
274     LogPrintf(LogWARN, "exec() of %s failed\n", argc > 0 ? argv[0] : shell);
275     exit(255);
276  }
277
278  if( shpid == (pid_t)-1 ) {
279    LogPrintf(LogERROR, "Fork failed: %s\n", strerror(errno));
280  } else {
281    int status;
282    (void)waitpid(shpid, &status, 0);
283  }
284
285  TtyCommandMode(1);
286
287  return(0);
288}
289
290struct cmdtab const Commands[] = {
291  { "accept",  NULL,    AcceptCommand,	LOCAL_AUTH,
292  	"accept option request",	"accept option .."},
293  { "add",     NULL,	AddCommand,	LOCAL_AUTH,
294	"add route",			"add dest mask gateway"},
295  { "close",   NULL,    CloseCommand,	LOCAL_AUTH,
296	"Close connection",		"close"},
297  { "delete",  NULL,    DeleteCommand,	LOCAL_AUTH,
298	"delete route",                 "delete ALL | dest [gateway [mask]]"},
299  { "deny",    NULL,    DenyCommand,	LOCAL_AUTH,
300  	"Deny option request",		"deny option .."},
301  { "dial",    "call",  DialCommand,	LOCAL_AUTH,
302  	"Dial and login",		"dial|call [remote]"},
303  { "disable", NULL,    DisableCommand,	LOCAL_AUTH,
304  	"Disable option",		"disable option .."},
305  { "display", NULL,    DisplayCommand,	LOCAL_AUTH,
306  	"Display option configs",	"display"},
307  { "enable",  NULL,    EnableCommand,	LOCAL_AUTH,
308  	"Enable option",		"enable option .."},
309  { "passwd",  NULL,	LocalAuthCommand,LOCAL_NO_AUTH,
310  	"Password for manipulation", "passwd option .."},
311  { "load",    NULL,    LoadCommand,	LOCAL_AUTH,
312  	"Load settings",		"load [remote]"},
313  { "save",    NULL,    SaveCommand,	LOCAL_AUTH,
314  	"Save settings", "save"},
315  { "set",     "setup", SetCommand,	LOCAL_AUTH,
316  	"Set parameters",  "set[up] var value"},
317  { "shell",   "!",     ShellCommand,   LOCAL_AUTH,
318	"Run a subshell",  "shell|! [sh command]"},
319  { "show",    NULL,    ShowCommand,	LOCAL_AUTH,
320  	"Show status and statictics", "show var"},
321  { "term",    NULL,    TerminalCommand,LOCAL_AUTH,
322  	"Enter to terminal mode", "term"},
323  { "alias",   NULL,    AliasCommand,   LOCAL_AUTH,
324        "alias control",        "alias option [yes|no]"},
325  { "quit",    "bye",   QuitCommand,	LOCAL_AUTH | LOCAL_NO_AUTH,
326	"Quit PPP program", "quit|bye [all]"},
327  { "help",    "?",     HelpCommand,	LOCAL_AUTH | LOCAL_NO_AUTH,
328	"Display this message", "help|? [command]", (void *)Commands },
329  { NULL,      "down",  DownCommand,	LOCAL_AUTH,
330  	"Generate down event",		"down"},
331  { NULL,      NULL,    NULL },
332};
333
334extern int ReportCcpStatus();
335extern int ReportLcpStatus();
336extern int ReportIpcpStatus();
337extern int ReportProtStatus();
338extern int ReportCompress();
339extern int ShowModemStatus();
340extern int ReportHdlcStatus();
341extern int ShowMemMap();
342
343static int ShowLogLevel()
344{
345  int i;
346
347  if (!VarTerm)
348    return 0;
349  fprintf(VarTerm, "Log:");
350  for (i = LogMIN; i < LogMAXCONF; i++) {
351    if (LogIsKept(i))
352      fprintf(VarTerm, " %s", LogName(i));
353  }
354  fprintf(VarTerm, "\n");
355
356  return 0;
357}
358
359static int ShowEscape()
360{
361  int code, bit;
362
363  if (!VarTerm)
364    return 0;
365  if (EscMap[32]) {
366    for (code = 0; code < 32; code++)
367      if (EscMap[code])
368        for (bit = 0; bit < 8; bit++)
369          if (EscMap[code] & (1<<bit))
370            fprintf(VarTerm, " 0x%02x", (code << 3) + bit);
371    fprintf(VarTerm, "\n");
372  }
373  return 1;
374}
375
376static int ShowTimeout()
377{
378  if (!VarTerm)
379    return 0;
380  fprintf(VarTerm, " Idle Timer: %d secs   LQR Timer: %d secs"
381          "   Retry Timer: %d secs\n", VarIdleTimeout, VarLqrTimeout,
382          VarRetryTimeout);
383  return 1;
384}
385
386static int ShowAuthKey()
387{
388  if (!VarTerm)
389    return 0;
390  fprintf(VarTerm, "AuthName = %s\n", VarAuthName);
391  fprintf(VarTerm, "AuthKey  = %s\n", VarAuthKey);
392  return 1;
393}
394
395static int ShowVersion()
396{
397  extern char VarVersion[];
398  extern char VarLocalVersion[];
399
400  if (!VarTerm)
401    return 0;
402  fprintf(VarTerm, "%s - %s \n", VarVersion, VarLocalVersion);
403  return 1;
404}
405
406static int ShowInitialMRU()
407{
408  if (!VarTerm)
409    return 0;
410  fprintf(VarTerm, " Initial MRU: %ld\n", VarMRU);
411  return 1;
412}
413
414static int ShowPreferredMTU()
415{
416  if (!VarTerm)
417    return 0;
418  if (VarPrefMTU)
419    fprintf(VarTerm, " Preferred MTU: %ld\n", VarPrefMTU);
420  else
421    fprintf(VarTerm, " Preferred MTU: unspecified\n");
422  return 1;
423}
424
425static int ShowReconnect()
426{
427  if (!VarTerm)
428    return 0;
429  fprintf(VarTerm, " Reconnect Timer:  %d,  %d tries\n",
430         VarReconnectTimer, VarReconnectTries);
431  return 1;
432}
433
434static int ShowRedial()
435{
436  if (!VarTerm)
437    return 0;
438  fprintf(VarTerm, " Redial Timer: ");
439
440  if (VarRedialTimeout >= 0) {
441    fprintf(VarTerm, " %d seconds, ", VarRedialTimeout);
442  }
443  else {
444    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
445  }
446
447  fprintf(VarTerm, " Redial Next Timer: ");
448
449  if (VarRedialNextTimeout >= 0) {
450    fprintf(VarTerm, " %d seconds, ", VarRedialNextTimeout);
451  }
452  else {
453    fprintf(VarTerm, " Random 0 - %d seconds, ", REDIAL_PERIOD);
454  }
455
456  if (VarDialTries)
457      fprintf(VarTerm, "%d dial tries", VarDialTries);
458
459  fprintf(VarTerm, "\n");
460
461  return 1;
462}
463
464#ifndef NOMSEXT
465static int ShowMSExt()
466{
467  if (!VarTerm)
468    return 0;
469  fprintf(VarTerm, " MS PPP extention values \n" );
470  fprintf(VarTerm, "   Primary NS     : %s\n", inet_ntoa( ns_entries[0] ));
471  fprintf(VarTerm, "   Secondary NS   : %s\n", inet_ntoa( ns_entries[1] ));
472  fprintf(VarTerm, "   Primary NBNS   : %s\n", inet_ntoa( nbns_entries[0] ));
473  fprintf(VarTerm, "   Secondary NBNS : %s\n", inet_ntoa( nbns_entries[1] ));
474  return 1;
475}
476#endif
477
478extern int ShowIfilter(), ShowOfilter(), ShowDfilter(), ShowAfilter();
479
480struct cmdtab const ShowCommands[] = {
481  { "afilter",  NULL,     ShowAfilter,		LOCAL_AUTH,
482	"Show keep Alive filters", "show afilter option .."},
483  { "auth",     NULL,     ShowAuthKey,		LOCAL_AUTH,
484	"Show auth name/key", "show auth"},
485  { "ccp",      NULL,     ReportCcpStatus,	LOCAL_AUTH,
486	"Show CCP status", "show cpp"},
487  { "compress", NULL,     ReportCompress,	LOCAL_AUTH,
488	"Show compression statictics", "show compress"},
489  { "dfilter",  NULL,     ShowDfilter,		LOCAL_AUTH,
490	"Show Demand filters", "show dfilteroption .."},
491  { "escape",   NULL,     ShowEscape,		LOCAL_AUTH,
492	"Show escape characters", "show escape"},
493  { "hdlc",	NULL,	  ReportHdlcStatus,	LOCAL_AUTH,
494	"Show HDLC error summary", "show hdlc"},
495  { "ifilter",  NULL,     ShowIfilter,		LOCAL_AUTH,
496	"Show Input filters", "show ifilter option .."},
497  { "ipcp",     NULL,     ReportIpcpStatus,	LOCAL_AUTH,
498	"Show IPCP status", "show ipcp"},
499  { "lcp",      NULL,     ReportLcpStatus,	LOCAL_AUTH,
500	"Show LCP status", "show lcp"},
501  { "log",	NULL,	  ShowLogLevel,	LOCAL_AUTH,
502	"Show current log level", "show log"},
503  { "mem",      NULL,     ShowMemMap,		LOCAL_AUTH,
504	"Show memory map", "show mem"},
505  { "modem",    NULL,     ShowModemStatus,	LOCAL_AUTH,
506	"Show modem setups", "show modem"},
507  { "mru",      NULL,     ShowInitialMRU,	LOCAL_AUTH,
508	"Show Initial MRU", "show mru"},
509  { "mtu",      NULL,     ShowPreferredMTU,	LOCAL_AUTH,
510	"Show Preferred MTU", "show mtu"},
511  { "ofilter",  NULL,     ShowOfilter,		LOCAL_AUTH,
512	"Show Output filters", "show ofilter option .."},
513  { "proto",    NULL,     ReportProtStatus,	LOCAL_AUTH,
514	"Show protocol summary", "show proto"},
515  { "reconnect",NULL,	  ShowReconnect,	LOCAL_AUTH,
516	"Show Reconnect timer,tries", "show reconnect"},
517  { "redial",   NULL,	  ShowRedial,		LOCAL_AUTH,
518	"Show Redial timeout value", "show redial"},
519  { "route",    NULL,     ShowRoute,		LOCAL_AUTH,
520	"Show routing table", "show route"},
521  { "timeout",  NULL,	  ShowTimeout,		LOCAL_AUTH,
522	"Show Idle timeout value", "show timeout"},
523#ifndef NOMSEXT
524  { "msext", 	NULL,	  ShowMSExt,		LOCAL_AUTH,
525	"Show MS PPP extentions", "show msext"},
526#endif
527  { "version",  NULL,	  ShowVersion,		LOCAL_NO_AUTH | LOCAL_AUTH,
528	"Show version string", "show version"},
529  { "help",     "?",      HelpCommand,		LOCAL_NO_AUTH | LOCAL_AUTH,
530	"Display this message", "show help|? [command]", (void *)ShowCommands},
531  { NULL,       NULL,     NULL },
532};
533
534struct cmdtab *
535FindCommand(cmds, str, pmatch)
536struct cmdtab *cmds;
537char *str;
538int *pmatch;
539{
540  int nmatch;
541  int len;
542  struct cmdtab *found;
543
544  found = NULL;
545  len = strlen(str);
546  nmatch = 0;
547  while (cmds->func) {
548    if (cmds->name && strncasecmp(str, cmds->name, len) == 0) {
549      if (cmds->name[len] == '\0') {
550        *pmatch = 1;
551        return cmds;
552      }
553      nmatch++;
554      found = cmds;
555    } else if(cmds->alias && strncasecmp(str, cmds->alias, len) == 0) {
556      if (cmds->alias[len] == '\0') {
557        *pmatch = 1;
558        return cmds;
559      }
560      nmatch++;
561      found = cmds;
562    }
563    cmds++;
564  }
565  *pmatch = nmatch;
566  return found;
567}
568
569int
570FindExec(cmdlist, argc, argv)
571struct cmdtab *cmdlist;
572int argc;
573char **argv;
574{
575  struct cmdtab *cmd;
576  int val = 1;
577  int nmatch;
578
579  cmd = FindCommand(cmdlist, *argv, &nmatch);
580  if (nmatch > 1)
581    LogPrintf(LogWARN, "%s: Ambiguous command\n", *argv);
582  else if (cmd && ( cmd->lauth & VarLocalAuth ) )
583    val = (cmd->func)(cmd, --argc, ++argv, cmd->args);
584  else
585    LogPrintf(LogWARN, "%s: Invalid command\n", *argv);
586
587  if (val == -1)
588    LogPrintf(LogWARN, "Usage: %s\n", cmd->syntax);
589  else if(val)
590    LogPrintf(LogCOMMAND, "%s: Failed %d\n", *argv, val);
591
592  return val;
593}
594
595int aft_cmd = 1;
596extern int TermMode;
597
598void
599Prompt()
600{
601  char *pconnect, *pauth;
602
603  if (!(mode & MODE_INTER) || !VarTerm || TermMode)
604    return;
605
606  if (!aft_cmd)
607    fprintf(VarTerm, "\n");
608  else
609    aft_cmd = 0;
610
611  if ( VarLocalAuth == LOCAL_AUTH )
612    pauth = " ON ";
613  else
614    pauth = " on ";
615  if (IpcpFsm.state == ST_OPENED && phase == PHASE_NETWORK)
616    pconnect = "PPP";
617  else
618    pconnect = "ppp";
619  fprintf(VarTerm, "%s%s%s> ", pconnect, pauth, VarShortHost);
620  fflush(VarTerm);
621}
622
623void
624DecodeCommand(buff, nb, prompt)
625char *buff;
626int nb;
627int prompt;
628{
629  char *vector[20];
630  char **argv;
631  int argc;
632  char *cp;
633
634  if (nb > 0) {
635    cp = buff + strcspn(buff, "\r\n");
636    if (cp)
637      *cp = '\0';
638    argc = MakeArgs(buff, vector, VECSIZE(vector));
639    argv = vector;
640
641    if (argc > 0)
642      FindExec(Commands, argc, argv);
643  }
644  if (prompt)
645    Prompt();
646}
647
648static int
649ShowCommand(list, argc, argv)
650struct cmdtab *list;
651int argc;
652char **argv;
653{
654  if (argc > 0)
655    FindExec(ShowCommands, argc, argv);
656  else if (VarTerm)
657    fprintf(VarTerm, "Use ``show ?'' to get a list.\n");
658  else
659    LogPrintf(LogWARN, "show command must have arguments\n");
660
661  return 0;
662}
663
664static int
665TerminalCommand()
666{
667  if (LcpFsm.state > ST_CLOSED) {
668    if (VarTerm)
669      fprintf(VarTerm, "LCP state is [%s]\n", StateNames[LcpFsm.state]);
670    return 1;
671  }
672  if (!IsInteractive())
673    return(1);
674  modem = OpenModem(mode);
675  if (modem < 0) {
676    if (VarTerm)
677      fprintf(VarTerm, "Failed to open modem.\n");
678    return(1);
679  }
680  if (VarTerm) {
681    fprintf(VarTerm, "Enter to terminal mode.\n");
682    fprintf(VarTerm, "Type `~?' for help.\n");
683  }
684  TtyTermMode();
685  return(0);
686}
687
688static int
689QuitCommand(list, argc, argv)
690struct cmdtab *list;
691int argc;
692char **argv;
693{
694  FILE *oVarTerm;
695
696  if (mode & (MODE_DIRECT|MODE_DEDICATED|MODE_AUTO)) {
697    if (argc > 0 && (VarLocalAuth & LOCAL_AUTH)) {
698      Cleanup(EX_NORMAL);
699      mode &= ~MODE_INTER;
700      oVarTerm = VarTerm;
701      VarTerm = 0;
702      if (oVarTerm && oVarTerm != stdout)
703        fclose(oVarTerm);
704    } else {
705      LogPrintf(LogPHASE, "Client connection closed.\n");
706      VarLocalAuth = LOCAL_NO_AUTH;
707      mode &= ~MODE_INTER;
708      oVarTerm = VarTerm;
709      VarTerm = 0;
710      if (oVarTerm && oVarTerm != stdout)
711        fclose(oVarTerm);
712      close(netfd);
713      netfd = -1;
714    }
715  } else
716    Cleanup(EX_NORMAL);
717
718  return 0;
719}
720
721static int
722CloseCommand()
723{
724  reconnect(RECON_FALSE);
725  LcpClose();
726  if (mode & MODE_BACKGROUND)
727      Cleanup(EX_NORMAL);
728  return 0;
729}
730
731static int
732DownCommand()
733{
734  LcpDown();
735  return 0;
736}
737
738static int
739SetModemSpeed(list, argc, argv)
740struct cmdtab *list;
741int argc;
742char **argv;
743{
744  int speed;
745
746  if (argc > 0) {
747    if (strcmp(*argv, "sync") == 0) {
748      VarSpeed = 0;
749      return 0;
750    }
751    speed = atoi(*argv);
752    if (IntToSpeed(speed) != B0) {
753      VarSpeed = speed;
754      return 0;
755    }
756    LogPrintf(LogWARN, "%s: Invalid speed\n", *argv);
757  }
758  return -1;
759}
760
761static int
762SetReconnect(list, argc, argv)
763struct cmdtab *list;
764int argc;
765char **argv;
766{
767  if (argc == 2) {
768    VarReconnectTimer = atoi(argv[0]);
769    VarReconnectTries = atoi(argv[1]);
770    return 0;
771  }
772
773  return -1;
774}
775
776static int
777SetRedialTimeout(list, argc, argv)
778struct cmdtab *list;
779int argc;
780char **argv;
781{
782  int timeout;
783  int tries;
784  char *dot;
785
786  if (argc == 1 || argc == 2 ) {
787    if (strncasecmp(argv[0], "random", 6) == 0 &&
788	(argv[0][6] == '\0' || argv[0][6] == '.')) {
789      VarRedialTimeout = -1;
790      if (!randinit) {
791	randinit = 1;
792	srandomdev();
793      }
794    } else {
795      timeout = atoi(argv[0]);
796
797      if (timeout >= 0)
798	VarRedialTimeout = timeout;
799      else {
800	LogPrintf(LogWARN, "Invalid redial timeout\n");
801        return -1;
802      }
803    }
804
805    dot = index(argv[0],'.');
806    if (dot) {
807      if (strcasecmp(++dot, "random") == 0) {
808        VarRedialNextTimeout = -1;
809        if (!randinit) {
810          randinit = 1;
811	  srandomdev();
812        }
813      }
814      else {
815        timeout = atoi(dot);
816        if (timeout >= 0)
817          VarRedialNextTimeout = timeout;
818        else {
819          LogPrintf(LogWARN, "Invalid next redial timeout\n");
820	  return -1;
821        }
822      }
823    }
824    else
825      VarRedialNextTimeout = NEXT_REDIAL_PERIOD;   /* Default next timeout */
826
827    if (argc == 2) {
828      tries = atoi(argv[1]);
829
830      if (tries >= 0) {
831	VarDialTries = tries;
832      } else {
833	LogPrintf(LogWARN, "Invalid retry value\n");
834	return 1;
835      }
836    }
837    return 0;
838  }
839
840  return -1;
841}
842
843static int
844SetServer(list, argc, argv)
845struct cmdtab *list;
846int argc;
847char **argv;
848{
849  int res = -1;
850
851  if (argc > 0 && argc < 3)
852    if (strcasecmp(argv[0], "none") == 0) {
853      ServerClose();
854      LogPrintf(LogPHASE, "Disabling server port.\n");
855      res = 0;
856    } else if (*argv[0] == '/') {
857      mode_t mask;
858      umask(mask = umask(0));
859      if (argc == 2) {
860        unsigned m;
861        if (sscanf(argv[1], "%o", &m) == 1)
862          mask = m;
863      }
864      res = ServerLocalOpen(argv[0], mask);
865    } else {
866      int port;
867      if (strspn(argv[0], "0123456789") != strlen(argv[0])) {
868        struct servent *s;
869        if ((s = getservbyname(argv[0], "tcp")) == NULL) {
870          port = 0;
871          LogPrintf(LogWARN, "%s: Invalid port or service\n", argv[0]);
872        } else
873          port = ntohs(s->s_port);
874      } else
875        port = atoi(argv[0]);
876      if (port)
877        res = ServerTcpOpen(port);
878    }
879
880  return res;
881}
882
883static int
884SetModemParity(list, argc, argv)
885struct cmdtab *list;
886int argc;
887char **argv;
888{
889  return argc > 0 ? ChangeParity(*argv) : -1;
890}
891
892static int
893SetLogLevel(list, argc, argv)
894struct cmdtab *list;
895int argc;
896char **argv;
897{
898  int i;
899  int res;
900  char *arg;
901
902  res = 0;
903  if (argc == 0 || (argv[0][0] != '+' && argv[0][0] != '-'))
904    LogDiscardAll();
905  while (argc--) {
906    arg = **argv == '+' || **argv == '-' ? *argv + 1 : *argv;
907    for (i = LogMIN; i <= LogMAX; i++)
908      if (strcasecmp(arg, LogName(i)) == 0) {
909        if (**argv == '-')
910          LogDiscard(i);
911        else
912	  LogKeep(i);
913	break;
914      }
915    if (i > LogMAX) {
916      LogPrintf(LogWARN, "%s: Invalid log value\n", arg);
917      res = -1;
918    }
919    argv++;
920  }
921  return res;
922}
923
924static int
925SetEscape(list, argc, argv)
926struct cmdtab *list;
927int argc;
928char **argv;
929{
930  int code;
931
932  for (code = 0; code < 33; code++)
933    EscMap[code] = 0;
934  while (argc-- > 0) {
935    sscanf(*argv++, "%x", &code);
936    code &= 0xff;
937    EscMap[code >> 3] |= (1 << (code&7));
938    EscMap[32] = 1;
939  }
940  return 0;
941}
942
943static int
944SetInitialMRU(list, argc, argv)
945struct cmdtab *list;
946int argc;
947char **argv;
948{
949  long mru;
950  char *err;
951
952  if (argc > 0) {
953    mru = atol(*argv);
954    if (mru < MIN_MRU)
955      err = "Given MRU value (%ld) is too small.\n";
956    else if (mru > MAX_MRU)
957      err = "Given MRU value (%ld) is too big.\n";
958    else {
959      VarMRU = mru;
960      return 0;
961    }
962    LogPrintf(LogWARN, err, mru);
963  }
964
965  return -1;
966}
967
968static int
969SetPreferredMTU(list, argc, argv)
970struct cmdtab *list;
971int argc;
972char **argv;
973{
974  long mtu;
975  char *err;
976
977  if (argc > 0) {
978    mtu = atol(*argv);
979    if (mtu == 0) {
980      VarPrefMTU = 0;
981      return 0;
982    } else if (mtu < MIN_MTU)
983      err = "Given MTU value (%ld) is too small.\n";
984    else if (mtu > MAX_MTU)
985      err = "Given MTU value (%ld) is too big.\n";
986    else {
987      VarPrefMTU = mtu;
988      return 0;
989    }
990    LogPrintf(LogWARN, err, mtu);
991  }
992
993  return -1;
994}
995
996static int
997SetIdleTimeout(list, argc, argv)
998struct cmdtab *list;
999int argc;
1000char **argv;
1001{
1002  if (argc-- > 0) {
1003    VarIdleTimeout = atoi(*argv++);
1004    UpdateIdleTimer();  /* If we're connected, restart the idle timer */
1005    if (argc-- > 0) {
1006      VarLqrTimeout = atoi(*argv++);
1007      if (VarLqrTimeout < 1)
1008	VarLqrTimeout = 30;
1009      if (argc > 0) {
1010	VarRetryTimeout = atoi(*argv);
1011	if (VarRetryTimeout < 1 || VarRetryTimeout > 10)
1012	  VarRetryTimeout = 3;
1013      }
1014    }
1015    return 0;
1016  }
1017
1018  return -1;
1019}
1020
1021struct in_addr
1022GetIpAddr(cp)
1023char *cp;
1024{
1025  struct hostent *hp;
1026  struct in_addr ipaddr;
1027
1028  hp = gethostbyname(cp);
1029  if (hp && hp->h_addrtype == AF_INET)
1030    bcopy(hp->h_addr, &ipaddr, hp->h_length);
1031  else if (inet_aton(cp, &ipaddr) == 0)
1032    ipaddr.s_addr = 0;
1033  return(ipaddr);
1034}
1035
1036static int
1037SetInterfaceAddr(list, argc, argv)
1038struct cmdtab *list;
1039int argc;
1040char **argv;
1041{
1042
1043  DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L;
1044  if (argc > 4)
1045     return -1;
1046
1047  if (argc > 0) {
1048    if (ParseAddr(argc, argv++,
1049            &DefMyAddress.ipaddr,
1050	    &DefMyAddress.mask,
1051	    &DefMyAddress.width) == 0)
1052       return 1;
1053    if (--argc > 0) {
1054      if (ParseAddr(argc, argv++,
1055		    &DefHisAddress.ipaddr,
1056		    &DefHisAddress.mask,
1057		    &DefHisAddress.width) == 0)
1058	 return 2;
1059      if (--argc > 0) {
1060        ifnetmask = GetIpAddr(*argv);
1061    	if (--argc > 0) {
1062	   if (ParseAddr(argc, argv++,
1063			 &DefTriggerAddress.ipaddr,
1064			 &DefTriggerAddress.mask,
1065			 &DefTriggerAddress.width) == 0)
1066	      return 3;
1067	}
1068      }
1069    }
1070  }
1071  /*
1072   * For backwards compatibility, 0.0.0.0 means any address.
1073   */
1074  if (DefMyAddress.ipaddr.s_addr == 0) {
1075    DefMyAddress.mask.s_addr = 0;
1076    DefMyAddress.width = 0;
1077  }
1078  if (DefHisAddress.ipaddr.s_addr == 0) {
1079    DefHisAddress.mask.s_addr = 0;
1080    DefHisAddress.width = 0;
1081  }
1082
1083  if ((mode & MODE_AUTO) ||
1084	((mode & MODE_DEDICATED) && dstsystem)) {
1085    if (OsSetIpaddress(DefMyAddress.ipaddr, DefHisAddress.ipaddr, ifnetmask) < 0)
1086       return 4;
1087  }
1088  return 0;
1089}
1090
1091#ifndef NOMSEXT
1092
1093void
1094SetMSEXT(pri_addr, sec_addr, argc, argv)
1095struct in_addr *pri_addr;
1096struct in_addr *sec_addr;
1097int argc;
1098char **argv;
1099{
1100  int dummyint;
1101  struct in_addr dummyaddr;
1102
1103  pri_addr->s_addr = sec_addr->s_addr = 0L;
1104
1105  if( argc > 0 ) {
1106    ParseAddr(argc, argv++, pri_addr, &dummyaddr, &dummyint);
1107    if( --argc > 0 )
1108      ParseAddr(argc, argv++, sec_addr, &dummyaddr, &dummyint);
1109    else
1110      sec_addr->s_addr = pri_addr->s_addr;
1111  }
1112
1113 /*
1114  * if the primary/secondary ns entries are 0.0.0.0 we should
1115  * set them to either the localhost's ip, or the values in
1116  * /etc/resolv.conf ??
1117  *
1118  * up to you if you want to implement this...
1119  */
1120
1121}
1122
1123static int
1124SetNS(list, argc, argv)
1125struct cmdtab *list;
1126int argc;
1127char **argv;
1128{
1129  SetMSEXT(&ns_entries[0], &ns_entries[1], argc, argv);
1130  return 0;
1131}
1132
1133static int
1134SetNBNS(list, argc, argv)
1135struct cmdtab *list;
1136int argc;
1137char **argv;
1138{
1139  SetMSEXT(&nbns_entries[0], &nbns_entries[1], argc, argv);
1140  return 0;
1141}
1142
1143#endif /* MS_EXT */
1144
1145#define	VAR_AUTHKEY	0
1146#define	VAR_DIAL	1
1147#define	VAR_LOGIN	2
1148#define	VAR_AUTHNAME	3
1149#define	VAR_DEVICE	4
1150#define	VAR_ACCMAP	5
1151#define	VAR_PHONE	6
1152
1153static int
1154SetVariable(list, argc, argv, param)
1155struct cmdtab *list;
1156int argc;
1157char **argv;
1158int param;
1159{
1160  u_long map;
1161  char *arg;
1162
1163  if (argc > 0)
1164    arg = *argv;
1165  else
1166    arg = "";
1167
1168  switch (param) {
1169    case VAR_AUTHKEY:
1170      strncpy(VarAuthKey, arg, sizeof(VarAuthKey)-1);
1171      VarAuthKey[sizeof(VarAuthKey)-1] = '\0';
1172      break;
1173    case VAR_AUTHNAME:
1174      strncpy(VarAuthName, arg, sizeof(VarAuthName)-1);
1175      VarAuthName[sizeof(VarAuthName)-1] = '\0';
1176      break;
1177    case VAR_DIAL:
1178      strncpy(VarDialScript, arg, sizeof(VarDialScript)-1);
1179      VarDialScript[sizeof(VarDialScript)-1] = '\0';
1180      break;
1181    case VAR_LOGIN:
1182      strncpy(VarLoginScript, arg, sizeof(VarLoginScript)-1);
1183      VarLoginScript[sizeof(VarLoginScript)-1] = '\0';
1184      break;
1185    case VAR_DEVICE:
1186      CloseModem();
1187      strncpy(VarDevice, arg, sizeof(VarDevice)-1);
1188      VarDevice[sizeof(VarDevice)-1] = '\0';
1189      VarBaseDevice = rindex(VarDevice, '/');
1190      VarBaseDevice = VarBaseDevice ? VarBaseDevice + 1 : "";
1191      break;
1192    case VAR_ACCMAP:
1193      sscanf(arg, "%lx", &map);
1194      VarAccmap = map;
1195      break;
1196    case VAR_PHONE:
1197      strncpy(VarPhoneList, arg, sizeof(VarPhoneList)-1);
1198      VarPhoneList[sizeof(VarPhoneList)-1] = '\0';
1199      strcpy(VarPhoneCopy, VarPhoneList);
1200      VarNextPhone = VarPhoneCopy;
1201      break;
1202  }
1203  return 0;
1204}
1205
1206static int SetCtsRts(list, argc, argv)
1207struct cmdtab *list;
1208int argc;
1209char **argv;
1210{
1211  if (argc > 0) {
1212    if (strcmp(*argv, "on") == 0)
1213      VarCtsRts = TRUE;
1214    else if (strcmp(*argv, "off") == 0)
1215      VarCtsRts = FALSE;
1216    else
1217      return -1;
1218    return 0;
1219  }
1220  return -1;
1221}
1222
1223
1224static int SetOpenMode(list, argc, argv)
1225struct cmdtab *list;
1226int argc;
1227char **argv;
1228{
1229  if (argc > 0) {
1230    if (strcmp(*argv, "active") == 0)
1231      VarOpenMode = OPEN_ACTIVE;
1232    else if (strcmp(*argv, "passive") == 0)
1233      VarOpenMode = OPEN_PASSIVE;
1234    else
1235      return -1;
1236    return 0;
1237  }
1238  return -1;
1239}
1240
1241extern int SetIfilter(), SetOfilter(), SetDfilter(), SetAfilter();
1242
1243struct cmdtab const SetCommands[] = {
1244  { "accmap",   NULL,	  SetVariable,		LOCAL_AUTH,
1245	"Set accmap value", "set accmap hex-value", (void *)VAR_ACCMAP},
1246  { "afilter",  NULL,     SetAfilter, 		LOCAL_AUTH,
1247	"Set keep Alive filter", "set afilter ..."},
1248  { "authkey",  "key",     SetVariable,		LOCAL_AUTH,
1249	"Set authentication key", "set authkey|key key", (void *)VAR_AUTHKEY},
1250  { "authname", NULL,     SetVariable,		LOCAL_AUTH,
1251	"Set authentication name", "set authname name", (void *)VAR_AUTHNAME},
1252  { "ctsrts", NULL,	  SetCtsRts,		LOCAL_AUTH,
1253	"Use CTS/RTS modem signalling", "set ctsrts [on|off]"},
1254  { "device",     "line", SetVariable, 		LOCAL_AUTH,
1255	"Set modem device name", "set device|line device-name", (void *)VAR_DEVICE},
1256  { "dfilter",  NULL,     SetDfilter,		 LOCAL_AUTH,
1257	"Set demand filter", "set dfilter ..."},
1258  { "dial",     NULL,     SetVariable, 		LOCAL_AUTH,
1259	"Set dialing script", "set dial chat-script", (void *)VAR_DIAL},
1260  { "escape",   NULL,	  SetEscape, 		LOCAL_AUTH,
1261	"Set escape characters", "set escape hex-digit ..."},
1262  { "ifaddr",   NULL,   SetInterfaceAddr,	LOCAL_AUTH,
1263	"Set destination address", "set ifaddr [src-addr [dst-addr [netmask [trg-addr]]]]"},
1264  { "ifilter",  NULL,     SetIfilter, 		LOCAL_AUTH,
1265	"Set input filter", "set ifilter ..."},
1266  { "log",    NULL,	  SetLogLevel,	LOCAL_AUTH,
1267	"Set log level", "set log [+|-]value..."},
1268  { "login",    NULL,     SetVariable,		LOCAL_AUTH,
1269	"Set login script", "set login chat-script",	(void *)VAR_LOGIN },
1270  { "mru",      NULL,     SetInitialMRU,	LOCAL_AUTH,
1271	"Set Initial MRU value", "set mru value" },
1272  { "mtu",      NULL,     SetPreferredMTU,	LOCAL_AUTH,
1273	"Set Preferred MTU value", "set mtu value" },
1274  { "ofilter",  NULL,	  SetOfilter,		LOCAL_AUTH,
1275	"Set output filter", "set ofilter ..." },
1276  { "openmode", NULL,	  SetOpenMode,		LOCAL_AUTH,
1277	"Set open mode", "set openmode [active|passive]"},
1278  { "parity",   NULL,     SetModemParity,	LOCAL_AUTH,
1279	"Set modem parity", "set parity [odd|even|none]"},
1280  { "phone",    NULL,     SetVariable,		LOCAL_AUTH,
1281	"Set telephone number(s)", "set phone phone1[:phone2[...]]", (void *)VAR_PHONE },
1282  { "reconnect",NULL,     SetReconnect,		LOCAL_AUTH,
1283	"Set Reconnect timeout", "set reconnect value ntries"},
1284  { "redial",   NULL,     SetRedialTimeout,	LOCAL_AUTH,
1285	"Set Redial timeout", "set redial value|random[.value|random] [dial_attempts]"},
1286  { "server",    "socket",     SetServer,	LOCAL_AUTH,
1287	"Set server port", "set server|socket TcpPort|LocalName|none [mask]"},
1288  { "speed",    NULL,     SetModemSpeed,	LOCAL_AUTH,
1289	"Set modem speed", "set speed value"},
1290  { "timeout",  NULL,     SetIdleTimeout,	LOCAL_AUTH,
1291	"Set Idle timeout", "set timeout value"},
1292#ifndef NOMSEXT
1293  { "ns",	NULL,	  SetNS,		LOCAL_AUTH,
1294	"Set NameServer", "set ns pri-addr [sec-addr]"},
1295  { "nbns",	NULL,	  SetNBNS,		LOCAL_AUTH,
1296	"Set NetBIOS NameServer", "set nbns pri-addr [sec-addr]"},
1297#endif
1298  { "help",     "?",      HelpCommand,		LOCAL_AUTH | LOCAL_NO_AUTH,
1299	"Display this message", "set help|? [command]", (void *)SetCommands},
1300  { NULL,       NULL,     NULL },
1301};
1302
1303static int
1304SetCommand(list, argc, argv)
1305struct cmdtab *list;
1306int argc;
1307char **argv;
1308{
1309  if (argc > 0)
1310    FindExec(SetCommands, argc, argv);
1311  else if (VarTerm)
1312    fprintf(VarTerm, "Use `set ?' to get a list or `set ? <var>' for"
1313	    " syntax help.\n");
1314  else
1315    LogPrintf(LogWARN, "set command must have arguments\n");
1316
1317  return 0;
1318}
1319
1320
1321static int
1322AddCommand(list, argc, argv)
1323struct cmdtab *list;
1324int argc;
1325char **argv;
1326{
1327  struct in_addr dest, gateway, netmask;
1328
1329  if (argc == 3) {
1330    if (strcasecmp(argv[0], "MYADDR") == 0)
1331      dest = IpcpInfo.want_ipaddr;
1332    else
1333      dest = GetIpAddr(argv[0]);
1334    netmask = GetIpAddr(argv[1]);
1335    if (strcasecmp(argv[2], "HISADDR") == 0)
1336      gateway = IpcpInfo.his_ipaddr;
1337    else
1338      gateway = GetIpAddr(argv[2]);
1339    OsSetRoute(RTM_ADD, dest, gateway, netmask);
1340    return 0;
1341  }
1342
1343  return -1;
1344}
1345
1346static int
1347DeleteCommand(list, argc, argv)
1348struct cmdtab *list;
1349int argc;
1350char **argv;
1351{
1352  struct in_addr dest, gateway, netmask;
1353
1354  if (argc == 1 && strcasecmp(argv[0], "all") == 0)
1355    DeleteIfRoutes(0);
1356  else if (argc > 0 && argc < 4) {
1357    if (strcasecmp(argv[0], "MYADDR") == 0)
1358      dest = IpcpInfo.want_ipaddr;
1359    else
1360      dest = GetIpAddr(argv[0]);
1361    netmask.s_addr = INADDR_ANY;
1362    if (argc > 1) {
1363      if (strcasecmp(argv[1], "HISADDR") == 0)
1364        gateway = IpcpInfo.his_ipaddr;
1365      else
1366        gateway = GetIpAddr(argv[1]);
1367      if (argc == 3) {
1368        if (inet_aton(argv[2], &netmask) == 0) {
1369	  LogPrintf(LogWARN, "Bad netmask value.\n");
1370	  return -1;
1371        }
1372      }
1373    } else
1374      gateway.s_addr = INADDR_ANY;
1375    OsSetRoute(RTM_DELETE, dest, gateway, netmask);
1376  } else
1377    return -1;
1378
1379  return 0;
1380}
1381
1382static int AliasEnable();
1383static int AliasOption();
1384
1385static struct cmdtab const AliasCommands[] =
1386{
1387  { "enable",   NULL,     AliasEnable,          LOCAL_AUTH,
1388        "enable IP aliasing", "alias enable [yes|no]"},
1389  { "port",   NULL,     AliasRedirectPort,          LOCAL_AUTH,
1390        "port redirection", "alias port [proto addr_local:port_local  port_alias]"},
1391  { "addr",   NULL,     AliasRedirectAddr,          LOCAL_AUTH,
1392        "static address translation", "alias addr [addr_local addr_alias]"},
1393  { "deny_incoming",  NULL,    AliasOption,     LOCAL_AUTH,
1394        "stop incoming connections",   "alias deny_incoming [yes|no]",
1395        (void*)PKT_ALIAS_DENY_INCOMING},
1396  { "log",  NULL,     AliasOption,              LOCAL_AUTH,
1397        "log aliasing link creation",           "alias log [yes|no]",
1398        (void*)PKT_ALIAS_LOG},
1399  { "same_ports", NULL,     AliasOption,        LOCAL_AUTH,
1400        "try to leave port numbers unchanged", "alias same_ports [yes|no]",
1401        (void*)PKT_ALIAS_SAME_PORTS},
1402  { "use_sockets", NULL,     AliasOption,       LOCAL_AUTH,
1403        "allocate host sockets", "alias use_sockets [yes|no]",
1404        (void*)PKT_ALIAS_USE_SOCKETS },
1405  { "unregistered_only", NULL,     AliasOption, LOCAL_AUTH,
1406        "alias unregistered (private) IP address space only",
1407        "alias unregistered_only [yes|no]",
1408        (void*)PKT_ALIAS_UNREGISTERED_ONLY},
1409  { "help",     "?",      HelpCommand,          LOCAL_AUTH | LOCAL_NO_AUTH,
1410        "Display this message", "alias help|? [command]",
1411        (void *)AliasCommands},
1412  { NULL,       NULL,     NULL },
1413};
1414
1415
1416static int
1417AliasCommand(list, argc, argv)
1418struct cmdtab *list;
1419int argc;
1420char **argv;
1421{
1422  if (argc > 0)
1423    FindExec(AliasCommands, argc, argv);
1424  else if (VarTerm)
1425    fprintf(VarTerm, "Use `alias help' to get a list or `alias help <option>'"
1426	    " for syntax help.\n");
1427  else
1428    LogPrintf(LogWARN, "alias command must have arguments\n");
1429
1430  return 0;
1431}
1432
1433static int
1434AliasEnable(list, argc, argv)
1435struct cmdtab *list;
1436int argc;
1437char **argv;
1438{
1439  if (argc == 1)
1440    if (strcasecmp(argv[0], "yes") == 0) {
1441      if (!(mode & MODE_ALIAS)) {
1442        if (loadAliasHandlers(&VarAliasHandlers) == 0) {
1443          mode |= MODE_ALIAS;
1444          return 0;
1445        }
1446        LogPrintf(LogWARN, "Cannot load alias library\n");
1447        return 1;
1448      }
1449      return 0;
1450    } else if (strcasecmp(argv[0], "no") == 0) {
1451      if (mode & MODE_ALIAS) {
1452        unloadAliasHandlers();
1453        mode &= ~MODE_ALIAS;
1454      }
1455      return 0;
1456    }
1457
1458  return -1;
1459}
1460
1461
1462static int
1463AliasOption(list, argc, argv, param)
1464struct cmdtab *list;
1465int argc;
1466char **argv;
1467void* param;
1468{
1469   if (argc == 1)
1470     if (strcasecmp(argv[0], "yes") == 0) {
1471       if (mode & MODE_ALIAS) {
1472         VarSetPacketAliasMode((unsigned)param, (unsigned)param);
1473         return 0;
1474       }
1475       LogPrintf(LogWARN, "alias not enabled\n");
1476     } else if (strcmp(argv[0], "no") == 0) {
1477       if (mode & MODE_ALIAS) {
1478         VarSetPacketAliasMode(0, (unsigned)param);
1479         return 0;
1480       }
1481       LogPrintf(LogWARN, "alias not enabled\n");
1482     }
1483
1484   return -1;
1485}
1486