void DB_ViewPut(int vol, struct GBD *ptr) // que block for write { short s; // for funcs volnum = vol; // for ron writing = 0; // clear this s = SemOp(SEM_GLOBAL, WRITE); // write lock if (s < 0) // check error { return; // quit if so } ptr->last_accessed = MTIME(0); // reset access if (ptr->mem->type) // if used { Used_block(ptr->block); // mark it so } else // trying to free it { Free_block(ptr->block); // do so bzero(ptr->mem, systab->vol[(volnum)-1]->vollab->block_size); // clear it } level = 0; // for Queit if (ptr->dirty == NULL) // check dirty ptr { ptr->dirty = ptr; // set if reqd blk[level] = ptr; // ditto Queit(); // do this } if (curr_lock) { SemOp(SEM_GLOBAL, -curr_lock); // release lock } return; // and exit }
short DB_GetLen( mvar *var, int lock, u_char *buf) // length of node { short s; // for returns int sav; // save curr_lock if ((lock == -1) && (buf == NULL)) // just unlock? { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // unlock it } return 0; // exit } sav = curr_lock; // save this s = Copy2local(var); // get local copy curr_lock = sav; // restore current lock if (s < 0) // check for error { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // and return } s = Get_data(0); // attempt to get it if (s < 0) // check for error { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // and return } if (buf != NULL) // want data? { s = mcopy(record->buf, buf, record->len); // copy the data } if ((lock != 1) && (curr_lock)) // preserve lock? { SemOp( SEM_GLOBAL, -curr_lock); // no - release it } return s; // and exit }
short DB_Data(mvar *var, u_char *buf) // get $DATA() { short s; // for returns int i; // a handy int s = Copy2local(var); // get local copy if (s < 0) { return s; // exit on error } systab->vol[volnum-1]->stats.dbdat++; // update stats s = Get_data(0); // attempt to get it i = 1; // assume data found if (s == -ERRM7) // undefined global? { i = 0; // yes - no data if (level == 0) // check for global { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } buf[0] = '0'; // zero to return buf[1] = '\0'; // null terminated return 1; // and exit } } else if (s < 0) // if it failed { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // and exit } if ((!db_var.slen) && (!i)) // pointing at 1st { Index++; } if ((i) || (Index > blk[level]->mem->last_idx)) // found or passed end { s = Locate_next(); // get next record if (s == -ERRM7) // any more? { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return itocstring(buf, i); // return result } else if (s < 0) // error? { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // and exit } } // got next record if (((db_var.slen < keybuf[0]) && // if smaller key and (bcmp(&keybuf[1], db_var.key, db_var.slen) == 0)) || // a descendant? (!db_var.slen)) { i += 10; // add 10 to result } if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return itocstring(buf, i); // return result }
short DB_QueryD(mvar *var, u_char *buf) // get next key { short s; // for returns // int i; // a handy int s = Copy2local(var); // get local copy if (s < 0) { return s; // exit on error } s = Get_data(0); // try to find that if ((s < 0) && (s != -ERRM7)) // check for errors { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // and return the error } if ((level == 0) && (s == -ERRM7)) // if no such global { buf[0] = '\0'; // null terminate ret if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return -(ERRMLAST+ERRZ55); // and return } if ((s < 0) && (db_var.slen)) // If we had a "real" { Index--; // <UNDEF> last time } // back up Index s = Locate_next(); // point at next if (s < 0) // not found or error { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } if (s == -ERRM7) // if no more { s = -(ERRMLAST+ERRZ55); // say 'at end' } return s; // done } // for (i = 10; i <= Index; i++) // scan to current // { chunk = (cstring *) &iidx[idx[i]]; // point at the chunk // bcopy(&chunk->buf[2], &keybuf[chunk->buf[0]+1], // chunk->buf[1]); // update the key // keybuf[0] = chunk->buf[0] + chunk->buf[1]; // and the size // } bcopy(&keybuf[1], var->key, (int) keybuf[0]); // copy in the key var->slen = keybuf[0]; // update the length s = mcopy(record->buf, buf, record->len); // copy the data if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // return the count }
void DB_ViewRel(int vol, struct GBD *ptr) // release block, gbd { short s; // for functions writing = 0; // clear this ptr->last_accessed = MTIME(0); // reset access if (ptr->dirty != NULL) // not owned elsewhere { s = SemOp(SEM_GLOBAL, WRITE); // write lock if (s < 0) // check error { return; // quit if so // PROBABLY SHOULD PERSIST HERE } Free_GBD(ptr); // free it SemOp(SEM_GLOBAL, -curr_lock); // release lock } return; // and exit }
int DB_Free(int vol) // total free blocks { short s; // for funcs u_int i; // loop cnt int count = 0; // blk count s = SemOp( SEM_GLOBAL, READ); // lock the globals if (s < 0) { return s; // return any errors } for (i = 1; // start at block 1 i <= systab->vol[vol-1]->vollab->max_block; // while still in map i++) // going up by one { count += // add up blocks (((((u_char *)systab->vol[vol-1]->map)[i>>3]) &(1<<(i&7))) == 0); } SemOp( SEM_GLOBAL, -curr_lock); // unlock the globals return count; // return the count } // end DB_Free
int DB_SetFlags(mvar *var, int flags) // Set flags { int clearit = 0; int i; short s; if (flags < 0) { clearit = 1; // setup to clear flags = -flags; // get flags correct } s = Copy2local(var); // get local copy if (s < 0) { return s; // exit on error } systab->vol[volnum-1]->stats.dbset++; // update stats writing = 1; // say we are writing while (systab->vol[volnum - 1]->writelock) // check for write lock { i = sleep(5); // wait a bit if (partab.jobtab->attention) { return -(ERRZLAST+ERRZ51); // for <Control><C> } } // end writelock check Get_GBDs(1); // ensure this many s = Get_data(0); // try to find that if ((s < 0) && (s != -ERRM7)) // check for errors { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return (int) s; // return error } i = ((int *)record)[1]; // get current flags if (clearit) { i = i & ~flags; // clear flags } else { i = i | flags; // set flags } ((int *)record)[1] = i; // set back to GD if (blk[level]->dirty == (gbd *) 1) // if reserved { blk[level]->dirty = blk[level]; // terminate list Queit(); // que for write } SemOp( SEM_GLOBAL, -curr_lock); // release global lock return i; // return current flags }
int main() { int *array = (int *)ShmAllocate(10*sizeof(int)); array[0]=1; int x = Fork(); int id = SemGet(SEMKEY); if(x == 0) { SemOp(id, -1); PrintChar('C'); array[0]=10; SemOp(id, 1); } else { Join(x); SemOp(id, -1); PrintChar('P'); PrintInt(array[0]); SemOp(id, 1); } }
struct GBD *DB_ViewGet(int vol, int block) // return gbd for blk { short s; // for func if ((block < 1) || (block > systab->vol[vol-1]->vollab->max_block)) { return NULL; // validate } level = 0; // where it goes volnum = vol; // need this writing = 0; // clear this s = SemOp(SEM_GLOBAL, READ); // write lock if (s < 0) // check error { return NULL; // quit if so } s = Get_block(block); // get it if (s >= 0) { blk[level]->last_accessed = MTIME(0)+86400; // push last access } if (curr_lock) { SemOp( SEM_GLOBAL, -curr_lock); // unlock the globals } return (s < 0) ? NULL : blk[level]; // return whatever }
int DB_GetFlags(mvar *var) // Get flags { short s; // for returns int i; // a handy int s = Copy2local(var); // get local copy if (s < 0) { return s; // exit on error } s = Get_data(0); // try to find that if ((s < 0) && (s != -ERRM7)) // check for errors { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // and return the error } i = ((int *) record)[1]; // get the value if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return i; // return the flags }
int Enqueue (int x, int id) { int y; SemOp(semid, -1); while (array[SIZE+2] == SIZE) { SemOp(stdoutsemid, -1); PrintString("Enqueuer "); PrintInt(id); PrintString(": waiting on queue full."); PrintChar('\n'); SemOp(stdoutsemid, 1); CondOp(notFullid, COND_OP_WAIT, semid); } array[array[SIZE+1]] = x; y = array[SIZE+1]; array[SIZE+1] = (array[SIZE+1] + 1)%SIZE; array[SIZE+2]++; CondOp(notEmptyid, COND_OP_SIGNAL, semid); SemOp(semid, 1); return y; }
int Dequeue (int id, int *y) { int x; SemOp(semid, -1); while (array[SIZE+2] == 0) { SemOp(stdoutsemid, -1); PrintString("Dequeuer "); PrintInt(id); PrintString(": waiting on queue empty."); PrintChar('\n'); SemOp(stdoutsemid, 1); CondOp(notEmptyid, COND_OP_WAIT, semid); } x = array[array[SIZE]]; (*y) = array[SIZE]; array[SIZE] = (array[SIZE] + 1)%SIZE; array[SIZE+2]--; CondOp(notFullid, COND_OP_SIGNAL, semid); SemOp(semid, 1); return x; }
void DB_StopJournal(int vol, u_char action) // Stop journal { jrnrec jj; volnum = vol; // set common var if (!systab->vol[vol - 1]->vollab->journal_available) // if no journal { return; // just exit } while (SemOp( SEM_GLOBAL, WRITE)) { sleep(1); } jj.action = action; jj.uci = 0; jj.name.var_qu = 0; jj.slen = 0; DoJournal(&jj, NULL); systab->vol[vol - 1]->vollab->journal_available = 0; return; }
short DB_Set(mvar *var, cstring *data) // set global data { short s; // for returns int i; // a handy int s = Copy2local(var); // get local copy if (s < 0) { return s; // exit on error } i = 4 + db_var.slen + 2 + data->len; // space reqd if (i & 3) // if required { i += (4 - (i & 3)); // round up } i += 4; // add Index if (i > (systab->vol[volnum-1]->vollab->block_size - 20)) // if too big { return -ERRM75; // return an error } systab->vol[volnum-1]->stats.dbset++; // update stats writing = 1; // say we are writing while (systab->vol[volnum - 1]->writelock) // check for write lock { i = sleep(5); // wait a bit if (partab.jobtab->attention) { return -(ERRZLAST+ERRZ51); // for <Control><C> } } // end writelock check i = systab->vol[volnum-1]->vollab->max_block >> 3; // last map byte while (i) // check from the end { if ((((u_char *) systab->vol[volnum - 1]->map)[i--]) == 0) { break; // OK if byte is free } } if (!i) { return -(ERRZLAST+ERRZ11); // complain if failed } s = Set_data(data); // do the set if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // return the result }
short DB_Get(mvar *var, u_char *buf) // get global data { short s; // for returns s = Copy2local(var); // get local copy if (s < 0) { return s; // exit on error } systab->vol[volnum-1]->stats.dbget++; // update stats s = Get_data(0); // attempt to get it if (s >= 0) // if worked { if (bcmp("$GLOBAL\0", &db_var.name.var_cu[0], 8) == 0) // if ^$G { s = itocstring(buf, *(u_int *) record); // block number } else { s = mcopy(record->buf, buf, record->len); // copy the data } } if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // return the count }
short DB_Order(mvar *var, u_char *buf, int dir) // get next subscript { short s; // for returns int i; // a handy int int last_key; // start of last key s = Copy2local(var); // get local copy if (s < 0) { return s; // exit on error } systab->vol[volnum-1]->stats.dbord++; // update stats last_key = UTIL_Key_Last(&db_var); // get start of last buf[0] = '\0'; // null terminate ret if (dir < 0) // if it's backward { s = Get_data(-1); // get the previous if ((s < 0) && (s != -ERRM7)) // check for errors { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // and return the error } if ((level == 0) && (s == -ERRM7) && // if no such global (bcmp(&db_var.name.var_cu[0], "$GLOBAL\0", 8))) // and not ^$G() { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return 0; // and return } Index--; // backup the Index if (Index < 10) // can't happen? { panic("DB_Order: Problem with negative direction"); } chunk = (cstring *) &iidx[idx[Index]]; // point at the chunk record = (cstring *) &chunk->buf[chunk->buf[1]+4]; // point at the dbc } // end backwards else // it's forward { db_var.key[db_var.slen++] = 255; // force next key s = Get_data(0); // try to find that if (s != -ERRM7) // MUST be undefined { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return (s < 0) ? s : -(ERRMLAST+ERRZ61); // and return the error } if ((level == 0) && // if no such global (bcmp(&db_var.name.var_cu[0], "$GLOBAL\0", 8))) // and not ^$G() { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return 0; // and return } if (Index > blk[level]->mem->last_idx) // no more avbl { s = Locate_next(); // get next (if there) if (s < 0) // failed? { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return (s == -ERRM7) ? 0 : s; // done } } } // end forwards for (i = 10; i <= Index; i++) // scan to current { chunk = (cstring *) &iidx[idx[i]]; // point at the chunk bcopy(&chunk->buf[2], &keybuf[chunk->buf[0]+1], chunk->buf[1]); // update the key keybuf[0] = chunk->buf[0] + chunk->buf[1]; // and the size } if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } if ((keybuf[0] < (last_key + 1)) || (bcmp(&keybuf[1], db_var.key, last_key))) // check for past it { return 0; // done } i = 0; // clear flag s = UTIL_Key_Extract(&keybuf[last_key+1], buf, &i); // extract the key return s; // return result }
short DB_Compress(mvar *var, int flags) // Compress global { int i; short s; int retlevel; // the ACTUAL level flags &= 15; // clear high bits s = Copy2local(var); // get local copy if (s < 0) { return s; // exit on error } bzero(rekey_blk, MAXREKEY * sizeof(u_int)); // clear that table bzero(rekey_lvl, MAXREKEY * sizeof(int)); // and that table bcopy(&db_var, var, sizeof(mvar)); // copy the data back s = Get_data(flags); // get to level 'flags' retlevel = level; // save real level if (!level) { return -ERRM7; // give up if nosuch } chunk = (cstring *) &iidx[idx[10]]; // point at the first bcopy(&chunk->buf[1], &var->slen, chunk->buf[1]+1); // save the real key while (TRUE) { bcopy(var, &db_var, sizeof(mvar)); // get next key writing = 0; // flag we are reading while (systab->vol[volnum - 1]->writelock) // check for write lock { i = sleep(5); // wait a bit if (partab.jobtab->attention) { return -(ERRZLAST+ERRZ51); // for <Control><C> } } // end writelock check if (partab.jobtab->attention) { return -(ERRZLAST+ERRZ51); // for <Control><C> } s = Get_data(retlevel); // get the block if ((s == -ERRM7) && (!db_var.slen)) // if first node { s = 0; // it exists } if (s == -ERRM7) // if key changed { if (blk[level]->mem->right_ptr) // if more { chunk = (cstring *) &iidx[idx[10]]; // point at the first bcopy(&chunk->buf[1], &db_var.slen, chunk->buf[1]+1); // save real key SemOp( SEM_GLOBAL, -curr_lock); // release global lock continue; // go again } SemOp( SEM_GLOBAL, -curr_lock); // release global lock return retlevel; // all done, exit } if (s < 0) { SemOp( SEM_GLOBAL, -curr_lock); // release global lock return s; // exit on error } if (!blk[level]->mem->right_ptr) // if no more { SemOp( SEM_GLOBAL, -curr_lock); // release global lock if ((retlevel == 2) && (!db_var.slen)) // if only block lvl 2 { s = Compress1(); // do that SemOp( SEM_GLOBAL, -curr_lock); // release write lock if (s < 0) { return s; // exit on error } } return retlevel; // all done, exit } level++; s = Get_block(blk[level - 1]->mem->right_ptr); if (s < 0) // if error { SemOp( SEM_GLOBAL, -curr_lock); // release global lock return s; // exit on error } i = ((blk[level-1]->mem->last_free*2 + 1 - blk[level-1]->mem->last_idx)*2) + ((blk[level]->mem->last_free*2 + 1 - blk[level]->mem->last_idx)*2); if (i < 1024) // if REALLY not enough space (btw: make this a param) { chunk = (cstring *) &iidx[idx[10]]; // point at first in RL bcopy(&chunk->buf[1], &var->slen, chunk->buf[1]+1); // save the real key SemOp( SEM_GLOBAL, -curr_lock); // release global lock continue; // go again } level = retlevel; SemOp( SEM_GLOBAL, -curr_lock); // release read lock s = Compress1(); // do that SemOp( SEM_GLOBAL, -curr_lock); // release write lock if (s < 0) { return s; // exit on error } if (!var->volset) // if done { return retlevel; } } }
int main() { array = (int*)ShmAllocate(sizeof(int)*(SIZE+3)); // queue[SIZE], head, tail, count int x, i, j, seminit = 1, y; int pid[NUM_DEQUEUER+NUM_ENQUEUER]; for (i=0; i<SIZE; i++) array[i] = -1; array[SIZE] = 0; array[SIZE+1] = 0; array[SIZE+2] = 0; semid = SemGet(SEM_KEY1); SemCtl(semid, SYNCH_SET, &seminit); stdoutsemid = SemGet(SEM_KEY2); SemCtl(stdoutsemid, SYNCH_SET, &seminit); notFullid = CondGet(COND_KEY1); notEmptyid = CondGet(COND_KEY2); int temp; temp = -11; SemCtl(semid,SYNCH_GET,&temp); PrintInt(temp); for (i=0; i<NUM_DEQUEUER; i++) { x = Fork(); if (x == 0) { for (j=0; j<NUM_DEQUEUE_OP; j++) { x = Dequeue (i, &y); SemOp(stdoutsemid, -1); PrintString("Dequeuer "); PrintInt(i); PrintString(": Got "); PrintInt(x); PrintString(" from slot "); PrintInt(y); PrintChar('\n'); SemOp(stdoutsemid, 1); } Exit(DEQUEUE_EXIT_CODE); } pid[i] = x; } for (i=0; i<NUM_ENQUEUER; i++) { x = Fork(); if (x == 0) { x = i*NUM_ENQUEUE_OP; for (j=0; j<NUM_ENQUEUE_OP; j++) { y = Enqueue (x+j, i); SemOp(stdoutsemid, -1); PrintString("Enqueuer "); PrintInt(i); PrintString(": Inserted "); PrintInt(x+j); PrintString(" in slot "); PrintInt(y); PrintChar('\n'); SemOp(stdoutsemid, 1); } Exit(ENQUEUE_EXIT_CODE); } pid[i+NUM_DEQUEUER] = x; } for (i=0; i<NUM_DEQUEUER+NUM_ENQUEUER; i++) { x = Join(pid[i]); SemOp(stdoutsemid, -1); PrintString("Parent joined with "); PrintInt(pid[i]); PrintString(" having exit code "); PrintInt(x); PrintChar('\n'); SemOp(stdoutsemid, 1); } SemCtl(semid, SYNCH_REMOVE, 0); SemCtl(stdoutsemid, SYNCH_REMOVE, 0); CondRemove(notFullid); CondRemove(notEmptyid); return 0; }
//**************************************************************************** // Attach to an environment - switches are: // x = xecute command Opt // e = environment (UCI) Opt int INIT_Run( char *file, // database file char *env, // environment (UCI) char *cmd) // command { int i; // an int int dbfd = 0; // database file descriptor int ret = 0; // return value int env_num = 1; // startup environemnt number var_u tmp; // temp descriptor uci_tab *uci_ptr; // for uci search int pid; // job number int ssp = 0; // string stack ptr int asp = 0; // address stack ptr mvar *var; // a variable pointer cstring *cptr; // a handy pointer cstring *sptr; // cstring ptr short s; // for functions short start_type = TYPE_RUN; // how we started gid_t gidset[MAX_GROUPS]; // for getgroups() struct termios tty_settings; // man 4 termios start: #if defined(__APPLE__) || defined(__FreeBSD__) srandomdev(); // randomize #endif partab.jobtab = (jobtab *) NULL; // clear jobtab pointer dbfd = open(file, O_RDONLY); // open the database for read if (dbfd < 0) return (errno); // if that failed // i = fcntl(dbfd, F_NOCACHE, 1); if (start_type == TYPE_RUN) // if not from JOB { i = UTIL_Share(file); // attach to shared mem if (i != 0) return(i); // quit on error } if (env != NULL) // passed in uci ? { env_num = 0; // clear uci number uci_ptr = &systab->vol[0]->vollab->uci[0]; // get ptr to uci table //tmp.var_qu = 0; // zero entire name X_Clear(tmp.var_xu); // zero entire name for (i = 0; i < MAX_NAME_BYTES; i++) // copy in name { if (env[i] == '\0') break; // done at null tmp.var_cu[i] = env[i]; // copy character } for (i = 0; i < UCIS; i++) // scan all ucis //if (uci_ptr[i].name.var_qu == tmp.var_qu) // if we have a match if (X_EQ(uci_ptr[i].name.var_xu, tmp.var_xu)) // if we have a match { env_num = i + 1; // save it break; // and exit loop } if (env_num == 0) { ret = ENOENT; // complain on fail goto exit; // and exit } } pid = (int) getpid(); // get process id for (i = 0; i < systab->maxjob; i++) // scan the slots { ret = systab->jobtab[i].pid; // get pid if ((ret != pid) && (ret)) // if one there and not us { if (kill(ret, 0)) // check the job { if (errno == ESRCH) // doesn't exist { ret = CleanJob(i + 1); // zot if not there if (ret == 0) // success ? break; // have at least one } } } else // it's free or ours { break; // quit } } ret = SemOp(SEM_SYS, -systab->maxjob); // lock systab if (ret < 0) goto exit; // give up on error for (i = 0; i < systab->maxjob; i++) // look for a free slot { if (((systab->jobtab[i].pid == 0) && // this one ? (start_type == TYPE_RUN)) || ((systab->jobtab[i].pid == pid) && // or already done (JOB) (start_type == TYPE_JOB))) { bzero(&systab->jobtab[i], sizeof(jobtab)); // yes - zot the lot partab.jobtab = &systab->jobtab[i]; // and save our jobtab address partab.jobtab->pid = pid; // copy in our pid break; // end loop } } ret = SemOp(SEM_SYS, systab->maxjob); // unlock systab if (partab.jobtab == NULL) // if that failed { ret = ENOMEM; // error message goto exit; // and exit } partab.jobtab->user = (short) getuid(); // get user number if ((partab.jobtab->user == systab->start_user) || // if he started it (partab.jobtab->user == 0)) // or is root { partab.jobtab->priv = 1; // say yes } else { if (systab->maxjob == 1) // if single job { ret = ENOMEM; // error message partab.jobtab = NULL; // clear this goto exit; // and exit } i = getgroups(MAX_GROUPS, gidset); // get groups if (i < 0) // if an error { ret = errno; // get the error goto exit; // and exit } while (i > 0) // for each group { if (gidset[i - 1] == PRVGRP) // if it's "wheel" or "admin" { partab.jobtab->priv = 1; // say yes break; // and exit } i--; // decrement i } } partab.jobtab->precision = systab->precision; // decimal precision partab.jobtab->uci = env_num; // uci number partab.jobtab->vol = 1; // volset partab.jobtab->luci = env_num; // uci number partab.jobtab->lvol = 1; // volset partab.jobtab->ruci = env_num; // uci number partab.jobtab->rvol = 1; // volset partab.jobtab->start_len = Vhorolog(partab.jobtab->start_dh); // store start date/time partab.jobtab->dostk[0].type = TYPE_RUN; // ensure slot 0 has a value failed_tty = tcgetattr ( 0, &tty_settings ); i = SQ_Init(); // have seqio setup chan 0 systab->last_blk_used[partab.jobtab - systab->jobtab] = 0; // clear last global block partab.debug = 0; // clear debug flag partab.sstk_start = &sstk[0]; // address of sstk partab.sstk_last = &sstk[MAX_SSTK]; // and the last char partab.varlst = NULL; // used by compiler partab.vol_fds[0] = dbfd; // make sure fd is right ST_Init(); // initialize symbol table if ((systab->vol[0]->vollab->journal_available) && (systab->vol[0]->vollab->journal_requested)) // if journaling { partab.jnl_fds[0] = open(systab->vol[0]->vollab->journal_file, O_RDWR); if (partab.jnl_fds[0] < 0) { fprintf(stderr, "Failed to open journal file %s\nerrno = %d\n", systab->vol[0]->vollab->journal_file, errno); ret = -1; if (cmd != NULL) goto exit; } else { // i = fcntl(dbfd, F_NOCACHE, 1); } } if (cmd != NULL) // command specified ? { source_ptr = (u_char *) cmd; // where the code is cptr = (cstring *) &sstk[ssp]; // where the compiled goes comp_ptr = cptr->buf; // the data bit parse(); *comp_ptr++ = CMQUIT; // add the quit *comp_ptr++ = ENDLIN; // JIC *comp_ptr++ = ENDLIN; // JIC i = &comp_ptr[0] - &cptr->buf[0]; // get number of bytes cptr->len = i; // save for ron ssp = ssp + i + sizeof(short) + 1; // point past it mumpspc = &cptr->buf[0]; // setup the mumpspc partab.jobtab->dostk[0].routine = (u_char *) cmd; // where we started partab.jobtab->dostk[0].pc = mumpspc; // where we started partab.jobtab->dostk[0].symbol = NULL; // nowhere partab.jobtab->dostk[0].newtab = NULL; // nowhere partab.jobtab->dostk[0].endlin = mumpspc + i - 4; // ENDLIN //partab.jobtab->dostk[0].rounam.var_qu = 0;// zero the routine name X_Clear(partab.jobtab->dostk[0].rounam.var_xu); // zero the routine name partab.jobtab->dostk[0].vol = partab.jobtab->vol; // current volume partab.jobtab->dostk[0].uci = partab.jobtab->uci; // current uci partab.jobtab->dostk[0].line_num = 0; // no line number partab.jobtab->dostk[0].type = start_type; // how we started partab.jobtab->dostk[0].estack = 0; // estack offset partab.jobtab->dostk[0].level = 0; // where we started partab.jobtab->dostk[0].flags = 0; // no flags partab.jobtab->dostk[0].savasp = asp; // address stack ptr partab.jobtab->dostk[0].savssp = ssp; // string stack partab.jobtab->dostk[0].asp = asp; // address stack ptr partab.jobtab->dostk[0].ssp = ssp; // string stack partab.jobtab->attention = 0; partab.jobtab->trap = 0; partab.jobtab->async_error = 0; isp = 0; // clear indirect pointer s = run(asp, ssp); if (s == OPHALT) goto exit; // look after halt if (s == JOBIT) goto jobit; // look after JOB partab.jobtab->io = 0; // force chan 0 var = (mvar *) &sstk[0]; // space to setup a var X_set("$ECODE\0\0", &var->name.var_cu[0], 8); var->volset = 0; var->uci = UCI_IS_LOCALVAR; var->slen = 0; // setup for $EC cptr = (cstring *) &sstk[sizeof(mvar)]; // for result bcopy("$ECODE=", cptr->buf, 7); s = ST_Get(var, &cptr->buf[7]); if (s > 1) // ignore if nothing there { cptr->len = s + 7; s = SQ_WriteFormat(SQ_LF); // new line s = SQ_Write(cptr); // write the prompt s = SQ_WriteFormat(SQ_LF); // new line cptr = (cstring *) (((u_char *) cptr) + 8); if (cptr->buf[0] != 'U') { cptr->len = 4; // max error size cptr->len = Xcall_errmsg((char *) cptr->buf, cptr, cptr); // cvt to str s = SQ_Write(cptr); // write the error s = SQ_WriteFormat(SQ_LF); // new line } ret = ESRCH; // set an error for exit } goto exit; // and halt } while (TRUE) // forever { sptr = (cstring *) &sstk[0]; // front of string stack asp = 0; // zot address stack ssp = 0; // and the string stack bcopy("M> ", sptr->buf, 3); // copy in the prompt sptr->buf[3] = '\0'; // null terminate sptr->len = 3; // and the length partab.jobtab->io = 0; // force chan 0 if (partab.jobtab->seqio[0].dx) // if not at right margin { s = SQ_WriteFormat(SQ_LF); // new line if (s < 0) ser(s); // check for error } s = SQ_Write(sptr); // write the prompt if (s < 0) ser(s); // check for error s = SQ_Read(sptr->buf, -1, -1); // get a string i = attention(); // check signals if (i == OPHALT) break; // exit on halt if (i == -(ERRZ51+ERRMLAST)) // control c controlc(); // say if (s < 0) { ser(s); // complain on error s = 0; } sptr->len = s; // save the length if (s == 0) continue; // ignore null astk[asp++] = (u_char *) sptr; // save address of string ssp = ssp + s + sizeof(short) + 1; // point past it s = SQ_WriteFormat(SQ_LF); // new line if (s < 0) ser(s); // check for error source_ptr = sptr->buf; // where the code is cptr = (cstring *) &sstk[ssp]; // where the compiled goes comp_ptr = cptr->buf; // the data bit parse(); *comp_ptr++ = CMQUIT; // add the quit *comp_ptr++ = ENDLIN; // JIC *comp_ptr++ = ENDLIN; // JIC i = &comp_ptr[0] - &cptr->buf[0]; // get number of bytes cptr->len = i; // save for ron ssp = ssp + i + sizeof(short) + 1; // point past it mumpspc = &cptr->buf[0]; // setup the mumpspc partab.jobtab->dostk[0].routine = sptr->buf; // where we started partab.jobtab->dostk[0].pc = mumpspc; // where we started partab.jobtab->dostk[0].symbol = NULL; // nowhere partab.jobtab->dostk[0].newtab = NULL; // nowhere partab.jobtab->dostk[0].endlin = mumpspc + i - 4; // ENDLIN //partab.jobtab->dostk[0].rounam.var_qu = 0;// zero the routine name X_Clear(partab.jobtab->dostk[0].rounam.var_xu);// zero the routine name partab.jobtab->dostk[0].vol = partab.jobtab->vol; // current volume partab.jobtab->dostk[0].uci = partab.jobtab->uci; // current uci partab.jobtab->dostk[0].line_num = 0; // no line number partab.jobtab->dostk[0].type = TYPE_RUN; // how we started partab.jobtab->dostk[0].estack = 0; // estack offset partab.jobtab->dostk[0].level = 0; // where we started partab.jobtab->dostk[0].flags = 0; // no flags partab.jobtab->dostk[0].savasp = asp; // address stack ptr partab.jobtab->dostk[0].savssp = ssp; // string stack partab.jobtab->dostk[0].asp = asp; // address stack ptr partab.jobtab->dostk[0].ssp = ssp; // string stack partab.jobtab->attention = 0; partab.jobtab->trap = 0; partab.jobtab->async_error = 0; isp = 0; // clear indirect pointer s = run(asp, ssp); if (s == JOBIT) goto jobit; // look after JOB if (s == OPHALT) break; // exit on halt partab.jobtab->io = 0; // force chan 0 if (s == -(ERRZ51+ERRMLAST)) // control c controlc(); // say else if (s < 0) ser(s); partab.jobtab->error_frame = 0; // and that one var = (mvar *) &sstk[0]; // space to setup a var X_set("$ECODE\0\0", &var->name.var_cu[0], 8); var->volset = 0; var->uci = UCI_IS_LOCALVAR; var->slen = 0; // setup for $EC cptr = (cstring *) &sstk[sizeof(mvar)]; // for result bcopy("$ECODE=", cptr->buf, 7); s = ST_Get(var, &cptr->buf[7]); if (s < 1) continue; // ignore if nothing there cptr->len = s + 7; s = SQ_Write(cptr); // write the prompt if (s < 0) ser(s); // check for error s = SQ_WriteFormat(SQ_LF); // new line if (s < 0) ser(s); // check for error s = ST_Kill(var); // dong $EC cptr = (cstring *) (((u_char *) cptr) + 8); if (cptr->buf[0] != 'U') { cptr->len = 4; // max error size cptr->len = Xcall_errmsg((char *) cptr->buf, cptr, cptr); // cvt to str s = SQ_Write(cptr); // write the error if (s < 0) ser(s); // check for error s = SQ_WriteFormat(SQ_LF); // new line } } // end command level loop exit: // general exit code if (partab.jobtab != NULL) // if we have a jobtab CleanJob(0); // remove all locks etc i = shmdt(systab); // detach the shared mem if (dbfd) i = close(dbfd); // close the database if (!failed_tty) // reset terminal if possible { failed_tty = tcsetattr ( 0, TCSANOW, &tty_settings ); } if (start_type == TYPE_JOB) return 0; // no error from JOB return ret; // and exit jobit: // code for JOB start_type = TYPE_JOB; // what we are doing env_num = partab.jobtab->ruci; // remember (current) rou uci cmd = (char *) &sstk[0]; // where the command is ssp = strlen((const char *) sstk); // protect original command isp = 0; // clear all these asp = 0; ret = 0; env = NULL; goto start; // go do it }
int main (int argc, char *argv []) { key_t key = ftok (argv [0], 0); semid = semget (key, nsems, 0644 | IPC_CREAT | IPC_EXCL); if (semid >= 0) { //got it first SemInit(); } else if (errno == EEXIST) { //someone else got it first semid = semget (key, nsems, 0); if (semid < 0) { fprintf (stderr, "Failed to open semaphore\n"); semctl (semid, 0, IPC_RMID, NULL); shmdt (shared); exit(EXIT_FAILURE); } unsigned short *ptr = (unsigned short *) calloc (nsems, sizeof (unsigned short)); semctl (semid, mutex, GETALL, ptr); if (ptr [mutex] != 1 || ptr [full] != 0 || ptr [empty] != buf_num) { SemInit(); } } else { semctl (semid, 0, IPC_RMID, NULL); shmdt (shared); perror("\nFailed to create semaphore."); semctl (semid, 0, IPC_RMID, NULL); shmdt (shared); exit(EXIT_FAILURE); } int shmid = shmget (key, sizeof (in_data), 0644 | IPC_CREAT); if (shmid == -1) { perror("\nFailed to allocate shared memory."); semctl (semid, 0, IPC_RMID, NULL); shmdt (shared); exit(EXIT_FAILURE); } shared = (in_data*) shmat (shmid, NULL, 0); if (argc > 1) { SemOpMul (semid, ping1, 1, SEM_UNDO); SemOpMul (semid, ping2, 1, SEM_UNDO); SemOpMul (semid, init1, -1, SEM_UNDO); SemOpMul (semid, init2, 0, 0); //writer (Producer) int src = open (argv [1], O_RDONLY, 0); int ret_num = 1; while (ret_num > 0) { SemOp ('P', semid, empty, 0, ping1); SemOp ('P', semid, mutex, 0, ping1); ret_num = read (src, shared -> buffer, buf_size); shared -> num = ret_num; SemOp ('V', semid, mutex, 0, ping1); SemOp ('V', semid, full, 0, ping1); } } else { //reader (Consumer) SemOpMul (semid, ping2, 1, SEM_UNDO); SemOpMul (semid, ping1, 1, SEM_UNDO); SemOpMul (semid, init2, -1, SEM_UNDO); SemOpMul (semid, init1, 0, 0); while (1) { SemOp ('P', semid, full, 0, ping2); SemOp ('P', semid, mutex, 0, ping2); write (1, shared -> buffer, shared -> num); fflush (stdout); SemOp ('V', semid, mutex, 0, ping2); SemOp ('V', semid, empty, 0, ping2); } } semctl (semid, 0, IPC_RMID, NULL); shmdt (shared); return 0; }
short DB_Kill(mvar *var) // remove sub-tree { short s; // for returns int i; // a handy int s = Copy2local(var); // get local copy if (s < 0) { return s; // exit on error } systab->vol[volnum-1]->stats.dbkil++; // update stats while (systab->vol[volnum - 1]->writelock) // check for write lock { i = sleep(5); // wait a bit if (partab.jobtab->attention) { return -(ERRZLAST+ERRZ51); // for <Control><C> } } // end writelock check s = Get_data(0); // attempt to get it if (((s == -ERRM7) && (level == 0)) || // if nosuch ((s < 0) && (s != -ERRM7))) // or an error { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } if (s == -ERRM7) // if undefined { s = 0; // that is OK } return s; // nothing to do } if ((s == -ERRM7) && (db_var.slen)) // if undefined { if (Index <= blk[level]->mem->last_idx) // and still in block { if ((db_var.slen > keybuf[0]) || // found smaller key (bcmp(&keybuf[1], db_var.key, db_var.slen))) // not a descendant? { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return 0; // nothing to do } } // end still in block else { s = Locate_next(); // point at next block if (!s) // found one { if ((db_var.slen > keybuf[0]) || // found smaller key (bcmp(&keybuf[1], db_var.key, db_var.slen))) // not a descendant? { s = -ERRM7; // flag for later } } if (s < 0) // no such or error { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } if (s == -ERRM7) { s = 0; } return 0; // nothing to do } } } s = Kill_data(); // do the kill if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // return the result }
short DB_Query(mvar *var, u_char *buf, int dir) // get next key { short s; // for returns int i; // a handy int s = Copy2local(var); // get local copy if (s < 0) { return s; // exit on error } systab->vol[volnum-1]->stats.dbqry++; // update stats if (dir < 0) // if it's backward { s = Get_data(-1); // get the previous if ((s < 0) && (s != -ERRM7)) // check for errors { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // and return the error } if ((level == 0) && (s == -ERRM7)) // if no such global { buf[0] = '\0'; // null terminate ret if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return 0; // and return } Index--; // backup the Index if (Index < 10) // can't happen? { panic("DB_Query: Problem with negative direction"); } chunk = (cstring *) &iidx[idx[Index]]; // point at the chunk record = (cstring *) &chunk->buf[chunk->buf[1]+4]; // point at the dbc if ((!chunk->buf[0]) && (!chunk->buf[1]) && // if first node ((partab.jobtab->last_block_flags & GL_TOP_DEFINED) == 0)) { buf[0] = '\0'; // null terminate ret if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return 0; // and return } } // end backwards else // it's forward { s = Get_data(0); // try to find that if ((s < 0) && (s != -ERRM7)) // check for errors { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return s; // and return the error } if ((level == 0) && (s == -ERRM7)) // if no such global { buf[0] = '\0'; // null terminate ret if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } return 0; // and return } if ((s < 0) && (!db_var.slen)) { Index++; } if ((Index > blk[level]->mem->last_idx) || (s >= 0)) // want next one { s = Locate_next(); // point at next if (s < 0) // not found or error { if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } buf[0] = '\0'; // null terminate ret if (s == -ERRM7) // undefined? { s = 0; // yes - clear it } return s; // done } } } for (i = 10; i <= Index; i++) // scan to current { chunk = (cstring *) &iidx[idx[i]]; // point at the chunk bcopy(&chunk->buf[2], &keybuf[chunk->buf[0]+1], chunk->buf[1]); // update the key keybuf[0] = chunk->buf[0] + chunk->buf[1]; // and the size } if (curr_lock) // if locked { SemOp( SEM_GLOBAL, -curr_lock); // release global lock } db_var.uci = var->uci; // copy db_var.volset = var->volset; // original & new db_var.name.var_qu = var->name.var_qu; // data db_var.slen = keybuf[0]; // to bcopy(&keybuf[1], &db_var.key[0], keybuf[0]); // db_var return UTIL_String_Mvar(&db_var, buf, 9999); // convert and return }
int CBD1 semop(int semid, struct sembuf semoparray[], size_t nsops) { int i; int piid; DWORD procid; HANDLE hIpct = NULL; IPCT *ipct = NULL; // StartIPCD(); if (semid<0 || semid>=MAXNOOFIPC) { errno=EINVAL; return -1; } if (GetIPCT(&hIpct, &ipct)<0) { errno=EFAULT; return -1; } if (ipct->semt[semid].key<0) { procid=GetCurrentProcessId(); piid=FindPINFO(OPT_SEM, procid, ipct); if (piid>=0) { for (i=0; i<MAXNSEM; i++) ipct->pseminfo[piid].semadj[semid][i]=0; ipct->pseminfo[piid].semid[semid]=0; InitPINFO(OPT_SEM, piid, ipct); } errno=EINVAL; FreeIPCT(hIpct, ipct); return -1; } procid=GetCurrentProcessId(); piid=FindPINFO(OPT_SEM, procid, ipct); if (piid<0) { piid=GetEmptyPINFO(OPT_SEM, ipct); if (piid<0) { errno=ENOSPC; FreeIPCT(hIpct, ipct); return -1; } ipct->pseminfo[piid].procid=procid; // ipct->pseminfo[piid].semid[semid]=1; } for (i=0; i<(int)nsops; i++) { if (SemOp(semid, &semoparray[i], procid, piid, ipct)<0) { // ipct->pseminfo[piid].semid[semid]=0; // for (j=0; j<MAXNSEM; j++) // ipct->pseminfo[piid].semadj[semid][j]=0; // InitPINFO(OPT_SEM, piid, ipct); FreeIPCT(hIpct, ipct); return -1; } } // ipct->pseminfo[piid].semid[semid]=0; // for (j=0; j<MAXNSEM; j++) // ipct->pseminfo[piid].semadj[semid][j]=0; // InitPINFO(OPT_SEM, piid, ipct); FreeIPCT(hIpct, ipct); return 0; }