*/
#ifndef lint
-static char rcsid[] = "$Id: options.c,v 1.55 1999/03/24 05:05:24 paulus Exp $";
+static const char rcsid[] = "$Id: options.c,v 1.63 1999/08/13 01:57:36 paulus Exp $";
#endif
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <termios.h>
#include <syslog.h>
bool lockflag = 0; /* Create lock file to lock the serial dev */
bool nodetach = 0; /* Don't detach from controlling tty */
bool updetach = 0; /* Detach once link is up */
+char *initializer = NULL; /* Script to initialize physical link */
char *connector = NULL; /* Script to establish physical link */
char *disconnector = NULL; /* Script to disestablish physical link */
char *welcomer = NULL; /* Script to run after phys link estab. */
bool notty = 0; /* Stdin/out is not a tty */
char *record_file = NULL; /* File to record chars sent/received */
int using_pty = 0;
+bool sync_serial = 0; /* Device is synchronous serial device */
+int log_to_fd = 1; /* send log messages to this fd too */
+int maxfail = 10; /* max # of unsuccessful connection attempts */
+char linkname[MAXPATHLEN]; /* logical name for link */
extern option_t auth_options[];
+extern struct stat devstat;
+extern int prepass; /* Doing pre-pass to find device name */
+struct option_info initializer_info;
struct option_info connector_info;
struct option_info disconnector_info;
struct option_info welcomer_info;
pcap_t pc; /* Fake struct pcap so we can compile expr */
#endif
+char *current_option; /* the name of the option being parsed */
+int privileged_option; /* set iff the current option came from root */
+char *option_source; /* string saying where the option came from */
+bool log_to_file; /* log_to_fd is a file opened by us */
+
/*
* Prototypes
*/
-static int setdevname __P((char *, int));
+static int setdevname __P((char *));
static int setipaddr __P((char *));
static int setspeed __P((char *));
static int noopt __P((char **));
static int showversion __P((char **));
static int showhelp __P((char **));
static void usage __P((void));
+static int setlogfile __P((char **));
#ifdef PPP_FILTER
static int setpassfilter __P((char **));
"Lock serial device with UUCP-style lock file", 1 },
{ "-all", o_special_noarg, noopt,
"Don't request/allow any LCP or IPCP options (useless)" },
+ { "init", o_string, &initializer,
+ "A program to initialize the device",
+ OPT_A2INFO | OPT_PRIVFIX, &initializer_info },
{ "connect", o_string, &connector,
"A program to set up a connection",
OPT_A2INFO | OPT_PRIVFIX, &connector_info },
OPT_A2INFO | OPT_PRIVFIX, &welcomer_info },
{ "pty", o_string, &ptycommand,
"Script to run on pseudo-tty master side",
- OPT_A2INFO | OPT_PRIVFIX, &ptycommand_info },
+ OPT_A2INFO | OPT_PRIVFIX | OPT_DEVNAM, &ptycommand_info },
{ "notty", o_bool, ¬ty,
- "Input/output is not a tty", 1 },
+ "Input/output is not a tty", OPT_DEVNAM | 1 },
{ "record", o_string, &record_file,
"Record characters sent/received to file" },
{ "maxconnect", o_int, &maxconnect,
{ "local", o_bool, &modem,
"Don't use modem control lines" },
{ "file", o_special, readfile,
- "Take options from a file" },
+ "Take options from a file", OPT_PREPASS },
{ "call", o_special, callfile,
- "Take options from a privileged file" },
+ "Take options from a privileged file", OPT_PREPASS },
{ "persist", o_bool, &persist,
"Keep on reopening connection after close", 1 },
{ "nopersist", o_bool, &persist,
"Turn off persist option" },
{ "demand", o_bool, &demand,
- "Dial on demand", 1, &persist },
+ "Dial on demand", OPT_INITONLY | 1, &persist },
{ "--version", o_special_noarg, showversion,
"Show version number" },
{ "--help", o_special_noarg, showhelp,
"Show brief listing of options" },
{ "-h", o_special_noarg, showhelp,
"Show brief listing of options" },
+ { "sync", o_bool, &sync_serial,
+ "Use synchronous HDLC serial encoding", 1 },
+ { "logfd", o_int, &log_to_fd,
+ "Send log messages to this file descriptor" },
+ { "logfile", o_special, setlogfile,
+ "Append log messages to this file" },
+ { "nolog", o_int, &log_to_fd,
+ "Don't send log messages to any file",
+ OPT_NOARG | OPT_VAL(-1) },
+ { "nologfd", o_int, &log_to_fd,
+ "Don't send log messages to any file descriptor",
+ OPT_NOARG | OPT_VAL(-1) },
+ { "linkname", o_string, linkname,
+ "Set logical name for link",
+ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
+ { "maxfail", o_int, &maxfail,
+ "Maximum number of unsuccessful connection attempts to allow" },
#ifdef PPP_FILTER
{ "pdebug", o_int, &dflag,
/*
* parse_args - parse a string of arguments from the command line.
+ * If prepass is true, we are scanning for the device name and only
+ * processing a few options, so error messages are suppressed.
*/
int
parse_args(argc, argv)
/*
* Maybe a tty name, speed or IP address?
*/
- if ((ret = setdevname(arg, 0)) == 0
+ if ((ret = setdevname(arg)) == 0
&& (ret = setspeed(arg)) == 0
&& (ret = setipaddr(arg)) == 0) {
option_error("unrecognized option '%s'", arg);
return 1;
}
+#if 0
/*
* scan_args - scan the command line arguments to get the tty name,
* if specified. Also checks whether the notty or pty option was given.
(void) setdevname(arg, 1);
}
}
+#endif
/*
* options_from_file - Read a string of options from a file,
int priv;
{
FILE *f;
- int i, newline, ret;
+ int i, newline, ret, err;
option_t *opt;
int oldpriv;
char *oldsource;
if (check_prot)
seteuid(getuid());
f = fopen(filename, "r");
+ err = errno;
if (check_prot)
seteuid(0);
if (f == NULL) {
- if (!must_exist && errno == ENOENT)
+ if (!must_exist && err == ENOENT)
return 1;
+ errno = err;
option_error("Can't open options file %s: %m", filename);
return 0;
}
argv[i] = args[i];
}
current_option = cmd;
+ if ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) {
+ option_error("the %s option may not be used in the %s file",
+ cmd, filename);
+ goto err;
+ }
if (!process_option(opt, argv))
goto err;
continue;
/*
* Maybe a tty name, speed or IP address?
*/
- if ((i = setdevname(cmd, 0)) == 0
+ if ((i = setdevname(cmd)) == 0
&& (i = setspeed(cmd)) == 0
&& (i = setipaddr(cmd)) == 0) {
option_error("In file %s: unrecognized option '%s'",
return ret;
}
+/*
+ * options_from_list - process a string of options in a wordlist.
+ */
+int
+options_from_list(w, priv)
+ struct wordlist *w;
+ int priv;
+{
+ char *argv[MAXARGS];
+ option_t *opt;
+ int i, ret = 0;
+
+ privileged_option = priv;
+ option_source = "secrets file";
+
+ while (w != NULL) {
+ /*
+ * First see if it's a command.
+ */
+ opt = find_option(w->word);
+ if (opt != NULL) {
+ int n = n_arguments(opt);
+ struct wordlist *w0 = w;
+ for (i = 0; i < n; ++i) {
+ w = w->next;
+ if (w == NULL) {
+ option_error(
+ "In secrets file: too few parameters for option '%s'",
+ w0->word);
+ goto err;
+ }
+ argv[i] = w->word;
+ }
+ current_option = w0->word;
+ if (!process_option(opt, argv))
+ goto err;
+ continue;
+ }
+
+ /*
+ * Maybe a tty name, speed or IP address?
+ */
+ if ((i = setdevname(w->word)) == 0
+ && (i = setspeed(w->word)) == 0
+ && (i = setipaddr(w->word)) == 0) {
+ option_error("In secrets file: unrecognized option '%s'",
+ w->word);
+ goto err;
+ }
+ if (i < 0) /* error */
+ goto err;
+ }
+ ret = 1;
+
+err:
+ return ret;
+}
+
/*
* find_option - scan the option lists for the various protocols
* looking for an entry with the given name.
char *sv;
int (*parser) __P((char **));
+ if ((opt->flags & OPT_PREPASS) == 0 && prepass)
+ return 1;
+ if ((opt->flags & OPT_INITONLY) && phase != PHASE_INITIALIZE) {
+ option_error("it's too late to use the %s option", opt->name);
+ return 0;
+ }
if ((opt->flags & OPT_PRIV) && !privileged_option) {
option_error("using the %s option requires root privilege", opt->name);
return 0;
va_start(args);
fmt = va_arg(args, char *);
#endif
+ if (prepass) {
+ va_end(args);
+ return;
+ }
vslprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if (phase == PHASE_INITIALIZE)
* setdevname - Set the device name.
*/
static int
-setdevname(cp, quiet)
+setdevname(cp)
char *cp;
- int quiet;
{
struct stat statbuf;
char dev[MAXPATHLEN];
}
/*
- * Check if there is a device by this name.
+ * Check if there is a character device by this name.
*/
if (stat(cp, &statbuf) < 0) {
- if (errno == ENOENT || quiet)
+ if (errno == ENOENT)
return 0;
option_error("Couldn't stat %s: %m", cp);
return -1;
}
+ if (!S_ISCHR(statbuf.st_mode)) {
+ option_error("%s is not a character device", cp);
+ return -1;
+ }
+
+ if (phase != PHASE_INITIALIZE) {
+ option_error("device name cannot be changed after initialization");
+ return -1;
+ } else if (devnam_fixed) {
+ option_error("per-tty options file may not specify device name");
+ return -1;
+ }
if (devnam_info.priv && !privileged_option) {
- if (!quiet)
- option_error("device name cannot be overridden");
+ option_error("device name cannot be overridden");
return -1;
}
strlcpy(devnam, cp, sizeof(devnam));
+ devstat = statbuf;
default_device = 0;
devnam_info.priv = privileged_option;
devnam_info.source = option_source;
*/
if ((colon = strchr(arg, ':')) == NULL)
return 0;
+ if (prepass)
+ return 1;
/*
* If colon first character, then no local addr.
crtscts = -2;
return (1);
}
+
+static int
+setlogfile(argv)
+ char **argv;
+{
+ int fd, err;
+
+ if (!privileged_option)
+ seteuid(getuid());
+ fd = open(*argv, O_WRONLY | O_APPEND);
+ err = errno;
+ if (!privileged_option)
+ seteuid(0);
+ if (fd < 0) {
+ errno = err;
+ option_error("Can't open log file %s: %m", *argv);
+ return 0;
+ }
+ if (log_to_file && log_to_fd >= 0)
+ close(log_to_fd);
+ log_to_fd = fd;
+ log_to_file = 1;
+ return 1;
+}