1*31457Sminshall #include <sys/types.h>
2*31457Sminshall #include <sys/socket.h>
3*31457Sminshall #include <netinet/in.h>
431455Sminshall #include <sys/wait.h>
531455Sminshall 
6*31457Sminshall #include <errno.h>
7*31457Sminshall extern int errno;
8*31457Sminshall 
9*31457Sminshall #include <netdb.h>
10*31457Sminshall #include <signal.h>
1131455Sminshall #include <stdio.h>
12*31457Sminshall #include <pwd.h>
1331455Sminshall 
1431455Sminshall #include "../general/general.h"
1531455Sminshall #include "../api/api.h"
16*31457Sminshall #include "api_exch.h"
1731455Sminshall 
1831455Sminshall #include "../general/globals.h"
1931455Sminshall 
2031455Sminshall 
2131455Sminshall static int shell_pid = 0;
2231455Sminshall 
23*31457Sminshall static char *ourENVlist[200];		/* Lots of room */
24*31457Sminshall 
25*31457Sminshall static int sock = -1;
26*31457Sminshall 
27*31457Sminshall static enum { DEAD, UNCONNECTED, CONNECTED } state;
28*31457Sminshall 
2931455Sminshall static int
30*31457Sminshall     storage_address,		/* Address we have */
31*31457Sminshall     storage_length = 0,		/* Length we have */
32*31457Sminshall     storage_must_send = 0,	/* Storage belongs on other side of wire */
33*31457Sminshall     storage_accessed = 0;	/* The storage is accessed (so leave alone)! */
34*31457Sminshall 
35*31457Sminshall static long storage[250];
36*31457Sminshall 
37*31457Sminshall union REGS inputRegs;
38*31457Sminshall struct SREGS inputSregs;
39*31457Sminshall 
40*31457Sminshall kill_connection()
41*31457Sminshall {
42*31457Sminshall     state = DEAD;
43*31457Sminshall     (void) close(sock);
44*31457Sminshall     sock = -1;
45*31457Sminshall }
46*31457Sminshall 
47*31457Sminshall 
48*31457Sminshall static int
4931455Sminshall child_died()
5031455Sminshall {
5131455Sminshall     union wait *status;
52*31457Sminshall     register int pid;
5331455Sminshall 
54*31457Sminshall     while ((pid = wait3(&status, WNOHANG, 0)) > 0) {
5531455Sminshall 	if (pid == shell_pid) {
56*31457Sminshall 	    char inputbuffer[100];
57*31457Sminshall 
5831455Sminshall 	    shell_active = 0;
59*31457Sminshall 	    if (sock != -1) {
60*31457Sminshall 		(void) close(sock);
61*31457Sminshall 		sock = -1;
62*31457Sminshall 		printf("[Hit return to continue]");
63*31457Sminshall 		fflush(stdout);
64*31457Sminshall 		(void) gets(inputbuffer);
65*31457Sminshall 		setconnmode();
66*31457Sminshall 		ConnectScreen();	/* Turn screen on (if need be) */
67*31457Sminshall 	    }
6831455Sminshall 	}
6931455Sminshall     }
7031455Sminshall     signal(SIGCHLD, child_died);
7131455Sminshall }
7231455Sminshall 
73*31457Sminshall static int
74*31457Sminshall nextchar()
75*31457Sminshall {
76*31457Sminshall     unsigned char c;
77*31457Sminshall 
78*31457Sminshall     if (read(sock, &c, 1) != 1) {
79*31457Sminshall 	return -1;
80*31457Sminshall     } else {
81*31457Sminshall 	return c;
82*31457Sminshall     }
83*31457Sminshall }
84*31457Sminshall 
85*31457Sminshall static int
86*31457Sminshall checktype(type)
87*31457Sminshall int type;
88*31457Sminshall {
89*31457Sminshall     int was;
90*31457Sminshall 
91*31457Sminshall     if ((was = nextchar()) != type) {
92*31457Sminshall 	fprintf(stderr, "Wrong type of data.  Should be 0x%02x, was 0x%02x.\n",
93*31457Sminshall 		type, was);
94*31457Sminshall 	return -1;
95*31457Sminshall     } else {
96*31457Sminshall 	return 0;
97*31457Sminshall     }
98*31457Sminshall }
99*31457Sminshall 
100*31457Sminshall 
101*31457Sminshall static int
102*31457Sminshall fill(where, length)
103*31457Sminshall char	*where;
104*31457Sminshall int	length;
105*31457Sminshall {
106*31457Sminshall     while (length) {
107*31457Sminshall 	int i;
108*31457Sminshall 
109*31457Sminshall 	if ((i = read(sock, where, length)) < 0) {
110*31457Sminshall 	    perror("read");
111*31457Sminshall 	    return -1;
112*31457Sminshall 	} else {
113*31457Sminshall 	    length -= i;
114*31457Sminshall 	    where += i;
115*31457Sminshall 	}
116*31457Sminshall     }
117*31457Sminshall }
118*31457Sminshall 
119*31457Sminshall 
120*31457Sminshall static int
121*31457Sminshall nextlength()
122*31457Sminshall {
123*31457Sminshall     short length;
124*31457Sminshall 
125*31457Sminshall     if (fill(&length, sizeof length) == -1) {
126*31457Sminshall 	return -1;
127*31457Sminshall     } else {
128*31457Sminshall 	return ntohs(length);
129*31457Sminshall     }
130*31457Sminshall }
131*31457Sminshall 
132*31457Sminshall 
133*31457Sminshall static int
134*31457Sminshall nextaddress()
135*31457Sminshall {
136*31457Sminshall     long address;
137*31457Sminshall 
138*31457Sminshall     return fill(&address, sizeof address);
139*31457Sminshall }
140*31457Sminshall 
141*31457Sminshall 
142*31457Sminshall 
143*31457Sminshall static int
144*31457Sminshall nextbytes(type, where, length)
145*31457Sminshall int	type;
146*31457Sminshall char	*where;
147*31457Sminshall int	length;
148*31457Sminshall {
149*31457Sminshall     int was;
150*31457Sminshall 
151*31457Sminshall     if (checktype(type) == -1) {
152*31457Sminshall 	return -1;
153*31457Sminshall     }
154*31457Sminshall     if ((was = nextlength()) != length) {
155*31457Sminshall 	fprintf(stderr, "Type 0x%02x had bad length.  Should be %d, was %d.\n",
156*31457Sminshall 		type, length, was);
157*31457Sminshall 	return -1;
158*31457Sminshall     } else {
159*31457Sminshall 	return fill(where, length);
160*31457Sminshall     }
161*31457Sminshall }
162*31457Sminshall 
163*31457Sminshall static int
164*31457Sminshall nextstore()
165*31457Sminshall {
166*31457Sminshall     if (nextchar() != EXCH_HEREIS) {
167*31457Sminshall 	fprintf(stderr, "Bad data from other side.\n");
168*31457Sminshall 	fprintf(stderr, "(Encountered at %s, %s.)\n", __FILE__, __LINE__);
169*31457Sminshall 	return -1;
170*31457Sminshall     }
171*31457Sminshall     if ((storage_address = nextaddress()) == -1) {
172*31457Sminshall 	storage_length = 0;
173*31457Sminshall 	return -1;
174*31457Sminshall     }
175*31457Sminshall     if ((storage_length = nextlength()) > sizeof storage) {
176*31457Sminshall 	fprintf(stderr, "API client tried to send too much storage (%d).\n",
177*31457Sminshall 		storage_length);
178*31457Sminshall 	return -1;
179*31457Sminshall     }
180*31457Sminshall     return fill((char *)storage, storage_length);
181*31457Sminshall }
182*31457Sminshall 
183*31457Sminshall 
184*31457Sminshall static int
185*31457Sminshall doreject(message)
186*31457Sminshall char	*message;
187*31457Sminshall {
188*31457Sminshall     int length = strlen(message);
189*31457Sminshall     char buffer[100];
190*31457Sminshall 
191*31457Sminshall     length = htons(length);
192*31457Sminshall     sprintf(buffer, "%c%c%c%s", EXCH_REJECTED, length>>8, length&0xff, buffer);
193*31457Sminshall     if (write(sock, buffer, length+3) != length+3) {
194*31457Sminshall 	perror("writing API socket");
195*31457Sminshall 	return -1;
196*31457Sminshall     }
197*31457Sminshall     return 0;
198*31457Sminshall }
199*31457Sminshall 
200*31457Sminshall 
20131455Sminshall /*
202*31457Sminshall  * doconnect()
203*31457Sminshall  *
204*31457Sminshall  * Negotiate with the other side and try to do something.
205*31457Sminshall  */
206*31457Sminshall 
207*31457Sminshall static int
208*31457Sminshall doconnect()
209*31457Sminshall {
210*31457Sminshall     struct passwd *pwent;
211*31457Sminshall     char
212*31457Sminshall 	promptbuf[100],
213*31457Sminshall 	buffer[200];
214*31457Sminshall     int promptlen, passwdlen;
215*31457Sminshall     int length;
216*31457Sminshall     int was;
217*31457Sminshall 
218*31457Sminshall     if ((pwent = getpwuid(geteuid())) == 0) {
219*31457Sminshall 	return -1;
220*31457Sminshall     }
221*31457Sminshall     sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name);
222*31457Sminshall     promptlen = strlen(promptbuf);
223*31457Sminshall     passwdlen = strlen(pwent->pw_name);
224*31457Sminshall     sprintf(buffer, "%c%c%c%s%c%c%s", EXCH_SEND_AUTH,
225*31457Sminshall 		promptlen>>8, promptlen&0xff, promptbuf,
226*31457Sminshall 		passwdlen>>8, passwdlen&0xff, pwent->pw_name);
227*31457Sminshall     length = strlen(buffer);
228*31457Sminshall     if (write(sock, buffer, length) != length) {
229*31457Sminshall 	perror("write to API socket");
230*31457Sminshall 	return -1;
231*31457Sminshall     }
232*31457Sminshall     if ((was = nextchar()) != EXCH_AUTH) {
233*31457Sminshall 	fprintf(stderr,
234*31457Sminshall 	    "API client sent command 0x%02x when EXCH_AUTH expected.\n", was);
235*31457Sminshall     }
236*31457Sminshall     if ((length = nextlength()) > sizeof buffer) {
237*31457Sminshall 	doreject("Password entered was too long");
238*31457Sminshall 	return 0;
239*31457Sminshall     }
240*31457Sminshall     if (fill(buffer, length) == -1) {
241*31457Sminshall 	return -1;
242*31457Sminshall     }
243*31457Sminshall     buffer[length] = 0;
244*31457Sminshall 
245*31457Sminshall     /* Is this the correct password? */
246*31457Sminshall     if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) == 0) {
247*31457Sminshall 	char code = EXCH_CONNECTED;
248*31457Sminshall 	if (write(sock, &code, 1) != 1) {
249*31457Sminshall 	    perror("writing to API socket");
250*31457Sminshall 	    return -1;
251*31457Sminshall 	}
252*31457Sminshall     } else {
253*31457Sminshall 	doreject("Invalid password");
254*31457Sminshall 	sleep(10);		/* Don't let us do too many of these */
255*31457Sminshall     }
256*31457Sminshall     return 0;
257*31457Sminshall }
258*31457Sminshall 
259*31457Sminshall 
260*31457Sminshall void
261*31457Sminshall freestorage()
262*31457Sminshall {
263*31457Sminshall     int i, j;
264*31457Sminshall     char buffer[40];
265*31457Sminshall 
266*31457Sminshall     if (storage_accessed) {
267*31457Sminshall 	fprintf(stderr, "Internal error - attempt to free accessed storage.\n");
268*31457Sminshall 	fprintf(stderr, "(Enountered in file %s at line %s.)\n",
269*31457Sminshall 			__FILE__, __LINE__);
270*31457Sminshall 	quit();
271*31457Sminshall     }
272*31457Sminshall     if (storage_must_send == 0) {
273*31457Sminshall 	return;
274*31457Sminshall     }
275*31457Sminshall     storage_must_send = 0;
276*31457Sminshall     i = htonl(storage_address);
277*31457Sminshall     j = htonl(storage_length);
278*31457Sminshall     sprintf(buffer, "%c%c%c%c%c%c%c",
279*31457Sminshall 		EXCH_HEREIS, i>>24, i>>16, i>>8, i, j>>8, j);
280*31457Sminshall     if (write(sock, buffer, 5) != 5) {
281*31457Sminshall 	perror("writing to API socket");
282*31457Sminshall 	kill_connection();
283*31457Sminshall 	return;
284*31457Sminshall     }
285*31457Sminshall     if (write(sock, (char *)storage, storage_length) != storage_length) {
286*31457Sminshall 	perror("writing to API socket");
287*31457Sminshall 	kill_connection();
288*31457Sminshall 	return;
289*31457Sminshall     }
290*31457Sminshall }
291*31457Sminshall 
292*31457Sminshall 
293*31457Sminshall void
294*31457Sminshall getstorage(address, length)
295*31457Sminshall {
296*31457Sminshall     int i, j;
297*31457Sminshall     char buffer[40];
298*31457Sminshall 
299*31457Sminshall     freestorage();
300*31457Sminshall     if (storage_accessed) {
301*31457Sminshall 	fprintf(stderr,
302*31457Sminshall 		"Internal error - attempt to get while storage accessed.\n");
303*31457Sminshall 	fprintf(stderr, "(Enountered in file %s at line %s.)\n",
304*31457Sminshall 			__FILE__, __LINE__);
305*31457Sminshall 	quit();
306*31457Sminshall     }
307*31457Sminshall     if (storage_must_send == 0) {
308*31457Sminshall 	return;
309*31457Sminshall     }
310*31457Sminshall     storage_must_send = 0;
311*31457Sminshall     i = htonl(storage_address);
312*31457Sminshall     j = htonl(storage_length);
313*31457Sminshall     sprintf(buffer, "%c%c%c%c%c%c%c",
314*31457Sminshall 		EXCH_GIMME, i>>24, i>>16, i>>8, i, j>>8, j);
315*31457Sminshall     if (write(sock, buffer, 5) != 5) {
316*31457Sminshall 	perror("writing to API socket");
317*31457Sminshall 	kill_connection();
318*31457Sminshall 	return;
319*31457Sminshall     }
320*31457Sminshall     if (nextstore() == -1) {
321*31457Sminshall 	kill_connection();
322*31457Sminshall 	return;
323*31457Sminshall     }
324*31457Sminshall }
325*31457Sminshall 
326*31457Sminshall void
327*31457Sminshall movetous(local, es, di, length)
328*31457Sminshall char
329*31457Sminshall     *local;
330*31457Sminshall int
331*31457Sminshall     es,
332*31457Sminshall     di;
333*31457Sminshall int
334*31457Sminshall     length;
335*31457Sminshall {
336*31457Sminshall     if (length > sizeof storage) {
337*31457Sminshall 	fprintf(stderr, "Internal API error - movetous() length too long.\n");
338*31457Sminshall 	fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
339*31457Sminshall 	quit();
340*31457Sminshall     } else if (length == 0) {
341*31457Sminshall 	return;
342*31457Sminshall     }
343*31457Sminshall     getstorage(di, length);
344*31457Sminshall     memcpy(local, storage+(di-storage_address), length);
345*31457Sminshall }
346*31457Sminshall 
347*31457Sminshall void
348*31457Sminshall movetothem(es, di, local, length)
349*31457Sminshall int
350*31457Sminshall     es,
351*31457Sminshall     di;
352*31457Sminshall char
353*31457Sminshall     *local;
354*31457Sminshall int
355*31457Sminshall     length;
356*31457Sminshall {
357*31457Sminshall     if (length > sizeof storage) {
358*31457Sminshall 	fprintf(stderr, "Internal API error - movetothem() length too long.\n");
359*31457Sminshall 	fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
360*31457Sminshall 	quit();
361*31457Sminshall     } else if (length == 0) {
362*31457Sminshall 	return;
363*31457Sminshall     }
364*31457Sminshall     freestorage();
365*31457Sminshall     memcpy((char *)storage, local, length);
366*31457Sminshall     storage_length = length;
367*31457Sminshall     storage_address = di;
368*31457Sminshall     storage_must_send = 1;
369*31457Sminshall }
370*31457Sminshall 
371*31457Sminshall 
372*31457Sminshall char *
373*31457Sminshall access_api(location, length)
374*31457Sminshall int
375*31457Sminshall     location,
376*31457Sminshall     length;
377*31457Sminshall {
378*31457Sminshall     if (storage_accessed) {
379*31457Sminshall 	fprintf(stderr, "Internal error - storage accessed twice\n");
380*31457Sminshall 	fprintf(stderr, "(Encountered in file %s, line %s.)\n",
381*31457Sminshall 				__FILE__, __LINE__);
382*31457Sminshall 	quit();
383*31457Sminshall     } else if (length != 0) {
384*31457Sminshall 	storage_accessed = 1;
385*31457Sminshall 	freestorage();
386*31457Sminshall 	getstorage(location, length);
387*31457Sminshall     }
388*31457Sminshall     return (char *) storage;
389*31457Sminshall }
390*31457Sminshall 
391*31457Sminshall unaccess_api(location, local, length)
392*31457Sminshall int	location;
393*31457Sminshall char	*local;
394*31457Sminshall int	length;
395*31457Sminshall {
396*31457Sminshall     if (storage_accessed == 0) {
397*31457Sminshall 	fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n");
398*31457Sminshall 	fprintf(stderr, "(Encountered in file %s, line %s.)\n",
399*31457Sminshall 			__FILE__, __LINE__);
400*31457Sminshall 	quit();
401*31457Sminshall     }
402*31457Sminshall     storage_accessed = 0;
403*31457Sminshall     storage_must_send = 1;	/* Needs to go back */
404*31457Sminshall }
405*31457Sminshall 
406*31457Sminshall 
407*31457Sminshall /*
40831455Sminshall  * shell_continue() actually runs the command, and looks for API
40931455Sminshall  * requests coming back in.
41031455Sminshall  *
41131455Sminshall  * We are called from the main loop in telnet.c.
41231455Sminshall  */
41331455Sminshall 
41431455Sminshall int
41531455Sminshall shell_continue()
41631455Sminshall {
417*31457Sminshall     switch (state) {
418*31457Sminshall     case DEAD:
419*31457Sminshall 	pause();			/* Nothing to do */
420*31457Sminshall 	break;
421*31457Sminshall     case UNCONNECTED:
422*31457Sminshall 	if (nextchar() != EXCH_CONNECT) {
423*31457Sminshall 	    kill_connection();
424*31457Sminshall 	} else {
425*31457Sminshall 	    switch (doconnect()) {
426*31457Sminshall 	    case -1:
427*31457Sminshall 		kill_connection();
428*31457Sminshall 		break;
429*31457Sminshall 	    case 0:
430*31457Sminshall 		break;
431*31457Sminshall 	    case 1:
432*31457Sminshall 		state = CONNECTED;
433*31457Sminshall 	    }
434*31457Sminshall 	}
435*31457Sminshall 	break;
436*31457Sminshall     case CONNECTED:
437*31457Sminshall 	if (nextchar() == EXCH_REQUEST) {
438*31457Sminshall 	    /* Eat up request packet. */
439*31457Sminshall 	    nextbytes(&inputRegs, sizeof inputRegs);
440*31457Sminshall 	    nextbytes(&inputSregs, sizeof inputSregs);
441*31457Sminshall 	    nextstore();		/* Initial storage sent */
442*31457Sminshall 	    handle_api(&inputRegs, &inputSregs);
443*31457Sminshall 	} else {
444*31457Sminshall 	    kill_connection();
445*31457Sminshall 	}
446*31457Sminshall     }
44731455Sminshall     return shell_active;
44831455Sminshall }
44931455Sminshall 
45031455Sminshall 
45131455Sminshall /*
45231455Sminshall  * Called from telnet.c to fork a lower command.com.  We
45331455Sminshall  * use the spint... routines so that we can pick up
45431455Sminshall  * interrupts generated by application programs.
45531455Sminshall  */
45631455Sminshall 
45731455Sminshall 
45831455Sminshall int
45931455Sminshall shell(argc,argv)
46031455Sminshall int	argc;
46131455Sminshall char	*argv[];
46231455Sminshall {
463*31457Sminshall     int serversock, length;
464*31457Sminshall     struct sockaddr_in server;
465*31457Sminshall     char sockNAME[100];
466*31457Sminshall     static char **whereAPI = 0;
467*31457Sminshall 
468*31457Sminshall     /* First, create the socket which will be connected to */
469*31457Sminshall     serversock = socket(AF_INET, SOCK_STREAM, 0);
470*31457Sminshall     if (serversock < 0) {
471*31457Sminshall 	perror("opening API socket");
472*31457Sminshall 	return 0;
473*31457Sminshall     }
474*31457Sminshall     server.sin_family = AF_INET;
475*31457Sminshall     server.sin_addr.s_addr = INADDR_ANY;
476*31457Sminshall     server.sin_port = 0;
477*31457Sminshall     if (bind(serversock, &server, sizeof server) < 0) {
478*31457Sminshall 	perror("binding API socket");
479*31457Sminshall 	return 0;
480*31457Sminshall     }
481*31457Sminshall     length = sizeof server;
482*31457Sminshall     if (getsockname(serversock, &server, &length) < 0) {
483*31457Sminshall 	perror("getting API socket name");
484*31457Sminshall 	(void) close(serversock);
485*31457Sminshall     }
486*31457Sminshall     listen(serversock, 1);
487*31457Sminshall     /* Get name to advertise in address list */
488*31457Sminshall     strcpy(sockNAME, "API3270=");
489*31457Sminshall     gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME));
490*31457Sminshall     if (strlen(sockNAME) > (sizeof sockNAME-10)) {
491*31457Sminshall 	fprintf(stderr, "Local hostname too large; using 'localhost'.\n");
492*31457Sminshall 	strcpy(sockNAME, "localhost");
493*31457Sminshall     }
494*31457Sminshall     sprintf(sockNAME+strlen(sockNAME), ":%d", ntohs(server.sin_port));
495*31457Sminshall 
496*31457Sminshall     if (whereAPI == 0) {
497*31457Sminshall 	char **ptr, **nextenv;
498*31457Sminshall 	extern char **environ;
499*31457Sminshall 
500*31457Sminshall 	ptr = environ;
501*31457Sminshall 	nextenv = ourENVlist;
502*31457Sminshall 	while (*ptr) {
503*31457Sminshall 	    if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) {
504*31457Sminshall 		fprintf(stderr, "Too many environmental variables\n");
505*31457Sminshall 		break;
506*31457Sminshall 	    }
507*31457Sminshall 	    *nextenv++ = *ptr++;
508*31457Sminshall 	}
509*31457Sminshall 	whereAPI = nextenv++;
510*31457Sminshall 	*nextenv++ = 0;
511*31457Sminshall 	environ = ourENVlist;		/* New environment */
512*31457Sminshall     }
513*31457Sminshall     *whereAPI = sockNAME;
514*31457Sminshall 
515*31457Sminshall     child_died();			/* Start up signal handler */
516*31457Sminshall     shell_active = 1;			/* We are running down below */
517*31457Sminshall     if (shell_pid = vfork()) {
518*31457Sminshall 	if (shell_pid == -1) {
519*31457Sminshall 	    perror("vfork");
520*31457Sminshall 	    (void) close(serversock);
521*31457Sminshall 	} else {
522*31457Sminshall 	    fd_set fdset;
523*31457Sminshall 	    int i;
524*31457Sminshall 
525*31457Sminshall 	    FD_ZERO(&fdset);
526*31457Sminshall 	    FD_SET(serversock, &fdset);
527*31457Sminshall 	    while (shell_active) {
528*31457Sminshall 		if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) {
529*31457Sminshall 		    if (errno = EINTR) {
530*31457Sminshall 			continue;
531*31457Sminshall 		    } else {
532*31457Sminshall 			perror("in select waiting for API connection");
533*31457Sminshall 			break;
534*31457Sminshall 		    }
535*31457Sminshall 		} else {
536*31457Sminshall 		    i = accept(serversock, 0, 0);
537*31457Sminshall 		    if (i == -1) {
538*31457Sminshall 			perror("accepting API connection");
539*31457Sminshall 		    }
540*31457Sminshall 		    sock = i;
541*31457Sminshall 		    break;
542*31457Sminshall 		}
543*31457Sminshall 	    }
544*31457Sminshall 	    (void) close(serversock);
545*31457Sminshall 	    /* If the process has already exited, we may need to close */
546*31457Sminshall 	    if ((shell_active == 0) && (sock != -1)) {
547*31457Sminshall 		(void) close(sock);
548*31457Sminshall 		sock = -1;
549*31457Sminshall 		setcommandmode();	/* In case child_died sneaked in */
550*31457Sminshall 	    }
551*31457Sminshall 	}
55231455Sminshall     } else {				/* New process */
55331455Sminshall 	register int i;
55431455Sminshall 
55531455Sminshall 	for (i = 3; i < 30; i++) {
55631455Sminshall 	    (void) close(i);
55731455Sminshall 	}
55831455Sminshall 	if (argc == 1) {		/* Just get a shell */
55931455Sminshall 	    char *cmdname;
560*31457Sminshall 	    extern char *getenv();
56131455Sminshall 
56231455Sminshall 	    cmdname = getenv("SHELL");
56331455Sminshall 	    execlp(cmdname, cmdname, 0);
56431455Sminshall 	    perror("Exec'ing new shell...\n");
56531455Sminshall 	    exit(1);
56631455Sminshall 	} else {
56731455Sminshall 	    execvp(argv[1], &argv[1]);
56831455Sminshall 	    perror("Exec'ing command.\n");
56931455Sminshall 	    exit(1);
57031455Sminshall 	}
57131455Sminshall 	/*NOTREACHED*/
57231455Sminshall     }
573*31457Sminshall     return shell_active;		/* Go back to main loop */
57431455Sminshall }
575