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 $
27 * $DragonFly: src/usr.sbin/pppctl/pppctl.c,v 1.7 2006/01/14 22:58:18 corecode Exp $
30 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
51 static char Buffer
[LINELEN
], Command
[LINELEN
];
56 fprintf(stderr
, "usage: pppctl [-v] [-t n] [-p passwd] "
57 "Port|LocalSock [command[;command]...]\n");
58 fprintf(stderr
, " -v tells pppctl to output all"
60 fprintf(stderr
, " -t n specifies a timeout of n"
61 " seconds when connecting (default 2)\n");
62 fprintf(stderr
, " -p passwd specifies your password\n");
66 static int TimedOut
= 0;
73 #define REC_PASSWD (1)
75 #define REC_VERBOSE (4)
81 GetPrompt(EditLine
*e
)
89 Receive(int fd
, int display
)
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(Buffer
, Buffer
+ flush
);
154 static int data
= -1;
155 static jmp_buf pppdead
;
163 static char buf
[LINELEN
];
168 t
.tv_sec
= t
.tv_usec
= 0;
169 if (select(data
+1, &f
, NULL
, NULL
, &t
) > 0) {
170 len
= read(data
, buf
, sizeof buf
);
174 longjmp(pppdead
, -1);
180 smartgets(EditLine
*e
, int *count
, int fd
)
185 signal(SIGALRM
, check_fd
);
186 ualarm(500000, 500000);
187 result
= setjmp(pppdead
) ? NULL
: el_gets(e
, count
);
189 signal(SIGALRM
, SIG_DFL
);
196 main(int argc
, char **argv
)
200 struct sockaddr
*sock
;
201 struct sockaddr_in ifsin
;
202 struct sockaddr_un ifsun
;
203 int n
, socksz
, arg
, fd
, len
, verbose
, save_errno
, hide1
, hide1off
, hide2
;
205 char *DoneWord
= "x", *next
, *start
;
206 struct sigaction act
, oact
;
210 hide1
= hide1off
= hide2
= 0;
212 for (arg
= 1; arg
< argc
; arg
++)
213 if (*argv
[arg
] == '-') {
214 for (start
= argv
[arg
] + 1; *start
; start
++)
217 TimeoutVal
= (unsigned)atoi
218 (start
[1] ? start
+ 1 : argv
[++arg
]);
223 verbose
= REC_VERBOSE
;
229 hide1off
= start
- argv
[arg
];
233 hide1off
= start
- argv
[arg
];
234 passwd
= argv
[++arg
];
255 for (harg
= pos
= 0; harg
< argc
; harg
++)
256 if (harg
== 0 || harg
!= hide2
) {
257 if (harg
== 0 || harg
!= hide1
)
258 n
= snprintf(title
+ pos
, sizeof title
- pos
, "%s%s",
259 harg
? " " : "", argv
[harg
]);
260 else if (hide1off
> 1)
261 n
= snprintf(title
+ pos
, sizeof title
- pos
, " %.*s",
262 hide1off
, argv
[harg
]);
265 if (n
< 0 || n
>= sizeof title
- pos
)
270 setproctitle("-%s", title
);
272 setproctitle("%s", title
);
276 if (*argv
[arg
] == '/') {
277 sock
= (struct sockaddr
*)&ifsun
;
278 socksz
= sizeof ifsun
;
280 memset(&ifsun
, '\0', sizeof ifsun
);
281 ifsun
.sun_len
= strlen(argv
[arg
]);
282 if (ifsun
.sun_len
> sizeof ifsun
.sun_path
- 1) {
283 warnx("%s: path too long", argv
[arg
]);
286 ifsun
.sun_family
= AF_LOCAL
;
287 strcpy(ifsun
.sun_path
, argv
[arg
]);
289 if (fd
= socket(AF_LOCAL
, SOCK_STREAM
, 0), fd
< 0) {
290 warnx("cannot create local domain socket");
294 char *port
, *host
, *colon
;
297 colon
= strchr(argv
[arg
], ':');
306 sock
= (struct sockaddr
*)&ifsin
;
307 socksz
= sizeof ifsin
;
310 memset(&ifsin
, '\0', sizeof ifsin
);
311 if (strspn(host
, "0123456789.") == hlen
) {
312 if (!inet_aton(host
, &ifsin
.sin_addr
)) {
313 warnx("cannot translate %s", host
);
316 } else if ((h
= gethostbyname(host
)) == 0) {
317 warnx("cannot resolve %s", host
);
321 ifsin
.sin_addr
.s_addr
= *(u_long
*)h
->h_addr_list
[0];
326 if (strspn(port
, "0123456789") == strlen(port
))
327 ifsin
.sin_port
= htons(atoi(port
));
328 else if (s
= getservbyname(port
, "tcp"), !s
) {
329 warnx("%s isn't a valid port or service!", port
);
333 ifsin
.sin_port
= s
->s_port
;
335 ifsin
.sin_len
= sizeof(ifsin
);
336 ifsin
.sin_family
= AF_INET
;
338 if (fd
= socket(AF_INET
, SOCK_STREAM
, 0), fd
< 0) {
339 warnx("cannot create internet socket");
346 act
.sa_handler
= Timeout
;
347 sigemptyset(&act
.sa_mask
);
349 sigaction(SIGALRM
, &act
, &oact
);
353 if (connect(fd
, sock
, socksz
) < 0) {
357 sigaction(SIGALRM
, &oact
, 0);
361 warnx("timeout: cannot connect to socket %s", argv
[arg
]);
364 warn("cannot connect to socket %s", argv
[arg
]);
366 warnx("cannot connect to socket %s", argv
[arg
]);
374 sigaction(SIGALRM
, &oact
, 0);
378 Command
[sizeof(Command
)-1] = '\0';
379 for (arg
++; arg
< argc
; arg
++) {
380 if (len
&& len
< sizeof(Command
)-1)
381 strcpy(Command
+len
++, " ");
382 strncpy(Command
+len
, argv
[arg
], sizeof(Command
)-len
-1);
383 len
+= strlen(Command
+len
);
386 switch (Receive(fd
, verbose
| REC_PASSWD
))
389 fprintf(stderr
, "Password incorrect\n");
400 hist
= history_init();
401 if ((env
= getenv("EL_SIZE"))) {
407 history(hist
, &he
, H_SETSIZE
, size
);
408 edit
= el_init("pppctl", stdin
, stdout
, stderr
);
409 el_source(edit
, NULL
);
410 el_set(edit
, EL_PROMPT
, GetPrompt
);
411 if ((env
= getenv("EL_EDITOR"))) {
412 if (!strcmp(env
, "vi"))
413 el_set(edit
, EL_EDITOR
, "vi");
414 else if (!strcmp(env
, "emacs"))
415 el_set(edit
, EL_EDITOR
, "emacs");
417 el_set(edit
, EL_SIGNAL
, 1);
418 el_set(edit
, EL_HIST
, history
, (const char *)hist
);
419 while ((l
= smartgets(edit
, &len
, fd
))) {
421 history(hist
, &he
, H_ENTER
, l
);
423 if (Receive(fd
, REC_SHOW
) != 0)
426 fprintf(stderr
, "Connection closed\n");
432 next
= strchr(start
, ';');
433 while (*start
== ' ' || *start
== '\t')
437 strcpy(Buffer
, start
);
438 Buffer
[sizeof(Buffer
)-2] = '\0';
439 strcat(Buffer
, "\n");
441 write(1, Buffer
, strlen(Buffer
));
442 write(fd
, Buffer
, strlen(Buffer
));
443 if (Receive(fd
, verbose
| REC_SHOW
) != 0) {
444 fprintf(stderr
, "Connection closed\n");
449 } while (next
&& *next
);
456 warnx("ppp is not responding");