#include /* Copyright Massachusetts Institute of Technology 1984, 1985 */ /* ptyx.c */ #ifndef lint static char *rcsid_ptyx_c = "$Header: main.c,v 10.44 86/05/16 10:17:20 jg Exp $"; #endif lint #include #include #include #include #include #include #include #include #include #include #include #include "ptyx.h" #include #include #include char *xterm_name; /* argv[0] */ Terminal term; /* master data structure for client */ int am_slave = 0; /* set to 1 if running as a slave process */ int debug = 0; /* true causes error messages to be displayed */ static char *ptydev = "/dev/ptyxx"; static char *ttydev = "/dev/ttyxx"; #include "../cursors/xterm.cursor" #include "../cursors/xterm_mask.cursor" #include "icon.ic" #include "icon_mask.ic" static int reapchild (); static char **command_to_exec = (char **) NULL; static char *win_name = (char *) 0; static struct sgttyb d_sg = { 0, 0, 0177, CKILL, EVENP|ODDP|ECHO|XTABS|CRMOD }; static struct tchars d_tc = { CINTR, CQUIT, CSTART, CSTOP, CEOF, CBRK, }; static struct ltchars d_ltc = { CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT }; static int d_disipline = NTTYDISC; static int d_lmode = LCRTBS|LCRTERA|LCRTKIL|LCTLECH; static int no_dev_tty = 0; static int loginflag = 0; static int dologinflag = 0; #ifdef sun #ifdef TIOCCONS static int SunConsole = 0; #endif TIOCCONS #endif sun main (argc, argv) int argc; char **argv; { int ind; char *strind, *strind1, *strscan(); char *fn = "vtsingle"; char *fb = "vtbold"; short fnflag = 0; /* True iff -fn option used */ short fbflag = 0; /* True iff -fb option used */ char *getty = NULL; int reverse = 0, multiscroll = 0; int border = 1, tek = 0; int borderwidth = 2; int bitmapicon = 0; #ifdef JUMPSCROLL int jumpscroll = 0; #endif JUMPSCROLL int slave = 0; /* if non-zero, run as slave */ char passedPty[2]; /* name if pty if slave */ char *fore_color; char *back_color; char *brdr_color; char *curs_color; char *mous_color; char display[256]; char *getenv(); char *option; char *geometry, *def = "=80x24+1+1"; xterm_name = argv[0]; display[0] = '\0'; /* * go get options out of default file */ if ((option = XGetDefault(argv[0], "BodyFont")) != NULL) { fn = option; fnflag = 1; } if ((option = XGetDefault(argv[0], "BoldFont")) != NULL) { fb = option; fbflag = 1; } if ((option = XGetDefault(argv[0], "InternalBorder")) != NULL) { border = atoi (option); } if ((option = XGetDefault(argv[0], "BorderWidth")) != NULL) { borderwidth = atoi (option); } if ((option = XGetDefault(argv[0], "BitmapIcon")) != NULL) if (strcmp (option, "on") == 0) bitmapicon = 1; if ((option = XGetDefault(argv[0], "ReverseVideo")) != NULL) if (strcmp (option, "on") == 0) reverse = 1; if ((option = XGetDefault(argv[0], "Tektronix")) != NULL) if (strcmp (option, "on") == 0) tek = 1; #ifdef JUMPSCROLL if ((option = XGetDefault(argv[0], "JumpScroll")) != NULL) if (strcmp (option, "on") == 0) jumpscroll = 1; #endif JUMPSCROLL fore_color = XGetDefault(argv[0], "Foreground"); back_color = XGetDefault(argv[0], "Background"); brdr_color = XGetDefault(argv[0], "Border"); curs_color = XGetDefault(argv[0], "Cursor"); mous_color = XGetDefault(argv[0], "Mouse"); /* parse command line */ for (ind = 1; ind < argc; ind++) { if (argv [ind] [0] == '=') { geometry = argv[ind]; continue; } strind = index (argv[ind], ':'); if(strind != NULL) { strncpy(display,argv[ind],sizeof(display)); continue; } strind = (char *) index (argv [ind], '-'); if (strind == NULL) Syntax (); if (strcmp (argv [ind], "-L") == 0) { char tt[32]; int mode = O_RDWR|O_NDELAY; loginflag = 1; getty = argv[argc-1]; argc -= 1; strcpy(tt,"/dev/"); strcat(tt, getty); chown(tt, 0, 0); chmod(tt, 0622); if (open(tt, mode, 0) < 0) { consolepr("open failed\n"); } signal(SIGHUP, SIG_IGN); vhangup(); setpgrp(0,0); signal(SIGHUP, SIG_DFL); open(tt, mode, 0); close(0); dup(1); dup(0); continue; } if (strncmp (argv [ind], "-S", 2) == 0) { sscanf(argv[ind] + 2, "%c%c%d", passedPty, passedPty+1, &slave); if (slave <= 0) Syntax(); am_slave = 1; continue; } if (strcmp (argv [ind], "-e") == 0) { if (++ind >= argc) Syntax (); command_to_exec = argv + ind; break; } /* Switch to set up Tektronix-shaped (4096x3128 -> 512x390) window * with characters sized to fit 39 lines of 85 characters each */ if (strcmp (argv [ind], "-t") == 0) { tek = 1; if (!fnflag) fn = "6x10"; if (!fbflag) fb = "6x10"; def = "85x39+1+1"; continue; } if (strcmp (argv [ind], "-fn") == 0) { if (++ind >= argc) Syntax (); fn = argv [ind]; fnflag = 1; continue; } if (strcmp (argv [ind], "-fb") == 0) { if (++ind >= argc) Syntax (); fb = argv [ind]; fbflag = 1; continue; } if (strcmp (argv [ind], "-fg") == 0) { if (++ind >= argc) Syntax (); fore_color = argv [ind]; continue; } if (strcmp (argv [ind], "-bg") == 0) { if (++ind >= argc) Syntax (); back_color = argv [ind]; continue; } if (strcmp (argv [ind], "-bd") == 0) { if (++ind >= argc) Syntax (); brdr_color = argv [ind]; continue; } if (strcmp (argv [ind], "-cr") == 0) { if (++ind >= argc) Syntax (); curs_color = argv [ind]; continue; } if (strcmp (argv [ind], "-ms") == 0) { if (++ind >= argc) Syntax (); mous_color = argv [ind]; continue; } if (strcmp (argv [ind], "-l") == 0) { dologinflag = 1; continue; } if (strcmp (argv [ind], "-d") == 0) { debug = 1; continue; } if (strcmp (argv [ind], "-b") == 0) { if (++ind >= argc) Syntax (); border = atoi (argv [ind]); continue; } if (strcmp (argv [ind], "-bw") == 0 || strcmp (argv [ind], "-w") == 0) { if (++ind >= argc) Syntax (); borderwidth = atoi (argv [ind]); continue; } if (strcmp (argv [ind], "-rv") == 0 || strcmp (argv [ind], "-r") == 0) { reverse = 1; /* backwards from usual definition */ continue; } if (strcmp (argv [ind], "-s") == 0) { multiscroll = 1; continue; } if (strcmp (argv [ind], "-i") == 0) { bitmapicon = 1; continue; } #ifdef JUMPSCROLL if (strcmp (argv [ind], "-j") == 0) { jumpscroll = 1; continue; } #endif JUMPSCROLL if (strcmp (argv [ind], "-n") == 0) { if (++ind >= argc) Syntax (); win_name = argv [ind]; continue; } #ifdef sun #ifdef TIOCCONS if (strcmp (argv [ind], "-C") == 0) { SunConsole = 1; continue; } #endif TIOCCONS #endif sun Syntax (); } if (fnflag && !fbflag) fb = fn; if (!fnflag && fbflag) fn = fb; #ifdef JUMPSCROLL if(tek) jumpscroll = 0; #endif JUMPSCROLL Serve (display, fn, fb, geometry, def, getty, slave, passedPty, border, borderwidth, tek, reverse, multiscroll, bitmapicon, fore_color, back_color, brdr_color, curs_color, mous_color #ifdef JUMPSCROLL , jumpscroll #endif JUMPSCROLL ); } Syntax () { static char *ustring[] = { "Usage: xterm [-rv] [-fn normal_font] [-fb bold_font]\n", "\t[=[width]x[height][[+-]xoff[[+-]yoff]]] [-bw bdr_width]\n", "\t[-fg color] [-bg color] [-bd color] [-cr color] [-ms color]\n", "\t[[[host]:vs]] [-d] [-s] [-t] [-i] [-j] [-e command_to_exec]\n", "\t[-n window_name]\n\n", "Fonts must be of fixed width and of same size;\n", "If only one font is specified, it will be used for normal and bold text\n", #ifdef JUMPSCROLL "The -j option enables jump scroll\n", #endif "The -s option enables asynchronous scrolling\n", "The -t option enables Tektronics 4010 emulation\n", "The -i option enables bitmap icons\n", "The -d option turns debugging on (error messages printed)\n", "The -n option sets the window name\n", "The -b option specifies the inner padding\n", "Default is: xterm -fn vtsingle -fb vtbold =80x24 :0\n", 0}; char **us = ustring; while (*us) fputs(*us++, stderr); exit (1); } char *strscan (search, what) /* Returns pointer to first char ins search which is also in what, else NULL. */ char *search, *what; { int i, len = strlen (what); char c; while ((c = *(search++)) != NULL) for (i = 0; i < len; i++) if (c == what [i]) return (--search); return (NULL); } Serve (disp, fn, fb, geometry, def, getty, slave, passedPty, border, borderwidth, tek, reverse, multiscroll, bitmapicon, fore_color, back_color, brdr_color, curs_color, mous_color #ifdef JUMPSCROLL , jumpscroll #endif JUMPSCROLL ) char *disp; /* host of display to serve */ char *fn; /* fontname of normal characters */ char *fb; /* fontname of bold characters */ char *getty; /* true iff child should be getty */ int slave; /* true if should run as slave (contains file # of pty) */ char *passedPty; /* name of pty to use if slave */ char *geometry; /* user supplied geometry spec */ char *def; /* default geometry spec */ int border; /* inner border in pixels */ int borderwidth; /* outer border in pixels */ int tek; /* true ==> Tektronics emulation */ int reverse; /* true ==> black background, white characters */ int multiscroll; /* true ==> asynchronous full-screen scrolling */ int bitmapicon; /* true ==> bitmap icons rather than text icon */ #ifdef JUMPSCROLL int jumpscroll; /* true ==> fast multi-line scrolling */ #endif JUMPSCROLL char *fore_color;/* text color */ char *back_color;/* background color */ char *brdr_color;/* border color */ char *curs_color;/* text cursor color */ char *mous_color;/* mouse cursor color */ { int pty; /* fildes for pty of client */ XEvent reply; XEvent *rep = & reply; int aborted = 0; int Select_mask, select_mask = 0; int maxplus1; short toggled = NULL; Screen *screen = &term.screen; int Xsocket; int pty_mask, X_mask; extern int errno; int mode = 1; #ifdef TIOCSWINSZ struct winsize ws; #endif signal (SIGCHLD, reapchild); signal (SIGHUP, SIG_IGN); /* open a terminal for client */ get_terminal (disp, &term, fn, fb, geometry, def, border, borderwidth, (int)getty, slave, reverse, multiscroll, bitmapicon, tek, fore_color, back_color, brdr_color, curs_color, mous_color #ifdef JUMPSCROLL , jumpscroll #endif JUMPSCROLL ); Xsocket = screen->display->fd; spawn (disp, &pty, Xsocket, screen, getty, slave, passedPty); if (slave) { /* Write window id so master end can read and use */ write(pty, &screen->window, sizeof(screen->window)); write(pty, "\n", 1); } screen->respond = term.buf.fildes = pty; #ifdef TIOCSWINSZ /* tell tty how big window is */ ws.ws_row = screen->max_row + 1; ws.ws_col = screen->max_col + 1; ws.ws_xpixel = screen->width; ws.ws_ypixel = screen->height; ioctl (screen->respond, TIOCSWINSZ, &ws); #endif /* Initialize Tektronix graphics mode parameters */ TekErase (&term); screen->TekEmu = tek; screen->cur_x = screen->cur_y = 0; screen->cur_X = screen->cur_Y = 0; screen->TekGMode = 0; screen->TekAMode = 0; screen->TekPMode = 0; if (ioctl (pty, FIONBIO, &mode) == -1) Error (); pty_mask = 1 << pty; X_mask = 1 << Xsocket; Select_mask = pty_mask | X_mask; maxplus1 = (pty < Xsocket) ? (1 + Xsocket) : (1 + pty); if (debug) printf ("debugging on\n"); while (1) { if (! aborted) { #ifdef JUMPSCROLL if(screen->scroll_amt) FlushScroll(screen); #endif JUMPSCROLL if (toggled) { CursorToggle (screen, toggled); toggled = NULL; } select_mask = Select_mask; XFlush(); while (select (maxplus1, &select_mask, NULL, NULL, 0) <= 0) { if (errno != EINTR) Error(); } } else select_mask = NULL; if (select_mask & pty_mask || aborted) { if (!toggled) { CursorToggle (screen, toggled); toggled = 1; } do { aborted = (*screen->mode)(&term); } while (screen->display->qlen==0 && term.buf.cnt>0); } if (select_mask & X_mask || aborted) { #ifdef JUMPSCROLL if(screen->scroll_amt) FlushScroll(screen); #endif JUMPSCROLL XPending (); do { XNextEvent (&reply); switch ((int)reply.type) { case KeyPressed: Input (&term.keyboard, &term.screen, (XKeyPressedEvent *)rep); break; case ExposeWindow: if (bitmapicon) { if (((XExposeWindowEvent *)rep)->window == screen->iconwindow) { RefreshIcon(screen); break; } } toggled = 1; if (ScreenResize (screen, ((XExposeWindowEvent *)rep)->width, ((XExposeWindowEvent *)rep)->height, &term.flags) != -1) { TabReset (term.tabs); XClear (screen->window); ScrnRefresh (screen, 0, 0, screen->max_row + 1, screen->max_col + 1); if (screen->TekEmu) TekRefresh (&term); } break; case ExposeRegion: if (((XExposeWindowEvent *)rep)->detail == ExposeCopy && screen->incopy <= 0) { screen->incopy = 1; if (screen->scrolls > 0) screen->scrolls--; } if (HandleExposure (screen, &reply)) toggled = 1; break; case ExposeCopy: if (screen->incopy <= 0 && screen->scrolls > 0) screen->scrolls--; if (screen->scrolls) screen->incopy = -1; else screen->incopy = 0; break; case ButtonPressed: case ButtonReleased: if (screen->incopy) CopyWait (screen); if (HandleButtons(&term,&reply,pty)) toggled = 1; break; /* * Enter window is being handled just to give xterm * a kick in the pants when the mouse gets in the * window in case it was swapped out. Of course, * one might thrash... */ case EnterWindow: break; default: break; } } while (screen->display->qlen > 0); } } } RefreshIcon(screen) register Screen *screen; { XBitmapBitsPut(screen->iconwindow, 0, 0, icon_width, icon_height, icon_bits, screen->foreground, screen->background, screen->iconmask, GXcopy, AllPlanes); } get_pty (pty, pty_name) /* opens a pty, storing fildes in pty and it's identifying character in pty_name. */ int *pty; char *pty_name; { int devindex, letter = 0; int fd; extern errno; if (debug) { fd = open ("xterm.debug.log", O_WRONLY | O_CREAT | O_TRUNC, 0666); dup2 (fd, fileno (stderr)); } while (letter < 4) { ttydev [8] = ptydev [8] = "pqrs" [letter++]; devindex = 0; while (devindex < 16) { ptydev [9] = *pty_name = "0123456789abcdef" [devindex++]; if ((*pty = open (ptydev, O_RDWR, 0)) < 0) { if (debug) fprintf (stderr, "pty %d code %d\n", devindex - 1, errno); continue; } goto got_pty; } } fprintf (stderr,"Not enough available pty's\n"); exit (11); got_pty: if (debug) { close (fileno (stderr)); close (fd); } } get_terminal (disp, term, fn, fb, geometry, def, border, borderwidth, do_warp, slave, reverse, multiscroll, bitmapicon, tek, fore_color, back_color, brdr_color, curs_color, mous_color #ifdef JUMPSCROLL , jumpscroll #endif JUMPSCROLL ) /* * sets up X and initializes the terminal structure except for term.buf.fildes. */ char *disp; register Terminal *term; char *fn, *fb; char *geometry, *def; int border, borderwidth, do_warp, reverse, multiscroll, bitmapicon; int slave; int tek; #ifdef JUMPSCROLL int jumpscroll; #endif JUMPSCROLL char *fore_color, *back_color, *brdr_color, *curs_color, *mous_color; { int width, height; FontInfo *fInfo; register Keyboard *keyboard; register Screen *screen; Buffer *buf; double scale_x, scale_y; Color cdef; int pixels[2]; int try = 10; OpaqueFrame twindow; keyboard = &term->keyboard; screen = &term->screen; buf = &term->buf; term->flags = WRAPAROUND|SMOOTHSCROLL; keyboard->flags = NULL; keyboard->offset = 0; buf->cnt = 0; buf->ptr = &buf->buf[0]; TabReset (term->tabs); while (try--) if ((screen->display = XOpenDisplay(disp)) == NULL) { if (loginflag == 0) { fprintf(stderr,"No such display server %s\n", disp); exit(1); } sleep (5); continue; } else break; if (try <= 0) { fprintf (stderr,"Can't connect to display server %s\n", disp); exit (111); } screen->foreground = BlackPixel; screen->background = WhitePixel; screen->cursorcolor = BlackPixel; screen->mousecolor = BlackPixel; screen->xorplane = 1; if (DisplayCells() > 2 && (fore_color || back_color || curs_color)) { if (tek) { if (curs_color && XParseColor(curs_color, &cdef)) { if (XGetColorCells(0, 2, 1, &screen->xorplane, pixels)) { screen->background = pixels[0]; screen->foreground = pixels[1]; screen->cursorcolor = screen->background | screen->xorplane; cdef.pixel = screen->cursorcolor; XStoreColor(&cdef); } } else if (XGetColorCells(0, 1, 1, &screen->xorplane, &screen->background)) { screen->foreground = screen->background | screen->xorplane; screen->cursorcolor = screen->foreground; } if (screen->background != WhitePixel) { if (back_color == NULL || !XParseColor(back_color, &cdef)) { cdef.pixel = WhitePixel; XQueryColor(&cdef); } cdef.pixel = screen->background; XStoreColor(&cdef); if(screen->cursorcolor != screen->foreground) { cdef.pixel = screen->foreground | screen->xorplane; XStoreColor(&cdef); } if (fore_color == NULL || !XParseColor(fore_color, &cdef)) { cdef.pixel = BlackPixel; XQueryColor(&cdef); } cdef.pixel = screen->foreground; XStoreColor(&cdef); } } else { if (fore_color && XParseColor(fore_color, &cdef) && XGetHardwareColor(&cdef)) { screen->foreground = screen->foreground = cdef.pixel; reverse = 0; } if (back_color && XParseColor(back_color, &cdef) && XGetHardwareColor(&cdef)) { screen->background = cdef.pixel; reverse = 0; } if (curs_color && XParseColor(curs_color, &cdef) && XGetHardwareColor(&cdef)) screen->cursorcolor = cdef.pixel; else screen->cursorcolor = screen->foreground; } } screen->border = border; screen->borderwidth = borderwidth; screen->fnt_norm = screen->fnt_bold = NULL; if ((fInfo = XOpenFont(fn)) == NULL) { fprintf(stderr, "%s: Could not open font %s!\n", xterm_name, fn); exit(1); } if (fn) screen->fnt_norm = fInfo->id; if (fb) screen->fnt_bold = XOpenFont(fb)->id; screen->f_width = fInfo->width; screen->f_height = fInfo->height; if (brdr_color && DisplayCells() > 2 && XParseColor(brdr_color, &cdef) && XGetHardwareColor(&cdef)) screen->bordertile = XMakeTile(cdef.pixel); else screen->bordertile = BlackPixmap; screen->cursor = XStoreBitmap(xterm_width, xterm_height, xterm_bits); screen->mask = XStoreBitmap(xterm_mask_width, xterm_mask_height, xterm_mask_bits); if (mous_color && DisplayCells() > 2 && XParseColor(mous_color, &cdef) && XGetHardwareColor(&cdef)) screen->mousecolor = cdef.pixel; else screen->mousecolor = screen->cursorcolor; screen->curs = XStoreCursor(screen->cursor, screen->mask, 5, 8, screen->mousecolor, screen->background, GXcopy); screen->rcurs = XStoreCursor(screen->cursor, screen->mask, 5, 8, screen->background, screen->mousecolor, GXcopy); if (reverse) { /* reverse is black background with white chars */ term->flags |= REVERSE_VIDEO; screen->cursorcolor = screen->background; screen->background = screen->foreground; screen->foreground = screen->cursorcolor; if (screen->bordertile == BlackPixmap) screen->bordertile = WhitePixmap; } screen->bgndtile = XMakeTile(screen->background); twindow.bdrwidth = screen->borderwidth; twindow.border = screen->bordertile; twindow.background = screen->bgndtile; screen->window = XCreateTerm ("Terminal Emulator", xterm_name, geometry, def, &twindow, 12, 8, screen->border * 2, screen->border * 2, &width, &height, fInfo, fInfo->width, fInfo->height); screen->width = twindow.width - border * 2; screen->height = twindow.height - border * 2; /* Reset variables used by ANSI emulation. */ screen->ansi.a_type = 0; /* New sequence. */ screen->ansi.a_pintro = 0; /* New sequence. */ screen->ansi.a_final = 0; /* New sequence. */ screen->gsets[0] = 'B'; /* ASCII_G */ screen->gsets[1] = 'B'; screen->gsets[2] = '<'; /* DEC supplemental. */ screen->gsets[3] = '<'; screen->curgl = 0; /* G0 => GL. */ screen->curgr = 2; /* G2 => GR. */ screen->curss = 0; /* No single shift. */ screen->rx8bit = 0; /* 7 bit. */ screen->tx8bit = 0; /* 7 bit. */ screen->mode = ANSInormal; /* Reset Tektronix alpha mode */ screen->TekGMode = 0; screen->TekAMode = 0; screen->cur_x = screen->cur_y = 0; screen->cur_X = screen->cur_Y = 0; scale_x = screen->width / 4096.0; scale_y = screen->height / 3128.0; screen->TekScale = scale_x; if (scale_y < scale_x) screen->TekScale = scale_y; if (bitmapicon) { screen->iconwindow = XCreateWindow (RootWindow, 0, 0, icon_width, icon_height, 0, 0, 0); XTileRelative(screen->iconwindow); XSetIconWindow(screen->window, screen->iconwindow); screen->iconmask = XStoreBitmap(icon_mask_width, icon_mask_height, icon_mask_bits); XSelectInput (screen->iconwindow, ExposeWindow); } if (reverse) XDefineCursor(screen->window, screen->rcurs); else XDefineCursor(screen->window, screen->curs); XStoreName (screen->window, (win_name != (char *) 0 ? win_name: (do_warp ? "login" : (slave ? "xtermslave" : (command_to_exec ? command_to_exec[0] : "xterm"))))); XSetResizeHint (screen->window, 2 * border, 2 * border, fInfo->width, fInfo->height); XMapWindow (screen->window); XSelectInput (screen->window, KeyPressed | ExposeWindow | EnterWindow | ButtonPressed | ButtonReleased | ExposeRegion | ExposeCopy); if (do_warp) XWarpMouse (screen->window, screen->width >> 1, screen->height >>1); screen->cur_col = screen->cur_row = 0; screen->max_col = screen->width / fInfo->width - 1; screen->top_marg = 0; screen->bot_marg = screen->max_row = screen->height/ fInfo->height - 1; screen->sc.row = screen->sc.col = screen->sc.flags = NULL; /* allocate memory for screen buffer */ screen->buf = (ScrnBuf) Allocate (screen->max_row + 1, screen->max_col +1); screen->do_wrap = NULL; screen->scrolls = screen->incopy = 0; screen->multiscroll = multiscroll; #ifdef JUMPSCROLL if (screen->jumpscroll = jumpscroll) term->flags &= ~SMOOTHSCROLL; #endif JUMPSCROLL /* display initial cursor */ CursorToggle (screen, 1); } spawn (display, pty, Xsocket, screen, getty, slave, passedPty) /* * Inits pty and tty and forks a login process. Returns fd for pty in pty. * Does not close fd Xsocket. * If getty, execs getty rather than csh and uses std fd's rather * than opening a pty/tty pair. * If slave, the pty named in passedPty is already open for use */ int *pty, Xsocket; Screen *screen; char *getty; /* if true execs /etc/getty - Xwindow */ int slave; char *passedPty; char *display; { int index1, tty; char pty_name; int discipline; unsigned lmode; struct tchars tc; struct ltchars ltc; struct sgttyb sg; char termcap [1024]; char newtc [1024]; char prog [256]; char numbuf[10]; char *ptr; char *index (), *strindex (); int i = 0; char **envnew; /* new environment */ struct passwd *getpwuid(); struct passwd *pw; char logindev[32]; char *TermName = "xterm"; int ldisc = 0; /* be real paranoid about getting some usable entry */ if (tgetent (termcap, TermName) == 1 || (TermName = "vt102", tgetent(termcap, TermName)) == 1 || (TermName = "ansi", tgetent(termcap, TermName)) == 1) { /* update termcap string */ /* first do columns */ if ((ptr = strindex (termcap, "co#")) == NULL){ fprintf(stderr,"Can't find co# in termcap string %s\n", TermName); exit (1); } strncpy (newtc, termcap, ptr - termcap + 3); newtc[ptr-termcap+3] = '\0'; sprintf (numbuf, "%d\0", screen->max_col + 1); strcat (newtc, numbuf); ptr = index (ptr, ':'); strcat (newtc, ptr); strncpy (termcap, newtc, sizeof(termcap)); /* now do lines */ if ((ptr = strindex (termcap, "li#")) == NULL) { fprintf(stderr,"Can't find li# in termcap string %s\n", TermName); exit (1); } strncpy (newtc, termcap, ptr - termcap + 3); newtc[ptr-termcap+3] = '\0'; sprintf (numbuf, "%d\0", screen->max_row + 1); strcat (newtc, numbuf); ptr = index (ptr, ':'); strcat (newtc, ptr); if (strcmp(TermName, "xterm") != 0) fprintf(stderr, "xterm: can't find xterm termcap entry, using %s instead!\n", TermName); } else fprintf(stderr,"xterm: can't find any usable termcap entry!\n"); if (getty) { strcpy(logindev,"/dev/"); strcat(logindev,getty); logindev [5] = 'p'; *pty = open (logindev, O_RDWR, 0); } else if (slave) { *pty = slave; ptydev[8] = ttydev[8] = passedPty[0]; ptydev[9] = ttydev[9] = passedPty[1]; } else { if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) { if (errno != ENXIO) Error(); else { no_dev_tty = 1; sg = d_sg; tc = d_tc; discipline = d_disipline; ltc = d_ltc; lmode = d_lmode; for (index1 = 0; index1 < 3; index1++) close (index1); } } else { /* get a copy of the current terminal's state */ if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) Error (); if (ioctl (tty, TIOCGETP, &sg) == -1) Error (); if (ioctl (tty, TIOCGETC, (int *)&tc) == -1) Error (); if (ioctl (tty, TIOCGETD, &discipline) == -1) Error (); if (ioctl (tty, TIOCGLTC, (int *)<c) == -1) Error (); if (ioctl (tty, TIOCLGET, &lmode) == -1) Error (); close (tty); /* close all std file descriptors */ for (index1 = 0; index1 < 3; index1++) close (index1); if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) Error (); if (ioctl (tty, TIOCNOTTY, 0) == -1) Error (); close (tty); } get_pty (pty, &pty_name); if (*pty != Xsocket + 1) { dup2 (*pty, Xsocket + 1); close (*pty); *pty = Xsocket + 1; } ttydev [9] = pty_name; if ((tty = open (ttydev, O_RDWR, 0)) < 0) Error (); /* change ownership of tty to real group and user id */ chown (ttydev, getuid (), tty_gid (getgid())); /* change protection of tty */ chmod (ttydev, 0620); if (tty != Xsocket + 2) { dup2 (tty, Xsocket + 2); close (tty); tty = Xsocket + 2; } /* set the new terminal's state to be the old one's with minor modifications for efficiency */ 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; if (ioctl (tty, TIOCSETP, &sg) == -1) Error (); if (ioctl (tty, TIOCSETC, (int *)&tc) == -1) Error (); if (ioctl (tty, TIOCSETD, &discipline) == -1) Error (); if (ioctl (tty, TIOCSLTC, (int *)<c) == -1) Error (); if (ioctl (tty, TIOCLSET, &lmode) == -1) Error (); #ifdef sun #ifdef TIOCCONS if (SunConsole) { int on = 1; if (ioctl (tty, TIOCCONS, &on) == -1) Error(); } #endif TIOCCONS #endif sun close (open ("/dev/null", O_RDWR, 0)); for (index1 = 0; index1 < 3; index1++) dup2 (tty, index1); } if (!slave && (screen->pid = fork ()) == -1) Error (); if (!slave && screen->pid == 0) { extern char **environ; int pgrp = getpid(); close (Xsocket); close (*pty); if (getty == NULL) close (tty); signal (SIGCHLD, SIG_DFL); signal (SIGHUP, SIG_IGN); /* copy the environment before Setenving */ while (environ [i] != NULL) i++; envnew = (char **) malloc (sizeof (char *) * (i + 4)); for (; i >= 0; i--) envnew [i] = environ [i]; environ = envnew; Setenv ("TERM=", TermName); Setenv ("TERMCAP=", newtc); /* put the display into the environment of the shell*/ if (display[0] != '\0') Setenv ("DISPLAY=", screen->display->displayname); pw = getpwuid (getuid ()); signal(SIGTERM, SIG_DFL); ioctl(0, TIOCSPGRP, &pgrp); setpgrp (0, 0); close(open(ttyname(0), O_WRONLY, 0)); setpgrp (0, pgrp); if (dologinflag) /* login */ utrelog(1, pw->pw_name, screen->display->displayname); setgid(getgid ()); setuid(getuid ()); if (command_to_exec) { execvp(command_to_exec[0], command_to_exec, 0); } signal(SIGHUP, SIG_IGN); if (getty) { ioctl (0, TIOCNOTTY, 0); execl ("/etc/getty", "+", "Xwindow", getty, 0); } signal(SIGHUP, SIG_DFL); if (*pw->pw_shell == '\0') pw->pw_shell = "/bin/sh"; /* make sure line discipline gets set */ ldisc = 0; ioctl(0, TIOCSETD, &ldisc); if (!strcmp(pw->pw_shell, "/bin/csh")) { ldisc = NTTYDISC; ioctl(0, TIOCSETD, &ldisc); } ptr = rindex(pw->pw_shell, '/'); if (ptr == NULL) ptr = pw->pw_shell; else ptr++; if (dologinflag) { prog[0] = '-'; strcpy(&prog[1], ptr); } else strcpy(prog, ptr); execlp (pw->pw_shell, prog, 0); fprintf (stderr,"Error: Could not exec %s!\n", pw->pw_shell); sleep(5); Cleanup(121); } close (tty); signal(SIGHUP,SIG_IGN); signal(SIGTTOU,SIG_IGN); /* so that TIOCSWINSZ doesn't block */ if ((tty = open (no_dev_tty ? "/dev/null" : "/dev/tty", O_RDWR, 0)) < 0) Error(); for (index1 = 0; index1 < 3; index1++) dup2 (tty, index1); if (tty > 2) close (tty); /* set ids to user's */ /* setgid (getgid ()); setuid (getuid ()); setregid (getegid (), getgid ()); setreuid (geteuid (), getuid ()); */ } static reapchild () { extern Terminal term; register long pgrp; union wait status; int pid; if (debug) printf ("Exiting\n"); pid = wait3 (&status, WNOHANG, NULL); if (!pid) return; if (pid != term.screen.pid) return; if (dologinflag) utrelog(0, "", ""); Cleanup(0); } consolepr(string) char *string; { extern int errno; extern char *sys_errlist[]; int oerrno; int f; oerrno = errno; f = open("/dev/console",O_WRONLY, 0); write(f, "xterm: ", 7); write(f, string, strlen(string)); write(f, ": ", 2); write(f, sys_errlist[oerrno],strlen(sys_errlist[oerrno])); write(f, "\n", 1); close(f); if ((f = open("/dev/tty", 2, 0)) >= 0) { ioctl(f, TIOCNOTTY, 0); close(f); } } #define TTYGRPNAME "tty" tty_gid(default_gid) int default_gid; { struct group *getgrnam(), *gr; int gid = default_gid; gr = getgrnam(TTYGRPNAME); if (gr != (struct group *) 0) gid = gr->gr_gid; endgrent(); return (gid); } utrelog(io, user, display) int io; char *user; char *display; { struct utmp ut; struct ttyent *ty; register int s; long slot; int ufd; char *colon; if (io == 1) { strncpy(ut.ut_line, &ttydev[5], sizeof ut.ut_line); colon = index(display, ':'); if (colon) *colon = '\0'; strncpy(ut.ut_host, display, sizeof ut.ut_host); if (colon) *colon = ':'; strncpy(ut.ut_name, user, sizeof ut.ut_name); (void) time(&ut.ut_time); } else { strcpy(ut.ut_line, ""); strcpy(ut.ut_name, ""); strcpy(ut.ut_host, ""); ut.ut_time = 0; chown(ttydev, 0, 0); chmod(ttydev, 0666); } setttyent(); slot = 0; s = 0; while ((ty = getttyent()) != NULL) { s++; if (strcmp(ty->ty_name, &ttydev[5]) == 0) { slot = s; break; } } endttyent(); if (slot > 0 && (ufd = open("/etc/utmp", O_WRONLY, 0)) >= 0) { if (lseek(ufd, slot * sizeof ut, 0) < 0L || write(ufd, (char *)&ut, sizeof ut) != sizeof ut) { close(ufd); return(-1); } close(ufd); } return(0); }