X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=builtin-mailsplit.c;h=ae2b4cb21bf4e691a044e2ace3cdd4861562ceca;hb=8366b7baae7e5a33f609b07c939a3571653a2314;hp=10fa1773401d6474d8e6c88065e3a992690ae0f8;hpb=b574c8d846dbdbaaad1e96ae365d452bc5cd6d64;p=git.git diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c index 10fa17734..ae2b4cb21 100644 --- a/builtin-mailsplit.c +++ b/builtin-mailsplit.c @@ -45,6 +45,24 @@ static int is_from_line(const char *line, int len) /* Could be as small as 64, enough to hold a Unix "From " line. */ static char buf[4096]; +/* We cannot use fgets() because our lines can contain NULs */ +int read_line_with_nul(char *buf, int size, FILE *in) +{ + int len = 0, c; + + for (;;) { + c = getc(in); + if (c == EOF) + break; + buf[len++] = c; + if (c == '\n' || len + 1 >= size) + break; + } + buf[len] = '\0'; + + return len; +} + /* Called with the first line (potentially partial) * already in buf[] -- normally that should begin with * the Unix "From " line. Write it into the specified @@ -70,19 +88,19 @@ static int split_one(FILE *mbox, const char *name, int allow_bare) * "From " and having something that looks like a date format. */ for (;;) { - int is_partial = (buf[len-1] != '\n'); + int is_partial = len && buf[len-1] != '\n'; - if (fputs(buf, output) == EOF) + if (fwrite(buf, 1, len, output) != len) die("cannot write output"); - if (fgets(buf, sizeof(buf), mbox) == NULL) { + len = read_line_with_nul(buf, sizeof(buf), mbox); + if (len == 0) { if (feof(mbox)) { status = 1; break; } die("cannot read mbox"); } - len = strlen(buf); if (!is_partial && !is_bare && is_from_line(buf, len)) break; /* done with one message */ } @@ -170,6 +188,7 @@ static int split_mbox(const char *file, const char *dir, int allow_bare, { char name[PATH_MAX]; int ret = -1; + int peek; FILE *f = !strcmp(file, "-") ? stdin : fopen(file, "r"); int file_done = 0; @@ -179,6 +198,11 @@ static int split_mbox(const char *file, const char *dir, int allow_bare, goto out; } + do { + peek = fgetc(f); + } while (isspace(peek)); + ungetc(peek, f); + if (fgets(buf, sizeof(buf), f) == NULL) { /* empty stdin is OK */ if (f != stdin) {