void env_filter(void) { RC_STRINGLIST *env_allow; RC_STRINGLIST *profile; RC_STRINGLIST *env_list; RC_STRING *env; char *e; size_t i = 0; /* Add the user defined list of vars */ env_allow = rc_stringlist_split(rc_conf_value("rc_env_allow"), " "); /* * If '*' is an entry in rc_env_allow, do nothing as we are to pass * through all environment variables. */ if (rc_stringlist_find(env_allow, "*")) return; profile = rc_config_load(RC_PROFILE_ENV); /* Copy the env and work from this so we can manipulate it safely */ env_list = rc_stringlist_new(); while (environ && environ[i]) { env = rc_stringlist_add(env_list, environ[i++]); e = strchr(env->value, '='); if (e) *e = '\0'; } TAILQ_FOREACH(env, env_list, entries) { /* Check the whitelist */ for (i = 0; env_whitelist[i]; i++) { if (strcmp(env_whitelist[i], env->value) == 0) break; } if (env_whitelist[i]) continue; /* Check our user defined list */ if (rc_stringlist_find(env_allow, env->value)) continue; /* OK, not allowed! */ unsetenv(env->value); } /* Now add anything missing from the profile */ TAILQ_FOREACH(env, profile, entries) { e = strchr(env->value, '='); *e = '\0'; if (!getenv(env->value)) setenv(env->value, e + 1, 1); }
void env_filter(void) { RC_STRINGLIST *env_allow; RC_STRINGLIST *profile; RC_STRINGLIST *env_list; RC_STRING *env; char *e; size_t i = 0; profile = rc_config_load(RC_PROFILE_ENV); /* Copy the env and work from this so we can manipulate it safely */ env_list = rc_stringlist_new(); while (environ && environ[i]) { env = rc_stringlist_add(env_list, environ[i++]); e = strchr(env->value, '='); if (e) *e = '\0'; } if (rc_conf_value("rc_env_allow") != "*") { /* Add the user defined list of vars */ env_allow = rc_stringlist_split(rc_conf_value("rc_env_allow"), " "); TAILQ_FOREACH(env, env_list, entries) { /* Check the whitelist */ for (i = 0; env_whitelist[i]; i++) { if (strcmp(env_whitelist[i], env->value) == 0) break; } if (env_whitelist[i]) continue; /* Check our user defined list */ if (rc_stringlist_find(env_allow, env->value)) continue; /* OK, not allowed! */ unsetenv(env->value); } }
static int signal_processes(int sig, RC_STRINGLIST *omits, bool dryrun) { sigset_t signals; sigset_t oldsigs; DIR *dir; struct dirent *d; char *buf = NULL; pid_t pid; int sendcount = 0; kill(-1, SIGSTOP); sigfillset(&signals); sigemptyset(&oldsigs); sigprocmask(SIG_SETMASK, &signals, &oldsigs); /* * Open the /proc directory. * CWD must be /proc to avoid problems if / is affected by the killing * (i.e. depends on fuse). */ if (chdir("/proc") == -1) { syslog(LOG_ERR, "chdir /proc failed"); sigprocmask(SIG_SETMASK, &oldsigs, NULL); kill(-1, SIGCONT); return -1; } dir = opendir("."); if (!dir) { syslog(LOG_ERR, "cannot opendir(/proc)"); sigprocmask(SIG_SETMASK, &oldsigs, NULL); kill(-1, SIGCONT); return -1; } /* Walk through the directory. */ while ((d = readdir(dir)) != NULL) { /* Is this a process? */ pid = (pid_t) atoi(d->d_name); if (pid == 0) continue; /* Is this a process we have been requested to omit? */ if (buf) { free(buf); buf = NULL; } xasprintf(&buf, "%d", pid); if (rc_stringlist_find(omits, buf)) continue; /* Is this process in our session? */ if (getsid(getpid()) == getsid(pid)) continue; /* Is this a kernel thread? */ if (!is_user_process(pid)) continue; if (dryrun) einfo("Would send signal %d to process %d", sig, pid); else if (kill(pid, sig) == 0) sendcount++; } closedir(dir); sigprocmask(SIG_SETMASK, &oldsigs, NULL); kill(-1, SIGCONT); return sendcount; }
static void do_stop_services(RC_STRINGLIST *types_n, RC_STRINGLIST *start_services, const RC_STRINGLIST *stop_services, const RC_DEPTREE *deptree, const char *newlevel, bool parallel, bool going_down) { pid_t pid; RC_STRING *service, *svc1, *svc2; RC_STRINGLIST *deporder, *tmplist, *kwords; RC_SERVICE state; RC_STRINGLIST *nostop; bool crashed, nstop; if (!types_n) { types_n = rc_stringlist_new(); rc_stringlist_add(types_n, "needsme"); } crashed = rc_conf_yesno("rc_crashed_stop"); nostop = rc_stringlist_split(rc_conf_value("rc_nostop"), " "); TAILQ_FOREACH_REVERSE(service, stop_services, rc_stringlist, entries) { state = rc_service_state(service->value); if (state & RC_SERVICE_STOPPED || state & RC_SERVICE_FAILED) continue; /* Sometimes we don't ever want to stop a service. */ if (rc_stringlist_find(nostop, service->value)) { rc_service_mark(service->value, RC_SERVICE_FAILED); continue; } kwords = rc_deptree_depend(deptree, service->value, "keyword"); if (rc_stringlist_find(kwords, "-stop") || rc_stringlist_find(kwords, "nostop") || (going_down && (rc_stringlist_find(kwords, "-shutdown") || rc_stringlist_find(kwords, "noshutdown")))) nstop = true; else nstop = false; rc_stringlist_free(kwords); if (nstop) { rc_service_mark(service->value, RC_SERVICE_FAILED); continue; } /* If the service has crashed, skip futher checks and just stop it */ if (crashed && rc_service_daemons_crashed(service->value)) goto stop; /* If we're in the start list then don't bother stopping us */ svc1 = rc_stringlist_find(start_services, service->value); if (svc1) { if (newlevel && strcmp(runlevel, newlevel) != 0) { /* So we're in the start list. But we should * be stopped if we have a runlevel * configuration file for either the current * or next so we use the correct one. */ if (!runlevel_config(service->value,runlevel) && !runlevel_config(service->value,newlevel)) continue; } else continue; } /* We got this far. Last check is to see if any any service * that going to be started depends on us */ if (!svc1) { tmplist = rc_stringlist_new(); rc_stringlist_add(tmplist, service->value); deporder = rc_deptree_depends(deptree, types_n, tmplist, newlevel ? newlevel : runlevel, RC_DEP_STRICT | RC_DEP_TRACE); rc_stringlist_free(tmplist); svc2 = NULL; TAILQ_FOREACH(svc1, deporder, entries) { svc2 = rc_stringlist_find(start_services, svc1->value); if (svc2) break; }