1223 lines
25 KiB
C
1223 lines
25 KiB
C
/*
|
|
* 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 <signal.h>
|
|
#include <errno.h>
|
|
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__DragonFly__)
|
|
#define USE_OLD_TTY
|
|
#if defined(__NetBSD__)
|
|
#define LACKOF_SETLOCALE
|
|
#endif
|
|
#if defined(__FreeBSD__)
|
|
#include <sys/ioctl_compat.h>
|
|
#endif
|
|
#include <curses.h>
|
|
#endif
|
|
|
|
#include "select.h"
|
|
#include "common.h"
|
|
#ifdef SVR4
|
|
#include <sys/fcntl.h>
|
|
#include <sys/stropts.h>
|
|
#include <netdb.h>
|
|
#endif
|
|
#include <locale.h>
|
|
#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 <termios.h>
|
|
#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)();
|
|
#else
|
|
int (*sigpipe)();
|
|
#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, *getpwnam(), *getpwuid();
|
|
char * getlogin(), *getenv();
|
|
|
|
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 <grp.h>
|
|
#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* getenv();
|
|
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)();
|
|
#else
|
|
int (*old_sigtstp)();
|
|
#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);
|
|
}
|