131457Sminshall #include <sys/types.h>
231457Sminshall #include <sys/socket.h>
331457Sminshall #include <netinet/in.h>
431455Sminshall #include <sys/wait.h>
531455Sminshall 
631457Sminshall #include <errno.h>
731457Sminshall extern int errno;
831457Sminshall 
931457Sminshall #include <netdb.h>
1031457Sminshall #include <signal.h>
1131455Sminshall #include <stdio.h>
1231457Sminshall #include <pwd.h>
1331455Sminshall 
1431455Sminshall #include "../general/general.h"
1531455Sminshall #include "../api/api.h"
1631463Sminshall #include "../apilib/api_exch.h"
1731455Sminshall 
1831455Sminshall #include "../general/globals.h"
1931455Sminshall 
2031455Sminshall 
2131455Sminshall static int shell_pid = 0;
2231455Sminshall 
2331457Sminshall static char *ourENVlist[200];		/* Lots of room */
2431457Sminshall 
2531465Sminshall static int
2631465Sminshall     sock = -1,				/* Connected socket */
2731465Sminshall     serversock;				/* Server (listening) socket */
2831457Sminshall 
2931457Sminshall static enum { DEAD, UNCONNECTED, CONNECTED } state;
3031457Sminshall 
3131455Sminshall static int
3231463Sminshall     storage_location,		/* Address we have */
3331457Sminshall     storage_length = 0,		/* Length we have */
3431457Sminshall     storage_must_send = 0,	/* Storage belongs on other side of wire */
3531457Sminshall     storage_accessed = 0;	/* The storage is accessed (so leave alone)! */
3631457Sminshall 
3731503Sminshall static long storage[1000];
3831457Sminshall 
3931463Sminshall static union REGS inputRegs;
4031463Sminshall static struct SREGS inputSregs;
4131457Sminshall 
4231463Sminshall 
4331463Sminshall static void
4431457Sminshall kill_connection()
4531457Sminshall {
4631465Sminshall     state = UNCONNECTED;
4731465Sminshall     if (sock != -1) {
4831465Sminshall 	(void) close(sock);
4931465Sminshall 	sock = -1;
5031465Sminshall     }
5131457Sminshall }
5231457Sminshall 
5331457Sminshall 
5431457Sminshall static int
5531463Sminshall nextstore()
5631455Sminshall {
5731463Sminshall     struct storage_descriptor sd;
5831455Sminshall 
5931463Sminshall     if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
6031457Sminshall 	storage_length = 0;
6131457Sminshall 	return -1;
6231457Sminshall     }
6331463Sminshall     storage_length = ntohs(sd.length);
6431463Sminshall     storage_location = ntohl(sd.location);
6531463Sminshall     if (storage_length > sizeof storage) {
6631457Sminshall 	fprintf(stderr, "API client tried to send too much storage (%d).\n",
6731457Sminshall 		storage_length);
6831463Sminshall 	storage_length = 0;
6931457Sminshall 	return -1;
7031457Sminshall     }
7131471Sminshall     if (storage_length != 0) {
7231471Sminshall 	if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage)
7331471Sminshall 							    == -1) {
7431471Sminshall 	    storage_length = 0;
7531471Sminshall 	    return -1;
7631471Sminshall 	}
7731463Sminshall     }
7831471Sminshall     return 0;
7931457Sminshall }
8031457Sminshall 
8131457Sminshall 
8231457Sminshall static int
8331457Sminshall doreject(message)
8431457Sminshall char	*message;
8531457Sminshall {
8631463Sminshall     struct storage_descriptor sd;
8731457Sminshall     int length = strlen(message);
8831457Sminshall 
8931492Sminshall     if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) {
9031457Sminshall 	return -1;
9131457Sminshall     }
9231463Sminshall     sd.length = htons(length);
9331465Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
9431463Sminshall 	return -1;
9531463Sminshall     }
9631463Sminshall     if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) {
9731463Sminshall 	return -1;
9831463Sminshall     }
9931457Sminshall     return 0;
10031457Sminshall }
10131457Sminshall 
10231457Sminshall 
10331455Sminshall /*
10431465Sminshall  * doassociate()
10531457Sminshall  *
10631457Sminshall  * Negotiate with the other side and try to do something.
10731457Sminshall  */
10831457Sminshall 
10931457Sminshall static int
11031465Sminshall doassociate()
11131457Sminshall {
11231457Sminshall     struct passwd *pwent;
11331457Sminshall     char
11431457Sminshall 	promptbuf[100],
11531457Sminshall 	buffer[200];
11631457Sminshall     int length;
11731457Sminshall     int was;
11831463Sminshall     struct storage_descriptor sd;
11931457Sminshall 
12031457Sminshall     if ((pwent = getpwuid(geteuid())) == 0) {
12131457Sminshall 	return -1;
12231457Sminshall     }
12331457Sminshall     sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name);
12431492Sminshall     if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) {
12531465Sminshall 	return -1;
12631465Sminshall     }
12731465Sminshall     sd.length = htons(strlen(promptbuf));
12831465Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
12931465Sminshall 	return -1;
13031465Sminshall     }
13131465Sminshall     if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) == -1) {
13231465Sminshall 	return -1;
13331465Sminshall     }
13431465Sminshall     sd.length = htons(strlen(pwent->pw_name));
13531465Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
13631465Sminshall 	return -1;
13731465Sminshall     }
13831465Sminshall     if (api_exch_outtype(EXCH_TYPE_BYTES,
13931465Sminshall 			strlen(pwent->pw_name), pwent->pw_name) == -1) {
14031465Sminshall 	return -1;
14131465Sminshall     }
14231492Sminshall     if (api_exch_incommand(EXCH_CMD_AUTH) == -1) {
14331457Sminshall 	return -1;
14431457Sminshall     }
14531463Sminshall     if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
14631463Sminshall 	return -1;
14731457Sminshall     }
14831463Sminshall     sd.length = ntohs(sd.length);
14931463Sminshall     if (sd.length > sizeof buffer) {
15031457Sminshall 	doreject("Password entered was too long");
15131465Sminshall 	return -1;
15231457Sminshall     }
15331463Sminshall     if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
15431457Sminshall 	return -1;
15531457Sminshall     }
15631463Sminshall     buffer[sd.length] = 0;
15731457Sminshall 
15831457Sminshall     /* Is this the correct password? */
15931465Sminshall     if (strlen(pwent->pw_name)) {
16031465Sminshall 	char *ptr;
16131465Sminshall 	int i;
16231465Sminshall 
16331465Sminshall 	ptr = pwent->pw_name;
16431465Sminshall 	i = 0;
16531465Sminshall 	while (i < sd.length) {
16631465Sminshall 	    buffer[i++] ^= *ptr++;
16731465Sminshall 	    if (*ptr == 0) {
16831465Sminshall 		ptr = pwent->pw_name;
16931465Sminshall 	    }
17031465Sminshall 	}
17131465Sminshall     }
17231457Sminshall     if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) == 0) {
17331492Sminshall 	if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) {
17431465Sminshall 	    return -1;
17531471Sminshall 	} else {
17631471Sminshall 	    return 1;
17731465Sminshall 	}
17831457Sminshall     } else {
17931457Sminshall 	doreject("Invalid password");
18031457Sminshall 	sleep(10);		/* Don't let us do too many of these */
18131471Sminshall 	return 0;
18231457Sminshall     }
18331457Sminshall }
18431457Sminshall 
18531457Sminshall 
18631457Sminshall void
18731457Sminshall freestorage()
18831457Sminshall {
18931457Sminshall     char buffer[40];
19031463Sminshall     struct storage_descriptor sd;
19131457Sminshall 
19231457Sminshall     if (storage_accessed) {
19331457Sminshall 	fprintf(stderr, "Internal error - attempt to free accessed storage.\n");
19431503Sminshall 	fprintf(stderr, "(Encountered in file %s at line %d.)\n",
19531457Sminshall 			__FILE__, __LINE__);
19631457Sminshall 	quit();
19731457Sminshall     }
19831457Sminshall     if (storage_must_send == 0) {
19931457Sminshall 	return;
20031457Sminshall     }
20131457Sminshall     storage_must_send = 0;
20231492Sminshall     if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) {
20331457Sminshall 	kill_connection();
20431457Sminshall 	return;
20531457Sminshall     }
20631463Sminshall     sd.length = htons(storage_length);
20731463Sminshall     sd.location = htonl(storage_location);
20831463Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
20931457Sminshall 	kill_connection();
21031457Sminshall 	return;
21131457Sminshall     }
21231471Sminshall     if (storage_length != 0) {
21331471Sminshall 	if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage)
21431471Sminshall 								== -1) {
21531471Sminshall 	    kill_connection();
21631471Sminshall 	    return;
21731471Sminshall 	}
21831463Sminshall     }
21931457Sminshall }
22031457Sminshall 
22131457Sminshall 
22231463Sminshall static int
223*31508Sminshall getstorage(address, length, copyin)
224*31508Sminshall int
225*31508Sminshall     address,
226*31508Sminshall     length,
227*31508Sminshall     copyin;
22831457Sminshall {
22931463Sminshall     struct storage_descriptor sd;
23031457Sminshall     char buffer[40];
23131457Sminshall 
23231457Sminshall     freestorage();
23331457Sminshall     if (storage_accessed) {
23431457Sminshall 	fprintf(stderr,
23531457Sminshall 		"Internal error - attempt to get while storage accessed.\n");
23631503Sminshall 	fprintf(stderr, "(Encountered in file %s at line %d.)\n",
23731457Sminshall 			__FILE__, __LINE__);
23831457Sminshall 	quit();
23931457Sminshall     }
24031457Sminshall     storage_must_send = 0;
24131492Sminshall     if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) {
24231457Sminshall 	kill_connection();
24331463Sminshall 	return -1;
24431457Sminshall     }
24531471Sminshall     storage_location = address;
24631471Sminshall     storage_length = length;
247*31508Sminshall     if (copyin) {
248*31508Sminshall 	sd.location = htonl(storage_location);
249*31508Sminshall 	sd.length = htons(storage_length);
250*31508Sminshall 	if (api_exch_outtype(EXCH_TYPE_STORE_DESC,
251*31508Sminshall 					sizeof sd, (char *)&sd) == -1) {
252*31508Sminshall 	    kill_connection();
253*31508Sminshall 	    return -1;
254*31508Sminshall 	}
255*31508Sminshall 	if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) {
256*31508Sminshall 	    fprintf(stderr, "Bad data from other side.\n");
257*31508Sminshall 	    fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__);
258*31508Sminshall 	    return -1;
259*31508Sminshall 	}
260*31508Sminshall 	if (nextstore() == -1) {
261*31508Sminshall 	    kill_connection();
262*31508Sminshall 	    return -1;
263*31508Sminshall 	}
26431463Sminshall     }
26531463Sminshall     return 0;
26631457Sminshall }
26731457Sminshall 
26831457Sminshall void
26931457Sminshall movetous(local, es, di, length)
27031457Sminshall char
27131457Sminshall     *local;
27231457Sminshall int
27331457Sminshall     es,
27431457Sminshall     di;
27531457Sminshall int
27631457Sminshall     length;
27731457Sminshall {
27831457Sminshall     if (length > sizeof storage) {
27931457Sminshall 	fprintf(stderr, "Internal API error - movetous() length too long.\n");
28031457Sminshall 	fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
28131457Sminshall 	quit();
28231457Sminshall     } else if (length == 0) {
28331457Sminshall 	return;
28431457Sminshall     }
285*31508Sminshall     getstorage(di, length, 1);
28631463Sminshall     memcpy(local, storage+(di-storage_location), length);
28731457Sminshall }
28831457Sminshall 
28931457Sminshall void
29031457Sminshall movetothem(es, di, local, length)
29131457Sminshall int
29231457Sminshall     es,
29331457Sminshall     di;
29431457Sminshall char
29531457Sminshall     *local;
29631457Sminshall int
29731457Sminshall     length;
29831457Sminshall {
29931457Sminshall     if (length > sizeof storage) {
30031457Sminshall 	fprintf(stderr, "Internal API error - movetothem() length too long.\n");
30131457Sminshall 	fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
30231457Sminshall 	quit();
30331457Sminshall     } else if (length == 0) {
30431457Sminshall 	return;
30531457Sminshall     }
30631457Sminshall     freestorage();
30731457Sminshall     memcpy((char *)storage, local, length);
30831457Sminshall     storage_length = length;
30931463Sminshall     storage_location = di;
31031457Sminshall     storage_must_send = 1;
31131457Sminshall }
31231457Sminshall 
31331457Sminshall 
31431457Sminshall char *
315*31508Sminshall access_api(location, length, copyin)
31631457Sminshall int
31731457Sminshall     location,
318*31508Sminshall     length,
319*31508Sminshall     copyin;			/* Do we need to copy in initially? */
32031457Sminshall {
32131457Sminshall     if (storage_accessed) {
32231457Sminshall 	fprintf(stderr, "Internal error - storage accessed twice\n");
32331503Sminshall 	fprintf(stderr, "(Encountered in file %s, line %d.)\n",
32431457Sminshall 				__FILE__, __LINE__);
32531457Sminshall 	quit();
32631457Sminshall     } else if (length != 0) {
32731457Sminshall 	freestorage();
328*31508Sminshall 	getstorage(location, length, copyin);
32931503Sminshall 	storage_accessed = 1;
33031457Sminshall     }
33131457Sminshall     return (char *) storage;
33231457Sminshall }
33331457Sminshall 
334*31508Sminshall unaccess_api(location, local, length, copyout)
33531457Sminshall int	location;
33631457Sminshall char	*local;
33731457Sminshall int	length;
33831457Sminshall {
33931457Sminshall     if (storage_accessed == 0) {
34031457Sminshall 	fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n");
34131503Sminshall 	fprintf(stderr, "(Encountered in file %s, line %d.)\n",
34231457Sminshall 			__FILE__, __LINE__);
34331457Sminshall 	quit();
34431457Sminshall     }
34531457Sminshall     storage_accessed = 0;
346*31508Sminshall     storage_must_send = copyout;	/* if needs to go back */
34731457Sminshall }
34831457Sminshall 
34931465Sminshall /*
35031465Sminshall  * Accept a connection from an API client, aborting if the child dies.
35131465Sminshall  */
35231457Sminshall 
35331465Sminshall static int
35431465Sminshall doconnect()
35531465Sminshall {
35631465Sminshall     fd_set fdset;
35731465Sminshall     int i;
35831465Sminshall 
35931465Sminshall     sock = -1;
36031465Sminshall     FD_ZERO(&fdset);
36131465Sminshall     while (shell_active && (sock == -1)) {
36231465Sminshall 	FD_SET(serversock, &fdset);
36331465Sminshall 	if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) {
36431465Sminshall 	    if (errno = EINTR) {
36531465Sminshall 		continue;
36631465Sminshall 	    } else {
36731465Sminshall 		perror("in select waiting for API connection");
36831465Sminshall 		return -1;
36931465Sminshall 	    }
37031465Sminshall 	} else {
37131465Sminshall 	    i = accept(serversock, 0, 0);
37231465Sminshall 	    if (i == -1) {
37331465Sminshall 		perror("accepting API connection");
37431465Sminshall 		return -1;
37531465Sminshall 	    }
37631465Sminshall 	    sock = i;
37731465Sminshall 	}
37831465Sminshall     }
37931465Sminshall     /* If the process has already exited, we may need to close */
38031465Sminshall     if ((shell_active == 0) && (sock != -1)) {
38131465Sminshall 	(void) close(sock);
38231465Sminshall 	sock = -1;
38331465Sminshall 	setcommandmode();	/* In case child_died sneaked in */
38431465Sminshall     }
38531465Sminshall }
38631465Sminshall 
38731457Sminshall /*
38831455Sminshall  * shell_continue() actually runs the command, and looks for API
38931455Sminshall  * requests coming back in.
39031455Sminshall  *
39131455Sminshall  * We are called from the main loop in telnet.c.
39231455Sminshall  */
39331455Sminshall 
39431455Sminshall int
39531455Sminshall shell_continue()
39631455Sminshall {
39731492Sminshall     int i;
39831492Sminshall 
39931457Sminshall     switch (state) {
40031457Sminshall     case DEAD:
40131457Sminshall 	pause();			/* Nothing to do */
40231457Sminshall 	break;
40331457Sminshall     case UNCONNECTED:
40431465Sminshall 	if (doconnect() == -1) {
40531457Sminshall 	    kill_connection();
40631465Sminshall 	    return -1;
40731465Sminshall 	}
40831492Sminshall 	if (api_exch_init(sock, "server") == -1) {
40931465Sminshall 	    return -1;
41031465Sminshall 	}
41131465Sminshall 	while (state == UNCONNECTED) {
41231492Sminshall 	    if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) {
41331457Sminshall 		kill_connection();
41431465Sminshall 		return -1;
41531465Sminshall 	    } else {
41631465Sminshall 		switch (doassociate()) {
41731465Sminshall 		case -1:
41831465Sminshall 		    kill_connection();
41931465Sminshall 		    return -1;
42031465Sminshall 		case 0:
42131465Sminshall 		    break;
42231465Sminshall 		case 1:
42331465Sminshall 		    state = CONNECTED;
42431465Sminshall 		}
42531457Sminshall 	    }
42631457Sminshall 	}
42731457Sminshall 	break;
42831457Sminshall     case CONNECTED:
42931492Sminshall 	switch (i = api_exch_nextcommand()) {
43031492Sminshall 	case EXCH_CMD_REQUEST:
43131492Sminshall 	    if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs,
43231492Sminshall 				    (char *)&inputRegs) == -1) {
43331463Sminshall 		kill_connection();
43431492Sminshall 	    } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs,
43531492Sminshall 				    (char *)&inputSregs) == -1) {
43631463Sminshall 		kill_connection();
43731492Sminshall 	    } else if (nextstore() == -1) {
43831463Sminshall 		kill_connection();
43931492Sminshall 	    } else {
44031492Sminshall 		handle_api(&inputRegs, &inputSregs);
44131492Sminshall 		freestorage();			/* Send any storage back */
44231492Sminshall 		if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) {
44331492Sminshall 		    kill_connection();
44431492Sminshall 		} else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs,
44531492Sminshall 				    (char *)&inputRegs) == -1) {
44631492Sminshall 		    kill_connection();
44731492Sminshall 		} else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs,
44831492Sminshall 				    (char *)&inputSregs) == -1) {
44931492Sminshall 		    kill_connection();
45031492Sminshall 		}
45131492Sminshall 		/* Done, and it all worked! */
45231463Sminshall 	    }
45331492Sminshall 	    break;
45431492Sminshall 	case EXCH_CMD_DISASSOCIATE:
45531492Sminshall 	    kill_connection();
45631492Sminshall 	    break;
45731492Sminshall 	default:
45831503Sminshall 	    if (i != -1) {
45931503Sminshall 		fprintf(stderr,
46031503Sminshall 			"Looking for a REQUEST or DISASSOCIATE command\n");
46131503Sminshall 		fprintf(stderr, "\treceived 0x%02x.\n", i);
46231503Sminshall 	    }
46331492Sminshall 	    kill_connection();
46431503Sminshall 	    break;
46531457Sminshall 	}
46631457Sminshall     }
46731455Sminshall     return shell_active;
46831455Sminshall }
46931455Sminshall 
47031455Sminshall 
47131463Sminshall static int
47231463Sminshall child_died()
47331463Sminshall {
47431463Sminshall     union wait *status;
47531463Sminshall     register int pid;
47631463Sminshall 
47731463Sminshall     while ((pid = wait3(&status, WNOHANG, 0)) > 0) {
47831463Sminshall 	if (pid == shell_pid) {
47931463Sminshall 	    char inputbuffer[100];
48031463Sminshall 
48131463Sminshall 	    shell_active = 0;
48231463Sminshall 	    if (sock != -1) {
48331463Sminshall 		(void) close(sock);
48431463Sminshall 		sock = -1;
48531463Sminshall 	    }
48631471Sminshall 	    printf("[Hit return to continue]");
48731471Sminshall 	    fflush(stdout);
48831471Sminshall 	    (void) gets(inputbuffer);
48931465Sminshall 	    setconnmode();
49031465Sminshall 	    ConnectScreen();	/* Turn screen on (if need be) */
49131465Sminshall 	    (void) close(serversock);
49231463Sminshall 	}
49331463Sminshall     }
49431463Sminshall     signal(SIGCHLD, child_died);
49531463Sminshall }
49631463Sminshall 
49731463Sminshall 
49831455Sminshall /*
49931455Sminshall  * Called from telnet.c to fork a lower command.com.  We
50031455Sminshall  * use the spint... routines so that we can pick up
50131455Sminshall  * interrupts generated by application programs.
50231455Sminshall  */
50331455Sminshall 
50431455Sminshall 
50531455Sminshall int
50631455Sminshall shell(argc,argv)
50731455Sminshall int	argc;
50831455Sminshall char	*argv[];
50931455Sminshall {
51031465Sminshall     int length;
51131457Sminshall     struct sockaddr_in server;
51231457Sminshall     char sockNAME[100];
51331457Sminshall     static char **whereAPI = 0;
51431457Sminshall 
51531457Sminshall     /* First, create the socket which will be connected to */
51631457Sminshall     serversock = socket(AF_INET, SOCK_STREAM, 0);
51731457Sminshall     if (serversock < 0) {
51831457Sminshall 	perror("opening API socket");
51931457Sminshall 	return 0;
52031457Sminshall     }
52131457Sminshall     server.sin_family = AF_INET;
52231457Sminshall     server.sin_addr.s_addr = INADDR_ANY;
52331457Sminshall     server.sin_port = 0;
52431457Sminshall     if (bind(serversock, &server, sizeof server) < 0) {
52531457Sminshall 	perror("binding API socket");
52631457Sminshall 	return 0;
52731457Sminshall     }
52831457Sminshall     length = sizeof server;
52931457Sminshall     if (getsockname(serversock, &server, &length) < 0) {
53031457Sminshall 	perror("getting API socket name");
53131457Sminshall 	(void) close(serversock);
53231457Sminshall     }
53331457Sminshall     listen(serversock, 1);
53431457Sminshall     /* Get name to advertise in address list */
53531457Sminshall     strcpy(sockNAME, "API3270=");
53631457Sminshall     gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME));
53731457Sminshall     if (strlen(sockNAME) > (sizeof sockNAME-10)) {
53831457Sminshall 	fprintf(stderr, "Local hostname too large; using 'localhost'.\n");
53931457Sminshall 	strcpy(sockNAME, "localhost");
54031457Sminshall     }
54131457Sminshall     sprintf(sockNAME+strlen(sockNAME), ":%d", ntohs(server.sin_port));
54231457Sminshall 
54331457Sminshall     if (whereAPI == 0) {
54431457Sminshall 	char **ptr, **nextenv;
54531457Sminshall 	extern char **environ;
54631457Sminshall 
54731457Sminshall 	ptr = environ;
54831457Sminshall 	nextenv = ourENVlist;
54931457Sminshall 	while (*ptr) {
55031457Sminshall 	    if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) {
55131457Sminshall 		fprintf(stderr, "Too many environmental variables\n");
55231457Sminshall 		break;
55331457Sminshall 	    }
55431457Sminshall 	    *nextenv++ = *ptr++;
55531457Sminshall 	}
55631457Sminshall 	whereAPI = nextenv++;
55731457Sminshall 	*nextenv++ = 0;
55831457Sminshall 	environ = ourENVlist;		/* New environment */
55931457Sminshall     }
56031457Sminshall     *whereAPI = sockNAME;
56131457Sminshall 
56231457Sminshall     child_died();			/* Start up signal handler */
56331457Sminshall     shell_active = 1;			/* We are running down below */
56431457Sminshall     if (shell_pid = vfork()) {
56531457Sminshall 	if (shell_pid == -1) {
56631457Sminshall 	    perror("vfork");
56731457Sminshall 	    (void) close(serversock);
56831457Sminshall 	} else {
56931465Sminshall 	    state = UNCONNECTED;
57031457Sminshall 	}
57131455Sminshall     } else {				/* New process */
57231455Sminshall 	register int i;
57331455Sminshall 
57431455Sminshall 	for (i = 3; i < 30; i++) {
57531455Sminshall 	    (void) close(i);
57631455Sminshall 	}
57731455Sminshall 	if (argc == 1) {		/* Just get a shell */
57831455Sminshall 	    char *cmdname;
57931457Sminshall 	    extern char *getenv();
58031455Sminshall 
58131455Sminshall 	    cmdname = getenv("SHELL");
58231455Sminshall 	    execlp(cmdname, cmdname, 0);
58331455Sminshall 	    perror("Exec'ing new shell...\n");
58431455Sminshall 	    exit(1);
58531455Sminshall 	} else {
58631455Sminshall 	    execvp(argv[1], &argv[1]);
58731455Sminshall 	    perror("Exec'ing command.\n");
58831455Sminshall 	    exit(1);
58931455Sminshall 	}
59031455Sminshall 	/*NOTREACHED*/
59131455Sminshall     }
59231457Sminshall     return shell_active;		/* Go back to main loop */
59331455Sminshall }
594