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 
20*31795Sminshall #ifndef	FD_SETSIZE
21*31795Sminshall /*
22*31795Sminshall  * The following is defined just in case someone should want to run
23*31795Sminshall  * this telnet on a 4.2 system.
24*31795Sminshall  *
25*31795Sminshall  */
2631455Sminshall 
27*31795Sminshall #define	FD_SET(n, p)	((p)->fds_bits[0] |= (1<<(n)))
28*31795Sminshall #define	FD_CLR(n, p)	((p)->fds_bits[0] &= ~(1<<(n)))
29*31795Sminshall #define	FD_ISSET(n, p)	((p)->fds_bits[0] & (1<<(n)))
30*31795Sminshall #define FD_ZERO(p)	((p)->fds_bits[0] = 0)
31*31795Sminshall 
32*31795Sminshall #endif
33*31795Sminshall 
3431455Sminshall static int shell_pid = 0;
3531455Sminshall 
3631457Sminshall static char *ourENVlist[200];		/* Lots of room */
3731457Sminshall 
3831465Sminshall static int
3931465Sminshall     sock = -1,				/* Connected socket */
4031465Sminshall     serversock;				/* Server (listening) socket */
4131457Sminshall 
4231457Sminshall static enum { DEAD, UNCONNECTED, CONNECTED } state;
4331457Sminshall 
4431455Sminshall static int
4531463Sminshall     storage_location,		/* Address we have */
4631457Sminshall     storage_length = 0,		/* Length we have */
4731457Sminshall     storage_must_send = 0,	/* Storage belongs on other side of wire */
4831457Sminshall     storage_accessed = 0;	/* The storage is accessed (so leave alone)! */
4931457Sminshall 
5031503Sminshall static long storage[1000];
5131457Sminshall 
5231463Sminshall static union REGS inputRegs;
5331463Sminshall static struct SREGS inputSregs;
5431457Sminshall 
5531463Sminshall 
5631463Sminshall static void
5731457Sminshall kill_connection()
5831457Sminshall {
5931465Sminshall     state = UNCONNECTED;
6031465Sminshall     if (sock != -1) {
6131465Sminshall 	(void) close(sock);
6231465Sminshall 	sock = -1;
6331465Sminshall     }
6431457Sminshall }
6531457Sminshall 
6631457Sminshall 
6731457Sminshall static int
6831463Sminshall nextstore()
6931455Sminshall {
7031463Sminshall     struct storage_descriptor sd;
7131455Sminshall 
7231463Sminshall     if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
7331457Sminshall 	storage_length = 0;
7431457Sminshall 	return -1;
7531457Sminshall     }
7631463Sminshall     storage_length = ntohs(sd.length);
7731463Sminshall     storage_location = ntohl(sd.location);
7831463Sminshall     if (storage_length > sizeof storage) {
7931457Sminshall 	fprintf(stderr, "API client tried to send too much storage (%d).\n",
8031457Sminshall 		storage_length);
8131463Sminshall 	storage_length = 0;
8231457Sminshall 	return -1;
8331457Sminshall     }
8431511Sminshall     if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage)
8531511Sminshall 							== -1) {
8631511Sminshall 	storage_length = 0;
8731511Sminshall 	return -1;
8831463Sminshall     }
8931471Sminshall     return 0;
9031457Sminshall }
9131457Sminshall 
9231457Sminshall 
9331457Sminshall static int
9431457Sminshall doreject(message)
9531457Sminshall char	*message;
9631457Sminshall {
9731463Sminshall     struct storage_descriptor sd;
9831457Sminshall     int length = strlen(message);
9931457Sminshall 
10031492Sminshall     if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) {
10131457Sminshall 	return -1;
10231457Sminshall     }
10331463Sminshall     sd.length = htons(length);
10431465Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
10531463Sminshall 	return -1;
10631463Sminshall     }
10731463Sminshall     if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) {
10831463Sminshall 	return -1;
10931463Sminshall     }
11031457Sminshall     return 0;
11131457Sminshall }
11231457Sminshall 
11331457Sminshall 
11431455Sminshall /*
11531465Sminshall  * doassociate()
11631457Sminshall  *
11731457Sminshall  * Negotiate with the other side and try to do something.
11831457Sminshall  */
11931457Sminshall 
12031457Sminshall static int
12131465Sminshall doassociate()
12231457Sminshall {
12331457Sminshall     struct passwd *pwent;
12431457Sminshall     char
12531457Sminshall 	promptbuf[100],
12631457Sminshall 	buffer[200];
12731457Sminshall     int length;
12831457Sminshall     int was;
12931463Sminshall     struct storage_descriptor sd;
13031457Sminshall 
13131457Sminshall     if ((pwent = getpwuid(geteuid())) == 0) {
13231457Sminshall 	return -1;
13331457Sminshall     }
13431457Sminshall     sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name);
13531492Sminshall     if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) {
13631465Sminshall 	return -1;
13731465Sminshall     }
13831465Sminshall     sd.length = htons(strlen(promptbuf));
13931465Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
14031465Sminshall 	return -1;
14131465Sminshall     }
14231465Sminshall     if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) == -1) {
14331465Sminshall 	return -1;
14431465Sminshall     }
14531465Sminshall     sd.length = htons(strlen(pwent->pw_name));
14631465Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
14731465Sminshall 	return -1;
14831465Sminshall     }
14931465Sminshall     if (api_exch_outtype(EXCH_TYPE_BYTES,
15031465Sminshall 			strlen(pwent->pw_name), pwent->pw_name) == -1) {
15131465Sminshall 	return -1;
15231465Sminshall     }
15331492Sminshall     if (api_exch_incommand(EXCH_CMD_AUTH) == -1) {
15431457Sminshall 	return -1;
15531457Sminshall     }
15631463Sminshall     if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
15731463Sminshall 	return -1;
15831457Sminshall     }
15931463Sminshall     sd.length = ntohs(sd.length);
16031463Sminshall     if (sd.length > sizeof buffer) {
16131457Sminshall 	doreject("Password entered was too long");
16231465Sminshall 	return -1;
16331457Sminshall     }
16431463Sminshall     if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
16531457Sminshall 	return -1;
16631457Sminshall     }
16731463Sminshall     buffer[sd.length] = 0;
16831457Sminshall 
16931457Sminshall     /* Is this the correct password? */
17031465Sminshall     if (strlen(pwent->pw_name)) {
17131465Sminshall 	char *ptr;
17231465Sminshall 	int i;
17331465Sminshall 
17431465Sminshall 	ptr = pwent->pw_name;
17531465Sminshall 	i = 0;
17631465Sminshall 	while (i < sd.length) {
17731465Sminshall 	    buffer[i++] ^= *ptr++;
17831465Sminshall 	    if (*ptr == 0) {
17931465Sminshall 		ptr = pwent->pw_name;
18031465Sminshall 	    }
18131465Sminshall 	}
18231465Sminshall     }
18331457Sminshall     if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) == 0) {
18431492Sminshall 	if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) {
18531465Sminshall 	    return -1;
18631471Sminshall 	} else {
18731471Sminshall 	    return 1;
18831465Sminshall 	}
18931457Sminshall     } else {
19031457Sminshall 	doreject("Invalid password");
19131457Sminshall 	sleep(10);		/* Don't let us do too many of these */
19231471Sminshall 	return 0;
19331457Sminshall     }
19431457Sminshall }
19531457Sminshall 
19631457Sminshall 
19731457Sminshall void
19831457Sminshall freestorage()
19931457Sminshall {
20031457Sminshall     char buffer[40];
20131463Sminshall     struct storage_descriptor sd;
20231457Sminshall 
20331457Sminshall     if (storage_accessed) {
20431457Sminshall 	fprintf(stderr, "Internal error - attempt to free accessed storage.\n");
20531503Sminshall 	fprintf(stderr, "(Encountered in file %s at line %d.)\n",
20631457Sminshall 			__FILE__, __LINE__);
20731457Sminshall 	quit();
20831457Sminshall     }
20931457Sminshall     if (storage_must_send == 0) {
21031457Sminshall 	return;
21131457Sminshall     }
21231457Sminshall     storage_must_send = 0;
21331492Sminshall     if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) {
21431457Sminshall 	kill_connection();
21531457Sminshall 	return;
21631457Sminshall     }
21731463Sminshall     sd.length = htons(storage_length);
21831463Sminshall     sd.location = htonl(storage_location);
21931463Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
22031457Sminshall 	kill_connection();
22131457Sminshall 	return;
22231457Sminshall     }
22331511Sminshall     if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage)
22431511Sminshall 							    == -1) {
22531511Sminshall 	kill_connection();
22631511Sminshall 	return;
22731463Sminshall     }
22831457Sminshall }
22931457Sminshall 
23031457Sminshall 
23131463Sminshall static int
23231508Sminshall getstorage(address, length, copyin)
23331508Sminshall int
23431508Sminshall     address,
23531508Sminshall     length,
23631508Sminshall     copyin;
23731457Sminshall {
23831463Sminshall     struct storage_descriptor sd;
23931457Sminshall     char buffer[40];
24031457Sminshall 
24131457Sminshall     freestorage();
24231457Sminshall     if (storage_accessed) {
24331457Sminshall 	fprintf(stderr,
24431457Sminshall 		"Internal error - attempt to get while storage accessed.\n");
24531503Sminshall 	fprintf(stderr, "(Encountered in file %s at line %d.)\n",
24631457Sminshall 			__FILE__, __LINE__);
24731457Sminshall 	quit();
24831457Sminshall     }
24931457Sminshall     storage_must_send = 0;
25031492Sminshall     if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) {
25131457Sminshall 	kill_connection();
25231463Sminshall 	return -1;
25331457Sminshall     }
25431471Sminshall     storage_location = address;
25531471Sminshall     storage_length = length;
25631508Sminshall     if (copyin) {
25731508Sminshall 	sd.location = htonl(storage_location);
25831508Sminshall 	sd.length = htons(storage_length);
25931508Sminshall 	if (api_exch_outtype(EXCH_TYPE_STORE_DESC,
26031508Sminshall 					sizeof sd, (char *)&sd) == -1) {
26131508Sminshall 	    kill_connection();
26231508Sminshall 	    return -1;
26331508Sminshall 	}
26431508Sminshall 	if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) {
26531508Sminshall 	    fprintf(stderr, "Bad data from other side.\n");
26631508Sminshall 	    fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__);
26731508Sminshall 	    return -1;
26831508Sminshall 	}
26931508Sminshall 	if (nextstore() == -1) {
27031508Sminshall 	    kill_connection();
27131508Sminshall 	    return -1;
27231508Sminshall 	}
27331463Sminshall     }
27431463Sminshall     return 0;
27531457Sminshall }
27631457Sminshall 
27731457Sminshall void
27831457Sminshall movetous(local, es, di, length)
27931457Sminshall char
28031457Sminshall     *local;
28131457Sminshall int
28231457Sminshall     es,
28331457Sminshall     di;
28431457Sminshall int
28531457Sminshall     length;
28631457Sminshall {
28731457Sminshall     if (length > sizeof storage) {
28831457Sminshall 	fprintf(stderr, "Internal API error - movetous() length too long.\n");
28931457Sminshall 	fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
29031457Sminshall 	quit();
29131457Sminshall     } else if (length == 0) {
29231457Sminshall 	return;
29331457Sminshall     }
29431508Sminshall     getstorage(di, length, 1);
29531463Sminshall     memcpy(local, storage+(di-storage_location), length);
29631457Sminshall }
29731457Sminshall 
29831457Sminshall void
29931457Sminshall movetothem(es, di, local, length)
30031457Sminshall int
30131457Sminshall     es,
30231457Sminshall     di;
30331457Sminshall char
30431457Sminshall     *local;
30531457Sminshall int
30631457Sminshall     length;
30731457Sminshall {
30831457Sminshall     if (length > sizeof storage) {
30931457Sminshall 	fprintf(stderr, "Internal API error - movetothem() length too long.\n");
31031457Sminshall 	fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
31131457Sminshall 	quit();
31231457Sminshall     } else if (length == 0) {
31331457Sminshall 	return;
31431457Sminshall     }
31531457Sminshall     freestorage();
31631457Sminshall     memcpy((char *)storage, local, length);
31731457Sminshall     storage_length = length;
31831463Sminshall     storage_location = di;
31931457Sminshall     storage_must_send = 1;
32031457Sminshall }
32131457Sminshall 
32231457Sminshall 
32331457Sminshall char *
32431508Sminshall access_api(location, length, copyin)
32531457Sminshall int
32631457Sminshall     location,
32731508Sminshall     length,
32831508Sminshall     copyin;			/* Do we need to copy in initially? */
32931457Sminshall {
33031457Sminshall     if (storage_accessed) {
33131457Sminshall 	fprintf(stderr, "Internal error - storage accessed twice\n");
33231503Sminshall 	fprintf(stderr, "(Encountered in file %s, line %d.)\n",
33331457Sminshall 				__FILE__, __LINE__);
33431457Sminshall 	quit();
33531457Sminshall     } else if (length != 0) {
33631457Sminshall 	freestorage();
33731508Sminshall 	getstorage(location, length, copyin);
33831503Sminshall 	storage_accessed = 1;
33931457Sminshall     }
34031457Sminshall     return (char *) storage;
34131457Sminshall }
34231457Sminshall 
34331508Sminshall unaccess_api(location, local, length, copyout)
34431457Sminshall int	location;
34531457Sminshall char	*local;
34631457Sminshall int	length;
34731457Sminshall {
34831457Sminshall     if (storage_accessed == 0) {
34931457Sminshall 	fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n");
35031503Sminshall 	fprintf(stderr, "(Encountered in file %s, line %d.)\n",
35131457Sminshall 			__FILE__, __LINE__);
35231457Sminshall 	quit();
35331457Sminshall     }
35431457Sminshall     storage_accessed = 0;
35531508Sminshall     storage_must_send = copyout;	/* if needs to go back */
35631457Sminshall }
35731457Sminshall 
35831465Sminshall /*
35931465Sminshall  * Accept a connection from an API client, aborting if the child dies.
36031465Sminshall  */
36131457Sminshall 
36231465Sminshall static int
36331465Sminshall doconnect()
36431465Sminshall {
36531465Sminshall     fd_set fdset;
36631465Sminshall     int i;
36731465Sminshall 
36831465Sminshall     sock = -1;
36931465Sminshall     FD_ZERO(&fdset);
37031465Sminshall     while (shell_active && (sock == -1)) {
37131465Sminshall 	FD_SET(serversock, &fdset);
37231465Sminshall 	if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) {
37331465Sminshall 	    if (errno = EINTR) {
37431465Sminshall 		continue;
37531465Sminshall 	    } else {
37631465Sminshall 		perror("in select waiting for API connection");
37731465Sminshall 		return -1;
37831465Sminshall 	    }
37931465Sminshall 	} else {
38031465Sminshall 	    i = accept(serversock, 0, 0);
38131465Sminshall 	    if (i == -1) {
38231465Sminshall 		perror("accepting API connection");
38331465Sminshall 		return -1;
38431465Sminshall 	    }
38531465Sminshall 	    sock = i;
38631465Sminshall 	}
38731465Sminshall     }
38831465Sminshall     /* If the process has already exited, we may need to close */
38931465Sminshall     if ((shell_active == 0) && (sock != -1)) {
39031465Sminshall 	(void) close(sock);
39131465Sminshall 	sock = -1;
39231465Sminshall 	setcommandmode();	/* In case child_died sneaked in */
39331465Sminshall     }
39431465Sminshall }
39531465Sminshall 
39631457Sminshall /*
39731455Sminshall  * shell_continue() actually runs the command, and looks for API
39831455Sminshall  * requests coming back in.
39931455Sminshall  *
40031455Sminshall  * We are called from the main loop in telnet.c.
40131455Sminshall  */
40231455Sminshall 
40331455Sminshall int
40431455Sminshall shell_continue()
40531455Sminshall {
40631492Sminshall     int i;
40731492Sminshall 
40831457Sminshall     switch (state) {
40931457Sminshall     case DEAD:
41031457Sminshall 	pause();			/* Nothing to do */
41131457Sminshall 	break;
41231457Sminshall     case UNCONNECTED:
41331465Sminshall 	if (doconnect() == -1) {
41431457Sminshall 	    kill_connection();
41531465Sminshall 	    return -1;
41631465Sminshall 	}
41731492Sminshall 	if (api_exch_init(sock, "server") == -1) {
41831465Sminshall 	    return -1;
41931465Sminshall 	}
42031465Sminshall 	while (state == UNCONNECTED) {
42131492Sminshall 	    if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) {
42231457Sminshall 		kill_connection();
42331465Sminshall 		return -1;
42431465Sminshall 	    } else {
42531465Sminshall 		switch (doassociate()) {
42631465Sminshall 		case -1:
42731465Sminshall 		    kill_connection();
42831465Sminshall 		    return -1;
42931465Sminshall 		case 0:
43031465Sminshall 		    break;
43131465Sminshall 		case 1:
43231465Sminshall 		    state = CONNECTED;
43331465Sminshall 		}
43431457Sminshall 	    }
43531457Sminshall 	}
43631457Sminshall 	break;
43731457Sminshall     case CONNECTED:
43831492Sminshall 	switch (i = api_exch_nextcommand()) {
43931492Sminshall 	case EXCH_CMD_REQUEST:
44031492Sminshall 	    if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs,
44131492Sminshall 				    (char *)&inputRegs) == -1) {
44231463Sminshall 		kill_connection();
44331492Sminshall 	    } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs,
44431492Sminshall 				    (char *)&inputSregs) == -1) {
44531463Sminshall 		kill_connection();
44631492Sminshall 	    } else if (nextstore() == -1) {
44731463Sminshall 		kill_connection();
44831492Sminshall 	    } else {
44931492Sminshall 		handle_api(&inputRegs, &inputSregs);
45031492Sminshall 		freestorage();			/* Send any storage back */
45131492Sminshall 		if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) {
45231492Sminshall 		    kill_connection();
45331492Sminshall 		} else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs,
45431492Sminshall 				    (char *)&inputRegs) == -1) {
45531492Sminshall 		    kill_connection();
45631492Sminshall 		} else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs,
45731492Sminshall 				    (char *)&inputSregs) == -1) {
45831492Sminshall 		    kill_connection();
45931492Sminshall 		}
46031492Sminshall 		/* Done, and it all worked! */
46131463Sminshall 	    }
46231492Sminshall 	    break;
46331492Sminshall 	case EXCH_CMD_DISASSOCIATE:
46431492Sminshall 	    kill_connection();
46531492Sminshall 	    break;
46631492Sminshall 	default:
46731503Sminshall 	    if (i != -1) {
46831503Sminshall 		fprintf(stderr,
46931503Sminshall 			"Looking for a REQUEST or DISASSOCIATE command\n");
47031503Sminshall 		fprintf(stderr, "\treceived 0x%02x.\n", i);
47131503Sminshall 	    }
47231492Sminshall 	    kill_connection();
47331503Sminshall 	    break;
47431457Sminshall 	}
47531457Sminshall     }
47631455Sminshall     return shell_active;
47731455Sminshall }
47831455Sminshall 
47931455Sminshall 
48031463Sminshall static int
48131463Sminshall child_died()
48231463Sminshall {
48331463Sminshall     union wait *status;
48431463Sminshall     register int pid;
48531463Sminshall 
48631463Sminshall     while ((pid = wait3(&status, WNOHANG, 0)) > 0) {
48731463Sminshall 	if (pid == shell_pid) {
48831463Sminshall 	    char inputbuffer[100];
48931463Sminshall 
49031463Sminshall 	    shell_active = 0;
49131463Sminshall 	    if (sock != -1) {
49231463Sminshall 		(void) close(sock);
49331463Sminshall 		sock = -1;
49431463Sminshall 	    }
49531471Sminshall 	    printf("[Hit return to continue]");
49631471Sminshall 	    fflush(stdout);
49731471Sminshall 	    (void) gets(inputbuffer);
49831465Sminshall 	    setconnmode();
49931465Sminshall 	    ConnectScreen();	/* Turn screen on (if need be) */
50031465Sminshall 	    (void) close(serversock);
50131463Sminshall 	}
50231463Sminshall     }
50331463Sminshall     signal(SIGCHLD, child_died);
50431463Sminshall }
50531463Sminshall 
50631463Sminshall 
50731455Sminshall /*
50831455Sminshall  * Called from telnet.c to fork a lower command.com.  We
50931455Sminshall  * use the spint... routines so that we can pick up
51031455Sminshall  * interrupts generated by application programs.
51131455Sminshall  */
51231455Sminshall 
51331455Sminshall 
51431455Sminshall int
51531455Sminshall shell(argc,argv)
51631455Sminshall int	argc;
51731455Sminshall char	*argv[];
51831455Sminshall {
51931465Sminshall     int length;
52031457Sminshall     struct sockaddr_in server;
52131457Sminshall     char sockNAME[100];
52231457Sminshall     static char **whereAPI = 0;
52331457Sminshall 
52431457Sminshall     /* First, create the socket which will be connected to */
52531457Sminshall     serversock = socket(AF_INET, SOCK_STREAM, 0);
52631457Sminshall     if (serversock < 0) {
52731457Sminshall 	perror("opening API socket");
52831457Sminshall 	return 0;
52931457Sminshall     }
53031457Sminshall     server.sin_family = AF_INET;
53131457Sminshall     server.sin_addr.s_addr = INADDR_ANY;
53231457Sminshall     server.sin_port = 0;
53331457Sminshall     if (bind(serversock, &server, sizeof server) < 0) {
53431457Sminshall 	perror("binding API socket");
53531457Sminshall 	return 0;
53631457Sminshall     }
53731457Sminshall     length = sizeof server;
53831457Sminshall     if (getsockname(serversock, &server, &length) < 0) {
53931457Sminshall 	perror("getting API socket name");
54031457Sminshall 	(void) close(serversock);
54131457Sminshall     }
54231457Sminshall     listen(serversock, 1);
54331457Sminshall     /* Get name to advertise in address list */
54431457Sminshall     strcpy(sockNAME, "API3270=");
54531457Sminshall     gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME));
54631457Sminshall     if (strlen(sockNAME) > (sizeof sockNAME-10)) {
54731457Sminshall 	fprintf(stderr, "Local hostname too large; using 'localhost'.\n");
54831457Sminshall 	strcpy(sockNAME, "localhost");
54931457Sminshall     }
55031457Sminshall     sprintf(sockNAME+strlen(sockNAME), ":%d", ntohs(server.sin_port));
55131457Sminshall 
55231457Sminshall     if (whereAPI == 0) {
55331457Sminshall 	char **ptr, **nextenv;
55431457Sminshall 	extern char **environ;
55531457Sminshall 
55631457Sminshall 	ptr = environ;
55731457Sminshall 	nextenv = ourENVlist;
55831457Sminshall 	while (*ptr) {
55931457Sminshall 	    if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) {
56031457Sminshall 		fprintf(stderr, "Too many environmental variables\n");
56131457Sminshall 		break;
56231457Sminshall 	    }
56331457Sminshall 	    *nextenv++ = *ptr++;
56431457Sminshall 	}
56531457Sminshall 	whereAPI = nextenv++;
56631457Sminshall 	*nextenv++ = 0;
56731457Sminshall 	environ = ourENVlist;		/* New environment */
56831457Sminshall     }
56931457Sminshall     *whereAPI = sockNAME;
57031457Sminshall 
57131457Sminshall     child_died();			/* Start up signal handler */
57231457Sminshall     shell_active = 1;			/* We are running down below */
57331457Sminshall     if (shell_pid = vfork()) {
57431457Sminshall 	if (shell_pid == -1) {
57531457Sminshall 	    perror("vfork");
57631457Sminshall 	    (void) close(serversock);
57731457Sminshall 	} else {
57831465Sminshall 	    state = UNCONNECTED;
57931457Sminshall 	}
58031455Sminshall     } else {				/* New process */
58131455Sminshall 	register int i;
58231455Sminshall 
58331455Sminshall 	for (i = 3; i < 30; i++) {
58431455Sminshall 	    (void) close(i);
58531455Sminshall 	}
58631455Sminshall 	if (argc == 1) {		/* Just get a shell */
58731455Sminshall 	    char *cmdname;
58831457Sminshall 	    extern char *getenv();
58931455Sminshall 
59031455Sminshall 	    cmdname = getenv("SHELL");
59131455Sminshall 	    execlp(cmdname, cmdname, 0);
59231455Sminshall 	    perror("Exec'ing new shell...\n");
59331455Sminshall 	    exit(1);
59431455Sminshall 	} else {
59531455Sminshall 	    execvp(argv[1], &argv[1]);
59631455Sminshall 	    perror("Exec'ing command.\n");
59731455Sminshall 	    exit(1);
59831455Sminshall 	}
59931455Sminshall 	/*NOTREACHED*/
60031455Sminshall     }
60131457Sminshall     return shell_active;		/* Go back to main loop */
60231455Sminshall }
603