mirror of
https://github.com/ecki/net-tools.git
synced 2025-04-22 16:06:00 +00:00
Compilers don't really care about these anymore, and certainly isn't needed in these programs that are not performance sensitive.
767 lines
17 KiB
C
767 lines
17 KiB
C
/*
|
|
* slattach A program for handling dialup IP connecions.
|
|
* This program forces a TTY line to go into a special
|
|
* terminal line discipline, so that it can be used for
|
|
* network traffic instead of the regular terminal I/O.
|
|
*
|
|
* Usage: slattach [-ehlmnqv] [ -k keepalive ] [ -o outfill ]
|
|
* [-c cmd] [-s speed] [-p protocol] tty | -
|
|
*
|
|
* Version: @(#)slattach.c 1.20 1999-05-29
|
|
*
|
|
* Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
|
|
* Copyright 1988-1993 MicroWalt Corporation
|
|
*
|
|
* Modified:
|
|
* Alan Cox, <A.Cox@swansea.ac.uk> , July 16 1994
|
|
* Miquel van Smoorenburg, <miquels@drinkel.ow.org>, October 1994
|
|
* George Shearer, <gshearer@one.net>, January 3, 1995
|
|
* Yossi Gottlieb, <yogo@math.tau.ac.il>, February 11, 1995
|
|
* Peter Tobias, <tobias@et-inf.fho-emden.de>, July 30 1995
|
|
* Bernd Eckenfels <net-tools@lina.inka.de>, May 29, 1999
|
|
* added some more printf's for debug and NOBLOCK to open
|
|
* this should be enough to support 2.2 ttyS-style locks
|
|
*
|
|
* This program is free software; you can redistribute it
|
|
* and/or modify it under the terms of the GNU General
|
|
* Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at
|
|
* your option) any later version.
|
|
*/
|
|
#include <sys/param.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/stat.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <limits.h>
|
|
#include <pwd.h>
|
|
#include <signal.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
#include <getopt.h>
|
|
#include <linux/if_slip.h>
|
|
|
|
#include "pathnames.h"
|
|
#include "net-support.h"
|
|
#include "version.h"
|
|
#include "config.h"
|
|
#include "intl.h"
|
|
#include "util.h"
|
|
|
|
#ifndef _PATH_LOCKD
|
|
#define _PATH_LOCKD "/var/lock" /* lock files */
|
|
#endif
|
|
#ifndef _UID_UUCP
|
|
#define _UID_UUCP "uucp" /* owns locks */
|
|
#endif
|
|
#ifndef _PATH_DEVPTMX
|
|
#define _PATH_DEVPTMX "/dev/ptmx" /* pseudo-terminal master */
|
|
#endif
|
|
|
|
|
|
#define DEF_PROTO "cslip"
|
|
|
|
|
|
static char *Release = RELEASE, *Signature = "Fred N. van Kempen et al.";
|
|
|
|
|
|
struct {
|
|
const char *speed;
|
|
int code;
|
|
} tty_speeds[] = { /* table of usable baud rates */
|
|
{ "50", B50 }, { "75", B75 },
|
|
{ "110", B110 }, { "300", B300 },
|
|
{ "600", B600 }, { "1200", B1200 },
|
|
{ "2400", B2400 }, { "4800", B4800 },
|
|
{ "9600", B9600 },
|
|
#ifdef B14400
|
|
{ "14400", B14400 },
|
|
#endif
|
|
#ifdef B19200
|
|
{ "19200", B19200 },
|
|
#endif
|
|
#ifdef B38400
|
|
{ "38400", B38400 },
|
|
#endif
|
|
#ifdef B57600
|
|
{ "57600", B57600 },
|
|
#endif
|
|
#ifdef B115200
|
|
{ "115200", B115200 },
|
|
#endif
|
|
{ NULL, 0 }
|
|
};
|
|
struct termios tty_saved, /* saved TTY device state */
|
|
tty_current; /* current TTY device state */
|
|
int tty_sdisc, /* saved TTY line discipline */
|
|
tty_ldisc, /* current TTY line discipline */
|
|
tty_fd = -1; /* TTY file descriptor */
|
|
char * path_pts = NULL; /* slave pseudo-terminal device */
|
|
int opt_c = 0; /* "command" to run at exit */
|
|
int opt_e = 0; /* "activate only" flag */
|
|
int opt_h = 0; /* "hangup" on carrier loss */
|
|
#ifdef SIOCSKEEPALIVE
|
|
int opt_k = 0; /* "keepalive" value */
|
|
#endif
|
|
int opt_l = 0; /* "lock it" flag */
|
|
int opt_L = 0; /* 3-wire mode flag */
|
|
int opt_m = 0; /* "set RAW mode" flag */
|
|
int opt_n = 0; /* "set No Mesg" flag */
|
|
#ifdef SIOCSOUTFILL
|
|
int opt_o = 0; /* "outfill" value */
|
|
#endif
|
|
int opt_q = 0; /* "quiet" flag */
|
|
int opt_d = 0; /* debug flag */
|
|
int opt_v = 0; /* Verbose flag */
|
|
|
|
/* Disable any messages to the input channel of this process. */
|
|
static int
|
|
tty_nomesg(int fd)
|
|
{
|
|
if (opt_n == 0) return(0);
|
|
return(fchmod(fd, 0600));
|
|
}
|
|
|
|
/* Check for an existing lock file on our device */
|
|
static int
|
|
tty_already_locked(char *nam)
|
|
{
|
|
int i = 0, pid = 0;
|
|
FILE *fd = (FILE *)0;
|
|
|
|
/* Does the lock file on our device exist? */
|
|
if ((fd = fopen(nam, "r")) == (FILE *)0)
|
|
return(0); /* No, return perm to continue */
|
|
|
|
/* Yes, the lock is there. Now let's make sure */
|
|
/* at least there's no active process that owns */
|
|
/* that lock. */
|
|
i = fscanf(fd, "%d", &pid);
|
|
(void) fclose(fd);
|
|
|
|
if (i != 1) /* Lock file format's wrong! Kill't */
|
|
return(0);
|
|
|
|
/* We got the pid, check if the process's alive */
|
|
if (kill(pid, 0) == 0) /* it found process */
|
|
return(1); /* Yup, it's running... */
|
|
|
|
/* Dead, we can proceed locking this device... */
|
|
return(0);
|
|
}
|
|
|
|
/* Lock or unlock a terminal line. */
|
|
static int
|
|
tty_lock(char *path, int mode)
|
|
{
|
|
static char saved_path[PATH_MAX];
|
|
static int saved_lock = 0;
|
|
struct passwd *pw;
|
|
int fd;
|
|
char apid[16];
|
|
|
|
/* We do not lock standard input. */
|
|
if ((opt_l == 0) || ((path == NULL) && (saved_lock == 0))) return(0);
|
|
|
|
if (mode == 1) { /* lock */
|
|
sprintf(saved_path, "%s/LCK..%s", _PATH_LOCKD, path);
|
|
if (tty_already_locked(saved_path)) {
|
|
fprintf(stderr, _("slattach: /dev/%s already locked!\n"), path);
|
|
return(-1);
|
|
}
|
|
if ((fd = creat(saved_path, 0644)) < 0) {
|
|
if (errno != EEXIST)
|
|
if (opt_q == 0) fprintf(stderr,
|
|
_("slattach: tty_lock: (%s): %s\n"),
|
|
saved_path, strerror(errno));
|
|
return(-1);
|
|
}
|
|
sprintf(apid, "%10d\n", getpid());
|
|
if (write(fd, apid, strlen(apid)) != strlen(apid)) {
|
|
fprintf(stderr, _("slattach: cannot write PID file\n"));
|
|
close(fd);
|
|
unlink(saved_path);
|
|
return(-1);
|
|
}
|
|
|
|
/* Make sure UUCP owns the lockfile. Required by some packages. */
|
|
if ((pw = getpwnam(_UID_UUCP)) == NULL) {
|
|
if (opt_q == 0) fprintf(stderr, _("slattach: tty_lock: UUCP user %s unknown!\n"),
|
|
_UID_UUCP);
|
|
(void) close(fd);
|
|
return(0); /* keep the lock anyway */
|
|
}
|
|
if (fchown(fd, pw->pw_uid, pw->pw_gid))
|
|
/* keep the lock anyway */;
|
|
|
|
(void) close(fd);
|
|
|
|
saved_lock = 1;
|
|
} else { /* unlock */
|
|
if (saved_lock != 1) return(0);
|
|
if (unlink(saved_path) < 0) {
|
|
if (opt_q == 0) fprintf(stderr,
|
|
"slattach: tty_unlock: (%s): %s\n", saved_path,
|
|
strerror(errno));
|
|
return(-1);
|
|
}
|
|
saved_lock = 0;
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Find a serial speed code in the table. */
|
|
static int
|
|
tty_find_speed(const char *speed)
|
|
{
|
|
int i;
|
|
|
|
i = 0;
|
|
while (tty_speeds[i].speed != NULL) {
|
|
if (!strcmp(tty_speeds[i].speed, speed)) return(tty_speeds[i].code);
|
|
i++;
|
|
}
|
|
return(-EINVAL);
|
|
}
|
|
|
|
|
|
/* Set the number of stop bits. */
|
|
static int
|
|
tty_set_stopbits(struct termios *tty, char *stopbits)
|
|
{
|
|
if (opt_d) printf("slattach: tty_set_stopbits: %c\n", *stopbits);
|
|
switch(*stopbits) {
|
|
case '1':
|
|
tty->c_cflag &= ~CSTOPB;
|
|
break;
|
|
|
|
case '2':
|
|
tty->c_cflag |= CSTOPB;
|
|
break;
|
|
|
|
default:
|
|
return(-EINVAL);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Set the number of data bits. */
|
|
static int
|
|
tty_set_databits(struct termios *tty, char *databits)
|
|
{
|
|
if (opt_d) printf("slattach: tty_set_databits: %c\n", *databits);
|
|
tty->c_cflag &= ~CSIZE;
|
|
switch(*databits) {
|
|
case '5':
|
|
tty->c_cflag |= CS5;
|
|
break;
|
|
|
|
case '6':
|
|
tty->c_cflag |= CS6;
|
|
break;
|
|
|
|
case '7':
|
|
tty->c_cflag |= CS7;
|
|
break;
|
|
|
|
case '8':
|
|
tty->c_cflag |= CS8;
|
|
break;
|
|
|
|
default:
|
|
return(-EINVAL);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Set the type of parity encoding. */
|
|
static int
|
|
tty_set_parity(struct termios *tty, char *parity)
|
|
{
|
|
if (opt_d) printf("slattach: tty_set_parity: %c\n", *parity);
|
|
switch(toupper(*parity)) {
|
|
case 'N':
|
|
tty->c_cflag &= ~(PARENB | PARODD);
|
|
break;
|
|
|
|
case 'O':
|
|
tty->c_cflag &= ~(PARENB | PARODD);
|
|
tty->c_cflag |= (PARENB | PARODD);
|
|
break;
|
|
|
|
case 'E':
|
|
tty->c_cflag &= ~(PARENB | PARODD);
|
|
tty->c_cflag |= (PARENB);
|
|
break;
|
|
|
|
default:
|
|
return(-EINVAL);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Set the line speed of a terminal line. */
|
|
static int
|
|
tty_set_speed(struct termios *tty, const char *speed)
|
|
{
|
|
int code;
|
|
|
|
if (opt_d) printf("slattach: tty_set_speed: %s\n", speed);
|
|
if ((code = tty_find_speed(speed)) < 0) return(code);
|
|
tty->c_cflag &= ~CBAUD;
|
|
tty->c_cflag |= code;
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Put a terminal line in a transparent state. */
|
|
static int
|
|
tty_set_raw(struct termios *tty)
|
|
{
|
|
int i;
|
|
int speed;
|
|
|
|
for(i = 0; i < NCCS; i++)
|
|
tty->c_cc[i] = '\0'; /* no spec chr */
|
|
tty->c_cc[VMIN] = 1;
|
|
tty->c_cc[VTIME] = 0;
|
|
tty->c_iflag = (IGNBRK | IGNPAR); /* input flags */
|
|
tty->c_oflag = (0); /* output flags */
|
|
tty->c_lflag = (0); /* local flags */
|
|
speed = (tty->c_cflag & CBAUD); /* save current speed */
|
|
tty->c_cflag = (HUPCL | CREAD); /* UART flags */
|
|
if (opt_L)
|
|
tty->c_cflag |= CLOCAL;
|
|
else
|
|
tty->c_cflag |= CRTSCTS;
|
|
tty->c_cflag |= speed; /* restore speed */
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Fetch the state of a terminal. */
|
|
static int
|
|
tty_get_state(struct termios *tty)
|
|
{
|
|
if (ioctl(tty_fd, TCGETS, tty) < 0) {
|
|
if (opt_q == 0) fprintf(stderr,
|
|
"slattach: tty_get_state: %s\n", strerror(errno));
|
|
return(-errno);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Set the state of a terminal. */
|
|
static int
|
|
tty_set_state(struct termios *tty)
|
|
{
|
|
if (ioctl(tty_fd, TCSETS, tty) < 0) {
|
|
if (opt_q == 0) fprintf(stderr,
|
|
"slattach: tty_set_state: %s\n", strerror(errno));
|
|
return(-errno);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Get the line discipline of a terminal line. */
|
|
static int
|
|
tty_get_disc(int *disc)
|
|
{
|
|
if (ioctl(tty_fd, TIOCGETD, disc) < 0) {
|
|
if (opt_q == 0) fprintf(stderr,
|
|
"slattach: tty_get_disc: %s\n", strerror(errno));
|
|
return(-errno);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Set the line discipline of a terminal line. */
|
|
static int
|
|
tty_set_disc(int disc)
|
|
{
|
|
if (disc == -1) disc = tty_sdisc;
|
|
|
|
if (ioctl(tty_fd, TIOCSETD, &disc) < 0) {
|
|
if (opt_q == 0) fprintf(stderr,
|
|
"slattach: tty_set_disc(%d, %d): %s\n", tty_fd,
|
|
disc, strerror(errno));
|
|
return(-errno);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Fetch the name of the network interface attached to this terminal. */
|
|
static int
|
|
tty_get_name(char *name)
|
|
{
|
|
if (ioctl(tty_fd, SIOCGIFNAME, name) < 0) {
|
|
if (opt_q == 0)
|
|
perror("tty_get_name");
|
|
return(-errno);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Hangup the line. */
|
|
static int
|
|
tty_hangup(void)
|
|
{
|
|
struct termios tty;
|
|
|
|
tty = tty_current;
|
|
(void) tty_set_speed(&tty, "0");
|
|
if (tty_set_state(&tty) < 0) {
|
|
if (opt_q == 0) fprintf(stderr, _("slattach: tty_hangup(DROP): %s\n"), strerror(errno));
|
|
return(-errno);
|
|
}
|
|
|
|
(void) sleep(1);
|
|
|
|
if (tty_set_state(&tty_current) < 0) {
|
|
if (opt_q == 0) fprintf(stderr, _("slattach: tty_hangup(RAISE): %s\n"), strerror(errno));
|
|
return(-errno);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Close down a terminal line. */
|
|
static int
|
|
tty_close(void)
|
|
{
|
|
(void) tty_set_disc(tty_sdisc);
|
|
(void) tty_hangup();
|
|
(void) tty_lock(NULL, 0);
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Open and initialize a terminal line. */
|
|
static int
|
|
tty_open(char *name, const char *speed)
|
|
{
|
|
char pathbuf[PATH_MAX];
|
|
char *path_open, *path_lock;
|
|
int fd;
|
|
|
|
/* Try opening the TTY device. */
|
|
if (name != NULL) {
|
|
if (name[0] != '/') {
|
|
if (strlen(name + 6) > sizeof(pathbuf)) {
|
|
if (opt_q == 0) fprintf(stderr,
|
|
_("slattach: tty name too long\n"));
|
|
return (-1);
|
|
}
|
|
sprintf(pathbuf, "/dev/%s", name);
|
|
path_open = pathbuf;
|
|
path_lock = name;
|
|
} else if (!strncmp(name, "/dev/", 5)) {
|
|
path_open = name;
|
|
path_lock = name + 5;
|
|
} else {
|
|
path_open = name;
|
|
path_lock = name;
|
|
}
|
|
if (opt_d) printf("slattach: tty_open: looking for lock\n");
|
|
if (tty_lock(path_lock, 1)) return(-1); /* can we lock the device? */
|
|
if (opt_d) printf("slattach: tty_open: trying to open %s\n", path_open);
|
|
if ((fd = open(path_open, O_RDWR|O_NDELAY)) < 0) {
|
|
if (opt_q == 0) fprintf(stderr,
|
|
"slattach: tty_open(%s, RW): %s\n",
|
|
path_open, strerror(errno));
|
|
return(-errno);
|
|
}
|
|
tty_fd = fd;
|
|
if (opt_d) printf("slattach: tty_open: %s (fd=%d)\n", path_open, fd);
|
|
if (!strcmp(path_open, _PATH_DEVPTMX)) {
|
|
if (opt_d) printf("slattach: tty_open: trying to grantpt and unlockpt\n");
|
|
if (grantpt(fd) < 0) {
|
|
if (opt_q == 0) fprintf(stderr,
|
|
"slattach: tty_open: grantpt: %s\n", strerror(errno));
|
|
return(-errno);
|
|
}
|
|
if (unlockpt(fd) < 0) {
|
|
if (opt_q == 0) fprintf(stderr,
|
|
"slattach: tty_open: unlockpt: %s\n", strerror(errno));
|
|
return(-errno);
|
|
}
|
|
path_pts = ptsname(fd);
|
|
if (path_pts == NULL) {
|
|
if (opt_q == 0) fprintf(stderr,
|
|
"slattach: tty_open: ptsname: %s\n", strerror(errno));
|
|
return(-errno);
|
|
}
|
|
if (opt_d) printf("slattach: tty_open: %s: slave pseudo-terminal is %s\n",
|
|
path_open, path_pts);
|
|
}
|
|
} else {
|
|
tty_fd = 0;
|
|
}
|
|
|
|
/* Fetch the current state of the terminal. */
|
|
if (tty_get_state(&tty_saved) < 0) {
|
|
if (opt_q == 0) fprintf(stderr, _("slattach: tty_open: cannot get current state!\n"));
|
|
return(-errno);
|
|
}
|
|
tty_current = tty_saved;
|
|
|
|
/* Fetch the current line discipline of this terminal. */
|
|
if (tty_get_disc(&tty_sdisc) < 0) {
|
|
if (opt_q == 0) fprintf(stderr, _("slattach: tty_open: cannot get current line disc!\n"));
|
|
return(-errno);
|
|
}
|
|
tty_ldisc = tty_sdisc;
|
|
|
|
/* Put this terminal line in a 8-bit transparent mode. */
|
|
if (opt_m == 0) {
|
|
if (tty_set_raw(&tty_current) < 0) {
|
|
if (opt_q == 0) fprintf(stderr, _("slattach: tty_open: cannot set RAW mode!\n"));
|
|
return(-errno);
|
|
}
|
|
|
|
/* Set the default speed if we need to. */
|
|
if (speed != NULL) {
|
|
if (tty_set_speed(&tty_current, speed) != 0) {
|
|
if (opt_q == 0) fprintf(stderr, _("slattach: tty_open: cannot set %s bps!\n"),
|
|
speed);
|
|
return(-errno);
|
|
}
|
|
}
|
|
|
|
/* Set up a completely 8-bit clean line. */
|
|
if (tty_set_databits(&tty_current, "8") ||
|
|
tty_set_stopbits(&tty_current, "1") ||
|
|
tty_set_parity(&tty_current, "N")) {
|
|
if (opt_q == 0) fprintf(stderr, _("slattach: tty_open: cannot set 8N1 mode!\n"));
|
|
return(-errno);
|
|
}
|
|
|
|
/* Set the new line mode. */
|
|
if ((fd = tty_set_state(&tty_current)) < 0) return(fd);
|
|
}
|
|
|
|
/* OK, line is open. Do we need to "silence" it? */
|
|
(void) tty_nomesg(tty_fd);
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Catch any signals. */
|
|
static void
|
|
sig_catch(int sig)
|
|
{
|
|
/* (void) signal(sig, sig_catch); */
|
|
tty_close();
|
|
exit(0);
|
|
}
|
|
|
|
|
|
static void
|
|
usage(int rc)
|
|
{
|
|
FILE *fp = rc ? stderr : stdout;
|
|
char *usage_msg = "Usage: slattach [-ehlLmnqv] "
|
|
#ifdef SIOCSKEEPALIVE
|
|
"[-k keepalive] "
|
|
#endif
|
|
#ifdef SIOCSOUTFILL
|
|
"[-o outfill] "
|
|
#endif
|
|
"[-c cmd] [-s speed] [-p protocol] tty | -\n"
|
|
" slattach -V | --version\n";
|
|
|
|
fputs(usage_msg, fp);
|
|
exit(rc);
|
|
}
|
|
|
|
|
|
static void
|
|
version(void)
|
|
{
|
|
printf("%s\n%s\n", Release, Signature);
|
|
exit(E_VERSION);
|
|
}
|
|
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
char path_buf[128] = "";
|
|
char *path_dev;
|
|
char buff[128];
|
|
const char *speed = NULL;
|
|
const char *proto = DEF_PROTO;
|
|
const char *extcmd = NULL;
|
|
int s;
|
|
static struct option longopts[] = {
|
|
{ "version", 0, NULL, 'V' },
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
|
|
path_dev = path_buf;
|
|
|
|
/* Scan command line for any arguments. */
|
|
opterr = 0;
|
|
while ((s = getopt_long(argc, argv, "c:ehlLmnp:qs:vdVk:o:", longopts, NULL)) != EOF) switch(s) {
|
|
case 'c':
|
|
extcmd = optarg;
|
|
break;
|
|
|
|
case 'e':
|
|
opt_e = 1 - opt_e;
|
|
break;
|
|
|
|
case 'h':
|
|
opt_h = 1 - opt_h;
|
|
break;
|
|
|
|
#ifdef SIOCSKEEPALIVE
|
|
case 'k':
|
|
opt_k = atoi(optarg);
|
|
break;
|
|
#endif
|
|
|
|
case 'L':
|
|
opt_L = 1 - opt_L;
|
|
break;
|
|
|
|
case 'l':
|
|
opt_l = 1 - opt_l;
|
|
break;
|
|
|
|
case 'm':
|
|
opt_m = 1 - opt_m;
|
|
break;
|
|
|
|
case 'n':
|
|
opt_n = 1 - opt_n;
|
|
break;
|
|
|
|
#ifdef SIOCSOUTFILL
|
|
case 'o':
|
|
opt_o = atoi(optarg);
|
|
break;
|
|
#endif
|
|
|
|
case 'p':
|
|
proto = optarg;
|
|
break;
|
|
|
|
case 'q':
|
|
opt_q = 1 - opt_q;
|
|
break;
|
|
|
|
case 's':
|
|
speed = optarg;
|
|
break;
|
|
|
|
case 'd':
|
|
opt_d = 1 - opt_d;
|
|
break;
|
|
|
|
case 'v':
|
|
opt_v = 1 - opt_v;
|
|
break;
|
|
|
|
case 'V':
|
|
version();
|
|
/*NOTREACHED*/
|
|
|
|
default:
|
|
usage(E_OPTERR);
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
if (setvbuf(stdout,0,_IOLBF,0)) {
|
|
if (opt_q == 0) fprintf(stderr, _("slattach: setvbuf(stdout,0,_IOLBF,0) : %s\n"),
|
|
strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
activate_init();
|
|
|
|
if (!strcmp(proto, "tty"))
|
|
opt_m++;
|
|
|
|
/* Is a terminal given? */
|
|
if (optind != (argc - 1)) usage(E_OPTERR);
|
|
safe_strncpy(path_buf, argv[optind], sizeof(path_buf));
|
|
if (!strcmp(path_buf, "-")) {
|
|
opt_e = 1;
|
|
path_dev = NULL;
|
|
if (tty_open(NULL, speed) < 0) { return(3); }
|
|
} else {
|
|
path_dev = path_buf;
|
|
if (tty_open(path_dev, speed) < 0) { return(3); }
|
|
}
|
|
|
|
/* Start the correct protocol. */
|
|
if (!strcmp(proto, "tty")) {
|
|
tty_sdisc = N_TTY;
|
|
tty_close();
|
|
return(0);
|
|
}
|
|
if (activate_ld(proto, tty_fd))
|
|
return(1);
|
|
if ((opt_v == 1) || (opt_d == 1)) {
|
|
if (tty_get_name(buff)) { return(3); }
|
|
printf(_("%s started"), proto);
|
|
if (path_dev != NULL) printf(_(" on %s"), path_dev);
|
|
if (path_pts != NULL) printf(_(" ptsname %s"), path_pts);
|
|
printf(_(" interface %s\n"), buff);
|
|
}
|
|
|
|
/* Configure keepalive and outfill. */
|
|
#ifdef SIOCSKEEPALIVE
|
|
if (opt_k && (ioctl(tty_fd, SIOCSKEEPALIVE, &opt_k) < 0))
|
|
fprintf(stderr, "slattach: ioctl(SIOCSKEEPALIVE): %s\n", strerror(errno));
|
|
#endif
|
|
#ifdef SIOCSOUTFILL
|
|
if (opt_o && (ioctl(tty_fd, SIOCSOUTFILL, &opt_o) < 0))
|
|
fprintf(stderr, "slattach: ioctl(SIOCSOUTFILL): %s\n", strerror(errno));
|
|
#endif
|
|
|
|
(void) signal(SIGHUP, sig_catch);
|
|
(void) signal(SIGINT, sig_catch);
|
|
(void) signal(SIGQUIT, sig_catch);
|
|
(void) signal(SIGTERM, sig_catch);
|
|
|
|
/* Wait until we get killed if hanging on a terminal. */
|
|
if (opt_e == 0) {
|
|
while(1) {
|
|
if(opt_h == 1) { /* hangup on carrier loss */
|
|
int n = 0;
|
|
|
|
ioctl(tty_fd, TIOCMGET, &n);
|
|
if(!(n & TIOCM_CAR))
|
|
break;
|
|
sleep(15);
|
|
}
|
|
else
|
|
sleep(60);
|
|
};
|
|
|
|
tty_close();
|
|
if(extcmd) /* external command on exit */
|
|
exit(system(extcmd));
|
|
}
|
|
exit(0);
|
|
}
|