feat(xce-test-rc-file): task 1.2 rc-file line-loading via pluggable runner
Adds rcfile_load(path, runner) to rcfile.c/rcfile.h: reads lines with getline() (no fixed-size buffer, so a long line like a multi-peer `set masters ...` can never be silently truncated or split), strips the trailing newline, invokes the caller-supplied runner once per line, and stops at the first nonzero runner return, propagating that value. A missing rc file is a silent no-op; any other open failure prints one stderr warning and returns 0. Found during GREEN: fopen() succeeds on a directory path on this platform, so the EISDIR failure only surfaces on the first getline() call (ferror(f) set) -- added a post-loop ferror() check to catch it (bug-1716). 5 new unit tests (11 total with task 1.1): ENOENT-silent, per-line-in-order with newline stripped, stop-on-nonzero with exact propagation, non-ENOENT open-failure warning, and a >4KB single line proving no truncation/split. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AgYRU3zDTqNGV5Jk8aiKLg
This commit is contained in:
parent
b3c462ede4
commit
77aba21fb0
4 changed files with 305 additions and 6 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#define _GNU_SOURCE
|
||||
#include "rcfile.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
@ -36,3 +37,44 @@ char* rcfile_resolve_path(void)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rcfile_load(const char* path, int (*runner)(char* line))
|
||||
{
|
||||
if (!path)
|
||||
return 0;
|
||||
|
||||
FILE* f = fopen(path, "r");
|
||||
if (!f) {
|
||||
if (errno == ENOENT)
|
||||
return 0; /* missing rc file: silent no-op success */
|
||||
fprintf(stderr, "xce_test: warning: could not open rc file %s: %s\n",
|
||||
path, strerror(errno));
|
||||
return 0; /* present but unreadable: non-fatal warning */
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
char* line = NULL;
|
||||
size_t cap = 0;
|
||||
ssize_t n;
|
||||
while ((n = getline(&line, &cap, f)) != -1) {
|
||||
if (n > 0 && line[n - 1] == '\n')
|
||||
line[n - 1] = '\0';
|
||||
rc = runner(line);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* fopen() succeeds on a directory on this platform -- the failure only
|
||||
* surfaces on the first read (getline() returns -1 with errno==EISDIR
|
||||
* and ferror(f) set, feof(f) NOT set). Treat that the same as an open
|
||||
* failure: one non-fatal stderr warning, no runner calls attributed to
|
||||
* it (rc is still 0 here since no line was ever successfully read). */
|
||||
if (rc == 0 && ferror(f)) {
|
||||
fprintf(stderr, "xce_test: warning: could not read rc file %s: %s\n",
|
||||
path, strerror(errno));
|
||||
}
|
||||
|
||||
free(line);
|
||||
fclose(f);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue