Make rc_getline private and save it's buffer so it's sort of like getline from glibc.

This commit is contained in:
Roy Marples 2008-03-17 21:27:37 +00:00
parent b9eb450696
commit 51c825ceee
9 changed files with 77 additions and 82 deletions

View File

@ -22,17 +22,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.Dd Mar 16, 2008 .Dd Mar 17, 2008
.Dt RC_CONFIG 3 SMM .Dt RC_CONFIG 3 SMM
.Os OpenRC .Os OpenRC
.Sh NAME .Sh NAME
.Nm rc_getline , rc_config_list , rc_config_load , rc_config_value , rc_yesno .Nm rc_config_list , rc_config_load , rc_config_value , rc_yesno
.Nd functions to query OpenRC service configurations .Nd functions to query OpenRC service configurations
.Sh LIBRARY .Sh LIBRARY
Run Command library (librc, -lrc) Run Command library (librc, -lrc)
.Sh SYNOPSIS .Sh SYNOPSIS
.In rc.h .In rc.h
.Ft "char *" Fn rc_getline "FILE *fp"
.Ft "RC_STRINGLIST *" Fn rc_config_list "const char *file" .Ft "RC_STRINGLIST *" Fn rc_config_list "const char *file"
.Ft "RC_STRINGLIST *" Fn rc_config_load "const char *file" .Ft "RC_STRINGLIST *" Fn rc_config_load "const char *file"
.Ft "char *" Fn rc_config_value "const char *const *list" "const char *entry" .Ft "char *" Fn rc_config_value "const char *const *list" "const char *entry"
@ -40,14 +39,6 @@ Run Command library (librc, -lrc)
.Sh DESCRIPTION .Sh DESCRIPTION
These functions provide an easy means of querying OpenRC configuration files. These functions provide an easy means of querying OpenRC configuration files.
.Pp .Pp
.Fn rc_getline
expands it's buffer using
.Fn malloc
until it has read a whole line from the file or EOF.
Trailing newlines are removed and the buffer is returned. Any functions that
read from files should use this function to avoid any potential overflows and
to ensure that arbitary long lines are read.
.Pp
.Fn rc_config_list .Fn rc_config_list
returns a list of non comment lines in returns a list of non comment lines in
.Fa file . .Fa file .

View File

