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;
72 #define REC_PASSWD (1)
74 #define REC_VERBOSE (4)
80 GetPrompt(EditLine
*e
)
88 Receive(int fd
, int display
)
96 while (Result
= read(fd
, Buffer
+len
, sizeof(Buffer
)-len
-1), Result
!= -1) {
97 if (Result
== 0 && errno
!= EINTR
) {
103 if (len
> 2 && !strcmp(Buffer
+len
-2, "> ")) {
104 prompt
= strrchr(Buffer
, '\n');
105 if (display
& (REC_SHOW
|REC_VERBOSE
)) {
106 if (display
& REC_VERBOSE
)
112 write(1, Buffer
, last
-Buffer
);
115 prompt
= prompt
== NULL
? Buffer
: prompt
+1;
116 for (last
= Buffer
+len
-2; last
> Buffer
&& *last
!= ' '; last
--)
118 if (last
> Buffer
+3 && !strncmp(last
-3, " on", 3)) {
119 /* a password is required ! */
120 if (display
& REC_PASSWD
) {
123 passwd
= getpass("Password: ");
124 sprintf(Buffer
, "passwd %s\n", passwd
);
125 memset(passwd
, '\0', strlen(passwd
));
126 if (display
& REC_VERBOSE
)
127 write(1, Buffer
, strlen(Buffer
));
128 write(fd
, Buffer
, strlen(Buffer
));
129 memset(Buffer
, '\0', strlen(Buffer
));
130 return Receive(fd
, display
& ~REC_PASSWD
);
137 if (len
== sizeof Buffer
- 1) {
139 if ((last
= strrchr(Buffer
, '\n')) == NULL
)
140 /* Yeuch - this is one mother of a line ! */
141 flush
= sizeof Buffer
/ 2;
143 flush
= last
- Buffer
+ 1;
144 write(1, Buffer
, flush
);
145 strcpy(Buffer
, Buffer
+ flush
);
153 static int data
= -1;
154 static jmp_buf pppdead
;
162 static char buf
[LINELEN
];
167 t
.tv_sec
= t
.tv_usec
= 0;
168 if (select(data
+1, &f
, NULL
, NULL
, &t
) > 0) {
169 len
= read(data
, buf
, sizeof buf
);
173 longjmp(pppdead
, -1);
179 smartgets(EditLine
*e
, int *count
, int fd
)
184 signal(SIGALRM
, check_fd
);
185 ualarm(500000, 500000);
186 result
= setjmp(pppdead
) ? NULL
: el_gets(e
, count
);
188 signal(SIGALRM
, SIG_DFL
);
195 main(int argc
, char **argv
)
199 struct sockaddr
*sock
;
200 struct sockaddr_in ifsin
;
201 struct sockaddr_un ifsun
;
202 int n
, socksz
, arg
, fd
, len
, verbose
, save_errno
, hide1
, hide1off
, hide2
;
204 char *DoneWord
= "x", *next
, *start
;
205 struct sigaction act
, oact
;
209 hide1
= hide1off
= hide2
= 0;
211 for (arg
= 1; arg
< argc
; arg
++)
212 if (*argv
[arg
] == '-') {
213 for (start
= argv
[arg
] + 1; *start
; start
++)
216 TimeoutVal
= (unsigned)atoi
217 (start
[1] ? start
+ 1 : argv
[++arg
]);
222 verbose
= REC_VERBOSE
;
228 hide1off
= start
- argv
[arg
];
232 hide1off
= start
- argv
[arg
];
233 passwd
= argv
[++arg
];
254 for (harg
= pos
= 0; harg
< argc
; harg
++)
255 if (harg
== 0 || harg
!= hide2
) {
256 if (harg
== 0 || harg
!= hide1
)
257 n
= snprintf(title
+ pos
, sizeof title
- pos
, "%s%s",
258 harg
? " " : "", argv
[harg
]);
259 else if (hide1off
> 1)
260 n
= snprintf(title
+ pos
, sizeof title
- pos
, " %.*s",
261 hide1off
, argv
[harg
]);
264 if (n
< 0 || n
>= sizeof title
- pos
)
269 setproctitle("-%s", title
);
271 setproctitle("%s", title
);
275 if (*argv
[arg
] == '/') {
276 sock
= (struct sockaddr
*)&ifsun
;
277 socksz
= sizeof ifsun
;
279 memset(&ifsun
, '\0', sizeof ifsun
);
280 ifsun
.sun_len
= strlen(argv
[arg
]);
281 if (ifsun
.sun_len
> sizeof ifsun
.sun_path
- 1) {
282 warnx("%s: path too long", argv
[arg
]);
285 ifsun
.sun_family
= AF_LOCAL
;
286 strcpy(ifsun
.sun_path
, argv
[arg
]);
288 if (fd
= socket(AF_LOCAL
, SOCK_STREAM
, 0), fd
< 0) {
289 warnx("cannot create local domain socket");
293 char *port
, *host
, *colon
;
296 colon
= strchr(argv
[arg
], ':');
305 sock
= (struct sockaddr
*)&ifsin
;
306 socksz
= sizeof ifsin
;
309 memset(&ifsin
, '\0', sizeof ifsin
);
310 if (strspn(host
, "0123456789.") == hlen
) {
311 if (!inet_aton(host
, &ifsin
.sin_addr
)) {
312 warnx("cannot translate %s", host
);
315 } else if ((h
= gethostbyname(host
)) == NULL
) {
316 warnx("cannot resolve %s", host
);
320 ifsin
.sin_addr
.s_addr
= *(u_long
*)h
->h_addr_list
[0];
325 if (strspn(port
, "0123456789") == strlen(port
))
326 ifsin
.sin_port
= htons(atoi(port
));
327 else if (s
= getservbyname(port
, "tcp"), !s
) {
328 warnx("%s isn't a valid port or service!", port
);
332 ifsin
.sin_port
= s
->s_port
;
334 ifsin
.sin_len
= sizeof(ifsin
);
335 ifsin
.sin_family
= AF_INET
;
337 if (fd
= socket(AF_INET
, SOCK_STREAM
, 0), fd
< 0) {
338 warnx("cannot create internet socket");
345 act
.sa_handler
= Timeout
;
346 sigemptyset(&act
.sa_mask
);
348 sigaction(SIGALRM
, &act
, &oact
);
352 if (connect(fd
, sock
, socksz
) < 0) {
356 sigaction(SIGALRM
, &oact
, 0);
360 warnx("timeout: cannot connect to socket %s", argv
[arg
]);
363 warn("cannot connect to socket %s", argv
[arg
]);
365 warnx("cannot connect to socket %s", argv
[arg
]);
373 sigaction(SIGALRM
, &oact
, 0);
377 Command
[sizeof(Command
)-1] = '\0';
378 for (arg
++; arg
< argc
; arg
++) {
379 if (len
&& len
< sizeof(Command
)-1)
380 strcpy(Command
+len
++, " ");
381 strncpy(Command
+len
, argv
[arg
], sizeof(Command
)-len
-1);
382 len
+= strlen(Command
+len
);
385 switch (Receive(fd
, verbose
| REC_PASSWD
))
388 fprintf(stderr
, "Password incorrect\n");
399 hist
= history_init();
400 if ((env
= getenv("EL_SIZE"))) {
406 history(hist
, &he
, H_SETSIZE
, size
);
407 edit
= el_init("pppctl", stdin
, stdout
, stderr
);
408 el_source(edit
, NULL
);
409 el_set(edit
, EL_PROMPT
, GetPrompt
);
410 if ((env
= getenv("EL_EDITOR"))) {
411 if (!strcmp(env
, "vi"))
412 el_set(edit
, EL_EDITOR
, "vi");
413 else if (!strcmp(env
, "emacs"))
414 el_set(edit
, EL_EDITOR
, "emacs");
416 el_set(edit
, EL_SIGNAL
, 1);
417 el_set(edit
, EL_HIST
, history
, (const char *)hist
);
418 while ((l
= smartgets(edit
, &len
, fd
))) {
420 history(hist
, &he
, H_ENTER
, l
);
422 if (Receive(fd
, REC_SHOW
) != 0)
425 fprintf(stderr
, "Connection closed\n");
431 next
= strchr(start
, ';');
432 while (*start
== ' ' || *start
== '\t')
436 strcpy(Buffer
, start
);
437 Buffer
[sizeof(Buffer
)-2] = '\0';
438 strcat(Buffer
, "\n");
440 write(1, Buffer
, strlen(Buffer
));
441 write(fd
, Buffer
, strlen(Buffer
));
442 if (Receive(fd
, verbose
| REC_SHOW
) != 0) {
443 fprintf(stderr
, "Connection closed\n");
448 } while (next
&& *next
);
455 warnx("ppp is not responding");