mleisher@NMSU.Edu (05/11/91)
Submitted-by: mleisher@NMSU.Edu Posting-number: Volume 12, Issue 94 Archive-name: kterm/part13 #!/bin/sh # this is kt412.13 (part 13 of kterm-4.1.2) # do not concatenate these parts, unpack them in order with /bin/sh # file kterm-4.1.2/main.c continued # if test ! -r _shar_seq_.tmp; then echo 'Please unpack part 1 first!' exit 1 fi (read Scheck if test "$Scheck" != 13; then echo Please unpack part "$Scheck" next! exit 1 else exit 0 fi ) < _shar_seq_.tmp || exit 1 if test ! -f _shar_wnt_.tmp; then echo 'x - still skipping kterm-4.1.2/main.c' else echo 'x - continuing file kterm-4.1.2/main.c' sed 's/^X//' << 'SHAR_EOF' >> 'kterm-4.1.2/main.c' && #define XTTYMODE_start 7 { "stop", 4, 0, '\0' }, /* tchars.t_stopc */ #define XTTYMODE_stop 8 { "brk", 3, 0, '\0' }, /* tchars.t_brkc */ #define XTTYMODE_brk 9 { "susp", 4, 0, '\0' }, /* ltchars.t_suspc */ #define XTTYMODE_susp 10 { "dsusp", 5, 0, '\0' }, /* ltchars.t_dsuspc */ #define XTTYMODE_dsusp 11 { "rprnt", 5, 0, '\0' }, /* ltchars.t_rprntc */ #define XTTYMODE_rprnt 12 { "flush", 5, 0, '\0' }, /* ltchars.t_flushc */ #define XTTYMODE_flush 13 { "weras", 5, 0, '\0' }, /* ltchars.t_werasc */ #define XTTYMODE_weras 14 { "lnext", 5, 0, '\0' }, /* ltchars.t_lnextc */ #define XTTYMODE_lnext 15 #define NXTTYMODES 16 }; X #ifdef USE_SYSV_UTMP extern struct utmp *getutent(); extern struct utmp *getutid(); extern struct utmp *getutline(); extern void pututline(); extern void setutent(); extern void endutent(); extern void utmpname(); X extern struct passwd *getpwent(); extern struct passwd *getpwuid(); extern struct passwd *getpwnam(); extern void setpwent(); extern void endpwent(); extern struct passwd *fgetpwent(); #else /* not USE_SYSV_UTMP */ static char etc_utmp[] = UTMP_FILENAME; #ifdef LASTLOG static char etc_lastlog[] = LASTLOG_FILENAME; #endif #ifdef WTMP static char etc_wtmp[] = WTMP_FILENAME; #endif #endif /* USE_SYSV_UTMP */ X /* X * Some people with 4.3bsd /bin/login seem to like to use login -p -f user X * to implement xterm -ls. They can turn on USE_LOGIN_DASH_P and turn off X * WTMP and LASTLOG. X */ #ifdef USE_LOGIN_DASH_P #ifndef LOGIN_FILENAME #define LOGIN_FILENAME "/bin/login" #endif static char bin_login[] = LOGIN_FILENAME; #endif X static int inhibit; static char passedPty[2]; /* name if pty if slave */ X #ifdef TIOCCONS static int Console; #endif /* TIOCCONS */ #ifndef USE_SYSV_UTMP static int tslot; #endif /* USE_SYSV_UTMP */ static jmp_buf env; X char *ProgramName; Boolean sunFunctionKeys; X static struct _resource { X char *xterm_name; X char *icon_geometry; X char *title; X char *icon_name; X char *term_name; X char *tty_modes; X Boolean utmpInhibit; X Boolean sunFunctionKeys; /* %%% should be widget resource? */ X Boolean wait_for_map; #ifdef KEEPALIVE X Boolean keepalive; #endif } resource; X /* used by VT (charproc.c) */ X #define offset(field) XtOffset(struct _resource *, field) X static XtResource application_resources[] = { X {"name", "Name", XtRString, sizeof(char *), #ifdef KTERM X offset(xterm_name), XtRString, "kterm"}, #else /* !KTERM */ X offset(xterm_name), XtRString, "xterm"}, #endif /* !KTERM */ X {"iconGeometry", "IconGeometry", XtRString, sizeof(char *), X offset(icon_geometry), XtRString, (caddr_t) NULL}, X {XtNtitle, XtCTitle, XtRString, sizeof(char *), X offset(title), XtRString, (caddr_t) NULL}, X {XtNiconName, XtCIconName, XtRString, sizeof(char *), X offset(icon_name), XtRString, (caddr_t) NULL}, X {"termName", "TermName", XtRString, sizeof(char *), X offset(term_name), XtRString, (caddr_t) NULL}, X {"ttyModes", "TtyModes", XtRString, sizeof(char *), X offset(tty_modes), XtRString, (caddr_t) NULL}, X {"utmpInhibit", "UtmpInhibit", XtRBoolean, sizeof (Boolean), X offset(utmpInhibit), XtRString, "false"}, X {"sunFunctionKeys", "SunFunctionKeys", XtRBoolean, sizeof (Boolean), X offset(sunFunctionKeys), XtRString, "false"}, X {"waitForMap", "WaitForMap", XtRBoolean, sizeof (Boolean), X offset(wait_for_map), XtRString, "false"}, #ifdef KEEPALIVE X {"keepAlive", "KeepAlive", XtRBoolean, sizeof (Boolean), X offset(keepalive), XtRString, "false"}, #endif /* KEEPALIVE */ }; #undef offset X /* Command line options table. Only resources are entered here...there is a X pass over the remaining options after XtParseCommand is let loose. */ X static char *fallback_resources[] = { #ifdef KTERM X "KTerm*SimpleMenu*menuLabel.vertSpace: 100", X "KTerm*SimpleMenu*HorizontalMargins: 16", X "KTerm*SimpleMenu*Sme.height: 16", X "KTerm*SimpleMenu*Cursor: left_ptr", X "KTerm*mainMenu.Label: Main Options (no app-defaults)", X "KTerm*vtMenu.Label: VT Options (no app-defaults)", X "KTerm*fontMenu.Label: VT Fonts (no app-defaults)", X "KTerm*tekMenu.Label: Tek Options (no app-defaults)", #else /* !KTERM */ X "XTerm*SimpleMenu*menuLabel.vertSpace: 100", X "XTerm*SimpleMenu*HorizontalMargins: 16", X "XTerm*SimpleMenu*Sme.height: 16", X "XTerm*SimpleMenu*Cursor: left_ptr", X "XTerm*mainMenu.Label: Main Options (no app-defaults)", X "XTerm*vtMenu.Label: VT Options (no app-defaults)", X "XTerm*fontMenu.Label: VT Fonts (no app-defaults)", X "XTerm*tekMenu.Label: Tek Options (no app-defaults)", #endif /* !KTERM */ X NULL }; X static XrmOptionDescRec optionDescList[] = { {"-geometry", "*vt100.geometry",XrmoptionSepArg, (caddr_t) NULL}, {"-132", "*c132", XrmoptionNoArg, (caddr_t) "on"}, {"+132", "*c132", XrmoptionNoArg, (caddr_t) "off"}, {"-ah", "*alwaysHighlight", XrmoptionNoArg, (caddr_t) "on"}, {"+ah", "*alwaysHighlight", XrmoptionNoArg, (caddr_t) "off"}, {"-b", "*internalBorder",XrmoptionSepArg, (caddr_t) NULL}, {"-cb", "*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "off"}, {"+cb", "*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "on"}, {"-cc", "*charClass", XrmoptionSepArg, (caddr_t) NULL}, {"-cn", "*cutNewline", XrmoptionNoArg, (caddr_t) "off"}, {"+cn", "*cutNewline", XrmoptionNoArg, (caddr_t) "on"}, {"-cr", "*cursorColor", XrmoptionSepArg, (caddr_t) NULL}, {"-cu", "*curses", XrmoptionNoArg, (caddr_t) "on"}, {"+cu", "*curses", XrmoptionNoArg, (caddr_t) "off"}, {"-e", NULL, XrmoptionSkipLine, (caddr_t) NULL}, #ifndef ENBUG /* kagotani */ {"-fn", "*vt100.font", XrmoptionSepArg, (caddr_t) NULL}, #endif {"-fb", "*boldFont", XrmoptionSepArg, (caddr_t) NULL}, #ifdef KTERM {"-fl", "*fontList", XrmoptionSepArg, (caddr_t) NULL}, {"-flb", "*boldFontList", XrmoptionSepArg, (caddr_t) NULL}, {"-fr", "*romanKanaFont", XrmoptionSepArg, (caddr_t) NULL}, {"-frb", "*romanKanaBoldFont", XrmoptionSepArg, (caddr_t) NULL}, #ifdef KTERM_KANJI #ifdef KTERM_HANZI {"-fhz", "*hanziFont", XrmoptionSepArg, (caddr_t) NULL}, {"-fhzb", "*hanziBoldFont", XrmoptionSepArg, (caddr_t) NULL}, {"-hzm", "*hanziMode", XrmoptionSepArg, (caddr_t) NULL}, #endif /* KTERM_HANZI */ #ifdef KTERM_HANGUL {"-fhg", "*hangulFont", XrmoptionSepArg, (caddr_t) NULL}, {"-fhgb", "*hangulBoldFont", XrmoptionSepArg, (caddr_t) NULL}, {"-hgm", "*hangulMode", XrmoptionSepArg, (caddr_t) NULL}, #endif /* KTERM_HANGUL */ {"-fk", "*kanjiFont", XrmoptionSepArg, (caddr_t) NULL}, {"-fkb", "*kanjiBoldFont", XrmoptionSepArg, (caddr_t) NULL}, {"-km", "*kanjiMode", XrmoptionSepArg, (caddr_t) NULL}, {"-lang", "*language", XrmoptionSepArg, (caddr_t) NULL}, #endif /* KTERM_KANJI */ {"-lsp", "*lineSpace", XrmoptionSepArg, (caddr_t) NULL}, #endif /* KTERM */ {"-j", "*jumpScroll", XrmoptionNoArg, (caddr_t) "on"}, {"+j", "*jumpScroll", XrmoptionNoArg, (caddr_t) "off"}, #ifdef KEEPALIVE {"-ka", "*keepAlive", XrmoptionNoArg, (caddr_t) "on"}, {"+ka", "*keepAlive", XrmoptionNoArg, (caddr_t) "off"}, #endif /* KEEPALIVE */ {"-l", "*logging", XrmoptionNoArg, (caddr_t) "on"}, {"+l", "*logging", XrmoptionNoArg, (caddr_t) "off"}, {"-lf", "*logFile", XrmoptionSepArg, (caddr_t) NULL}, {"-ls", "*loginShell", XrmoptionNoArg, (caddr_t) "on"}, {"+ls", "*loginShell", XrmoptionNoArg, (caddr_t) "off"}, {"-mb", "*marginBell", XrmoptionNoArg, (caddr_t) "on"}, {"+mb", "*marginBell", XrmoptionNoArg, (caddr_t) "off"}, {"-mc", "*multiClickTime", XrmoptionSepArg, (caddr_t) NULL}, {"-ms", "*pointerColor",XrmoptionSepArg, (caddr_t) NULL}, {"-nb", "*nMarginBell", XrmoptionSepArg, (caddr_t) NULL}, {"-rw", "*reverseWrap", XrmoptionNoArg, (caddr_t) "on"}, {"+rw", "*reverseWrap", XrmoptionNoArg, (caddr_t) "off"}, {"-s", "*multiScroll", XrmoptionNoArg, (caddr_t) "on"}, {"+s", "*multiScroll", XrmoptionNoArg, (caddr_t) "off"}, {"-sb", "*scrollBar", XrmoptionNoArg, (caddr_t) "on"}, {"+sb", "*scrollBar", XrmoptionNoArg, (caddr_t) "off"}, {"-sf", "*sunFunctionKeys", XrmoptionNoArg, (caddr_t) "on"}, {"+sf", "*sunFunctionKeys", XrmoptionNoArg, (caddr_t) "off"}, {"-si", "*scrollTtyOutput", XrmoptionNoArg, (caddr_t) "off"}, {"+si", "*scrollTtyOutput", XrmoptionNoArg, (caddr_t) "on"}, {"-sk", "*scrollKey", XrmoptionNoArg, (caddr_t) "on"}, {"+sk", "*scrollKey", XrmoptionNoArg, (caddr_t) "off"}, #ifdef STATUSLINE {"-st", "*statusLine", XrmoptionNoArg, (caddr_t) "on"}, {"+st", "*statusLine", XrmoptionNoArg, (caddr_t) "off"}, {"-sn", "*statusNormal", XrmoptionNoArg, (caddr_t) "on"}, {"+sn", "*statusNormal", XrmoptionNoArg, (caddr_t) "off"}, #endif /* STATUSLINE */ {"-sl", "*saveLines", XrmoptionSepArg, (caddr_t) NULL}, {"-t", "*tekStartup", XrmoptionNoArg, (caddr_t) "on"}, {"+t", "*tekStartup", XrmoptionNoArg, (caddr_t) "off"}, {"-tm", "*ttyModes", XrmoptionSepArg, (caddr_t) NULL}, {"-tn", "*termName", XrmoptionSepArg, (caddr_t) NULL}, {"-ut", "*utmpInhibit", XrmoptionNoArg, (caddr_t) "on"}, {"+ut", "*utmpInhibit", XrmoptionNoArg, (caddr_t) "off"}, {"-vb", "*visualBell", XrmoptionNoArg, (caddr_t) "on"}, {"+vb", "*visualBell", XrmoptionNoArg, (caddr_t) "off"}, {"-wf", "*waitForMap", XrmoptionNoArg, (caddr_t) "on"}, {"+wf", "*waitForMap", XrmoptionNoArg, (caddr_t) "off"}, /* bogus old compatibility stuff for which there are X standard XtInitialize options now */ {"%", "*tekGeometry", XrmoptionStickyArg, (caddr_t) NULL}, {"#", ".iconGeometry",XrmoptionStickyArg, (caddr_t) NULL}, {"-T", "*title", XrmoptionSepArg, (caddr_t) NULL}, {"-n", "*iconName", XrmoptionSepArg, (caddr_t) NULL}, {"-r", "*reverseVideo",XrmoptionNoArg, (caddr_t) "on"}, {"+r", "*reverseVideo",XrmoptionNoArg, (caddr_t) "off"}, {"-rv", "*reverseVideo",XrmoptionNoArg, (caddr_t) "on"}, {"+rv", "*reverseVideo",XrmoptionNoArg, (caddr_t) "off"}, {"-w", ".borderWidth", XrmoptionSepArg, (caddr_t) NULL}, }; X static struct _options { X char *opt; X char *desc; } options[] = { { "-help", "print out this message" }, #ifdef KTERM { "-version", "print out kterm version info" }, #endif /* KTERM */ { "-display displayname", "X server to contact" }, { "-geometry geom", "size (in characters) and position" }, { "-/+rv", "turn on/off reverse video" }, { "-bg color", "background color" }, { "-fg color", "foreground color" }, { "-bd color", "border color" }, { "-bw number", "border width in pixels" }, { "-fn fontname", "normal text font" }, { "-iconic", "start iconic" }, { "-name string", "client instance, icon, and title strings" }, { "-title string", "title string" }, { "-xrm resourcestring", "additional resource specifications" }, { "-/+132", "turn on/off column switch inhibiting" }, { "-/+ah", "turn on/off always highlight" }, { "-b number", "internal border in pixels" }, { "-/+cb", "turn on/off cut-to-beginning-of-line inhibit" }, { "-cc classrange", "specify additional character classes" }, { "-/+cn", "turn on/off cut newline inhibit" }, { "-cr color", "text cursor color" }, { "-/+cu", "turn on/off curses emulation" }, { "-fb fontname", "bold text font" }, #ifdef KTERM { "-fl fontlist", "normal fonts" }, { "-flb fontlist", "bold fonts" }, { "-fr fontname", "normal kana font" }, { "-frb fontname", "bold kana font" }, #ifdef KTERM_KANJI #ifdef KTERM_HANZI { "-fhz fontname", "normal Hanzi font" }, { "-fhzb fontname", "bold Hanzi font" }, { "-hzm hanzimode", "input Hanzi code (guobiao|big5|shift-guobiao)" }, #endif /* KTERM_HANZI */ #ifdef KTERM_HANGUL { "-fhg fontname", "normal Hangul font" }, { "-fhgb fontname", "bold Hangul font" }, { "-hgm hangulmode", "input Hangul code (ks-8bit|n-byte)" }, #endif /* KTERM_HANGUL */ { "-fk fontname", "normal Kanji font" }, { "-fkb fontname", "bold Kanji font" }, { "-km kanjimode", "input Kanji code (jis|euc|sjis)" }, { "-lang language", "which language to be displayed (chinese|japanese|korean)" }, #endif /* KTERM_KANJI */ { "-lsp number", "number of extra dots between lines" }, #endif /* KTERM */ { "-/+j", "turn on/off jump scroll" }, #ifdef KEEPALIVE { "-/+ka", "turn on/off keeping connection alive" }, #endif /* KEEPALIVE */ { "-/+l", "turn on/off logging" }, { "-lf filename", "logging filename" }, { "-/+ls", "turn on/off login shell" }, { "-/+mb", "turn on/off margin bell" }, { "-mc milliseconds", "multiclick time in milliseconds" }, { "-ms color", "pointer color" }, { "-nb number", "margin bell in characters from right end" }, { "-/+rw", "turn on/off reverse wraparound" }, { "-/+s", "turn on/off multiscroll" }, { "-/+sb", "turn on/off scrollbar" }, { "-/+sf", "turn on/off Sun Function Key escape codes" }, { "-/+si", "turn on/off scroll-on-tty-output inhibit" }, { "-/+sk", "turn on/off scroll-on-keypress" }, { "-sl number", "number of scrolled lines to save" }, #ifdef STATUSLINE { "-/+st", "turn on/off status line" }, { "-/+sn", "turn on/off status line normal video" }, #endif /* STATUSLINE */ { "-/+t", "turn on/off Tek emulation window" }, { "-tm string", "terminal mode keywords and characters" }, { "-tn name", "TERM environment variable name" }, { "-/+ut", "turn on/off utmp inhibit" }, { "-/+vb", "turn on/off visual bell" }, { "-e command args", "command to execute" }, { "%geom", "Tek window geometry" }, { "#geom", "icon window geometry" }, { "-T string", "title name for window" }, { "-n string", "icon name for window" }, { "-C", "intercept console messages, if supported" }, { "-Sxxd", "slave mode on \"ttyxx\", file descriptor \"d\"" }, { NULL, NULL }}; X static char *message[] = { "Fonts must be fixed width and, if both normal and bold are specified, must", "have the same size. If only a normal font is specified, it will be used for", "both normal and bold text (by doing overstriking). The -e option, if given,", "must be appear at the end of the command line, otherwise the user's default", "shell will be started. Options that start with a plus sign (+) restore the", "default.", NULL}; X static void Syntax (badOption) X char *badOption; { X struct _options *opt; X int col; X X fprintf (stderr, "%s: bad command line option \"%s\"\r\n\n", X ProgramName, badOption); X X fprintf (stderr, "usage: %s", ProgramName); X col = 8 + strlen(ProgramName); X for (opt = options; opt->opt; opt++) { X int len = 3 + strlen(opt->opt); /* space [ string ] */ X if (col + len > 79) { X fprintf (stderr, "\r\n "); /* 3 spaces */ X col = 3; X } X fprintf (stderr, " [%s]", opt->opt); X col += len; X } X X fprintf (stderr, "\r\n\nType %s -help for a full description.\r\n\n", X ProgramName); X exit (1); } X static void Help () { X struct _options *opt; X char **cpp; X X fprintf (stderr, "usage:\n %s [-options ...] [-e command args]\n\n", X ProgramName); X fprintf (stderr, "where options include:\n"); X for (opt = options; opt->opt; opt++) { X fprintf (stderr, " %-28s %s\n", opt->opt, opt->desc); X } X X putc ('\n', stderr); X for (cpp = message; *cpp; cpp++) { X fputs (*cpp, stderr); X putc ('\n', stderr); X } X putc ('\n', stderr); X X exit (0); } X #ifdef KTERM static void Version () { X fprintf (stderr, "kterm: version %s (patchlevel %d)\n", KTERM_VERSION, X patchlevel); X fprintf (stderr, " with"); #ifdef KTERM_KANJI X fprintf (stderr, " [KTERM_KANJI]"); # ifdef KTERM_HANZI X fprintf(stderr, " [KTERM_HANZI]"); # endif # ifdef KTERM_HANGUL X fprintf(stderr, " [KTERM_HANGUL]"); # endif # ifdef MB_WSEL X fprintf(stderr, " [MB_WSEL]"); # endif #endif #ifdef KTERM_KCONV X fprintf (stderr, " [KTERM_KCONV]"); #endif #ifdef KTERM_CTEXT X fprintf(stderr, " [KTERM_CTEXT]"); #endif /* KTERM_CTEXT */ #ifdef COLOR_TEXT X fprintf(stderr, " [COLOR_TEXT]"); #endif /* COLOR_TEXT */ #ifdef STATUSLINE X fprintf (stderr, " [STATUSLINE]"); #endif #ifdef KEEPALIVE X fprintf (stderr, " [KEEPALIVE]"); #endif X fprintf (stderr, " options.\n"); X X exit (0); } #endif /* KTERM */ X extern WidgetClass xtermWidgetClass; X Arg ourTopLevelShellArgs[] = { X { XtNallowShellResize, (XtArgVal) TRUE }, X { XtNinput, (XtArgVal) TRUE }, }; int number_ourTopLevelShellArgs = 2; X XXtAppContext app_con; Widget toplevel; Bool waiting_for_initial_map; X main (argc, argv) int argc; char **argv; { X register TScreen *screen; X register int i, pty; X int Xsocket, mode; X char *basename(); X int xerror(), xioerror(); X X ProgramName = argv[0]; X X ttydev = (char *) malloc (strlen (TTYDEV) + 1); X ptydev = (char *) malloc (strlen (PTYDEV) + 1); X if (!ttydev || !ptydev) { X fprintf (stderr, X "%s: unable to allocate memory for ttydev or ptydev\n", X ProgramName); X exit (1); X } X strcpy (ttydev, TTYDEV); X strcpy (ptydev, PTYDEV); X #ifdef USE_SYSV_TERMIO X /* Initialization is done here rather than above in order X ** to prevent any assumptions about the order of the contents X ** of the various terminal structures (which may change from X ** implementation to implementation). X */ #if defined(macII) || defined(att) X d_tio.c_iflag = ICRNL|IXON; X d_tio.c_oflag = OPOST|ONLCR|TAB3; X d_tio.c_cflag = B9600|CS8|CREAD|PARENB|HUPCL; X d_tio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; X X d_tio.c_line = 0; X X d_tio.c_cc[VINTR] = CINTR; X d_tio.c_cc[VQUIT] = CQUIT; X d_tio.c_cc[VERASE] = CERASE; X d_tio.c_cc[VKILL] = CKILL; X d_tio.c_cc[VEOF] = CEOF; X d_tio.c_cc[VEOL] = CNUL; X d_tio.c_cc[VEOL2] = CNUL; X d_tio.c_cc[VSWTCH] = CNUL; X #ifdef TIOCSLTC X d_ltc.t_suspc = CSUSP; /* t_suspc */ X d_ltc.t_dsuspc = CDSUSP; /* t_dsuspc */ X d_ltc.t_rprntc = 0; /* reserved...*/ X d_ltc.t_flushc = 0; X d_ltc.t_werasc = 0; X d_ltc.t_lnextc = 0; #endif /* TIOCSLTC */ #else /* else !macII */ X d_tio.c_iflag = ICRNL|IXON; X d_tio.c_oflag = OPOST|ONLCR|TAB3; #ifdef BAUD_0 X d_tio.c_cflag = CS8|CREAD|PARENB|HUPCL; #else /* !BAUD_0 */ X d_tio.c_cflag = B9600|CS8|CREAD|PARENB|HUPCL; #endif /* !BAUD_0 */ X d_tio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; X d_tio.c_line = 0; X d_tio.c_cc[VINTR] = 0x7f; /* DEL */ X d_tio.c_cc[VQUIT] = '\\' & 0x3f; /* '^\' */ X d_tio.c_cc[VERASE] = '#'; /* '#' */ X d_tio.c_cc[VKILL] = '@'; /* '@' */ X d_tio.c_cc[VEOF] = 'D' & 0x3f; /* '^D' */ X d_tio.c_cc[VEOL] = '@' & 0x3f; /* '^@' */ #ifdef VSWTCH X d_tio.c_cc[VSWTCH] = '@' & 0x3f; /* '^@' */ #endif /* VSWTCH */ X /* now, try to inherit tty settings */ X { X int i; X X for (i = 0; i <= 2; i++) { X struct termio deftio; X if (ioctl (i, TCGETA, &deftio) == 0) { X d_tio.c_cc[VINTR] = deftio.c_cc[VINTR]; X d_tio.c_cc[VQUIT] = deftio.c_cc[VQUIT]; X d_tio.c_cc[VERASE] = deftio.c_cc[VERASE]; X d_tio.c_cc[VKILL] = deftio.c_cc[VKILL]; X d_tio.c_cc[VEOF] = deftio.c_cc[VEOF]; X d_tio.c_cc[VEOL] = deftio.c_cc[VEOL]; #ifdef VSWTCH X d_tio.c_cc[VSWTCH] = deftio.c_cc[VSWTCH]; #endif /* VSWTCH */ X break; X } X } X } #ifdef TIOCSLTC X d_ltc.t_suspc = '\000'; /* t_suspc */ X d_ltc.t_dsuspc = '\000'; /* t_dsuspc */ X d_ltc.t_rprntc = '\377'; /* reserved...*/ X d_ltc.t_flushc = '\377'; X d_ltc.t_werasc = '\377'; X d_ltc.t_lnextc = '\377'; #endif /* TIOCSLTC */ #ifdef TIOCLSET X d_lmode = 0; #endif /* TIOCLSET */ #endif /* macII */ #endif /* USE_SYSV_TERMIO */ X X /* Init the Toolkit. */ #ifdef KTERM X toplevel = XtAppInitialize (&app_con, "KTerm", #else /* !KTERM */ X toplevel = XtAppInitialize (&app_con, "XTerm", #endif /* !KTERM */ X optionDescList, XtNumber(optionDescList), X &argc, argv, fallback_resources, X NULL, 0); X X XtGetApplicationResources( toplevel, &resource, application_resources, X XtNumber(application_resources), NULL, 0 ); X X waiting_for_initial_map = resource.wait_for_map; X #ifdef KEEPALIVE X if (resource.keepalive) { X int on = 1; X (void)setsockopt(ConnectionNumber(XtDisplay(toplevel)), X SOL_SOCKET, SO_KEEPALIVE, X (char *)&on, sizeof(on)); X } #endif /* KEEPALIVE */ X /* X * fill in terminal modes X */ X if (resource.tty_modes) { X int n = parse_tty_modes (resource.tty_modes, X ttymodelist, NXTTYMODES); X if (n < 0) { X fprintf (stderr, "%s: bad tty modes \"%s\"\n", X ProgramName, resource.tty_modes); X } else if (n > 0) { X override_tty_modes = 1; X } X } X X xterm_name = resource.xterm_name; X sunFunctionKeys = resource.sunFunctionKeys; #ifdef KTERM X if (strcmp(xterm_name, "-") == 0) xterm_name = "kterm"; #else /* KTERM */ X if (strcmp(xterm_name, "-") == 0) xterm_name = "xterm"; #endif /* KTERM */ X if (resource.icon_geometry != NULL) { X int scr, junk; X int ix, iy; X Arg args[2]; X X for(scr = 0; /* yyuucchh */ X XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel),scr); X scr++); X X args[0].name = XtNiconX; X args[1].name = XtNiconY; X XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "", X 0, 0, 0, 0, 0, &ix, &iy, &junk, &junk); X args[0].value = (XtArgVal) ix; X args[1].value = (XtArgVal) iy; X XtSetValues( toplevel, args, 2); X } X X XtSetValues (toplevel, ourTopLevelShellArgs, X number_ourTopLevelShellArgs); X X X /* Parse the rest of the command line */ X for (argc--, argv++ ; argc > 0 ; argc--, argv++) { X if(**argv != '-') Syntax (*argv); X X switch(argv[0][1]) { X case 'h': X Help (); X /* NOTREACHED */ #ifdef KTERM X case 'v': X Version (); X /* NOTREACHED */ #endif /* KTERM */ X case 'C': #ifdef TIOCCONS X Console = TRUE; #endif /* TIOCCONS */ X continue; X case 'S': X sscanf(*argv + 2, "%c%c%d", passedPty, passedPty+1, X &am_slave); X if (am_slave <= 0) Syntax(*argv); X continue; #ifdef DEBUG X case 'D': X debug = TRUE; X continue; #endif /* DEBUG */ X case 'e': X if (argc <= 1) Syntax (*argv); X command_to_exec = ++argv; X break; X default: X Syntax (*argv); X } X break; X } X X XawSimpleMenuAddGlobalActions (XtWidgetToApplicationContext(toplevel)); X XtRegisterGrabAction (HandlePopupMenu, True, X (ButtonPressMask|ButtonReleaseMask), X GrabModeAsync, GrabModeAsync); X X term = (XtermWidget) XtCreateManagedWidget( X "vt100", xtermWidgetClass, toplevel, NULL, 0); X /* this causes the initialize method to be called */ X X screen = &term->screen; X X term->flags = WRAPAROUND; X update_autowrap(); X if (!screen->jumpscroll) { X term->flags |= SMOOTHSCROLL; X update_jumpscroll(); X } X if (term->misc.reverseWrap) { X term->flags |= REVERSEWRAP; X update_reversewrap(); X } X if (term->misc.re_verse) { X term->flags |= REVERSE_VIDEO; X update_reversevideo(); X } X #ifdef KTERM_KANJI X if (!term->misc.lang) { X XtWarning("Language choice not found."); X term->misc.lang = KTERM_DEFAULT_LANG; X term->misc.k_m = KTERM_DEFAULT_MODE; X } X X switch(term->misc.lang[0]) { #ifdef KTERM_HANZI X case 'c': X case 'C': X (void)load_hzconv_table(term->misc.hz_gb2big_tbl); X (void)load_hzconv_table(term->misc.hz_big2gb_tbl); X if (term->misc.hz_m) { X switch (term->misc.hz_m[0]) { X case 'g': case 'G': X term->flags |= GUOBIAO_HANZI; X break; X case 'b': case 'B': X term->flags |= BIG5_HANZI; X update_big5mode(); X break; X case 's': case 'S': X term->flags |= SGB_HANZI; X update_sgbmode(); X break; X } X } X break; #endif /* KTERM_HANZI */ #ifdef KTERM_HANGUL X case 'k': X case 'K': X load_hgconv_table(term->misc.hg_n2ks_tbl); X if (term->misc.hg_m) { X switch(term->misc.hg_m[0]) { X case 'k': case 'K': X term->flags |= KS_HANGUL; X update_ksmode(); X break; X case 'n': case 'N': X term->flags |= NBYTE_HANGUL; X update_nbmode(); X break; X } X } X break; #endif /* KTERM_HANGUL */ X /* X * The default language will be Japanese, so set necessary flags. X */ X X default: X switch (term->misc.k_m[0]) { X case 'j': case 'J': X break; X case 'e': case 'E': case 'x': case 'X': case 'u': case 'U': X term->flags |= EUC_KANJI; X update_eucmode(); X break; X case 's': case 'S': case 'm': case 'M': X term->flags |= SJIS_KANJI; X update_sjismode(); X break; X } X } #endif /* KTERM_KANJI */ X X inhibit = 0; X if (term->misc.logInhibit) inhibit |= I_LOG; X if (term->misc.signalInhibit) inhibit |= I_SIGNAL; X if (term->misc.tekInhibit) inhibit |= I_TEK; X #ifdef STATUSLINE X screen->reversestatus = !term->misc.statusnormal; #endif /* STATUSLINE */ X X term->initflags = term->flags; X /* X * Set title and icon name if not specified X */ X X if (command_to_exec) { X Arg args[2]; X X if (!resource.title) { X if (command_to_exec) { X resource.title = basename (command_to_exec[0]); X } /* else not reached */ X } X X if (!resource.icon_name) X resource.icon_name = resource.title; X XtSetArg (args[0], XtNtitle, resource.title); X XtSetArg (args[1], XtNiconName, resource.icon_name); X X XtSetValues (toplevel, args, 2); X } X X X if(inhibit & I_TEK) X screen->TekEmu = FALSE; X X if(screen->TekEmu && !TekInit()) X exit(ERROR_INIT); X X /* set up stderr properly */ X i = -1; #ifdef DEBUG X if(debug) X i = open ("xterm.debug.log", O_WRONLY | O_CREAT | O_TRUNC, X 0666); #endif /* DEBUG */ X if(i >= 0) { #ifdef USE_SYSV_TERMIO X /* SYSV has another pointer which should be part of the X ** FILE structure but is actually a seperate array. X */ X unsigned char *old_bufend; X X old_bufend = (unsigned char *) _bufend(stderr); X stderr->_file = i; X _bufend(stderr) = old_bufend; #else /* USE_SYSV_TERMIO */ X stderr->_file = i; #endif /* USE_SYSV_TERMIO */ X X /* mark this file as close on exec */ X (void) fcntl(i, F_SETFD, 1); X } X X /* open a terminal for client */ X get_terminal (); X spawn (); X /* Child process is out there, let's catch it's termination */ X signal (SIGCHLD, reapchild); X X /* Realize procs have now been executed */ X X Xsocket = screen->display->fd; X pty = screen->respond; X X if (am_slave) { /* Write window id so master end can read and use */ X char buf[80]; X X buf[0] = '\0'; X sprintf (buf, "%lx\n", X screen->TekEmu ? XtWindow (XtParent (tekWidget)) : X XtWindow (XtParent (term))); X write (pty, buf, strlen (buf)); X } X X if (term->misc.log_on) { X StartLog(screen); X } X screen->inhibit = inhibit; X #ifdef USE_SYSV_TERMIO X if (0 > (mode = fcntl(pty, F_GETFL, 0))) X Error(); X mode |= O_NDELAY; X if (fcntl(pty, F_SETFL, mode)) X Error(); #else /* USE_SYSV_TERMIO */ X mode = 1; X if (ioctl (pty, FIONBIO, (char *)&mode) == -1) SysError (ERROR_FIONBIO); #endif /* USE_SYSV_TERMIO */ X X pty_mask = 1 << pty; X X_mask = 1 << Xsocket; X Select_mask = pty_mask | X_mask; X max_plus1 = (pty < Xsocket) ? (1 + Xsocket) : (1 + pty); X #ifdef DEBUG X if (debug) printf ("debugging on\n"); #endif /* DEBUG */ X XSetErrorHandler(xerror); X XSetIOErrorHandler(xioerror); X for( ; ; ) { X if(screen->TekEmu) { X TekRun(); X } else X VTRun(); X } } X char *basename(name) char *name; { X register char *cp; X char *rindex(); X X return((cp = rindex(name, '/')) ? cp + 1 : name); } X /* This function opens up a pty master and stuffs it's value into pty. X * If it finds one, it returns a value of 0. If it does not find one, X * it returns a value of !0. This routine is designed to be re-entrant, X * so that if a pty master is found and later, we find that the slave X * has problems, we can re-enter this function and get another one. X */ X get_pty (pty) int *pty; { X static int devindex, letter = 0; X #ifdef att X if ((*pty = open ("/dev/ptmx", O_RDWR)) < 0) { X return 1; X } X return 0; #else /* !att, need lots of code */ X #if defined(umips) && defined (SYSTYPE_SYSV) X struct stat fstat_buf; X X *pty = open ("/dev/ptc", O_RDWR); X if (*pty < 0 || (fstat (*pty, &fstat_buf)) < 0) { X return(1); X } X sprintf (ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev)); X sprintf (ptydev, "/dev/ptyq%d", minor(fstat_buf.st_rdev)); X if ((*tty = open (ttydev, O_RDWR)) < 0) { X close (*pty); X return(1); X } X /* got one! */ X return(0); #else /* not (umips && SYSTYPE_SYSV) */ #ifdef CRAY X for (; devindex < 256; devindex++) { X sprintf (ttydev, "/dev/ttyp%03d", devindex); X sprintf (ptydev, "/dev/pty/%03d", devindex); X X if ((*pty = open (ptydev, O_RDWR)) >= 0) { X /* We need to set things up for our next entry X * into this function! X */ X (void) devindex++; X return(0); X } X } #else /* !CRAY */ X while (PTYCHAR1[letter]) { X ttydev [strlen(ttydev) - 2] = ptydev [strlen(ptydev) - 2] = X PTYCHAR1 [letter]; X X while (PTYCHAR2[devindex]) { X ttydev [strlen(ttydev) - 1] = ptydev [strlen(ptydev) - 1] = X PTYCHAR2 [devindex]; X if ((*pty = open (ptydev, O_RDWR)) >= 0) { X /* We need to set things up for our next entry X * into this function! X */ X (void) devindex++; X return(0); X } X devindex++; X } X devindex = 0; X (void) letter++; X } #endif /* CRAY else not CRAY */ X /* We were unable to allocate a pty master! Return an error X * condition and let our caller terminate cleanly. X */ X return(1); #endif /* umips && SYSTYPE_SYSV */ #endif /* att */ } X get_terminal () /* X * sets up X and initializes the terminal structure except for term.buf.fildes. X */ { X register TScreen *screen = &term->screen; X X screen->arrow = make_colored_cursor (XC_left_ptr, X screen->mousecolor, X screen->mousecolorback); } X /* X * The only difference in /etc/termcap between 4014 and 4015 is that X * the latter has support for switching character sets. We support the X * 4015 protocol, but ignore the character switches. Therefore, we should X * probably choose 4014 over 4015. X */ X static char *tekterm[] = { X "tek4014", X "tek4015", /* has alternate character set switching */ X "tek4013", X "tek4010", X "dumb", X 0 }; X static char *vtterm[] = { #ifdef KTERM X "kterm", #endif #ifdef USE_X11TERM X "x11term", /* for people who want special term name */ #endif X "xterm", /* the prefered name, should be fastest */ X "vt102", X "vt100", X "ansi", X "dumb", X 0 }; X /* ARGSUSED */ SIGNAL_T hungtty(i) X int i; { X longjmp(env, 1); X SIGNAL_RETURN; } X #ifdef USE_HANDSHAKE typedef enum { /* c == child, p == parent */ X PTY_BAD, /* c->p: can't open pty slave for some reason */ X PTY_FATALERROR, /* c->p: we had a fatal error with the pty */ X PTY_GOOD, /* c->p: we have a good pty, let's go on */ X PTY_NEW, /* p->c: here is a new pty slave, try this */ X PTY_NOMORE, /* p->c; no more pty's, terminate */ X UTMP_ADDED, /* c->p: utmp entry has been added */ X UTMP_TTYSLOT, /* c->p: here is my ttyslot */ X PTY_EXEC /* p->c: window has been mapped the first time */ } status_t; X typedef struct { X status_t status; X int error; X int fatal_error; X int tty_slot; X int rows; X int cols; X char buffer[1024]; } handshake_t; X /* HsSysError() X * X * This routine does the equivalent of a SysError but it handshakes X * over the errno and error exit to the master process so that it can X * display our error message and exit with our exit code so that the X * user can see it. X */ X void HsSysError(pf, error) int pf; int error; { X handshake_t handshake; X X handshake.status = PTY_FATALERROR; X handshake.error = errno; X handshake.fatal_error = error; X strcpy(handshake.buffer, ttydev); X write(pf, &handshake, sizeof(handshake)); X exit(error); } X static int pc_pipe[2]; /* this pipe is used for parent to child transfer */ static int cp_pipe[2]; /* this pipe is used for child to parent transfer */ X first_map_occurred () { X handshake_t handshake; X register TScreen *screen = &term->screen; X X if (screen->max_row > 0 && screen->max_col > 0) { X handshake.status = PTY_EXEC; X handshake.rows = screen->max_row; X handshake.cols = screen->max_col; X write (pc_pipe[1], (char *) &handshake, sizeof(handshake)); X close (cp_pipe[0]); X close (pc_pipe[1]); X waiting_for_initial_map = False; X } } #else /* X * temporary hack to get xterm working on att ptys X */ first_map_occurred () { X return; } #define HsSysError(a,b) #endif /* USE_HANDSHAKE else !USE_HANDSHAKE */ X X spawn () /* X * Inits pty and tty and forks a login process. X * Does not close fd Xsocket. X * If slave, the pty named in passedPty is already open for use X */ { X extern char *SysErrorMsg(); X register TScreen *screen = &term->screen; X int Xsocket = screen->display->fd; #ifdef USE_HANDSHAKE X handshake_t handshake; #else X int fds[2]; #endif X int tty = -1; X int discipline; X int done; #ifdef USE_SYSV_TERMIO X struct termio tio; X struct termio dummy_tio; #ifdef TIOCLSET X unsigned lmode; #endif /* TIOCLSET */ #ifdef TIOCSLTC X struct ltchars ltc; #endif /* TIOCSLTC */ X int one = 1; X int zero = 0; X int status; #else /* else not USE_SYSV_TERMIO */ X unsigned lmode; X struct tchars tc; X struct ltchars ltc; X struct sgttyb sg; #endif /* USE_SYSV_TERMIO */ X X char termcap [1024]; X char newtc [1024]; X char *ptr, *shname, *shname_minus; X int i, no_dev_tty = FALSE; #ifdef USE_SYSV_TERMIO X char *dev_tty_name = (char *) 0; X int fd; /* for /etc/wtmp */ #endif /* USE_SYSV_TERMIO */ X char **envnew; /* new environment */ X char buf[32]; X char *TermName = NULL; X int ldisc = 0; #ifdef sun #ifdef TIOCSSIZE X struct ttysize ts; #endif /* TIOCSSIZE */ #else /* not sun */ #ifdef TIOCSWINSZ X struct winsize ws; #endif /* TIOCSWINSZ */ #endif /* sun */ X struct passwd *pw = NULL; #ifdef UTMP X struct utmp utmp; #ifdef LASTLOG X struct lastlog lastlog; #endif /* LASTLOG */ #endif /* UTMP */ X X screen->uid = getuid(); X screen->gid = getgid(); X #ifdef SIGTTOU X /* so that TIOCSWINSZ || TIOCSIZE doesn't block */ X signal(SIGTTOU,SIG_IGN); #endif X X if (am_slave) { X screen->respond = am_slave; X ptydev[strlen(ptydev) - 2] = ttydev[strlen(ttydev) - 2] = X passedPty[0]; X ptydev[strlen(ptydev) - 1] = ttydev[strlen(ttydev) - 1] = X passedPty[1]; X X setgid (screen->gid); X setuid (screen->uid); X } else { X Bool tty_got_hung = False; X X /* X * Sometimes /dev/tty hangs on open (as in the case of a pty X * that has gone away). Simply make up some reasonable X * defaults. X */ X signal(SIGALRM, hungtty); X alarm(2); /* alarm(1) might return too soon */ X if (! setjmp(env)) { X tty = open ("/dev/tty", O_RDWR, 0); X alarm(0); X } else { X tty_got_hung = True; X tty = -1; X errno = ENXIO; X } X signal(SIGALRM, SIG_DFL); X X /* X * Check results and ignore current control terminal if X * necessary. ENXIO is what is normally returned if there is X * no controlling terminal, but some systems (e.g. SunOS 4.0) X * seem to return EIO. X */ X if (tty < 0) { X if (tty_got_hung || errno == ENXIO || errno == EIO) { X no_dev_tty = TRUE; #ifdef USE_SYSV_TERMIO X tio = d_tio; #ifdef TIOCSLTC X ltc = d_ltc; #endif /* TIOCSLTC */ #ifdef TIOCLSET X lmode = d_lmode; #endif /* TIOCLSET */ #else /* not USE_SYSV_TERMIO */ X sg = d_sg; X tc = d_tc; X discipline = d_disipline; X ltc = d_ltc; X lmode = d_lmode; #endif /* USE_SYSV_TERMIO */ X } else { X SysError(ERROR_OPDEVTTY); X } X } else { X /* get a copy of the current terminal's state */ X #ifdef USE_SYSV_TERMIO X if(ioctl(tty, TCGETA, &tio) == -1) X SysError(ERROR_TIOCGETP); #ifdef TIOCSLTC X if(ioctl(tty, TIOCGLTC, <c) == -1) X SysError(ERROR_TIOCGLTC); #endif /* TIOCSLTC */ #ifdef TIOCLSET X if(ioctl(tty, TIOCLGET, &lmode) == -1) X SysError(ERROR_TIOCLGET); #endif /* TIOCLSET */ #else /* not USE_SYSV_TERMIO */ X if(ioctl(tty, TIOCGETP, (char *)&sg) == -1) X SysError (ERROR_TIOCGETP); X if(ioctl(tty, TIOCGETC, (char *)&tc) == -1) X SysError (ERROR_TIOCGETC); X if(ioctl(tty, TIOCGETD, (char *)&discipline) == -1) X SysError (ERROR_TIOCGETD); X if(ioctl(tty, TIOCGLTC, (char *)<c) == -1) X SysError (ERROR_TIOCGLTC); X if(ioctl(tty, TIOCLGET, (char *)&lmode) == -1) X SysError (ERROR_TIOCLGET); #endif /* USE_SYSV_TERMIO */ X close (tty); X /* tty is no longer an open fd! */ X tty = -1; X } X #ifdef PUCC_PTYD X if(-1 == (screen->respond = openrpty(ttydev, ptydev, X (resource.utmpInhibit ? OPTY_NOP : OPTY_LOGIN), X getuid(), XDisplayString(screen->display)))) { #else /* not PUCC_PTYD */ X if (get_pty (&screen->respond)) { #endif /* PUCC_PTYD */ X /* no ptys! */ X (void) fprintf(stderr, "%s: no available ptys\n", X xterm_name); X exit (ERROR_PTYS); #ifdef PUCC_PTYD X } #else X } /* keep braces balanced for emacs */ #endif #ifdef PUCC_PTYD X else { X /* X * set the fd of the master in a global var so X * we can undo all this on exit X * X */ X Ptyfd = screen->respond; X } #endif /* PUCC_PTYD */ X } X X /* avoid double MapWindow requests */ X XtSetMappedWhenManaged( screen->TekEmu ? XtParent(tekWidget) : X XtParent(term), False ); X /* Realize the Tek or VT widget, depending on which mode we're in. X If VT mode, this calls VTRealize (the widget's Realize proc) */ X XtRealizeWidget (screen->TekEmu ? XtParent(tekWidget) : X XtParent(term)); X X if(screen->TekEmu) { X envnew = tekterm; X ptr = newtc; X } else { X envnew = vtterm; X ptr = termcap; X } X TermName = NULL; X if (resource.term_name) { X if (tgetent (ptr, resource.term_name) == 1) { X TermName = resource.term_name; X if (!screen->TekEmu) X resize (screen, TermName, termcap, newtc); X } else { X fprintf (stderr, "%s: invalid termcap entry \"%s\".\n", X ProgramName, resource.term_name); X } X } X if (!TermName) { X while (*envnew != NULL) { X if(tgetent(ptr, *envnew) == 1) { X TermName = *envnew; X if(!screen->TekEmu) X resize(screen, TermName, termcap, newtc); X break; X } X envnew++; X } X if (TermName == NULL) { X fprintf (stderr, "%s: unable to find usable termcap entry.\n", X ProgramName); X Exit (1); X } X } X #ifdef sun #ifdef TIOCSSIZE X /* tell tty how big window is */ X if(screen->TekEmu) { X ts.ts_lines = 38; X ts.ts_cols = 81; X } else { X ts.ts_lines = screen->max_row + 1; X ts.ts_cols = screen->max_col + 1; X } #endif /* TIOCSSIZE */ #else /* not sun */ #ifdef TIOCSWINSZ X /* tell tty how big window is */ X if(screen->TekEmu) { X ws.ws_row = 38; X ws.ws_col = 81; X ws.ws_xpixel = TFullWidth(screen); X ws.ws_ypixel = TFullHeight(screen); X } else { X ws.ws_row = screen->max_row + 1; X ws.ws_col = screen->max_col + 1; X ws.ws_xpixel = FullWidth(screen); X ws.ws_ypixel = FullHeight(screen); X } #endif /* TIOCSWINSZ */ #endif /* sun */ X X if (!am_slave) { #ifdef USE_HANDSHAKE X if (pipe(pc_pipe) || pipe(cp_pipe)) X SysError (ERROR_FORK); #endif X if ((screen->pid = fork ()) == -1) X SysError (ERROR_FORK); X X if (screen->pid == 0) { X /* X * now in child process X */ X extern char **environ; X int pgrp = getpid(); #ifdef USE_SYSV_TERMIO X char numbuf[12]; #endif /* USE_SYSV_TERMIO */ X #ifndef USE_HANDSHAKE X int ptyfd; X X setpgrp(); X grantpt (screen->respond); X unlockpt (screen->respond); X if ((ptyfd = open (ptsname(screen->respond), O_RDWR)) < 0) { X SysError (1); X } X if (ioctl (ptyfd, I_PUSH, "ptem") < 0) { X SysError (2); X } X if (!getenv("CONSEM") && ioctl (ptyfd, I_PUSH, "consem") < 0) { X SysError (3); X } X if (ioctl (ptyfd, I_PUSH, "ldterm") < 0) { X SysError (4); X } X tty = ptyfd; X close (screen->respond); #ifdef TIOCSWINSZ X /* tell tty how big window is */ X if(screen->TekEmu) { X ws.ws_row = 24; X ws.ws_col = 80; X ws.ws_xpixel = TFullWidth(screen); X ws.ws_ypixel = TFullHeight(screen); X } else { X ws.ws_row = screen->max_row + 1; X ws.ws_col = screen->max_col + 1; X ws.ws_xpixel = FullWidth(screen); X ws.ws_ypixel = FullHeight(screen); X } #endif X X #else /* USE_HANDSHAKE: warning, goes for a long ways */ X /* close parent's sides of the pipes */ X close (cp_pipe[0]); X close (pc_pipe[1]); X X /* Make sure that our sides of the pipes are not in the X * 0, 1, 2 range so that we don't fight with stdin, out X * or err. X */ X if (cp_pipe[1] <= 2) { X if ((i = fcntl(cp_pipe[1], F_DUPFD, 3)) >= 0) { X (void) close(cp_pipe[1]); X cp_pipe[1] = i; X } X } X if (pc_pipe[0] <= 2) { X if ((i = fcntl(pc_pipe[0], F_DUPFD, 3)) >= 0) { X (void) close(pc_pipe[0]); X pc_pipe[0] = i; X } X } X X /* we don't need the socket, or the pty master anymore */ X close (Xsocket); X close (screen->respond); X X /* Now is the time to set up our process group and X * open up the pty slave. X */ #ifdef USE_SYSV_PGRP X (void) setpgrp(); #endif /* USE_SYSV_PGRP */ X while (1) { #ifdef TIOCNOTTY X if ((tty = open ("/dev/tty", 2)) >= 0) { X ioctl (tty, TIOCNOTTY, (char *) NULL); X close (tty); X } #endif /* TIOCNOTTY */ X if ((tty = open(ttydev, O_RDWR, 0)) >= 0) { #ifdef USE_SYSV_PGRP X /* We need to make sure that we are acutally X * the process group leader for the pty. If X * we are, then we should now be able to open X * /dev/tty. X */ X if ((i = open("/dev/tty", O_RDWR, 0)) >= 0) { X /* success! */ X close(i); X break; X } #else /* USE_SYSV_PGRP */ X break; #endif /* USE_SYSV_PGRP */ X } X #ifdef TIOCSCTTY X ioctl(tty, TIOCSCTTY, 0); #endif X /* let our master know that the open failed */ X handshake.status = PTY_BAD; X handshake.error = errno; X strcpy(handshake.buffer, ttydev); X write(cp_pipe[1], (char *) &handshake, X sizeof(handshake)); X X /* get reply from parent */ X i = read(pc_pipe[0], (char *) &handshake, X sizeof(handshake)); X if (i <= 0) { X /* parent terminated */ X exit(1); X } X X if (handshake.status == PTY_NOMORE) { X /* No more ptys, let's shutdown. */ X exit(1); X } X X /* We have a new pty to try */ X free(ttydev); X ttydev = malloc((unsigned) X (strlen(handshake.buffer) + 1)); X strcpy(ttydev, handshake.buffer); X } X X /* use the same tty name that everyone else will use X ** (from ttyname) X */ X if (ptr = ttyname(tty)) X { X /* it may be bigger */ X ttydev = realloc (ttydev, (unsigned) (strlen(ptr) + 1)); X (void) strcpy(ttydev, ptr); X } X #endif /* !USE_HANDSHAKE else USE_HANDSHAKE - from near fork */ X #ifdef USE_TTY_GROUP X { #include <grp.h> X struct group *ttygrp; X if (ttygrp = getgrnam("tty")) { X /* change ownership of tty to real uid, "tty" gid */ X chown (ttydev, screen->uid, ttygrp->gr_gid); X chmod (ttydev, 0620); X } X else { X /* change ownership of tty to real group and user id */ X chown (ttydev, screen->uid, screen->gid); X chmod (ttydev, 0622); X } X endgrent(); X } #else /* else !USE_TTY_GROUP */ X /* change ownership of tty to real group and user id */ X chown (ttydev, screen->uid, screen->gid); X X /* change protection of tty */ X chmod (ttydev, 0622); #endif /* USE_TTY_GROUP */ X X /* X * set up the tty modes X */ X { #ifdef USE_SYSV_TERMIO #ifdef umips X /* If the control tty had its modes screwed around with, X eg. by lineedit in the shell, or emacs, etc. then tio X will have bad values. Let's just get termio from the X new tty and tailor it. */ X if (ioctl (tty, TCGETA, &tio) == -1) X SysError (ERROR_TIOCGETP); X tio.c_lflag |= ECHOE; #endif /* umips */ X /* Now is also the time to change the modes of the X * child pty. X */ X /* input: nl->nl, don't ignore cr, cr->nl */ X tio.c_iflag &= ~(INLCR|IGNCR); X tio.c_iflag |= ICRNL; X /* ouput: cr->cr, nl is not return, no delays, ln->cr/nl */ X tio.c_oflag &= X ~(OCRNL|ONLRET|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); X tio.c_oflag |= ONLCR; #ifdef BAUD_0 X /* baud rate is 0 (don't care) */ X tio.c_cflag &= ~(CBAUD); #else /* !BAUD_0 */ X /* baud rate is 9600 (nice default) */ X tio.c_cflag &= ~(CBAUD); X tio.c_cflag |= B9600; #endif /* !BAUD_0 */ X /* enable signals, canonical processing (erase, kill, etc), X ** echo X */ X tio.c_lflag |= ISIG|ICANON|ECHO; X /* reset EOL to defalult value */ X tio.c_cc[VEOL] = '@' & 0x3f; /* '^@' */ X /* certain shells (ksh & csh) change EOF as well */ X tio.c_cc[VEOF] = 'D' & 0x3f; /* '^D' */ X #define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value; X if (override_tty_modes) { X /* sysv-specific */ X TMODE (XTTYMODE_intr, tio.c_cc[VINTR]); X TMODE (XTTYMODE_quit, tio.c_cc[VQUIT]); X TMODE (XTTYMODE_erase, tio.c_cc[VERASE]); X TMODE (XTTYMODE_kill, tio.c_cc[VKILL]); X TMODE (XTTYMODE_eof, tio.c_cc[VEOF]); X TMODE (XTTYMODE_eol, tio.c_cc[VEOL]); #ifdef VSWTCH X TMODE (XTTYMODE_swtch, d_tio.c_cc[VSWTCH]); #endif #ifdef TIOCSLTC X /* both SYSV and BSD have ltchars */ X TMODE (XTTYMODE_susp, ltc.t_suspc); X TMODE (XTTYMODE_dsusp, ltc.t_dsuspc); X TMODE (XTTYMODE_rprnt, ltc.t_rprntc); X TMODE (XTTYMODE_flush, ltc.t_flushc); X TMODE (XTTYMODE_weras, ltc.t_werasc); X TMODE (XTTYMODE_lnext, ltc.t_lnextc); #endif X } #undef TMODE X X if (ioctl (tty, TCSETA, &tio) == -1) X HsSysError(cp_pipe[1], ERROR_TIOCSETP); #ifdef TIOCSLTC X if (ioctl (tty, TIOCSLTC, <c) == -1) X HsSysError(cp_pipe[1], ERROR_TIOCSETC); #endif /* TIOCSLTC */ #ifdef TIOCLSET X if (ioctl (tty, TIOCLSET, (char *)&lmode) == -1) X HsSysError(cp_pipe[1], ERROR_TIOCLSET); #endif /* TIOCLSET */ #ifdef TIOCCONS X if (Console) { X int on = 1; X if (ioctl (tty, TIOCCONS, (char *)&on) == -1) X HsSysError(cp_pipe[1], ERROR_TIOCCONS); X } #endif /* TIOCCONS */ #else /* USE_SYSV_TERMIO */ #ifdef KTERM X sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW X | EVENP | ODDP); #else /* !KTERM */ X sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW); #endif /* !KTERM */ X sg.sg_flags |= ECHO | CRMOD; X /* make sure speed is set on pty so that editors work right*/ X sg.sg_ispeed = B9600; X sg.sg_ospeed = B9600; X /* reset t_brkc to default value */ X tc.t_brkc = -1; X #define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value; X if (override_tty_modes) { X TMODE (XTTYMODE_intr, tc.t_intrc); X TMODE (XTTYMODE_quit, tc.t_quitc); X TMODE (XTTYMODE_erase, sg.sg_erase); X TMODE (XTTYMODE_kill, sg.sg_kill); X TMODE (XTTYMODE_eof, tc.t_eofc); X TMODE (XTTYMODE_start, tc.t_startc); X TMODE (XTTYMODE_stop, tc.t_stopc); X TMODE (XTTYMODE_brk, tc.t_brkc); X /* both SYSV and BSD have ltchars */ X TMODE (XTTYMODE_susp, ltc.t_suspc); X TMODE (XTTYMODE_dsusp, ltc.t_dsuspc); X TMODE (XTTYMODE_rprnt, ltc.t_rprntc); X TMODE (XTTYMODE_flush, ltc.t_flushc); X TMODE (XTTYMODE_weras, ltc.t_werasc); X TMODE (XTTYMODE_lnext, ltc.t_lnextc); X } #undef TMODE X X if (ioctl (tty, TIOCSETP, (char *)&sg) == -1) X HsSysError (cp_pipe[1], ERROR_TIOCSETP); X if (ioctl (tty, TIOCSETC, (char *)&tc) == -1) X HsSysError (cp_pipe[1], ERROR_TIOCSETC); X if (ioctl (tty, TIOCSETD, (char *)&discipline) == -1) X HsSysError (cp_pipe[1], ERROR_TIOCSETD); X if (ioctl (tty, TIOCSLTC, (char *)<c) == -1) X HsSysError (cp_pipe[1], ERROR_TIOCSLTC); X if (ioctl (tty, TIOCLSET, (char *)&lmode) == -1) X HsSysError (cp_pipe[1], ERROR_TIOCLSET); #ifdef TIOCCONS X if (Console) { X int on = 1; X if (ioctl (tty, TIOCCONS, (char *)&on) == -1) X HsSysError(cp_pipe[1], ERROR_TIOCCONS); X } #endif /* TIOCCONS */ #endif /* !USE_SYSV_TERMIO */ X } X X signal (SIGCHLD, SIG_DFL); #ifdef att X /* watch out for extra shells (I don't understand either) */ X signal (SIGHUP, SIG_DFL); #else X signal (SIGHUP, SIG_IGN); #endif X /* restore various signals to their defaults */ X signal (SIGINT, SIG_DFL); X signal (SIGQUIT, SIG_DFL); X signal (SIGTERM, SIG_DFL); X X /* copy the environment before Setenving */ X for (i = 0 ; environ [i] != NULL ; i++) ; X /* X * The `4' (`5' for SYSV) is the number of Setenv() X * calls which may add a new entry to the environment. X * The `1' is for the NULL terminating entry. X */ #ifdef USE_SYSV_ENVVARS X envnew = (char **) calloc ((unsigned) i + (5 + 1), sizeof(char *)); #else X envnew = (char **) calloc ((unsigned) i + (4 + 1), sizeof(char *)); #endif /* USE_SYSV_ENVVARS */ SHAR_EOF true || echo 'restore of kterm-4.1.2/main.c failed' fi echo 'End of kterm-4.1.2 part 13' echo 'File kterm-4.1.2/main.c is continued in part 14' echo 14 > _shar_seq_.tmp exit 0 ----------------------------------------------------------------------------- mleisher@nmsu.edu "I laughed. Mark Leisher I cried. Computing Research Lab I fell down. New Mexico State University It changed my life." Las Cruces, NM - Rich [Cowboy Feng's Space Bar and Grille] -- Dan Heller O'Reilly && Associates Z-Code Software Comp-sources-x: Senior Writer President comp-sources.x@uunet.uu.net argv@ora.com argv@zipcode.com