ctm_dequeue.c revision 18119
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 * 2918119Speter * $Id: ctm_dequeue.c,v 1.4 1996/09/07 19:46:29 peter 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 7918119Speter if (log_file) 8018119Speter err_set_log(log_file); 8118119Speter 8216880Sgpalmer queue_dir = argv[1]; 8316880Sgpalmer list[0] = queue_dir; 8416880Sgpalmer list[1] = NULL; 8516880Sgpalmer 8616880Sgpalmer fts = fts_open(list, FTS_PHYSICAL, fts_sort); 8716880Sgpalmer if (fts == NULL) 8816880Sgpalmer { 8916880Sgpalmer err("fts failed on `%s'", queue_dir); 9016880Sgpalmer exit(1); 9116880Sgpalmer } 9216880Sgpalmer 9316880Sgpalmer (void) fts_read(fts); 9416880Sgpalmer 9516880Sgpalmer ftsent = fts_children(fts, 0); 9616880Sgpalmer if (ftsent == NULL) 9716880Sgpalmer { 9818114Speter if (errno) { 9918114Speter err("ftschildren failed"); 10018114Speter exit(1); 10118114Speter } else 10218114Speter exit(0); 10316880Sgpalmer } 10416880Sgpalmer 10516880Sgpalmer /* assumption :-( */ 10616880Sgpalmer len = strlen(queue_dir) + 40; 10716880Sgpalmer filename = malloc(len); 10816880Sgpalmer if (filename == NULL) 10916880Sgpalmer { 11016880Sgpalmer err("malloc failed"); 11116880Sgpalmer exit(1); 11216880Sgpalmer } 11316880Sgpalmer 11416880Sgpalmer for (piece = 0; piece < num_to_send ; piece++) 11516880Sgpalmer { 11616880Sgpalmer /* Skip non-files and files we should ignore (ones starting with `.') */ 11716880Sgpalmer 11816880Sgpalmer#define ISFILE ((ftsent->fts_info & FTS_F) == FTS_F) 11916880Sgpalmer#define IGNORE (ftsent->fts_name[0] == '.') 12016880Sgpalmer#define HASNEXT (ftsent->fts_link != NULL) 12116880Sgpalmer 12216880Sgpalmer while(((!ISFILE) || (IGNORE)) && (HASNEXT)) 12316880Sgpalmer ftsent = ftsent->fts_link; 12416880Sgpalmer 12517131Sgpalmer if ((!ISFILE) || (IGNORE)) 12616880Sgpalmer { 12716880Sgpalmer err("No more chunks to mail"); 12816880Sgpalmer exit(0); 12916880Sgpalmer } 13016880Sgpalmer 13116880Sgpalmer#undef ISFILE 13216880Sgpalmer#undef IGNORE 13316880Sgpalmer#undef HASNEXT 13416880Sgpalmer 13516880Sgpalmer if (snprintf(filename, len, "%s/%s", queue_dir, ftsent->fts_name) > len) 13616880Sgpalmer err("snprintf(filename) longer than buffer"); 13716880Sgpalmer 13816880Sgpalmer fp = open(filename, O_RDONLY, 0); 13916880Sgpalmer if (fp < 0) 14016880Sgpalmer { 14116880Sgpalmer err("open(`%s') failed, errno = %d", filename, errno); 14216880Sgpalmer exit(1); 14316880Sgpalmer } 14416880Sgpalmer 14516880Sgpalmer buffer = mmap(0, ftsent->fts_statp->st_size, PROT_READ, MAP_PRIVATE, fp, 0); 14616880Sgpalmer if (((int) buffer) <= 0) 14716880Sgpalmer { 14816880Sgpalmer err("mmap failed, errno = %d", errno); 14916880Sgpalmer exit(1); 15016880Sgpalmer } 15116880Sgpalmer 15216880Sgpalmer sfp = open_sendmail(); 15316880Sgpalmer if (sfp == NULL) 15416880Sgpalmer exit(1); 15516880Sgpalmer 15616880Sgpalmer if (fwrite(buffer, ftsent->fts_statp->st_size, 1, sfp) < 1) 15716880Sgpalmer { 15816880Sgpalmer err("fwrite failed: errno = %d", errno); 15916880Sgpalmer close_sendmail(sfp); 16016880Sgpalmer exit(1); 16116880Sgpalmer } 16216880Sgpalmer 16316880Sgpalmer if (!close_sendmail(sfp)) 16416880Sgpalmer exit(1); 16516880Sgpalmer 16616880Sgpalmer munmap(buffer, ftsent->fts_statp->st_size); 16716880Sgpalmer close(fp); 16817131Sgpalmer 16917131Sgpalmer if (unlink(filename) < 0) 17017131Sgpalmer { 17117131Sgpalmer err("unlink of `%s' failed", filename); 17217131Sgpalmer exit(1); 17317131Sgpalmer } 17416880Sgpalmer 17516880Sgpalmer err("sent file `%s'", ftsent->fts_name); 17616880Sgpalmer 17716880Sgpalmer if (ftsent->fts_link != NULL) 17816880Sgpalmer ftsent = ftsent->fts_link; 17917131Sgpalmer else 18017131Sgpalmer break; 18116880Sgpalmer } 18217131Sgpalmer 18316880Sgpalmer err("exiting normally"); 18416880Sgpalmer return(0); 18516880Sgpalmer} 18616880Sgpalmer 18716880Sgpalmerint 18816880Sgpalmerfts_sort(const FTSENT ** a, const FTSENT ** b) 18916880Sgpalmer{ 19016880Sgpalmer int a_info, b_info; 19116880Sgpalmer 19216880Sgpalmer a_info = (*a)->fts_info; 19316880Sgpalmer if (a_info == FTS_ERR) 19416880Sgpalmer return (0); 19516880Sgpalmer b_info = (*b)->fts_info; 19616880Sgpalmer if (b_info == FTS_ERR) 19716880Sgpalmer return (0); 19816880Sgpalmer 19916880Sgpalmer return (strcmp((*a)->fts_name, (*b)->fts_name)); 20016880Sgpalmer} 20116880Sgpalmer 20216880Sgpalmer/* 20316880Sgpalmer * Start a pipe to sendmail. Sendmail will decode the destination 20416880Sgpalmer * from the message contents. 20516880Sgpalmer */ 20616880SgpalmerFILE * 20716880Sgpalmeropen_sendmail() 20816880Sgpalmer{ 20916880Sgpalmer FILE *fp; 21016880Sgpalmer char buf[100]; 21116880Sgpalmer 21218110Speter sprintf(buf, "%s -odq -t", _PATH_SENDMAIL); 21316880Sgpalmer if ((fp = popen(buf, "w")) == NULL) 21416880Sgpalmer err("cannot start sendmail"); 21516880Sgpalmer return fp; 21616880Sgpalmer} 21716880Sgpalmer 21816880Sgpalmer 21916880Sgpalmer/* 22016880Sgpalmer * Close a pipe to sendmail. Sendmail will then do its bit. 22116880Sgpalmer * Return 1 on success, 0 on failure. 22216880Sgpalmer */ 22316880Sgpalmerint 22416880Sgpalmerclose_sendmail(FILE *fp) 22516880Sgpalmer{ 22616880Sgpalmer int status; 22716880Sgpalmer 22816880Sgpalmer fflush(fp); 22916880Sgpalmer if (ferror(fp)) 23016880Sgpalmer { 23116880Sgpalmer err("error writing to sendmail"); 23216880Sgpalmer return 0; 23316880Sgpalmer } 23416880Sgpalmer 23516880Sgpalmer if ((status = pclose(fp)) != 0) 23616880Sgpalmer err("sendmail failed with status %d", status); 23716880Sgpalmer 23816880Sgpalmer return (status == 0); 23916880Sgpalmer} 240