1: #include <X/mit-copyright.h> 2: 3: /* Copyright Massachusetts Institute of Technology 1984, 1985 */ 4: 5: /* ptyx.c */ 6: 7: #ifndef lint 8: static char *rcsid_ptyx_c = "$Header: main.c,v 10.44 86/05/16 10:17:20 jg Exp $"; 9: #endif lint 10: 11: #include <pwd.h> 12: #include <sgtty.h> 13: #include <sys/wait.h> 14: #include <sys/time.h> 15: #include <sys/resource.h> 16: #include <stdio.h> 17: #include <sys/file.h> 18: #include <errno.h> 19: #include <signal.h> 20: #include <strings.h> 21: #include <X/Xlib.h> 22: #include "ptyx.h" 23: #include <grp.h> 24: #include <ttyent.h> 25: #include <utmp.h> 26: 27: char *xterm_name; /* argv[0] */ 28: Terminal term; /* master data structure for client */ 29: int am_slave = 0; /* set to 1 if running as a slave process */ 30: int debug = 0; /* true causes error messages to be displayed */ 31: 32: static char *ptydev = "/dev/ptyxx"; 33: static char *ttydev = "/dev/ttyxx"; 34: 35: #include "../cursors/xterm.cursor" 36: #include "../cursors/xterm_mask.cursor" 37: #include "icon.ic" 38: #include "icon_mask.ic" 39: 40: static int reapchild (); 41: 42: static char **command_to_exec = (char **) NULL; 43: static char *win_name = (char *) 0; 44: 45: 46: static struct sgttyb d_sg = { 47: 0, 0, 0177, CKILL, EVENP|ODDP|ECHO|XTABS|CRMOD 48: }; 49: static struct tchars d_tc = { 50: CINTR, CQUIT, CSTART, 51: CSTOP, CEOF, CBRK, 52: }; 53: static struct ltchars d_ltc = { 54: CSUSP, CDSUSP, CRPRNT, 55: CFLUSH, CWERASE, CLNEXT 56: }; 57: static int d_disipline = NTTYDISC; 58: static int d_lmode = LCRTBS|LCRTERA|LCRTKIL|LCTLECH; 59: static int no_dev_tty = 0; 60: static int loginflag = 0; 61: static int dologinflag = 0; 62: #ifdef sun 63: #ifdef TIOCCONS 64: static int SunConsole = 0; 65: #endif TIOCCONS 66: #endif sun 67: 68: 69: main (argc, argv) 70: int argc; 71: char **argv; 72: { 73: int ind; 74: char *strind, *strind1, *strscan(); 75: char *fn = "vtsingle"; 76: char *fb = "vtbold"; 77: short fnflag = 0; /* True iff -fn option used */ 78: short fbflag = 0; /* True iff -fb option used */ 79: char *getty = NULL; 80: int reverse = 0, multiscroll = 0; 81: int border = 1, tek = 0; 82: int borderwidth = 2; 83: int bitmapicon = 0; 84: #ifdef JUMPSCROLL 85: int jumpscroll = 0; 86: #endif JUMPSCROLL 87: int slave = 0; /* if non-zero, run as slave */ 88: char passedPty[2]; /* name if pty if slave */ 89: char *fore_color; 90: char *back_color; 91: char *brdr_color; 92: char *curs_color; 93: char *mous_color; 94: char display[256]; 95: char *getenv(); 96: char *option; 97: char *geometry, *def = "=80x24+1+1"; 98: 99: xterm_name = argv[0]; 100: 101: display[0] = '\0'; 102: /* 103: * go get options out of default file 104: */ 105: if ((option = XGetDefault(argv[0], "BodyFont")) != NULL) { 106: fn = option; 107: fnflag = 1; 108: } 109: if ((option = XGetDefault(argv[0], "BoldFont")) != NULL) { 110: fb = option; 111: fbflag = 1; 112: } 113: if ((option = XGetDefault(argv[0], "InternalBorder")) != NULL) { 114: border = atoi (option); 115: } 116: if ((option = XGetDefault(argv[0], "BorderWidth")) != NULL) { 117: borderwidth = atoi (option); 118: } 119: 120: if ((option = XGetDefault(argv[0], "BitmapIcon")) != NULL) 121: if (strcmp (option, "on") == 0) 122: bitmapicon = 1; 123: 124: if ((option = XGetDefault(argv[0], "ReverseVideo")) != NULL) 125: if (strcmp (option, "on") == 0) 126: reverse = 1; 127: 128: if ((option = XGetDefault(argv[0], "Tektronix")) != NULL) 129: if (strcmp (option, "on") == 0) 130: tek = 1; 131: #ifdef JUMPSCROLL 132: if ((option = XGetDefault(argv[0], "JumpScroll")) != NULL) 133: if (strcmp (option, "on") == 0) 134: jumpscroll = 1; 135: #endif JUMPSCROLL 136: 137: fore_color = XGetDefault(argv[0], "Foreground"); 138: back_color = XGetDefault(argv[0], "Background"); 139: brdr_color = XGetDefault(argv[0], "Border"); 140: curs_color = XGetDefault(argv[0], "Cursor"); 141: mous_color = XGetDefault(argv[0], "Mouse"); 142: 143: /* parse command line */ 144: 145: for (ind = 1; ind < argc; ind++) { 146: if (argv [ind] [0] == '=') { 147: geometry = argv[ind]; 148: continue; 149: } 150: 151: strind = index (argv[ind], ':'); 152: if(strind != NULL) { 153: strncpy(display,argv[ind],sizeof(display)); 154: continue; 155: } 156: 157: 158: strind = (char *) index (argv [ind], '-'); 159: 160: if (strind == NULL) Syntax (); 161: 162: if (strcmp (argv [ind], "-L") == 0) { 163: char tt[32]; 164: int mode = O_RDWR|O_NDELAY; 165: loginflag = 1; 166: getty = argv[argc-1]; 167: argc -= 1; 168: strcpy(tt,"/dev/"); 169: strcat(tt, getty); 170: chown(tt, 0, 0); 171: chmod(tt, 0622); 172: if (open(tt, mode, 0) < 0) { 173: consolepr("open failed\n"); 174: } 175: signal(SIGHUP, SIG_IGN); 176: vhangup(); 177: setpgrp(0,0); 178: signal(SIGHUP, SIG_DFL); 179: open(tt, mode, 0); 180: close(0); 181: dup(1); 182: dup(0); 183: continue; 184: } 185: 186: if (strncmp (argv [ind], "-S", 2) == 0) { 187: sscanf(argv[ind] + 2, "%c%c%d", passedPty, passedPty+1, 188: &slave); 189: if (slave <= 0) Syntax(); 190: am_slave = 1; 191: continue; 192: } 193: 194: if (strcmp (argv [ind], "-e") == 0) { 195: if (++ind >= argc) Syntax (); 196: command_to_exec = argv + ind; 197: break; 198: } 199: 200: /* Switch to set up Tektronix-shaped (4096x3128 -> 512x390) window 201: * with characters sized to fit 39 lines of 85 characters each */ 202: 203: if (strcmp (argv [ind], "-t") == 0) { 204: tek = 1; 205: if (!fnflag) fn = "6x10"; 206: if (!fbflag) fb = "6x10"; 207: def = "85x39+1+1"; 208: continue; 209: } 210: 211: if (strcmp (argv [ind], "-fn") == 0) { 212: if (++ind >= argc) Syntax (); 213: fn = argv [ind]; 214: fnflag = 1; 215: continue; 216: } 217: 218: if (strcmp (argv [ind], "-fb") == 0) { 219: if (++ind >= argc) Syntax (); 220: fb = argv [ind]; 221: fbflag = 1; 222: continue; 223: } 224: 225: if (strcmp (argv [ind], "-fg") == 0) { 226: if (++ind >= argc) Syntax (); 227: fore_color = argv [ind]; 228: continue; 229: } 230: 231: if (strcmp (argv [ind], "-bg") == 0) { 232: if (++ind >= argc) Syntax (); 233: back_color = argv [ind]; 234: continue; 235: } 236: 237: if (strcmp (argv [ind], "-bd") == 0) { 238: if (++ind >= argc) Syntax (); 239: brdr_color = argv [ind]; 240: continue; 241: } 242: 243: if (strcmp (argv [ind], "-cr") == 0) { 244: if (++ind >= argc) Syntax (); 245: curs_color = argv [ind]; 246: continue; 247: } 248: 249: if (strcmp (argv [ind], "-ms") == 0) { 250: if (++ind >= argc) Syntax (); 251: mous_color = argv [ind]; 252: continue; 253: } 254: 255: if (strcmp (argv [ind], "-l") == 0) { 256: dologinflag = 1; 257: continue; 258: } 259: 260: if (strcmp (argv [ind], "-d") == 0) { 261: debug = 1; 262: continue; 263: } 264: 265: if (strcmp (argv [ind], "-b") == 0) { 266: if (++ind >= argc) Syntax (); 267: border = atoi (argv [ind]); 268: continue; 269: } 270: 271: if (strcmp (argv [ind], "-bw") == 0 || 272: strcmp (argv [ind], "-w") == 0) { 273: if (++ind >= argc) Syntax (); 274: borderwidth = atoi (argv [ind]); 275: continue; 276: } 277: 278: if (strcmp (argv [ind], "-rv") == 0 || 279: strcmp (argv [ind], "-r") == 0) { 280: reverse = 1; /* backwards from usual definition */ 281: continue; 282: } 283: 284: if (strcmp (argv [ind], "-s") == 0) { 285: multiscroll = 1; 286: continue; 287: } 288: 289: if (strcmp (argv [ind], "-i") == 0) { 290: bitmapicon = 1; 291: continue; 292: } 293: 294: #ifdef JUMPSCROLL 295: if (strcmp (argv [ind], "-j") == 0) { 296: jumpscroll = 1; 297: continue; 298: } 299: #endif JUMPSCROLL 300: 301: if (strcmp (argv [ind], "-n") == 0) { 302: if (++ind >= argc) Syntax (); 303: win_name = argv [ind]; 304: continue; 305: } 306: #ifdef sun 307: #ifdef TIOCCONS 308: if (strcmp (argv [ind], "-C") == 0) { 309: SunConsole = 1; 310: continue; 311: } 312: #endif TIOCCONS 313: #endif sun 314: 315: Syntax (); 316: } 317: 318: if (fnflag && !fbflag) fb = fn; 319: if (!fnflag && fbflag) fn = fb; 320: #ifdef JUMPSCROLL 321: if(tek) 322: jumpscroll = 0; 323: #endif JUMPSCROLL 324: Serve (display, fn, fb, geometry, def, getty, slave, passedPty, 325: border, borderwidth, tek, reverse, multiscroll, bitmapicon, 326: fore_color, back_color, brdr_color, curs_color, mous_color 327: #ifdef JUMPSCROLL 328: , jumpscroll 329: #endif JUMPSCROLL 330: ); 331: } 332: 333: Syntax () 334: { 335: static char *ustring[] = { 336: "Usage: xterm [-rv] [-fn normal_font] [-fb bold_font]\n", 337: "\t[=[width]x[height][[+-]xoff[[+-]yoff]]] [-bw bdr_width]\n", 338: "\t[-fg color] [-bg color] [-bd color] [-cr color] [-ms color]\n", 339: "\t[[[host]:vs]] [-d] [-s] [-t] [-i] [-j] [-e command_to_exec]\n", 340: "\t[-n window_name]\n\n", 341: "Fonts must be of fixed width and of same size;\n", 342: "If only one font is specified, it will be used for normal and bold text\n", 343: #ifdef JUMPSCROLL 344: "The -j option enables jump scroll\n", 345: #endif 346: "The -s option enables asynchronous scrolling\n", 347: "The -t option enables Tektronics 4010 emulation\n", 348: "The -i option enables bitmap icons\n", 349: "The -d option turns debugging on (error messages printed)\n", 350: "The -n option sets the window name\n", 351: "The -b option specifies the inner padding\n", 352: "Default is: xterm -fn vtsingle -fb vtbold =80x24 :0\n", 353: 0}; 354: char **us = ustring; 355: while (*us) fputs(*us++, stderr); 356: exit (1); 357: } 358: 359: char *strscan (search, what) 360: /* 361: Returns pointer to first char ins search which is also in what, else NULL. 362: */ 363: char *search, *what; 364: { 365: int i, len = strlen (what); 366: char c; 367: 368: while ((c = *(search++)) != NULL) 369: for (i = 0; i < len; i++) 370: if (c == what [i]) return (--search); 371: 372: return (NULL); 373: } 374: 375: Serve (disp, fn, fb, geometry, def, getty, slave, passedPty, 376: border, borderwidth, tek, reverse, multiscroll, bitmapicon, 377: fore_color, back_color, brdr_color, curs_color, mous_color 378: #ifdef JUMPSCROLL 379: , jumpscroll 380: #endif JUMPSCROLL 381: ) 382: char *disp; /* host of display to serve */ 383: char *fn; /* fontname of normal characters */ 384: char *fb; /* fontname of bold characters */ 385: char *getty; /* true iff child should be getty */ 386: int slave; /* true if should run as slave (contains file # of pty) */ 387: char *passedPty; /* name of pty to use if slave */ 388: char *geometry; /* user supplied geometry spec */ 389: char *def; /* default geometry spec */ 390: int border; /* inner border in pixels */ 391: int borderwidth; /* outer border in pixels */ 392: int tek; /* true ==> Tektronics emulation */ 393: int reverse; /* true ==> black background, white characters */ 394: int multiscroll; /* true ==> asynchronous full-screen scrolling */ 395: int bitmapicon; /* true ==> bitmap icons rather than text icon */ 396: #ifdef JUMPSCROLL 397: int jumpscroll; /* true ==> fast multi-line scrolling */ 398: #endif JUMPSCROLL 399: char *fore_color;/* text color */ 400: char *back_color;/* background color */ 401: char *brdr_color;/* border color */ 402: char *curs_color;/* text cursor color */ 403: char *mous_color;/* mouse cursor color */ 404: { 405: int pty; /* fildes for pty of client */ 406: XEvent reply; 407: XEvent *rep = & reply; 408: int aborted = 0; 409: int Select_mask, select_mask = 0; 410: int maxplus1; 411: short toggled = NULL; 412: Screen *screen = &term.screen; 413: int Xsocket; 414: int pty_mask, X_mask; 415: extern int errno; 416: int mode = 1; 417: #ifdef TIOCSWINSZ 418: struct winsize ws; 419: #endif 420: 421: signal (SIGCHLD, reapchild); 422: signal (SIGHUP, SIG_IGN); 423: 424: /* open a terminal for client */ 425: get_terminal (disp, &term, fn, fb, geometry, def, border, 426: borderwidth, (int)getty, slave, reverse, multiscroll, bitmapicon, 427: tek, fore_color, back_color, brdr_color, curs_color, mous_color 428: #ifdef JUMPSCROLL 429: , jumpscroll 430: #endif JUMPSCROLL 431: ); 432: 433: Xsocket = screen->display->fd; 434: 435: spawn (disp, &pty, Xsocket, screen, getty, slave, passedPty); 436: 437: if (slave) { /* Write window id so master end can read and use */ 438: write(pty, &screen->window, sizeof(screen->window)); 439: write(pty, "\n", 1); 440: } 441: 442: screen->respond = term.buf.fildes = pty; 443: 444: #ifdef TIOCSWINSZ 445: /* tell tty how big window is */ 446: ws.ws_row = screen->max_row + 1; 447: ws.ws_col = screen->max_col + 1; 448: ws.ws_xpixel = screen->width; 449: ws.ws_ypixel = screen->height; 450: ioctl (screen->respond, TIOCSWINSZ, &ws); 451: #endif 452: 453: /* Initialize Tektronix graphics mode parameters */ 454: TekErase (&term); 455: screen->TekEmu = tek; 456: screen->cur_x = screen->cur_y = 0; 457: screen->cur_X = screen->cur_Y = 0; 458: screen->TekGMode = 0; 459: screen->TekAMode = 0; 460: screen->TekPMode = 0; 461: 462: if (ioctl (pty, FIONBIO, &mode) == -1) Error (); 463: 464: pty_mask = 1 << pty; 465: X_mask = 1 << Xsocket; 466: Select_mask = pty_mask | X_mask; 467: maxplus1 = (pty < Xsocket) ? (1 + Xsocket) : (1 + pty); 468: 469: if (debug) printf ("debugging on\n"); 470: 471: while (1) 472: { 473: if (! aborted) 474: { 475: #ifdef JUMPSCROLL 476: if(screen->scroll_amt) 477: FlushScroll(screen); 478: #endif JUMPSCROLL 479: if (toggled) 480: { 481: CursorToggle (screen, toggled); 482: toggled = NULL; 483: } 484: 485: select_mask = Select_mask; 486: XFlush(); 487: while (select (maxplus1, &select_mask, NULL, NULL, 0) <= 0) { 488: if (errno != EINTR) Error(); 489: } 490: } 491: else select_mask = NULL; 492: 493: if (select_mask & pty_mask || aborted) 494: { 495: if (!toggled) 496: { 497: CursorToggle (screen, toggled); 498: toggled = 1; 499: } 500: do { 501: aborted = (*screen->mode)(&term); 502: } while (screen->display->qlen==0 && term.buf.cnt>0); 503: } 504: 505: if (select_mask & X_mask || aborted) 506: { 507: #ifdef JUMPSCROLL 508: if(screen->scroll_amt) 509: FlushScroll(screen); 510: #endif JUMPSCROLL 511: XPending (); 512: do { 513: XNextEvent (&reply); 514: 515: switch ((int)reply.type) 516: { 517: case KeyPressed: 518: Input (&term.keyboard, &term.screen, 519: (XKeyPressedEvent *)rep); 520: break; 521: 522: case ExposeWindow: 523: if (bitmapicon) { 524: if (((XExposeWindowEvent *)rep)->window 525: == screen->iconwindow) { 526: RefreshIcon(screen); 527: break; 528: } 529: } 530: toggled = 1; 531: if (ScreenResize (screen, 532: ((XExposeWindowEvent *)rep)->width, 533: ((XExposeWindowEvent *)rep)->height, 534: &term.flags) != -1) 535: { 536: TabReset (term.tabs); 537: XClear (screen->window); 538: ScrnRefresh (screen, 0, 0, 539: screen->max_row + 1, 540: screen->max_col + 1); 541: 542: if (screen->TekEmu) TekRefresh (&term); 543: } 544: break; 545: 546: case ExposeRegion: 547: if (((XExposeWindowEvent *)rep)->detail == 548: ExposeCopy && 549: screen->incopy <= 0) { 550: screen->incopy = 1; 551: if (screen->scrolls > 0) 552: screen->scrolls--; 553: } 554: if (HandleExposure (screen, &reply)) 555: toggled = 1; 556: break; 557: 558: case ExposeCopy: 559: if (screen->incopy <= 0 && screen->scrolls > 0) 560: screen->scrolls--; 561: if (screen->scrolls) 562: screen->incopy = -1; 563: else 564: screen->incopy = 0; 565: break; 566: 567: case ButtonPressed: 568: case ButtonReleased: 569: if (screen->incopy) 570: CopyWait (screen); 571: if (HandleButtons(&term,&reply,pty)) 572: toggled = 1; 573: break; 574: /* 575: * Enter window is being handled just to give xterm 576: * a kick in the pants when the mouse gets in the 577: * window in case it was swapped out. Of course, 578: * one might thrash... 579: */ 580: case EnterWindow: 581: break; 582: default: 583: break; 584: } 585: } while (screen->display->qlen > 0); 586: } 587: } 588: } 589: 590: RefreshIcon(screen) 591: register Screen *screen; 592: { 593: XBitmapBitsPut(screen->iconwindow, 0, 0, icon_width, icon_height, 594: icon_bits, screen->foreground, screen->background, 595: screen->iconmask, GXcopy, AllPlanes); 596: } 597: 598: get_pty (pty, pty_name) 599: /* 600: opens a pty, storing fildes in pty 601: and it's identifying character in pty_name. 602: */ 603: int *pty; 604: char *pty_name; 605: { 606: int devindex, letter = 0; 607: int fd; 608: extern errno; 609: 610: if (debug) { 611: fd = open ("xterm.debug.log", O_WRONLY | O_CREAT | O_TRUNC, 0666); 612: dup2 (fd, fileno (stderr)); 613: } 614: 615: while (letter < 4) { 616: ttydev [8] = ptydev [8] = "pqrs" [letter++]; 617: devindex = 0; 618: 619: while (devindex < 16) { 620: ptydev [9] = *pty_name = "0123456789abcdef" [devindex++]; 621: if ((*pty = open (ptydev, O_RDWR, 0)) < 0) { 622: if (debug) fprintf (stderr, "pty %d code %d\n", 623: devindex - 1, errno); 624: continue; 625: } 626: goto got_pty; 627: } 628: } 629: 630: fprintf (stderr,"Not enough available pty's\n"); 631: exit (11); 632: 633: got_pty: 634: if (debug) { 635: close (fileno (stderr)); 636: close (fd); 637: } 638: } 639: 640: get_terminal (disp, term, fn, fb, geometry, def, 641: border, borderwidth, do_warp, slave, reverse, multiscroll, bitmapicon, 642: tek, fore_color, back_color, brdr_color, curs_color, mous_color 643: #ifdef JUMPSCROLL 644: , jumpscroll 645: #endif JUMPSCROLL 646: ) 647: /* 648: * sets up X and initializes the terminal structure except for term.buf.fildes. 649: */ 650: char *disp; 651: register Terminal *term; 652: char *fn, *fb; 653: char *geometry, *def; 654: int border, borderwidth, do_warp, reverse, multiscroll, bitmapicon; 655: int slave; 656: int tek; 657: #ifdef JUMPSCROLL 658: int jumpscroll; 659: #endif JUMPSCROLL 660: char *fore_color, *back_color, *brdr_color, *curs_color, *mous_color; 661: { 662: int width, height; 663: FontInfo *fInfo; 664: register Keyboard *keyboard; 665: register Screen *screen; 666: Buffer *buf; 667: double scale_x, scale_y; 668: Color cdef; 669: int pixels[2]; 670: int try = 10; 671: OpaqueFrame twindow; 672: 673: keyboard = &term->keyboard; 674: screen = &term->screen; 675: buf = &term->buf; 676: 677: term->flags = WRAPAROUND|SMOOTHSCROLL; 678: 679: keyboard->flags = NULL; 680: keyboard->offset = 0; 681: 682: buf->cnt = 0; 683: buf->ptr = &buf->buf[0]; 684: 685: TabReset (term->tabs); 686: 687: while (try--) 688: if ((screen->display = XOpenDisplay(disp)) == NULL) { 689: if (loginflag == 0) { 690: fprintf(stderr,"No such display server %s\n", disp); 691: exit(1); 692: } 693: sleep (5); 694: continue; 695: } 696: else break; 697: 698: if (try <= 0) { 699: fprintf (stderr,"Can't connect to display server %s\n", 700: disp); 701: exit (111); 702: } 703: 704: screen->foreground = BlackPixel; 705: screen->background = WhitePixel; 706: screen->cursorcolor = BlackPixel; 707: screen->mousecolor = BlackPixel; 708: screen->xorplane = 1; 709: if (DisplayCells() > 2 && (fore_color || back_color || curs_color)) { 710: if (tek) { 711: if (curs_color && XParseColor(curs_color, &cdef)) { 712: if (XGetColorCells(0, 2, 1, &screen->xorplane, 713: pixels)) { 714: screen->background = pixels[0]; 715: screen->foreground = pixels[1]; 716: screen->cursorcolor = screen->background | 717: screen->xorplane; 718: cdef.pixel = screen->cursorcolor; 719: XStoreColor(&cdef); 720: } 721: } 722: else if (XGetColorCells(0, 1, 1, &screen->xorplane, 723: &screen->background)) { 724: screen->foreground = screen->background | 725: screen->xorplane; 726: screen->cursorcolor = screen->foreground; 727: } 728: if (screen->background != WhitePixel) { 729: if (back_color == NULL || 730: !XParseColor(back_color, &cdef)) { 731: cdef.pixel = WhitePixel; 732: XQueryColor(&cdef); 733: } 734: cdef.pixel = screen->background; 735: XStoreColor(&cdef); 736: if(screen->cursorcolor != screen->foreground) { 737: cdef.pixel = screen->foreground | 738: screen->xorplane; 739: XStoreColor(&cdef); 740: } 741: if (fore_color == NULL || 742: !XParseColor(fore_color, &cdef)) { 743: cdef.pixel = BlackPixel; 744: XQueryColor(&cdef); 745: } 746: cdef.pixel = screen->foreground; 747: XStoreColor(&cdef); 748: } 749: } 750: else { 751: if (fore_color && XParseColor(fore_color, &cdef) && 752: XGetHardwareColor(&cdef)) { 753: screen->foreground = 754: screen->foreground = cdef.pixel; 755: reverse = 0; 756: } 757: if (back_color && XParseColor(back_color, &cdef) && 758: XGetHardwareColor(&cdef)) { 759: screen->background = cdef.pixel; 760: reverse = 0; 761: } 762: if (curs_color && XParseColor(curs_color, &cdef) && 763: XGetHardwareColor(&cdef)) 764: screen->cursorcolor = cdef.pixel; 765: else 766: screen->cursorcolor = screen->foreground; 767: } 768: } 769: 770: screen->border = border; 771: screen->borderwidth = borderwidth; 772: screen->fnt_norm = screen->fnt_bold = NULL; 773: 774: if ((fInfo = XOpenFont(fn)) == NULL) { 775: fprintf(stderr, "%s: Could not open font %s!\n", 776: xterm_name, fn); 777: exit(1); 778: } 779: if (fn) screen->fnt_norm = fInfo->id; 780: if (fb) screen->fnt_bold = XOpenFont(fb)->id; 781: screen->f_width = fInfo->width; 782: screen->f_height = fInfo->height; 783: 784: if (brdr_color && DisplayCells() > 2 && 785: XParseColor(brdr_color, &cdef) && XGetHardwareColor(&cdef)) 786: screen->bordertile = XMakeTile(cdef.pixel); 787: else 788: screen->bordertile = BlackPixmap; 789: 790: screen->cursor = XStoreBitmap(xterm_width, xterm_height, xterm_bits); 791: screen->mask = XStoreBitmap(xterm_mask_width, xterm_mask_height, 792: xterm_mask_bits); 793: if (mous_color && DisplayCells() > 2 && 794: XParseColor(mous_color, &cdef) && XGetHardwareColor(&cdef)) 795: screen->mousecolor = cdef.pixel; 796: else 797: screen->mousecolor = screen->cursorcolor; 798: screen->curs = XStoreCursor(screen->cursor, screen->mask, 5, 8, 799: screen->mousecolor, screen->background, GXcopy); 800: screen->rcurs = XStoreCursor(screen->cursor, screen->mask, 5, 8, 801: screen->background, screen->mousecolor, GXcopy); 802: 803: if (reverse) { /* reverse is black background with white chars */ 804: term->flags |= REVERSE_VIDEO; 805: screen->cursorcolor = screen->background; 806: screen->background = screen->foreground; 807: screen->foreground = screen->cursorcolor; 808: if (screen->bordertile == BlackPixmap) 809: screen->bordertile = WhitePixmap; 810: } 811: screen->bgndtile = XMakeTile(screen->background); 812: 813: twindow.bdrwidth = screen->borderwidth; 814: twindow.border = screen->bordertile; 815: twindow.background = screen->bgndtile; 816: 817: screen->window = XCreateTerm ("Terminal Emulator", xterm_name, 818: geometry, def, &twindow, 12, 8, 819: screen->border * 2, screen->border * 2, 820: &width, &height, 821: fInfo, fInfo->width, fInfo->height); 822: 823: screen->width = twindow.width - border * 2; 824: screen->height = twindow.height - border * 2; 825: 826: /* Reset variables used by ANSI emulation. */ 827: 828: screen->ansi.a_type = 0; /* New sequence. */ 829: screen->ansi.a_pintro = 0; /* New sequence. */ 830: screen->ansi.a_final = 0; /* New sequence. */ 831: screen->gsets[0] = 'B'; /* ASCII_G */ 832: screen->gsets[1] = 'B'; 833: screen->gsets[2] = '<'; /* DEC supplemental. */ 834: screen->gsets[3] = '<'; 835: screen->curgl = 0; /* G0 => GL. */ 836: screen->curgr = 2; /* G2 => GR. */ 837: screen->curss = 0; /* No single shift. */ 838: screen->rx8bit = 0; /* 7 bit. */ 839: screen->tx8bit = 0; /* 7 bit. */ 840: screen->mode = ANSInormal; 841: 842: /* Reset Tektronix alpha mode */ 843: screen->TekGMode = 0; 844: screen->TekAMode = 0; 845: screen->cur_x = screen->cur_y = 0; 846: screen->cur_X = screen->cur_Y = 0; 847: 848: scale_x = screen->width / 4096.0; 849: scale_y = screen->height / 3128.0; 850: screen->TekScale = scale_x; 851: if (scale_y < scale_x) screen->TekScale = scale_y; 852: 853: if (bitmapicon) { 854: screen->iconwindow = XCreateWindow (RootWindow, 855: 0, 0, icon_width, icon_height, 0, 0, 0); 856: 857: XTileRelative(screen->iconwindow); 858: 859: XSetIconWindow(screen->window, screen->iconwindow); 860: 861: screen->iconmask = XStoreBitmap(icon_mask_width, 862: icon_mask_height, icon_mask_bits); 863: 864: XSelectInput (screen->iconwindow, ExposeWindow); 865: } 866: 867: if (reverse) 868: XDefineCursor(screen->window, screen->rcurs); 869: else XDefineCursor(screen->window, screen->curs); 870: 871: XStoreName (screen->window, (win_name != (char *) 0 ? win_name: 872: (do_warp ? "login" : 873: (slave ? "xtermslave" : 874: (command_to_exec ? command_to_exec[0] : "xterm"))))); 875: 876: XSetResizeHint (screen->window, 877: 2 * border, 2 * border, fInfo->width, fInfo->height); 878: 879: XMapWindow (screen->window); 880: 881: XSelectInput (screen->window, KeyPressed | ExposeWindow | EnterWindow | 882: ButtonPressed | ButtonReleased | ExposeRegion | ExposeCopy); 883: 884: 885: if (do_warp) 886: XWarpMouse (screen->window, 887: screen->width >> 1, screen->height >>1); 888: 889: screen->cur_col = screen->cur_row = 0; 890: screen->max_col = screen->width / fInfo->width - 1; 891: screen->top_marg = 0; 892: screen->bot_marg = screen->max_row = screen->height/ fInfo->height - 1; 893: 894: screen->sc.row = screen->sc.col = screen->sc.flags = NULL; 895: 896: 897: /* allocate memory for screen buffer */ 898: screen->buf = (ScrnBuf) Allocate (screen->max_row + 1, 899: screen->max_col +1); 900: 901: screen->do_wrap = NULL; 902: screen->scrolls = screen->incopy = 0; 903: screen->multiscroll = multiscroll; 904: #ifdef JUMPSCROLL 905: if (screen->jumpscroll = jumpscroll) 906: term->flags &= ~SMOOTHSCROLL; 907: #endif JUMPSCROLL 908: 909: 910: /* display initial cursor */ 911: CursorToggle (screen, 1); 912: } 913: 914: spawn (display, pty, Xsocket, screen, getty, slave, passedPty) 915: /* 916: * Inits pty and tty and forks a login process. Returns fd for pty in pty. 917: * Does not close fd Xsocket. 918: * If getty, execs getty rather than csh and uses std fd's rather 919: * than opening a pty/tty pair. 920: * If slave, the pty named in passedPty is already open for use 921: */ 922: int *pty, Xsocket; 923: Screen *screen; 924: char *getty; /* if true execs /etc/getty - Xwindow */ 925: int slave; 926: char *passedPty; 927: char *display; 928: { 929: int index1, tty; 930: char pty_name; 931: int discipline; 932: unsigned lmode; 933: struct tchars tc; 934: struct ltchars ltc; 935: struct sgttyb sg; 936: 937: char termcap [1024]; 938: char newtc [1024]; 939: char prog [256]; 940: char numbuf[10]; 941: char *ptr; 942: char *index (), *strindex (); 943: int i = 0; 944: char **envnew; /* new environment */ 945: struct passwd *getpwuid(); 946: struct passwd *pw; 947: char logindev[32]; 948: char *TermName = "xterm"; 949: int ldisc = 0; 950: 951: /* be real paranoid about getting some usable entry */ 952: if (tgetent (termcap, TermName) == 1 953: || (TermName = "vt102", tgetent(termcap, TermName)) == 1 954: || (TermName = "ansi", tgetent(termcap, TermName)) == 1) { 955: /* update termcap string */ 956: /* first do columns */ 957: if ((ptr = strindex (termcap, "co#")) == NULL){ 958: fprintf(stderr,"Can't find co# in termcap string %s\n", 959: TermName); 960: exit (1); 961: } 962: strncpy (newtc, termcap, ptr - termcap + 3); 963: newtc[ptr-termcap+3] = '\0'; 964: sprintf (numbuf, "%d\0", screen->max_col + 1); 965: strcat (newtc, numbuf); 966: ptr = index (ptr, ':'); 967: strcat (newtc, ptr); 968: strncpy (termcap, newtc, sizeof(termcap)); 969: /* now do lines */ 970: if ((ptr = strindex (termcap, "li#")) == NULL) { 971: fprintf(stderr,"Can't find li# in termcap string %s\n", 972: TermName); 973: exit (1); 974: } 975: strncpy (newtc, termcap, ptr - termcap + 3); 976: newtc[ptr-termcap+3] = '\0'; 977: sprintf (numbuf, "%d\0", screen->max_row + 1); 978: strcat (newtc, numbuf); 979: ptr = index (ptr, ':'); 980: strcat (newtc, ptr); 981: if (strcmp(TermName, "xterm") != 0) 982: fprintf(stderr, 983: "xterm: can't find xterm termcap entry, using %s instead!\n", TermName); 984: } 985: else fprintf(stderr,"xterm: can't find any usable termcap entry!\n"); 986: 987: if (getty) { 988: strcpy(logindev,"/dev/"); 989: strcat(logindev,getty); 990: logindev [5] = 'p'; 991: *pty = open (logindev, O_RDWR, 0); 992: } 993: else if (slave) { 994: *pty = slave; 995: ptydev[8] = ttydev[8] = passedPty[0]; 996: ptydev[9] = ttydev[9] = passedPty[1]; 997: } 998: else { 999: if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) { 1000: if (errno != ENXIO) Error(); 1001: else { 1002: no_dev_tty = 1; 1003: sg = d_sg; 1004: tc = d_tc; 1005: discipline = d_disipline; 1006: ltc = d_ltc; 1007: lmode = d_lmode; 1008: for (index1 = 0; index1 < 3; index1++) 1009: close (index1); 1010: } 1011: } 1012: else { 1013: /* get a copy of the current terminal's state */ 1014: 1015: if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) Error (); 1016: 1017: if (ioctl (tty, TIOCGETP, &sg) == -1) Error (); 1018: if (ioctl (tty, TIOCGETC, (int *)&tc) == -1) Error (); 1019: if (ioctl (tty, TIOCGETD, &discipline) == -1) Error (); 1020: if (ioctl (tty, TIOCGLTC, (int *)<c) == -1) Error (); 1021: if (ioctl (tty, TIOCLGET, &lmode) == -1) Error (); 1022: 1023: close (tty); 1024: 1025: /* close all std file descriptors */ 1026: for (index1 = 0; index1 < 3; index1++) 1027: close (index1); 1028: if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) Error (); 1029: 1030: if (ioctl (tty, TIOCNOTTY, 0) == -1) Error (); 1031: close (tty); 1032: } 1033: 1034: get_pty (pty, &pty_name); 1035: 1036: if (*pty != Xsocket + 1) { 1037: dup2 (*pty, Xsocket + 1); 1038: close (*pty); 1039: *pty = Xsocket + 1; 1040: } 1041: 1042: ttydev [9] = pty_name; 1043: if ((tty = open (ttydev, O_RDWR, 0)) < 0) Error (); 1044: 1045: /* change ownership of tty to real group and user id */ 1046: chown (ttydev, getuid (), tty_gid (getgid())); 1047: 1048: /* change protection of tty */ 1049: chmod (ttydev, 0620); 1050: 1051: if (tty != Xsocket + 2) { 1052: dup2 (tty, Xsocket + 2); 1053: close (tty); 1054: tty = Xsocket + 2; 1055: } 1056: 1057: /* set the new terminal's state to be the old one's 1058: with minor modifications for efficiency */ 1059: 1060: sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW); 1061: sg.sg_flags |= ECHO | CRMOD; 1062: /* make sure speed is set on pty so that editors work right*/ 1063: sg.sg_ispeed = B9600; 1064: sg.sg_ospeed = B9600; 1065: 1066: if (ioctl (tty, TIOCSETP, &sg) == -1) Error (); 1067: if (ioctl (tty, TIOCSETC, (int *)&tc) == -1) Error (); 1068: if (ioctl (tty, TIOCSETD, &discipline) == -1) Error (); 1069: if (ioctl (tty, TIOCSLTC, (int *)<c) == -1) Error (); 1070: if (ioctl (tty, TIOCLSET, &lmode) == -1) Error (); 1071: #ifdef sun 1072: #ifdef TIOCCONS 1073: if (SunConsole) { 1074: int on = 1; 1075: if (ioctl (tty, TIOCCONS, &on) == -1) Error(); 1076: } 1077: #endif TIOCCONS 1078: #endif sun 1079: 1080: close (open ("/dev/null", O_RDWR, 0)); 1081: 1082: for (index1 = 0; index1 < 3; index1++) 1083: dup2 (tty, index1); 1084: } 1085: 1086: if (!slave && (screen->pid = fork ()) == -1) Error (); 1087: 1088: if (!slave && screen->pid == 0) { 1089: extern char **environ; 1090: int pgrp = getpid(); 1091: 1092: close (Xsocket); 1093: close (*pty); 1094: 1095: if (getty == NULL) close (tty); 1096: 1097: signal (SIGCHLD, SIG_DFL); 1098: signal (SIGHUP, SIG_IGN); 1099: 1100: /* copy the environment before Setenving */ 1101: while (environ [i] != NULL) i++; 1102: envnew = (char **) malloc (sizeof (char *) * (i + 4)); 1103: for (; i >= 0; i--) envnew [i] = environ [i]; 1104: environ = envnew; 1105: Setenv ("TERM=", TermName); 1106: Setenv ("TERMCAP=", newtc); 1107: /* put the display into the environment of the shell*/ 1108: if (display[0] != '\0') 1109: Setenv ("DISPLAY=", screen->display->displayname); 1110: 1111: pw = getpwuid (getuid ()); 1112: signal(SIGTERM, SIG_DFL); 1113: ioctl(0, TIOCSPGRP, &pgrp); 1114: setpgrp (0, 0); 1115: close(open(ttyname(0), O_WRONLY, 0)); 1116: setpgrp (0, pgrp); 1117: if (dologinflag) /* login */ 1118: utrelog(1, pw->pw_name, screen->display->displayname); 1119: 1120: setgid(getgid ()); 1121: setuid(getuid ()); 1122: 1123: if (command_to_exec) { 1124: execvp(command_to_exec[0], command_to_exec, 0); 1125: } 1126: signal(SIGHUP, SIG_IGN); 1127: if (getty) { 1128: ioctl (0, TIOCNOTTY, 0); 1129: execl ("/etc/getty", "+", "Xwindow", getty, 0); 1130: } 1131: signal(SIGHUP, SIG_DFL); 1132: 1133: if (*pw->pw_shell == '\0') pw->pw_shell = "/bin/sh"; 1134: 1135: /* make sure line discipline gets set */ 1136: ldisc = 0; 1137: ioctl(0, TIOCSETD, &ldisc); 1138: if (!strcmp(pw->pw_shell, "/bin/csh")) { 1139: ldisc = NTTYDISC; 1140: ioctl(0, TIOCSETD, &ldisc); 1141: } 1142: 1143: ptr = rindex(pw->pw_shell, '/'); 1144: if (ptr == NULL) 1145: ptr = pw->pw_shell; 1146: else 1147: ptr++; 1148: if (dologinflag) { 1149: prog[0] = '-'; 1150: strcpy(&prog[1], ptr); 1151: } else 1152: strcpy(prog, ptr); 1153: execlp (pw->pw_shell, prog, 0); 1154: fprintf (stderr,"Error: Could not exec %s!\n", pw->pw_shell); 1155: sleep(5); 1156: Cleanup(121); 1157: } 1158: 1159: close (tty); 1160: signal(SIGHUP,SIG_IGN); 1161: signal(SIGTTOU,SIG_IGN); /* so that TIOCSWINSZ doesn't block */ 1162: 1163: if ((tty = open (no_dev_tty ? "/dev/null" : "/dev/tty", 1164: O_RDWR, 0)) < 0) Error(); 1165: for (index1 = 0; index1 < 3; index1++) 1166: dup2 (tty, index1); 1167: if (tty > 2) close (tty); 1168: 1169: /* set ids to user's */ 1170: /* 1171: setgid (getgid ()); 1172: setuid (getuid ()); 1173: setregid (getegid (), getgid ()); 1174: setreuid (geteuid (), getuid ()); 1175: */ 1176: 1177: } 1178: 1179: 1180: static reapchild () 1181: { 1182: extern Terminal term; 1183: register long pgrp; 1184: union wait status; 1185: int pid; 1186: 1187: if (debug) printf ("Exiting\n"); 1188: pid = wait3 (&status, WNOHANG, NULL); 1189: if (!pid) return; 1190: if (pid != term.screen.pid) return; 1191: 1192: if (dologinflag) 1193: utrelog(0, "", ""); 1194: Cleanup(0); 1195: } 1196: 1197: consolepr(string) 1198: char *string; 1199: { 1200: extern int errno; 1201: extern char *sys_errlist[]; 1202: int oerrno; 1203: int f; 1204: oerrno = errno; 1205: f = open("/dev/console",O_WRONLY, 0); 1206: write(f, "xterm: ", 7); 1207: write(f, string, strlen(string)); 1208: write(f, ": ", 2); 1209: write(f, sys_errlist[oerrno],strlen(sys_errlist[oerrno])); 1210: write(f, "\n", 1); 1211: close(f); 1212: if ((f = open("/dev/tty", 2, 0)) >= 0) { 1213: ioctl(f, TIOCNOTTY, 0); 1214: close(f); 1215: } 1216: } 1217: 1218: #define TTYGRPNAME "tty" 1219: 1220: tty_gid(default_gid) 1221: int default_gid; 1222: { 1223: struct group *getgrnam(), *gr; 1224: int gid = default_gid; 1225: 1226: gr = getgrnam(TTYGRPNAME); 1227: if (gr != (struct group *) 0) 1228: gid = gr->gr_gid; 1229: 1230: endgrent(); 1231: 1232: return (gid); 1233: } 1234: 1235: utrelog(io, user, display) 1236: int io; 1237: char *user; 1238: char *display; 1239: { 1240: struct utmp ut; 1241: struct ttyent *ty; 1242: register int s; 1243: long slot; 1244: int ufd; 1245: char *colon; 1246: 1247: if (io == 1) { 1248: strncpy(ut.ut_line, &ttydev[5], sizeof ut.ut_line); 1249: colon = index(display, ':'); 1250: if (colon) 1251: *colon = '\0'; 1252: strncpy(ut.ut_host, display, sizeof ut.ut_host); 1253: if (colon) 1254: *colon = ':'; 1255: strncpy(ut.ut_name, user, sizeof ut.ut_name); 1256: (void) time(&ut.ut_time); 1257: } 1258: else { 1259: strcpy(ut.ut_line, ""); 1260: strcpy(ut.ut_name, ""); 1261: strcpy(ut.ut_host, ""); 1262: ut.ut_time = 0; 1263: chown(ttydev, 0, 0); 1264: chmod(ttydev, 0666); 1265: } 1266: 1267: setttyent(); 1268: slot = 0; 1269: s = 0; 1270: while ((ty = getttyent()) != NULL) { 1271: s++; 1272: if (strcmp(ty->ty_name, &ttydev[5]) == 0) { 1273: slot = s; 1274: break; 1275: } 1276: } 1277: endttyent(); 1278: if (slot > 0 && (ufd = open("/etc/utmp", O_WRONLY, 0)) >= 0) { 1279: if (lseek(ufd, slot * sizeof ut, 0) < 0L || 1280: write(ufd, (char *)&ut, sizeof ut) != sizeof ut) { 1281: close(ufd); 1282: return(-1); 1283: } 1284: close(ufd); 1285: } 1286: return(0); 1287: }