Annotation of 43BSDTahoe/ucb/tn3270/sys_curses/system.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.