ctm_dequeue.c revision 16880
116880Sgpalmer/*
216880Sgpalmer * Copyright (c) 1996, Gary J. Palmer
316880Sgpalmer * All rights reserved.
416880Sgpalmer *
516880Sgpalmer * Redistribution and use in source and binary forms, with or without
616880Sgpalmer * modification, are permitted provided that the following conditions
716880Sgpalmer * are met:
816880Sgpalmer *
916880Sgpalmer * 1. Redistributions of source code must retain the above copyright
1016880Sgpalmer *    notice, this list of conditions and the following disclaimer,
1116880Sgpalmer *    verbatim and that no modifications are made prior to this
1216880Sgpalmer *    point in the file.
1316880Sgpalmer * 2. Redistributions in binary form must reproduce the above copyright
1416880Sgpalmer *    notice, this list of conditions and the following disclaimer in the
1516880Sgpalmer *    documentation and/or other materials provided with the distribution.
1616880Sgpalmer *
1716880Sgpalmer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1816880Sgpalmer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1916880Sgpalmer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2016880Sgpalmer * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2116880Sgpalmer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2216880Sgpalmer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2316880Sgpalmer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2416880Sgpalmer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2516880Sgpalmer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2616880Sgpalmer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2716880Sgpalmer * SUCH DAMAGE.
2816880Sgpalmer *
2916880Sgpalmer *	$Id$
3016880Sgpalmer */
3116880Sgpalmer
3216880Sgpalmer/*
3316880Sgpalmer * Change this if you want to alter how many files it sends out by
3416880Sgpalmer * default
3516880Sgpalmer */
3616880Sgpalmer
3716880Sgpalmer#define DEFAULT_NUM 2
3816880Sgpalmer
3916880Sgpalmer#include <stdio.h>
4016880Sgpalmer#include <stdlib.h>
4116880Sgpalmer#include <string.h>
4216880Sgpalmer#include <unistd.h>
4316880Sgpalmer#include <fcntl.h>
4416880Sgpalmer#include <sys/types.h>
4516880Sgpalmer#include <sys/stat.h>
4616880Sgpalmer#include <fts.h>
4716880Sgpalmer#include <sys/mman.h>
4816880Sgpalmer#include <errno.h>
4916880Sgpalmer#include <paths.h>
5016880Sgpalmer#include "error.h"
5116880Sgpalmer#include "options.h"
5216880Sgpalmer
5316880Sgpalmerint fts_sort(const FTSENT **, const FTSENT **);
5416880SgpalmerFILE *open_sendmail(void);
5516880Sgpalmerint close_sendmail(FILE *fp);
5616880Sgpalmer
5716880Sgpalmerint
5816880Sgpalmermain(int argc, char **argv)
5916880Sgpalmer{
6016880Sgpalmer    char *log_file = NULL;
6116880Sgpalmer    char *queue_dir = NULL;
6216880Sgpalmer    char *list[2];
6316880Sgpalmer    char *buffer, *filename;
6416880Sgpalmer    int num_to_send = DEFAULT_NUM, piece, fp, len;
6516880Sgpalmer    FTS *fts;
6616880Sgpalmer    FTSENT *ftsent;
6716880Sgpalmer    FILE *sfp;
6816880Sgpalmer
6916880Sgpalmer    err_prog_name(argv[0]);
7016880Sgpalmer
7116880Sgpalmer    OPTIONS("[-l log] [-n num] queuedir")
7216880Sgpalmer	NUMBER('n', num_to_send)
7316880Sgpalmer	STRING('l', log_file)
7416880Sgpalmer    ENDOPTS;
7516880Sgpalmer
7616880Sgpalmer    if (argc != 2)
7716880Sgpalmer	usage();
7816880Sgpalmer
7916880Sgpalmer    queue_dir = argv[1];
8016880Sgpalmer    list[0] = queue_dir;
8116880Sgpalmer    list[1] = NULL;
8216880Sgpalmer
8316880Sgpalmer    fts = fts_open(list, FTS_PHYSICAL, fts_sort);
8416880Sgpalmer    if (fts == NULL)
8516880Sgpalmer    {
8616880Sgpalmer	err("fts failed on `%s'", queue_dir);
8716880Sgpalmer	exit(1);
8816880Sgpalmer    }
8916880Sgpalmer
9016880Sgpalmer    (void) fts_read(fts);
9116880Sgpalmer
9216880Sgpalmer    ftsent = fts_children(fts, 0);
9316880Sgpalmer    if (ftsent == NULL)
9416880Sgpalmer    {
9516880Sgpalmer	err("ftschildren failed");
9616880Sgpalmer	exit(1);
9716880Sgpalmer    }
9816880Sgpalmer
9916880Sgpalmer    /* assumption :-( */
10016880Sgpalmer    len = strlen(queue_dir) + 40;
10116880Sgpalmer    filename = malloc(len);
10216880Sgpalmer    if (filename == NULL)
10316880Sgpalmer    {
10416880Sgpalmer	err("malloc failed");
10516880Sgpalmer	exit(1);
10616880Sgpalmer    }
10716880Sgpalmer
10816880Sgpalmer    for (piece = 0; piece < num_to_send ; piece++)
10916880Sgpalmer    {
11016880Sgpalmer	/* Skip non-files and files we should ignore (ones starting with `.') */
11116880Sgpalmer
11216880Sgpalmer#define ISFILE ((ftsent->fts_info & FTS_F) == FTS_F)
11316880Sgpalmer#define IGNORE (ftsent->fts_name[0] == '.')
11416880Sgpalmer#define HASNEXT (ftsent->fts_link != NULL)
11516880Sgpalmer
11616880Sgpalmer	while(((!ISFILE) || (IGNORE)) && (HASNEXT))
11716880Sgpalmer	    ftsent = ftsent->fts_link;
11816880Sgpalmer
11916880Sgpalmer	if ((!ISFILE) || (IGNORE) || (!HASNEXT))
12016880Sgpalmer	{
12116880Sgpalmer	    err("No more chunks to mail");
12216880Sgpalmer	    exit(0);
12316880Sgpalmer	}
12416880Sgpalmer
12516880Sgpalmer#undef ISFILE
12616880Sgpalmer#undef IGNORE
12716880Sgpalmer#undef HASNEXT
12816880Sgpalmer
12916880Sgpalmer	if (snprintf(filename, len, "%s/%s", queue_dir, ftsent->fts_name) > len)
13016880Sgpalmer	    err("snprintf(filename) longer than buffer");
13116880Sgpalmer
13216880Sgpalmer	fp = open(filename, O_RDONLY, 0);
13316880Sgpalmer	if (fp <  0)
13416880Sgpalmer	{
13516880Sgpalmer	    err("open(`%s') failed, errno = %d", filename, errno);
13616880Sgpalmer	    exit(1);
13716880Sgpalmer	}
13816880Sgpalmer
13916880Sgpalmer	buffer = mmap(0, ftsent->fts_statp->st_size, PROT_READ, MAP_PRIVATE, fp, 0);
14016880Sgpalmer	if (((int) buffer) <= 0)
14116880Sgpalmer	{
14216880Sgpalmer	    err("mmap failed, errno = %d", errno);
14316880Sgpalmer	    exit(1);
14416880Sgpalmer	}
14516880Sgpalmer
14616880Sgpalmer	sfp = open_sendmail();
14716880Sgpalmer	if (sfp == NULL)
14816880Sgpalmer	    exit(1);
14916880Sgpalmer
15016880Sgpalmer	if (fwrite(buffer, ftsent->fts_statp->st_size, 1, sfp) < 1)
15116880Sgpalmer	{
15216880Sgpalmer	    err("fwrite failed: errno = %d", errno);
15316880Sgpalmer	    close_sendmail(sfp);
15416880Sgpalmer	    exit(1);
15516880Sgpalmer	}
15616880Sgpalmer
15716880Sgpalmer	if (!close_sendmail(sfp))
15816880Sgpalmer	    exit(1);
15916880Sgpalmer
16016880Sgpalmer	munmap(buffer, ftsent->fts_statp->st_size);
16116880Sgpalmer	close(fp);
16216880Sgpalmer
16316880Sgpalmer	err("sent file `%s'", ftsent->fts_name);
16416880Sgpalmer
16516880Sgpalmer	if (ftsent->fts_link != NULL)
16616880Sgpalmer	    ftsent = ftsent->fts_link;
16716880Sgpalmer    }
16816880Sgpalmer    err("exiting normally");
16916880Sgpalmer    return(0);
17016880Sgpalmer}
17116880Sgpalmer
17216880Sgpalmerint
17316880Sgpalmerfts_sort(const FTSENT ** a, const FTSENT ** b)
17416880Sgpalmer{
17516880Sgpalmer	int a_info, b_info;
17616880Sgpalmer
17716880Sgpalmer	a_info = (*a)->fts_info;
17816880Sgpalmer	if (a_info == FTS_ERR)
17916880Sgpalmer		return (0);
18016880Sgpalmer	b_info = (*b)->fts_info;
18116880Sgpalmer	if (b_info == FTS_ERR)
18216880Sgpalmer		return (0);
18316880Sgpalmer
18416880Sgpalmer	return (strcmp((*a)->fts_name, (*b)->fts_name));
18516880Sgpalmer}
18616880Sgpalmer
18716880Sgpalmer/*
18816880Sgpalmer * Start a pipe to sendmail.  Sendmail will decode the destination
18916880Sgpalmer * from the message contents.
19016880Sgpalmer */
19116880SgpalmerFILE *
19216880Sgpalmeropen_sendmail()
19316880Sgpalmer{
19416880Sgpalmer    FILE *fp;
19516880Sgpalmer    char buf[100];
19616880Sgpalmer
19716880Sgpalmer    sprintf(buf, "%s -t", _PATH_SENDMAIL);
19816880Sgpalmer    if ((fp = popen(buf, "w")) == NULL)
19916880Sgpalmer	err("cannot start sendmail");
20016880Sgpalmer    return fp;
20116880Sgpalmer}
20216880Sgpalmer
20316880Sgpalmer
20416880Sgpalmer/*
20516880Sgpalmer * Close a pipe to sendmail.  Sendmail will then do its bit.
20616880Sgpalmer * Return 1 on success, 0 on failure.
20716880Sgpalmer */
20816880Sgpalmerint
20916880Sgpalmerclose_sendmail(FILE *fp)
21016880Sgpalmer{
21116880Sgpalmer    int status;
21216880Sgpalmer
21316880Sgpalmer    fflush(fp);
21416880Sgpalmer    if (ferror(fp))
21516880Sgpalmer    {
21616880Sgpalmer	err("error writing to sendmail");
21716880Sgpalmer	return 0;
21816880Sgpalmer    }
21916880Sgpalmer
22016880Sgpalmer    if ((status = pclose(fp)) != 0)
22116880Sgpalmer	err("sendmail failed with status %d", status);
22216880Sgpalmer
22316880Sgpalmer    return (status == 0);
22416880Sgpalmer}
225