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