|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.