<commit_before>/*
 * Send a compressed CTM delta to a recipient mailing list by encoding it
 * in safe ASCII characters, in mailer-friendly chunks, and passing it
 * to sendmail.  The encoding is almost the same as MIME BASE64, and is
 * protected by a simple checksum.
 *
 * Author: <NAME>
 *
 * NOTICE: This is free software.  I hope you get some use from this program.
 * In return you should think about all the nice people who give away software.
 * Maybe you should write some free software too.
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <paths.h>
#include "error.h"
#include "options.h"

#define DEF_MAX_MSG	64000	/* Default maximum mail msg minus headers. */

#define LINE_LENGTH	76	/* Chars per encode line. Divisible by 4. */

void chop_and_send(char *delta, off_t ctm_size, long max_msg_size,
	char *mail_alias);
unsigned encode_body(FILE *sm_fp, FILE *delta_fp, long msg_size);
void write_header(FILE *sfp, char *mail_alias, char *delta, int pce,
	int npieces);
void write_trailer(FILE *sfp, unsigned sum);
void apologise(char *delta, off_t ctm_size, long max_ctm_size,
	char *mail_alias);
FILE *open_sendmail(void);
int close_sendmail(FILE *fp);


int
main(int argc, char **argv)
    {
    char *delta_file;
    char *mail_alias;
    long max_msg_size = DEF_MAX_MSG;
    long max_ctm_size = 0;
    char *log_file = NULL;
    struct stat sb;

    err_prog_name(argv[0]);

    OPTIONS("[-l log] [-m maxmsgsize] [-c maxctmsize] ctm-delta mail-alias")
	NUMBER('m', max_msg_size)
	NUMBER('c', max_ctm_size)
	STRING('l', log_file)
    ENDOPTS

    if (argc != 3)
	usage();

    if (log_file != NULL)
	err_set_log(log_file);

    delta_file = argv[1];
    mail_alias = argv[2];

    if (stat(delta_file, &sb) < 0)
	{
	err("%s: %s", delta_file, strerror(errno));
	exit(1);
	}

    if (max_ctm_size != 0 && sb.st_size > max_ctm_size)
	apologise(delta_file, sb.st_size, max_ctm_size, mail_alias);
    else
	chop_and_send(delta_file, sb.st_size, max_msg_size, mail_alias);

    return 0;
    }


/*
 * Carve our CTM delta into pieces, encode them, and send them.
 */
void
chop_and_send(char *delta, off_t ctm_size, long max_msg_size, char *mail_alias)
    {
    int npieces;
    long msg_size;
    long exp_size;
    int pce;
    FILE *sfp;
    FILE *dfp;
    unsigned sum;

#define howmany(x,y)	(((x)+((y)-1))/(y))

    /*
     * Work out how many pieces we need, bearing in mind that each piece
     * grows by 4/3 when encoded.  We count the newlines too, but ignore
     * all mail headers and piece headers.  They are a "small" (almost
     * constant) per message overhead that we make the user worry about. :-)
     */
    exp_size = ctm_size * 4 / 3;
    exp_size += howmany(exp_size, LINE_LENGTH);
    npieces = howmany(exp_size, max_msg_size);
    msg_size = howmany(ctm_size, npieces);

#undef howmany

    if ((dfp = fopen(delta, "r")) == NULL)
	{
	err("cannot open '%s' for reading.", delta);
	exit(1);
	}

    for (pce = 1; pce <= npieces; pce++)
	{
	sfp = open_sendmail();
	if (sfp == NULL)
	    exit(1);
	write_header(sfp, mail_alias, delta, pce, npieces);<commit_msg>Updated howmany() to be once again identical with the namespace-polluting one in <sys/types.h>.  Lite2 changed the white space in the latter.<commit_after>/*
 * Send a compressed CTM delta to a recipient mailing list by encoding it
 * in safe ASCII characters, in mailer-friendly chunks, and passing it
 * to sendmail.  The encoding is almost the same as MIME BASE64, and is
 * protected by a simple checksum.
 *
 * Author: <NAME>
 *
 * NOTICE: This is free software.  I hope you get some use from this program.
 * In return you should think about all the nice people who give away software.
 * Maybe you should write some free software too.
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <paths.h>
#include "error.h"
#include "options.h"

#define DEF_MAX_MSG	64000	/* Default maximum mail msg minus headers. */

#define LINE_LENGTH	76	/* Chars per encode line. Divisible by 4. */

void chop_and_send(char *delta, off_t ctm_size, long max_msg_size,
	char *mail_alias);
unsigned encode_body(FILE *sm_fp, FILE *delta_fp, long msg_size);
void write_header(FILE *sfp, char *mail_alias, char *delta, int pce,
	int npieces);
void write_trailer(FILE *sfp, unsigned sum);
void apologise(char *delta, off_t ctm_size, long max_ctm_size,
	char *mail_alias);
FILE *open_sendmail(void);
int close_sendmail(FILE *fp);


int
main(int argc, char **argv)
    {
    char *delta_file;
    char *mail_alias;
    long max_msg_size = DEF_MAX_MSG;
    long max_ctm_size = 0;
    char *log_file = NULL;
    struct stat sb;

    err_prog_name(argv[0]);

    OPTIONS("[-l log] [-m maxmsgsize] [-c maxctmsize] ctm-delta mail-alias")
	NUMBER('m', max_msg_size)
	NUMBER('c', max_ctm_size)
	STRING('l', log_file)
    ENDOPTS

    if (argc != 3)
	usage();

    if (log_file != NULL)
	err_set_log(log_file);

    delta_file = argv[1];
    mail_alias = argv[2];

    if (stat(delta_file, &sb) < 0)
	{
	err("%s: %s", delta_file, strerror(errno));
	exit(1);
	}

    if (max_ctm_size != 0 && sb.st_size > max_ctm_size)
	apologise(delta_file, sb.st_size, max_ctm_size, mail_alias);
    else
	chop_and_send(delta_file, sb.st_size, max_msg_size, mail_alias);

    return 0;
    }


/*
 * Carve our CTM delta into pieces, encode them, and send them.
 */
void
chop_and_send(char *delta, off_t ctm_size, long max_msg_size, char *mail_alias)
    {
    int npieces;
    long msg_size;
    long exp_size;
    int pce;
    FILE *sfp;
    FILE *dfp;
    unsigned sum;

#define	howmany(x, y)	(((x) + ((y) - 1)) / (y))

    /*
     * Work out how many pieces we need, bearing in mind that each piece
     * grows by 4/3 when encoded.  We count the newlines too, but ignore
     * all mail headers and piece headers.  They are a "small" (almost
     * constant) per message overhead that we make the user worry about. :-)
     */
    exp_size = ctm_size * 4 / 3;
    exp_size += howmany(exp_size, LINE_LENGTH);
    npieces = howmany(exp_size, max_msg_size);
    msg_size = howmany(ctm_size, npieces);

#undef howmany

    if ((dfp = fopen(delta, "r")) == NULL)
	{
	err("cannot open '%s' for reading.", delta);
	exit(1);
	}

    for (pce = 1; pce <= npieces; pce++)
	{
	sfp = open_sendmail();
	if (sfp == NULL)
	    exit(1);
	write_header(sfp, mail_alias, delta, pce, npieces);
{'fraction_non_alphanumeric': 0.12205633369247344, 'fraction_numerical': 0.008465445590272434, 'mean_word_length': 3.563202247191011, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4209675', 'n_tokens_mistral': 2459, 'n_tokens_neox': 2359, 'n_words': 753}