/* * Copyright (c) 1994 Sony Corporation * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL SONY CORPORATION BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name of Sony Corporation * shall not be used in advertising or otherwise to promote the sale, use * or other dealings in this Software without prior written authorization * from Sony Corporation. * */ #include "sj_sysvdef.h" #include "wchar16.h" #include #include #include #include #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__DragonFly__) #define USE_OLD_TTY #if defined(__NetBSD__) #define LACKOF_SETLOCALE #endif #if defined(__FreeBSD__) #include #endif #include #endif #include "select.h" #include "common.h" #ifdef SVR4 #include #include #include #endif #include #include "sj3.h" #ifndef _PATH_UTMP #define _PATH_UTMP "/etc/utmp" #endif #ifdef SVR4 #define killpg(pid, sig) kill(-(pid), (sig)) #define signal sigset #endif #ifndef linux #define DEFAULTSHELL "/bin/csh" #else #define DEFAULTSHELL "/bin/sh" #endif #if defined(linux) && defined(__GLIBC__) && (__GLIBC__ >= 2) #include #endif int Lflag = 0; int shell_flag = 0; char progname[LONGLENGTH]; char shellname[LONGLENGTH]; char home[LONGLENGTH]; char user_name[SHORTLENGTH]; char term_name[SHORTLENGTH]; char shellprog[LONGLENGTH]; char tty_name[SHORTLENGTH]; #ifdef SVR4 char* slave_name; #else char slave_name[SHORTLENGTH]; #endif char* shellargs[SHORTLENGTH]; #ifdef SVR4 char* mptname = "/dev/ptmx"; char* ptsname(int); #else static char line[SHORTLENGTH]; #endif char* cur_serv; char my_hname[MAXHOSTNAMELEN]; char** serv_list; extern int vflag; extern char** environ; extern int status_line; #ifdef SYSV_TERMIOS struct winsize Ttysize; #define ts_lines ws_row #define ts_cols ws_col #else int Ttyslot; struct ttysize Ttysize; #endif int master; int slave; #ifdef SYSV_TERMIOS struct termios b; #else struct sgttyb b; struct tchars tc, tc1; struct ltchars lc, lc1; int lb; int l; #endif #ifdef __sony_news int jmode, jmode2; struct jtchars jtc; #endif int erase_char; wchar16_t erase_str[2]; #ifdef SIGTYPE_VOID void (*sigpipe)(int); #else int (*sigpipe)(int); #endif int Pid_shell; int current_locale; int main(int argc, char** argv) { init(argv); get_ttymode(); init_messages(); parsearg(argc, argv); InitConversion(); checkterm(); getsjrc(); print_version(); getsjrk(erase_char); sjinit(); forkshell(); inputprocess(); done(); } void makecore(void) { chdir("/tmp"); setgid(getgid()); setuid(getuid()); abort(); } void init(char** argv) { char* cp; (void)signal(SIGTERM, (void (*)())done); (void)signal(SIGWINCH, SIG_IGN); (void)signal(SIGQUIT, (void (*)())makecore); (void)signal(SIGBUS, (void (*)())makecore); (void)signal(SIGSEGV, (void (*)())makecore); (void)signal(SIGFPE, (void (*)())makecore); /* * Remove warning. * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp) 1996/8/10 */ #ifdef SIGTYPE_VOID sigpipe = (void (*)())signal(SIGPIPE, SIG_IGN); #else sigpipe = (int (*)())signal(SIGPIPE, SIG_IGN); #endif if(argv[0][0] == '-') Lflag++; if((cp = strrchr(argv[0], '/')) == NULL) cp = argv[0]; else cp++; strcpy(progname, cp); init_env(); } void init_env(void) { char * uname, *hp, *tname; int i; struct passwd* pwd; user_name[0] = '\0'; home[0] = '\0'; shellprog[0] = '\0'; gethostname(my_hname, MAXHOSTNAMELEN); if((serv_list = (char**)malloc(MAXSERVER * sizeof(char*))) == NULL) { fprintf(stderr, "init_env: can't alloc memory\n\r"); done3(); } for(i = 0; i < MAXSERVER; i++) serv_list[i] = NULL; cur_serv = NULL; uname = getlogin(); hp = getenv("HOME"); setpwent(); if(uname == NULL || *uname == '\0') pwd = getpwuid(getuid()); else pwd = getpwnam(uname); if(pwd != NULL) { strcpy(user_name, pwd->pw_name); if(hp == NULL) hp = pwd->pw_dir; endpwent(); } if(hp != NULL) strcpy(home, hp); if((tname = getenv("TERM")) == NULL) { aprintf("Can't getenv TERM\n\r"); perror("getenv"); exit(1); } strcpy(term_name, tname); } void parsearg(int argc, char** argv) { int ap; char c; int sp; char** shella; shella = shellargs; ap = 1; --argc; while(argc > 0) { if(*argv[ap] == '-') { c = argv[ap][1]; switch(c) { case 'L': Lflag++; break; case 'E': aprintf("euc mode\n\r"); set_eucmode(); break; case 'V': vflag = 0; break; case 'v': aprintf("verbose\n\r"); vflag++; break; case 'f': if(argv[ap + 1] == (char*)NULL) usage(); strcpy(shellprog, argv[ap + 1]); shell_flag++; break; case 'e': if(argv[ap + 1] == (char*)NULL) usage(); strcpy(shellprog, argv[++ap]); sp = 0; while(argv[ap] != (char*)NULL) shella[sp++] = argv[ap++]; shella[sp] = (char*)NULL; break; #ifdef OKB case 'o': oasys++; break; #endif case 'H': if(argv[ap + 1] == (char*)NULL) usage(); sp = 0; while(argc > 1 && *argv[ap + 1] != '-') { if(sp >= MAXSERVER) break; serv_list[sp++] = argv[ap + 1]; ap++; argc--; } cur_serv = serv_list[0]; break; case 'h': default: usage(); break; } } argc--; ap++; } if(cur_serv == NULL || *cur_serv == '\0') setsjserv(getenv("SJ3SERV")); } void usage(void) { aprintf("Usage: %s [-option ...]\n\r", progname); aprintf("\t-option\n\r"); aprintf("\t\t-h \thelp\n\r"); aprintf("\t\t-L \tlogin shell\n\r"); aprintf("\t\t-f shellname \texec shell name\n\r"); aprintf("\t\t-e command... \texec command arguments\n\r"); #ifdef OKB aprintf("\t\t-o \toyayubi shift keyboard\n\r"); #endif aprintf("\t\t-H hostname... \tname list of server hosts\n\r"); if(vflag > 2) { aprintf("\t\t-v \tverbose mode\n\r"); aprintf("\t\t-E \tEUC mode\n\r"); } exit(1); } void sjinit(void) { getfixtty(); setshellname(); if(cur_serv == NULL) cur_serv = serv_list[0] = my_hname; SJ2_henkan_init(); start_guideline(); } void setshellname(void) { char* s; char* namep; if(shellprog[0] == '\0') { s = getenv("SHELL"); if((s == NULL) || (*s == '\0') || Lflag) strcpy(shellprog, DEFAULTSHELL); else strcpy(shellprog, s); } if(Lflag) strcpy(shellname, "-"); #ifndef SVR4 else strcpy(shellname, "J"); #endif if((namep = strrchr(shellprog, '/')) == NULL) namep = shellprog; else namep++; strcat(shellname, namep); strcat(shellname, "["); strcat(shellname, user_name); strcat(shellname, " on "); strcat(shellname, progname); strcat(shellname, "]"); } void getfixtty(void) { getmaster(); fixtty(); setdev(); } void get_ttymode(void) { #ifdef SYSV_TERMIOS ioctl(0, TCGETS, (char*)&b); erase_char = b.c_cc[VERASE]; set_bs(erase_char); erase_str[0] = erase_char; erase_str[1] = '\0'; #else ioctl(0, TIOCGETP, (char*)&b); erase_char = b.sg_erase; set_bs(erase_char); erase_str[0] = erase_char; erase_str[1] = '\0'; ioctl(0, TIOCGETC, (char*)&tc); ioctl(0, TIOCGETC, (char*)&tc1); ioctl(0, TIOCGETD, (char*)&l); ioctl(0, TIOCGLTC, (char*)&lc); ioctl(0, TIOCGLTC, (char*)&lc1); ioctl(0, TIOCLGET, (char*)&lb); #endif #ifdef __sony_news ioctl(0, TIOCKGET, (char*)&jmode); jmode2 = set_jmode(jmode); ioctl(0, TIOCKGETC, (char*)&jtc); #else (void)set_jmode(); #endif } void getmaster(void) { #ifdef SVR4 struct stat stb; if((master = open(mptname, O_RDWR)) < 0) { aprintf("Out of pty's\n\r"); done3(); } ioctl(master, I_PUSH, "pckt"); #else /* * Change pseudo-devices. * Because FreeBSD's master pseudo-devices are pty[p-sP-S][0-9a-v]. * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp) 1996/8/10 */ #if defined(__FreeBSD__) || defined(__DragonFly__) struct stat stb; int h, i, j, k1, k2; #else /* !__FreeBSD__ */ char c; struct stat stb; int i, j, k1, k2; #endif /* __FreeBSD__ */ strcpy(line, "/dev/ptyXX"); k1 = strlen("/dev/pty"); k2 = strlen("/dev/ptyp"); /* * Change pseudo-devices. * Because FreeBSD's master pseudo-devices are pty[p-sP-S][0-9a-v]. * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp) 1996/8/10 */ #if defined(__FreeBSD__) || defined(__DragonFly__) for(h = 0; h < 8; h++) { line[k1] = "pqrsPQRS"[h]; line[k2] = '0'; if(stat(line, &stb) < 0) break; for(i = 0; i < 32; i++) { line[k2] = "0123456789abcdefghijklmnopqrstuv"[i]; #else /* !__FreeBSD__ */ for(c = 'p'; c <= 'z'; c++) { line[k1] = c; line[k2] = '0'; if(stat(line, &stb) < 0) break; for(i = 0; i < 16; i++) { line[k2] = "0123456789abcdef"[i]; #endif /* __FreeBSD__ */ master = open(line, 2); if(master >= 0) { j = 1; ioctl(master, TIOCPKT, &j); return; } } } aprintf("Out of pty's\n\r"); done3(); #endif } void #ifdef __sony_news set_jmode(int mode) #else set_jmode(void) #endif { #ifdef __sony_news int term_mode; term_mode = mode & KM_KANJI; if(term_mode == KM_JIS) { aprintf("error: tty jis terminal mode\n\r"); fflush(stdout); exit(1); } if(term_mode == KM_ASCII) { aprintf("error: tty ascii terminal mode\n\r"); fflush(stdout); exit(1); } else if(term_mode == KM_EUC) { set_eucmode(); mode &= ~KM_SYSSJIS; mode |= KM_SYSEUC; (void)setlocale(LC_CTYPE, "ja_JP.EUC"); current_locale = LC_CTYPE_EUC; } else if(term_mode == KM_SJIS) { mode &= ~KM_SYSEUC; mode |= KM_SYSSJIS; (void)setlocale(LC_CTYPE, "ja_JP.SJIS"); current_locale = LC_CTYPE_SHIFTJIS; } else { aprintf("error: unknown tty terminal code\n\r"); fflush(stdout); exit(1); } return (mode); #else char* loc; #ifdef LACKOF_SETLOCALE loc = getenv("LANG"); #else loc = setlocale(LC_CTYPE, ""); #endif if(!loc) { aprintf("error: bad locale\n"); fflush(stdout); exit(1); } if(strcmp(loc, "ja_JP.SJIS") == 0) { current_locale = LC_CTYPE_SHIFTJIS; } else if(strncmp(loc, "ja", 2) == 0 || strncmp(loc, "Ja", 2) == 0) { current_locale = LC_CTYPE_EUC; set_eucmode(); } else { aprintf("error: This locale will not use japanese.\n"); fflush(stdout); exit(1); } #endif /* __sony_news */ } void fixtty(void) { #ifdef SYSV_TERMIOS struct termios sbuf; sbuf = b; sbuf.c_iflag &= ~(INLCR | IGNCR | ICRNL | IUCLC | IXON); sbuf.c_oflag &= ~(ONLCR | OPOST); sbuf.c_lflag &= ~(ICANON | ECHO); sbuf.c_cc[VMIN] = 1; sbuf.c_cc[VTIME] = 0; sbuf.c_cc[VINTR] = 0; sbuf.c_cc[VQUIT] = 0; sbuf.c_cc[VSUSP] = 0; #ifdef VDSUSP sbuf.c_cc[VDSUSP] = 0; #endif /* VDSUSP */ sbuf.c_cc[VREPRINT] = 0; sbuf.c_cc[VDISCARD] = 0; sbuf.c_cc[VWERASE] = 0; sbuf.c_cc[VLNEXT] = 0; (void)ioctl(0, TCSETSW, (char*)&sbuf); #else struct sgttyb sbuf; sbuf = b; sbuf.sg_flags &= ~(EVENP | ODDP | ECHO | CRMOD | RAW | TBDELAY); sbuf.sg_flags |= CBREAK; sbuf.sg_flags |= TANDEM; ioctl(0, TIOCSETN, (char*)&sbuf); tc1.t_intrc = -1; tc1.t_quitc = -1; tc1.t_eofc = -1; ioctl(0, TIOCSETC, (char*)&tc1); lc1.t_suspc = -1; lc1.t_dsuspc = -1; lc1.t_rprntc = -1; lc1.t_flushc = -1; lc1.t_werasc = -1; lc1.t_lnextc = -1; ioctl(0, TIOCSLTC, (char*)&lc1); #endif #ifdef __sony_news ioctl(0, TIOCKSET, (char*)&jmode2); #endif } #ifdef BSD43 #include #endif void setdev(void) { char* cp; #ifdef BSD43 struct group* ttygrp; #endif Conversion* cv; cv = current_conversion; if((cp = ttyname(2)) != NULL) strcpy(tty_name, cp); else *tty_name = '\0'; #ifndef SVR4 strcpy(slave_name, line); slave_name[strlen("/dev/")] = 't'; #endif #ifdef BSD43 if((ttygrp = getgrnam("tty")) != NULL) chown(slave_name, getuid(), ttygrp->gr_gid); else chown(slave_name, getuid(), getgid()); chmod(slave_name, 0620); #else chown(slave_name, getuid(), getgid()); chmod(slave_name, 0622); #endif #ifndef SYSV_TERMIOS Ttyslot = nmttyslot(slave_name); #endif #ifdef SYSV_TERMIOS if(ioctl(0, TIOCGWINSZ, &Ttysize) == 0) #else if(ioctl(0, TIOCGSIZE, &Ttysize) == 0) #endif { if(!status_line) --Ttysize.ts_lines; if(Ttysize.ts_lines < 1) { aprintf("not enough lines\n\r"); done3(); } if(Ttysize.ts_cols < 1) { aprintf("not enough columns\n\r"); done3(); } cv->line = Ttysize.ts_lines; cv->column = Ttysize.ts_cols; SetRegion(); } else { if(cv->line < 1) cv->line = 24; if(cv->column < 1) cv->column = 80; Ttysize.ts_lines = cv->line; Ttysize.ts_cols = cv->column; if(ioctl(0, TIOCSWINSZ, &Ttysize) < 0) { aprintf("Warnning: Can't get tty size, use rows(%d) and columns(%d).\n\r", cv->line, cv->column); } if(!status_line) { Ttysize.ts_lines--; cv->line--; } SetRegion(); } if(cv->column < MINCOL) { if(Hlevel > 1) Hlevel = 1; } else if(HHlevel > 1) { Hlevel = 2; } if(vflag > 1) { aprintf("line %d\n\r", cv->line); aprintf("column %d\n\r", cv->column); } #ifndef SVR4 /* * Remove warning. * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp) 1996/8/10 */ (void)signal(SIGCHLD, (void (*)())exitprocess); #endif } static char shellbuf[128]; void forkshell(void) { #ifdef SVR4 struct sigaction action; sigset_t sset; #endif Pid_shell = fork(); if(Pid_shell < 0) { perror("fork"); done(); } if(Pid_shell == 0) { shellprocess(); } if(vflag > 1) { aprintf("sj3 pid = %d\n\r", getpid()); aprintf("shell pid = %d\n\r", Pid_shell); } (void)signal(SIGHUP, (void (*)())fail); (void)signal(SIGINT, (void (*)())fail); (void)signal(SIGTERM, (void (*)())fail); (void)signal(SIGWINCH, (void (*)())onwinch); #ifdef SVR4 (void)sigemptyset(&sset); (void)sigaddset(&sset, SIGCHLD); action.sa_handler = (void (*)())exitprocess; action.sa_mask = sset; action.sa_flags = SA_RESTART; (void)sigaction(SIGCHLD, &action, NULL); #endif } void sj3_setenv(char* ename, char* eval, char* buf) { char * cp, *dp; char** ep = environ; while((dp = *ep++) != NULL) { for(cp = ename; *cp == *dp && *cp; cp++, dp++) continue; if(*cp == 0 && (*dp == '=' || *dp == 0)) { strcat(buf, eval); *--ep = buf; return; } } } void shellprocess(void) { int t, f; #ifdef SYSV_TERMIOS #ifdef SYSV_UTMP struct utmp Utmp; #else struct utmpx Utmp; #endif setsid(); getslave(); memset((char*)&Utmp, '\0', sizeof(Utmp)); (void)strncpy(Utmp.ut_user, user_name, sizeof(Utmp.ut_user)); (void)strncpy(Utmp.ut_line, &slave_name[sizeof("/dev/") - 1], sizeof(Utmp.ut_line)); Utmp.ut_type = USER_PROCESS; #ifdef SYSV_UTMP Utmp.ut_pid = (pid_t)getpid(); strncpy(Utmp.ut_id, &Utmp.ut_line[2], 4); Utmp.ut_id[0] = 't'; Utmp.ut_time = time(0); setutent(); getutid(&Utmp); pututline(&Utmp); endutent(); #else Utmp.ut_pid = (o_pid_t)getpid(); Utmp.ut_id[0] = 's'; Utmp.ut_id[1] = 'j'; Utmp.ut_id[2] = SC_WILDC; Utmp.ut_id[3] = SC_WILDC; Utmp.ut_exit.e_termination = 0; Utmp.ut_exit.e_exit = 0; (void)time(&Utmp.ut_tv.tv_sec); if(makeutx(&Utmp) == NULL) aprintf("%s:\tmakeutx failed\r\n", progname); #endif /* SYSV_UTMP */ #else /* SYSV_TERMIOS */ struct utmp Utmp; char* p; /* * Remove warning. * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp) 1996/8/10 */ #define SCPYN(a, b) strncpy(a, b, sizeof(a)) if((p = ttyname(0)) == NULL) SCPYN(Utmp.ut_host, progname); else { SCPYN(Utmp.ut_host, progname); strcat(Utmp.ut_host, " on "); p = strrchr(p, '/') + 1; strcat(Utmp.ut_host, p); } SCPYN(Utmp.ut_name, user_name); SCPYN(Utmp.ut_line, strrchr(slave_name, '/') + 1); time(&Utmp.ut_time); #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__DragonFly__) if(setsid() < 0) perror("setsid()"); #else t = open("/dev/tty", 2); if(t >= 0) { ioctl(t, TIOCNOTTY, (char*)0); (void)close(t); } #endif getslave(); #endif /* SYSV_TERMIOS */ (void)close(master); dup2(slave, 0); dup2(slave, 1); dup2(slave, 2); (void)close(slave); #ifndef SYSV_TERMIOS if(Ttyslot > 0 && (f = open(_PATH_UTMP, 1)) >= 0) { lseek(f, (long)(Ttyslot * sizeof(Utmp)), 0); write(f, (char*)&Utmp, sizeof(Utmp)); close(f); } #endif /* SYSV_TERMIOS */ setgid(getgid()); setuid(getuid()); if(shellargs[0] == (char*)NULL) { shellargs[0] = shellname; shellargs[1] = (char*)0; } /* * Remove warning. * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp) 1996/8/10 */ (void)signal(SIGPIPE, (void (*)())sigpipe); if(*shellprog == '/') { if(shell_flag) { strcpy(shellbuf, "SHELL="); sj3_setenv("SHELL", shellprog, shellbuf); } (void)execve(shellprog, shellargs, environ); } else execcmd(shellprog, shellargs); perror(shellprog); exit(1); } void getslave(void) { #ifdef SVR4 grantpt(master); unlockpt(master); slave_name = ptsname(master); slave = open(slave_name, O_RDWR); if(slave < 0) { perror(slave_name); done2(); } ioctl(slave, I_PUSH, "ptem"); ioctl(slave, I_PUSH, "ldterm"); ioctl(slave, I_PUSH, "ttcompat"); (void)ioctl(slave, TCSETSF, (char*)&b); (void)ioctl(slave, TIOCSWINSZ, (char*)&Ttysize); #ifdef __sony_news (void)ioctl(slave, TIOCKSET, (char*)&jmode); (void)ioctl(slave, TIOCKSETC, (char*)&jtc); #endif #else line[strlen("/dev/")] = 't'; slave = open(line, 2); if(slave < 0) { perror(line); done2(); } #ifndef SYSV_TERMIOS #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__DragonFly__) ioctl(slave, TIOCSCTTY, NULL); #endif ioctl(slave, TIOCSETP, (char*)&b); ioctl(slave, TIOCSETC, (char*)&tc); ioctl(slave, TIOCSLTC, (char*)&lc); ioctl(slave, TIOCLSET, (char*)&lb); ioctl(slave, TIOCSETD, (char*)&l); #ifdef __sony_news ioctl(slave, TIOCKSET, (char*)&jmode); ioctl(slave, TIOCKSETC, (char*)&jtc); #endif ioctl(slave, TIOCSSIZE, &Ttysize); #else /* SYSV_TERMIOS */ (void)ioctl(slave, TCSETSF, (char*)&b); (void)ioctl(slave, TIOCSWINSZ, (char*)&Ttysize); #endif /* SYSV_TERMIOS */ #endif /* SVR4 */ } void execcmd(char* cmd, char** ap) { int c; char *path, *cp, fullcmd[BUFSIZ]; path = getenv("PATH"); cp = fullcmd; while((c = *path++) != 0) { if(c == ':') { *cp++ = '/'; *cp = '\0'; cp = fullcmd; (void)strcat(cp, cmd); if(shell_flag) { strcpy(shellbuf, "SHELL="); sj3_setenv("SHELL", cp, shellbuf); } (void)execve(cp, ap, environ); cp = fullcmd; } else *cp++ = c; } *cp++ = '/'; *cp = '\0'; cp = fullcmd; (void)strcat(cp, cmd); if(shell_flag) { strcpy(shellbuf, "SHELL="); sj3_setenv("SHELL", cp, shellbuf); } (void)execve(cp, ap, environ); } void fail(void) { (void)kill(0, SIGTERM); done(); } void done(void) { (void)signal(SIGWINCH, SIG_IGN); clear_guide_line(); end_guideline(); done2(); } void done2(void) { chown(slave_name, 0, 0); chmod(slave_name, 0666); #ifdef SYSV_TERMIOS ioctl(0, TCSETSW, (char*)&b); #else /* SYSV_TERMIOS */ ioctl(0, TIOCSETP, (char*)&b); ioctl(0, TIOCSETC, (char*)&tc); ioctl(0, TIOCSLTC, (char*)&lc); #endif /* SYSV_TERMIOS */ #ifdef __sony_news ioctl(0, TIOCKSET, (char*)&jmode); #endif if(!status_line) { ++Ttysize.ts_lines; SetRegion(); } clearutmpentry(); SJ2_henkan_end(); EndConversion(); done3(); } void done3(void) { aprintf("\r\nexit %s.\r\n", progname); exit(0); } void exitprocess(void) { #ifdef SVR4 siginfo_t info; (void)waitid(P_ALL, 0, &info, WNOHANG | WUNTRACED | WEXITED | WTRAPPED | WCONTINUED); if((info.si_code == CLD_CONTINUED) || (info.si_code == CLD_TRAPPED)) return; if(info.si_code == CLD_STOPPED) #else int pid, status; /* * Remove warning. * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp) 1996/8/10 */ pid = wait3(&status, (WNOHANG | WUNTRACED), 0); if(WIFSTOPPED(status)) #endif suspend(); else done(); } void suspend(void) { #ifdef SIGTYPE_VOID void (*old_sigtstp)(int); #else int (*old_sigtstp)(int); #endif SELECT_FD ifds; int nc; struct timeval t; clear_guide_line(); do { cont: t.tv_sec = 0; t.tv_usec = UsecWeight(1); FD_ZERO(&ifds); FD_SET(master, &ifds); if(select(master + 1, &ifds, 0, 0, &t) > 0) { if(FD_ISSET(master, &ifds)) output_master(); } else if(errno == EINTR) { errno = 0; goto cont; } if(ioctl(master, TIOCOUTQ, &nc) < 0) #ifdef SVR4 break; #else fail(); #endif } while(nc > 0); #ifdef SYSV_TERMIOS ioctl(0, TCSETSW, (char*)&b); #else /* SYSV_TERMIOS */ ioctl(0, TIOCSETP, (char*)&b); ioctl(0, TIOCSETC, (char*)&tc); ioctl(0, TIOCSLTC, (char*)&lc); #endif /* SYSV_TERMIOS */ #ifdef __sony_news ioctl(0, TIOCKSET, (char*)&jmode); #endif if(!status_line) { ++Ttysize.ts_lines; SetRegion(); } /* * Remove warning. * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp) 1996/8/10 */ #ifdef SIGTYPE_VOID old_sigtstp = (void (*)())signal(SIGTSTP, SIG_DFL); #else old_sigtstp = (int (*)())signal(SIGTSTP, SIG_DFL); #endif kill(0, SIGTSTP); /* * Remove warning. * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp) 1996/8/10 */ (void)signal(SIGTSTP, (void (*)())old_sigtstp); killpg(Pid_shell, SIGCONT); fixtty(); if(!status_line) { --Ttysize.ts_lines; SetRegion(); } print_guide_line(); } #ifdef SVR4 void clearutmpentry(void) { struct utmpx* up; #ifdef SVR4 struct sigaction action; sigset_t sset; sigemptyset(&sset); sigaddset(&sset, SIGCHLD); action.sa_handler = SIG_IGN; action.sa_mask = sset; action.sa_flags = SA_RESTART; (void)sigaction(SIGCHLD, &action, NULL); #else signal(SIGCHLD, SIG_IGN); #endif setutxent(); while((up = getutxent())) { if(up->ut_pid != (o_pid_t)Pid_shell) continue; up->ut_type = DEAD_PROCESS; up->ut_exit.e_termination = 0; up->ut_exit.e_exit = 0; (void)time(&up->ut_tv.tv_sec); if(modutx(up) == NULL) aprintf("%s:\tmodutx failed\r\n", progname); break; } endutxent(); #ifdef SVR4 action.sa_handler = (void (*)())exitprocess; action.sa_mask = sset; action.sa_flags = SA_RESTART; (void)sigaction(SIGCHLD, &action, NULL); #else signal(SIGCHLD, (void (*)())exitprocess); #endif } #else /* SVR4 */ #ifdef SYSV_UTMP void clearutmpentry(void) { struct utmp Utmp; memset((char*)&Utmp, '\0', sizeof(Utmp)); (void)strncpy(Utmp.ut_user, user_name, sizeof(Utmp.ut_user)); (void)strncpy(Utmp.ut_line, &slave_name[sizeof("/dev/") - 1], sizeof(Utmp.ut_line)); Utmp.ut_type = DEAD_PROCESS; Utmp.ut_pid = (pid_t)getpid(); strncpy(Utmp.ut_id, &Utmp.ut_line[2], 4); Utmp.ut_id[0] = 't'; Utmp.ut_time = time(0); setutent(); getutid(&Utmp); pututline(&Utmp); endutent(); } #else /* SYSV_UTMP */ void clearutmpentry(void) { int f; struct utmp Utmp; Utmp.ut_line[0] = '\0'; Utmp.ut_name[0] = '\0'; Utmp.ut_host[0] = '\0'; Utmp.ut_time = 0; if(Ttyslot > 0 && (f = open(_PATH_UTMP, 1)) >= 0) { lseek(f, (long)(Ttyslot * sizeof(Utmp)), 0); write(f, (char*)&Utmp, sizeof(Utmp)); close(f); } } #endif /* SYSV_UTMP */ #endif /* SVR4 */ void onwinch(void) { int ttypgrp; Conversion* cv; cv = current_conversion; (void)signal(SIGWINCH, SIG_IGN); #ifdef SYSV_TERMIOS if(ioctl(0, TIOCGWINSZ, &Ttysize) == 0) #else /* SYSV_TERMIOS */ if(ioctl(0, TIOCGSIZE, &Ttysize) == 0) #endif /* SYSV_TERMIOS */ { if(!status_line) { clear_guide_line(); --Ttysize.ts_lines; } cv->line = Ttysize.ts_lines; cv->column = Ttysize.ts_cols; if(cv->column < MINCOL) { if(Hlevel > 1) Hlevel = 1; } else if(HHlevel > 1) { Hlevel = 2; } SetRegion(); if(!status_line) { print_guide_line(); } killpg(Pid_shell, SIGWINCH); if(ioctl(master, TIOCGPGRP, &ttypgrp) == 0) killpg(ttypgrp, SIGWINCH); } (void)signal(SIGWINCH, (void (*)())onwinch); } void SetRegion(void) { set_tty_size(); if(!status_line) RegionSet(1, Ttysize.ts_lines); } void set_tty_size(void) { #ifdef SYSV_TERMIOS ioctl(master, TIOCSWINSZ, &Ttysize); #else /* SYSV_TERMIOS */ ioctl(master, TIOCSSIZE, &Ttysize); #endif /* SYSV_TERMIOS */ } void setsjserv(char* hname) { char* p; int i; char* sbuf; if(hname == NULL || *hname == '\0') return; if((sbuf = (char*)malloc(strlen(hname))) == NULL) { fprintf(stderr, "setsjserv: can't alloc memory\n\r"); done3(); } strcpy(sbuf, hname); p = sbuf; for(i = 0; i < MAXSERVER; i++) { serv_list[i] = p; while(*p != '\0' && *p != ' ' && *p != '\t') p++; if(*p == '\0') break; *p++ = '\0'; } cur_serv = serv_list[0]; } char* chmyhname(char* hname) { if(hname != NULL) { if(strcmp(my_hname, hname) == 0 || strcmp("localhost", hname) == 0) hname = NULL; } return (hname); }