Make rc_getline private and save it's buffer so it's sort of like getline from glibc.
This commit is contained in:
parent
b9eb450696
commit
51c825ceee
@ -22,17 +22,16 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd Mar 16, 2008
|
||||
.Dd Mar 17, 2008
|
||||
.Dt RC_CONFIG 3 SMM
|
||||
.Os OpenRC
|
||||
.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
|
||||
.Sh LIBRARY
|
||||
Run Command library (librc, -lrc)
|
||||
.Sh SYNOPSIS
|
||||
.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_load "const char *file"
|
||||
.Ft "char *" Fn rc_config_value "const char *const *list" "const char *entry"
|
||||
@ -40,14 +39,6 @@ Run Command library (librc, -lrc)
|
||||
.Sh DESCRIPTION
|
||||
These functions provide an easy means of querying OpenRC configuration files.
|
||||
.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
|
||||
returns a list of non comment lines in
|
||||
.Fa file .
|
||||
|
@ -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;
|
||||
return 0;
|
||||
|
||||
do {
|
||||
len += BUFSIZ;
|
||||
line = xrealloc (line, sizeof (char) * len);
|
||||
p = line + last;
|
||||
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');
|
||||
} 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;
|
||||
|
Loading…
Reference in New Issue
Block a user