#define MAX_SPEED 10 /* max. nr. of baud rates */
struct options {
- int flags; /* toggle switches, see below */
- int timeout; /* time-out period */
- char *login; /* login program */
- char *tty; /* name of tty */
- char *initstring; /* modem init string */
- char *issue; /* alternative issue file */
- int numspeed; /* number of baud rates to try */
- int speeds[MAX_SPEED]; /* baud rates to be tried */
- int eightbits; /* assume 8bit-clean tty */
+ int flags; /* toggle switches, see below */
+ int timeout; /* time-out period */
+ char *login; /* login program */
+ char *tty; /* name of tty */
+ char *initstring; /* modem init string */
+ char *issue; /* alternative issue file */
+ int numspeed; /* number of baud rates to try */
+ speed_t speeds[MAX_SPEED]; /* baud rates to be tried */
};
#define F_PARSE (1<<0) /* process modem status messages */
#define F_LCUC (1<<8) /* support for *LCUC stty modes */
#define F_KEEPSPEED (1<<9) /* follow baud rate from kernel */
#define F_KEEPCFLAGS (1<<10) /* reuse c_cflags setup from kernel */
+#define F_EIGHTBITS (1<<11) /* Assume 8bit-clean tty */
/* Storage for things detected while the login name was read. */
struct chardata {
struct Speedtab {
long speed;
- int code;
+ speed_t code;
};
static struct Speedtab speedtab[] = {
static void termio_final(struct options *op,
struct termios *tp, struct chardata *cp);
static int caps_lock(char *s);
-static int bcode(char *s);
-static void usage(FILE * out);
-static void error(const char *, ...);
+static speed_t bcode(char *s);
+static void usage(FILE * out) __attribute__((__noreturn__));
+static void log_err(const char *, ...) __attribute__((__noreturn__)) __attribute__((__format__(printf, 1, 2)));
+static void log_warn (const char *, ...) __attribute__((__format__(printf, 1, 2)));
/* Fake hostname for ut_host specified on command line. */
-char *fakehost = NULL;
+static char *fakehost;
#ifdef DEBUGGING
#define debug(s) fprintf(dbf,s); fflush(dbf)
"tty1", /* default tty line */
"", /* modem init string */
ISSUE, /* default issue file */
- 0, /* no baud rates known yet */
+ 0, /* no baud rates known yet */
+ { 0 }
};
setlocale(LC_ALL, "");
/* Let the login program take care of password validation. */
execl(options.login, options.login, "--", logname, NULL);
- error(_("%s: can't exec %s: %m"), options.tty, options.login);
+ log_err(_("%s: can't exec %s: %m"), options.tty, options.login);
}
/* Parse command-line arguments. */
-void parse_args(int argc, char **argv, struct options *op)
+static void parse_args(int argc, char **argv, struct options *op)
{
extern char *optarg;
extern int optind;
{ NULL, 0, 0, 0 }
};
- while ((c =
- getopt_long(argc, argv, "8cf:hH:iI:l:Lmnst:Uw", longopts,
+ while ((c = getopt_long(argc, argv, "8cf:hH:iI:l:Lmnst:Uw", longopts,
NULL)) != -1) {
switch (c) {
case '8':
- op->eightbits = 1;
+ op->flags |= F_EIGHTBITS;
break;
case 'c':
op->flags |= F_KEEPCFLAGS;
break;
case 't':
if ((op->timeout = atoi(optarg)) <= 0)
- error(_("bad timeout value: %s"), optarg);
+ log_err(_("bad timeout value: %s"), optarg);
break;
case 'U':
op->flags |= F_LCUC;
debug("after getopt loop\n");
if (argc < optind + 2) {
- warnx(_("not enough arguments"));
+ log_warn(_("not enough arguments"));
usage(stderr);
}
}
/* Parse alternate baud rates. */
-void parse_speeds(struct options *op, char *arg)
+static void parse_speeds(struct options *op, char *arg)
{
char *cp;
debug("entered parse_speeds\n");
for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *)0, ",")) {
if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0)
- error(_("bad speed: %s"), cp);
+ log_err(_("bad speed: %s"), cp);
if (op->numspeed >= MAX_SPEED)
- error(_("too many alternate speeds"));
+ log_err(_("too many alternate speeds"));
}
debug("exiting parsespeeds\n");
}
#ifdef SYSV_STYLE
/* Update our utmp entry. */
-void update_utmp(char *line)
+static void update_utmp(char *line)
{
struct utmp ut;
time_t t;
#endif /* SYSV_STYLE */
/* Set up tty as stdin, stdout & stderr. */
-void open_tty(char *tty, struct termios *tp, int local)
+static void open_tty(char *tty, struct termios *tp, int __attribute__((__unused__)) local)
{
/* Get rid of the present outputs. */
close(STDOUT_FILENO);
/* Sanity checks. */
if (chdir("/dev"))
- error(_("/dev: chdir() failed: %m"));
+ log_err(_("/dev: chdir() failed: %m"));
if (stat(tty, &st) < 0)
- error("/dev/%s: %m", tty);
+ log_err("/dev/%s: %m", tty);
if ((st.st_mode & S_IFMT) != S_IFCHR)
- error(_("/dev/%s: not a character device"), tty);
+ log_err(_("/dev/%s: not a character device"), tty);
/* Open the tty as standard input. */
close(STDIN_FILENO);
debug("open(2)\n");
if (open(tty, O_RDWR | O_NONBLOCK, 0) != 0)
- error(_("/dev/%s: cannot open as standard input: %m"),
+ log_err(_("/dev/%s: cannot open as standard input: %m"),
tty);
} else {
/*
* sure it is open for read/write.
*/
if ((fcntl(STDIN_FILENO, F_GETFL, 0) & O_RDWR) != O_RDWR)
- error(_("%s: not open for read/write"), tty);
+ log_err(_("%s: not open for read/write"), tty);
}
/* Set up standard output and standard error file descriptors. */
/* set up stdout and stderr */
if (dup(STDIN_FILENO) != 1 || dup(STDIN_FILENO) != 2)
- error(_("%s: dup problem: %m"), tty);
+ log_err(_("%s: dup problem: %m"), tty);
/*
* The following ioctl will fail if stdin is not a tty, but also when
* "zsadtrlow" to a larger value; 5 seconds seems to be a good value.
* http://www.sunmanagers.org/archives/1993/0574.html
*/
+ memset(tp, 0, sizeof(struct termios));
if (tcgetattr(STDIN_FILENO, tp) < 0)
- error("%s: tcgetattr: %m", tty);
+ log_err("%s: tcgetattr: %m", tty);
/*
* Linux login(1) will change tty permissions. Use root owner and group
}
/* Initialize termios settings. */
-char gbuf[1024];
-char area[1024];
-
-void termio_init(struct options *op, struct termios *tp)
+static void termio_init(struct options *op, struct termios *tp)
{
speed_t ispeed, ospeed;
}
/* Extract baud rate from modem status message. */
-void auto_baud(struct termios *tp)
+static void auto_baud(struct termios *tp)
{
- int speed;
+ speed_t speed;
int vmin;
unsigned iflag;
char buf[BUFSIZ];
}
/* Show login prompt, optionally preceded by /etc/issue contents. */
-void do_prompt(struct options *op, struct termios *tp)
+static void do_prompt(struct options *op, struct termios *tp)
{
#ifdef ISSUE
FILE *fd;
int oflag;
- int c;
+ int c, i;
struct utsname uts;
uname(&uts);
printf("%s", op->tty);
break;
case 'b':
- for (int i = 0; speedtab[i].speed; i++)
+ for (i = 0; speedtab[i].speed; i++)
if (speedtab[i].code == cfgetispeed(tp))
printf("%ld", speedtab[i].speed);
break;
}
/* Select next baud rate. */
-void next_speed(struct options *op, struct termios *tp)
+static void next_speed(struct options *op, struct termios *tp)
{
static int baud_index = -1;
}
/* Get user name, establish parity, speed, erase, kill & eol. */
-char *get_logname(struct options *op, struct termios *tp, struct chardata *cp)
+static char *get_logname(struct options *op, struct termios *tp, struct chardata *cp)
{
static char logname[BUFSIZ];
char *bp;
if (read(STDIN_FILENO, &c, 1) < 1) {
if (errno == EINTR || errno == EIO)
exit(EXIT_SUCCESS);
- error(_("%s: read: %m"), op->tty);
+ log_err(_("%s: read: %m"), op->tty);
}
/* Do BREAK handling elsewhere. */
if ((c == 0) && op->numspeed > 1)
return EXIT_SUCCESS;
/* Do parity bit handling. */
- if (op->eightbits) {
+ if (op->flags & F_EIGHTBITS) {
ascval = c;
} else if (c != (ascval = (c & 0177))) {
/* Set "parity" bit on. */
default:
if (!isascii(ascval) || !isprint(ascval)) {
/* Ignore garbage characters. */ ;
- } else if (bp - logname >= sizeof(logname) - 1) {
- error(_("%s: input overrun"), op->tty);
+ } else if ((size_t)(bp - logname) >= sizeof(logname) - 1) {
+ log_err(_("%s: input overrun"), op->tty);
} else {
/* Echo the character... */
ignore_result(write
}
/* Set the final tty mode bits. */
-void termio_final(struct options *op, struct termios *tp, struct chardata *cp)
+static void termio_final(struct options *op, struct termios *tp, struct chardata *cp)
{
/* General terminal-independent stuff. */
/* Finally, make the new settings effective. */
if (tcsetattr(STDIN_FILENO, TCSANOW, tp) < 0)
- error("%s: tcsetattr: TCSANOW: %m", op->tty);
+ log_err("%s: tcsetattr: TCSANOW: %m", op->tty);
}
/*
* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=52940
* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=156242
*/
-int caps_lock(char *s)
+static int caps_lock(char *s)
{
int capslock;
}
/* Convert speed string to speed code; return 0 on failure. */
-int bcode(s)
-char *s;
+static speed_t bcode(char *s)
{
struct Speedtab *sp;
long speed = atol(s);
return 0;
}
-void __attribute__ ((__noreturn__)) usage(FILE * out)
+static void __attribute__ ((__noreturn__)) usage(FILE * out)
{
fprintf(out, _("\nUsage:\n"
" %1$s [options] line baud_rate,... [termtype]\n"
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
-/* Report errors to console or syslog; only understands %s and %m. */
+/*
+ * Helper function reports errors to console or syslog.
+ * Will be used by log_err() and log_warn() therefore
+ * it takes a format as well as va_list.
+ */
#define str2cpy(b,s1,s2) strcat(strcpy(b,s1),s2)
-void error(const char *fmt, ...)
+static void dolog(int priority, const char *fmt, va_list ap)
{
- va_list ap;
#ifndef USE_SYSLOG
int fd;
#endif
str2cpy(buf, program_invocation_short_name, ": ");
bp = buf + strlen(buf);
#endif /* USE_SYSLOG */
-
- /*
- * %s expansion is done by hand. On a System V Release 2 system without
- * shared libraries and without syslog(3), linking with the the stdio
- * library used to make the program three times as big...
- *
- * %m expansion is done here as well. Too bad syslog(3) does not have a
- * vsprintf() like interface.
- */
- va_start(ap, fmt);
- while (*fmt && bp < &buf[BUFSIZ - 1]) {
- if (strncmp(fmt, "%s", 2) == 0) {
- xstrncpy(bp, va_arg(ap, char *), &buf[BUFSIZ - 1] - bp);
- bp += strlen(bp);
- fmt += 2;
- } else if (strncmp(fmt, "%m", 2) == 0) {
- xstrncpy(bp, strerror(errno), &buf[BUFSIZ - 1] - bp);
- bp += strlen(bp);
- fmt += 2;
- } else {
- *bp++ = *fmt++;
- }
- }
- *bp = 0;
- va_end(ap);
+ vsnprintf (bp, sizeof(buf)-strlen(buf), fmt, ap);
/*
* Write the diagnostic directly to /dev/console if we do not use the
*/
#ifdef USE_SYSLOG
openlog(program_invocation_short_name, LOG_PID, LOG_AUTHPRIV);
- syslog(LOG_ERR, "%s", buf);
+ syslog(priority, "%s", buf);
closelog();
#else
/* Terminate with CR-LF since the console mode is unknown. */
close(fd);
}
#endif /* USE_SYSLOG */
+}
+
+static void log_err(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ dolog(LOG_ERR, fmt, ap);
+ va_end(ap);
+
/* Be kind to init(8). */
sleep(10);
exit(EXIT_FAILURE);
}
+
+static void log_warn(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ dolog(LOG_WARNING, fmt, ap);
+ va_end(ap);
+}