pppctl.c revision 31829
1/* 2 * $Id: pppctl.c,v 1.11 1997/12/17 00:26:58 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 ifsun.sun_len = strlen(argv[arg]); 214 if (ifsun.sun_len > sizeof ifsun.sun_path - 1) { 215 fprintf(stderr, "%s: Path too long\n", argv[arg]); 216 return 1; 217 } 218 ifsun.sun_family = AF_LOCAL; 219 strcpy(ifsun.sun_path, argv[arg]); 220 221 if (fd = socket(AF_LOCAL, SOCK_STREAM, 0), fd < 0) { 222 fprintf(stderr, "Cannot create local domain socket\n"); 223 return 2; 224 } 225 } else { 226 char *port, *host, *colon; 227 int hlen; 228 229 colon = strchr(argv[arg], ':'); 230 if (colon) { 231 port = colon + 1; 232 *colon = '\0'; 233 host = argv[arg]; 234 } else { 235 port = argv[arg]; 236 host = "127.0.0.1"; 237 } 238 sock = (struct sockaddr *)&ifsin; 239 socksz = sizeof ifsin; 240 hlen = strlen(host); 241 242 if (strspn(host, "0123456789.") == hlen) { 243 if (!inet_aton(host, &ifsin.sin_addr)) { 244 fprintf(stderr, "Cannot translate %s\n", host); 245 return 1; 246 } 247 } else if ((h = gethostbyname(host)) == 0) { 248 fprintf(stderr, "Cannot resolve %s\n", host); 249 return 1; 250 } 251 else 252 ifsin.sin_addr.s_addr = *(u_long *)h->h_addr_list[0]; 253 254 if (colon) 255 *colon = ':'; 256 257 if (strspn(port, "0123456789") == strlen(port)) 258 ifsin.sin_port = htons(atoi(port)); 259 else if (s = getservbyname(port, "tcp"), !s) { 260 fprintf(stderr, "%s isn't a valid port or service!\n", port); 261 return Usage(); 262 } 263 else 264 ifsin.sin_port = s->s_port; 265 266 ifsin.sin_len = sizeof(ifsin); 267 ifsin.sin_family = AF_INET; 268 269 if (fd = socket(AF_INET, SOCK_STREAM, 0), fd < 0) { 270 fprintf(stderr, "Cannot create internet socket\n"); 271 return 2; 272 } 273 } 274 275 TimedOut = 0; 276 if (TimeoutVal) { 277 act.sa_handler = Timeout; 278 sigemptyset(&act.sa_mask); 279 act.sa_flags = 0; 280 sigaction(SIGALRM, &act, &oact); 281 alarm(TimeoutVal); 282 } 283 284 if (connect(fd, sock, socksz) < 0) { 285 if (TimeoutVal) { 286 alarm(0); 287 sigaction(SIGALRM, &oact, 0); 288 } 289 if (TimedOut) 290 fputs("Timeout: ", stderr); 291 fprintf(stderr, "Cannot connect to socket %s\n", argv[arg]); 292 close(fd); 293 return 3; 294 } 295 296 if (TimeoutVal) { 297 alarm(0); 298 sigaction(SIGALRM, &oact, 0); 299 } 300 301 len = 0; 302 Command[sizeof(Command)-1] = '\0'; 303 for (arg++; arg < argc; arg++) { 304 if (len && len < sizeof(Command)-1) 305 strcpy(Command+len++, " "); 306 strncpy(Command+len, argv[arg], sizeof(Command)-len-1); 307 len += strlen(Command+len); 308 } 309 310 switch (Receive(fd, verbose | REC_PASSWD)) 311 { 312 case 1: 313 fprintf(stderr, "Password incorrect\n"); 314 break; 315 316 case 0: 317 if (len == 0) { 318 EditLine *edit; 319 History *hist; 320 const char *l, *env; 321 int size; 322 323 hist = history_init(); 324 if ((env = getenv("EL_SIZE"))) { 325 size = atoi(env); 326 if (size < 0) 327 size = 20; 328 } else 329 size = 20; 330 history(hist, H_EVENT, size); 331 332 edit = el_init("pppctl", stdin, stdout); 333 el_source(edit, NULL); 334 el_set(edit, EL_PROMPT, GetPrompt); 335 if ((env = getenv("EL_EDITOR"))) 336 if (!strcmp(env, "vi")) 337 el_set(edit, EL_EDITOR, "vi"); 338 else if (!strcmp(env, "emacs")) 339 el_set(edit, EL_EDITOR, "emacs"); 340 el_set(edit, EL_SIGNAL, 1); 341 el_set(edit, EL_HIST, history, (const char *)hist); 342 while ((l = smartgets(edit, &len, fd))) { 343 if (len > 1) 344 history(hist, H_ENTER, l); 345 write(fd, l, len); 346 if (Receive(fd, REC_SHOW) != 0) 347 break; 348 } 349 fprintf(stderr, "Connection closed\n"); 350 el_end(edit); 351 history_end(hist); 352 } else { 353 start = Command; 354 do { 355 next = strchr(start, ';'); 356 while (*start == ' ' || *start == '\t') 357 start++; 358 if (next) 359 *next = '\0'; 360 strcpy(Buffer, start); 361 Buffer[sizeof(Buffer)-2] = '\0'; 362 strcat(Buffer, "\n"); 363 if (verbose) 364 write(1, Buffer, strlen(Buffer)); 365 write(fd, Buffer, strlen(Buffer)); 366 if (Receive(fd, verbose | REC_SHOW) != 0) { 367 fprintf(stderr, "Connection closed\n"); 368 break; 369 } 370 if (next) 371 start = ++next; 372 } while (next && *next); 373 if (verbose) 374 puts(""); 375 } 376 break; 377 378 default: 379 fprintf(stderr, "ppp is not responding\n"); 380 break; 381 } 382 383 close(fd); 384 385 return 0; 386} 387