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 
25*31465Sminshall static int
26*31465Sminshall     sock = -1,				/* Connected socket */
27*31465Sminshall     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 
3731457Sminshall static long storage[250];
3831457Sminshall 
3931463Sminshall static union REGS inputRegs;
4031463Sminshall static struct SREGS inputSregs;
4131457Sminshall 
4231463Sminshall 
4331463Sminshall static void
4431457Sminshall kill_connection()
4531457Sminshall {
46*31465Sminshall     state = UNCONNECTED;
47*31465Sminshall     if (sock != -1) {
48*31465Sminshall 	(void) close(sock);
49*31465Sminshall 	sock = -1;
50*31465Sminshall     }
5131457Sminshall }
5231457Sminshall 
5331457Sminshall 
5431457Sminshall static int
5531463Sminshall nextstore()
5631455Sminshall {
5731463Sminshall     struct storage_descriptor sd;
5831455Sminshall 
5931463Sminshall     if (api_exch_incommand(EXCH_HEREIS) == -1) {
6031457Sminshall 	fprintf(stderr, "Bad data from other side.\n");
6131457Sminshall 	fprintf(stderr, "(Encountered at %s, %s.)\n", __FILE__, __LINE__);
6231457Sminshall 	return -1;
6331457Sminshall     }
6431463Sminshall     if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
6531457Sminshall 	storage_length = 0;
6631457Sminshall 	return -1;
6731457Sminshall     }
6831463Sminshall     storage_length = ntohs(sd.length);
6931463Sminshall     storage_location = ntohl(sd.location);
7031463Sminshall     if (storage_length > sizeof storage) {
7131457Sminshall 	fprintf(stderr, "API client tried to send too much storage (%d).\n",
7231457Sminshall 		storage_length);
7331463Sminshall 	storage_length = 0;
7431457Sminshall 	return -1;
7531457Sminshall     }
7631463Sminshall     if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage) == -1) {
7731463Sminshall 	storage_length = 0;
7831463Sminshall 	return -1;
7931463Sminshall     }
8031457Sminshall }
8131457Sminshall 
8231457Sminshall 
8331457Sminshall static int
8431457Sminshall doreject(message)
8531457Sminshall char	*message;
8631457Sminshall {
8731463Sminshall     struct storage_descriptor sd;
8831457Sminshall     int length = strlen(message);
8931457Sminshall 
9031463Sminshall     if (api_exch_outcommand(EXCH_REJECTED) == -1) {
9131457Sminshall 	return -1;
9231457Sminshall     }
9331463Sminshall     sd.length = htons(length);
94*31465Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
9531463Sminshall 	return -1;
9631463Sminshall     }
9731463Sminshall     if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) {
9831463Sminshall 	return -1;
9931463Sminshall     }
10031457Sminshall     return 0;
10131457Sminshall }
10231457Sminshall 
10331457Sminshall 
10431455Sminshall /*
105*31465Sminshall  * doassociate()
10631457Sminshall  *
10731457Sminshall  * Negotiate with the other side and try to do something.
10831457Sminshall  */
10931457Sminshall 
11031457Sminshall static int
111*31465Sminshall doassociate()
11231457Sminshall {
11331457Sminshall     struct passwd *pwent;
11431457Sminshall     char
11531457Sminshall 	promptbuf[100],
11631457Sminshall 	buffer[200];
11731457Sminshall     int length;
11831457Sminshall     int was;
11931463Sminshall     struct storage_descriptor sd;
12031457Sminshall 
12131457Sminshall     if ((pwent = getpwuid(geteuid())) == 0) {
12231457Sminshall 	return -1;
12331457Sminshall     }
12431457Sminshall     sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name);
125*31465Sminshall     if (api_exch_outcommand(EXCH_SEND_AUTH) == -1) {
126*31465Sminshall 	return -1;
127*31465Sminshall     }
128*31465Sminshall     sd.length = htons(strlen(promptbuf));
129*31465Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
130*31465Sminshall 	return -1;
131*31465Sminshall     }
132*31465Sminshall     if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf) == -1) {
133*31465Sminshall 	return -1;
134*31465Sminshall     }
135*31465Sminshall     sd.length = htons(strlen(pwent->pw_name));
136*31465Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
137*31465Sminshall 	return -1;
138*31465Sminshall     }
139*31465Sminshall     if (api_exch_outtype(EXCH_TYPE_BYTES,
140*31465Sminshall 			strlen(pwent->pw_name), pwent->pw_name) == -1) {
141*31465Sminshall 	return -1;
142*31465Sminshall     }
14331463Sminshall     if (api_exch_incommand(EXCH_AUTH) == -1) {
14431457Sminshall 	return -1;
14531457Sminshall     }
14631463Sminshall     if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
14731463Sminshall 	return -1;
14831457Sminshall     }
14931463Sminshall     sd.length = ntohs(sd.length);
15031463Sminshall     if (sd.length > sizeof buffer) {
15131457Sminshall 	doreject("Password entered was too long");
152*31465Sminshall 	return -1;
15331457Sminshall     }
15431463Sminshall     if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
15531457Sminshall 	return -1;
15631457Sminshall     }
15731463Sminshall     buffer[sd.length] = 0;
15831457Sminshall 
15931457Sminshall     /* Is this the correct password? */
160*31465Sminshall     if (strlen(pwent->pw_name)) {
161*31465Sminshall 	char *ptr;
162*31465Sminshall 	int i;
163*31465Sminshall 
164*31465Sminshall 	ptr = pwent->pw_name;
165*31465Sminshall 	i = 0;
166*31465Sminshall 	while (i < sd.length) {
167*31465Sminshall 	    buffer[i++] ^= *ptr++;
168*31465Sminshall 	    if (*ptr == 0) {
169*31465Sminshall 		ptr = pwent->pw_name;
170*31465Sminshall 	    }
171*31465Sminshall 	}
172*31465Sminshall     }
17331457Sminshall     if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) == 0) {
174*31465Sminshall 	if (api_exch_outcommand(EXCH_ASSOCIATED) == -1) {
175*31465Sminshall 	    return -1;
176*31465Sminshall 	}
17731457Sminshall     } else {
17831457Sminshall 	doreject("Invalid password");
17931457Sminshall 	sleep(10);		/* Don't let us do too many of these */
18031457Sminshall     }
18131457Sminshall     return 0;
18231457Sminshall }
18331457Sminshall 
18431457Sminshall 
18531457Sminshall void
18631457Sminshall freestorage()
18731457Sminshall {
18831457Sminshall     char buffer[40];
18931463Sminshall     struct storage_descriptor sd;
19031457Sminshall 
19131457Sminshall     if (storage_accessed) {
19231457Sminshall 	fprintf(stderr, "Internal error - attempt to free accessed storage.\n");
19331457Sminshall 	fprintf(stderr, "(Enountered in file %s at line %s.)\n",
19431457Sminshall 			__FILE__, __LINE__);
19531457Sminshall 	quit();
19631457Sminshall     }
19731457Sminshall     if (storage_must_send == 0) {
19831457Sminshall 	return;
19931457Sminshall     }
20031457Sminshall     storage_must_send = 0;
20131463Sminshall     if (api_exch_outcommand(EXCH_HEREIS) == -1) {
20231457Sminshall 	kill_connection();
20331457Sminshall 	return;
20431457Sminshall     }
20531463Sminshall     sd.length = htons(storage_length);
20631463Sminshall     sd.location = htonl(storage_location);
20731463Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
20831457Sminshall 	kill_connection();
20931457Sminshall 	return;
21031457Sminshall     }
21131463Sminshall     if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage) == -1) {
21231463Sminshall 	kill_connection();
21331463Sminshall 	return;
21431463Sminshall     }
21531457Sminshall }
21631457Sminshall 
21731457Sminshall 
21831463Sminshall static int
21931457Sminshall getstorage(address, length)
22031457Sminshall {
22131463Sminshall     struct storage_descriptor sd;
22231457Sminshall     char buffer[40];
22331457Sminshall 
22431457Sminshall     freestorage();
22531457Sminshall     if (storage_accessed) {
22631457Sminshall 	fprintf(stderr,
22731457Sminshall 		"Internal error - attempt to get while storage accessed.\n");
22831457Sminshall 	fprintf(stderr, "(Enountered in file %s at line %s.)\n",
22931457Sminshall 			__FILE__, __LINE__);
23031457Sminshall 	quit();
23131457Sminshall     }
23231457Sminshall     if (storage_must_send == 0) {
23331457Sminshall 	return;
23431457Sminshall     }
23531457Sminshall     storage_must_send = 0;
23631463Sminshall     if (api_exch_outcommand(EXCH_GIMME) == -1) {
23731457Sminshall 	kill_connection();
23831463Sminshall 	return -1;
23931457Sminshall     }
24031463Sminshall     sd.location = htonl(storage_location);
24131463Sminshall     sd.length = htons(storage_length);
24231463Sminshall     if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
24331463Sminshall 	kill_connection();
24431463Sminshall 	return -1;
24531463Sminshall     }
24631457Sminshall     if (nextstore() == -1) {
24731457Sminshall 	kill_connection();
24831463Sminshall 	return -1;
24931457Sminshall     }
25031463Sminshall     return 0;
25131457Sminshall }
25231457Sminshall 
25331457Sminshall void
25431457Sminshall movetous(local, es, di, length)
25531457Sminshall char
25631457Sminshall     *local;
25731457Sminshall int
25831457Sminshall     es,
25931457Sminshall     di;
26031457Sminshall int
26131457Sminshall     length;
26231457Sminshall {
26331457Sminshall     if (length > sizeof storage) {
26431457Sminshall 	fprintf(stderr, "Internal API error - movetous() length too long.\n");
26531457Sminshall 	fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
26631457Sminshall 	quit();
26731457Sminshall     } else if (length == 0) {
26831457Sminshall 	return;
26931457Sminshall     }
27031457Sminshall     getstorage(di, length);
27131463Sminshall     memcpy(local, storage+(di-storage_location), length);
27231457Sminshall }
27331457Sminshall 
27431457Sminshall void
27531457Sminshall movetothem(es, di, local, length)
27631457Sminshall int
27731457Sminshall     es,
27831457Sminshall     di;
27931457Sminshall char
28031457Sminshall     *local;
28131457Sminshall int
28231457Sminshall     length;
28331457Sminshall {
28431457Sminshall     if (length > sizeof storage) {
28531457Sminshall 	fprintf(stderr, "Internal API error - movetothem() length too long.\n");
28631457Sminshall 	fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
28731457Sminshall 	quit();
28831457Sminshall     } else if (length == 0) {
28931457Sminshall 	return;
29031457Sminshall     }
29131457Sminshall     freestorage();
29231457Sminshall     memcpy((char *)storage, local, length);
29331457Sminshall     storage_length = length;
29431463Sminshall     storage_location = di;
29531457Sminshall     storage_must_send = 1;
29631457Sminshall }
29731457Sminshall 
29831457Sminshall 
29931457Sminshall char *
30031457Sminshall access_api(location, length)
30131457Sminshall int
30231457Sminshall     location,
30331457Sminshall     length;
30431457Sminshall {
30531457Sminshall     if (storage_accessed) {
30631457Sminshall 	fprintf(stderr, "Internal error - storage accessed twice\n");
30731457Sminshall 	fprintf(stderr, "(Encountered in file %s, line %s.)\n",
30831457Sminshall 				__FILE__, __LINE__);
30931457Sminshall 	quit();
31031457Sminshall     } else if (length != 0) {
31131457Sminshall 	storage_accessed = 1;
31231457Sminshall 	freestorage();
31331457Sminshall 	getstorage(location, length);
31431457Sminshall     }
31531457Sminshall     return (char *) storage;
31631457Sminshall }
31731457Sminshall 
31831457Sminshall unaccess_api(location, local, length)
31931457Sminshall int	location;
32031457Sminshall char	*local;
32131457Sminshall int	length;
32231457Sminshall {
32331457Sminshall     if (storage_accessed == 0) {
32431457Sminshall 	fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n");
32531457Sminshall 	fprintf(stderr, "(Encountered in file %s, line %s.)\n",
32631457Sminshall 			__FILE__, __LINE__);
32731457Sminshall 	quit();
32831457Sminshall     }
32931457Sminshall     storage_accessed = 0;
33031457Sminshall     storage_must_send = 1;	/* Needs to go back */
33131457Sminshall }
33231457Sminshall 
333*31465Sminshall /*
334*31465Sminshall  * Accept a connection from an API client, aborting if the child dies.
335*31465Sminshall  */
33631457Sminshall 
337*31465Sminshall static int
338*31465Sminshall doconnect()
339*31465Sminshall {
340*31465Sminshall     fd_set fdset;
341*31465Sminshall     int i;
342*31465Sminshall 
343*31465Sminshall     sock = -1;
344*31465Sminshall     FD_ZERO(&fdset);
345*31465Sminshall     while (shell_active && (sock == -1)) {
346*31465Sminshall 	FD_SET(serversock, &fdset);
347*31465Sminshall 	if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) {
348*31465Sminshall 	    if (errno = EINTR) {
349*31465Sminshall 		continue;
350*31465Sminshall 	    } else {
351*31465Sminshall 		perror("in select waiting for API connection");
352*31465Sminshall 		return -1;
353*31465Sminshall 	    }
354*31465Sminshall 	} else {
355*31465Sminshall 	    i = accept(serversock, 0, 0);
356*31465Sminshall 	    if (i == -1) {
357*31465Sminshall 		perror("accepting API connection");
358*31465Sminshall 		return -1;
359*31465Sminshall 	    }
360*31465Sminshall 	    sock = i;
361*31465Sminshall 	}
362*31465Sminshall     }
363*31465Sminshall     /* If the process has already exited, we may need to close */
364*31465Sminshall     if ((shell_active == 0) && (sock != -1)) {
365*31465Sminshall 	(void) close(sock);
366*31465Sminshall 	sock = -1;
367*31465Sminshall 	setcommandmode();	/* In case child_died sneaked in */
368*31465Sminshall     }
369*31465Sminshall }
370*31465Sminshall 
37131457Sminshall /*
37231455Sminshall  * shell_continue() actually runs the command, and looks for API
37331455Sminshall  * requests coming back in.
37431455Sminshall  *
37531455Sminshall  * We are called from the main loop in telnet.c.
37631455Sminshall  */
37731455Sminshall 
37831455Sminshall int
37931455Sminshall shell_continue()
38031455Sminshall {
38131457Sminshall     switch (state) {
38231457Sminshall     case DEAD:
38331457Sminshall 	pause();			/* Nothing to do */
38431457Sminshall 	break;
38531457Sminshall     case UNCONNECTED:
386*31465Sminshall 	if (doconnect() == -1) {
38731457Sminshall 	    kill_connection();
388*31465Sminshall 	    return -1;
389*31465Sminshall 	}
390*31465Sminshall 	if (api_exch_init(sock, "client") == -1) {
391*31465Sminshall 	    return -1;
392*31465Sminshall 	}
393*31465Sminshall 	while (state == UNCONNECTED) {
394*31465Sminshall 	    if (api_exch_incommand(EXCH_ASSOCIATE) == -1) {
39531457Sminshall 		kill_connection();
396*31465Sminshall 		return -1;
397*31465Sminshall 	    } else {
398*31465Sminshall 		switch (doassociate()) {
399*31465Sminshall 		case -1:
400*31465Sminshall 		    kill_connection();
401*31465Sminshall 		    return -1;
402*31465Sminshall 		case 0:
403*31465Sminshall 		    break;
404*31465Sminshall 		case 1:
405*31465Sminshall 		    state = CONNECTED;
406*31465Sminshall 		}
40731457Sminshall 	    }
40831457Sminshall 	}
40931457Sminshall 	break;
41031457Sminshall     case CONNECTED:
41131463Sminshall 	if (api_exch_incommand(EXCH_REQUEST) == -1) {
41231463Sminshall 	    kill_connection();
41331463Sminshall 	} else if (api_exch_intype(EXCH_TYPE_BYTES, sizeof inputRegs,
41431463Sminshall 				(char *)&inputRegs) == -1) {
41531463Sminshall 	    kill_connection();
41631463Sminshall 	} else if (api_exch_intype(EXCH_TYPE_BYTES, sizeof inputSregs,
41731463Sminshall 				(char *)&inputSregs) == -1) {
41831463Sminshall 	    kill_connection();
41931463Sminshall 	} else if (nextstore() == -1) {
42031463Sminshall 	    kill_connection();
42131463Sminshall 	} else {
42231457Sminshall 	    handle_api(&inputRegs, &inputSregs);
42331463Sminshall 	    freestorage();			/* Send any storage back */
42431463Sminshall 	    if (api_exch_outcommand(EXCH_REPLY) == -1) {
42531463Sminshall 		kill_connection();
42631463Sminshall 	    } else if (api_exch_outtype(EXCH_TYPE_BYTES, sizeof inputRegs,
42731463Sminshall 				(char *)&inputRegs) == -1) {
42831463Sminshall 		kill_connection();
42931463Sminshall 	    } else if (api_exch_outtype(EXCH_TYPE_BYTES, sizeof inputSregs,
43031463Sminshall 				(char *)&inputSregs) == -1) {
43131463Sminshall 		kill_connection();
43231463Sminshall 	    }
43331463Sminshall 	    /* Done, and it all worked! */
43431457Sminshall 	}
43531457Sminshall     }
43631455Sminshall     return shell_active;
43731455Sminshall }
43831455Sminshall 
43931455Sminshall 
44031463Sminshall static int
44131463Sminshall child_died()
44231463Sminshall {
44331463Sminshall     union wait *status;
44431463Sminshall     register int pid;
44531463Sminshall 
44631463Sminshall     while ((pid = wait3(&status, WNOHANG, 0)) > 0) {
44731463Sminshall 	if (pid == shell_pid) {
44831463Sminshall 	    char inputbuffer[100];
44931463Sminshall 
45031463Sminshall 	    shell_active = 0;
45131463Sminshall 	    if (sock != -1) {
45231463Sminshall 		(void) close(sock);
45331463Sminshall 		sock = -1;
45431463Sminshall 		printf("[Hit return to continue]");
45531463Sminshall 		fflush(stdout);
45631463Sminshall 		(void) gets(inputbuffer);
45731463Sminshall 	    }
458*31465Sminshall 	    setconnmode();
459*31465Sminshall 	    ConnectScreen();	/* Turn screen on (if need be) */
460*31465Sminshall 	    (void) close(serversock);
46131463Sminshall 	}
46231463Sminshall     }
46331463Sminshall     signal(SIGCHLD, child_died);
46431463Sminshall }
46531463Sminshall 
46631463Sminshall 
46731455Sminshall /*
46831455Sminshall  * Called from telnet.c to fork a lower command.com.  We
46931455Sminshall  * use the spint... routines so that we can pick up
47031455Sminshall  * interrupts generated by application programs.
47131455Sminshall  */
47231455Sminshall 
47331455Sminshall 
47431455Sminshall int
47531455Sminshall shell(argc,argv)
47631455Sminshall int	argc;
47731455Sminshall char	*argv[];
47831455Sminshall {
479*31465Sminshall     int length;
48031457Sminshall     struct sockaddr_in server;
48131457Sminshall     char sockNAME[100];
48231457Sminshall     static char **whereAPI = 0;
48331457Sminshall 
48431457Sminshall     /* First, create the socket which will be connected to */
48531457Sminshall     serversock = socket(AF_INET, SOCK_STREAM, 0);
48631457Sminshall     if (serversock < 0) {
48731457Sminshall 	perror("opening API socket");
48831457Sminshall 	return 0;
48931457Sminshall     }
49031457Sminshall     server.sin_family = AF_INET;
49131457Sminshall     server.sin_addr.s_addr = INADDR_ANY;
49231457Sminshall     server.sin_port = 0;
49331457Sminshall     if (bind(serversock, &server, sizeof server) < 0) {
49431457Sminshall 	perror("binding API socket");
49531457Sminshall 	return 0;
49631457Sminshall     }
49731457Sminshall     length = sizeof server;
49831457Sminshall     if (getsockname(serversock, &server, &length) < 0) {
49931457Sminshall 	perror("getting API socket name");
50031457Sminshall 	(void) close(serversock);
50131457Sminshall     }
50231457Sminshall     listen(serversock, 1);
50331457Sminshall     /* Get name to advertise in address list */
50431457Sminshall     strcpy(sockNAME, "API3270=");
50531457Sminshall     gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME));
50631457Sminshall     if (strlen(sockNAME) > (sizeof sockNAME-10)) {
50731457Sminshall 	fprintf(stderr, "Local hostname too large; using 'localhost'.\n");
50831457Sminshall 	strcpy(sockNAME, "localhost");
50931457Sminshall     }
51031457Sminshall     sprintf(sockNAME+strlen(sockNAME), ":%d", ntohs(server.sin_port));
51131457Sminshall 
51231457Sminshall     if (whereAPI == 0) {
51331457Sminshall 	char **ptr, **nextenv;
51431457Sminshall 	extern char **environ;
51531457Sminshall 
51631457Sminshall 	ptr = environ;
51731457Sminshall 	nextenv = ourENVlist;
51831457Sminshall 	while (*ptr) {
51931457Sminshall 	    if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) {
52031457Sminshall 		fprintf(stderr, "Too many environmental variables\n");
52131457Sminshall 		break;
52231457Sminshall 	    }
52331457Sminshall 	    *nextenv++ = *ptr++;
52431457Sminshall 	}
52531457Sminshall 	whereAPI = nextenv++;
52631457Sminshall 	*nextenv++ = 0;
52731457Sminshall 	environ = ourENVlist;		/* New environment */
52831457Sminshall     }
52931457Sminshall     *whereAPI = sockNAME;
53031457Sminshall 
53131457Sminshall     child_died();			/* Start up signal handler */
53231457Sminshall     shell_active = 1;			/* We are running down below */
53331457Sminshall     if (shell_pid = vfork()) {
53431457Sminshall 	if (shell_pid == -1) {
53531457Sminshall 	    perror("vfork");
53631457Sminshall 	    (void) close(serversock);
53731457Sminshall 	} else {
538*31465Sminshall 	    state = UNCONNECTED;
53931457Sminshall 	}
54031455Sminshall     } else {				/* New process */
54131455Sminshall 	register int i;
54231455Sminshall 
54331455Sminshall 	for (i = 3; i < 30; i++) {
54431455Sminshall 	    (void) close(i);
54531455Sminshall 	}
54631455Sminshall 	if (argc == 1) {		/* Just get a shell */
54731455Sminshall 	    char *cmdname;
54831457Sminshall 	    extern char *getenv();
54931455Sminshall 
55031455Sminshall 	    cmdname = getenv("SHELL");
55131455Sminshall 	    execlp(cmdname, cmdname, 0);
55231455Sminshall 	    perror("Exec'ing new shell...\n");
55331455Sminshall 	    exit(1);
55431455Sminshall 	} else {
55531455Sminshall 	    execvp(argv[1], &argv[1]);
55631455Sminshall 	    perror("Exec'ing command.\n");
55731455Sminshall 	    exit(1);
55831455Sminshall 	}
55931455Sminshall 	/*NOTREACHED*/
56031455Sminshall     }
56131457Sminshall     return shell_active;		/* Go back to main loop */
56231455Sminshall }
563