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