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