📄 main.c
字号:
* now in child process */ extern char **environ;#if defined(_POSIX_SOURCE) || defined(SVR4) || defined(__convex__) int pgrp = setsid();#else int pgrp = getpid();#endif#ifdef USE_SYSV_TERMIO char numbuf[12];#if defined(UTMP) && defined(USE_SYSV_UTMP) char *ptyname;#endif#endif /* USE_SYSV_TERMIO */#ifdef USE_USG_PTYS#if defined(SYSV) && defined(SYSV386) if (IsPts) { /* SYSV386 supports both, which did we open? */#endif /* SYSV && SYSV386 */ int ptyfd; setpgrp(); grantpt (screen->respond); unlockpt (screen->respond); if ((ptyfd = open (ptsname(screen->respond), O_RDWR)) < 0) { SysError (1); } if (ioctl (ptyfd, I_PUSH, "ptem") < 0) { SysError (2); }#if !defined(SVR4) && !defined(SYSV386) && !defined(sgi) if (!getenv("CONSEM") && ioctl (ptyfd, I_PUSH, "consem") < 0) { SysError (3); }#endif /* !SVR4 */ if (ioctl (ptyfd, I_PUSH, "ldterm") < 0) { SysError (4); }#if defined(SVR4) && !defined(sgi) /* from Sony */ if (ioctl (ptyfd, I_PUSH, "ttcompat") < 0) { SysError (5); }#endif /* SVR4 */ tty = ptyfd; close (screen->respond);#ifdef TIOCSWINSZ /* tell tty how big window is */ if(screen->TekEmu) { ws.ws_row = 24; ws.ws_col = 80; ws.ws_xpixel = TFullWidth(screen); ws.ws_ypixel = TFullHeight(screen); } else { ws.ws_row = screen->max_row + 1; ws.ws_col = screen->max_col + 1; ws.ws_xpixel = FullWidth(screen); ws.ws_ypixel = FullHeight(screen); }#endif#if defined(SYSV) && defined(SYSV386) } else { /* else pty, not pts */#endif /* SYSV && SYSV386 */#endif /* USE_USG_PTYS */#ifdef USE_HANDSHAKE /* warning, goes for a long ways */ /* close parent's sides of the pipes */ close (cp_pipe[0]); close (pc_pipe[1]); /* Make sure that our sides of the pipes are not in the * 0, 1, 2 range so that we don't fight with stdin, out * or err. */ if (cp_pipe[1] <= 2) { if ((i = fcntl(cp_pipe[1], F_DUPFD, 3)) >= 0) { (void) close(cp_pipe[1]); cp_pipe[1] = i; } } if (pc_pipe[0] <= 2) { if ((i = fcntl(pc_pipe[0], F_DUPFD, 3)) >= 0) { (void) close(pc_pipe[0]); pc_pipe[0] = i; } } /* we don't need the socket, or the pty master anymore */ close (Xsocket); close (screen->respond); /* Now is the time to set up our process group and * open up the pty slave. */#ifdef USE_SYSV_PGRP#if defined(CRAY) && (OSMAJORVERSION > 5) (void) setsid();#else (void) setpgrp();#endif#endif /* USE_SYSV_PGRP */ while (1) {#ifdef TIOCNOTTY if (!no_dev_tty && (tty = open ("/dev/tty", O_RDWR)) >= 0) { ioctl (tty, TIOCNOTTY, (char *) NULL); close (tty); }#endif /* TIOCNOTTY */ if ((tty = open(ttydev, O_RDWR, 0)) >= 0) {#if defined(CRAY) && defined(TCSETCTTY) /* make /dev/tty work */ ioctl(tty, TCSETCTTY, 0);#endif#ifdef USE_SYSV_PGRP /* We need to make sure that we are acutally * the process group leader for the pty. If * we are, then we should now be able to open * /dev/tty. */ if ((i = open("/dev/tty", O_RDWR, 0)) >= 0) { /* success! */ close(i); break; }#else /* USE_SYSV_PGRP */ break;#endif /* USE_SYSV_PGRP */ }#ifdef TIOCSCTTY ioctl(tty, TIOCSCTTY, 0);#endif /* let our master know that the open failed */ handshake.status = PTY_BAD; handshake.error = errno; strcpy(handshake.buffer, ttydev); write(cp_pipe[1], (char *) &handshake, sizeof(handshake)); /* get reply from parent */ i = read(pc_pipe[0], (char *) &handshake, sizeof(handshake)); if (i <= 0) { /* parent terminated */ exit(1); } if (handshake.status == PTY_NOMORE) { /* No more ptys, let's shutdown. */ exit(1); } /* We have a new pty to try */ free(ttydev); ttydev = malloc((unsigned) (strlen(handshake.buffer) + 1)); strcpy(ttydev, handshake.buffer); } /* use the same tty name that everyone else will use ** (from ttyname) */ if (ptr = ttyname(tty)) { /* it may be bigger */ ttydev = realloc (ttydev, (unsigned) (strlen(ptr) + 1)); (void) strcpy(ttydev, ptr); }#if defined(SYSV) && defined(SYSV386) } /* end of IsPts else clause */#endif /* SYSV && SYSV386 */#endif /* USE_HANDSHAKE -- from near fork */#ifdef USE_TTY_GROUP { #include <grp.h> struct group *ttygrp; if (ttygrp = getgrnam("tty")) { /* change ownership of tty to real uid, "tty" gid */ chown (ttydev, screen->uid, ttygrp->gr_gid); chmod (ttydev, 0620); } else { /* change ownership of tty to real group and user id */ chown (ttydev, screen->uid, screen->gid); chmod (ttydev, 0622); } endgrent(); }#else /* else !USE_TTY_GROUP */ /* change ownership of tty to real group and user id */ chown (ttydev, screen->uid, screen->gid); /* change protection of tty */ chmod (ttydev, 0622);#endif /* USE_TTY_GROUP */ /* * set up the tty modes */ {#ifdef USE_SYSV_TERMIO#if defined(umips) || defined(CRAY) /* If the control tty had its modes screwed around with, eg. by lineedit in the shell, or emacs, etc. then tio will have bad values. Let's just get termio from the new tty and tailor it. */ if (ioctl (tty, TCGETA, &tio) == -1) SysError (ERROR_TIOCGETP); tio.c_lflag |= ECHOE;#endif /* umips */ /* Now is also the time to change the modes of the * child pty. */ /* input: nl->nl, don't ignore cr, cr->nl */ tio.c_iflag &= ~(INLCR|IGNCR); tio.c_iflag |= ICRNL; /* ouput: cr->cr, nl is not return, no delays, ln->cr/nl */#ifndef BSD_TERMIOS /* NetBSD lacks these oflags -- JLM */ tio.c_oflag &= ~(OCRNL|ONLRET|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);#endif tio.c_oflag |= ONLCR;#ifdef OPOST tio.c_oflag |= OPOST;#endif /* OPOST */ #ifdef BAUD_0 /* baud rate is 0 (don't care) */ tio.c_cflag &= ~(CBAUD);#else /* !BAUD_0 */ /* baud rate is 9600 (nice default) */#ifndef BSD_TERMIOS /* NetBSD has no CBAUD -- JLM */ tio.c_cflag &= ~(CBAUD); tio.c_cflag |= B9600;#endif#endif /* !BAUD_0 */ /* enable signals, canonical processing (erase, kill, etc), ** echo */ tio.c_lflag |= ISIG|ICANON|ECHO; /* reset EOL to defalult value */ tio.c_cc[VEOL] = '@' & 0x3f; /* '^@' */ /* certain shells (ksh & csh) change EOF as well */ tio.c_cc[VEOF] = 'D' & 0x3f; /* '^D' */#define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value; if (override_tty_modes) { /* sysv-specific */ TMODE (XTTYMODE_intr, tio.c_cc[VINTR]); TMODE (XTTYMODE_quit, tio.c_cc[VQUIT]); TMODE (XTTYMODE_erase, tio.c_cc[VERASE]); TMODE (XTTYMODE_kill, tio.c_cc[VKILL]); TMODE (XTTYMODE_eof, tio.c_cc[VEOF]); TMODE (XTTYMODE_eol, tio.c_cc[VEOL]);#ifdef VSWTCH TMODE (XTTYMODE_swtch, d_tio.c_cc[VSWTCH]);#endif#ifdef TIOCSLTC /* both SYSV and BSD have ltchars */ TMODE (XTTYMODE_susp, ltc.t_suspc); TMODE (XTTYMODE_dsusp, ltc.t_dsuspc); TMODE (XTTYMODE_rprnt, ltc.t_rprntc); TMODE (XTTYMODE_flush, ltc.t_flushc); TMODE (XTTYMODE_weras, ltc.t_werasc); TMODE (XTTYMODE_lnext, ltc.t_lnextc);#endif }#undef TMODE if (ioctl (tty, TCSETA, &tio) == -1) HsSysError(cp_pipe[1], ERROR_TIOCSETP);#ifdef TIOCSLTC if (ioctl (tty, TIOCSLTC, <c) == -1) HsSysError(cp_pipe[1], ERROR_TIOCSETC);#endif /* TIOCSLTC */#ifdef TIOCLSET if (ioctl (tty, TIOCLSET, (char *)&lmode) == -1) HsSysError(cp_pipe[1], ERROR_TIOCLSET);#endif /* TIOCLSET */#else /* USE_SYSV_TERMIO */ sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW); sg.sg_flags |= ECHO | CRMOD; /* make sure speed is set on pty so that editors work right*/ sg.sg_ispeed = B9600; sg.sg_ospeed = B9600; /* reset t_brkc to default value */ tc.t_brkc = -1;#ifdef sony if (screen->input_eight_bits) lmode |= LPASS8; else lmode &= ~(LPASS8); jmode &= ~KM_KANJI;#endif /* sony */#define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value; if (override_tty_modes) { TMODE (XTTYMODE_intr, tc.t_intrc); TMODE (XTTYMODE_quit, tc.t_quitc); TMODE (XTTYMODE_erase, sg.sg_erase); TMODE (XTTYMODE_kill, sg.sg_kill); TMODE (XTTYMODE_eof, tc.t_eofc); TMODE (XTTYMODE_start, tc.t_startc); TMODE (XTTYMODE_stop, tc.t_stopc); TMODE (XTTYMODE_brk, tc.t_brkc); /* both SYSV and BSD have ltchars */ TMODE (XTTYMODE_susp, ltc.t_suspc); TMODE (XTTYMODE_dsusp, ltc.t_dsuspc); TMODE (XTTYMODE_rprnt, ltc.t_rprntc); TMODE (XTTYMODE_flush, ltc.t_flushc); TMODE (XTTYMODE_weras, ltc.t_werasc); TMODE (XTTYMODE_lnext, ltc.t_lnextc); }#undef TMODE if (ioctl (tty, TIOCSETP, (char *)&sg) == -1) HsSysError (cp_pipe[1], ERROR_TIOCSETP); if (ioctl (tty, TIOCSETC, (char *)&tc) == -1) HsSysError (cp_pipe[1], ERROR_TIOCSETC); if (ioctl (tty, TIOCSETD, (char *)&discipline) == -1) HsSysError (cp_pipe[1], ERROR_TIOCSETD); if (ioctl (tty, TIOCSLTC, (char *)<c) == -1) HsSysError (cp_pipe[1], ERROR_TIOCSLTC); if (ioctl (tty, TIOCLSET, (char *)&lmode) == -1) HsSysError (cp_pipe[1], ERROR_TIOCLSET);#ifdef sony if (ioctl (tty, TIOCKSET, (char *)&jmode) == -1) HsSysError (cp_pipe[1], ERROR_TIOCKSET); if (ioctl (tty, TIOCKSETC, (char *)&jtc) == -1) HsSysError (cp_pipe[1], ERROR_TIOCKSETC);#endif /* sony */#endif /* !USE_SYSV_TERMIO */#ifdef TIOCCONS if (Console) { int on = 1; if (ioctl (tty, TIOCCONS, (char *)&on) == -1) fprintf(stderr, "%s: cannot open console\n", xterm_name); }#endif /* TIOCCONS */ } signal (SIGCHLD, SIG_DFL);#ifdef USE_SYSV_SIGHUP /* watch out for extra shells (I don't understand either) */ signal (SIGHUP, SIG_DFL);#else signal (SIGHUP, SIG_IGN);#endif /* restore various signals to their defaults */ signal (SIGINT, SIG_DFL); signal (SIGQUIT, SIG_DFL); signal (SIGTERM, SIG_DFL); /* copy the environment before Setenving */ for (i = 0 ; environ [i] != NULL ; i++) ; /* compute number of Setenv() calls below */ envsize = 1; /* (NULL terminating entry) */ envsize += 3; /* TERM, WINDOWID, DISPLAY */#ifdef UTMP envsize += 1; /* LOGNAME */#endif /* UTMP */#ifdef USE_SYSV_ENVVARS#ifndef TIOCSWINSZ /* window size not stored in driver? */ envsize += 2; /* COLUMNS, LINES */#endif /* TIOCSWINSZ */#ifdef UTMP envsize += 2; /* HOME, SHELL */#endif /* UTMP */#else /* USE_SYSV_ENVVARS */ envsize += 1; /* TERMCAP */#endif /* USE_SYSV_ENVVARS */ envnew = (char **) calloc ((unsigned) i + envsize, sizeof(char *)); bcopy((char *)environ, (char *)envnew, i * sizeof(char *)); environ = envnew; Setenv ("TERM=", TermName); if(!TermName) *newtc = 0; sprintf (buf, "%lu", screen->TekEmu ? ((unsigned long) XtWindow (XtParent(tekWidget))) : ((unsigned long) XtWindow (XtParent(term)))); Setenv ("WINDOWID=", buf); /* put the display into the environment of the shell*/ Setenv ("DISPLAY=", XDisplayString (screen->display)); signal(SIGTERM, SIG_DFL); /* this is the time to go and set up stdin, out, and err */ {#if defined(CRAY) && (OSMAJORVERSION >= 6) (void) close(tty); (void) close(0); if (open ("/dev/tty", O_RDWR)) { fprintf(stderr, "cannot open /dev/tty\n"); exit(1); } (void) close(1); (void) close(2); dup(0); dup(0);#else /* dup the tty */ for (i = 0; i <= 2; i++) if (i != tty) { (void) close(i); (void) dup(tty); }#ifndef ATT /* and close the tty */ if (tty > 2) (void) close(tty);#endif#endif /* CRAY */ }#ifndef USE_SYSV_PGRP#ifdef TIOCSCTTY setsid(); ioctl(0, TIOCSCTTY, 0);#endif ioctl(0, TIOCSPGRP, (char *)&pgrp); setpgrp(0,0); close(open(ttydev, O_WRONLY, 0)); setpgrp (0, pgrp);#endif /* !USE_SYSV_PGRP */#ifdef UTMP pw = getpwuid(screen->uid); if (pw && pw->pw_name) Setenv ("LOGNAME=", pw->pw_name); /* for POSIX */#ifdef USE_SYSV_UTMP /* Set up our utmp entry now. We need to do it here ** for the following reasons: ** - It needs to have our correct process id (for ** login). ** - If our parent was to set it after the fork(), ** it might make it out before we need it. ** - We need to do it before we go and change our ** user and group id's. */#ifdef CRAY#define PTYCHARLEN 4#else#define PTYCHARLEN 2#endif (void) setutent (); /* set up entry to search for */ ptyname = ttydev; (void) strncpy(utmp.ut_id,ptyname + strlen(ptyname)-PTYCHARLEN, sizeof (utmp.ut_id)); utmp.ut_type = DEAD_PROCESS; /* position to entry in utmp file */ (void) getutid(&utmp); /* set up the new entry */ utmp.ut_type = USER_PROCESS; utmp.ut_exit.e_exit = 2; (void) strncpy(utmp.ut_user, (pw && pw->pw_name) ? pw->pw_name : "????", sizeof(utmp.ut_user)); (void)strncpy(utmp.ut_id, ptyname + strlen(ptyname)-PTYCHARLEN, sizeof(utmp.ut_id)); (void) strncpy (utmp.ut_line, ptyname + strlen("/dev/"), sizeof (utmp.ut_line));#ifdef HAS_UTMP_UT_HOST (void) strncpy(buf, DisplayString(screen
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -