Makes error detection and handling easier for a common operation.
Signed-off-by: Andrew Gregory andrew.gregory.8@gmail.com --- lib/libalpm/alpm_list.c | 20 ++++++++++++++++++++ lib/libalpm/alpm_list.h | 1 + 2 files changed, 21 insertions(+)
diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c index 36b01c71..0f1b819c 100644 --- a/lib/libalpm/alpm_list.c +++ b/lib/libalpm/alpm_list.c @@ -132,6 +132,26 @@ alpm_list_t SYMEXPORT *alpm_list_append(alpm_list_t **list, void *data) }
/** + * @brief Duplicate and append a string to a list. + * + * @param list the list to append to + * @param data the string to duplicate and append + * + * @return the newly added item + */ +alpm_list_t SYMEXPORT *alpm_list_append_strdup(alpm_list_t **list, const char *data) +{ + alpm_list_t *ret; + char *dup; + if((dup = strdup(data)) && (ret = alpm_list_append(list, dup))) { + return ret; + } else { + free(dup); + return NULL; + } +} + +/** * @brief Add items to a list in sorted order. * * @param list the list to add to diff --git a/lib/libalpm/alpm_list.h b/lib/libalpm/alpm_list.h index d7306cc5..1cb237d0 100644 --- a/lib/libalpm/alpm_list.h +++ b/lib/libalpm/alpm_list.h @@ -58,6 +58,7 @@ void alpm_list_free_inner(alpm_list_t *list, alpm_list_fn_free fn); /* item mutators */ alpm_list_t *alpm_list_add(alpm_list_t *list, void *data); alpm_list_t *alpm_list_append(alpm_list_t **list, void *data); +alpm_list_t *alpm_list_append_strdup(alpm_list_t **list, const char *data); alpm_list_t *alpm_list_add_sorted(alpm_list_t *list, void *data, alpm_list_fn_cmp fn); alpm_list_t *alpm_list_join(alpm_list_t *first, alpm_list_t *second); alpm_list_t *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, alpm_list_fn_cmp fn);
Newline-separated input is more reliable because most of the arguments we accept over stdin can validly contain spaces but not newlines.
Resolves FS#52992
Signed-off-by: Andrew Gregory andrew.gregory.8@gmail.com --- src/pacman/pacman.c | 55 ++++++++++++++++++++++------------------------------- 1 file changed, 23 insertions(+), 32 deletions(-)
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index a459cf00..7651df3c 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -1094,7 +1094,6 @@ static void cl_to_log(int argc, char *argv[]) int main(int argc, char *argv[]) { int ret = 0; - size_t i; uid_t myuid = getuid();
install_segv_handler(); @@ -1142,44 +1141,36 @@ int main(int argc, char *argv[]) if(alpm_list_find_str(pm_targets, "-")) { if(!isatty(fileno(stdin))) { int target_found = 0; - size_t current_size = PATH_MAX; - char *vdata, *line = malloc(current_size); - int c; + char *vdata, *line = NULL; + size_t line_size = 0; + ssize_t nread;
/* remove the '-' from the list */ pm_targets = alpm_list_remove_str(pm_targets, "-", &vdata); free(vdata);
- i = 0; - do { - c = fgetc(stdin); - if(c == EOF || isspace(c)) { - /* avoid adding zero length arg when multiple spaces separate args */ - if(i > 0) { - line[i] = '\0'; - pm_targets = alpm_list_add(pm_targets, strdup(line)); - target_found = 1; - i = 0; - } - } else { - line[i++] = (char)c; - /* we may be at the end of our allocated buffer now */ - if(i >= current_size) { - char *new = realloc(line, current_size * 2); - if(new) { - line = new; - current_size *= 2; - } else { - free(line); - pm_printf(ALPM_LOG_ERROR, - _("memory exhausted in argument parsing\n")); - cleanup(EXIT_FAILURE); - } - } + while((nread = getline(&line, &line_size, stdin)) != -1) { + if(line[nread - 1] == '\n') { + /* remove trailing newline */ + line[nread - 1] = '\0'; } - } while(c != EOF); - + if(line[0] == '\0') { + /* skip empty lines */ + continue; + } + if(!alpm_list_append_strdup(&pm_targets, line)) { + break; + } + target_found = 1; + } free(line); + + if(ferror(stdin)) { + pm_printf(ALPM_LOG_ERROR, + _("failed to read arguments from stdin: (%s)\n"), strerror(errno)); + cleanup(EXIT_FAILURE); + } + if(!freopen(ctermid(NULL), "r", stdin)) { pm_printf(ALPM_LOG_ERROR, _("failed to reopen stdin for reading: (%s)\n"), strerror(errno));
On 02/18/17 at 05:09pm, Andrew Gregory wrote:
Newline-separated input is more reliable because most of the arguments we accept over stdin can validly contain spaces but not newlines.
Resolves FS#52992
Signed-off-by: Andrew Gregory andrew.gregory.8@gmail.com
src/pacman/pacman.c | 55 ++++++++++++++++++++++------------------------------- 1 file changed, 23 insertions(+), 32 deletions(-)
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index a459cf00..7651df3c 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -1094,7 +1094,6 @@ static void cl_to_log(int argc, char *argv[]) int main(int argc, char *argv[]) { int ret = 0;
size_t i; uid_t myuid = getuid();
install_segv_handler();
@@ -1142,44 +1141,36 @@ int main(int argc, char *argv[]) if(alpm_list_find_str(pm_targets, "-")) { if(!isatty(fileno(stdin))) { int target_found = 0;
size_t current_size = PATH_MAX;
char *vdata, *line = malloc(current_size);
int c;
char *vdata, *line = NULL;
size_t line_size = 0;
ssize_t nread; /* remove the '-' from the list */ pm_targets = alpm_list_remove_str(pm_targets, "-", &vdata); free(vdata);
i = 0;
do {
c = fgetc(stdin);
if(c == EOF || isspace(c)) {
/* avoid adding zero length arg when multiple spaces separate args */
if(i > 0) {
line[i] = '\0';
pm_targets = alpm_list_add(pm_targets, strdup(line));
target_found = 1;
i = 0;
}
} else {
line[i++] = (char)c;
/* we may be at the end of our allocated buffer now */
if(i >= current_size) {
char *new = realloc(line, current_size * 2);
if(new) {
line = new;
current_size *= 2;
} else {
free(line);
pm_printf(ALPM_LOG_ERROR,
_("memory exhausted in argument parsing\n"));
cleanup(EXIT_FAILURE);
}
}
while((nread = getline(&line, &line_size, stdin)) != -1) {
if(line[nread - 1] == '\n') {
/* remove trailing newline */
line[nread - 1] = '\0'; }
} while(c != EOF);
if(line[0] == '\0') {
/* skip empty lines */
continue;
}
if(!alpm_list_append_strdup(&pm_targets, line)) {
break;
}
target_found = 1;
} free(line);
if(ferror(stdin)) {
pm_printf(ALPM_LOG_ERROR,
_("failed to read arguments from stdin: (%s)\n"), strerror(errno));
cleanup(EXIT_FAILURE);
}
This, of course, won't catch errors from appending to pm_targets. Switched to using errno for error detection in my repo.
if(!freopen(ctermid(NULL), "r", stdin)) { pm_printf(ALPM_LOG_ERROR, _("failed to reopen stdin for reading: (%s)\n"), strerror(errno));
-- 2.11.1
On 19/02/17 08:09, Andrew Gregory wrote:
Makes error detection and handling easier for a common operation.
Signed-off-by: Andrew Gregory andrew.gregory.8@gmail.com
OK
Are you intending to spread the use of this function?
A
pacman-dev@lists.archlinux.org