Added to repository
Showing
6 changed files
with
1090 additions
and
0 deletions
libmu_scm/mu_guimb.c
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #include <mu_scm.h> | ||
19 | |||
20 | static void _scheme_main (void *closure, int argc, char **argv); | ||
21 | |||
22 | void | ||
23 | mu_process_mailbox (int argc, char *argv[], guimb_param_t *param) | ||
24 | { | ||
25 | scm_boot_guile (argc, argv, _scheme_main, param); | ||
26 | } | ||
27 | |||
28 | SCM _current_mailbox; | ||
29 | SCM _user_name; | ||
30 | |||
31 | static SCM | ||
32 | catch_body (void *closure) | ||
33 | { | ||
34 | guimb_param_t *param = closure; | ||
35 | return param->catch_body (param->data, param->mbox); | ||
36 | } | ||
37 | |||
38 | void | ||
39 | _scheme_main (void *closure, int argc, char **argv) | ||
40 | { | ||
41 | guimb_param_t *param = closure; | ||
42 | SCM *scm_loc; | ||
43 | |||
44 | if (param->debug_guile) | ||
45 | { | ||
46 | SCM_DEVAL_P = 1; | ||
47 | SCM_BACKTRACE_P = 1; | ||
48 | SCM_RECORD_POSITIONS_P = 1; | ||
49 | SCM_RESET_DEBUG_MODE; | ||
50 | } | ||
51 | |||
52 | /* Initialize scheme library */ | ||
53 | mu_scm_init (); | ||
54 | |||
55 | /* Provide basic primitives */ | ||
56 | #include <mu_guimb.x> | ||
57 | |||
58 | _current_mailbox = mu_scm_mailbox_create (param->mbox); | ||
59 | scm_loc = SCM_CDRLOC (scm_sysintern ("current-mailbox", SCM_EOL)); | ||
60 | *scm_loc = _current_mailbox; | ||
61 | |||
62 | _user_name = param->user_name ? | ||
63 | scm_makfrom0str (param->user_name) : SCM_BOOL_F; | ||
64 | scm_loc = SCM_CDRLOC (scm_sysintern ("user-name", SCM_EOL)); | ||
65 | *scm_loc = _user_name; | ||
66 | |||
67 | if (param->init) | ||
68 | param->init (param->data); | ||
69 | |||
70 | do { | ||
71 | scm_internal_lazy_catch (SCM_BOOL_T, | ||
72 | catch_body, closure, | ||
73 | param->catch_handler, param->data); | ||
74 | } while (param->next && param->next (param->data, param->mbox)); | ||
75 | |||
76 | if (param->exit) | ||
77 | exit (param->exit (param->data, param->mbox)); | ||
78 | |||
79 | exit (0); | ||
80 | } |
mail.local/Makefile.am
0 → 100644
1 | AUTOMAKE_OPTIONS = ../lib/ansi2knr | ||
2 | INCLUDES =-I$(srcdir) -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir)/libmu_scm | ||
3 | |||
4 | libexec_PROGRAMS = mail.local | ||
5 | mail_local_SOURCES = main.c mailquota.c script.c mail.local.h | ||
6 | |||
7 | mail_local_LDADD = @LIBMU_SCM@ ../mailbox/libmailbox.la ../lib/libmailutils.a @GUILE_LIBS@ | ||
8 | |||
9 | install-exec-hook: | ||
10 | for i in $(libexec_PROGRAMS); do\ | ||
11 | chown root:mail $(libexecdir)/$$i;\ | ||
12 | chmod 4755 $(libexecdir)/$$i;\ | ||
13 | done |
mail.local/mail.local.h
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #if defined(HAVE_CONFIG_H) | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | #include <errno.h> | ||
22 | #include <stdio.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <unistd.h> | ||
25 | #include <string.h> | ||
26 | #include <syslog.h> | ||
27 | #include <pwd.h> | ||
28 | #include <grp.h> | ||
29 | #include <stdarg.h> | ||
30 | #include <sys/stat.h> | ||
31 | #include <sysexits.h> | ||
32 | #include "getopt.h" | ||
33 | |||
34 | #ifdef HAVE_STRINGS_H | ||
35 | # include <strings.h> | ||
36 | #endif | ||
37 | |||
38 | #include <mailutils/mailbox.h> | ||
39 | #include <mailutils/message.h> | ||
40 | #include <mailutils/error.h> | ||
41 | #include <mailutils/registrar.h> | ||
42 | #include <mailutils/stream.h> | ||
43 | #include <mailutils/mutil.h> | ||
44 | #include <mu_dbm.h> | ||
45 | |||
46 | /* Debug */ | ||
47 | extern int debug_level; | ||
48 | #define dbg() if (debug_level) debug | ||
49 | |||
50 | /* mailquota settings */ | ||
51 | #define MQUOTA_OK 0 | ||
52 | #define MQUOTA_EXCEEDED 1 | ||
53 | #define MQUOTA_UNLIMITED 2 | ||
54 | |||
55 | struct mda_data | ||
56 | { | ||
57 | FILE *fp; | ||
58 | char *progfile; | ||
59 | char *progfile_pattern; | ||
60 | char **argv; | ||
61 | char *tempfile; | ||
62 | }; | ||
63 | |||
64 | extern char *quotadbname; | ||
65 | extern int exit_code; | ||
66 | |||
67 | extern void setgroupquota (char *str); | ||
68 | extern int check_quota (char *name, size_t size, size_t *rest); | ||
69 | |||
70 | int mda (FILE *fp, char *username, mailbox_t mbox); | ||
71 | char *make_progfile_name (char *pattern, char *username); | ||
72 | |||
73 | #ifdef WITH_GUILE | ||
74 | int prog_mda (struct mda_data *data); | ||
75 | #endif | ||
76 |
mail.local/mailquota.c
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #include <mail.local.h> | ||
19 | |||
20 | #ifdef USE_DBM | ||
21 | |||
22 | #define DEFRETVAL MQUOTA_UNLIMITED | ||
23 | |||
24 | size_t groupquota = 5*1024*1024UL; | ||
25 | static int get_size (char *, size_t *, char **); | ||
26 | |||
27 | int | ||
28 | get_size (char *str, size_t *size, char **endp) | ||
29 | { | ||
30 | size_t s; | ||
31 | |||
32 | s = strtol (str, &str, 0); | ||
33 | switch (*str) | ||
34 | { | ||
35 | case 0: | ||
36 | break; | ||
37 | case 'k': | ||
38 | case 'K': | ||
39 | s *= 1024; | ||
40 | break; | ||
41 | case 'm': | ||
42 | case 'M': | ||
43 | s *= 1024*1024; | ||
44 | break; | ||
45 | default: | ||
46 | *endp = str; | ||
47 | return -1; | ||
48 | } | ||
49 | *size = s; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | int | ||
54 | check_quota (char *name, size_t size, size_t *rest) | ||
55 | { | ||
56 | DBM_FILE db; | ||
57 | DBM_DATUM named, contentd; | ||
58 | size_t quota; | ||
59 | char buffer[64]; | ||
60 | int unlimited = 0; | ||
61 | int rc; | ||
62 | |||
63 | if (!quotadbname || mu_dbm_open (quotadbname, &db, MU_STREAM_READ, 0600)) | ||
64 | return DEFRETVAL; | ||
65 | |||
66 | memset (&named, 0, sizeof named); | ||
67 | MU_DATUM_PTR (named) = name; | ||
68 | MU_DATUM_SIZE (named) = strlen (name); | ||
69 | rc = mu_dbm_fetch (db, named, &contentd); | ||
70 | if (rc || !MU_DATUM_PTR (contentd)) | ||
71 | { | ||
72 | /* User not in database, try default quota */ | ||
73 | memset (&named, 0, sizeof named); | ||
74 | MU_DATUM_PTR (named) = "DEFAULT"; | ||
75 | MU_DATUM_SIZE (named) = strlen ("DEFAULT"); | ||
76 | rc = mu_dbm_fetch (db, named, &contentd); | ||
77 | if (rc) | ||
78 | { | ||
79 | //mu_error("can't fetch data: %s", strerror (rc)); | ||
80 | return DEFRETVAL; | ||
81 | } | ||
82 | if (!MU_DATUM_PTR (contentd)) | ||
83 | return DEFRETVAL; | ||
84 | } | ||
85 | |||
86 | if (strncasecmp("none", | ||
87 | MU_DATUM_PTR (contentd), | ||
88 | MU_DATUM_SIZE (contentd)) == 0) | ||
89 | unlimited = 1; | ||
90 | else if (MU_DATUM_SIZE (contentd) > sizeof(buffer)-1) | ||
91 | { | ||
92 | mu_error ("mailbox quota for `%s' is too big: %d digits", | ||
93 | name, MU_DATUM_SIZE (contentd)); | ||
94 | quota = groupquota; | ||
95 | } | ||
96 | else | ||
97 | { | ||
98 | char *p; | ||
99 | |||
100 | strncpy(buffer, MU_DATUM_PTR (contentd), MU_DATUM_SIZE (contentd)); | ||
101 | buffer[MU_DATUM_SIZE (contentd)] = 0; | ||
102 | quota = strtoul (buffer, &p, 0); | ||
103 | if (get_size (buffer, "a, &p)) | ||
104 | { | ||
105 | mu_error ("bogus mailbox quota for `%s' (near `%s')", name, p); | ||
106 | quota = groupquota; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | mu_dbm_close (db); | ||
111 | if (unlimited) | ||
112 | return MQUOTA_UNLIMITED; | ||
113 | else if (quota < size) /* Mailbox full */ | ||
114 | return MQUOTA_EXCEEDED; | ||
115 | |||
116 | if (rest) | ||
117 | *rest = quota - size; | ||
118 | |||
119 | return MQUOTA_OK; | ||
120 | } | ||
121 | |||
122 | #endif |
mail.local/main.c
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #include <mail.local.h> | ||
19 | |||
20 | int debug_level; | ||
21 | int multiple_delivery; | ||
22 | int bounce_quota; | ||
23 | int exit_code = EX_OK; | ||
24 | uid_t uid; | ||
25 | char *maildir = MU_PATH_MAILDIR; | ||
26 | char *quotadbname = NULL; | ||
27 | int lock_timeout = 300; | ||
28 | |||
29 | #define MAXFD 64 | ||
30 | |||
31 | static void print_help (void); | ||
32 | static void print_license (void); | ||
33 | static void print_version (void); | ||
34 | void close_fds (); | ||
35 | int switch_user_id (uid_t uid); | ||
36 | FILE *make_tmp (const char *from, char **tempfile); | ||
37 | void deliver (FILE *fp, char *name); | ||
38 | void guess_retval (int ec); | ||
39 | void mailer_err (char *fmt, ...); | ||
40 | |||
41 | char short_opts[] = "hf:Llm:q:r:s:x::v"; | ||
42 | |||
43 | static struct option long_opts[] = { | ||
44 | { "from", required_argument, 0, 'f' }, | ||
45 | { "help", no_argument, 0, 'h' }, | ||
46 | { "license", no_argument, 0, 'L' }, | ||
47 | { "maildir", required_argument, 0, 'm' }, | ||
48 | { "multiple-delivery", no_argument, 0, 'M' }, | ||
49 | { "quota-db", required_argument, 0, 'q' }, | ||
50 | { "source", required_argument, 0, 's' }, | ||
51 | { "timeout", required_argument, 0, 't' }, | ||
52 | { "debug", optional_argument, 0, 'x' }, | ||
53 | { "version", no_argument, 0, 'v' }, | ||
54 | { 0, 0, 0, 0 } | ||
55 | }; | ||
56 | |||
57 | |||
58 | int | ||
59 | main (int argc, char *argv[]) | ||
60 | { | ||
61 | int c; | ||
62 | FILE *fp; | ||
63 | char *from = NULL; | ||
64 | char *progfile_pattern = NULL; | ||
65 | struct mda_data mda_data; | ||
66 | |||
67 | /* Preparative work: close inherited fds, force a reasonable umask | ||
68 | and prepare a logging. */ | ||
69 | close_fds (); | ||
70 | umask (0077); | ||
71 | |||
72 | openlog ("mail.local", LOG_PID, LOG_FACILITY); | ||
73 | mu_error_set_print (mu_syslog_error_printer); | ||
74 | |||
75 | uid = getuid (); | ||
76 | while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != EOF) | ||
77 | switch (c) | ||
78 | { | ||
79 | case 'r': | ||
80 | case 'f': | ||
81 | if (from != NULL) | ||
82 | { | ||
83 | mu_error ("multiple --from options"); | ||
84 | return 1; | ||
85 | } | ||
86 | from = optarg; | ||
87 | break; | ||
88 | |||
89 | case 'h': | ||
90 | print_help (); | ||
91 | break; | ||
92 | |||
93 | case 'L': | ||
94 | print_license (); | ||
95 | break; | ||
96 | |||
97 | case 'm': | ||
98 | maildir = optarg; | ||
99 | break; | ||
100 | |||
101 | case 'M': | ||
102 | multiple_delivery++; | ||
103 | break; | ||
104 | |||
105 | #ifdef USE_DBM | ||
106 | case 'q': | ||
107 | quotadbname = optarg; | ||
108 | break; | ||
109 | #endif | ||
110 | |||
111 | #ifdef WITH_GUILE | ||
112 | case 's': | ||
113 | progfile_pattern = optarg; | ||
114 | break; | ||
115 | #endif | ||
116 | |||
117 | case 't': | ||
118 | lock_timeout = strtoul (optarg, NULL, 0); | ||
119 | break; | ||
120 | |||
121 | case 'x': | ||
122 | if (optarg) | ||
123 | debug_level = strtoul (optarg, NULL, 0); | ||
124 | else | ||
125 | debug_level = 9; | ||
126 | break; | ||
127 | |||
128 | case 'v': | ||
129 | print_version (); | ||
130 | break; | ||
131 | |||
132 | default: | ||
133 | return 1; | ||
134 | } | ||
135 | |||
136 | argc -= optind; | ||
137 | argv += optind; | ||
138 | |||
139 | if (!argc) | ||
140 | print_help (); | ||
141 | |||
142 | maildir = mu_normalize_maildir (maildir); | ||
143 | if (!maildir) | ||
144 | { | ||
145 | mu_error ("Badly formed maildir: %s", maildir); | ||
146 | return 1; | ||
147 | } | ||
148 | |||
149 | if (!from) | ||
150 | { | ||
151 | struct passwd *pw = getpwuid (uid); | ||
152 | if (pw) | ||
153 | from = pw->pw_name; | ||
154 | else | ||
155 | { | ||
156 | mu_error ("From unknown"); | ||
157 | return 1; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | #ifdef HAVE_MYSQL | ||
162 | mu_register_getpwnam (getMpwnam); | ||
163 | #endif | ||
164 | /* Register local mbox formats. */ | ||
165 | { | ||
166 | list_t bookie; | ||
167 | registrar_get_list (&bookie); | ||
168 | list_append (bookie, mbox_record); | ||
169 | list_append (bookie, path_record); | ||
170 | /* Possible supported mailers. */ | ||
171 | list_append (bookie, sendmail_record); | ||
172 | list_append (bookie, smtp_record); | ||
173 | } | ||
174 | |||
175 | memset (&mda_data, 0, sizeof mda_data); | ||
176 | fp = make_tmp (from, &mda_data.tempfile); | ||
177 | |||
178 | if (multiple_delivery) | ||
179 | multiple_delivery = argc > 1; | ||
180 | |||
181 | #ifdef WITH_GUILE | ||
182 | mda_data.fp = fp; | ||
183 | mda_data.argv = argv; | ||
184 | mda_data.progfile_pattern = progfile_pattern; | ||
185 | |||
186 | if (progfile_pattern) | ||
187 | return prog_mda (&mda_data); | ||
188 | #endif | ||
189 | |||
190 | unlink (mda_data.tempfile); | ||
191 | for (; *argv; argv++) | ||
192 | mda (fp, *argv, NULL); | ||
193 | return exit_code; | ||
194 | } | ||
195 | |||
196 | char * | ||
197 | make_progfile_name (char *pattern, char *username) | ||
198 | { | ||
199 | char *homedir = NULL; | ||
200 | char *p, *q, *startp; | ||
201 | char *progfile; | ||
202 | int len = 0; | ||
203 | |||
204 | for (p = pattern; *p; p++) | ||
205 | { | ||
206 | if (*p == '%') | ||
207 | switch (*++p) | ||
208 | { | ||
209 | case 'u': | ||
210 | len += strlen (username); | ||
211 | break; | ||
212 | case 'h': | ||
213 | if (!homedir) | ||
214 | { | ||
215 | struct passwd *pwd = getpwnam (username); | ||
216 | if (!pwd) | ||
217 | return NULL; | ||
218 | homedir = pwd->pw_dir; | ||
219 | } | ||
220 | len += strlen (homedir); | ||
221 | break; | ||
222 | case '%': | ||
223 | len++; | ||
224 | break; | ||
225 | default: | ||
226 | len += 2; | ||
227 | } | ||
228 | else | ||
229 | len++; | ||
230 | } | ||
231 | |||
232 | progfile = malloc (len + 1); | ||
233 | if (!progfile) | ||
234 | return NULL; | ||
235 | |||
236 | startp = pattern; | ||
237 | q = progfile; | ||
238 | while (*startp && (p = strchr (startp, '%')) != NULL) | ||
239 | { | ||
240 | memcpy (q, startp, p - startp); | ||
241 | q += p - startp; | ||
242 | switch (*++p) | ||
243 | { | ||
244 | case 'u': | ||
245 | strcpy (q, username); | ||
246 | q += strlen (username); | ||
247 | break; | ||
248 | case 'h': | ||
249 | strcpy (q, homedir); | ||
250 | q += strlen (homedir); | ||
251 | break; | ||
252 | case '%': | ||
253 | *q++ = '%'; | ||
254 | break; | ||
255 | default: | ||
256 | *q++ = '%'; | ||
257 | *q++ = *p; | ||
258 | } | ||
259 | startp = p + 1; | ||
260 | } | ||
261 | if (*startp) | ||
262 | { | ||
263 | strcpy (q, startp); | ||
264 | q += strlen (startp); | ||
265 | } | ||
266 | *q = 0; | ||
267 | return progfile; | ||
268 | } | ||
269 | |||
270 | int | ||
271 | mda (FILE *fp, char *username, mailbox_t mbox) | ||
272 | { | ||
273 | if (mbox) | ||
274 | { | ||
275 | message_t mesg = NULL; | ||
276 | attribute_t attr = NULL; | ||
277 | |||
278 | mailbox_get_message (mbox, 1, &mesg); | ||
279 | message_get_attribute (mesg, &attr); | ||
280 | if (attribute_is_deleted (attr)) | ||
281 | return EX_OK; | ||
282 | } | ||
283 | |||
284 | deliver (fp, username); | ||
285 | |||
286 | if (multiple_delivery) | ||
287 | exit_code = EX_OK; | ||
288 | |||
289 | return exit_code; | ||
290 | } | ||
291 | |||
292 | void | ||
293 | close_fds () | ||
294 | { | ||
295 | int i; | ||
296 | long fdlimit = MAXFD; | ||
297 | |||
298 | #if defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX) | ||
299 | fdlimit = sysconf (_SC_OPEN_MAX); | ||
300 | #elif defined (HAVE_GETDTABLESIZE) | ||
301 | fdlimit = getdtablesize (); | ||
302 | #endif | ||
303 | |||
304 | for (i = 3; i < fdlimit; i++) | ||
305 | close (i); | ||
306 | } | ||
307 | |||
308 | int | ||
309 | switch_user_id (uid_t uid) | ||
310 | { | ||
311 | int rc; | ||
312 | #if defined(HAVE_SETREUID) | ||
313 | rc = setreuid (0, uid); | ||
314 | #elif defined(HAVE_SETRESUID) | ||
315 | rc = setresuid (-1, uid, -1); | ||
316 | #elif defined(HAVE_SETEUID) | ||
317 | rc = seteuid (uid); | ||
318 | #else | ||
319 | # error "No way to reset user privileges?" | ||
320 | #endif | ||
321 | if (rc < 0) | ||
322 | mailer_err ("setreuid(0, %d): %s (r=%d, e=%d)", | ||
323 | uid, strerror (errno), getuid (), geteuid ()); | ||
324 | return rc; | ||
325 | } | ||
326 | |||
327 | FILE * | ||
328 | make_tmp (const char *from, char **tempfile) | ||
329 | { | ||
330 | time_t t; | ||
331 | int fd = mu_tempfile (NULL, tempfile); | ||
332 | FILE *fp; | ||
333 | char *buf = NULL; | ||
334 | size_t n = 0; | ||
335 | |||
336 | if (fd == -1 || (fp = fdopen(fd, "w+")) == NULL) | ||
337 | { | ||
338 | mailer_err("unable to open temporary file"); | ||
339 | exit (exit_code); | ||
340 | } | ||
341 | |||
342 | time (&t); | ||
343 | fprintf (fp, "From %s %s", from, ctime (&t)); | ||
344 | |||
345 | while (getline(&buf, &n, stdin) > 0) { | ||
346 | if (!memcmp(buf, "From ", 5)) | ||
347 | fputc('>', fp); | ||
348 | if (fputs (buf, fp) == EOF) | ||
349 | { | ||
350 | mailer_err ("temporary file write error"); | ||
351 | fclose(fp); | ||
352 | return NULL; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | if (buf && strchr(buf, '\n') == NULL) | ||
357 | putc('\n', fp); | ||
358 | |||
359 | putc('\n', fp); | ||
360 | free (buf); | ||
361 | |||
362 | return fp; | ||
363 | } | ||
364 | |||
365 | void | ||
366 | deliver (FILE *fp, char *name) | ||
367 | { | ||
368 | mailbox_t mbox; | ||
369 | char *path; | ||
370 | url_t url = NULL; | ||
371 | size_t n = 0; | ||
372 | locker_t lock; | ||
373 | int timeout; | ||
374 | struct stat sb; | ||
375 | struct passwd *pw; | ||
376 | int status; | ||
377 | stream_t stream; | ||
378 | size_t size; | ||
379 | int failed = 0; | ||
380 | |||
381 | pw = mu_getpwnam (name); | ||
382 | if (!pw) | ||
383 | { | ||
384 | mailer_err ("%s: no such user", name); | ||
385 | exit_code = EX_UNAVAILABLE; | ||
386 | return; | ||
387 | } | ||
388 | |||
389 | path = malloc (strlen (maildir) + strlen (name) + 1); | ||
390 | if (!path) | ||
391 | { | ||
392 | mailer_err ("Out of memory"); | ||
393 | return; | ||
394 | } | ||
395 | sprintf (path, "%s%s", maildir, name); | ||
396 | |||
397 | if ((status = mailbox_create (&mbox, path)) != 0) | ||
398 | { | ||
399 | mailer_err ("can't open mailbox %s: %s", path, strerror (status)); | ||
400 | free (path); | ||
401 | return; | ||
402 | } | ||
403 | |||
404 | free (path); | ||
405 | |||
406 | mailbox_get_url (mbox, &url); | ||
407 | path = (char*) url_to_string (url); | ||
408 | |||
409 | /* Actually open the mailbox. Switch to the user's euid to make | ||
410 | sure the maildrop file will have right privileges, in case it | ||
411 | will be created */ | ||
412 | if (switch_user_id (pw->pw_uid)) | ||
413 | return; | ||
414 | status = mailbox_open (mbox, MU_STREAM_RDWR|MU_STREAM_CREAT); | ||
415 | if (switch_user_id (0)) | ||
416 | return; | ||
417 | if (status != 0) | ||
418 | { | ||
419 | mailer_err ("can't open mailbox %s: %s", path, strerror (status)); | ||
420 | mailbox_destroy (&mbox); | ||
421 | return; | ||
422 | } | ||
423 | |||
424 | mailbox_get_locker (mbox, &lock); | ||
425 | |||
426 | timeout = lock_timeout; | ||
427 | while ((status = locker_lock (lock, MU_LOCKER_WRLOCK))) | ||
428 | { | ||
429 | if (timeout-- <= 0) | ||
430 | break; | ||
431 | sleep (1); | ||
432 | } | ||
433 | |||
434 | if (status) | ||
435 | { | ||
436 | mailer_err ("cannot lock mailbox '%s': %s", path, strerror (status)); | ||
437 | mailbox_destroy (&mbox); | ||
438 | return; | ||
439 | } | ||
440 | |||
441 | if ((status = mailbox_get_stream (mbox, &stream))) | ||
442 | { | ||
443 | mailer_err ("can't get stream for mailbox %s: %s", | ||
444 | path, strerror (status)); | ||
445 | mailbox_destroy (&mbox); | ||
446 | return; | ||
447 | } | ||
448 | |||
449 | if ((status = stream_size (stream, (off_t *) &size))) | ||
450 | { | ||
451 | mailer_err ("can't get stream size (mailbox %s): %s", | ||
452 | path, strerror (status)); | ||
453 | mailbox_destroy (&mbox); | ||
454 | return; | ||
455 | } | ||
456 | |||
457 | #if defined(USE_DBM) | ||
458 | switch (check_quota (name, size, &n)) | ||
459 | { | ||
460 | case MQUOTA_EXCEEDED: | ||
461 | mailer_err ("%s: mailbox quota exceeded for this recipient", name); | ||
462 | exit_code = EX_UNAVAILABLE; | ||
463 | failed++; | ||
464 | break; | ||
465 | case MQUOTA_UNLIMITED: | ||
466 | break; | ||
467 | default: | ||
468 | if (fstat (fileno (fp), &sb)) | ||
469 | { | ||
470 | mailer_err ("cannot stat tempfile: %s", strerror (errno)); | ||
471 | exit_code = EX_UNAVAILABLE; | ||
472 | failed++; | ||
473 | } | ||
474 | else if (sb.st_size > n) | ||
475 | { | ||
476 | mailer_err ("%s: message would exceed maximum mailbox size for this recipient", | ||
477 | name); | ||
478 | exit_code = EX_UNAVAILABLE; | ||
479 | failed++; | ||
480 | } | ||
481 | break; | ||
482 | } | ||
483 | #endif | ||
484 | |||
485 | if (!failed && switch_user_id (pw->pw_uid) == 0) | ||
486 | { | ||
487 | off_t off = size; | ||
488 | size_t nwr; | ||
489 | char *buf = NULL; | ||
490 | |||
491 | n = 0; | ||
492 | status = 0; | ||
493 | fseek (fp, 0, SEEK_SET); | ||
494 | while (getline(&buf, &n, fp) > 0) { | ||
495 | status = stream_write (stream, buf, strlen (buf), off, &nwr); | ||
496 | if (status) | ||
497 | { | ||
498 | mailer_err ("error writing to mailbox: %s", strerror (status)); | ||
499 | break; | ||
500 | } | ||
501 | off += nwr; | ||
502 | } | ||
503 | free (buf); | ||
504 | switch_user_id (0); | ||
505 | } | ||
506 | |||
507 | locker_unlock (lock); | ||
508 | /* FIXME: Flush the data */ | ||
509 | mailbox_close (mbox); | ||
510 | mailbox_destroy (&mbox); | ||
511 | #if 0 /*FIXME*/ | ||
512 | if (!failed) | ||
513 | notify_biff (name, size); | ||
514 | #endif | ||
515 | } | ||
516 | |||
517 | void | ||
518 | mailer_err (char *fmt, ...) | ||
519 | { | ||
520 | va_list ap; | ||
521 | |||
522 | guess_retval (errno); | ||
523 | va_start (ap, fmt); | ||
524 | vfprintf (stderr, fmt, ap); | ||
525 | fprintf (stderr, "\n"); | ||
526 | mu_verror (fmt, ap); | ||
527 | va_end (ap); | ||
528 | } | ||
529 | |||
530 | int temp_errors[] = { | ||
531 | #ifdef EAGAIN | ||
532 | EAGAIN, /* Try again */ | ||
533 | #endif | ||
534 | #ifdef EDQUOT | ||
535 | EDQUOT, /* Disk quota esceeded */ | ||
536 | #endif | ||
537 | #ifdef EBUSY | ||
538 | EBUSY, /* Device or resource busy */ | ||
539 | #endif | ||
540 | #ifdef EPROCLIM | ||
541 | EPROCLIM, /* Too many processes */ | ||
542 | #endif | ||
543 | #ifdef EUSERS | ||
544 | EUSERS, /* Too many users */ | ||
545 | #endif | ||
546 | #ifdef ECONNABORTED | ||
547 | ECONNABORTED, /* Software caused connection abort */ | ||
548 | #endif | ||
549 | #ifdef ECONNREFUSED | ||
550 | ECONNREFUSED, /* Connection refused */ | ||
551 | #endif | ||
552 | #ifdef ECONNRESET | ||
553 | ECONNRESET, /* Connection reset by peer */ | ||
554 | #endif | ||
555 | #ifdef EDEADLK | ||
556 | EDEADLK, /* Resource deadlock would occur */ | ||
557 | #endif | ||
558 | #ifdef EDEADLOCK | ||
559 | EDEADLOCK, /* Resource deadlock would occur */ | ||
560 | #endif | ||
561 | #ifdef EFBIG | ||
562 | EFBIG, /* File too large */ | ||
563 | #endif | ||
564 | #ifdef EHOSTDOWN | ||
565 | EHOSTDOWN, /* Host is down */ | ||
566 | #endif | ||
567 | #ifdef EHOSTUNREACH | ||
568 | EHOSTUNREACH, /* No route to host */ | ||
569 | #endif | ||
570 | #ifdef EMFILE | ||
571 | EMFILE, /* Too many open files */ | ||
572 | #endif | ||
573 | #ifdef ENETDOWN | ||
574 | ENETDOWN, /* Network is down */ | ||
575 | #endif | ||
576 | #ifdef ENETUNREACH | ||
577 | ENETUNREACH, /* Network is unreachable */ | ||
578 | #endif | ||
579 | #ifdef ENETRESET | ||
580 | ENETRESET, /* Network dropped connection because of reset */ | ||
581 | #endif | ||
582 | #ifdef ENFILE | ||
583 | ENFILE, /* File table overflow */ | ||
584 | #endif | ||
585 | #ifdef ENOBUFS | ||
586 | ENOBUFS, /* No buffer space available */ | ||
587 | #endif | ||
588 | #ifdef ENOMEM | ||
589 | ENOMEM, /* Out of memory */ | ||
590 | #endif | ||
591 | #ifdef ENOSPC | ||
592 | ENOSPC, /* No space left on device */ | ||
593 | #endif | ||
594 | #ifdef EROFS | ||
595 | EROFS, /* Read-only file system */ | ||
596 | #endif | ||
597 | #ifdef ESTALE | ||
598 | ESTALE, /* Stale NFS file handle */ | ||
599 | #endif | ||
600 | #ifdef ETIMEDOUT | ||
601 | ETIMEDOUT, /* Connection timed out */ | ||
602 | #endif | ||
603 | #ifdef EWOULDBLOCK | ||
604 | EWOULDBLOCK, /* Operation would block */ | ||
605 | #endif | ||
606 | }; | ||
607 | |||
608 | |||
609 | void | ||
610 | guess_retval (int ec) | ||
611 | { | ||
612 | int i; | ||
613 | /* Temporary failures override hard errors. */ | ||
614 | if (exit_code == EX_TEMPFAIL) | ||
615 | return; | ||
616 | for (i = 0; i < sizeof (temp_errors)/sizeof (temp_errors[0]); i++) | ||
617 | if (temp_errors[i] == ec) | ||
618 | { | ||
619 | exit_code = EX_TEMPFAIL; | ||
620 | return; | ||
621 | } | ||
622 | exit_code = EX_UNAVAILABLE; | ||
623 | } | ||
624 | |||
625 | void | ||
626 | print_help () | ||
627 | { | ||
628 | static char help_message[] = | ||
629 | "Usage: mail.local [OPTIONS] recipient [recipient...]\n" | ||
630 | "Options are:\n" | ||
631 | " -f, --from ADDR Specify the sender's name\n" | ||
632 | " -h, --help Display this help and exit\n" | ||
633 | " -L, --license Display GNU General Public License\n" | ||
634 | " -m, --maildir PATH Specify path to mailspool directory\n" | ||
635 | " -M, --multiple-delivery Don't return errors when delivering to multiple\n" | ||
636 | " recipients\n" | ||
637 | #ifdef USE_DBM | ||
638 | " -q, --quota-db FILE Specify path to quota database.\n" | ||
639 | #endif | ||
640 | #ifdef WITH_GUILE | ||
641 | " -s, --source PATTERN Set name pattern for user-defined mail filters.\n" | ||
642 | #endif | ||
643 | " -t, --timeout NUMBER Set timeout for acquiring the lockfile\n" | ||
644 | " -x, --debug NUMBER Set debugging level\n" | ||
645 | " -v, --version Display program version and exit.\n" | ||
646 | "\nReport bugs to bug-mailutils@gnu.org\n"; | ||
647 | |||
648 | printf ("%s", help_message); | ||
649 | exit (0); | ||
650 | } | ||
651 | |||
652 | void | ||
653 | print_license () | ||
654 | { | ||
655 | static char license_text[] = | ||
656 | " This program is free software; you can redistribute it and/or modify\n" | ||
657 | " it under the terms of the GNU General Public License as published by\n" | ||
658 | " the Free Software Foundation; either version 2, or (at your option)\n" | ||
659 | " any later version.\n" | ||
660 | "\n" | ||
661 | " This program is distributed in the hope that it will be useful,\n" | ||
662 | " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" | ||
663 | " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" | ||
664 | " GNU General Public License for more details.\n" | ||
665 | "\n" | ||
666 | " You should have received a copy of the GNU General Public License\n" | ||
667 | " along with this program; if not, write to the Free Software\n" | ||
668 | " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"; | ||
669 | printf ("%s", license_text); | ||
670 | exit (0); | ||
671 | } | ||
672 | |||
673 | void | ||
674 | print_version () | ||
675 | { | ||
676 | printf ("mail.local ("PACKAGE " " VERSION ")\n"); | ||
677 | exit (0); | ||
678 | } | ||
679 |
mail.local/script.c
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #include <mail.local.h> | ||
19 | |||
20 | #ifdef WITH_GUILE | ||
21 | #include <mu_scm.h> | ||
22 | |||
23 | SCM mda_catch_body (void *data, mailbox_t mbox); | ||
24 | SCM mda_catch_handler (void *unused, SCM tag, SCM throw_args); | ||
25 | int mda_next (void *data, mailbox_t mbox); | ||
26 | int mda_exit (void *data, mailbox_t mbox); | ||
27 | int mda_init (void *data); | ||
28 | |||
29 | int | ||
30 | prog_mda (struct mda_data *data) | ||
31 | { | ||
32 | char *x_argv[2]; | ||
33 | guimb_param_t param; | ||
34 | mailbox_t mbox; | ||
35 | |||
36 | x_argv[0] = "mail.local"; | ||
37 | x_argv[1] = NULL; | ||
38 | |||
39 | fflush (data->fp); | ||
40 | if (mailbox_create (&mbox, data->tempfile) | ||
41 | || mailbox_open (mbox, MU_STREAM_RDWR) != 0) | ||
42 | { | ||
43 | mailer_err ("can't open temporary storage"); | ||
44 | return EX_UNAVAILABLE; | ||
45 | } | ||
46 | |||
47 | unlink (data->tempfile); | ||
48 | |||
49 | param.debug_guile = 1 /*FIXME*/; | ||
50 | param.mbox = mbox; | ||
51 | param.user_name = NULL; | ||
52 | param.init = mda_init; | ||
53 | param.catch_body = mda_catch_body; | ||
54 | param.catch_handler = mda_catch_handler; | ||
55 | param.next = mda_next; | ||
56 | param.exit = mda_exit; | ||
57 | param.data = data; | ||
58 | |||
59 | mu_process_mailbox (1, x_argv, ¶m); | ||
60 | return EX_UNAVAILABLE; | ||
61 | } | ||
62 | |||
63 | int | ||
64 | mda_init (void *data) | ||
65 | { | ||
66 | struct mda_data *md = data; | ||
67 | md->progfile = make_progfile_name (md->progfile_pattern, md->argv[0]); | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | SCM | ||
72 | mda_catch_body (void *data, mailbox_t mbox) | ||
73 | { | ||
74 | struct mda_data *md = data; | ||
75 | |||
76 | if (access (md->progfile, R_OK)) | ||
77 | { | ||
78 | syslog (LOG_ERR, "access to %s failed: %m", md->progfile); | ||
79 | } | ||
80 | else | ||
81 | scm_primitive_load (scm_makfrom0str (md->progfile)); | ||
82 | mda (md->fp, md->argv[0], mbox); | ||
83 | return SCM_BOOL_F; | ||
84 | } | ||
85 | |||
86 | SCM | ||
87 | mda_catch_handler (void *data, SCM tag, SCM throw_args) | ||
88 | { | ||
89 | exit_code = EX_TEMPFAIL; | ||
90 | return scm_handle_by_message_noexit ("mail.local", tag, throw_args); | ||
91 | } | ||
92 | |||
93 | int | ||
94 | mda_next (void *data, mailbox_t mbox) | ||
95 | { | ||
96 | struct mda_data *md = data; | ||
97 | message_t mesg = NULL; | ||
98 | attribute_t attr = NULL; | ||
99 | |||
100 | md->argv++; | ||
101 | if (*md->argv == NULL) | ||
102 | return 0; | ||
103 | if (md->progfile) | ||
104 | free (md->progfile); | ||
105 | md->progfile = make_progfile_name (md->progfile_pattern, *md->argv); | ||
106 | |||
107 | mailbox_get_message (mbox, 1, &mesg); | ||
108 | message_get_attribute (mesg, &attr); | ||
109 | attribute_unset_deleted (attr); | ||
110 | |||
111 | return md->progfile != NULL; | ||
112 | } | ||
113 | |||
114 | int | ||
115 | mda_exit (void *data, mailbox_t mbox) | ||
116 | { | ||
117 | return exit_code; | ||
118 | } | ||
119 | |||
120 | #endif |
-
Please register or sign in to post a comment