1: # include "monitor.h" 2: # include <ingres.h> 3: # include <version.h> 4: # include <opsys.h> 5: # include <pv.h> 6: # include <func.h> 7: # include <signal.h> 8: # include <pipes.h> 9: # include <setjmp.h> 10: # include <sccs.h> 11: 12: SCCSID(@(#)ttymon.c 8.1 12/31/84) 13: 14: 15: 16: # define ERRDELIM '~' 17: 18: /* 19: ** INTERACTIVE TERMINAL MONITOR 20: ** 21: ** The monitor gathers text from the standard input and performs 22: ** a variety of rudimentary editting functions. This program 23: ** is the main setup. Monitor() is then called, which does the 24: ** real work. 25: ** 26: ** variables: 27: ** Nodayfile -- zero prints all messages; positive one suppresses 28: ** dayfile and logout but not prompts; negative one 29: ** suppresses all printed material except results from \p. 30: ** Newline -- set when the last character in the query buffer 31: ** is a newline. 32: ** Prompt -- set when a prompt character is needed. 33: ** Autoclear -- set when the query buffer should be cleared before 34: ** putting another character in. 35: ** Nautoclear -- if set, suppresses the autoclear function 36: ** entirely. 37: ** 38: ** flags: 39: ** -M -- trace flag 40: ** -d -- suppress dayfile 41: ** -s -- suppress prompt (sets -d) 42: ** -a -- disable autoclear function 43: ** 44: ** The last three options can be set by stating "+x". 45: ** 46: ** Trace Flags: 47: ** 9 48: ** 11 (proc_err) 49: */ 50: 51: extern char *Usercode; 52: extern tm_mon(); 53: extern tm_init(); 54: extern tm_intr(); 55: short tTttymon[100]; 56: 57: struct fn_def TtyMonFn = 58: { 59: "MONITOR", 60: tm_mon, 61: tm_init, 62: tm_intr, 63: NULL, 64: 0, 65: tTttymon, 66: 100, 67: 'M', 68: 0 69: }; 70: 71: tm_init(argc, argv) 72: int argc; 73: char *argv[]; 74: { 75: register int ndx; 76: register char *p; 77: extern quit(); 78: extern int (*ExitFn)(); 79: extern int Equel; 80: char buff[100]; 81: extern char *getufield(); 82: extern jmp_buf CmReset; 83: extern char SysIdent[]; 84: 85: 86: /* insure that permissions are ok */ 87: setuid(getuid()); 88: # ifndef xB_UNIX 89: setgid(getgid()); 90: # endif 91: 92: setjmp(CmReset); 93: signal(SIGPIPE, quit); 94: 95: ExitFn = quit; 96: set_si_buf(); 97: 98: /* process arguments */ 99: if (!setflag(argv, 'd', 1)) 100: Nodayfile = 1; 101: if (!setflag(argv, 's', 1)) 102: Nodayfile = -1; 103: Nautoclear = !setflag(argv, 'a', 1); 104: 105: /* preinitialize macros */ 106: macinit(0, 0, 0); 107: macdefine("{pathname}", Pathname, 1); 108: 109: /* print the dayfile */ 110: if (Nodayfile >= 0) 111: { 112: time(buff); 113: printf("%s login\n%s", SysIdent, ctime(buff)); 114: } 115: if (Nodayfile == 0 && (Qryiop = fopen(ztack(ztack(Pathname, "/files/dayfile"), VERSION), "r")) != NULL) 116: { 117: while ((ndx = getc(Qryiop)) > 0) 118: putchar(ndx); 119: fclose(Qryiop); 120: } 121: 122: /* SET UP LOGICAL QUERY-BUFFER FILE */ 123: concat("/tmp/INGQ", Fileset, Qbname); 124: if ((Qryiop = fopen(Qbname, "w")) == NULL) 125: syserr("main: open(%s)", Qbname); 126: 127: /* GO TO IT ... */ 128: Prompt = Newline = TRUE; 129: Userdflag = Nodayfile; 130: Nodayfile = -1; 131: 132: /* run the system initialization file */ 133: setjmp(CmReset); 134: Phase++; 135: include(ztack(Pathname, "/files/startup")); 136: 137: /* find out what the user initialization file is */ 138: setjmp(CmReset); 139: if (getuser(Usercode, buff) == 0) 140: { 141: p = getufield(buff, 7); 142: if (*p != 0) 143: include(p); 144: } 145: getuser(0, 0); 146: 147: Nodayfile = Userdflag; 148: 149: /* 150: ** Get user input from terminal 151: ** 152: ** THIS CODE IS A CLUDGE!!! 153: ** 154: ** This code should return right after the setbuf call, 155: ** but it doesn't because we want the monitor to be in 156: ** control initially. The way the control module is 157: ** written, this will work. But we are definitely 158: ** cheating.... 159: */ 160: 161: Input = stdin; 162: setbuf(stdin, NULL); 163: monitor(FALSE); 164: quit(); 165: } 166: /* 167: ** CATCH SIGNALS 168: ** 169: ** clear out pipes and respond to user 170: ** 171: ** Uses trace flag 10 172: */ 173: 174: tm_intr(typ) 175: int typ; 176: { 177: register int i; 178: 179: if (typ != 2) 180: syserr("tm_intr: typ %d", typ); 181: 182: if (Xwaitpid == 0) 183: printf("\nInterrupt\n"); 184: 185: lseek(stdin->_file, 0L, 2); 186: Newline = Prompt = TRUE; 187: Nodayfile = Userdflag; 188: Oneline = FALSE; 189: Idepth = 0; 190: setbuf(stdin, NULL); 191: Input = stdin; 192: xwait(); 193: } 194: /* 195: ** PROCESS ERROR MESSAGE 196: ** 197: ** This routine takes an error message off of the pipe and 198: ** processes it for output to the terminal. This involves doing 199: ** a lookup in the .../files/error? files, where ? is the thous- 200: ** ands digit of the error number. The associated error message 201: ** then goes through parameter substitution and is printed. 202: ** 203: ** In the current version, the error message is just printed. 204: ** 205: ** We unquestionably cheat, by doing a longjmp rather than a 206: ** return here -- this is so that the synchronization works right. 207: ** 208: ** Trace Flags: 209: ** 30 210: */ 211: 212: proc_err(ppb, pc, pv) 213: pb_t *ppb; 214: int pc; 215: PARM pv[]; 216: { 217: register char c; 218: register char *p; 219: int i; 220: char buf[512]; 221: int err; 222: FILE *iop; 223: char *errfilen(); 224: extern char *mcall(); 225: bool fatal; 226: extern jmp_buf GoJmpBuf; 227: 228: if (pc <= 0 || pv[0].pv_type != PV_INT) 229: syserr("proc_err: pc %d pv0type %d", pc, pv[0].pv_type); 230: err = pv[0].pv_val.pv_int; 231: Error_id = err; 232: fatal = !bitset(PB_INFO, ppb->pb_stat); 233: 234: /* try calling the {catcherror} macro -- maybe not print */ 235: p = buf; 236: p += smove("{catcherror; ", p); 237: p += smove(iocv(err), p); 238: p += smove("}", p); 239: 240: p = mcall(buf); 241: if (sequal(p, "0")) 242: return (1); 243: 244: /* open the appropriate error file */ 245: p = errfilen(err / 1000); 246: 247: # ifdef xMTR3 248: if (tTf(30, -1)) 249: printf("proc_error: "); 250: if (tTf(30, 0)) 251: printf("%d, %s", err, p); 252: # endif 253: 254: if ((iop = fopen(p, "r")) == NULL) 255: syserr("proc_error: open(%s)", p); 256: 257: /* read in the code and check for correct */ 258: for (;;) 259: { 260: p = buf; 261: while ((c = getc(iop)) != '\t') 262: { 263: if (c <= 0) 264: { 265: /* no code exists, print the args */ 266: printf("%d:", err); 267: for (i = 0; i < pc; i++) 268: printf(" `%s'", pv[i].pv_val.pv_str); 269: printf("\n"); 270: fclose(iop); 271: if (fatal) 272: longjmp(CmReset, 1); 273: else 274: longjmp(GoJmpBuf, 1); 275: } 276: *p++ = c; 277: } 278: *p = 0; 279: i = atoi(buf); 280: 281: if (i != err) 282: { 283: while ((c = getc(iop)) != ERRDELIM) 284: if (c <= 0) 285: syserr("proc_error: format err %d", err); 286: getc(iop); /* throw out the newline */ 287: continue; 288: } 289: 290: /* got the correct line, print it doing parameter substitution */ 291: printf("%d: ", err); 292: c = '\n'; 293: for (;;) 294: { 295: c = getc(iop); 296: if (c <= 0 || c == ERRDELIM) 297: { 298: printf("\n"); 299: fclose(iop); 300: if (fatal) 301: longjmp(CmReset, 1); 302: else 303: longjmp(GoJmpBuf, 1); 304: } 305: if (c == '%') 306: { 307: c = getc(iop) - '0' + 1; 308: if (c >= pc) 309: syserr("proc_err: parm %d", c - 1); 310: switch (pv[c].pv_type) 311: { 312: case PV_STR: 313: for (p = pv[c].pv_val.pv_str; c = *p; p++) 314: xputchar(c); 315: continue; 316: 317: case PV_INT: 318: printf("%d", pv[c].pv_val.pv_int); 319: continue; 320: 321: default: 322: syserr("proc_err: arg %d type %d", c, pv[c].pv_type); 323: } 324: } 325: printf("%c", c); 326: } 327: } 328: } 329: /* 330: ** TM_MON -- "function to implement this module" 331: ** 332: ** Since we have cludged up this module to work, and hence 333: ** the init routine should never return, this routine just 334: ** syserr's. 335: */ 336: 337: tm_mon() 338: { 339: syserr("tm_mon"); 340: } 341: /* 342: ** ACC_INIT, PAGEFLUSH -- dummy access method routines 343: ** 344: ** Since the CM wants to do some basic access method functions, 345: ** we will let it. 346: */ 347: 348: acc_init() 349: { 350: } 351: 352: pageflush(x) 353: char *x; 354: { 355: return (0); 356: } 357: /* 358: ** CLOSECATALOG -- dummy catalog close routine. 359: ** 360: ** To keep from loading access methods. 361: */ 362: 363: closecatalog() 364: { 365: }