xref: /freebsd/usr.sbin/pppctl/pppctl.c (revision ce834215a70ff69e7e222827437116eee2f9ac6f)
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <netinet/in.h>
4 #include <sys/un.h>
5 #include <netdb.h>
6 #include <signal.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <stdlib.h>
11 
12 #define LINELEN 2048
13 static char Buffer[LINELEN], Command[LINELEN];
14 
15 static int Usage()
16 {
17     fprintf(stderr, "Usage: pppctl [-v] [ -t n ] [ -p passwd ] Port|LocalSock command[;command]...\n");
18     fprintf(stderr, "              -v tells pppctl to output all conversation\n");
19     fprintf(stderr, "              -t n specifies a timeout of n seconds (default 2)\n");
20     fprintf(stderr, "              -p passwd specifies your password\n");
21     return 1;
22 }
23 
24 static int TimedOut = 0;
25 void Timeout(int Sig)
26 {
27     TimedOut = 1;
28 }
29 
30 #define REC_PASSWD  (1)
31 #define REC_SHOW    (2)
32 #define REC_VERBOSE (4)
33 
34 static char *passwd;
35 
36 int Receive(int fd, unsigned TimeoutVal, int display)
37 {
38     int Result;
39     struct sigaction act, oact;
40     int len;
41     char *last;
42 
43     TimedOut = 0;
44     if (TimeoutVal) {
45         act.sa_handler = Timeout;
46         sigemptyset(&act.sa_mask);
47         act.sa_flags = 0;
48         sigaction(SIGALRM, &act, &oact);
49         alarm(TimeoutVal);
50     }
51 
52     len = 0;
53     while (Result = read(fd, Buffer+len, sizeof(Buffer)-len-1), Result != -1) {
54         len += Result;
55         Buffer[len] = '\0';
56         if (TimedOut) {
57             if (display & REC_VERBOSE)
58                 write(1,Buffer,len);
59             Result = -1;
60             break;
61         } else if (len > 2 && !strcmp(Buffer+len-2, "> ")) {
62             if (display & (REC_SHOW|REC_VERBOSE)) {
63                 if (display & REC_VERBOSE)
64                     last = Buffer+len-1;
65                 else
66                     last = rindex(Buffer, '\n');
67                 if (last) {
68                     *++last = '\0';
69                     write(1, Buffer, last-Buffer);
70                 }
71             }
72             for (last = Buffer+len-2; last > Buffer && *last != ' '; last--)
73                 ;
74             if (last > Buffer+3 && !strncmp(last-3, " on", 3)) {
75                  /* a password is required ! */
76                  if (display & REC_PASSWD) {
77                     if (TimeoutVal) {
78                         alarm(0);
79                         sigaction(SIGALRM, &oact, 0);
80                     }
81                     /* password time */
82                     if (!passwd)
83                         passwd = getpass("Password: ");
84                     sprintf(Buffer, "passwd %s\n", passwd);
85                     bzero(passwd, strlen(passwd));
86                     if (display & REC_VERBOSE)
87                         write(1, Buffer, strlen(Buffer));
88                     write(fd, Buffer, strlen(Buffer));
89                     bzero(Buffer, strlen(Buffer));
90                     return Receive(fd, TimeoutVal, display & ~REC_PASSWD);
91                 }
92                 Result = 1;
93             } else
94                 Result = 0;
95             break;
96         }
97     }
98 
99     if (TimedOut)
100         Result = -1;
101 
102     if (TimeoutVal) {
103         alarm(0);
104         sigaction(SIGALRM, &oact, 0);
105     }
106     return Result;
107 }
108 
109 int
110 main(int argc, char **argv)
111 {
112     struct servent *s;
113     struct hostent *h;
114     struct sockaddr *sock;
115     struct sockaddr_in ifsin;
116     struct sockaddr_un ifsun;
117     int socksz, arg, fd, len, verbose;
118     unsigned TimeoutVal;
119     char *DoneWord = "x", *next, *start;
120     struct sigaction act, oact;
121 
122     verbose = 0;
123     TimeoutVal = 2;
124 
125     for (arg = 1; arg < argc; arg++)
126         if (*argv[arg] == '-') {
127             for (start = argv[arg] + 1; *start; start++)
128                 switch (*start) {
129                     case 't':
130                         TimeoutVal = (unsigned)atoi
131                             (start[1] ? start + 1 : argv[++arg]);
132                         start = DoneWord;
133                         break;
134 
135                     case 'v':
136                         verbose = REC_VERBOSE;
137                         break;
138 
139                     case 'p':
140                         passwd = (start[1] ? start + 1 : argv[++arg]);
141                         start = DoneWord;
142                         break;
143 
144                     default:
145                         return Usage();
146                 }
147         }
148         else
149             break;
150 
151 
152     if (argc < arg + 2)
153         return Usage();
154 
155     if (*argv[arg] == '/') {
156         sock = (struct sockaddr *)&ifsun;
157         socksz = sizeof ifsun;
158 
159         ifsun.sun_len = strlen(argv[arg]);
160         if (ifsun.sun_len > sizeof ifsun.sun_path - 1) {
161             fprintf(stderr, "%s: Path too long\n", argv[arg]);
162             return 1;
163         }
164         ifsun.sun_family = AF_LOCAL;
165         strcpy(ifsun.sun_path, argv[arg]);
166 
167         if (fd = socket(AF_LOCAL, SOCK_STREAM, 0), fd < 0) {
168             fprintf(stderr, "Cannot create local domain socket\n");
169             return 2;
170         }
171     } else {
172         char *port, *host, *colon;
173 
174         colon = strchr(argv[arg], ':');
175         if (colon) {
176             port = colon + 1;
177             *colon = '\0';
178             host = argv[arg];
179         } else {
180             port = argv[arg];
181             host = "localhost";
182         }
183         sock = (struct sockaddr *)&ifsin;
184         socksz = sizeof ifsin;
185 
186         if ((h = gethostbyname(host)) == 0) {
187             fprintf(stderr, "Cannot resolve %s\n", host);
188             return 1;
189         }
190         if (colon)
191             *colon = ':';
192 
193         if (strspn(port, "0123456789") == strlen(port))
194             ifsin.sin_port = htons(atoi(port));
195         else if (s = getservbyname(port, "tcp"), !s) {
196             fprintf(stderr, "%s isn't a valid port or service!\n", port);
197             return Usage();
198         }
199         else
200             ifsin.sin_port = s->s_port;
201 
202         ifsin.sin_len = sizeof(ifsin);
203         ifsin.sin_family = AF_INET;
204         ifsin.sin_addr.s_addr = *(u_long *)h->h_addr_list[0];
205 
206         if (fd = socket(AF_INET, SOCK_STREAM, 0), fd < 0) {
207             fprintf(stderr, "Cannot create internet socket\n");
208             return 2;
209         }
210     }
211 
212     TimedOut = 0;
213     if (TimeoutVal) {
214         act.sa_handler = Timeout;
215         sigemptyset(&act.sa_mask);
216         act.sa_flags = 0;
217         sigaction(SIGALRM, &act, &oact);
218         alarm(TimeoutVal);
219     }
220 
221     if (connect(fd, sock, socksz) < 0) {
222         if (TimeoutVal) {
223             alarm(0);
224             sigaction(SIGALRM, &oact, 0);
225         }
226         if (TimedOut)
227             fputs("Timeout: ", stderr);
228         fprintf(stderr, "Cannot connect to socket %s\n", argv[arg]);
229         close(fd);
230         return 3;
231     }
232 
233     if (TimeoutVal) {
234         alarm(0);
235         sigaction(SIGALRM, &oact, 0);
236     }
237 
238     len = 0;
239     Command[sizeof(Command)-1] = '\0';
240     for (arg++; arg < argc; arg++) {
241         if (len && len < sizeof(Command)-1)
242             strcpy(Command+len++, " ");
243         strncpy(Command+len, argv[arg], sizeof(Command)-len-1);
244         len += strlen(Command+len);
245     }
246 
247     switch (Receive(fd, TimeoutVal, verbose | REC_PASSWD))
248     {
249         case 1:
250             fprintf(stderr, "Password incorrect\n");
251             break;
252 
253         case 0:
254             start = Command;
255             do {
256                 next = index(start, ';');
257                 while (*start == ' ' || *start == '\t')
258                     start++;
259                 if (next)
260                     *next = '\0';
261                 strcpy(Buffer, start);
262                 Buffer[sizeof(Buffer)-2] = '\0';
263                 strcat(Buffer, "\n");
264                 if (verbose)
265                     write(1, Buffer, strlen(Buffer));
266                 write(fd, Buffer, strlen(Buffer));
267                 if (Receive(fd, TimeoutVal, verbose | REC_SHOW) != 0) {
268                     fprintf(stderr, "No reply from ppp\n");
269                     break;
270                 }
271                 if (next)
272                     start = ++next;
273             } while (next && *next);
274             if (verbose)
275                 puts("");
276             break;
277 
278         default:
279             fprintf(stderr, "ppp is not responding\n");
280             break;
281     }
282 
283     close(fd);
284 
285     return 0;
286 }
287