env_h env_make( char **env_strings ) { env_s *ep ; char **pp ; for ( pp = env_strings ; *pp ; pp++ ) ; ep = alloc_env( (unsigned) (pp-env_strings) ) ; if ( ep == NULL ) { env_errno = ENV_ENOMEM ; return( ENV_NULL ) ; } for ( pp = env_strings ; *pp ; pp++ ) { char *p = new_string( *pp ) ; if ( p == NULL ) { env_destroy( ep ) ; env_errno = ENV_ENOMEM ; return( ENV_NULL ) ; } ep->vars[ ep->n_vars++ ] = p ; } return( ep ) ; }
env_h env_create( const env_h init_env ) { unsigned u ; env_s *ep ; unsigned max_vars ; if ( init_env == ENV_NULL ) max_vars = INITIAL_VARS ; else max_vars = init_env->n_vars + 5 ; ep = alloc_env( max_vars ) ; if ( ep == NULL ) { env_errno = ENV_ENOMEM ; return( ENV_NULL ) ; } if ( init_env == ENV_NULL ) return( ep ) ; for ( u = 0, ep->n_vars = 0 ; u < init_env->n_vars ; u++, ep->n_vars++ ) { ep->vars[ ep->n_vars ] = new_string( init_env->vars[ u ] ) ; if ( ep->vars[ ep->n_vars ] == NULL ) { env_destroy( ep ) ; env_errno = ENV_ENOMEM ; return( ENV_NULL ) ; } } return( ep ) ; }
static dumb_ptr<env_t> clone_env(dumb_ptr<env_t> src) { dumb_ptr<env_t> retval = alloc_env(src->base_env); for (int i = 0; i < src->base_env->varv.size(); i++) magic_copy_var(&retval->varu[i], &src->varu[i]); return retval; }
struct global_state *new_global_state(struct machine_specification *machine) /* Returns: A new global state for a motlle interpreter for machine */ { struct global_state *gstate; GCPRO1(machine); gstate = (struct global_state *)allocate_record(type_vector, 5); GCPRO1(gstate); gstate->modules = alloc_table(DEF_TABLE_SIZE); gstate->mvars = alloc_vector(GLOBAL_SIZE); gstate->global = alloc_table(GLOBAL_SIZE); gstate->environment = alloc_env(GLOBAL_SIZE); gstate->machine = machine; GCPOP(2); return gstate; }
/** * Choose what action should be taken according to passed settings. * * @1 Hotplug settings * @2 Event structure * * Returns: void * */ void action_perform(struct settings_t *settings, struct uevent_t *event) { int i; char **env; env = xmalloc(sizeof(char *) * event->env_vars_c); for (i = 0; i < event->env_vars_c; i++) { env[i] = alloc_env(event->env_vars[i].key, event->env_vars[i].value); putenv(env[i]); } if (settings->dumb == 0) { ruleset_execute(&settings->rules, event, settings); } else { action_dumb(settings, event); } for (i = 0; i < event->env_vars_c; i++) { unsetenv(event->env_vars[i].key); free(env[i]); } free(env); }
dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell, dumb_ptr<map_session_data> caster, int spellpower, XString param) { dumb_ptr<env_t> env = alloc_env(conf); switch (spell->spellarg_ty) { case SPELLARG::STRING: set_env_string(spell->arg, dumb_string::copys(param)); break; case SPELLARG::PC: { CharName name = stringish<CharName>(param); dumb_ptr<map_session_data> subject = map_nick2sd(name); if (!subject) subject = caster; set_env_entity(spell->arg, subject); break; } case SPELLARG::NONE: break; default: FPRINTF(stderr, "Unexpected spellarg type %d\n", spell->spellarg_ty); } set_env_entity(VAR_CASTER, caster); set_env_int(VAR_SPELLPOWER, spellpower); set_env_spell(VAR_SPELL, spell); return env; }
long xexec(WORD flag, char *path, char *tail, char *env) { PD *p; PGMHDR01 hdr; MD *m, *env_md; LONG rc; long max, needed; FH fh; KDEBUG(("BDOS xexec: flag or mode = %d\n",flag)); /* first branch - actions that do not require loading files */ switch(flag) { #if DETECT_NATIVE_FEATURES case PE_RELOCATE: /* internal use only, see bootstrap() in bios/bios.c */ p = (PD *) tail; rc = kpgm_relocate(p, (long)path); if (rc) { KDEBUG(("BDOS xexec: kpgm_reloc returned %ld (0x%lx)\n",rc,rc)); return rc; } /* invalidate instruction cache for the TEXT segment only * programs that jump into their DATA, BSS or HEAP are kindly invited * to do their cache management themselves. */ invalidate_instruction_cache( p+1, p->p_tlen); return (long)p; #endif case PE_BASEPAGE: /* just create a basepage */ path = (char *) 0L; /* (same as basepage+flags with flags set to zero) */ /* drop thru */ case PE_BASEPAGEFLAGS: /* create a basepage, respecting the flags */ env_md = alloc_env(env); if (env_md == NULL) { KDEBUG(("BDOS xexec: not enough memory!\n")); return ENSMEM; } m = alloc_tpa((ULONG)path,sizeof(PD),&max); if (m == NULL) { /* not even enough memory for basepage */ freeit(env_md, &pmd); KDEBUG(("BDOS xexec: No memory for basepage\n")); return ENSMEM; } p = (PD *) m->m_start; /* memory ownership */ m->m_own = env_md->m_own = run; /* initialize the PD */ init_pd_fields(p, tail, max, env_md); p->p_flags = (ULONG)path; /* set the flags */ init_pd_files(p); return (long)p; case PE_GOTHENFREE: /* set the owner of the memory to be this process */ p = (PD *) tail; set_owner(p, p, find_mpb(p)); set_owner(p->p_env, p, find_mpb(p->p_env)); /* fall through */ case PE_GO: p = (PD *) tail; proc_go(p); /* should not return ? */ return (long)p; case PE_LOADGO: case PE_LOAD: break; default: return EINVFN; } /* we now need to load a file */ KDEBUG(("BDOS xexec: trying to find the command ...\n")); if (ixsfirst(path,0,0L)) { KDEBUG(("BDOS xexec: command %s not found!!!\n",path)); return EFILNF; /* file not found */ } /* load the header - if I/O error occurs now, the longjmp in rwabs will * jump directly back to bdosmain.c, which is not a problem because * we haven't allocated anything yet. */ rc = kpgmhdrld(path, &hdr, &fh); if (rc) { KDEBUG(("BDOS xexec: kpgmhdrld returned %ld (0x%lx)\n",rc,rc)); return rc; } /* allocate the environment first, always in ST RAM */ env_md = alloc_env(env); if (env_md == NULL) { KDEBUG(("BDOS xexec: not enough memory!\n")); return ENSMEM; } /* allocate the basepage depending on memory policy */ needed = hdr.h01_tlen + hdr.h01_dlen + hdr.h01_blen + sizeof(PD); m = alloc_tpa(hdr.h01_flags,needed,&max); /* if failed, free env_md and return */ if (m == NULL) { KDEBUG(("BDOS xexec: no memory for TPA\n")); freeit(env_md, &pmd); return ENSMEM; } p = (PD *) m->m_start; /* memory ownership - the owner is either the new process being created, * or the parent */ if (flag == PE_LOADGO) { m->m_own = env_md->m_own = p; } else { m->m_own = env_md->m_own = run; } /* initialize the fields in the PD structure */ init_pd_fields(p, tail, max, env_md); /* set the flags (must be done after init_pd) */ p->p_flags = hdr.h01_flags; /* use static variable to avoid the obscure longjmp warning */ cur_p = p; cur_m = m; cur_env_md = env_md; /* we have now allocated memory, so we need to intercept longjmp. */ memcpy(bakbuf, errbuf, sizeof(errbuf)); if (setjmp(errbuf)) { KDEBUG(("Error and longjmp in xexec()!\n")); /* free any memory allocated yet */ freeit(cur_env_md, &pmd); freeit(cur_m, find_mpb(cur_m->m_start)); /* we still have to jump back to bdosmain.c so that the proper error * handling can occur. */ longjmp(bakbuf, 1); } /* now, load the rest of the program and perform relocation */ rc = kpgmld(cur_p, fh, &hdr); if (rc) { KDEBUG(("BDOS xexec: kpgmld returned %ld (0x%lx)\n",rc,rc)); /* free any memory allocated yet */ freeit(cur_env_md, &pmd); freeit(cur_m, find_mpb(cur_m->m_start)); return rc; } /* at this point the program has been correctly loaded in memory, and * more I/O errors cannot occur, so it is safe now to finish initializing * the new process. */ init_pd_files(cur_p); /* invalidate instruction cache for the TEXT segment only * programs that jump into their DATA, BSS or HEAP are kindly invited * to do their cache management themselves. */ invalidate_instruction_cache(((char *)cur_p) + sizeof(PD), hdr.h01_tlen); if (flag != PE_LOAD) proc_go(cur_p); return (long)cur_p; }
int main() { /* using NAME_MAX prevents EINVAL on read() (twice for UTF-16 on NTFS) */ char buf[sizeof(struct inotify_event) + NAME_MAX*2 + 1]; char *crtpath, *qpath, *rqpath, *looppath, *lsthost, *lstport; int sz, offset, rereg, evqok, retryid; struct inotify_event *iev; double retrytmout, lastclock; /* init logging */ syslog_init(); /* extract environment */ crtpath = alloc_env(CABLE_CERTS, "/" CERTS_NAME); qpath = alloc_env(CABLE_QUEUES, "/" QUEUE_NAME); rqpath = alloc_env(CABLE_QUEUES, "/" RQUEUE_NAME); looppath = alloc_env(CABLE_HOME, "/" LOOP_NAME); lsthost = alloc_env(CABLE_HOST, ""); lstport = alloc_env(CABLE_PORT, ""); /* initialize rng */ if (!rand_init()) warning("failed to initialize RNG"); /* initialize process accounting */ if (!init_process_acc()) warning("failed to initialize process accounting"); /* initialize webserver */ if (!init_server(crtpath, qpath, rqpath, lsthost, lstport)) { flog(LOG_ERR, "failed to initialize webserver"); return EXIT_FAILURE; } /* try to reregister watches as long as no signal caught */ for (lastclock = getmontime(), retryid = 0; !stop_requested(); ) { /* support empty CABLE_NOLOOP when testing, to act as pure server */ #ifdef TESTING if (getenv("CABLE_NOLOOP")) { sleepsec(RETRY_TMOUT); continue; } #endif wait_reg_watches(qpath, rqpath); /* read events as long as no signal caught and no unmount / move_self / etc. events read */ for (rereg = evqok = 0; !stop_requested() && !rereg; ) { /* wait for an event, or timeout (later blocking read() results in error) */ retrytmout = RETRY_TMOUT + RETRY_TMOUT * (rand_shift() / 2); if (wait_read(inotfd, retrytmout - (getmontime() - lastclock))) { /* read events (non-blocking), taking care to handle interrupts due to signals */ if ((sz = read(inotfd, buf, sizeof(buf))) == -1 && errno != EINTR) { /* happens buffer is too small (e.g., NTFS + 255 unicode chars) */ warning("error while reading from inotify queue"); rereg = 1; } /* process all events in buffer, sz = -1 and 0 are automatically ignored */ for (offset = 0; offset < sz && !stop_requested() && !rereg; evqok = 1) { /* get handler to next event in read buffer, and update offset */ iev = (struct inotify_event*) (buf + offset); offset += sizeof(struct inotify_event) + iev->len; /* IN_IGNORED is triggered by watched directory removal / fs unmount IN_MOVE_SELF is only triggered by move of actual watched directory (i.e., not its parent) */ if ((iev->mask & (IN_IGNORED | IN_UNMOUNT | IN_Q_OVERFLOW | IN_MOVE_SELF))) rereg = 1; /* ignore non-subdirectory events, and events with incorrect name */ else if (iev->len > 0 && (iev->mask & IN_ISDIR) && is_msgdir(iev->name)) { assert(iev->wd == inotqwd || iev->wd == inotrqwd); if (iev->wd == inotqwd || iev->wd == inotrqwd) { /* stop can be indicated here (while waiting for less processes) */ const char *qtype = (iev->wd == inotqwd) ? QUEUE_NAME : RQUEUE_NAME; run_loop(qtype, iev->name, looppath); } else flog(LOG_WARNING, "unknown watch descriptor"); } } } /* if sufficient time passed since last retries, retry again */ if (!stop_requested() && getmontime() - lastclock >= retrytmout) { /* alternate between queue dirs to prevent lock starvation on self-send */ if ((retryid ^= 1)) retry_dir(QUEUE_NAME, qpath, looppath); else retry_dir(RQUEUE_NAME, rqpath, looppath); lastclock = getmontime(); /* inotify is apparently unreliable on fuse, so reregister when no events */ if (!evqok) rereg = 1; evqok = 0; } } } unreg_watches(); if (!shutdown_server()) flog(LOG_WARNING, "failed to shutdown webserver"); dealloc_env(lstport); dealloc_env(lsthost); dealloc_env(looppath); dealloc_env(rqpath); dealloc_env(qpath); dealloc_env(crtpath); flog(LOG_INFO, "exiting"); closelog(); return EXIT_SUCCESS; }
/** * Executes a rule. Contains evaluation of all conditions prior * to execution. * * @1 Hotplug event structure * @2 The rule to be executed * * Returns: 0 if success, -1 if the whole event is to be * discared, 1 if bail out of this particular rule was required */ int rule_execute(struct hotplug2_event_t *event, struct rule_t *rule) { int i, last_rv, res; char **env; for (i = 0; i < rule->conditions_c; i++) { if (rule_condition_eval(event, &(rule->conditions[i])) != EVAL_MATCH) return 0; } res = 0; last_rv = 0; env = xmalloc(sizeof(char *) * event->env_vars_c); for (i = 0; i < event->env_vars_c; i++) { env[i] = alloc_env(event->env_vars[i].key, event->env_vars[i].value); putenv(env[i]); } for (i = 0; i < rule->actions_c; i++) { switch (rule->actions[i].type) { case ACT_STOP_PROCESSING: res = 1; break; case ACT_STOP_IF_FAILED: if (last_rv != 0) res = 1; break; case ACT_NEXT_EVENT: res = -1; break; case ACT_NEXT_IF_FAILED: if (last_rv != 0) res = -1; break; case ACT_MAKE_DEVICE: last_rv = make_dev_from_event(event, rule->actions[i].parameter[0], strtoul(rule->actions[i].parameter[1], NULL, 0)); break; case ACT_CHMOD: last_rv = chmod_file(event, rule->actions[i].parameter[0], rule->actions[i].parameter[1]); break; case ACT_CHOWN: case ACT_CHGRP: last_rv = chown_chgrp(event, rule->actions[i].type, rule->actions[i].parameter[0], rule->actions[i].parameter[1]); break; case ACT_SYMLINK: last_rv = make_symlink(event, rule->actions[i].parameter[0], rule->actions[i].parameter[1]); break; case ACT_RUN_SHELL: last_rv = exec_shell(event, rule->actions[i].parameter[0]); break; case ACT_RUN_NOSHELL: last_rv = exec_noshell(event, rule->actions[i].parameter[0], rule->actions[i].parameter); break; case ACT_SETENV: last_rv = setenv(rule->actions[i].parameter[0], rule->actions[i].parameter[1], 1); break; case ACT_REMOVE: last_rv = unlink(rule->actions[i].parameter[0]); rmdir_p(rule->actions[i].parameter[0]); break; case ACT_DEBUG: print_debug(event); last_rv = 0; break; } if (res != 0) break; } for (i = 0; i < event->env_vars_c; i++) { unsetenv(event->env_vars[i].key); free(env[i]); } free(env); return res; }
long xexec(WORD flag, char *path, char *tail, char *env) { PD *p; PGMHDR01 hdr; MD *m, *env_md; LONG rc; long max, needed; FH fh; D(("BDOS: xexec - flag or mode = %d\n", flag)); /* first branch - actions that do not require loading files */ switch(flag) { case PE_RELOCATE: p = (PD *) tail; rc = kpgm_relocate(p, (long)path); if(rc) { D(("BDOS: xexec - kpgm_relloc returned %ld (0x%lx)\n", rc, rc)); return(rc); } /* invalidate instruction cache for the TEXT segment only * programs that jump into their DATA, BSS or HEAP are kindly invited * to do their cache management themselves. */ invalidate_icache( p+1, p->p_tlen); return (long) p; case PE_BASEPAGE: /* just create a basepage */ env_md = alloc_env(env); if(env_md == NULL) { D(("xexec: Not Enough Memory!\n")); return(ENSMEM); } max = (long) ffit(-1L, &pmd); if(max >= sizeof(PD)) { m = ffit(max, &pmd); p = (PD *) m->m_start; } else { /* not even enough memory for basepage */ freeit(env_md, &pmd); D(("xexec: No memory for TPA\n")); return(ENSMEM); } /* memory ownership */ m->m_own = env_md->m_own = run; /* initialize the PD */ init_pd_fields(p, tail, max, env_md); init_pd_files(p); return (long) p; case PE_GOTHENFREE: /* set the owner of the memory to be this process */ p = (PD *) tail; set_owner(p, p, find_mpb(p)); set_owner(p->p_env, p, find_mpb(p->p_env)); /* fall through */ case PE_GO: p = (PD *) tail; proc_go(p); /* should not return ? */ return (long)p; case PE_LOADGO: case PE_LOAD: break; default: return EINVFN; } /* we now need to load a file */ D(("BDOS: xexec - trying to find the command ...\n")); if (ixsfirst(path,0,0L)) { D(("BDOS: Command %s not found!!!\n", path)); return(EFILNF); /* file not found */ } /* load the header - if IO error occurs now, the longjmp in rwabs will * jump directly back to bdosmain.c, which is not a problem because * we haven't allocated anything yet. */ rc = kpgmhdrld(path, &hdr, &fh); if(rc) { D(("BDOS: xexec - kpgmhdrld returned %ld (0x%lx)\n", rc, rc)); return(rc); } /* allocate the environment first, always in ST RAM */ env_md = alloc_env(env); if ( env_md == NULL ) { D(("xexec: Not Enough Memory!\n")); return(ENSMEM); } /* allocate the basepage depending on memory policy */ needed = hdr.h01_tlen + hdr.h01_dlen + hdr.h01_blen + sizeof(PD); max = 0; /* first try */ p = NULL; m = NULL; #if CONF_WITH_ALT_RAM if(has_alt_ram && (hdr.h01_flags & PF_TTRAMLOAD)) { /* use alternate ram preferably */ max = (long) ffit(-1L, &pmdalt); if(max >= needed) { m = ffit(max, &pmdalt); p = (PD *) m->m_start; } } #endif /* second try */ if(p == NULL) { max = (long) ffit(-1L, &pmd); if(max >= needed) { m = ffit(max, &pmd); p = (PD *) m->m_start; } } /* still failed? free env_md and return */ if(p == NULL) { D(("xexec: No memory for TPA\n")); freeit(env_md, &pmd); return(ENSMEM); } assert(m != NULL); /* memory ownership - the owner is either the new process being created, * or the parent */ if(flag == PE_LOADGO) { m->m_own = env_md->m_own = p; } else { m->m_own = env_md->m_own = run; } /* initialize the fields in the PD structure */ init_pd_fields(p, tail, max, env_md); /* set the flags (must be done after init_pd) */ p->p_flags = hdr.h01_flags; /* use static variable to avoid the obscure longjmp warning */ cur_p = p; cur_m = m; cur_env_md = env_md; /* we have now allocated memory, so we need to intercept longjmp. */ memcpy(bakbuf, errbuf, sizeof(errbuf)); if ( setjmp(errbuf) ) { kprintf("Error and longjmp in xexec()!\n"); /* free any memory allocated yet */ freeit(cur_env_md, &pmd); freeit(cur_m, find_mpb((void *)cur_m->m_start)); /* we still have to jump back to bdosmain.c so that the proper error * handling can occur. */ longjmp(bakbuf, 1); } /* now, load the rest of the program and perform relocation */ rc = kpgmld(cur_p, fh, &hdr); if ( rc ) { D(("BDOS: xexec - kpgmld returned %ld (0x%lx)\n", rc, rc)); /* free any memory allocated yet */ freeit(cur_env_md, &pmd); freeit(cur_m, find_mpb((void *)cur_m->m_start)); return rc; } /* at this point the program has been correctly loaded in memory, and * more IO errors cannot occur, so it is safe now to finish initializing * the new process. */ init_pd_files(cur_p); /* invalidate instruction cache for the TEXT segment only * programs that jump into their DATA, BSS or HEAP are kindly invited * to do their cache management themselves. */ invalidate_icache(((char *)cur_p) + sizeof(PD), hdr.h01_tlen); if(flag != PE_LOAD) proc_go(cur_p); return (long) cur_p; }