@ -311,7 +311,8 @@ librc_hidden_def(rc_find_pids)
static bool _match_daemon(const char *path, const char *file, static bool _match_daemon(const char *path, const char *file,
RC_STRINGLIST *match) RC_STRINGLIST *match)
{ {
char *line; char *line = NULL;
size_t len = 0;
char ffile[PATH_MAX]; char ffile[PATH_MAX];
FILE *fp; FILE *fp;
RC_STRING *m; RC_STRING *m;
@ -322,7 +323,7 @@ static bool _match_daemon(const char *path, const char *file,
if (! fp) if (! fp)
return false; return false;
while ((line = rc_getline(fp))) { while ((rc_getline(&line, &len, fp))) {
TAILQ_FOREACH(m, match, entries) TAILQ_FOREACH(m, match, entries)
if (strcmp(line, m->value) == 0) { if (strcmp(line, m->value) == 0) {
TAILQ_REMOVE(match, m, entries); TAILQ_REMOVE(match, m, entries);
@ -332,6 +333,7 @@ static bool _match_daemon(const char *path, const char *file,
break; break;
} }
fclose(fp); fclose(fp);
free(line);
if (TAILQ_FIRST(match)) if (TAILQ_FIRST(match))
return false; return false;
return true; return true;
@ -493,7 +495,8 @@ bool rc_service_daemons_crashed(const char *service)
struct dirent *d; struct dirent *d;
char *path = dirpath; char *path = dirpath;
FILE *fp; FILE *fp;
char *line; char *line = NULL;
size_t len = 0;
char **argv = NULL; char **argv = NULL;
char *exec = NULL; char *exec = NULL;
char *name = NULL; char *name = NULL;
@ -525,17 +528,13 @@ bool rc_service_daemons_crashed(const char *service)
if (! fp) if (! fp)
break; break;
while ((line = rc_getline(fp))) { while ((rc_getline(&line, &len, fp))) {
p = line; p = line;
if ((token = strsep(&p, "=")) == NULL || ! p) { if ((token = strsep(&p, "=")) == NULL || ! p)
free(line);
continue; continue;
}
if (! *p) { if (! *p)
free(line);
continue; continue;
}
if (strncmp(token, "argv_", 5) == 0) { if (strncmp(token, "argv_", 5) == 0) {
if (! list) if (! list)
@ -551,11 +550,10 @@ bool rc_service_daemons_crashed(const char *service)
name = xstrdup(p); name = xstrdup(p);
} else if (strcmp(token, "pidfile") == 0) { } else if (strcmp(token, "pidfile") == 0) {
pidfile = xstrdup(p); pidfile = xstrdup(p);
free(line);
break; break;
} }
free(line);
} }
free(line);
fclose(fp); fclose(fp);
pid = 0; pid = 0;

View File

@ -121,7 +121,8 @@ RC_DEPTREE *rc_deptree_load(void)
RC_DEPTREE *deptree; RC_DEPTREE *deptree;
RC_DEPINFO *depinfo = NULL; RC_DEPINFO *depinfo = NULL;
RC_DEPTYPE *deptype = NULL; RC_DEPTYPE *deptype = NULL;
char *line; char *line = NULL;
size_t len = 0;
char *type; char *type;
char *p; char *p;
char *e; char *e;
@ -133,43 +134,43 @@ RC_DEPTREE *rc_deptree_load(void)
deptree = xmalloc(sizeof(*deptree)); deptree = xmalloc(sizeof(*deptree));
STAILQ_INIT(deptree); STAILQ_INIT(deptree);
while ((line = rc_getline(fp))) while ((rc_getline(&line, &len, fp)))
{ {
p = line; p = line;
e = strsep(&p, "_"); e = strsep(&p, "_");
if (! e || strcmp(e, "depinfo") != 0) if (! e || strcmp(e, "depinfo") != 0)
goto next; continue;
e = strsep (&p, "_"); e = strsep (&p, "_");
if (! e || sscanf(e, "%d", &i) != 1) if (! e || sscanf(e, "%d", &i) != 1)
goto next; continue;
if (! (type = strsep(&p, "_="))) if (! (type = strsep(&p, "_=")))
goto next; continue;
if (strcmp(type, "service") == 0) if (strcmp(type, "service") == 0)
{ {
/* Sanity */ /* Sanity */
e = get_shell_value(p); e = get_shell_value(p);
if (! e || *e == '\0') if (! e || *e == '\0')
goto next; continue;
depinfo = xmalloc(sizeof(*depinfo)); depinfo = xmalloc(sizeof(*depinfo));
STAILQ_INIT(&depinfo->depends); STAILQ_INIT(&depinfo->depends);
depinfo->service = xstrdup(e); depinfo->service = xstrdup(e);
STAILQ_INSERT_TAIL(deptree, depinfo, entries); STAILQ_INSERT_TAIL(deptree, depinfo, entries);
deptype = NULL; deptype = NULL;
goto next; continue;
} }
e = strsep(&p, "="); e = strsep(&p, "=");
if (! e || sscanf(e, "%d", &i) != 1) if (! e || sscanf(e, "%d", &i) != 1)
goto next; continue;
/* Sanity */ /* Sanity */
e = get_shell_value(p); e = get_shell_value(p);
if (! e || *e == '\0') if (! e || *e == '\0')
goto next; continue;
if (! deptype || strcmp(deptype->type, type) != 0) { if (! deptype || strcmp(deptype->type, type) != 0) {
deptype = xmalloc(sizeof(*deptype)); deptype = xmalloc(sizeof(*deptype));
@ -179,10 +180,9 @@ RC_DEPTREE *rc_deptree_load(void)
} }
rc_stringlist_add(deptype->services, e); rc_stringlist_add(deptype->services, e);
next:
free(line);
} }
fclose(fp); fclose(fp);
free(line);
return deptree; return deptree;
} }
@ -724,14 +724,15 @@ bool rc_deptree_update(void)
RC_STRING *s; RC_STRING *s;
RC_STRING *s2; RC_STRING *s2;
RC_DEPTYPE *provide; RC_DEPTYPE *provide;
char *line; char *line = NULL;
size_t len = 0;
char *depend; char *depend;
char *depends; char *depends;
char *service; char *service;
char *type; char *type;
size_t i; size_t i;
size_t k; size_t k;
size_t len; size_t l;
int retval = true; int retval = true;
const char *sys = rc_sys(); const char *sys = rc_sys();
char *nosys; char *nosys;
@ -750,14 +751,14 @@ bool rc_deptree_update(void)
config = rc_stringlist_new(); config = rc_stringlist_new();
while ((line = rc_getline(fp))) while ((rc_getline(&line, &len, fp)))
{ {
depends = line; depends = line;
service = strsep(&depends, " "); service = strsep(&depends, " ");
if (! service || ! *service) if (! service || ! *service)
goto next; continue;
type = strsep(&depends, " ");
type = strsep(&depends, " ");
if (! depinfo || strcmp(depinfo->service, service) != 0) { if (! depinfo || strcmp(depinfo->service, service) != 0) {
deptype = NULL; deptype = NULL;
depinfo = get_depinfo(deptree, service); depinfo = get_depinfo(deptree, service);
@ -771,7 +772,7 @@ bool rc_deptree_update(void)
/* We may not have any depends */ /* We may not have any depends */
if (! type || ! depends) if (! type || ! depends)
goto next; continue;
/* Get the type */ /* Get the type */
if (strcmp(type, "config") != 0) { if (strcmp(type, "config") != 0) {
@ -798,11 +799,11 @@ bool rc_deptree_update(void)
} }
/* .sh files are not init scripts */ /* .sh files are not init scripts */
len = strlen(depend); l = strlen(depend);
if (len > 2 && if (l > 2 &&
depend[len - 3] == '.' && depend[l - 3] == '.' &&
depend[len - 2] == 's' && depend[l - 2] == 's' &&
depend[len - 1] == 'h') depend[l - 1] == 'h')
continue; continue;
/* Remove our dependency if instructed */ /* Remove our dependency if instructed */
@ -828,10 +829,8 @@ bool rc_deptree_update(void)
rc_stringlist_delete(dt->services, depend); rc_stringlist_delete(dt->services, depend);
} }
} }
next:
free(line);
} }
free(line);
pclose(fp); pclose(fp);
/* Phase 2 - if we're a special system, remove services that don't /* Phase 2 - if we're a special system, remove services that don't

View File

@ -54,37 +54,38 @@ bool rc_yesno (const char *value)
} }
librc_hidden_def(rc_yesno) 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; char *p;
size_t len = 0;
size_t last = 0; size_t last = 0;
if (feof (fp)) if (feof(fp))
return NULL; return 0;
do { do {
len += BUFSIZ; if (*line == NULL || last != 0) {
line = xrealloc (line, sizeof (char) * len); *len += BUFSIZ;
p = line + last; *line = xrealloc(*line, *len);
memset (p, 0, BUFSIZ); }
fgets (p, BUFSIZ, fp); p = *line + last;
last += strlen (p); memset(p, 0, BUFSIZ);
} while (! feof (fp) && line[last - 1] != '\n'); fgets(p, BUFSIZ, fp);
last += strlen(p);
} while (! feof(fp) && (*line)[last - 1] != '\n');
/* Trim the trailing newline */ /* Trim the trailing newline */
if (*line && line[--last] == '\n') if (**line && (*line)[last - 1] == '\n')
line[last] = '\0'; (*line)[last - 1] = '\0';
return line; return last;
} }
librc_hidden_def(rc_getline) librc_hidden_def(rc_getline)
RC_STRINGLIST *rc_config_list(const char *file) RC_STRINGLIST *rc_config_list(const char *file)
{ {
FILE *fp; FILE *fp;
char *buffer; char *buffer = NULL;
size_t len = 0;
char *p; char *p;
char *token; char *token;
RC_STRINGLIST *list = NULL; RC_STRINGLIST *list = NULL;
@ -92,7 +93,8 @@ RC_STRINGLIST *rc_config_list(const char *file)
if (!(fp = fopen(file, "r"))) if (!(fp = fopen(file, "r")))
return NULL; return NULL;
while ((p = buffer = rc_getline(fp))) { while ((rc_getline(&buffer, &len, fp))) {
p = buffer;
/* Strip leading spaces/tabs */ /* Strip leading spaces/tabs */
while ((*p == ' ') || (*p == '\t')) while ((*p == ' ') || (*p == '\t'))
p++; p++;
@ -111,9 +113,9 @@ RC_STRINGLIST *rc_config_list(const char *file)
rc_stringlist_add(list, token); rc_stringlist_add(list, token);
} }
} }
free(buffer);
} }
fclose(fp); fclose(fp);
free(buffer);
return list; return list;
} }

