Make rc_getline private and save it's buffer so it's sort of like getline from glibc.
This commit is contained in:
		@@ -311,7 +311,8 @@ librc_hidden_def(rc_find_pids)
 | 
			
		||||
static bool _match_daemon(const char *path, const char *file,
 | 
			
		||||
			  RC_STRINGLIST *match)
 | 
			
		||||
{
 | 
			
		||||
	char *line;
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	char ffile[PATH_MAX];
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	RC_STRING *m;
 | 
			
		||||
@@ -322,7 +323,7 @@ static bool _match_daemon(const char *path, const char *file,
 | 
			
		||||
	if (! fp)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	while ((line = rc_getline(fp))) {
 | 
			
		||||
	while ((rc_getline(&line, &len, fp))) {
 | 
			
		||||
		TAILQ_FOREACH(m, match, entries)
 | 
			
		||||
			if (strcmp(line, m->value) == 0) {
 | 
			
		||||
				TAILQ_REMOVE(match, m, entries);
 | 
			
		||||
@@ -332,6 +333,7 @@ static bool _match_daemon(const char *path, const char *file,
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
	free(line);
 | 
			
		||||
	if (TAILQ_FIRST(match))
 | 
			
		||||
		return false;
 | 
			
		||||
	return true;
 | 
			
		||||
@@ -493,7 +495,8 @@ bool rc_service_daemons_crashed(const char *service)
 | 
			
		||||
	struct dirent *d;
 | 
			
		||||
	char *path = dirpath;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char *line;
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	char **argv = NULL;
 | 
			
		||||
	char *exec = NULL;
 | 
			
		||||
	char *name = NULL;
 | 
			
		||||
@@ -525,17 +528,13 @@ bool rc_service_daemons_crashed(const char *service)
 | 
			
		||||
		if (! fp)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		while ((line = rc_getline(fp))) {
 | 
			
		||||
		while ((rc_getline(&line, &len, fp))) {
 | 
			
		||||
			p = line;
 | 
			
		||||
			if ((token = strsep(&p, "=")) == NULL || ! p) {
 | 
			
		||||
				free(line);
 | 
			
		||||
			if ((token = strsep(&p, "=")) == NULL || ! p)
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (! *p) {
 | 
			
		||||
				free(line);
 | 
			
		||||
			if (! *p)
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (strncmp(token, "argv_", 5) == 0) {
 | 
			
		||||
				if (! list)
 | 
			
		||||
@@ -551,11 +550,10 @@ bool rc_service_daemons_crashed(const char *service)
 | 
			
		||||
				name = xstrdup(p);
 | 
			
		||||
			} else if (strcmp(token, "pidfile") == 0) {
 | 
			
		||||
				pidfile = xstrdup(p);
 | 
			
		||||
				free(line);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			free(line);
 | 
			
		||||
		}
 | 
			
		||||
		free(line);
 | 
			
		||||
		fclose(fp);
 | 
			
		||||
 | 
			
		||||
		pid = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -121,7 +121,8 @@ RC_DEPTREE *rc_deptree_load(void)
 | 
			
		||||
	RC_DEPTREE *deptree;
 | 
			
		||||
	RC_DEPINFO *depinfo = NULL;
 | 
			
		||||
	RC_DEPTYPE *deptype = NULL;
 | 
			
		||||
	char *line;
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	char *type;
 | 
			
		||||
	char *p;
 | 
			
		||||
	char *e;
 | 
			
		||||
@@ -133,43 +134,43 @@ RC_DEPTREE *rc_deptree_load(void)
 | 
			
		||||
	deptree = xmalloc(sizeof(*deptree));
 | 
			
		||||
	STAILQ_INIT(deptree);
 | 
			
		||||
 | 
			
		||||
	while ((line = rc_getline(fp)))
 | 
			
		||||
	while ((rc_getline(&line, &len, fp)))
 | 
			
		||||
	{
 | 
			
		||||
		p = line;
 | 
			
		||||
		e = strsep(&p, "_");
 | 
			
		||||
		if (! e || strcmp(e, "depinfo") != 0)
 | 
			
		||||
			goto next;
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		e = strsep (&p, "_");
 | 
			
		||||
		if (! e || sscanf(e, "%d", &i) != 1)
 | 
			
		||||
			goto next;
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (! (type = strsep(&p, "_=")))
 | 
			
		||||
			goto next;
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (strcmp(type, "service") == 0)
 | 
			
		||||
		{
 | 
			
		||||
			/* Sanity */
 | 
			
		||||
			e = get_shell_value(p);
 | 
			
		||||
			if (! e || *e == '\0')
 | 
			
		||||
				goto next;
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			depinfo = xmalloc(sizeof(*depinfo));
 | 
			
		||||
			STAILQ_INIT(&depinfo->depends);
 | 
			
		||||
			depinfo->service = xstrdup(e);
 | 
			
		||||
			STAILQ_INSERT_TAIL(deptree, depinfo, entries);
 | 
			
		||||
			deptype = NULL;
 | 
			
		||||
			goto next;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		e = strsep(&p, "=");
 | 
			
		||||
		if (! e || sscanf(e, "%d", &i) != 1)
 | 
			
		||||
			goto next;
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* Sanity */
 | 
			
		||||
		e = get_shell_value(p);
 | 
			
		||||
		if (! e || *e == '\0')
 | 
			
		||||
			goto next;
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (! deptype || strcmp(deptype->type, type) != 0) {
 | 
			
		||||
			deptype = xmalloc(sizeof(*deptype));
 | 
			
		||||
@@ -179,10 +180,9 @@ RC_DEPTREE *rc_deptree_load(void)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		rc_stringlist_add(deptype->services, e);
 | 
			
		||||
next:
 | 
			
		||||
		free(line);
 | 
			
		||||
	}
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
	free(line);
 | 
			
		||||
	
 | 
			
		||||
	return deptree;
 | 
			
		||||
}
 | 
			
		||||
@@ -724,14 +724,15 @@ bool rc_deptree_update(void)
 | 
			
		||||
	RC_STRING *s;
 | 
			
		||||
	RC_STRING *s2;
 | 
			
		||||
	RC_DEPTYPE *provide;
 | 
			
		||||
	char *line;
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	char *depend;
 | 
			
		||||
	char *depends;
 | 
			
		||||
	char *service;
 | 
			
		||||
	char *type;
 | 
			
		||||
	size_t i;
 | 
			
		||||
	size_t k;
 | 
			
		||||
	size_t len;
 | 
			
		||||
	size_t l;
 | 
			
		||||
	int retval = true;
 | 
			
		||||
	const char *sys = rc_sys();
 | 
			
		||||
	char *nosys;
 | 
			
		||||
@@ -750,14 +751,14 @@ bool rc_deptree_update(void)
 | 
			
		||||
 | 
			
		||||
	config = rc_stringlist_new();
 | 
			
		||||
 | 
			
		||||
	while ((line = rc_getline(fp)))
 | 
			
		||||
	while ((rc_getline(&line, &len, fp)))
 | 
			
		||||
	{
 | 
			
		||||
		depends = line;
 | 
			
		||||
		service = strsep(&depends, " ");
 | 
			
		||||
		if (! service || ! *service)
 | 
			
		||||
			goto next;
 | 
			
		||||
		type = strsep(&depends, " ");
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		type = strsep(&depends, " ");
 | 
			
		||||
		if (! depinfo || strcmp(depinfo->service, service) != 0) {
 | 
			
		||||
			deptype = NULL;
 | 
			
		||||
			depinfo = get_depinfo(deptree, service);
 | 
			
		||||
@@ -771,7 +772,7 @@ bool rc_deptree_update(void)
 | 
			
		||||
		
 | 
			
		||||
		/* We may not have any depends */
 | 
			
		||||
		if (! type || ! depends)
 | 
			
		||||
			goto next;
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* Get the type */
 | 
			
		||||
		if (strcmp(type, "config") != 0) {
 | 
			
		||||
@@ -798,11 +799,11 @@ bool rc_deptree_update(void)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* .sh files are not init scripts */
 | 
			
		||||
			len = strlen(depend);
 | 
			
		||||
			if (len > 2 &&
 | 
			
		||||
			    depend[len - 3] == '.' &&
 | 
			
		||||
			    depend[len - 2] == 's' &&
 | 
			
		||||
			    depend[len - 1] == 'h')
 | 
			
		||||
			l = strlen(depend);
 | 
			
		||||
			if (l > 2 &&
 | 
			
		||||
			    depend[l - 3] == '.' &&
 | 
			
		||||
			    depend[l - 2] == 's' &&
 | 
			
		||||
			    depend[l - 1] == 'h')
 | 
			
		||||
				continue;
 | 
			
		||||
			
 | 
			
		||||
			/* Remove our dependency if instructed */
 | 
			
		||||
@@ -828,10 +829,8 @@ bool rc_deptree_update(void)
 | 
			
		||||
					rc_stringlist_delete(dt->services, depend);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
next:
 | 
			
		||||
		free(line);
 | 
			
		||||
	}
 | 
			
		||||
	free(line);
 | 
			
		||||
	pclose(fp);
 | 
			
		||||
 | 
			
		||||
	/* Phase 2 - if we're a special system, remove services that don't
 | 
			
		||||
 
 | 
			
		||||
@@ -54,37 +54,38 @@ bool rc_yesno (const char *value)
 | 
			
		||||
}
 | 
			
		||||
librc_hidden_def(rc_yesno)
 | 
			
		||||
 | 
			
		||||
char *rc_getline (FILE *fp)
 | 
			
		||||
ssize_t rc_getline (char **line, size_t *len, FILE *fp)
 | 
			
		||||
{
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	char *p;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	size_t last = 0;
 | 
			
		||||
 | 
			
		||||
	if (feof (fp))
 | 
			
		||||
		return NULL;
 | 
			
		||||
	if (feof(fp))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		len += BUFSIZ;
 | 
			
		||||
		line = xrealloc (line, sizeof (char) * len);
 | 
			
		||||
		p = line + last;
 | 
			
		||||
		memset (p, 0, BUFSIZ);
 | 
			
		||||
		fgets (p, BUFSIZ, fp);
 | 
			
		||||
		last += strlen (p);
 | 
			
		||||
	} while (! feof (fp) && line[last - 1] != '\n');
 | 
			
		||||
		if (*line == NULL || last != 0) {
 | 
			
		||||
			*len += BUFSIZ;
 | 
			
		||||
			*line = xrealloc(*line, *len);
 | 
			
		||||
		}
 | 
			
		||||
		p = *line + last;
 | 
			
		||||
		memset(p, 0, BUFSIZ);
 | 
			
		||||
		fgets(p, BUFSIZ, fp);
 | 
			
		||||
		last += strlen(p);
 | 
			
		||||
	} while (! feof(fp) && (*line)[last - 1] != '\n');
 | 
			
		||||
 | 
			
		||||
	/* Trim the trailing newline */
 | 
			
		||||
	if (*line && line[--last] == '\n')
 | 
			
		||||
		line[last] = '\0';
 | 
			
		||||
	if (**line && (*line)[last - 1] == '\n')
 | 
			
		||||
		(*line)[last - 1] = '\0';
 | 
			
		||||
 | 
			
		||||
	return line;
 | 
			
		||||
	return last;
 | 
			
		||||
}
 | 
			
		||||
librc_hidden_def(rc_getline)
 | 
			
		||||
 | 
			
		||||
RC_STRINGLIST *rc_config_list(const char *file)
 | 
			
		||||
{
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char *buffer;
 | 
			
		||||
	char *buffer = NULL;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	char *p;
 | 
			
		||||
	char *token;
 | 
			
		||||
	RC_STRINGLIST *list = NULL;
 | 
			
		||||
@@ -92,7 +93,8 @@ RC_STRINGLIST *rc_config_list(const char *file)
 | 
			
		||||
	if (!(fp = fopen(file, "r")))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	while ((p = buffer = rc_getline(fp))) {
 | 
			
		||||
	while ((rc_getline(&buffer, &len, fp))) {
 | 
			
		||||
		p = buffer;
 | 
			
		||||
		/* Strip leading spaces/tabs */
 | 
			
		||||
		while ((*p == ' ') || (*p == '\t'))
 | 
			
		||||
			p++;
 | 
			
		||||
@@ -111,9 +113,9 @@ RC_STRINGLIST *rc_config_list(const char *file)
 | 
			
		||||
				rc_stringlist_add(list, token);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		free(buffer);
 | 
			
		||||
	}
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
	free(buffer);
 | 
			
		||||
 | 
			
		||||
	return list;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -166,7 +166,8 @@ static bool rm_dir(const char *pathname, bool top)
 | 
			
		||||
static bool file_regex(const char *file, const char *regex)
 | 
			
		||||
{
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char *line;
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	regex_t re;
 | 
			
		||||
	bool retval = false;
 | 
			
		||||
	int result;
 | 
			
		||||
@@ -183,14 +184,14 @@ static bool file_regex(const char *file, const char *regex)
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while ((line = rc_getline(fp))) {
 | 
			
		||||
	while ((rc_getline(&line, &len, fp))) {
 | 
			
		||||
		if (regexec(&re, line, 0, NULL, 0) == 0)
 | 
			
		||||
			retval = true;
 | 
			
		||||
		free(line);
 | 
			
		||||
		if (retval)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
	free(line);
 | 
			
		||||
	regfree(&re);
 | 
			
		||||
 | 
			
		||||
	return retval;
 | 
			
		||||
@@ -401,6 +402,7 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)
 | 
			
		||||
	char *svc;
 | 
			
		||||
	char *cmd = NULL;
 | 
			
		||||
	char *buffer = NULL;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	RC_STRINGLIST *commands = NULL;
 | 
			
		||||
	char *token;
 | 
			
		||||
	char *p;
 | 
			
		||||
@@ -417,7 +419,8 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)
 | 
			
		||||
	free(svc);
 | 
			
		||||
 | 
			
		||||
	if ((fp = popen(cmd, "r"))) {
 | 
			
		||||
		p = buffer = rc_getline(fp);
 | 
			
		||||
		rc_getline(&buffer, &len, fp);
 | 
			
		||||
		p = buffer;
 | 
			
		||||
		while ((token = strsep(&p, " "))) {
 | 
			
		||||
			if (! commands)
 | 
			
		||||
				commands = rc_stringlist_new();
 | 
			
		||||
@@ -437,6 +440,7 @@ char *rc_service_description(const char *service, const char *option)
 | 
			
		||||
	char *svc;
 | 
			
		||||
	char *cmd;
 | 
			
		||||
	char *desc = NULL;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	size_t l;
 | 
			
		||||
 | 
			
		||||
@@ -451,7 +455,7 @@ char *rc_service_description(const char *service, const char *option)
 | 
			
		||||
	snprintf(cmd, l, DESCSTR, svc, option ? "_" : "", option);
 | 
			
		||||
	free(svc);
 | 
			
		||||
	if ((fp = popen(cmd, "r"))) {
 | 
			
		||||
		desc = rc_getline(fp);
 | 
			
		||||
		rc_getline(&desc, &len, fp);
 | 
			
		||||
		pclose(fp);
 | 
			
		||||
	}
 | 
			
		||||
	free(cmd);
 | 
			
		||||
@@ -633,12 +637,13 @@ char *rc_service_value_get(const char *service, const char *option)
 | 
			
		||||
{
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char *line = NULL;
 | 
			
		||||
	size_t len = 0;
 | 
			
		||||
	char file[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
	snprintf(file, sizeof(file), RC_SVCDIR "/options/%s/%s",
 | 
			
		||||
		 service, option);
 | 
			
		||||
	if ((fp = fopen(file, "r"))) {
 | 
			
		||||
		line = rc_getline(fp);
 | 
			
		||||
		rc_getline(&line, &len, fp);
 | 
			
		||||
		fclose(fp);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -71,6 +71,8 @@
 | 
			
		||||
#define librc_hidden_proto(x) hidden_proto(x)
 | 
			
		||||
#define librc_hidden_def(x) hidden_def(x)
 | 
			
		||||
 | 
			
		||||
ssize_t rc_getline(char **, size_t *, FILE *);
 | 
			
		||||
 | 
			
		||||
librc_hidden_proto(rc_config_list)
 | 
			
		||||
librc_hidden_proto(rc_config_load)
 | 
			
		||||
librc_hidden_proto(rc_config_value)
 | 
			
		||||
 
 | 
			
		||||
@@ -378,10 +378,6 @@ int rc_plugin_hook(RC_HOOK, const char *);
 | 
			
		||||
 * variables they wish. Variables should be separated by NULLs. */
 | 
			
		||||
extern FILE *rc_environ_fd;
 | 
			
		||||
 | 
			
		||||
/*! @name Configuration
 | 
			
		||||
 * These functions help to deal with shell based configuration files */
 | 
			
		||||
/*! Return a line from a file, stripping the trailing newline. */
 | 
			
		||||
char *rc_getline(FILE *);
 | 
			
		||||
 | 
			
		||||
/*! Return a NULL terminated list of non comment lines from a file. */
 | 
			
		||||
RC_STRINGLIST *rc_config_list(const char *);
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@ global:
 | 
			
		||||
	rc_deptree_update_needed;
 | 
			
		||||
	rc_environ_fd;
 | 
			
		||||
	rc_find_pids;
 | 
			
		||||
	rc_getline;
 | 
			
		||||
	rc_newer_than;
 | 
			
		||||
	rc_runlevel_exists;
 | 
			
		||||
	rc_runlevel_get;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								src/rc/rc.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/rc/rc.c
									
									
									
									
									
								
							@@ -49,6 +49,10 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
 | 
			
		||||
# include <ifaddrs.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
# include <asm/setup.h> /* for COMMAND_LINE_SIZE */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
@@ -176,7 +180,7 @@ static void cleanup(void)
 | 
			
		||||
static char *proc_getent(const char *ent)
 | 
			
		||||
{
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
	char *proc;
 | 
			
		||||
	char proc[COMMAND_LINE_SIZE];
 | 
			
		||||
	char *p;
 | 
			
		||||
	char *value = NULL;
 | 
			
		||||
	int i;
 | 
			
		||||
@@ -189,9 +193,9 @@ static char *proc_getent(const char *ent)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((proc = rc_getline(fp)) &&
 | 
			
		||||
	    (p = strstr(proc, ent)))
 | 
			
		||||
	{
 | 
			
		||||
	memset(proc, 0, sizeof(proc));
 | 
			
		||||
	fgets(proc, sizeof(proc), fp);
 | 
			
		||||
	if (*proc && (p = strstr(proc, ent))) {
 | 
			
		||||
		i = p - proc;
 | 
			
		||||
		if (i == '\0' || proc[i - 1] == ' ') {
 | 
			
		||||
			p += strlen(ent);
 | 
			
		||||
@@ -201,7 +205,6 @@ static char *proc_getent(const char *ent)
 | 
			
		||||
		}
 | 
			
		||||
	} else
 | 
			
		||||
		errno = ENOENT;
 | 
			
		||||
	free(proc);
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
 | 
			
		||||
	return value;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user