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