/*
* Copyright 1998-2002 Ben Smithurst <ben@smithurst.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Splits a mbox into its individual messages.
*/
#include "misc.h"
const char rcsid[] =
"$BCPS: src/mailutils/mail-split.c,v 1.29 2003/01/19 19:18:25 ben Exp $";
int split_maildir(int, char *, FILE *);
int split_file(FILE *, FILE *);
void usage(void);
char *prefix, *suffix;
int fflag;
int
main(int argc, char *argv[]) {
int ch;
/* defaults */
prefix = "%n-";
suffix = "";
fflag = 0;
while ((ch = getopt(argc, argv, "fp:s:")) != -1)
switch (ch) {
case 'f':
fflag = 1;
break;
case 'p':
prefix = optarg;
break;
case 's':
suffix = optarg;
break;
default:
usage();
/* NOTREACHED */
}
argc -= optind;
argv += optind;
return (process(argv, split_file, split_maildir) ? 0 : 1);
}
int
split_maildir(int reset, char *fn, FILE *in_fp) {
if (reset)
warnx("useless on Maildir %s", curfile);
return (RET_NOCHANGE);
}
/*
* Expands the given prefix, number and suffix into `buf', which has
* room for `size' characters including NUL. %N in prefix or suffix
* expands to the value of `curfile', %n to the last part of `curfile'
* (i.e. from the character after the last slash onwards, or the entire
* string if it doesn't contain any slashes.)
*/
int
fn_expand(char *buf, int size, char *prefix, char *suffix, int num) {
char numbuf[32];
char *b, *p;
int len, i;
int plen, slen, nlen, nblen, numlen;
snprintf(numbuf, sizeof numbuf, "%06d", num);
numlen = strlen(numbuf);
plen = strlen(prefix);
slen = strlen(suffix);
nlen = strlen(curfile);
if ((b = strrchr(curfile, '/')) == NULL) {
b = curfile;
nblen = nlen;
} else {
b++;
nblen = strlen(b);
}
/* Do the expansion */
len = 0;
for (i = 0; i < 3; i++) {
/* Second time through the loop, just copy the number */
if (i == 1) {
if (len + numlen >= size)
return (0);
strcpy(buf + len, numbuf);
len += numlen;
continue;
}
/*
* First time through (i == 0), process the prefix, otherwise
* (must be third time) process suffix.
*/
for (p = (i ? suffix : prefix); *p != '\0'; p++)
switch (*p) {
case '%':
switch (*++p) {
case 'n':
if (len + nblen >= size)
return (0);
strcpy(buf + len, b);
len += nblen;
break;
case 'N':
if (len + nlen >= size)
return (0);
strcpy(buf + len, curfile);
len += nlen;
break;
case '\0':
p--; /* So that for() loop sees \0 */
/* FALLTHROUGH */
case '%':
if (len + 1 >= size)
return (0);
buf[len++] = '%';
break;
default:
if (len + 2 >= size)
return (0);
buf[len++] = '%';
buf[len++] = *p;
break;
}
break;
default:
if (len + numlen >= size)
return (0);
buf[len++] = *p;
break;
}
}
buf[len] = '\0';
return (1);
}
int
split_file(FILE *in, FILE *junk) {
FILE *out;
char *line, filename[MAXPATHLEN];
int e, fd, from_line, num;
size_t len;
mode_t mask;
/* Set a restrictive umask since files containing mail are created */
mask = umask(077);
num = 0;
from_line = 0;
out = NULL;
while ((line = gl_getline(in)) != NULL) {
len = strlen(line);
chop(line, len);
if (is_from(line, 1)) {
num++;
from_line = 1;
if (out) {
fclose(out);
out = NULL;
}
/*
* build the new filename, increase num until
* a unique name is found.
*/
for (;;) {
/* Do expansion */
if (!fn_expand(filename, sizeof filename,
prefix, suffix, num))
{
warnx("fn_expand failed");
umask(mask);
return (RET_LOCALERROR);
}
/* Attempt to create file */
fd = open(filename, O_WRONLY|O_CREAT|O_EXCL,
0600);
if (fd >= 0)
break;
/* EEXIST is ok, anything else isn't. */
if (errno != EEXIST) {
e = errno;
umask(mask);
errno = e;
return (RET_ERROR);
}
/* Protect against overflow. */
if (num == INT_MAX) {
warnx("couldn't get unique name");
umask(mask);
return (RET_LOCALERROR);
}
num++;
}
if ((out = fdopen(fd, "w")) == NULL) {
e = errno;
umask(mask);
errno = e;
return (RET_ERROR);
}
} else
from_line = 0;
if (out && (fflag || !from_line))
fprintf(out, "%s\n", line);
}
gl_destroy(in);
if (out != NULL)
fclose(out);
umask(mask);
return (RET_NOCHANGE);
}
void
usage(void) {
fprintf(stderr, "usage: mail-split [-f] [-p prefix] [-s suffix]\n"
" [files ...]\n");
exit(EX_USAGE);
}
syntax highlighted by Code2HTML, v. 0.9.1