Ejemplo n.º 1
0
static bool
_match_daemon(const char *path, const char *file, RC_STRINGLIST *match)
{
	char *line = NULL;
	size_t len = 0;
	char ffile[PATH_MAX];
	FILE *fp;
	RC_STRING *m;

	snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
	fp = fopen(ffile, "r");

	if (!fp)
		return false;

	while ((rc_getline(&line, &len, fp))) {
		TAILQ_FOREACH(m, match, entries)
		    if (strcmp(line, m->value) == 0) {
			    TAILQ_REMOVE(match, m, entries);
			    break;
		    }
		if (!TAILQ_FIRST(match))
			break;
	}
	fclose(fp);
	free(line);
	if (TAILQ_FIRST(match))
		return false;
	return true;
}
Ejemplo n.º 2
0
static bool
file_regex(const char *file, const char *regex)
{
	FILE *fp;
	char *line = NULL;
	size_t len = 0;
	regex_t re;
	bool retval = true;
	int result;

	if (!(fp = fopen(file, "r")))
		return false;

	if ((result = regcomp(&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) {
		fclose(fp);
		line = xmalloc(sizeof(char) * BUFSIZ);
		regerror(result, &re, line, BUFSIZ);
		fprintf(stderr, "file_regex: %s", line);
		free(line);
		return false;
	}

	while ((rc_getline(&line, &len, fp))) {
		char *str = line;
		/* some /proc files have \0 separated content so we have to
		   loop through the 'line' */
		do {
			if (regexec(&re, str, 0, NULL, 0) == 0)
				goto found;
			str += strlen(str) + 1;
			/* len is the size of allocated buffer and we don't
			   want call regexec BUFSIZE times. find next str */
			while (str < line + len && *str == '\0')
				str++;
		} while (str < line + len);
	}
	retval = false;
found:
	fclose(fp);
	free(line);
	regfree(&re);

	return retval;
}
Ejemplo n.º 3
0
RC_PIDLIST *
rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
{
	DIR *procdir;
	struct dirent *entry;
	FILE *fp;
	bool container_pid = false;
	bool openvz_host = false;
	char *line = NULL;
	size_t len = 0;
	pid_t p;
	char buffer[PATH_MAX];
	struct stat sb;
	pid_t runscript_pid = 0;
	char *pp;
	RC_PIDLIST *pids = NULL;
	RC_PID *pi;

	if ((procdir = opendir("/proc")) == NULL)
		return NULL;

	/*
	  We never match RC_RUNSCRIPT_PID if present so we avoid the below
	  scenario

	  /etc/init.d/ntpd stop does
	  start-stop-daemon --stop --name ntpd
	  catching /etc/init.d/ntpd stop

	  nasty
	*/

	if ((pp = getenv("RC_RUNSCRIPT_PID"))) {
		if (sscanf(pp, "%d", &runscript_pid) != 1)
			runscript_pid = 0;
	}

	/*
	If /proc/self/status contains EnvID: 0, then we are an OpenVZ host,
	and we will need to filter out processes that are inside containers
	from our list of pids.
	*/

	if (exists("/proc/self/status")) {
		fp = fopen("/proc/self/status", "r");
		if (fp) {
			while (! feof(fp)) {
				rc_getline(&line, &len, fp);
				if (strncmp(line, "envID:\t0", 8) == 0) {
					openvz_host = true;
					break;
				}
			}
			fclose(fp);
		}
	}

	while ((entry = readdir(procdir)) != NULL) {
		if (sscanf(entry->d_name, "%d", &p) != 1)
			continue;
		if (runscript_pid != 0 && runscript_pid == p)
			continue;
		if (pid != 0 && pid != p)
			continue;
		if (uid) {
			snprintf(buffer, sizeof(buffer), "/proc/%d", p);
			if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
				continue;
		}
		if (exec && !pid_is_exec(p, exec))
			continue;
		if (argv &&
		    !pid_is_argv(p, (const char *const *)argv))
			continue;
		/* If this is an OpenVZ host, filter out container processes */
		if (openvz_host) {
			snprintf(buffer, sizeof(buffer), "/proc/%d/status", p);
			if (exists(buffer)) {
				fp = fopen(buffer, "r");
				if (! fp)
					continue;
				while (! feof(fp)) {
					rc_getline(&line, &len, fp);
					if (strncmp(line, "envID:", 6) == 0) {
						container_pid = ! (strncmp(line, "envID:\t0", 8) == 0);
						break;
					}
				}
				fclose(fp);
			}
		}
		if (container_pid)
			continue;
		if (!pids) {
			pids = xmalloc(sizeof(*pids));
			LIST_INIT(pids);
		}
		pi = xmalloc(sizeof(*pi));
		pi->pid = p;
		LIST_INSERT_HEAD(pids, pi, entries);
	}
	if (line != NULL)
		free(line);
	closedir(procdir);
	return pids;
}
Ejemplo n.º 4
0
bool
rc_service_daemons_crashed(const char *service)
{
	char dirpath[PATH_MAX];
	DIR *dp;
	struct dirent *d;
	char *path = dirpath;
	FILE *fp;
	char *line = NULL;
	size_t len = 0;
	char **argv = NULL;
	char *exec = NULL;
	char *name = NULL;
	char *pidfile = NULL;
	pid_t pid = 0;
	RC_PIDLIST *pids;
	RC_PID *p1;
	RC_PID *p2;
	char *p;
	char *token;
	bool retval = false;
	RC_STRINGLIST *list = NULL;
	RC_STRING *s;
	size_t i;
	char *ch_root;
	char *spidfile;

	path += snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
	    basename_c(service));

	if (!(dp = opendir(dirpath)))
		return false;

	while ((d = readdir(dp))) {
		if (d->d_name[0] == '.')
			continue;

		snprintf(path, sizeof(dirpath) - (path - dirpath), "/%s",
		    d->d_name);
		fp = fopen(dirpath, "r");
		if (!fp)
			break;

		while ((rc_getline(&line, &len, fp))) {
			p = line;
			if ((token = strsep(&p, "=")) == NULL || !p)
				continue;

			if (!*p)
				continue;

			if (strcmp(token, "exec") == 0) {
				if (exec)
					free(exec);
				exec = xstrdup(p);
			} else if (strncmp(token, "argv_", 5) == 0) {
				if (!list)
					list = rc_stringlist_new();
				rc_stringlist_add(list, p);
			} else if (strcmp(token, "name") == 0) {
				if (name)
					free(name);
				name = xstrdup(p);
			} else if (strcmp(token, "pidfile") == 0) {
				pidfile = xstrdup(p);
				break;
			}
		}
		fclose(fp);

		ch_root = rc_service_value_get(basename_c(service), "chroot");
		spidfile = pidfile;
		if (ch_root && pidfile) {
			spidfile = xmalloc(strlen(ch_root) + strlen(pidfile) + 1);
			strcpy(spidfile, ch_root);
			strcat(spidfile, pidfile);
			free(pidfile);
			pidfile = spidfile;
		}

		pid = 0;
		if (pidfile) {
			retval = true;
			if ((fp = fopen(pidfile, "r"))) {
				if (fscanf(fp, "%d", &pid) == 1)
					retval = false;
				fclose(fp);
			}
			free(pidfile);
			pidfile = NULL;

			/* We have the pid, so no need to match
			   on exec or name */
			free(exec);
			exec = NULL;
			free(name);
			name = NULL;
		} else {
			if (exec) {
				if (!list)
					list = rc_stringlist_new();
				if (!TAILQ_FIRST(list))
					rc_stringlist_add(list, exec);

				free(exec);
				exec = NULL;
			}

			if (list) {
				/* We need to flatten our linked list
				   into an array */
				i = 0;
				TAILQ_FOREACH(s, list, entries)
				    i++;
				argv = xmalloc(sizeof(char *) * (i + 1));
				i = 0;
				TAILQ_FOREACH(s, list, entries)
				    argv[i++] = s->value;
				argv[i] = '\0';
			}
		}

		if (!retval) {
			if (pid != 0) {
				if (kill(pid, 0) == -1 && errno == ESRCH)
					retval = true;
			} else if ((pids = rc_find_pids(exec,
				    (const char *const *)argv,
				    0, pid)))
			{
				p1 = LIST_FIRST(pids);
				while (p1) {
					p2 = LIST_NEXT(p1, entries);
					free(p1);
					p1 = p2;
				}
				free(pids);
			} else
				retval = true;
		}
		rc_stringlist_free(list);
		list = NULL;
		free(argv);
		argv = NULL;
		free(exec);
		exec = NULL;
		free(name);
		name = NULL;
		if (retval)
			break;
	}
	closedir(dp);
	free(line);

	return retval;
}