pppctl.c revision 31006
189580Smsmith#include <sys/types.h>
289580Smsmith#include <sys/socket.h>
389580Smsmith#include <netinet/in.h>
489580Smsmith#include <arpa/inet.h>
589580Smsmith#include <sys/un.h>
689580Smsmith#include <netdb.h>
789580Smsmith#include <signal.h>
889580Smsmith#include <string.h>
989580Smsmith#include <stdio.h>
1089580Smsmith#include <unistd.h>
1189580Smsmith#include <stdlib.h>
1289580Smsmith
1389580Smsmith#define LINELEN 2048
1489580Smsmithstatic char Buffer[LINELEN], Command[LINELEN];
1589580Smsmith
1689580Smsmithstatic int Usage()
1789580Smsmith{
1889580Smsmith    fprintf(stderr, "Usage: pppctl [-v] [ -t n ] [ -p passwd ] Port|LocalSock [command[;command]...]\n");
1989580Smsmith    fprintf(stderr, "              -v tells pppctl to output all conversation\n");
2089580Smsmith    fprintf(stderr, "              -t n specifies a timeout of n seconds (default 2)\n");
2189580Smsmith    fprintf(stderr, "              -p passwd specifies your password\n");
2289580Smsmith    return 1;
2389580Smsmith}
2489580Smsmith
2589580Smsmithstatic int TimedOut = 0;
2689580Smsmithvoid Timeout(int Sig)
2789580Smsmith{
2889580Smsmith    TimedOut = 1;
2989580Smsmith}
3089580Smsmith
3189580Smsmith#define REC_PASSWD  (1)
3289580Smsmith#define REC_SHOW    (2)
3389580Smsmith#define REC_VERBOSE (4)
3489580Smsmith
3589580Smsmithstatic char *passwd;
3689580Smsmith
3789580Smsmithint Receive(int fd, unsigned TimeoutVal, int display)
3889580Smsmith{
3989580Smsmith    int Result;
4089580Smsmith    struct sigaction act, oact;
4189580Smsmith    int len;
4289580Smsmith    char *last;
4389580Smsmith
4495533Smike    TimedOut = 0;
4589580Smsmith    if (TimeoutVal) {
4689580Smsmith        act.sa_handler = Timeout;
4789580Smsmith        sigemptyset(&act.sa_mask);
4889580Smsmith        act.sa_flags = 0;
4989580Smsmith        sigaction(SIGALRM, &act, &oact);
5089580Smsmith        alarm(TimeoutVal);
5189580Smsmith    }
5289580Smsmith
5389580Smsmith    len = 0;
5489580Smsmith    while (Result = read(fd, Buffer+len, sizeof(Buffer)-len-1), Result != -1) {
5589580Smsmith        len += Result;
5689580Smsmith        Buffer[len] = '\0';
5789580Smsmith        if (TimedOut) {
5889580Smsmith            if (display & REC_VERBOSE)
5989580Smsmith                write(1,Buffer,len);
6089580Smsmith            Result = -1;
6189580Smsmith            break;
6289580Smsmith        } else if (len > 2 && !strcmp(Buffer+len-2, "> ")) {
6389580Smsmith            if (display & (REC_SHOW|REC_VERBOSE)) {
6489580Smsmith                if (display & REC_VERBOSE)
6589580Smsmith                    last = Buffer+len-1;
6689580Smsmith                else
6789580Smsmith                    last = rindex(Buffer, '\n');
6889580Smsmith                if (last) {
6989580Smsmith                    *++last = '\0';
7089580Smsmith                    write(1, Buffer, last-Buffer);
7189580Smsmith                }
7289580Smsmith            }
7389580Smsmith            for (last = Buffer+len-2; last > Buffer && *last != ' '; last--)
7489580Smsmith                ;
7589580Smsmith            if (last > Buffer+3 && !strncmp(last-3, " on", 3)) {
7689580Smsmith                 /* a password is required ! */
7789580Smsmith                 if (display & REC_PASSWD) {
7889580Smsmith                    if (TimeoutVal) {
7989580Smsmith                        alarm(0);
8089580Smsmith                        sigaction(SIGALRM, &oact, 0);
8189580Smsmith                    }
8289580Smsmith                    /* password time */
8389580Smsmith                    if (!passwd)
8489580Smsmith                        passwd = getpass("Password: ");
8589580Smsmith                    sprintf(Buffer, "passwd %s\n", passwd);
8689580Smsmith                    bzero(passwd, strlen(passwd));
8789580Smsmith                    if (display & REC_VERBOSE)
8889580Smsmith                        write(1, Buffer, strlen(Buffer));
8989580Smsmith                    write(fd, Buffer, strlen(Buffer));
9089580Smsmith                    bzero(Buffer, strlen(Buffer));
9189580Smsmith                    return Receive(fd, TimeoutVal, display & ~REC_PASSWD);
9289580Smsmith                }
9389580Smsmith                Result = 1;
9489580Smsmith            } else
9589580Smsmith                Result = 0;
9689580Smsmith            break;
9789580Smsmith        }
9889580Smsmith    }
9989580Smsmith
10089580Smsmith    if (TimedOut)
10189580Smsmith        Result = -1;
10289580Smsmith
10389580Smsmith    if (TimeoutVal) {
10489580Smsmith        alarm(0);
10589580Smsmith        sigaction(SIGALRM, &oact, 0);
10689580Smsmith    }
10789580Smsmith    return Result;
10889580Smsmith}
10989580Smsmith
11089580Smsmithint
11189580Smsmithmain(int argc, char **argv)
11289580Smsmith{
11389580Smsmith    struct servent *s;
11489580Smsmith    struct hostent *h;
11589580Smsmith    struct sockaddr *sock;
11689580Smsmith    struct sockaddr_in ifsin;
11789580Smsmith    struct sockaddr_un ifsun;
11889580Smsmith    int socksz, arg, fd, len, verbose;
11989580Smsmith    unsigned TimeoutVal;
12089580Smsmith    char *DoneWord = "x", *next, *start;
12189580Smsmith    struct sigaction act, oact;
12289580Smsmith
12389580Smsmith    verbose = 0;
12489580Smsmith    TimeoutVal = 2;
12589580Smsmith
12689580Smsmith    for (arg = 1; arg < argc; arg++)
12789580Smsmith        if (*argv[arg] == '-') {
12889580Smsmith            for (start = argv[arg] + 1; *start; start++)
12989580Smsmith                switch (*start) {
13089580Smsmith                    case 't':
13189580Smsmith                        TimeoutVal = (unsigned)atoi
13289580Smsmith                            (start[1] ? start + 1 : argv[++arg]);
13389580Smsmith                        start = DoneWord;
13489580Smsmith                        break;
13589580Smsmith
13689580Smsmith                    case 'v':
13789580Smsmith                        verbose = REC_VERBOSE;
13889580Smsmith                        break;
13989580Smsmith
14089580Smsmith                    case 'p':
14189580Smsmith                        passwd = (start[1] ? start + 1 : argv[++arg]);
14289580Smsmith                        start = DoneWord;
14389580Smsmith                        break;
14489580Smsmith
14589580Smsmith                    default:
14689580Smsmith                        return Usage();
14789580Smsmith                }
14889580Smsmith        }
14989580Smsmith        else
15089580Smsmith            break;
15189580Smsmith
15289580Smsmith
15389580Smsmith    if (argc < arg + 1)
15489580Smsmith        return Usage();
15589580Smsmith
15689580Smsmith    if (*argv[arg] == '/') {
15789580Smsmith        sock = (struct sockaddr *)&ifsun;
15889580Smsmith        socksz = sizeof ifsun;
15989580Smsmith
16089580Smsmith        ifsun.sun_len = strlen(argv[arg]);
16189580Smsmith        if (ifsun.sun_len > sizeof ifsun.sun_path - 1) {
16289580Smsmith            fprintf(stderr, "%s: Path too long\n", argv[arg]);
16389580Smsmith            return 1;
16489580Smsmith        }
16589580Smsmith        ifsun.sun_family = AF_LOCAL;
16689580Smsmith        strcpy(ifsun.sun_path, argv[arg]);
16789580Smsmith
16889580Smsmith        if (fd = socket(AF_LOCAL, SOCK_STREAM, 0), fd < 0) {
16989580Smsmith            fprintf(stderr, "Cannot create local domain socket\n");
17089580Smsmith            return 2;
17189580Smsmith        }
17289580Smsmith    } else {
17389580Smsmith        char *port, *host, *colon;
17489580Smsmith	int hlen;
17589580Smsmith
17689580Smsmith        colon = strchr(argv[arg], ':');
17789580Smsmith        if (colon) {
17889580Smsmith            port = colon + 1;
17989580Smsmith            *colon = '\0';
18089580Smsmith            host = argv[arg];
18189580Smsmith        } else {
18289580Smsmith            port = argv[arg];
18389580Smsmith            host = "127.0.0.1";
18489580Smsmith        }
18589580Smsmith        sock = (struct sockaddr *)&ifsin;
18689580Smsmith        socksz = sizeof ifsin;
18789580Smsmith        hlen = strlen(host);
18889580Smsmith
18989580Smsmith        if (strspn(host, "0123456789.") == hlen) {
19089580Smsmith            if (!inet_aton(host, (struct in_addr *)&ifsin.sin_addr.s_addr)) {
19189580Smsmith                fprintf(stderr, "Cannot translate %s\n", host);
19289580Smsmith                return 1;
19389580Smsmith            }
19489580Smsmith        } else if ((h = gethostbyname(host)) == 0) {
19589580Smsmith            fprintf(stderr, "Cannot resolve %s\n", host);
19689580Smsmith            return 1;
19789580Smsmith        }
19889580Smsmith        else
19989580Smsmith            ifsin.sin_addr.s_addr = *(u_long *)h->h_addr_list[0];
20089580Smsmith
20189580Smsmith        if (colon)
20289580Smsmith            *colon = ':';
20389580Smsmith
20489580Smsmith        if (strspn(port, "0123456789") == strlen(port))
20589580Smsmith            ifsin.sin_port = htons(atoi(port));
20689580Smsmith        else if (s = getservbyname(port, "tcp"), !s) {
20789580Smsmith            fprintf(stderr, "%s isn't a valid port or service!\n", port);
20889580Smsmith            return Usage();
20989580Smsmith        }
21089580Smsmith        else
21189580Smsmith            ifsin.sin_port = s->s_port;
21289580Smsmith
21389580Smsmith        ifsin.sin_len = sizeof(ifsin);
21489580Smsmith        ifsin.sin_family = AF_INET;
21589580Smsmith
21689580Smsmith        if (fd = socket(AF_INET, SOCK_STREAM, 0), fd < 0) {
21789580Smsmith            fprintf(stderr, "Cannot create internet socket\n");
21889580Smsmith            return 2;
21989580Smsmith        }
22089580Smsmith    }
22189580Smsmith
22289580Smsmith    TimedOut = 0;
22389580Smsmith    if (TimeoutVal) {
22489580Smsmith        act.sa_handler = Timeout;
22589580Smsmith        sigemptyset(&act.sa_mask);
22689580Smsmith        act.sa_flags = 0;
22789580Smsmith        sigaction(SIGALRM, &act, &oact);
22889580Smsmith        alarm(TimeoutVal);
22989580Smsmith    }
23089580Smsmith
23189580Smsmith    if (connect(fd, sock, socksz) < 0) {
23289580Smsmith        if (TimeoutVal) {
23389580Smsmith            alarm(0);
23489580Smsmith            sigaction(SIGALRM, &oact, 0);
23589580Smsmith        }
23689580Smsmith        if (TimedOut)
23789580Smsmith            fputs("Timeout: ", stderr);
23889580Smsmith        fprintf(stderr, "Cannot connect to socket %s\n", argv[arg]);
23989580Smsmith        close(fd);
24089580Smsmith        return 3;
24189580Smsmith    }
24289580Smsmith
24389580Smsmith    if (TimeoutVal) {
24489580Smsmith        alarm(0);
24589580Smsmith        sigaction(SIGALRM, &oact, 0);
24689580Smsmith    }
24789580Smsmith
24889580Smsmith    len = 0;
24989580Smsmith    Command[sizeof(Command)-1] = '\0';
25089580Smsmith    for (arg++; arg < argc; arg++) {
25189580Smsmith        if (len && len < sizeof(Command)-1)
25289580Smsmith            strcpy(Command+len++, " ");
25389580Smsmith        strncpy(Command+len, argv[arg], sizeof(Command)-len-1);
25489580Smsmith        len += strlen(Command+len);
25589580Smsmith    }
25689580Smsmith
25789580Smsmith    switch (Receive(fd, TimeoutVal, verbose | REC_PASSWD))
25889580Smsmith    {
25989580Smsmith        case 1:
26089580Smsmith            fprintf(stderr, "Password incorrect\n");
26189580Smsmith            break;
26289580Smsmith
26389580Smsmith        case 0:
26489580Smsmith            if (len == 0) {
26589580Smsmith                if (!verbose) {
26689580Smsmith                    /* Give a \n to ppp for a prompt */
26789580Smsmith                    write(fd, "\n", 1);
26889580Smsmith                    if (Receive(fd, TimeoutVal, REC_VERBOSE | REC_SHOW) != 0) {
26989580Smsmith                        fprintf(stderr, "Connection closed\n");
27089580Smsmith                        break;
27189580Smsmith                    }
27289580Smsmith                }
27389580Smsmith                while (fgets(Buffer, sizeof(Buffer)-1, stdin)) {
27489580Smsmith                    write(fd, Buffer, strlen(Buffer));
27589580Smsmith                    if (Receive(fd, TimeoutVal, REC_VERBOSE | REC_SHOW) != 0) {
27689580Smsmith                        fprintf(stderr, "Connection closed\n");
27789580Smsmith                        break;
27889580Smsmith                    }
27989580Smsmith                }
28089580Smsmith            } else {
28189580Smsmith                start = Command;
28289580Smsmith                do {
28389580Smsmith                    next = index(start, ';');
28489580Smsmith                    while (*start == ' ' || *start == '\t')
28589580Smsmith                        start++;
28689580Smsmith                    if (next)
28789580Smsmith                        *next = '\0';
28889580Smsmith                    strcpy(Buffer, start);
28989580Smsmith                    Buffer[sizeof(Buffer)-2] = '\0';
29089580Smsmith                    strcat(Buffer, "\n");
29189580Smsmith                    if (verbose)
29289580Smsmith                        write(1, Buffer, strlen(Buffer));
29389580Smsmith                    write(fd, Buffer, strlen(Buffer));
29489580Smsmith                    if (Receive(fd, TimeoutVal, verbose | REC_SHOW) != 0) {
29589580Smsmith                        fprintf(stderr, "No reply from ppp\n");
29689580Smsmith                        break;
29789580Smsmith                    }
29889580Smsmith                    if (next)
29989580Smsmith                        start = ++next;
30089580Smsmith                } while (next && *next);
30189580Smsmith                if (verbose)
30289580Smsmith                    puts("");
30389580Smsmith            }
30489580Smsmith            break;
30589580Smsmith
30689580Smsmith        default:
30789580Smsmith            fprintf(stderr, "ppp is not responding\n");
30889580Smsmith            break;
30989580Smsmith    }
31089580Smsmith
31189580Smsmith    close(fd);
31289580Smsmith
31389580Smsmith    return 0;
31489580Smsmith}
31589580Smsmith