From 4cd0616eedceb71683cb87759c1f36069ad2f73d Mon Sep 17 00:00:00 2001 From: brian Date: Sat, 28 Jun 1997 01:04:54 +0000 Subject: Allow command line control of ppp through both TCP and AF_LOCAL sockets. --- usr.sbin/pppctl/Makefile | 8 ++ usr.sbin/pppctl/pppctl.8 | 76 +++++++++++++ usr.sbin/pppctl/pppctl.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 357 insertions(+) create mode 100644 usr.sbin/pppctl/Makefile create mode 100644 usr.sbin/pppctl/pppctl.8 create mode 100644 usr.sbin/pppctl/pppctl.c (limited to 'usr.sbin/pppctl') diff --git a/usr.sbin/pppctl/Makefile b/usr.sbin/pppctl/Makefile new file mode 100644 index 0000000..fca11dd --- /dev/null +++ b/usr.sbin/pppctl/Makefile @@ -0,0 +1,8 @@ +# $Id:$ + +PROG= pppctl +SRCS= pppctl.c +CFLAGS+=-Wall +MAN8= pppctl.8 + +.include diff --git a/usr.sbin/pppctl/pppctl.8 b/usr.sbin/pppctl/pppctl.8 new file mode 100644 index 0000000..8a3afe7 --- /dev/null +++ b/usr.sbin/pppctl/pppctl.8 @@ -0,0 +1,76 @@ +.\" $Id:$ +.Dd 26 June 1997 +.Os FreeBSD +.Dt PPPCTL 8 +.Sh NAME +.Nm pppctl +.Nd +PPP control program +.Sh SYNOPSIS +.Nm +.Op Fl v +.Op Fl t Ar n +.Op Fl p Ar passwd +.Ar Port | LocalSocket +.Ar command +.Op Ar ;command +.Ar ... +.Sh DESCRIPTION +This program provides command line control of the +.Nm ppp +daemon. Its primary use is to facilitate simple scripts that +control a running daemon. + +.Nm Pppctl +expects at least two arguments. The first is interpreted as the +socket on which the +.Nm ppp +daemon is listening. If the socket contains a leading '/', it +is taken as an AF_LOCAL socket. If it consists entirely of numbers, +it is interpreted as a TCP port number on localhost. If it contains +any characters, the first of which is not a '/' character, it is +interpreted as an entry of type "tcp" from +.Pa /etc/services . +All remaining arguments are concatenated to form the command(s) that +will be sent to the +.Nm ppp +daemon. If any semi-colon characters are found, they are treated +as command delimiters, allowing more than one command in a given +"session". For example; + + pppctl 3000 set timeout 300\\; show timeout + +Don't forget to escape or quote the ';' as it is a special character +for most shells. + +The following command line options are available: +.Bl -tag -width Ds +.It Fl v +Display all data sent to and received from the +.Nm ppp +daemon. Normally, +.Nm pppctl +displays only non-prompt lines received. +.It Fl t Ar n +Use a timeout of +.Ar n +instead of the default 2 seconds. This may be required if you +wish to control a daemon over a slow (or even a dialup) link. +.It Fl p Ar passwd +Specify the password required by the +.Nm ppp +daemon. If this switch is not used, +.Nm +will prompt for a password once it has successfully connected to +.Nm ppp +(assuming, of course, that one is required). +.El + +.Sh SEE ALSO +.Xr ppp 8 , +.Xr services 5 + +.Sh HISTORY +The +.Nm +command first appeared in FreeBSD 2.2.5. diff --git a/usr.sbin/pppctl/pppctl.c b/usr.sbin/pppctl/pppctl.c new file mode 100644 index 0000000..e63d736 --- /dev/null +++ b/usr.sbin/pppctl/pppctl.c @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LINELEN 2048 +static char Buffer[LINELEN], Command[LINELEN]; + +static int Usage() +{ + fprintf(stderr, "Usage: pppctl [-v] [ -t n ] [ -p passwd ] Port|LocalSock command[;command]...\n"); + fprintf(stderr, " -v tells pppctl to output all conversation\n"); + fprintf(stderr, " -t n specifies a timeout of n seconds (default 2)\n"); + fprintf(stderr, " -p passwd specifies your password\n"); + return 1; +} + +static int TimedOut = 0; +void Timeout(int Sig) +{ + TimedOut = 1; +} + +#define REC_PASSWD (1) +#define REC_SHOW (2) +#define REC_VERBOSE (4) + +static char *passwd; + +int Receive(int fd, unsigned TimeoutVal, int display) +{ + int Result; + struct sigaction act, oact; + int len; + char *last; + + TimedOut = 0; + if (TimeoutVal) { + act.sa_handler = Timeout; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGALRM, &act, &oact); + alarm(TimeoutVal); + } + + len = 0; + while (Result = read(fd, Buffer+len, sizeof(Buffer)-len-1), Result != -1) { + len += Result; + Buffer[len] = '\0'; + if (TimedOut) { + if (display & REC_VERBOSE) + write(1,Buffer,len); + Result = -1; + break; + } else if (len > 2 && !strcmp(Buffer+len-2, "> ")) { + if (display & (REC_SHOW|REC_VERBOSE)) { + if (display & REC_VERBOSE) + last = Buffer+len-1; + else + last = rindex(Buffer, '\n'); + if (last) { + *++last = '\0'; + write(1, Buffer, last-Buffer); + } + } + for (last = Buffer+len-2; last > Buffer && *last != ' '; last--) + ; + if (last > Buffer+3 && !strncmp(last-3, " on", 3)) { + /* a password is required ! */ + if (display & REC_PASSWD) { + if (TimeoutVal) { + alarm(0); + sigaction(SIGALRM, &oact, 0); + } + /* password time */ + if (!passwd) + passwd = getpass("Password: "); + sprintf(Buffer, "passwd %s\n", passwd); + bzero(passwd, strlen(passwd)); + if (display & REC_VERBOSE) + write(1, Buffer, strlen(Buffer)); + write(fd, Buffer, strlen(Buffer)); + bzero(Buffer, strlen(Buffer)); + return Receive(fd, TimeoutVal, display & ~REC_PASSWD); + } + Result = 1; + } else + Result = 0; + break; + } + } + + if (TimedOut) + Result = -1; + + if (TimeoutVal) { + alarm(0); + sigaction(SIGALRM, &oact, 0); + } + return Result; +} + +int +main(int argc, char **argv) +{ + struct servent *s; + struct hostent *h; + struct sockaddr *sock; + struct sockaddr_in ifsin; + struct sockaddr_un ifsun; + int socksz, arg, fd, len, verbose; + unsigned TimeoutVal; + char *DoneWord = "x", *next, *start; + struct sigaction act, oact; + + verbose = 0; + TimeoutVal = 2; + + for (arg = 1; arg < argc; arg++) + if (*argv[arg] == '-') { + for (start = argv[arg] + 1; *start; start++) + switch (*start) { + case 't': + TimeoutVal = (unsigned)atoi + (start[1] ? start + 1 : argv[++arg]); + start = DoneWord; + break; + + case 'v': + verbose = REC_VERBOSE; + break; + + case 'p': + passwd = (start[1] ? start + 1 : argv[++arg]); + start = DoneWord; + break; + + default: + return Usage(); + } + } + else + break; + + + if (argc < arg + 2) + return Usage(); + + if (*argv[arg] == '/') { + sock = (struct sockaddr *)&ifsun; + socksz = sizeof ifsun; + + ifsun.sun_len = strlen(argv[arg]); + if (ifsun.sun_len > sizeof ifsun.sun_path - 1) { + fprintf(stderr, "%s: Path too long\n", argv[arg]); + return 1; + } + ifsun.sun_family = AF_LOCAL; + strcpy(ifsun.sun_path, argv[arg]); + + if (fd = socket(AF_LOCAL, SOCK_STREAM, 0), fd < 0) { + fprintf(stderr, "Cannot create local domain socket\n"); + return 2; + } + } else { + sock = (struct sockaddr *)&ifsin; + socksz = sizeof ifsin; + + if ((h = gethostbyname("localhost")) == 0) { + fprintf(stderr, "Cannot resolve localhost\n"); + return 1; + } + + if (strspn(argv[arg], "0123456789") == strlen(argv[arg])) + ifsin.sin_port = htons(atoi(argv[arg])); + else if (s = getservbyname(argv[arg], "tcp"), !s) { + fprintf(stderr, "%s isn't a valid port or service!\n", argv[arg]); + return Usage(); + } + else + ifsin.sin_port = s->s_port; + + ifsin.sin_len = sizeof(ifsin); + ifsin.sin_family = AF_INET; + ifsin.sin_addr.s_addr = *(u_long *)h->h_addr_list[0]; + + if (fd = socket(AF_INET, SOCK_STREAM, 0), fd < 0) { + fprintf(stderr, "Cannot create internet socket\n"); + return 2; + } + } + + TimedOut = 0; + if (TimeoutVal) { + act.sa_handler = Timeout; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGALRM, &act, &oact); + alarm(TimeoutVal); + } + + if (connect(fd, sock, socksz) < 0) { + if (TimeoutVal) { + alarm(0); + sigaction(SIGALRM, &oact, 0); + } + if (TimedOut) + fputs("Timeout: ", stderr); + fprintf(stderr, "Cannot connect to socket %s\n", argv[arg]); + close(fd); + return 3; + } + + if (TimeoutVal) { + alarm(0); + sigaction(SIGALRM, &oact, 0); + } + + len = 0; + Command[sizeof(Command)-1] = '\0'; + for (arg++; arg < argc; arg++) { + if (len && len < sizeof(Command)-1) + strcpy(Command+len++, " "); + strncpy(Command+len, argv[arg], sizeof(Command)-len-1); + len += strlen(Command+len); + } + + switch (Receive(fd, TimeoutVal, verbose | REC_PASSWD)) + { + case 1: + fprintf(stderr, "Password incorrect\n"); + break; + + case 0: + start = Command; + do { + next = index(start, ';'); + while (*start == ' ' || *start == '\t') + start++; + if (next) + *next = '\0'; + strcpy(Buffer, start); + Buffer[sizeof(Buffer)-2] = '\0'; + strcat(Buffer, "\n"); + if (verbose) + write(1, Buffer, strlen(Buffer)); + write(fd, Buffer, strlen(Buffer)); + if (Receive(fd, TimeoutVal, verbose | REC_SHOW) != 0) { + fprintf(stderr, "No reply from ppp\n"); + break; + } + if (next) + start = ++next; + } while (next && *next); + if (verbose) + puts(""); + break; + + default: + fprintf(stderr, "ppp is not responding\n"); + break; + } + + close(fd); + + return 0; +} -- cgit v1.1