diff --git a/man/rc_config.3 b/man/rc_config.3 index f420d43b..2bf90a1a 100644 --- a/man/rc_config.3 +++ b/man/rc_config.3 @@ -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 . diff --git a/src/librc/librc-daemon.c b/src/librc/librc-daemon.c index aed37e42..46162d51 100644 --- a/src/librc/librc-daemon.c +++ b/src/librc/librc-daemon.c @@ -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; diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c index a9bf3045..d3a3f78b 100644 --- a/src/librc/librc-depend.c +++ b/src/librc/librc-depend.c @@ -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 diff --git a/src/librc/librc-misc.c b/src/librc/librc-misc.c index 747a8fb6..5c7e3660 100644 --- a/src/librc/librc-misc.c +++ b/src/librc/librc-misc.c @@ -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; } diff --git a/src/librc/librc.c b/src/librc/librc.c index cb75521f..75b0e412 100644 --- a/src/librc/librc.c +++ b/src/librc/librc.c @@ -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); } diff --git a/src/librc/librc.h b/src/librc/librc.h index 376a62ff..62d389b9 100644 --- a/src/librc/librc.h +++ b/src/librc/librc.h @@ -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) diff --git a/src/librc/rc.h b/src/librc/rc.h index ba49e78d..5deb0e9e 100644 --- a/src/librc/rc.h +++ b/src/librc/rc.h @@ -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 *); diff --git a/src/librc/rc.map b/src/librc/rc.map index 55dea008..845ae946 100644 --- a/src/librc/rc.map +++ b/src/librc/rc.map @@ -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; diff --git a/src/rc/rc.c b/src/rc/rc.c index 30bedcbf..eec03321 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -49,6 +49,10 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; # include #endif +#ifdef __linux__ +# include /* for COMMAND_LINE_SIZE */ +#endif + #include #include #include @@ -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;