|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: */ ! 17: ! 18: #ifndef lint ! 19: static char sccsid[] = "@(#)system.c 4.3 (Berkeley) 9/2/89"; ! 20: #endif /* not lint */ ! 21: ! 22: #include <sys/types.h> ! 23: ! 24: #if defined(pyr) ! 25: #define fd_set fdset_t ! 26: #endif /* defined(pyr) */ ! 27: ! 28: /* ! 29: * Wouldn't it be nice if these REALLY were in <sys/inode.h>? Or, ! 30: * equivalently, if <sys/inode.h> REALLY existed? ! 31: */ ! 32: #define IREAD 00400 ! 33: #define IWRITE 00200 ! 34: ! 35: #include <sys/file.h> ! 36: #include <sys/time.h> ! 37: #include <sys/socket.h> ! 38: #include <netinet/in.h> ! 39: #include <sys/wait.h> ! 40: ! 41: #include <errno.h> ! 42: extern int errno; ! 43: ! 44: #include <netdb.h> ! 45: #include <signal.h> ! 46: #include <stdio.h> ! 47: #include <pwd.h> ! 48: ! 49: #include "../general/general.h" ! 50: #include "../ctlr/api.h" ! 51: #include "../api/api_exch.h" ! 52: ! 53: #include "../general/globals.h" ! 54: ! 55: #ifndef FD_SETSIZE ! 56: /* ! 57: * The following is defined just in case someone should want to run ! 58: * this telnet on a 4.2 system. ! 59: * ! 60: */ ! 61: ! 62: #define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) ! 63: #define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) ! 64: #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) ! 65: #define FD_ZERO(p) ((p)->fds_bits[0] = 0) ! 66: ! 67: #endif ! 68: ! 69: static int shell_pid = 0; ! 70: static char key[50]; /* Actual key */ ! 71: static char *keyname; /* Name of file with key in it */ ! 72: ! 73: static char *ourENVlist[200]; /* Lots of room */ ! 74: ! 75: static int ! 76: sock = -1, /* Connected socket */ ! 77: serversock; /* Server (listening) socket */ ! 78: ! 79: static enum { DEAD, UNCONNECTED, CONNECTED } state; ! 80: ! 81: static long ! 82: storage_location; /* Address we have */ ! 83: static short ! 84: storage_length = 0; /* Length we have */ ! 85: static int ! 86: storage_must_send = 0, /* Storage belongs on other side of wire */ ! 87: storage_accessed = 0; /* The storage is accessed (so leave alone)! */ ! 88: ! 89: static long storage[1000]; ! 90: ! 91: static union REGS inputRegs; ! 92: static struct SREGS inputSregs; ! 93: ! 94: extern int apitrace; ! 95: ! 96: static void ! 97: kill_connection() ! 98: { ! 99: state = UNCONNECTED; ! 100: if (sock != -1) { ! 101: (void) close(sock); ! 102: sock = -1; ! 103: } ! 104: } ! 105: ! 106: ! 107: static int ! 108: nextstore() ! 109: { ! 110: struct storage_descriptor sd; ! 111: ! 112: if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { ! 113: storage_length = 0; ! 114: return -1; ! 115: } ! 116: storage_length = sd.length; ! 117: storage_location = sd.location; ! 118: if (storage_length > sizeof storage) { ! 119: fprintf(stderr, "API client tried to send too much storage (%d).\n", ! 120: storage_length); ! 121: storage_length = 0; ! 122: return -1; ! 123: } ! 124: if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage) ! 125: == -1) { ! 126: storage_length = 0; ! 127: return -1; ! 128: } ! 129: return 0; ! 130: } ! 131: ! 132: ! 133: static int ! 134: doreject(message) ! 135: char *message; ! 136: { ! 137: struct storage_descriptor sd; ! 138: int length = strlen(message); ! 139: ! 140: if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) { ! 141: return -1; ! 142: } ! 143: sd.length = length; ! 144: if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { ! 145: return -1; ! 146: } ! 147: if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) { ! 148: return -1; ! 149: } ! 150: return 0; ! 151: } ! 152: ! 153: ! 154: /* ! 155: * doassociate() ! 156: * ! 157: * Negotiate with the other side and try to do something. ! 158: * ! 159: * Returns: ! 160: * ! 161: * -1: Error in processing ! 162: * 0: Invalid password entered ! 163: * 1: Association OK ! 164: */ ! 165: ! 166: static int ! 167: doassociate() ! 168: { ! 169: struct passwd *pwent; ! 170: char ! 171: promptbuf[100], ! 172: buffer[200]; ! 173: struct storage_descriptor sd; ! 174: extern char *crypt(); ! 175: ! 176: if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { ! 177: return -1; ! 178: } ! 179: sd.length = sd.length; ! 180: if (sd.length > sizeof buffer) { ! 181: doreject("(internal error) Authentication key too long"); ! 182: return -1; ! 183: } ! 184: if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { ! 185: return -1; ! 186: } ! 187: buffer[sd.length] = 0; ! 188: ! 189: if (strcmp(buffer, key) != 0) { ! 190: #if (!defined(sun)) || defined(BSD) && (BSD >= 43) ! 191: extern uid_t geteuid(); ! 192: #endif /* (!defined(sun)) || defined(BSD) && (BSD >= 43) */ ! 193: ! 194: if ((pwent = getpwuid((int)geteuid())) == 0) { ! 195: return -1; ! 196: } ! 197: sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name); ! 198: if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) { ! 199: return -1; ! 200: } ! 201: sd.length = strlen(promptbuf); ! 202: if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) ! 203: == -1) { ! 204: return -1; ! 205: } ! 206: if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) ! 207: == -1) { ! 208: return -1; ! 209: } ! 210: sd.length = strlen(pwent->pw_name); ! 211: if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) ! 212: == -1) { ! 213: return -1; ! 214: } ! 215: if (api_exch_outtype(EXCH_TYPE_BYTES, ! 216: strlen(pwent->pw_name), pwent->pw_name) == -1) { ! 217: return -1; ! 218: } ! 219: if (api_exch_incommand(EXCH_CMD_AUTH) == -1) { ! 220: return -1; ! 221: } ! 222: if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) ! 223: == -1) { ! 224: return -1; ! 225: } ! 226: sd.length = sd.length; ! 227: if (sd.length > sizeof buffer) { ! 228: doreject("Password entered was too long"); ! 229: return -1; ! 230: } ! 231: if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { ! 232: return -1; ! 233: } ! 234: buffer[sd.length] = 0; ! 235: ! 236: /* Is this the correct password? */ ! 237: if (strlen(pwent->pw_name)) { ! 238: char *ptr; ! 239: int i; ! 240: ! 241: ptr = pwent->pw_name; ! 242: i = 0; ! 243: while (i < sd.length) { ! 244: buffer[i++] ^= *ptr++; ! 245: if (*ptr == 0) { ! 246: ptr = pwent->pw_name; ! 247: } ! 248: } ! 249: } ! 250: if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) != 0) { ! 251: doreject("Invalid password"); ! 252: sleep(10); /* Don't let us do too many of these */ ! 253: return 0; ! 254: } ! 255: } ! 256: if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) { ! 257: return -1; ! 258: } else { ! 259: return 1; ! 260: } ! 261: } ! 262: ! 263: ! 264: void ! 265: freestorage() ! 266: { ! 267: struct storage_descriptor sd; ! 268: ! 269: if (storage_accessed) { ! 270: fprintf(stderr, "Internal error - attempt to free accessed storage.\n"); ! 271: fprintf(stderr, "(Encountered in file %s at line %d.)\n", ! 272: __FILE__, __LINE__); ! 273: quit(); ! 274: } ! 275: if (storage_must_send == 0) { ! 276: return; ! 277: } ! 278: storage_must_send = 0; ! 279: if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) { ! 280: kill_connection(); ! 281: return; ! 282: } ! 283: sd.length = storage_length; ! 284: sd.location = storage_location; ! 285: if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { ! 286: kill_connection(); ! 287: return; ! 288: } ! 289: if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage) ! 290: == -1) { ! 291: kill_connection(); ! 292: return; ! 293: } ! 294: } ! 295: ! 296: ! 297: static int ! 298: getstorage(address, length, copyin) ! 299: long ! 300: address; ! 301: int ! 302: length, ! 303: copyin; ! 304: { ! 305: struct storage_descriptor sd; ! 306: ! 307: freestorage(); ! 308: if (storage_accessed) { ! 309: fprintf(stderr, ! 310: "Internal error - attempt to get while storage accessed.\n"); ! 311: fprintf(stderr, "(Encountered in file %s at line %d.)\n", ! 312: __FILE__, __LINE__); ! 313: quit(); ! 314: } ! 315: storage_must_send = 0; ! 316: if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) { ! 317: kill_connection(); ! 318: return -1; ! 319: } ! 320: storage_location = address; ! 321: storage_length = length; ! 322: if (copyin) { ! 323: sd.location = (long)storage_location; ! 324: sd.length = storage_length; ! 325: if (api_exch_outtype(EXCH_TYPE_STORE_DESC, ! 326: sizeof sd, (char *)&sd) == -1) { ! 327: kill_connection(); ! 328: return -1; ! 329: } ! 330: if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) { ! 331: fprintf(stderr, "Bad data from other side.\n"); ! 332: fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__); ! 333: return -1; ! 334: } ! 335: if (nextstore() == -1) { ! 336: kill_connection(); ! 337: return -1; ! 338: } ! 339: } ! 340: return 0; ! 341: } ! 342: ! 343: /*ARGSUSED*/ ! 344: void ! 345: movetous(local, es, di, length) ! 346: char ! 347: *local; ! 348: unsigned int ! 349: es, ! 350: di; ! 351: int ! 352: length; ! 353: { ! 354: long where = SEG_OFF_BACK(es, di); ! 355: ! 356: if (length > sizeof storage) { ! 357: fprintf(stderr, "Internal API error - movetous() length too long.\n"); ! 358: fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); ! 359: quit(); ! 360: } else if (length == 0) { ! 361: return; ! 362: } ! 363: getstorage(where, length, 1); ! 364: memcpy(local, (char *)(storage+((where-storage_location))), length); ! 365: if (apitrace) { ! 366: Dump('(', local, length); ! 367: } ! 368: } ! 369: ! 370: /*ARGSUSED*/ ! 371: void ! 372: movetothem(es, di, local, length) ! 373: unsigned int ! 374: es, ! 375: di; ! 376: char ! 377: *local; ! 378: int ! 379: length; ! 380: { ! 381: long where = SEG_OFF_BACK(es, di); ! 382: ! 383: if (length > sizeof storage) { ! 384: fprintf(stderr, "Internal API error - movetothem() length too long.\n"); ! 385: fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__); ! 386: quit(); ! 387: } else if (length == 0) { ! 388: return; ! 389: } ! 390: freestorage(); ! 391: memcpy((char *)storage, local, length); ! 392: if (apitrace) { ! 393: Dump(')', local, length); ! 394: } ! 395: storage_length = length; ! 396: storage_location = where; ! 397: storage_must_send = 1; ! 398: } ! 399: ! 400: ! 401: char * ! 402: access_api(location, length, copyin) ! 403: char * ! 404: location; ! 405: int ! 406: length, ! 407: copyin; /* Do we need to copy in initially? */ ! 408: { ! 409: if (storage_accessed) { ! 410: fprintf(stderr, "Internal error - storage accessed twice\n"); ! 411: fprintf(stderr, "(Encountered in file %s, line %d.)\n", ! 412: __FILE__, __LINE__); ! 413: quit(); ! 414: } else if (length != 0) { ! 415: freestorage(); ! 416: getstorage((long)location, length, copyin); ! 417: storage_accessed = 1; ! 418: } ! 419: return (char *) storage; ! 420: } ! 421: ! 422: /*ARGSUSED*/ ! 423: void ! 424: unaccess_api(location, local, length, copyout) ! 425: char *location; ! 426: char *local; ! 427: int length; ! 428: int copyout; ! 429: { ! 430: if (storage_accessed == 0) { ! 431: fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n"); ! 432: fprintf(stderr, "(Encountered in file %s, line %d.)\n", ! 433: __FILE__, __LINE__); ! 434: quit(); ! 435: } ! 436: storage_accessed = 0; ! 437: storage_must_send = copyout; /* if needs to go back */ ! 438: } ! 439: ! 440: /* ! 441: * Accept a connection from an API client, aborting if the child dies. ! 442: */ ! 443: ! 444: static int ! 445: doconnect() ! 446: { ! 447: fd_set fdset; ! 448: int i; ! 449: ! 450: sock = -1; ! 451: FD_ZERO(&fdset); ! 452: while (shell_active && (sock == -1)) { ! 453: FD_SET(serversock, &fdset); ! 454: if ((i = select(serversock+1, &fdset, ! 455: (fd_set *)0, (fd_set *)0, (struct timeval *)0)) < 0) { ! 456: if (errno = EINTR) { ! 457: continue; ! 458: } else { ! 459: perror("in select waiting for API connection"); ! 460: return -1; ! 461: } ! 462: } else { ! 463: i = accept(serversock, (struct sockaddr *)0, (int *)0); ! 464: if (i == -1) { ! 465: perror("accepting API connection"); ! 466: return -1; ! 467: } ! 468: sock = i; ! 469: } ! 470: } ! 471: /* If the process has already exited, we may need to close */ ! 472: if ((shell_active == 0) && (sock != -1)) { ! 473: extern void setcommandmode(); ! 474: ! 475: (void) close(sock); ! 476: sock = -1; ! 477: setcommandmode(); /* In case child_died sneaked in */ ! 478: } ! 479: return 0; ! 480: } ! 481: ! 482: /* ! 483: * shell_continue() actually runs the command, and looks for API ! 484: * requests coming back in. ! 485: * ! 486: * We are called from the main loop in telnet.c. ! 487: */ ! 488: ! 489: int ! 490: shell_continue() ! 491: { ! 492: int i; ! 493: ! 494: switch (state) { ! 495: case DEAD: ! 496: pause(); /* Nothing to do */ ! 497: break; ! 498: case UNCONNECTED: ! 499: if (doconnect() == -1) { ! 500: kill_connection(); ! 501: return -1; ! 502: } ! 503: /* At this point, it is possible that we've gone away */ ! 504: if (shell_active == 0) { ! 505: kill_connection(); ! 506: return -1; ! 507: } ! 508: if (api_exch_init(sock, "server") == -1) { ! 509: return -1; ! 510: } ! 511: while (state == UNCONNECTED) { ! 512: if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) { ! 513: kill_connection(); ! 514: return -1; ! 515: } else { ! 516: switch (doassociate()) { ! 517: case -1: ! 518: kill_connection(); ! 519: return -1; ! 520: case 0: ! 521: break; ! 522: case 1: ! 523: state = CONNECTED; ! 524: } ! 525: } ! 526: } ! 527: break; ! 528: case CONNECTED: ! 529: switch (i = api_exch_nextcommand()) { ! 530: case EXCH_CMD_REQUEST: ! 531: if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs, ! 532: (char *)&inputRegs) == -1) { ! 533: kill_connection(); ! 534: } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs, ! 535: (char *)&inputSregs) == -1) { ! 536: kill_connection(); ! 537: } else if (nextstore() == -1) { ! 538: kill_connection(); ! 539: } else { ! 540: handle_api(&inputRegs, &inputSregs); ! 541: freestorage(); /* Send any storage back */ ! 542: if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) { ! 543: kill_connection(); ! 544: } else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs, ! 545: (char *)&inputRegs) == -1) { ! 546: kill_connection(); ! 547: } else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs, ! 548: (char *)&inputSregs) == -1) { ! 549: kill_connection(); ! 550: } ! 551: /* Done, and it all worked! */ ! 552: } ! 553: break; ! 554: case EXCH_CMD_DISASSOCIATE: ! 555: kill_connection(); ! 556: break; ! 557: default: ! 558: if (i != -1) { ! 559: fprintf(stderr, ! 560: "Looking for a REQUEST or DISASSOCIATE command\n"); ! 561: fprintf(stderr, "\treceived 0x%02x.\n", i); ! 562: } ! 563: kill_connection(); ! 564: break; ! 565: } ! 566: } ! 567: return shell_active; ! 568: } ! 569: ! 570: ! 571: static int ! 572: child_died() ! 573: { ! 574: union wait status; ! 575: register int pid; ! 576: ! 577: while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) { ! 578: if (pid == shell_pid) { ! 579: char inputbuffer[100]; ! 580: extern void setconnmode(); ! 581: extern void ConnectScreen(); ! 582: ! 583: shell_active = 0; ! 584: if (sock != -1) { ! 585: (void) close(sock); ! 586: sock = -1; ! 587: } ! 588: printf("[Hit return to continue]"); ! 589: fflush(stdout); ! 590: (void) gets(inputbuffer); ! 591: setconnmode(); ! 592: ConnectScreen(); /* Turn screen on (if need be) */ ! 593: (void) close(serversock); ! 594: (void) unlink(keyname); ! 595: } ! 596: } ! 597: signal(SIGCHLD, child_died); ! 598: } ! 599: ! 600: ! 601: /* ! 602: * Called from telnet.c to fork a lower command.com. We ! 603: * use the spint... routines so that we can pick up ! 604: * interrupts generated by application programs. ! 605: */ ! 606: ! 607: ! 608: int ! 609: shell(argc,argv) ! 610: int argc; ! 611: char *argv[]; ! 612: { ! 613: int length; ! 614: struct sockaddr_in server; ! 615: char sockNAME[100]; ! 616: static char **whereAPI = 0; ! 617: int fd; ! 618: struct timeval tv; ! 619: long ikey; ! 620: extern long random(); ! 621: extern char *mktemp(); ! 622: extern char *strcpy(); ! 623: ! 624: /* First, create verification file. */ ! 625: do { ! 626: keyname = mktemp("/tmp/apiXXXXXX"); ! 627: fd = open(keyname, O_RDWR|O_CREAT|O_EXCL, IREAD|IWRITE); ! 628: } while ((fd == -1) && (errno == EEXIST)); ! 629: ! 630: if (fd == -1) { ! 631: perror("open"); ! 632: return 0; ! 633: } ! 634: ! 635: /* Now, get seed for random */ ! 636: ! 637: if (gettimeofday(&tv, (struct timezone *)0) == -1) { ! 638: perror("gettimeofday"); ! 639: return 0; ! 640: } ! 641: srandom(tv.tv_usec); /* seed random number generator */ ! 642: do { ! 643: ikey = random(); ! 644: } while (ikey == 0); ! 645: sprintf(key, "%lu\n", (unsigned long) ikey); ! 646: if (write(fd, key, strlen(key)) != strlen(key)) { ! 647: perror("write"); ! 648: return 0; ! 649: } ! 650: key[strlen(key)-1] = 0; /* Get rid of newline */ ! 651: ! 652: if (close(fd) == -1) { ! 653: perror("close"); ! 654: return 0; ! 655: } ! 656: ! 657: /* Next, create the socket which will be connected to */ ! 658: serversock = socket(AF_INET, SOCK_STREAM, 0); ! 659: if (serversock < 0) { ! 660: perror("opening API socket"); ! 661: return 0; ! 662: } ! 663: server.sin_family = AF_INET; ! 664: server.sin_addr.s_addr = INADDR_ANY; ! 665: server.sin_port = 0; ! 666: if (bind(serversock, (struct sockaddr *)&server, sizeof server) < 0) { ! 667: perror("binding API socket"); ! 668: return 0; ! 669: } ! 670: length = sizeof server; ! 671: if (getsockname(serversock, (struct sockaddr *)&server, &length) < 0) { ! 672: perror("getting API socket name"); ! 673: (void) close(serversock); ! 674: } ! 675: listen(serversock, 1); ! 676: /* Get name to advertise in address list */ ! 677: strcpy(sockNAME, "API3270="); ! 678: gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME)); ! 679: if (strlen(sockNAME) > (sizeof sockNAME-(10+strlen(keyname)))) { ! 680: fprintf(stderr, "Local hostname too large; using 'localhost'.\n"); ! 681: strcpy(sockNAME, "localhost"); ! 682: } ! 683: sprintf(sockNAME+strlen(sockNAME), ":%u", ntohs(server.sin_port)); ! 684: sprintf(sockNAME+strlen(sockNAME), ":%s", keyname); ! 685: ! 686: if (whereAPI == 0) { ! 687: char **ptr, **nextenv; ! 688: extern char **environ; ! 689: ! 690: ptr = environ; ! 691: nextenv = ourENVlist; ! 692: while (*ptr) { ! 693: if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) { ! 694: fprintf(stderr, "Too many environmental variables\n"); ! 695: break; ! 696: } ! 697: *nextenv++ = *ptr++; ! 698: } ! 699: whereAPI = nextenv++; ! 700: *nextenv++ = 0; ! 701: environ = ourENVlist; /* New environment */ ! 702: } ! 703: *whereAPI = sockNAME; ! 704: ! 705: child_died(); /* Start up signal handler */ ! 706: shell_active = 1; /* We are running down below */ ! 707: if (shell_pid = vfork()) { ! 708: if (shell_pid == -1) { ! 709: perror("vfork"); ! 710: (void) close(serversock); ! 711: } else { ! 712: state = UNCONNECTED; ! 713: } ! 714: } else { /* New process */ ! 715: register int i; ! 716: ! 717: for (i = 3; i < 30; i++) { ! 718: (void) close(i); ! 719: } ! 720: if (argc == 1) { /* Just get a shell */ ! 721: char *cmdname; ! 722: extern char *getenv(); ! 723: ! 724: cmdname = getenv("SHELL"); ! 725: execlp(cmdname, cmdname, 0); ! 726: perror("Exec'ing new shell...\n"); ! 727: exit(1); ! 728: } else { ! 729: execvp(argv[1], &argv[1]); ! 730: perror("Exec'ing command.\n"); ! 731: exit(1); ! 732: } ! 733: /*NOTREACHED*/ ! 734: } ! 735: return shell_active; /* Go back to main loop */ ! 736: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.