view f-demime/main.c @ 4:612c4d0df768

f-demime: rework for unboundedly long lines
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 06 May 2023 09:02:12 +0000
parents 7e0d08176f32
children
line wrap: on
line source

/*
 * This module contains the main() function for f-demime.  The following
 * functions are called to pass input to further processing:
 *
 * begin_new_message(): called after processing a "From " line
 * message_input_line(): called for all message lines after the "From " line
 * finish_msg_body(): called when hitting EOF or a new "From " line
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include "defs.h"

char *att_filename_buf, *att_filename_base, *att_filename_tail;

static void
get_attachment_dir()
{
	static char varname[] = "FDEMIME_ATT_DIR";
	char *env, *cp;
	unsigned dir_name_len;
	time_t curtime;
	struct tm *tm;

	env = getenv(varname);
	if (!env) {
		fprintf(stderr,
			"error: required environment variable %s is not set\n",
			varname);
		exit(1);
	}
	if (!env[0]) {
		fprintf(stderr,
			"error: empty string value for %s is not allowed\n",
			varname);
		exit(1);
	}
	dir_name_len = strlen(env);
	att_filename_buf = malloc(dir_name_len + 31);	/* Y10K extra margin */
	if (!att_filename_buf) {
		fprintf(stderr,
		"error: unable to malloc buffer for attachment filenames\n");
		exit(1);
	}
	strcpy(att_filename_buf, env);
	cp = att_filename_buf + dir_name_len;
	*cp++ = '/';
	att_filename_base = cp;
	time(&curtime);
	tm = gmtime(&curtime);
	sprintf(cp, "%u%02u%02ua", tm->tm_year + 1900, tm->tm_mon + 1,
		tm->tm_mday);
	att_filename_tail = index(cp, '\0');
}

main(argc, argv)
	char **argv;
{
	char linebuf[LINE_BUF_SIZE];
	int c, unterm, prev_unterm;
	unsigned lineno;

	if (argc > 3) {
		fprintf(stderr, "usage: %s [infile [outfile]]\n", argv[0]);
		exit(1);
	}
	get_attachment_dir();
	if (argc > 1 && !freopen(argv[1], "r", stdin)) {
		perror(argv[1]);
		exit(1);
	}
	if (argc > 2 && !freopen(argv[2], "w", stdout)) {
		perror(argv[2]);
		exit(1);
	}
	lineno = 0;
	for (prev_unterm = 0; fgets(linebuf, sizeof linebuf, stdin);
	     prev_unterm = unterm) {
		if (!prev_unterm)
			lineno++;
		if (index(linebuf, '\n'))
			unterm = 0;
		else
			unterm = 1;
		if (!prev_unterm && !strncmp(linebuf, "From ", 5)) {
			finish_msg_body();
			fputs(linebuf, stdout);
			if (unterm) {
				fprintf(stderr,
		"f-demime warning: From line %u too long or unterminated\n",
					lineno);
				for (;;) {
					c = getchar();
					if (c == EOF || c == '\n')
						break;
				}
				putchar('\n');
				unterm = 0;
			}
			begin_new_message();
			continue;
		}
		message_input_line(linebuf, unterm, prev_unterm);
	}
	finish_msg_body();
	exit(0);
}