pppctl.c revision 31914
1/* 2 * $Id: pppctl.c,v 1.12 1997/12/18 00:29:56 brian Exp $ 3 */ 4 5#include <sys/types.h> 6 7#include <sys/socket.h> 8#include <netinet/in.h> 9#include <arpa/inet.h> 10#include <sys/un.h> 11#include <netdb.h> 12 13#include <sys/time.h> 14#include <errno.h> 15#include <histedit.h> 16#include <setjmp.h> 17#include <signal.h> 18#include <stdio.h> 19#include <stdlib.h> 20#include <string.h> 21#include <time.h> 22#include <unistd.h> 23 24#define LINELEN 2048 25static char Buffer[LINELEN], Command[LINELEN]; 26 27static int 28Usage() 29{ 30 fprintf(stderr, "Usage: pppctl [-v] [ -t n ] [ -p passwd ] " 31 "Port|LocalSock [command[;command]...]\n"); 32 fprintf(stderr, " -v tells pppctl to output all" 33 " conversation\n"); 34 fprintf(stderr, " -t n specifies a timeout of n" 35 " seconds when connecting (default 2)\n"); 36 fprintf(stderr, " -p passwd specifies your password\n"); 37 return 1; 38} 39 40static int TimedOut = 0; 41static void 42Timeout(int Sig) 43{ 44 TimedOut = 1; 45} 46 47#define REC_PASSWD (1) 48#define REC_SHOW (2) 49#define REC_VERBOSE (4) 50 51static char *passwd; 52static char *prompt; 53 54static char * 55GetPrompt(EditLine *e) 56{ 57 if (prompt == NULL) 58 prompt = ""; 59 return prompt; 60} 61 62static int 63Receive(int fd, int display) 64{ 65 int Result; 66 int len; 67 char *last; 68 69 prompt = Buffer; 70 len = 0; 71 while (Result = read(fd, Buffer+len, sizeof(Buffer)-len-1), Result != -1) { 72 if (Result == 0 && errno != EINTR) { 73 Result = -1; 74 break; 75 } 76 len += Result; 77 Buffer[len] = '\0'; 78 if (TimedOut) { 79 if (display & REC_VERBOSE) 80 write(1,Buffer,len); 81 Result = -1; 82 break; 83 } else if (len > 2 && !strcmp(Buffer+len-2, "> ")) { 84 prompt = strrchr(Buffer, '\n'); 85 if (display & (REC_SHOW|REC_VERBOSE)) { 86 if (display & REC_VERBOSE) 87 last = Buffer+len-1; 88 else 89 last = prompt; 90 if (last) { 91 last++; 92 write(1, Buffer, last-Buffer); 93 } 94 } 95 prompt = prompt == NULL ? Buffer : prompt+1; 96 for (last = Buffer+len-2; last > Buffer && *last != ' '; last--) 97 ; 98 if (last > Buffer+3 && !strncmp(last-3, " on", 3)) { 99 /* a password is required ! */ 100 if (display & REC_PASSWD) { 101 /* password time */ 102 if (!passwd) 103 passwd = getpass("Password: "); 104 sprintf(Buffer, "passwd %s\n", passwd); 105 memset(passwd, '\0', strlen(passwd)); 106 if (display & REC_VERBOSE) 107 write(1, Buffer, strlen(Buffer)); 108 write(fd, Buffer, strlen(Buffer)); 109 memset(Buffer, '\0', strlen(Buffer)); 110 return Receive(fd, display & ~REC_PASSWD); 111 } 112 Result = 1; 113 } else 114 Result = 0; 115 break; 116 } 117 } 118 119 return Result; 120} 121 122static int data = -1; 123static jmp_buf pppdead; 124 125static void 126check_fd(int sig) 127{ 128 if (data != -1) { 129 struct timeval t; 130 fd_set f; 131 static char buf[LINELEN]; 132 int len; 133 134 FD_ZERO(&f); 135 FD_SET(data, &f); 136 t.tv_sec = t.tv_usec = 0; 137 if (select(data+1, &f, NULL, NULL, &t) > 0) { 138 len = read(data, buf, sizeof buf); 139 if (len > 0) 140 write(1, buf, len); 141 else 142 longjmp(pppdead, -1); 143 } 144 } 145} 146 147static const char * 148smartgets(EditLine *e, int *count, int fd) 149{ 150 const char *result; 151 152 data = fd; 153 signal(SIGALRM, check_fd); 154 ualarm(500000, 500000); 155 result = setjmp(pppdead) ? NULL : el_gets(e, count); 156 ualarm(0,0); 157 signal(SIGALRM, SIG_DFL); 158 data = -1; 159 160 return result; 161} 162 163int 164main(int argc, char **argv) 165{ 166 struct servent *s; 167 struct hostent *h; 168 struct sockaddr *sock; 169 struct sockaddr_in ifsin; 170 struct sockaddr_un ifsun; 171 int socksz, arg, fd, len, verbose; 172 unsigned TimeoutVal; 173 char *DoneWord = "x", *next, *start; 174 struct sigaction act, oact; 175 176 verbose = 0; 177 TimeoutVal = 2; 178 179 for (arg = 1; arg < argc; arg++) 180 if (*argv[arg] == '-') { 181 for (start = argv[arg] + 1; *start; start++) 182 switch (*start) { 183 case 't': 184 TimeoutVal = (unsigned)atoi 185 (start[1] ? start + 1 : argv[++arg]); 186 start = DoneWord; 187 break; 188 189 case 'v': 190 verbose = REC_VERBOSE; 191 break; 192 193 case 'p': 194 passwd = (start[1] ? start + 1 : argv[++arg]); 195 start = DoneWord; 196 break; 197 198 default: 199 return Usage(); 200 } 201 } 202 else 203 break; 204 205 206 if (argc < arg + 1) 207 return Usage(); 208 209 if (*argv[arg] == '/') { 210 sock = (struct sockaddr *)&ifsun; 211 socksz = sizeof ifsun; 212 213 memset(&ifsun, '\0', sizeof ifsun); 214 ifsun.sun_len = strlen(argv[arg]); 215 if (ifsun.sun_len > sizeof ifsun.sun_path - 1) { 216 fprintf(stderr, "%s: Path too long\n", argv[arg]); 217 return 1; 218 } 219 ifsun.sun_family = AF_LOCAL; 220 strcpy(ifsun.sun_path, argv[arg]); 221 222 if (fd = socket(AF_LOCAL, SOCK_STREAM, 0), fd < 0) { 223 fprintf(stderr, "Cannot create local domain socket\n"); 224 return 2; 225 } 226 } else { 227 char *port, *host, *colon; 228 int hlen; 229 230 colon = strchr(argv[arg], ':'); 231 if (colon) { 232 port = colon + 1; 233 *colon = '\0'; 234 host = argv[arg]; 235 } else { 236 port = argv[arg]; 237 host = "127.0.0.1"; 238 } 239 sock = (struct sockaddr *)&ifsin; 240 socksz = sizeof ifsin; 241 hlen = strlen(host); 242 243 memset(&ifsin, '\0', sizeof ifsin); 244 if (strspn(host, "0123456789.") == hlen) { 245 if (!inet_aton(host, &ifsin.sin_addr)) { 246 fprintf(stderr, "Cannot translate %s\n", host); 247 return 1; 248 } 249 } else if ((h = gethostbyname(host)) == 0) { 250 fprintf(stderr, "Cannot resolve %s\n", host); 251 return 1; 252 } 253 else 254 ifsin.sin_addr.s_addr = *(u_long *)h->h_addr_list[0]; 255 256 if (colon) 257 *colon = ':'; 258 259 if (strspn(port, "0123456789") == strlen(port)) 260 ifsin.sin_port = htons(atoi(port)); 261 else if (s = getservbyname(port, "tcp"), !s) { 262 fprintf(stderr, "%s isn't a valid port or service!\n", port); 263 return Usage(); 264 } 265 else 266 ifsin.sin_port = s->s_port; 267 268 ifsin.sin_len = sizeof(ifsin); 269 ifsin.sin_family = AF_INET; 270 271 if (fd = socket(AF_INET, SOCK_STREAM, 0), fd < 0) { 272 fprintf(stderr, "Cannot create internet socket\n"); 273 return 2; 274 } 275 } 276 277 TimedOut = 0; 278 if (TimeoutVal) { 279 act.sa_handler = Timeout; 280 sigemptyset(&act.sa_mask); 281 act.sa_flags = 0; 282 sigaction(SIGALRM, &act, &oact); 283 alarm(TimeoutVal); 284 } 285 286 if (connect(fd, sock, socksz) < 0) { 287 if (TimeoutVal) { 288 alarm(0); 289 sigaction(SIGALRM, &oact, 0); 290 } 291 if (TimedOut) 292 fputs("Timeout: ", stderr); 293 fprintf(stderr, "Cannot connect to socket %s\n", argv[arg]); 294 close(fd); 295 return 3; 296 } 297 298 if (TimeoutVal) { 299 alarm(0); 300 sigaction(SIGALRM, &oact, 0); 301 } 302 303 len = 0; 304 Command[sizeof(Command)-1] = '\0'; 305 for (arg++; arg < argc; arg++) { 306 if (len && len < sizeof(Command)-1) 307 strcpy(Command+len++, " "); 308 strncpy(Command+len, argv[arg], sizeof(Command)-len-1); 309 len += strlen(Command+len); 310 } 311 312 switch (Receive(fd, verbose | REC_PASSWD)) 313 { 314 case 1: 315 fprintf(stderr, "Password incorrect\n"); 316 break; 317 318 case 0: 319 if (len == 0) { 320 EditLine *edit; 321 History *hist; 322 const char *l, *env; 323 int size; 324 325 hist = history_init(); 326 if ((env = getenv("EL_SIZE"))) { 327 size = atoi(env); 328 if (size < 0) 329 size = 20; 330 } else 331 size = 20; 332 history(hist, H_EVENT, size); 333 334 edit = el_init("pppctl", stdin, stdout); 335 el_source(edit, NULL); 336 el_set(edit, EL_PROMPT, GetPrompt); 337 if ((env = getenv("EL_EDITOR"))) 338 if (!strcmp(env, "vi")) 339 el_set(edit, EL_EDITOR, "vi"); 340 else if (!strcmp(env, "emacs")) 341 el_set(edit, EL_EDITOR, "emacs"); 342 el_set(edit, EL_SIGNAL, 1); 343 el_set(edit, EL_HIST, history, (const char *)hist); 344 while ((l = smartgets(edit, &len, fd))) { 345 if (len > 1) 346 history(hist, H_ENTER, l); 347 write(fd, l, len); 348 if (Receive(fd, REC_SHOW) != 0) 349 break; 350 } 351 fprintf(stderr, "Connection closed\n"); 352 el_end(edit); 353 history_end(hist); 354 } else { 355 start = Command; 356 do { 357 next = strchr(start, ';'); 358 while (*start == ' ' || *start == '\t') 359 start++; 360 if (next) 361 *next = '\0'; 362 strcpy(Buffer, start); 363 Buffer[sizeof(Buffer)-2] = '\0'; 364 strcat(Buffer, "\n"); 365 if (verbose) 366 write(1, Buffer, strlen(Buffer)); 367 write(fd, Buffer, strlen(Buffer)); 368 if (Receive(fd, verbose | REC_SHOW) != 0) { 369 fprintf(stderr, "Connection closed\n"); 370 break; 371 } 372 if (next) 373 start = ++next; 374 } while (next && *next); 375 if (verbose) 376 puts(""); 377 } 378 break; 379 380 default: 381 fprintf(stderr, "ppp is not responding\n"); 382 break; 383 } 384 385 close(fd); 386 387 return 0; 388} 389