|
|
1.1 root 1: # include <stdio.h>
2: # include <signal.h>
3: # include "ctlmod.h"
4: # include "pipes.h"
5: # include <resp.h>
6: # include <ingres.h>
7: # include <aux.h>
8: # include <sccs.h>
9:
10: SCCSID(%W% %G%)
11:
12: /*
13: ** MAIN -- initialize control module
14: **
15: ** Called only once, this routine sets everything up.
16: **
17: ** The format of the argv is as follows:
18: ** argv[0] -- pathname
19: ** argv[1] -- file descriptor for input pipe or'ed with
20: ** 0100 to make it printable in a 'ps'.
21: ** argv[2] -- Fileset
22: ** argv[3] -- Usercode
23: ** argv[4] -- Database
24: ** argv[5] -- Pathname
25: **
26: ** Parameters:
27: ** argc, argv -- as usual
28: **
29: ** Returns:
30: ** none
31: **
32: ** Side Effects:
33: ** Many; see code.
34: ** Proc_name is set to the working process name.
35: ** Fileset, Database, Usercode -- set from argv.
36: ** Trace vectors are initialized.
37: **
38: ** Requires:
39: ** markopen -- to mark the open files.
40: ** The input pipe must have the Cm struct in it as
41: ** the first data.
42: **
43: ** Trace Flags:
44: ** 1
45: */
46:
47: struct resp Resp; /* State response structure */
48: struct _cm_t Cm; /* the system topography map */
49: struct _ctx_t Ctx; /* the current context */
50: int Syncs[CM_MAXPROC];/* expected SYNC's from each proc */
51:
52: /* General System Information */
53: char *Proc_name; /* the 'name' of the currently running proc */
54: char *Fileset; /* a unique string to make filenames from */
55: char *Database; /* the name of the current database */
56: char *Usercode; /* the code of the current user */
57: char *Pathname; /* the pathname of the root of INGRES */
58: int Equel; /* set if running an Equel program */
59: int RubLevel; /* rubout level, -1 if ignored */
60: struct out_arg Out_arg; /* output arguments */
61: jmp_buf CmReset; /* restart addr on interrupt */
62: # ifdef xMONITOR
63: struct monitor CmMonBuf; /* monitor buffer for CM overhead */
64: # endif xMONITOR
65:
66: main(argc, argv)
67: int argc;
68: char **argv;
69: {
70: register int i;
71: struct fn_def *f;
72: register char **q;
73: register char *p;
74: pb_t pb;
75: static int reenter;
76: extern rubcatch();
77: extern error();
78: bool nobuffer;
79: extern pb_t *MonPpb;
80: extern long CmOfiles; /* defined in markopen.c */
81:
82: Ctx.ctx_name = Proc_name = argv[0];
83: argv[argc] = NULL;
84: nobuffer = tTrace(argv, argv[1][1], FuncVect[0]->fn_tvect, 30);
85: Ctx.ctx_tvect = tT;
86: reenter = 0;
87: setjmp(CmReset);
88: if (reenter++)
89: exit(-1);
90: if (signal(SIGINT, SIG_IGN) == SIG_DFL)
91: signal(SIGINT, rubcatch);
92: else
93: RubLevel = -1;
94: MonPpb = &pb;
95:
96: /* mark all currently open files */
97: acc_init();
98: markopen(&CmOfiles);
99: if (tTf(23, 0))
100: {
101: printf("debug flag 23 is ON!!!!\n");
102: fflush(stdout);
103: }
104:
105: /*
106: ** Process argument vector.
107: ** The easy ones just involve saving a pointer.
108: ** argv[1] is used to get a file descriptor; this
109: ** becomes the initial input. This file
110: ** is read to fill in the Cm (configuration)
111: ** structure.
112: */
113:
114: if (tTf(1, 0) || argc < 6)
115: prargs(argc, argv);
116: if (argc < 6)
117: syserr("main: argc=%d", argc);
118: q = &argv[2];
119: Fileset = *q++;
120: Usercode = *q++;
121: Database = *q++;
122: Pathname = *q++;
123:
124: i = read(argv[1][0] & 077, (char *) &Cm, sizeof Cm);
125: if (i != sizeof Cm)
126: syserr("main: read %d", i);
127:
128: /* set up other globals */
129: Ctx.ctx_name = Proc_name = Cm.cm_myname;
130: initbuf(Qbuf, QbufSize, ERR_QBUF, error);
131: Ctx.ctx_cmark = Ctx.ctx_pmark = markbuf(Qbuf);
132:
133: /* process flags */
134: for (; (p = *q) != NULL; q++)
135: {
136: if (p[0] != '-')
137: continue;
138: switch (p[1])
139: {
140: case '&': /* equel program */
141: Equel = 1;
142: if (p[6] != '\0')
143: Equel = 2;
144: break;
145:
146: case 'c': /* c0 sizes */
147: atoi(&p[2], &Out_arg.c0width);
148: break;
149:
150: case 'i': /* iNsizes */
151: switch (p[2])
152: {
153:
154: case '1':
155: atoi(&p[3], &Out_arg.i1width);
156: break;
157:
158: case '2':
159: atoi(&p[3], &Out_arg.i2width);
160: break;
161:
162: case '4':
163: atoi(&p[3], &Out_arg.i4width);
164: break;
165:
166: }
167: break;
168:
169: case 'f': /* fN sizes */
170: p = &p[3];
171: i = *p++;
172: while (*p != '.')
173: p++;
174: *p++ = 0;
175: if ((*q)[2] == '4')
176: {
177: atoi(&(*q)[4], &Out_arg.f4width);
178: atoi(p, &Out_arg.f4prec);
179: Out_arg.f4style = i;
180: }
181: else
182: {
183: atoi(&(*q)[4], &Out_arg.f8width);
184: atoi(p, &Out_arg.f8prec);
185: Out_arg.f8style = i;
186: }
187: *--p = '.'; /* restore parm for dbu's */
188: break;
189:
190: case 'v': /* vertical seperator */
191: Out_arg.coldelim = p[2];
192: break;
193:
194: }
195: }
196:
197: /* set up trace flags */
198: for (i = 0; i < NumFunc; i++)
199: {
200: f = FuncVect[i];
201: if (f->fn_tflag != '\0')
202: nobuffer |= tTrace(argv, f->fn_tflag, f->fn_tvect, f->fn_tsize);
203: Ctx.ctx_name = Proc_name = f->fn_name;
204: (*f->fn_initfn)(argc, argv);
205: }
206: if (tTf(23, 0))
207: {
208: printf("debug flag 23 is ON!!!! after trace stuff.\n");
209: fflush(stdout);
210: }
211:
212: /*
213: ** Buffer standard output
214: **
215: ** Since VM/UNIX always buffers, we force non-buffered
216: ** output if any trace flags are set.
217: */
218:
219: if (!nobuffer)
220: set_so_buf();
221: else
222: setbuf(stdout, NULL);
223:
224: /* if Equel, tell the program to go ahead */
225: if (Equel && Cm.cm_myproc == 1)
226: {
227: pb_prime(&pb, PB_REG);
228: pb.pb_st = PB_FRONT;
229: pb_flush(&pb);
230: }
231:
232: /*
233: ** Start executing routines.
234: **
235: ** Do_seq knows to exit if we get an EOF on the input pipe.
236: */
237:
238: i = setjmp(CmReset);
239: # ifdef xMONITOR
240: markperf(&CmMonBuf);
241: # endif xMONITOR
242: initbuf(Qbuf, QbufSize, ERR_QBUF, error);
243: clrmem((char *) &Ctx, sizeof Ctx);
244: Ctx.ctx_cmark = Ctx.ctx_pmark = markbuf(Qbuf);
245: Ctx.ctx_name = Proc_name = Cm.cm_myname;
246: Ctx.ctx_tvect = tT = FuncVect[0]->fn_tvect;
247: # ifdef xCTR2
248: if (tTf(1, 1))
249: lprintf("main: setjmp: %d\n", i);
250: # endif
251: if (RubLevel >= 0)
252: signal(SIGINT, rubcatch);
253: closeall(FALSE, CmOfiles);
254: for (;;)
255: {
256: Cm.cm_input = Cm.cm_rinput;
257: pb.pb_st = PB_UNKNOWN;
258: do_seq(&pb);
259: }
260: }
261: /*
262: ** RUBPROC -- process rubout signals
263: **
264: ** This routine does the processing needed on rubouts
265: ** when running with the control module. It basically
266: ** flushes pipes.
267: **
268: ** Parameters:
269: ** none.
270: **
271: ** Returns:
272: ** never
273: **
274: ** Side Effects:
275: ** Flushes pipes, etc.
276: */
277:
278: rubproc()
279: {
280: register int i;
281: pb_t pb;
282: register int stat;
283:
284: /*
285: ** Update the world for consistency.
286: */
287:
288: fflush(stdout);
289: closecatalog(FALSE);
290: i = pageflush(NULL);
291: if (i != 0)
292: syserr("rubproc: pageflush %d", i);
293:
294: /*
295: ** Send SYNC blocks to all processes that are adjacent
296: ** in the write direction.
297: ** Arrange to ignore blocks from all processes that
298: ** are adjacent in the read direction.
299: */
300:
301: pb_prime(&pb, PB_SYNC);
302: for (i = 0; i < CM_MAXPROC; i++)
303: {
304: stat = Cm.cm_proc[i].pr_stat;
305: if ((stat & PR_RADJCT) != 0)
306: Syncs[i]++;
307: if ((stat & PR_WADJCT) != 0)
308: {
309: pb.pb_proc = i;
310: pb_write(&pb);
311: }
312: }
313:
314: /*
315: ** Cleanup and exit.
316: */
317:
318: cm_cleanup(2);
319: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.