ctm_dequeue.c revision 17131
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 * 2917131Sgpalmer * $Id: ctm_dequeue.c,v 1.1 1996/07/01 20:53:55 gpalmer Exp $ 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 11917131Sgpalmer if ((!ISFILE) || (IGNORE)) 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); 16217131Sgpalmer 16317131Sgpalmer if (unlink(filename) < 0) 16417131Sgpalmer { 16517131Sgpalmer err("unlink of `%s' failed", filename); 16617131Sgpalmer exit(1); 16717131Sgpalmer } 16816880Sgpalmer 16916880Sgpalmer err("sent file `%s'", ftsent->fts_name); 17016880Sgpalmer 17116880Sgpalmer if (ftsent->fts_link != NULL) 17216880Sgpalmer ftsent = ftsent->fts_link; 17317131Sgpalmer else 17417131Sgpalmer break; 17516880Sgpalmer } 17617131Sgpalmer 17716880Sgpalmer err("exiting normally"); 17816880Sgpalmer return(0); 17916880Sgpalmer} 18016880Sgpalmer 18116880Sgpalmerint 18216880Sgpalmerfts_sort(const FTSENT ** a, const FTSENT ** b) 18316880Sgpalmer{ 18416880Sgpalmer int a_info, b_info; 18516880Sgpalmer 18616880Sgpalmer a_info = (*a)->fts_info; 18716880Sgpalmer if (a_info == FTS_ERR) 18816880Sgpalmer return (0); 18916880Sgpalmer b_info = (*b)->fts_info; 19016880Sgpalmer if (b_info == FTS_ERR) 19116880Sgpalmer return (0); 19216880Sgpalmer 19316880Sgpalmer return (strcmp((*a)->fts_name, (*b)->fts_name)); 19416880Sgpalmer} 19516880Sgpalmer 19616880Sgpalmer/* 19716880Sgpalmer * Start a pipe to sendmail. Sendmail will decode the destination 19816880Sgpalmer * from the message contents. 19916880Sgpalmer */ 20016880SgpalmerFILE * 20116880Sgpalmeropen_sendmail() 20216880Sgpalmer{ 20316880Sgpalmer FILE *fp; 20416880Sgpalmer char buf[100]; 20516880Sgpalmer 20616880Sgpalmer sprintf(buf, "%s -t", _PATH_SENDMAIL); 20716880Sgpalmer if ((fp = popen(buf, "w")) == NULL) 20816880Sgpalmer err("cannot start sendmail"); 20916880Sgpalmer return fp; 21016880Sgpalmer} 21116880Sgpalmer 21216880Sgpalmer 21316880Sgpalmer/* 21416880Sgpalmer * Close a pipe to sendmail. Sendmail will then do its bit. 21516880Sgpalmer * Return 1 on success, 0 on failure. 21616880Sgpalmer */ 21716880Sgpalmerint 21816880Sgpalmerclose_sendmail(FILE *fp) 21916880Sgpalmer{ 22016880Sgpalmer int status; 22116880Sgpalmer 22216880Sgpalmer fflush(fp); 22316880Sgpalmer if (ferror(fp)) 22416880Sgpalmer { 22516880Sgpalmer err("error writing to sendmail"); 22616880Sgpalmer return 0; 22716880Sgpalmer } 22816880Sgpalmer 22916880Sgpalmer if ((status = pclose(fp)) != 0) 23016880Sgpalmer err("sendmail failed with status %d", status); 23116880Sgpalmer 23216880Sgpalmer return (status == 0); 23316880Sgpalmer} 234