1 /*
2  * Copyright (c) 1994  Sony Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL SONY CORPORATION BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
21  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Except as contained in this notice, the name of Sony Corporation
24  * shall not be used in advertising or otherwise to promote the sale, use
25  * or other dealings in this Software without prior written authorization
26  * from Sony Corporation.
27  *
28  */
29 
30 /*
31  * $SonyRCSfile: sj3.c,v $
32  * $SonyRevision: 1.7 $
33  * $SonyDate: 1997/01/23 11:26:30 $
34  */
35 
36 
37 
38 #include <stdlib.h>
39 #include <string.h>
40 #include "sj_sysvdef.h"
41 #include "wchar16.h"
42 #include <signal.h>
43 #include <unistd.h>
44 #include <errno.h>
45 #include <sys/errno.h>
46 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__OpenBSD__)
47 #if defined(__NetBSD__) || defined(__bsdi__)
48 #define	USE_OLD_TTY
49 #if defined(__NetBSD__)
50 #define LACKOF_SETLOCALE
51 #endif
52 #endif
53 #if defined(__OpenBSD__)
54 #include <sys/ioctl_compat.h>
55 #endif
56 #include <curses.h>
57 #endif
58 
59 #include "select.h"
60 #include "common.h"
61 #ifdef SVR4
62 #include <sys/fcntl.h>
63 #include <sys/stropts.h>
64 #include <netdb.h>
65 #endif
66 #include <locale.h>
67 
68 #include "sj3.h"
69 
70 #ifndef _PATH_UTMP
71 #define _PATH_UTMP "/etc/utmp"
72 #endif
73 
74 #ifdef SVR4
75 #define killpg(pid, sig) kill(-(pid),(sig))
76 #define signal sigset
77 #endif
78 #ifndef linux
79 #define	DEFAULTSHELL	"/bin/csh"
80 #else
81 #define DEFAULTSHELL	"/bin/sh"
82 #endif
83 
84 #include <termios.h>
85 
86 int	Lflag = 0;
87 int	shell_flag = 0;
88 
89 
90 
91 char	progname[LONGLENGTH];
92 char	shellname[LONGLENGTH];
93 char	home[LONGLENGTH];
94 char	user_name[SHORTLENGTH];
95 char	term_name[SHORTLENGTH];
96 char	shellprog[LONGLENGTH];
97 char	tty_name[SHORTLENGTH];
98 #ifdef SVR4
99 char    *slave_name;
100 #else
101 char	slave_name[SHORTLENGTH];
102 #endif
103 char	*shellargs[SHORTLENGTH];
104 #ifdef SVR4
105 char	*mptname = "/dev/ptmx";
106 char    *ptsname();
107 #else
108 static char	line[SHORTLENGTH];
109 #endif
110 char  *cur_serv;
111 
112 char  my_hname[MAXHOSTNAMELEN];
113 char  **serv_list;
114 
115 #ifdef SYSV_TERMIOS
116 struct	winsize	Ttysize;
117 #define ts_lines ws_row
118 #define ts_cols ws_col
119 #else
120 struct	ttysize	Ttysize;
121 #endif
122 int	Ttyslot;
123 int	master;
124 int	slave;
125 
126 #ifdef SYSV_TERMIOS
127 struct	termios	b;
128 #else
129 struct	sgttyb	b;
130 struct	tchars	tc, tc1;
131 struct	ltchars	lc, lc1;
132 int	lb;
133 int	l;
134 #endif
135 #ifdef __sony_news
136 int	jmode, jmode2;
137 struct	jtchars	jtc;
138 #endif
139 int	erase_char;
140 wchar16_t	erase_str[2];
141 #ifdef SIGTYPE_VOID
142 void	(*sigpipe)();
143 #else
144 int	(*sigpipe)();
145 #endif
146 
147 int Pid_shell;
148 
149 
150 int current_locale;
151 
main(int argc,char ** argv)152 main (int argc, char **argv)
153 {
154 	init (argv);
155 	get_ttymode ();
156 	init_messages ();
157 	parsearg (argc, argv);
158 	InitConversion ();
159 	checkterm ();
160 	getsjrc ();
161 	print_version ();
162 	getsjrk(erase_char);
163 	sjinit ();
164 	forkshell ();
165 	inputprocess ();
166 	done ();
167 }
168 
169 void
makecore()170 makecore()
171 {
172 	chdir ("/tmp");
173 	setgid (getgid ());
174 	setuid (getuid ());
175 	abort ();
176 }
177 
178 
179 
180 void
init(char ** argv)181 init(char **argv)
182 {
183 	char		*cp, *strrchr ();
184 
185 	(void) signal (SIGTERM, (void (*)())done);
186 	(void) signal (SIGWINCH, SIG_IGN);
187 	(void) signal (SIGQUIT, (void (*)())makecore);
188 	(void) signal (SIGBUS, (void (*)())makecore);
189 	(void) signal (SIGSEGV, (void (*)())makecore);
190 	(void) signal (SIGFPE, (void (*)())makecore);
191 /*
192  * Remove warning.
193  * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp)		1996/8/10
194  */
195 #ifdef SIGTYPE_VOID
196 	sigpipe = (void(*)()) signal (SIGPIPE, SIG_IGN);
197 #else
198 	sigpipe = (int(*)()) signal (SIGPIPE, SIG_IGN);
199 #endif
200 
201 	if (argv [0][0] == '-')
202 		Lflag ++;
203 	if ((cp = strrchr (argv [0], '/')) == NULL)
204 		cp = argv [0];
205 	else
206 		cp ++;
207 	strlcpy(progname, cp, sizeof(progname));
208 	init_env();
209 }
210 
211 
212 
213 void
init_env()214 init_env()
215 {
216 	char *uname, *hp, *tname;
217 	int  i;
218 	struct passwd  *pwd, *getpwnam(), *getpwuid();
219 	char	*getlogin(), *getenv();
220 
221 	user_name[0] = '\0';
222 	home[0] = '\0';
223 	shellprog[0] = '\0';
224 
225         gethostname(my_hname, MAXHOSTNAMELEN);
226         if ((serv_list = (char **)malloc(MAXSERVER * sizeof(char *))) == NULL){
227                 fprintf (stderr, "init_env: can't alloc memory\n\r");
228                 done3();
229         }
230         for (i = 0; i < MAXSERVER; i++)
231                 serv_list[i] = NULL;
232         cur_serv = NULL;
233 
234 	uname = getlogin ();
235 	hp = getenv("HOME");
236 
237 	setpwent ();
238 	if( uname == NULL || *uname == '\0' )
239 		pwd = getpwuid(getuid());
240 	else
241 		pwd = getpwnam(uname);
242 	if (pwd != NULL) {
243 		strlcpy(user_name, pwd -> pw_name, sizeof(user_name));
244 		if (hp == NULL)
245 			hp = pwd->pw_dir;
246 		endpwent();
247 	}
248 	if (hp != NULL)
249 		strlcpy(home, hp, sizeof(home));
250 
251 	if ((tname = getenv("TERM")) == NULL) {
252 		aprintf ("Can't getenv TERM\n\r");
253 		perror("getenv");
254 		exit(1);
255 	}
256 	strlcpy(term_name, tname, sizeof(term_name));
257 }
258 
259 
260 
261 void
parsearg(int argc,char ** argv)262 parsearg(int argc, char **argv)
263 {
264 	int	ap;
265 	char	c;
266 	int	sp;
267 	char	**shella;
268 
269 	shella = shellargs;
270 	ap = 1;
271 	-- argc;
272         while (argc > 0) {
273 		if (*argv[ap] == '-') {
274 			c = argv[ap][1];
275 			switch (c) {
276 			case 'L':
277 				Lflag ++;
278 				break;
279 			case 'E':
280 				aprintf ("euc mode\n\r");
281 				set_eucmode ();
282 				break;
283 			case 'V':
284 				vflag = 0;
285 				break;
286 			case 'v':
287 				aprintf ("verbose\n\r");
288 				vflag ++;
289 				break;
290 			case 'f':
291 				if (argv[ap + 1] == (char *) NULL)
292 					usage ();
293                                 strlcpy(shellprog, argv[ap+1], sizeof(shellprog));
294 				shell_flag ++;
295 				break;
296 			case 'e':
297 				if (argv[ap + 1] == (char *) NULL)
298 					usage ();
299                                 strlcpy(shellprog, argv[++ap],sizeof(shellprog));
300                                 sp = 0;
301 				while (argv[ap] != (char *) NULL)
302 					shella[sp++] = argv[ap++];
303 				shella[sp] = (char *) NULL;
304 				break;
305 #ifdef OKB
306 			case 'o':
307 				oasys ++;
308 				break;
309 #endif
310 			case 'H':
311 				if (argv[ap + 1] == (char *) NULL)
312 					usage();
313 
314 
315                                 sp = 0;
316                                 while (argc > 1 && *argv[ap + 1] != '-') {
317                                         if (sp >= MAXSERVER)
318                                                 break;
319                                         serv_list[sp++] = argv[ap + 1];
320                                         ap++;
321                                         argc--;
322                                 }
323                                 cur_serv = serv_list[0];
324 
325 
326 				break;
327 			case 'h':
328 			default:
329 				usage ();
330 				break;
331 			}
332 		}
333 		argc --;
334 		ap ++;
335 	}
336         if (cur_serv == NULL || *cur_serv == '\0')
337                 setsjserv(getenv("SJ3SERV"));
338 }
339 
340 
341 
342 void
usage()343 usage()
344 {
345 	aprintf ("Usage: %s [-option ...]\n\r", progname);
346 	aprintf ("\t-option\n\r");
347 	aprintf ("\t\t-h             \thelp\n\r");
348 	aprintf ("\t\t-L             \tlogin shell\n\r");
349 	aprintf ("\t\t-f shellname   \texec shell name\n\r");
350 	aprintf ("\t\t-e command...  \texec command arguments\n\r");
351 #ifdef OKB
352 	aprintf ("\t\t-o             \toyayubi shift keyboard\n\r");
353 #endif
354         aprintf ("\t\t-H hostname... \tname list of server hosts\n\r");
355 	if (vflag > 2) {
356 		aprintf ("\t\t-v          \tverbose mode\n\r");
357 		aprintf ("\t\t-E             \tEUC mode\n\r");
358 	}
359 	exit (1);
360 }
361 
362 
363 
364 void
sjinit()365 sjinit()
366 {
367 	getfixtty ();
368 	setshellname ();
369 
370         if (cur_serv == NULL)
371                 cur_serv = serv_list[0] = my_hname;
372 	SJ2_henkan_init ();
373 	start_guideline ();
374 }
375 
376 
377 
378 void
setshellname()379 setshellname()
380 {
381 	char	*s;
382 	char	*namep, *strrchr (), *getenv();
383 
384 	if (shellprog[0] == '\0') {
385 		s = getenv ("SHELL");
386 		if ((s == NULL) || (*s == '\0') || Lflag)
387 			strlcpy(shellprog, DEFAULTSHELL, sizeof(shellprog));
388 		else
389 			strlcpy(shellprog, s, sizeof(shellprog));
390 	}
391 	if ((namep = strrchr (shellprog, '/')) == NULL)
392 		namep = shellprog;
393 	else
394 		namep ++;
395 
396 	if (Lflag)
397 		snprintf(shellname, sizeof(shellname), "-%s[%s on %s]", namep, user_name, progname);
398 #ifndef SVR4
399 	else
400 		snprintf(shellname, sizeof(shellname), "J%s[%s on %s]", namep, user_name, progname);
401 #endif
402 }
403 
404 
405 
406 void
getfixtty()407 getfixtty()
408 {
409 	getmaster ();
410 	fixtty ();
411 	setdev ();
412 }
413 
414 
415 
416 void
get_ttymode()417 get_ttymode()
418 {
419 #ifdef SYSV_TERMIOS
420 	tcgetattr (0, &b);
421 	erase_char = b.c_cc[VERASE];
422 	set_bs(erase_char);
423 	erase_str[0] = erase_char;
424 	erase_str[1] = '\0';
425 #else
426 	ioctl (0, TIOCGETP, (char *)&b);
427 	erase_char = b.sg_erase;
428 	set_bs(erase_char);
429 	erase_str[0] = erase_char;
430 	erase_str[1] = '\0';
431 	ioctl (0, TIOCGETC, (char *)&tc);
432 	ioctl (0, TIOCGETC, (char *)&tc1);
433 	ioctl (0, TIOCGETD, (char *)&l);
434 	ioctl (0, TIOCGLTC, (char *)&lc);
435 	ioctl (0, TIOCGLTC, (char *)&lc1);
436 	ioctl (0, TIOCLGET, (char *)&lb);
437 #endif
438 #ifdef __sony_news
439 	ioctl (0, TIOCKGET, (char *)&jmode);
440 	jmode2 = set_jmode (jmode);
441 	ioctl (0, TIOCKGETC, (char *)&jtc);
442 #else
443 	(void) set_jmode(0);
444 #endif
445 }
446 
447 
448 
449 void
getmaster()450 getmaster()
451 {
452 #ifdef SVR4
453 	struct stat	stb;
454 
455 	if ((master = open(mptname, O_RDWR)) < 0) {
456 		aprintf ("Out of pty's\n\r");
457 		done3 ();
458 	}
459 
460 	ioctl(master, I_PUSH, "pckt");
461 #else
462 /*
463  * Change pseudo-devices.
464  * Because FreeBSD's master pseudo-devices are pty[p-sP-S][0-9a-v].
465  * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp)		1996/8/10
466  */
467 #if defined(__FreeBSD__) || defined(__OpenBSD__)
468 	struct stat	stb;
469 	int		h, i, j, k1, k2;
470 #else /* !__FreeBSD__ */
471 	char		c;
472 	struct stat	stb;
473 	int		i, j, k1, k2;
474 #endif /* __FreeBSD__ */
475 
476 	strlcpy(line, "/dev/ptyXX", sizeof(line));
477 
478 	k1 = strlen("/dev/pty");
479 	k2 = strlen ("/dev/ptyp");
480 
481 /*
482  * Change pseudo-devices.
483  * Because FreeBSD's master pseudo-devices are pty[p-sP-S][0-9a-v].
484  * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp)		1996/8/10
485  */
486 #if defined(__FreeBSD__) || defined(__OpenBSD__)
487 	for (h = 0; h < 8; h++) {
488 		line[k1] = "pqrsPQRS"[h];
489 		line[k2] = '0';
490 		if (stat (line, &stb) < 0)
491 			break;
492 		for (i = 0; i < 32; i++) {
493 			line[k2] = "0123456789abcdefghijklmnopqrstuv"[i];
494 #else /* !__FreeBSD__ */
495 	for (c = 'p'; c <= 'z'; c ++) {
496 		line[k1] = c;
497 		line[k2] = '0';
498 		if (stat (line, &stb) < 0)
499 			break;
500 		for (i = 0; i < 16; i++) {
501 			line[k2] = "0123456789abcdef"[i];
502 #endif /* __FreeBSD__ */
503 			master = open (line, 2);
504 			if (master >= 0) {
505 				j = 1;
506 				ioctl (master, TIOCPKT, &j);
507 				return;
508 			}
509 		}
510 	}
511 	aprintf ("Out of pty's\n\r");
512 	done3 ();
513 #endif
514 }
515 
516 void
517 set_jmode(int mode)
518 {
519 #ifdef __sony_news
520 	int	term_mode;
521 
522 	term_mode = mode & KM_KANJI;
523 	if (term_mode == KM_JIS) {
524 		aprintf ("error: tty jis terminal mode\n\r");
525 		fflush (stdout);
526 		exit (1);
527 	}
528 	if (term_mode == KM_ASCII) {
529 		aprintf ("error: tty ascii terminal mode\n\r");
530 		fflush (stdout);
531 		exit (1);
532 	}
533 	else if (term_mode == KM_EUC) {
534 		set_eucmode ();
535 		mode &= ~KM_SYSSJIS;
536 		mode |= KM_SYSEUC;
537 		(void) setlocale(LC_CTYPE, "ja_JP.EUC");
538 		current_locale = LC_CTYPE_EUC;
539 	}
540 	else if (term_mode == KM_SJIS) {
541 		mode &= ~KM_SYSEUC;
542 		mode |= KM_SYSSJIS;
543 		(void) setlocale(LC_CTYPE, "ja_JP.SJIS");
544 		current_locale = LC_CTYPE_SHIFTJIS;
545         } else {
546 		aprintf ("error: unknown tty terminal code\n\r");
547 		fflush (stdout);
548 		exit (1);
549 	}
550 	return (mode);
551 #else
552 	char *loc;
553 
554 #ifdef LACKOF_SETLOCALE
555 	loc = getenv("LANG");
556 #else
557 	loc = setlocale(LC_CTYPE, "");
558 #endif
559 	if (!loc) {
560 		aprintf("error: bad locale\n");
561 		fflush(stdout);
562 		exit(1);
563 	}
564 	if (strcmp(loc, "ja_JP.SJIS") == 0) {
565 		current_locale = LC_CTYPE_SHIFTJIS;
566 	} else if (strncmp(loc, "ja", 2) == 0 ||
567 		   strncmp(loc, "Ja", 2) == 0) {
568 		current_locale = LC_CTYPE_EUC;
569 		set_eucmode();
570 	} else {
571 		aprintf("error: This locale will not use japanese.\n");
572 		fflush(stdout);
573 		exit(1);
574 	}
575 #endif /* __sony_news */
576 }
577 
578 
579 
580 void
581 fixtty()
582 {
583 #ifdef SYSV_TERMIOS
584 	struct termios sbuf;
585 
586 	sbuf = b;
587 	sbuf.c_iflag &= ~(INLCR|IGNCR|ICRNL|IXON);
588 	sbuf.c_oflag &= ~(ONLCR|OPOST);
589 	sbuf.c_lflag &= ~(ICANON|ECHO);
590 	sbuf.c_cc[VMIN] = 1;
591 	sbuf.c_cc[VTIME] = 0;
592 	sbuf.c_cc[VINTR] = 0;
593 	sbuf.c_cc[VQUIT] = 0;
594 	sbuf.c_cc[VSUSP] = 0;
595 #ifdef VDSUSP
596 	sbuf.c_cc[VDSUSP] = 0;
597 #endif /* VDSUSP */
598 	sbuf.c_cc[VREPRINT] = 0;
599 	sbuf.c_cc[VDISCARD] = 0;
600 	sbuf.c_cc[VWERASE] = 0;
601 	sbuf.c_cc[VLNEXT] = 0;
602 	(void) tcsetattr(0, TCSADRAIN, &sbuf);
603 #else
604 	struct sgttyb sbuf;
605 
606 	sbuf = b;
607 	sbuf.sg_flags &= ~(EVENP|ODDP|ECHO|CRMOD|RAW|TBDELAY);
608 	sbuf.sg_flags |= CBREAK;
609 	sbuf.sg_flags |= TANDEM;
610 	ioctl (0, TIOCSETN, (char *)&sbuf);
611 
612 
613 
614 	tc1.t_intrc = -1;
615 	tc1.t_quitc = -1;
616 	tc1.t_eofc = -1;
617 	ioctl (0, TIOCSETC, (char *)&tc1);
618 
619 	lc1.t_suspc = -1;
620 	lc1.t_dsuspc = -1;
621 	lc1.t_rprntc = -1;
622 	lc1.t_flushc = -1;
623 	lc1.t_werasc = -1;
624 	lc1.t_lnextc = -1;
625 	ioctl (0, TIOCSLTC, (char *)&lc1);
626 #endif
627 
628 #ifdef __sony_news
629         ioctl (0, TIOCKSET, (char *)&jmode2);
630 #endif
631 }
632 
633 #ifdef BSD43
634 #include <grp.h>
635 #endif
636 
637 void
638 setdev()
639 {
640 	char	*cp;
641 #ifdef BSD43
642 	struct group	*ttygrp;
643 #endif
644 	Conversion	*cv;
645 
646 	cv = current_conversion;
647 
648 	if (cp = ttyname (2))
649 		strlcpy(tty_name, cp, sizeof(tty_name));
650 	else
651 		*tty_name = '\0';
652 #ifndef SVR4
653 	strlcpy(slave_name, line, sizeof(slave_name));
654 	slave_name[strlen ("/dev/")] = 't';
655 #endif
656 #ifdef BSD43
657 	if (ttygrp = getgrnam ("tty"))
658 		chown(slave_name, getuid(), ttygrp->gr_gid);
659 	else
660 		chown(slave_name, getuid(), getgid());
661 	chmod(slave_name, 0620);
662 #else
663 	chown(slave_name, getuid(), getgid());
664 	chmod(slave_name, 0622);
665 #endif
666 #ifndef SYSV_TERMIOS
667 	Ttyslot = nmttyslot (slave_name);
668 #endif
669 
670 
671 
672 #ifdef SYSV_TERMIOS
673 	if (ioctl(0, TIOCGWINSZ, &Ttysize) == 0) {
674 #else
675 	if (ioctl(0, TIOCGSIZE, &Ttysize) == 0) {
676 #endif
677 		if (!status_line)
678 			--Ttysize.ts_lines;
679 		if (Ttysize.ts_lines < 1) {
680 			aprintf ("not enough lines\n\r");
681 			done3 ();
682 		}
683 		if (Ttysize.ts_cols < 1) {
684 			aprintf ("not enough columns\n\r");
685 			done3 ();
686 		}
687 		cv->line = Ttysize.ts_lines;
688 		cv->column = Ttysize.ts_cols;
689 		SetRegion ();
690 	} else {
691 	        if (cv->line < 1) cv->line = 24;
692 	        if (cv->column < 1) cv->column = 80;
693 		Ttysize.ts_lines = cv->line;
694 		Ttysize.ts_cols = cv->column;
695 		if (ioctl(0, TIOCSWINSZ, &Ttysize) < 0) {
696 		    aprintf("Warnning: Can't get tty size, use rows(%d) and columns(%d).\n\r",
697 			    cv->line, cv->column);
698 		}
699 		if (!status_line) {
700 			Ttysize.ts_lines--;
701 			cv->line--;
702 		}
703 		SetRegion ();
704 	}
705 	if (cv->column < MINCOL) {
706 		if (Hlevel > 1)
707 			Hlevel = 1;
708 	}
709 	else if (HHlevel > 1) {
710 		Hlevel = 2;
711 	}
712 
713 	if (vflag > 1) {
714 		aprintf ("line %d\n\r", cv->line);
715 		aprintf ("column %d\n\r", cv->column);
716 	}
717 
718 #ifndef SVR4
719 /*
720  * Remove warning.
721  * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp)		1996/8/10
722  */
723 	(void) signal (SIGCHLD, (void (*)())exitprocess);
724 #endif
725 }
726 
727 
728 
729 static char	shellbuf[128];
730 
731 void
732 forkshell()
733 {
734 #ifdef SVR4
735   struct sigaction action;
736   sigset_t sset;
737 #endif
738 	Pid_shell = fork ();
739 	if (Pid_shell < 0) {
740 		perror ("fork");
741 		done ();
742 	}
743 	if (Pid_shell == 0) {
744 		shellprocess ();
745 	}
746 
747 	if (vflag > 1) {
748 		aprintf ("sj3   pid = %d\n\r", getpid ());
749 		aprintf ("shell pid = %d\n\r", Pid_shell);
750 	}
751 
752 	(void) signal (SIGHUP, (void (*)())fail);
753 	(void) signal (SIGINT, (void (*)())fail);
754 	(void) signal (SIGTERM, (void (*)())fail);
755 	(void) signal (SIGWINCH, (void (*)())onwinch);
756 #ifdef SVR4
757         (void) sigemptyset(&sset);
758         (void) sigaddset(&sset, SIGCHLD);
759         action.sa_handler = (void (*)()) exitprocess;
760         action.sa_mask =  sset;
761         action.sa_flags = SA_RESTART;
762         (void) sigaction(SIGCHLD, &action, NULL);
763 #endif
764 }
765 
766 extern char **environ;
767 
768 void
769 sj3_setenv(char *ename, char *eval, char *buf, int len)
770 {
771 	char *cp, *dp;
772 	char **ep = environ;
773 	int rest = len;
774 
775 
776 	while (dp = *ep++) {
777 		for (cp = ename; *cp == *dp && *cp; cp++, dp++)
778 			continue;
779 		if (*cp == 0 && (*dp == '=' || *dp == 0)) {
780 			strlcat(buf, eval, rest);
781 			rest -= strlen(eval);
782 			*--ep = buf;
783 			return;
784 		}
785 	}
786 }
787 
788 
789 
790 void
791 shellprocess()
792 {
793 	int			t, f;
794 #if 0
795 #ifdef SYSV_UTMP
796 	struct utmp Utmp;
797 #else
798 	struct utmpx Utmp;
799 #endif
800 
801 
802 	setsid();
803 	getslave ();
804 
805 	memset ((char *) &Utmp, '\0', sizeof (Utmp));
806 	(void) strncpy(Utmp.ut_user, user_name, sizeof(Utmp.ut_user));
807 	(void) strncpy(Utmp.ut_line, &slave_name[sizeof("/dev/")-1],
808 							sizeof(Utmp.ut_line));
809 	Utmp.ut_type = USER_PROCESS;
810 #ifdef SYSV_UTMP
811 	Utmp.ut_pid = (pid_t)getpid();
812 	strncpy(Utmp.ut_id, &Utmp.ut_line[2], 4);
813 	Utmp.ut_id[0] = 't';
814 	Utmp.ut_time = time(0);
815 	setutent();
816 	getutid(&Utmp);
817 	pututline(&Utmp);
818 	endutent();
819 #else
820 	Utmp.ut_pid = (o_pid_t)getpid();
821 	Utmp.ut_id[0] = 's';
822 	Utmp.ut_id[1] = 'j';
823 	Utmp.ut_id[2] = SC_WILDC;
824 	Utmp.ut_id[3] = SC_WILDC;
825 	Utmp.ut_exit.e_termination = 0;
826 	Utmp.ut_exit.e_exit = 0;
827 	(void) time (&Utmp.ut_tv.tv_sec);
828 	if (makeutx(&Utmp) == NULL)
829 		aprintf ("%s:\tmakeutx failed\r\n", progname);
830 #endif /* SYSV_UTMP */
831 #else /* SYSV_TERMIOS */
832 	struct utmp		Utmp;
833 	char		*p;
834 /*
835  * Remove warning.
836  * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp)		1996/8/10
837  */
838 	char			*ttyname (), *strrchr ();
839 #define SCPYN(a, b) strncpy(a, b, sizeof(a))
840 
841 	if ((p = ttyname (0)) == NULL)
842 		SCPYN(Utmp.ut_host, progname);
843 	else {
844 		SCPYN(Utmp.ut_host, progname);
845 		strlcat(Utmp.ut_host, " on ", sizeof(Utmp.ut_host));
846 		p = strrchr (p, '/') + 1;
847 		strlcat(Utmp.ut_host, p, sizeof(Utmp.ut_host));
848 	}
849 	SCPYN(Utmp.ut_name, user_name);
850 	SCPYN(Utmp.ut_line, strrchr (slave_name, '/') + 1);
851 	time (&Utmp.ut_time);
852 
853 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__OpenBSD__)
854 	if (setsid() < 0)
855 		perror("setsid()");
856 #else
857 	t = open ("/dev/tty", 2);
858 	if (t >= 0) {
859 		ioctl (t, TIOCNOTTY, (char *)0);
860 		(void) close(t);
861 	}
862 #endif
863 
864 	getslave ();
865 #endif /* SYSV_TERMIOS */
866 	(void) close (master);
867 	dup2 (slave, 0);
868 	dup2 (slave, 1);
869 	dup2 (slave, 2);
870 	(void) close (slave);
871 
872 #ifndef SYSV_TERMIOS
873 	if (Ttyslot > 0 && (f = open (_PATH_UTMP, 1)) >= 0) {
874 		lseek (f, (long) (Ttyslot * sizeof (Utmp)), 0);
875 		write (f, (char *)&Utmp, sizeof (Utmp));
876 		close (f);
877 	}
878 #endif /* SYSV_TERMIOS */
879 
880 	setgid (getgid ());
881 	setuid (getuid ());
882 
883 	if (shellargs[0] == (char *) NULL) {
884 		shellargs[0] = shellname;
885 		shellargs[1] = (char *) 0;
886 	}
887 
888 /*
889  * Remove warning.
890  * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp)		1996/8/10
891  */
892 	(void) signal (SIGPIPE, (void (*)())sigpipe);
893 	if ( *shellprog == '/' ) {
894 		if (shell_flag) {
895 			strlcpy(shellbuf, "SHELL=", sizeof(shellbuf));
896 			sj3_setenv("SHELL", shellprog, shellbuf, sizeof(shellbuf));
897 		}
898 		(void) execve (shellprog, shellargs, environ);
899 	}
900 	else
901 		execcmd (shellprog, shellargs);
902 
903 	perror (shellprog);
904 	exit (1);
905 }
906 
907 
908 
909 void
910 getslave()
911 {
912 #ifdef SVR4
913 	grantpt(master);
914 	unlockpt(master);
915 	slave_name = ptsname(master);
916 	slave = open(slave_name, O_RDWR);
917 	if (slave < 0) {
918 		perror(slave_name);
919 		done2();
920 	}
921 	ioctl(slave, I_PUSH, "ptem");
922 	ioctl(slave, I_PUSH, "ldterm");
923 	ioctl(slave, I_PUSH, "ttcompat");
924 
925 	(void) ioctl(slave, TCSETSF, (char *)&b);
926 	(void) ioctl(slave, TIOCSWINSZ, (char *)&Ttysize);
927 #ifdef __sony_news
928 	(void) ioctl(slave, TIOCKSET, (char *)&jmode);
929 	(void) ioctl(slave, TIOCKSETC, (char *)&jtc);
930 #endif
931 #else
932 	line[strlen ("/dev/")] = 't';
933 	slave = open (line, 2);
934 	if (slave < 0) {
935 		perror (line);
936 		done2 ();
937 	}
938 #ifndef SYSV_TERMIOS
939 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__OpenBSD__)
940 	ioctl(slave, TIOCSCTTY, NULL);
941 #endif
942 	ioctl (slave, TIOCSETP, (char *)&b);
943 	ioctl (slave, TIOCSETC, (char *)&tc);
944 	ioctl (slave, TIOCSLTC, (char *)&lc);
945 	ioctl (slave, TIOCLSET, (char *)&lb);
946 	ioctl (slave, TIOCSETD, (char *)&l);
947 #ifdef __sony_news
948 	ioctl (slave, TIOCKSET, (char *)&jmode);
949 	ioctl (slave, TIOCKSETC, (char *)&jtc);
950 #endif
951 	ioctl (slave, TIOCSSIZE, &Ttysize);
952 #else /* SYSV_TERMIOS */
953 	(void) tcsetattr(slave, TCSAFLUSH, &b);
954 	(void) ioctl(slave, TIOCSWINSZ, (char *)&Ttysize);
955 #endif /* SYSV_TERMIOS */
956 #endif /* SVR4 */
957 }
958 
959 
960 
961 void
962 execcmd(char *cmd, char **ap)
963 {
964 	int	c;
965 	char	*getenv ();
966 	char	*path, *cp, fullcmd[BUFSIZ];
967 
968 	path = getenv ("PATH");
969 	cp = fullcmd;
970 	int rest = sizeof(fullcmd);
971 
972 	while (c = *path++) {
973 		if (c == ':') {
974 			*cp++ = '/';
975 			*cp = '\0';
976 			cp = fullcmd;
977 			strlcat(cp, cmd, rest);
978 			rest -= strlen(cmd);
979 			if (shell_flag) {
980 				strlcpy(shellbuf, "SHELL=", sizeof(shellbuf));
981 				sj3_setenv ("SHELL", cp, shellbuf, sizeof(shellbuf));
982 			}
983 			(void) execve (cp, ap, environ);
984 			cp = fullcmd;
985 		} else
986 			*cp++ = c;
987 	}
988 
989 	*cp++ = '/';
990 	*cp = '\0';
991 	cp = fullcmd;
992 	strlcat(cp, cmd, rest);
993 	if (shell_flag) {
994 		strlcpy(shellbuf, "SHELL=", sizeof(shellbuf));
995 		sj3_setenv("SHELL", cp, shellbuf, sizeof(shellbuf));
996 	}
997 	(void) execve (cp, ap, environ);
998 }
999 
1000 
1001 
1002 void
1003 fail()
1004 {
1005 	(void) kill (0, SIGTERM);
1006 	done ();
1007 }
1008 
1009 
1010 
1011 void
1012 done()
1013 {
1014 	(void) signal (SIGWINCH, SIG_IGN);
1015 
1016 	clear_guide_line ();
1017 	end_guideline ();
1018 	done2 ();
1019 }
1020 
1021 void
1022 done2()
1023 {
1024 	chown (slave_name, 0, 0);
1025 	chmod (slave_name, 0666);
1026 #ifdef SYSV_TERMIOS
1027 	tcsetattr (0, TCSADRAIN, &b);
1028 #else /* SYSV_TERMIOS */
1029 	ioctl (0, TIOCSETP, (char *)&b);
1030 	ioctl (0, TIOCSETC, (char *)&tc);
1031 	ioctl (0, TIOCSLTC, (char *)&lc);
1032 #endif /* SYSV_TERMIOS */
1033 #ifdef __sony_news
1034 	ioctl (0, TIOCKSET, (char *)&jmode);
1035 #endif
1036 	if (!status_line) {
1037 		++Ttysize.ts_lines;
1038 		SetRegion();
1039 	}
1040 	clearutmpentry ();
1041 	SJ2_henkan_end ();
1042 	EndConversion ();
1043 	done3 ();
1044 }
1045 
1046 void
1047 done3()
1048 {
1049 	aprintf ("\r\nexit %s.\r\n", progname);
1050 	exit (0);
1051 }
1052 
1053 
1054 
1055 void
1056 exitprocess()
1057 {
1058 #ifdef SVR4
1059         siginfo_t       info;
1060 
1061         (void) waitid (P_ALL, 0, &info,
1062 		      WNOHANG | WUNTRACED | WEXITED | WTRAPPED | WCONTINUED);
1063         if ((info.si_code == CLD_CONTINUED) ||(info.si_code == CLD_TRAPPED))
1064            return;
1065         if (info.si_code == CLD_STOPPED)
1066 #else
1067 	int		pid, status;
1068 
1069 /*
1070  * Remove warning.
1071  * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp)		1996/8/10
1072  */
1073 	pid = wait3 (&status, (WNOHANG|WUNTRACED), 0);
1074 	if (WIFSTOPPED (status))
1075 #endif
1076 		suspend();
1077         else
1078 		done ();
1079 }
1080 
1081 
1082 
1083 void
1084 suspend()
1085 {
1086 #ifdef SIGTYPE_VOID
1087 	void		(*old_sigtstp) ();
1088 #else
1089 	int		(*old_sigtstp) ();
1090 #endif
1091 	SELECT_FD	ifds;
1092 	int		nc;
1093 	struct timeval	t;
1094 
1095 	clear_guide_line ();
1096 
1097 	do {
1098 cont:
1099 		t.tv_sec = 0;
1100 		t.tv_usec = UsecWeight (1);
1101 		FD_ZERO (&ifds);
1102 		FD_SET (master, &ifds);
1103 		if (select (master + 1, &ifds, 0, 0, &t) > 0) {
1104 			if (FD_ISSET (master, &ifds))
1105 				output_master ();
1106 		}
1107 		else if (errno == EINTR) {
1108 			errno = 0;
1109 			goto cont;
1110 		}
1111 		if (ioctl (master, TIOCOUTQ, &nc) < 0)
1112 #ifdef SVR4
1113                         break;
1114 #else
1115 			fail ();
1116 #endif
1117 	} while (nc > 0);
1118 
1119 #ifdef SYSV_TERMIOS
1120 	tcsetattr (0, TCSADRAIN, &b);
1121 #else /* SYSV_TERMIOS */
1122 	ioctl (0, TIOCSETP, (char *)&b);
1123 	ioctl (0, TIOCSETC, (char *)&tc);
1124 	ioctl (0, TIOCSLTC, (char *)&lc);
1125 #endif /* SYSV_TERMIOS */
1126 #ifdef __sony_news
1127 	ioctl (0, TIOCKSET, (char *)&jmode);
1128 #endif
1129 
1130 	if (!status_line) {
1131 		++Ttysize.ts_lines;
1132 		SetRegion();
1133 	}
1134 
1135 /*
1136  * Remove warning.
1137  * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp)		1996/8/10
1138  */
1139 #ifdef SIGTYPE_VOID
1140 	old_sigtstp = (void(*)()) signal (SIGTSTP, SIG_DFL);
1141 #else
1142 	old_sigtstp = (int(*)()) signal (SIGTSTP, SIG_DFL);
1143 #endif
1144 
1145 	kill (0, SIGTSTP);
1146 
1147 
1148 
1149 /*
1150  * Remove warning.
1151  * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp)		1996/8/10
1152  */
1153 	(void) signal (SIGTSTP, (void (*)())old_sigtstp);
1154 	killpg (Pid_shell, SIGCONT);
1155 	fixtty ();
1156 
1157 	if (!status_line) {
1158 		--Ttysize.ts_lines;
1159 		SetRegion();
1160 	}
1161 
1162 	print_guide_line ();
1163 }
1164 
1165 #ifdef SVR4
1166 void
1167 clearutmpentry()
1168 {
1169 	struct utmpx		*up;
1170 #ifdef SVR4
1171   struct sigaction action;
1172   sigset_t sset;
1173 
1174   sigemptyset(&sset);
1175   sigaddset(&sset, SIGCHLD);
1176   action.sa_handler = SIG_IGN;
1177   action.sa_mask =  sset;
1178   action.sa_flags = SA_RESTART;
1179   (void) sigaction(SIGCHLD, &action, NULL);
1180 #else
1181 	signal(SIGCHLD, SIG_IGN);
1182 #endif
1183 	setutxent();
1184 	while ( (up = getutxent()) ) {
1185 		if (up->ut_pid != (o_pid_t)Pid_shell)
1186 			continue;
1187 		up->ut_type = DEAD_PROCESS;
1188 		up->ut_exit.e_termination = 0;
1189 		up->ut_exit.e_exit = 0;
1190 		(void) time (&up->ut_tv.tv_sec);
1191 		if (modutx(up) == NULL)
1192 			aprintf("%s:\tmodutx failed\r\n", progname);
1193 		break;
1194 	}
1195 	endutxent();
1196 #ifdef SVR4
1197   action.sa_handler = (void (*)()) exitprocess;
1198   action.sa_mask =  sset;
1199   action.sa_flags = SA_RESTART;
1200   (void) sigaction(SIGCHLD, &action, NULL);
1201 #else
1202 	signal (SIGCHLD, (void (*)())exitprocess);
1203 #endif
1204 }
1205 #else /* SVR4 */
1206 #ifdef SYSV_UTMP
1207 void
1208 clearutmpentry()
1209 {
1210 	struct utmp             Utmp;
1211 
1212 	memset ((char *) &Utmp, '\0', sizeof (Utmp));
1213 	(void) strncpy(Utmp.ut_user, user_name, sizeof(Utmp.ut_user));
1214 	(void) strncpy(Utmp.ut_line, &slave_name[sizeof("/dev/")-1],
1215 							sizeof(Utmp.ut_line));
1216 	Utmp.ut_type = DEAD_PROCESS;
1217 	Utmp.ut_pid = (pid_t)getpid();
1218 	strncpy(Utmp.ut_id, &Utmp.ut_line[2], 4);
1219 	Utmp.ut_id[0] = 't';
1220 	Utmp.ut_time = time(0);
1221 	setutent();
1222 	getutid(&Utmp);
1223 	pututline(&Utmp);
1224 	endutent();
1225 }
1226 #else /* SYSV_UTMP */
1227 void
1228 clearutmpentry ()
1229 {
1230 	int			f;
1231 	struct utmp		Utmp;
1232 
1233 	Utmp.ut_line[0] = '\0';
1234 	Utmp.ut_name[0] = '\0';
1235 	Utmp.ut_host[0] = '\0';
1236 	Utmp.ut_time = 0;
1237 
1238 	if (Ttyslot > 0 && (f = open (_PATH_UTMP, 1)) >= 0) {
1239 		lseek (f, (long) (Ttyslot * sizeof (Utmp)), 0);
1240 		write (f, (char *)&Utmp, sizeof (Utmp));
1241 		close (f);
1242 	}
1243 }
1244 #endif /* SYSV_UTMP */
1245 #endif /* SVR4 */
1246 
1247 
1248 void
1249 onwinch()
1250 {
1251 	int ttypgrp;
1252 	Conversion	*cv;
1253 
1254 	cv = current_conversion;
1255 	(void) signal (SIGWINCH, SIG_IGN);
1256 
1257 #ifdef SYSV_TERMIOS
1258 	if (ioctl (0, TIOCGWINSZ, &Ttysize) == 0) {
1259 #else /* SYSV_TERMIOS */
1260 	if (ioctl (0, TIOCGSIZE, &Ttysize) == 0) {
1261 #endif /* SYSV_TERMIOS */
1262 		if (!status_line) {
1263 			clear_guide_line ();
1264 			--Ttysize.ts_lines;
1265 		}
1266 
1267 		cv->line = Ttysize.ts_lines;
1268 		cv->column = Ttysize.ts_cols;
1269 
1270 		if (cv->column < MINCOL) {
1271 			if (Hlevel > 1)
1272 				Hlevel = 1;
1273 		}
1274 		else if (HHlevel > 1) {
1275 			Hlevel = 2;
1276 		}
1277 
1278 		SetRegion();
1279 		if (!status_line) {
1280 			print_guide_line ();
1281 		}
1282 
1283 
1284 
1285 		killpg (Pid_shell, SIGWINCH);
1286 
1287 		if (ioctl (master, TIOCGPGRP, &ttypgrp) == 0)
1288 			killpg (ttypgrp, SIGWINCH);
1289 	}
1290 
1291 	(void) signal (SIGWINCH, (void (*)())onwinch);
1292 }
1293 
1294 void
1295 SetRegion()
1296 {
1297 	set_tty_size ();
1298 
1299 	if (!status_line)
1300 		RegionSet (1, Ttysize.ts_lines);
1301 }
1302 
1303 void
1304 set_tty_size()
1305 {
1306 
1307 #ifdef SYSV_TERMIOS
1308 	ioctl (master, TIOCSWINSZ, &Ttysize);
1309 #else /* SYSV_TERMIOS */
1310 	ioctl (master, TIOCSSIZE, &Ttysize);
1311 #endif /* SYSV_TERMIOS */
1312 }
1313 
1314 void
1315 setsjserv(char *hname)
1316 {
1317 	char *p;
1318         int i;
1319         char *sbuf;
1320 
1321         if (hname == NULL || *hname == '\0')
1322  		return;
1323         if ((sbuf = (char *)strdup(hname)) == NULL) {
1324                 fprintf(stderr, "setsjserv: can't alloc memory\n\r");
1325                 done3();
1326         }
1327         p = sbuf;
1328         for (i = 0; i < MAXSERVER; i++) {
1329                 serv_list[i] = p;
1330                 while(*p != '\0' && *p != ' ' && *p != '\t')
1331                         p++;
1332                 if (*p == '\0')
1333                         break;
1334                 *p++ = '\0';
1335         }
1336         cur_serv = serv_list[0];
1337 }
1338 
1339 char *
1340 chmyhname(char *hname)
1341 {
1342         if (hname != NULL) {
1343                 if (strcmp(my_hname, hname) == 0 ||
1344                     strcmp("localhost", hname) == 0)
1345                         hname = NULL;
1346         }
1347         return(hname);
1348 }
1349