home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / tn3270 / sys_curses / system.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-26  |  17.6 KB  |  754 lines

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