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