1: #ifndef lint 2: static char *rcsid_Xttylib_c = "$Header: Xttylib.c,v 10.6 86/02/01 15:42:48 tony Rel $"; 3: #endif 4: /* This version has a single reverse-video argument instead of colors. It 5: really only works well on monochrome displays */ 6: 7: /* Library of routines to create a terminal emulator window 8: * 9: * Routines in this library are: 10: * 11: * CreateTTYWindow Creates a new instance of a terminal window 12: * DestroyTTYWindow Destroys a terminal window 13: * TTYPutString Puts a string in a terminal window 14: * TTYPutChar Puts a character in a terminal window 15: * TTYPrintf Does a printf in a terminal window 16: * TTYGetString Gets s string from a terminal window 17: * TTYGetChar Gets a char from a terminal window 18: * SetStdout Flushes stdout and assigns it to a window 19: * ResetStdout Resets stdout to its inital value 20: * 21: * The terminal window created responds to exactly the same character 22: * sequences as xterm (not surprising). Creating a window automatically 23: * maps it 24: * 25: * These routines pass around a pointer to a TTYWindow: 26: * 27: * typedef struct _TTYWindow { 28: * Window w; The window id 29: * int pid; The pid of the subprocess xterm 30: * short file; The file id of the tty to read/write characters to/from 31: * } TTYWindow; 32: * 33: * 34: * The SetStdout routine is highly useful in conjunction with curses 35: * since curses always writes to stdout. 36: */ 37: 38: #include <X/Xlib.h> 39: #include <stdio.h> 40: #include <signal.h> 41: #include <sys/file.h> 42: #include <sys/ioctl.h> 43: #include <sgtty.h> 44: #include "Xtty.h" 45: 46: TTYWindow *CreateTTYWindow(cols, lines, x, y, normFont, boldFont, bwidth, 47: reverse) 48: int lines, cols, x, y, bwidth, reverse; 49: char *normFont, *boldFont; 50: { 51: TTYWindow *t; 52: 53: if ((t = (TTYWindow *) malloc(sizeof(TTYWindow))) == 54: NULL) return NULL; 55: 56: if (Start_slave_xterm(t, lines, cols, x, y, normFont, boldFont, 57: bwidth, reverse) == 0) { 58: free(t); 59: fprintf(stderr, "Couldn't start slave xterm\n"); 60: return NULL; 61: } 62: 63: return t; 64: } 65: 66: int ttyMasterPty; 67: int keepMasterOpen = 0; 68: 69: int Start_slave_xterm(t, lines, cols, x, y, normFont, boldFont, bwidth, 70: reverse) 71: TTYWindow *t; 72: int lines, cols, x, y, bwidth, reverse; 73: char *normFont, *boldFont; 74: { 75: #define BUFSIZE 20 76: 77: char ttyName[BUFSIZE]; 78: char Sbuf[BUFSIZE], sizeBuf[BUFSIZE], wdBuf[BUFSIZE], 79: inputBuffer[BUFSIZE]; 80: int bytesRead, len; 81: 82: if (boldFont == NULL) boldFont = normFont; 83: 84: ttyMasterPty = GetPty(ttyName); 85: if (ttyMasterPty == -1) return 0; 86: 87: if ((t->pid = vfork()) < 0) return 0; 88: 89: if (t->pid == 0) { 90: sprintf(Sbuf, "-S%c%c%d", ttyName[8], ttyName[9], ttyMasterPty); 91: sprintf(sizeBuf, "=%dx%d+%d+%d", cols, lines, x, y); 92: sprintf(wdBuf, "%d", bwidth); 93: 94: execlp("xterm", "xterm", Sbuf, "-fn", normFont, "-fb", boldFont, 95: sizeBuf, "-bw", wdBuf, reverse ? "-rv" : (char *) 0, 96: (char *) 0); 97: 98: } else { 99: if (!keepMasterOpen) close(ttyMasterPty); 100: 101: /* Open the slave end of the pty */ 102: 103: ttyName[5] = 't'; /* Change /dev/pty?? to /dev/tty?? */ 104: 105: t->file = open(ttyName, O_RDWR, 0777); 106: 107: if (t->file < 0) { 108: /* Couldn't open the tty--better get rid of the process */ 109: kill (t->pid, SIGINT); 110: return 0; 111: } 112: 113: /* Read the windowid from the pty */ 114: 115: len = 0; 116: while ((bytesRead = read(t->file, inputBuffer + len, 117: sizeof(Window) - len)) > 0) len += bytesRead; 118: 119: /* Flush the rest of the garbahge */ 120: 121: ioctl(t->file, TIOCFLUSH, (struct sgttyb *) NULL); 122: 123: /* the data consists of a binary window ID */ 124: 125: t->w = *(Window *) inputBuffer; 126: } 127: return 1; 128: #undef BUFSIZE 129: } 130: 131: int GetPty(name) 132: char *name; 133: { 134: register int devindex, letter; 135: int fd; 136: 137: strcpy(name, "/dev/ptyp0"); 138: 139: for (letter = 0; letter < 4; letter++) { 140: name[8] = "pqrs"[letter]; 141: 142: for (devindex = 0; devindex < 16; devindex++) { 143: name[9] = "0123456789abcdef"[devindex]; 144: if ((fd = open (name, O_RDWR)) >= 0) return fd; 145: } 146: } 147: 148: return -1; 149: } 150: 151: DestroyTTYWindow(t) 152: TTYWindow *t; 153: { 154: /* close the tty; this should cause the xterm to terminate with an I/O error */ 155: close(t->file); 156: free(t); 157: } 158: 159: TTYPutString(t, str) 160: TTYWindow *t; 161: char *str; 162: { 163: write(t->file, str, strlen(str)); 164: } 165: 166: TTYPutChar(t, ch) 167: TTYWindow *t; 168: char ch; 169: { 170: write(t->file, &ch, 1); 171: } 172: 173: TTYPrintf(t, format, args) 174: TTYWindow *t; 175: char *format; 176: { 177: #define TTY_BUFSIZE 2048 178: char buffer[TTY_BUFSIZE+1]; 179: struct _iobuf _strbuf; 180: 181: _strbuf._flag = _IOWRT+_IOSTRG; 182: _strbuf._ptr = buffer; 183: _strbuf._cnt = TTY_BUFSIZE; 184: _doprnt(format, &args, &_strbuf); 185: _strbuf._cnt++; /* Be sure there's room for the \0 */ 186: putc('\0', &_strbuf); 187: TTYPutString(t, buffer); 188: #undef TTY_BUFSIZE 189: } 190: 191: static initial_stdout = -1; 192: 193: SetStdout(t) 194: TTYWindow *t; 195: { 196: if (initial_stdout == -1) initial_stdout = stdout->_file; 197: fflush(stdout); 198: stdout->_file = t->file; 199: } 200: 201: ResetStdout() 202: { 203: fflush(stdout); 204: stdout->_file = initial_stdout; 205: initial_stdout = -1; 206: } 207: 208: #define CMASK 0377 209: 210: int TTYGetChar(t) 211: TTYWindow *t; 212: { 213: char c; 214: 215: if (read(t->file, &c, 1) > 0) 216: return (c & CMASK); 217: else return (EOF); 218: } 219: 220: char *TTYGetString(t, str, n) 221: register TTYWindow *t; 222: char *str; 223: register int n; 224: { 225: register char *cs; 226: 227: cs = str; 228: while (--n > 0 && read(t->file, cs, 1) > 0) { 229: if (*cs++ == '\n') break; 230: } 231: 232: if (cs == str) return NULL; 233: 234: *cs = '\0'; 235: return str; 236: 237: }