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