ctm_dequeue.c (18119) | ctm_dequeue.c (19984) |
---|---|
1/* 2 * Copyright (c) 1996, Gary J. Palmer 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * | 1/* 2 * Copyright (c) 1996, Gary J. Palmer 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * |
29 * $Id: ctm_dequeue.c,v 1.4 1996/09/07 19:46:29 peter Exp $ | 29 * $Id: ctm_dequeue.c,v 1.5 1996/09/07 20:41:09 peter Exp $ |
30 */ 31 | 30 */ 31 |
32/* 33 * Change this if you want to alter how many files it sends out by 34 * default | 32/* 33 * ctm_dequeue: Dequeue queued delta pieces and mail them. 34 * 35 * The pieces have already been packaged up as mail messages by ctm_smail, 36 * and will be simply passed to sendmail in alphabetical order. |
35 */ 36 | 37 */ 38 |
37#define DEFAULT_NUM 2 38 | |
39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include <unistd.h> 43#include <fcntl.h> 44#include <sys/types.h> 45#include <sys/stat.h> | 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include <unistd.h> 43#include <fcntl.h> 44#include <sys/types.h> 45#include <sys/stat.h> |
46#include <sys/wait.h> |
|
46#include <fts.h> | 47#include <fts.h> |
47#include <sys/mman.h> | 48#include <limits.h> |
48#include <errno.h> 49#include <paths.h> 50#include "error.h" 51#include "options.h" 52 | 49#include <errno.h> 50#include <paths.h> 51#include "error.h" 52#include "options.h" 53 |
54#define DEFAULT_NUM 1 /* Default number of pieces mailed per run. */ 55 |
|
53int fts_sort(const FTSENT **, const FTSENT **); | 56int fts_sort(const FTSENT **, const FTSENT **); |
54FILE *open_sendmail(void); 55int close_sendmail(FILE *fp); | 57int run_sendmail(int ifd); |
56 57int 58main(int argc, char **argv) 59{ 60 char *log_file = NULL; 61 char *queue_dir = NULL; 62 char *list[2]; | 58 59int 60main(int argc, char **argv) 61{ 62 char *log_file = NULL; 63 char *queue_dir = NULL; 64 char *list[2]; |
63 char *buffer, *filename; 64 int num_to_send = DEFAULT_NUM, piece, fp, len; | 65 int num_to_send = DEFAULT_NUM, chunk; 66 int fd; |
65 FTS *fts; 66 FTSENT *ftsent; | 67 FTS *fts; 68 FTSENT *ftsent; |
67 FILE *sfp; | 69 int piece, npieces; 70 char filename[PATH_MAX]; |
68 69 err_prog_name(argv[0]); 70 71 OPTIONS("[-l log] [-n num] queuedir") 72 NUMBER('n', num_to_send) 73 STRING('l', log_file) | 71 72 err_prog_name(argv[0]); 73 74 OPTIONS("[-l log] [-n num] queuedir") 75 NUMBER('n', num_to_send) 76 STRING('l', log_file) |
74 ENDOPTS; | 77 ENDOPTS |
75 76 if (argc != 2) 77 usage(); 78 79 if (log_file) 80 err_set_log(log_file); 81 82 queue_dir = argv[1]; 83 list[0] = queue_dir; 84 list[1] = NULL; 85 | 78 79 if (argc != 2) 80 usage(); 81 82 if (log_file) 83 err_set_log(log_file); 84 85 queue_dir = argv[1]; 86 list[0] = queue_dir; 87 list[1] = NULL; 88 |
86 fts = fts_open(list, FTS_PHYSICAL, fts_sort); | 89 fts = fts_open(list, FTS_PHYSICAL|FTS_COMFOLLOW, fts_sort); |
87 if (fts == NULL) 88 { 89 err("fts failed on `%s'", queue_dir); 90 exit(1); 91 } 92 | 90 if (fts == NULL) 91 { 92 err("fts failed on `%s'", queue_dir); 93 exit(1); 94 } 95 |
93 (void) fts_read(fts); 94 95 ftsent = fts_children(fts, 0); 96 if (ftsent == NULL) | 96 ftsent = fts_read(fts); 97 if (ftsent == NULL || ftsent->fts_info != FTS_D) |
97 { | 98 { |
98 if (errno) { 99 err("ftschildren failed"); 100 exit(1); 101 } else 102 exit(0); | 99 err("not a directory: %s", queue_dir); 100 exit(1); |
103 } 104 | 101 } 102 |
105 /* assumption :-( */ 106 len = strlen(queue_dir) + 40; 107 filename = malloc(len); 108 if (filename == NULL) | 103 ftsent = fts_children(fts, 0); 104 if (ftsent == NULL && errno) |
109 { | 105 { |
110 err("malloc failed"); | 106 err("*ftschildren failed"); |
111 exit(1); 112 } 113 | 107 exit(1); 108 } 109 |
114 for (piece = 0; piece < num_to_send ; piece++) | 110 for (chunk = 1; ftsent != NULL; ftsent = ftsent->fts_link) |
115 { | 111 { |
116 /* Skip non-files and files we should ignore (ones starting with `.') */ | 112 /* 113 * Skip non-files and ctm_smail tmp files (ones starting with `.') 114 */ 115 if (ftsent->fts_info != FTS_F || ftsent->fts_name[0] == '.') 116 continue; |
117 | 117 |
118#define ISFILE ((ftsent->fts_info & FTS_F) == FTS_F) 119#define IGNORE (ftsent->fts_name[0] == '.') 120#define HASNEXT (ftsent->fts_link != NULL) 121 122 while(((!ISFILE) || (IGNORE)) && (HASNEXT)) 123 ftsent = ftsent->fts_link; 124 125 if ((!ISFILE) || (IGNORE)) | 118 sprintf(filename, "%s/%s", queue_dir, ftsent->fts_name); 119 fd = open(filename, O_RDONLY); 120 if (fd < 0) |
126 { | 121 { |
127 err("No more chunks to mail"); 128 exit(0); 129 } 130 131#undef ISFILE 132#undef IGNORE 133#undef HASNEXT 134 135 if (snprintf(filename, len, "%s/%s", queue_dir, ftsent->fts_name) > len) 136 err("snprintf(filename) longer than buffer"); 137 138 fp = open(filename, O_RDONLY, 0); 139 if (fp < 0) 140 { 141 err("open(`%s') failed, errno = %d", filename, errno); | 122 err("*open: %s", filename); |
142 exit(1); 143 } 144 | 123 exit(1); 124 } 125 |
145 buffer = mmap(0, ftsent->fts_statp->st_size, PROT_READ, MAP_PRIVATE, fp, 0); 146 if (((int) buffer) <= 0) 147 { 148 err("mmap failed, errno = %d", errno); | 126 if (run_sendmail(fd)) |
149 exit(1); | 127 exit(1); |
150 } | |
151 | 128 |
152 sfp = open_sendmail(); 153 if (sfp == NULL) 154 exit(1); | 129 close(fd); |
155 | 130 |
156 if (fwrite(buffer, ftsent->fts_statp->st_size, 1, sfp) < 1) 157 { 158 err("fwrite failed: errno = %d", errno); 159 close_sendmail(sfp); 160 exit(1); 161 } 162 163 if (!close_sendmail(sfp)) 164 exit(1); 165 166 munmap(buffer, ftsent->fts_statp->st_size); 167 close(fp); 168 | |
169 if (unlink(filename) < 0) 170 { | 131 if (unlink(filename) < 0) 132 { |
171 err("unlink of `%s' failed", filename); | 133 err("*unlink: %s", filename); |
172 exit(1); 173 } 174 | 134 exit(1); 135 } 136 |
175 err("sent file `%s'", ftsent->fts_name); | 137 /* 138 * Deduce the delta, piece number, and number of pieces from 139 * the name of the file in the queue. Ideally, we should be 140 * able to get the mail alias name too. 141 * 142 * NOTE: This depends intimately on the queue name used in ctm_smail. 143 */ 144 npieces = atoi(&ftsent->fts_name[ftsent->fts_namelen-3]); 145 piece = atoi(&ftsent->fts_name[ftsent->fts_namelen-7]); 146 err("%.*s %d/%d sent", ftsent->fts_namelen-8, ftsent->fts_name, 147 piece, npieces); |
176 | 148 |
177 if (ftsent->fts_link != NULL) 178 ftsent = ftsent->fts_link; 179 else | 149 if (chunk++ == num_to_send) |
180 break; 181 } 182 | 150 break; 151 } 152 |
183 err("exiting normally"); | 153 fts_close(fts); 154 |
184 return(0); 185} 186 187int 188fts_sort(const FTSENT ** a, const FTSENT ** b) 189{ | 155 return(0); 156} 157 158int 159fts_sort(const FTSENT ** a, const FTSENT ** b) 160{ |
190 int a_info, b_info; | 161 if ((*a)->fts_info != FTS_F) 162 return(0); 163 if ((*a)->fts_info != FTS_F) 164 return(0); |
191 | 165 |
192 a_info = (*a)->fts_info; 193 if (a_info == FTS_ERR) 194 return (0); 195 b_info = (*b)->fts_info; 196 if (b_info == FTS_ERR) 197 return (0); 198 199 return (strcmp((*a)->fts_name, (*b)->fts_name)); | 166 return (strcmp((*a)->fts_name, (*b)->fts_name)); |
200} 201 202/* | 167} 168 169/* |
203 * Start a pipe to sendmail. Sendmail will decode the destination 204 * from the message contents. | 170 * Run sendmail with the given file descriptor as standard input. 171 * Sendmail will decode the destination from the message contents. 172 * Returns 0 on success, 1 on failure. |
205 */ | 173 */ |
206FILE * 207open_sendmail() 208{ 209 FILE *fp; 210 char buf[100]; 211 212 sprintf(buf, "%s -odq -t", _PATH_SENDMAIL); 213 if ((fp = popen(buf, "w")) == NULL) 214 err("cannot start sendmail"); 215 return fp; 216} 217 218 219/* 220 * Close a pipe to sendmail. Sendmail will then do its bit. 221 * Return 1 on success, 0 on failure. 222 */ | |
223int | 174int |
224close_sendmail(FILE *fp) | 175run_sendmail(int ifd) |
225{ | 176{ |
177 pid_t child, pid; |
|
226 int status; | 178 int status; |
227 228 fflush(fp); 229 if (ferror(fp)) | 179 180 switch (child = fork()) |
230 { | 181 { |
231 err("error writing to sendmail"); 232 return 0; | 182 case -1: 183 err("*fork"); 184 return(1); 185 186 case 0: /* Child */ 187 dup2(ifd, 0); 188 execl(_PATH_SENDMAIL, _PATH_SENDMAIL, "-odq", "-t", NULL); 189 err("*exec: %s", _PATH_SENDMAIL); 190 _exit(1); 191 192 default: /* Parent */ 193 while ((pid = wait(&status)) != child) 194 { 195 if (pid == -1 && errno != EINTR) 196 { 197 err("*wait"); 198 return(1); 199 } 200 } 201 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 202 { 203 err("sendmail failed"); 204 return(1); 205 } |
233 } | 206 } |
234 235 if ((status = pclose(fp)) != 0) 236 err("sendmail failed with status %d", status); 237 238 return (status == 0); | 207 208 return(0); |
239} | 209} |