2 * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/usr.sbin/pppctl/pppctl.c,v 1.21.2.2 2001/11/23 13:18:39 brian Exp $
29 #include <sys/param.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
50 static char Buffer
[LINELEN
], Command
[LINELEN
];
55 fprintf(stderr
, "usage: pppctl [-v] [-t n] [-p passwd] "
56 "Port|LocalSock [command[;command]...]\n");
57 fprintf(stderr
, " -v tells pppctl to output all"
59 fprintf(stderr
, " -t n specifies a timeout of n"
60 " seconds when connecting (default 2)\n");
61 fprintf(stderr
, " -p passwd specifies your password\n");
65 static int TimedOut
= 0;
67 Timeout(int Sig __unused
)
72 #define REC_PASSWD (1)
74 #define REC_VERBOSE (4)
80 GetPrompt(EditLine
*e __unused
)
88 Receive(int fd
, int display
)
90 char temp
[sizeof(Buffer
)];
97 while (Result
= read(fd
, Buffer
+len
, sizeof(Buffer
)-len
-1), Result
!= -1) {
98 if (Result
== 0 && errno
!= EINTR
) {
104 if (len
> 2 && !strcmp(Buffer
+len
-2, "> ")) {
105 prompt
= strrchr(Buffer
, '\n');
106 if (display
& (REC_SHOW
|REC_VERBOSE
)) {
107 if (display
& REC_VERBOSE
)
113 write(1, Buffer
, last
-Buffer
);
116 prompt
= prompt
== NULL
? Buffer
: prompt
+1;
117 for (last
= Buffer
+len
-2; last
> Buffer
&& *last
!= ' '; last
--)
119 if (last
> Buffer
+3 && !strncmp(last
-3, " on", 3)) {
120 /* a password is required ! */
121 if (display
& REC_PASSWD
) {
124 passwd
= getpass("Password: ");
125 sprintf(Buffer
, "passwd %s\n", passwd
);
126 memset(passwd
, '\0', strlen(passwd
));
127 if (display
& REC_VERBOSE
)
128 write(1, Buffer
, strlen(Buffer
));
129 write(fd
, Buffer
, strlen(Buffer
));
130 memset(Buffer
, '\0', strlen(Buffer
));
131 return Receive(fd
, display
& ~REC_PASSWD
);
138 if (len
== sizeof Buffer
- 1) {
140 if ((last
= strrchr(Buffer
, '\n')) == NULL
)
141 /* Yeuch - this is one mother of a line ! */
142 flush
= sizeof Buffer
/ 2;
144 flush
= last
- Buffer
+ 1;
145 write(1, Buffer
, flush
);
146 strcpy(temp
, Buffer
+ flush
);
147 strcpy(Buffer
, temp
);
155 static int data
= -1;
156 static jmp_buf pppdead
;
159 check_fd(int sig __unused
)
164 static char buf
[LINELEN
];
169 t
.tv_sec
= t
.tv_usec
= 0;
170 if (select(data
+1, &f
, NULL
, NULL
, &t
) > 0) {
171 len
= read(data
, buf
, sizeof buf
);
175 longjmp(pppdead
, -1);
181 smartgets(EditLine
*e
, int *count
, int fd
)
186 signal(SIGALRM
, check_fd
);
187 ualarm(500000, 500000);
188 result
= setjmp(pppdead
) ? NULL
: el_gets(e
, count
);
190 signal(SIGALRM
, SIG_DFL
);
197 main(int argc
, char **argv
)
201 struct sockaddr
*sock
;
202 struct sockaddr_in ifsin
;
203 struct sockaddr_un ifsun
;
204 int n
, socksz
, arg
, fd
, len
, verbose
, save_errno
, hide1
, hide1off
, hide2
;
206 char *DoneWord
= "x", *next
, *start
;
207 struct sigaction act
, oact
;
211 hide1
= hide1off
= hide2
= 0;
213 for (arg
= 1; arg
< argc
; arg
++)
214 if (*argv
[arg
] == '-') {
215 for (start
= argv
[arg
] + 1; *start
; start
++)
218 TimeoutVal
= (unsigned)atoi
219 (start
[1] ? start
+ 1 : argv
[++arg
]);
224 verbose
= REC_VERBOSE
;
230 hide1off
= start
- argv
[arg
];
234 hide1off
= start
- argv
[arg
];
235 passwd
= argv
[++arg
];
256 for (harg
= pos
= 0; harg
< argc
; harg
++)
257 if (harg
== 0 || harg
!= hide2
) {
258 if (harg
== 0 || harg
!= hide1
)
259 n
= snprintf(title
+ pos
, sizeof title
- pos
, "%s%s",
260 harg
? " " : "", argv
[harg
]);
261 else if (hide1off
> 1)
262 n
= snprintf(title
+ pos
, sizeof title
- pos
, " %.*s",
263 hide1off
, argv
[harg
]);
266 if (n
< 0 || n
>= sizeof title
- pos
)
271 setproctitle("-%s", title
);
273 setproctitle("%s", title
);
277 if (*argv
[arg
] == '/') {
278 sock
= (struct sockaddr
*)&ifsun
;
279 socksz
= sizeof ifsun
;
281 memset(&ifsun
, '\0', sizeof ifsun
);
282 ifsun
.sun_len
= strlen(argv
[arg
]);
283 if (ifsun
.sun_len
> sizeof ifsun
.sun_path
- 1) {
284 warnx("%s: path too long", argv
[arg
]);
287 ifsun
.sun_family
= AF_LOCAL
;
288 strcpy(ifsun
.sun_path
, argv
[arg
]);
290 if (fd
= socket(AF_LOCAL
, SOCK_STREAM
, 0), fd
< 0) {
291 warnx("cannot create local domain socket");
295 char *port
, *host
, *colon
;
298 colon
= strchr(argv
[arg
], ':');
307 sock
= (struct sockaddr
*)&ifsin
;
308 socksz
= sizeof ifsin
;
311 memset(&ifsin
, '\0', sizeof ifsin
);
312 if (strspn(host
, "0123456789.") == hlen
) {
313 if (!inet_aton(host
, &ifsin
.sin_addr
)) {
314 warnx("cannot translate %s", host
);
317 } else if ((h
= gethostbyname(host
)) == NULL
) {
318 warnx("cannot resolve %s", host
);
322 ifsin
.sin_addr
.s_addr
= *(u_long
*)h
->h_addr_list
[0];
327 if (strspn(port
, "0123456789") == strlen(port
))
328 ifsin
.sin_port
= htons(atoi(port
));
329 else if (s
= getservbyname(port
, "tcp"), !s
) {
330 warnx("%s isn't a valid port or service!", port
);
334 ifsin
.sin_port
= s
->s_port
;
336 ifsin
.sin_len
= sizeof(ifsin
);
337 ifsin
.sin_family
= AF_INET
;
339 if (fd
= socket(AF_INET
, SOCK_STREAM
, 0), fd
< 0) {
340 warnx("cannot create internet socket");
347 act
.sa_handler
= Timeout
;
348 sigemptyset(&act
.sa_mask
);
350 sigaction(SIGALRM
, &act
, &oact
);
354 if (connect(fd
, sock
, socksz
) < 0) {
358 sigaction(SIGALRM
, &oact
, 0);
362 warnx("timeout: cannot connect to socket %s", argv
[arg
]);
365 warn("cannot connect to socket %s", argv
[arg
]);
367 warnx("cannot connect to socket %s", argv
[arg
]);
375 sigaction(SIGALRM
, &oact
, 0);
379 Command
[sizeof(Command
)-1] = '\0';
380 for (arg
++; arg
< argc
; arg
++) {
381 if (len
&& len
< sizeof(Command
)-1)
382 strcpy(Command
+len
++, " ");
383 strncpy(Command
+len
, argv
[arg
], sizeof(Command
)-len
-1);
384 len
+= strlen(Command
+len
);
387 switch (Receive(fd
, verbose
| REC_PASSWD
))
390 fprintf(stderr
, "Password incorrect\n");
401 hist
= history_init();
402 if ((env
= getenv("EL_SIZE"))) {
408 history(hist
, &he
, H_SETSIZE
, size
);
409 edit
= el_init("pppctl", stdin
, stdout
, stderr
);
410 el_source(edit
, NULL
);
411 el_set(edit
, EL_PROMPT
, GetPrompt
);
412 if ((env
= getenv("EL_EDITOR"))) {
413 if (!strcmp(env
, "vi"))
414 el_set(edit
, EL_EDITOR
, "vi");
415 else if (!strcmp(env
, "emacs"))
416 el_set(edit
, EL_EDITOR
, "emacs");
418 el_set(edit
, EL_SIGNAL
, 1);
419 el_set(edit
, EL_HIST
, history
, (const char *)hist
);
420 while ((l
= smartgets(edit
, &len
, fd
))) {
422 history(hist
, &he
, H_ENTER
, l
);
424 if (Receive(fd
, REC_SHOW
) != 0)
427 fprintf(stderr
, "Connection closed\n");
433 next
= strchr(start
, ';');
434 while (*start
== ' ' || *start
== '\t')
438 strcpy(Buffer
, start
);
439 Buffer
[sizeof(Buffer
)-2] = '\0';
440 strcat(Buffer
, "\n");
442 write(1, Buffer
, strlen(Buffer
));
443 write(fd
, Buffer
, strlen(Buffer
));
444 if (Receive(fd
, verbose
| REC_SHOW
) != 0) {
445 fprintf(stderr
, "Connection closed\n");
450 } while (next
&& *next
);
457 warnx("ppp is not responding");