View File

@ -166,7 +166,8 @@ static bool rm_dir(const char *pathname, bool top)
static bool file_regex(const char *file, const char *regex) static bool file_regex(const char *file, const char *regex)
{ {
FILE *fp; FILE *fp;
char *line; char *line = NULL;
size_t len = 0;
regex_t re; regex_t re;
bool retval = false; bool retval = false;
int result; int result;
@ -183,14 +184,14 @@ static bool file_regex(const char *file, const char *regex)
return false; return false;
} }
while ((line = rc_getline(fp))) { while ((rc_getline(&line, &len, fp))) {
if (regexec(&re, line, 0, NULL, 0) == 0) if (regexec(&re, line, 0, NULL, 0) == 0)
retval = true; retval = true;
free(line);
if (retval) if (retval)
break; break;
} }
fclose(fp); fclose(fp);
free(line);
regfree(&re); regfree(&re);
return retval; return retval;
@ -401,6 +402,7 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)
char *svc; char *svc;
char *cmd = NULL; char *cmd = NULL;
char *buffer = NULL; char *buffer = NULL;
size_t len = 0;
RC_STRINGLIST *commands = NULL; RC_STRINGLIST *commands = NULL;
char *token; char *token;
char *p; char *p;
@ -417,7 +419,8 @@ RC_STRINGLIST *rc_service_extra_commands(const char *service)
free(svc); free(svc);
if ((fp = popen(cmd, "r"))) { if ((fp = popen(cmd, "r"))) {
p = buffer = rc_getline(fp); rc_getline(&buffer, &len, fp);
p = buffer;
while ((token = strsep(&p, " "))) { while ((token = strsep(&p, " "))) {
if (! commands) if (! commands)
commands = rc_stringlist_new(); commands = rc_stringlist_new();
@ -437,6 +440,7 @@ char *rc_service_description(const char *service, const char *option)
char *svc; char *svc;
char *cmd; char *cmd;
char *desc = NULL; char *desc = NULL;
size_t len = 0;
FILE *fp; FILE *fp;
size_t l; size_t l;
@ -451,7 +455,7 @@ char *rc_service_description(const char *service, const char *option)
snprintf(cmd, l, DESCSTR, svc, option ? "_" : "", option); snprintf(cmd, l, DESCSTR, svc, option ? "_" : "", option);
free(svc); free(svc);
if ((fp = popen(cmd, "r"))) { if ((fp = popen(cmd, "r"))) {
desc = rc_getline(fp); rc_getline(&desc, &len, fp);
pclose(fp); pclose(fp);
} }
free(cmd); free(cmd);
@ -633,12 +637,13 @@ char *rc_service_value_get(const char *service, const char *option)
{ {
FILE *fp; FILE *fp;
char *line = NULL; char *line = NULL;
size_t len = 0;
char file[PATH_MAX]; char file[PATH_MAX];
snprintf(file, sizeof(file), RC_SVCDIR "/options/%s/%s", snprintf(file, sizeof(file), RC_SVCDIR "/options/%s/%s",
service, option); service, option);
if ((fp = fopen(file, "r"))) { if ((fp = fopen(file, "r"))) {
line = rc_getline(fp); rc_getline(&line, &len, fp);
fclose(fp); fclose(fp);
} }

View File

@ -71,6 +71,8 @@
#define librc_hidden_proto(x) hidden_proto(x) #define librc_hidden_proto(x) hidden_proto(x)
#define librc_hidden_def(x) hidden_def(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_list)
librc_hidden_proto(rc_config_load) librc_hidden_proto(rc_config_load)
librc_hidden_proto(rc_config_value) librc_hidden_proto(rc_config_value)

View File

@ -378,10 +378,6 @@ int rc_plugin_hook(RC_HOOK, const char *);
* variables they wish. Variables should be separated by NULLs. */ * variables they wish. Variables should be separated by NULLs. */
extern FILE *rc_environ_fd; 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. */ /*! Return a NULL terminated list of non comment lines from a file. */
RC_STRINGLIST *rc_config_list(const char *); RC_STRINGLIST *rc_config_list(const char *);

View File

@ -12,7 +12,6 @@ global:
rc_deptree_update_needed; rc_deptree_update_needed;
rc_environ_fd; rc_environ_fd;
rc_find_pids; rc_find_pids;
rc_getline;
rc_newer_than; rc_newer_than;
rc_runlevel_exists; rc_runlevel_exists;
rc_runlevel_get; rc_runlevel_get;

View File

@ -49,6 +49,10 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
# include <ifaddrs.h> # include <ifaddrs.h>
#endif #endif
#ifdef __linux__
# include <asm/setup.h> /* for COMMAND_LINE_SIZE */
#endif
#include <errno.h> #include <errno.h>
#include <dirent.h> #include <dirent.h>
#include <ctype.h> #include <ctype.h>
@ -176,7 +180,7 @@ static void cleanup(void)
static char *proc_getent(const char *ent) static char *proc_getent(const char *ent)
{ {
FILE *fp; FILE *fp;
char *proc; char proc[COMMAND_LINE_SIZE];
char *p; char *p;
char *value = NULL; char *value = NULL;
int i; int i;
@ -189,9 +193,9 @@ static char *proc_getent(const char *ent)
return NULL; return NULL;
} }
if ((proc = rc_getline(fp)) && memset(proc, 0, sizeof(proc));
(p = strstr(proc, ent))) fgets(proc, sizeof(proc), fp);
{ if (*proc && (p = strstr(proc, ent))) {
i = p - proc; i = p - proc;
if (i == '\0' || proc[i - 1] == ' ') { if (i == '\0' || proc[i - 1] == ' ') {
p += strlen(ent); p += strlen(ent);
@ -201,7 +205,6 @@ static char *proc_getent(const char *ent)
} }
} else } else
errno = ENOENT; errno = ENOENT;
free(proc);
fclose(fp); fclose(fp);
return value; return value;