Codebase list fdm / 1909c4f
Expand leading ~s on paths and commands. Nicholas Marriott 17 years ago
22 changed file(s) with 142 addition(s) and 41 deletion(s). Raw diff Collapse all Expand all
00 12 March 2007
11
2 * Expand leading ~s into home directories where appropriate.
23 * Section headings are now numbered in MANUAL.
34
45 11 March 2007
222222 %anum = 57
223223 include "/etc/file-number-%{anum}"
224224
225 Macros are not substituted in strings specified using single-quotes.
226
225227 5 Invoking fdm =================================================================
226228
227229 fdm may be invoked manually from the command line or regularly using a program
441443 later section on regexps).
442444
443445 Some accounts add additional tags, discussed below.
444
446
447 Tags are replaced in almost all strings (including those in single-quotes!),
448 some when the configuration file is parsed and some when the string is used. In
449 addition, a leading ~ or ~user is expanded to a home directory where
450 appropriate.
451
445452 6.2 POP3 and POP3S -------------------------------------------------------------
446453
447454 Mail may be fetched from a POP3 account. A POP3 account is defined by
222222 %anum = 57
223223 include "/etc/file-number-%{anum}"
224224
225 Macros are not substituted in strings specified using single-quotes.
226
225227 ### Invoking fdm
226228
227229 fdm may be invoked manually from the command line or regularly using a program
441443 later section on regexps).
442444
443445 Some accounts add additional tags, discussed below.
444
446
447 Tags are replaced in almost all strings (including those in single-quotes!),
448 some when the configuration file is parsed and some when the string is used. In
449 addition, a leading ~ or ~user is expanded to a home directory where
450 appropriate.
451
445452 %%% POP3 and POP3S
446453
447454 Mail may be fetched from a POP3 account. A POP3 account is defined by
2727 - refactor & clean up privsep mail transfer code
2828 - document mail_file, mbox_file and exec action
2929 - document command0 etc
30 - expand ~s (special function on paths, check escaping)
31 - matching by account section in manual
3230 - -q option to silence normal (info) output
3331 - sort out so normal (info) goes to stdout and all else to stderr
462462
463463 /* tag mail if needed */
464464 if (r->key.str != NULL) {
465 tkey = replace(&r->key, m->tags, m, mctx->pm_valid,
466 mctx->pm);
467 tvalue = replace(&r->value, m->tags, m, mctx->pm_valid,
468 mctx->pm);
465 tkey = replacestr(&r->key,
466 m->tags, m, mctx->pm_valid, mctx->pm);
467 tvalue = replacestr(&r->value,
468 m->tags, m, mctx->pm_valid, mctx->pm);
469469
470470 if (tkey != NULL && *tkey != '\0' && tvalue != NULL) {
471471 log_debug2("%s: tagging message: %s (%s)",
561561
562562 for (i = 0; i < ARRAY_LENGTH(r->actions); i++) {
563563 rs = &ARRAY_ITEM(r->actions, i, struct replstr);
564 s = replace(rs, m->tags, m, mctx->pm_valid, mctx->pm);
564 s = replacestr(rs, m->tags, m, mctx->pm_valid, mctx->pm);
565565
566566 log_debug2("%s: looking for actions matching: %s", a->name, s);
567567 ta = match_actions(s);
3939 struct deliver_add_header_data *data = t->data;
4040 char *hdr, *value;
4141
42 hdr = replace(&data->hdr, m->tags, m, *dctx->pm_valid, dctx->pm);
42 hdr = replacestr(&data->hdr, m->tags, m, *dctx->pm_valid, dctx->pm);
4343 if (hdr == NULL || *hdr == '\0') {
4444 if (hdr != NULL)
4545 xfree(hdr);
4646 log_warnx("%s: empty header", a->name);
4747 return (DELIVER_FAILURE);
4848 }
49 value = replace(&data->value, m->tags, m, *dctx->pm_valid, dctx->pm);
49 value = replacestr(&data->value, m->tags, m, *dctx->pm_valid, dctx->pm);
5050 if (value == NULL) {
5151 log_warnx("%s: bad value for header %s", a->name, hdr);
5252 xfree(hdr);
5555 size_t first, last;
5656 gid_t gid;
5757
58 path = replace(&data->path, m->tags, m, *dctx->pm_valid, dctx->pm);
58 path = replacepath(&data->path, m->tags, m, *dctx->pm_valid, dctx->pm);
5959 if (path == NULL || *path == '\0') {
6060 log_warnx("%s: empty path", a->name);
6161 goto out;
7575 int res = DELIVER_FAILURE;
7676 gzFile gzf = NULL;
7777
78 path = replace(&data->path, m->tags, m, *dctx->pm_valid, dctx->pm);
78 path = replacepath(&data->path, m->tags, m, *dctx->pm_valid, dctx->pm);
7979 if (path == NULL || *path == '\0') {
8080 if (path != NULL)
8181 xfree(path);
6161 char *lbuf;
6262 size_t llen;
6363
64 s = replace(&data->cmd, m->tags, m, *dctx->pm_valid, dctx->pm);
64 s = replacepath(&data->cmd, m->tags, m, *dctx->pm_valid, dctx->pm);
6565 if (s == NULL || *s == '\0') {
6666 log_warnx("%s: empty command", a->name);
6767 if (s != NULL)
4141 size_t len, off, wrap;
4242 u_int i;
4343
44 hdr = replace(&data->hdr, m->tags, m, *dctx->pm_valid, dctx->pm);
44 hdr = replacestr(&data->hdr, m->tags, m, *dctx->pm_valid, dctx->pm);
4545 if (hdr == NULL || *hdr == '\0') {
4646 if (hdr != NULL)
4747 xfree(hdr);
5151 char *lbuf;
5252 size_t llen;
5353
54 s = replace(&data->cmd, m->tags, m, *dctx->pm_valid, dctx->pm);
54 s = replacepath(&data->cmd, m->tags, m, *dctx->pm_valid, dctx->pm);
5555 if (s == NULL || *s == '\0') {
5656 log_warnx("%s: empty command", a->name);
5757 if (s != NULL)
8686 if (data->to.str == NULL)
8787 to = xstrdup(from);
8888 else {
89 to = replace(&data->to, m->tags, m, *dctx->pm_valid, dctx->pm);
89 to = replacestr(&data->to, m->tags, m, *dctx->pm_valid,
90 dctx->pm);
9091 if (to == NULL || *to == '\0') {
9192 log_warnx("%s: empty to", a->name);
9293 goto error;
5858 char *path;
5959 FILE *f;
6060
61 path = replace(&data->path, m->tags, m, *dctx->pm_valid, dctx->pm);
61 path = replacepath(&data->path, m->tags, m, *dctx->pm_valid, dctx->pm);
6262 if (path == NULL || *path == '\0') {
6363 if (path != NULL)
6464 xfree(path);
7070
7171 /* Deliver mbox data. */
7272 struct deliver_mbox_data {
73 struct replstr path;
73 struct replpath path;
7474 int compress;
7575 };
7676
9292
9393 /* Deliver write data. */
9494 struct deliver_write_data {
95 struct replstr path;
95 struct replpath path;
9696 };
9797
9898 /* Deliver maildir data. */
9999 struct deliver_maildir_data {
100 struct replstr path;
100 struct replpath path;
101101 };
102102
103103 /* Deliver rewrite data. */
104104 struct deliver_rewrite_data {
105 struct replstr cmd;
105 struct replpath cmd;
106106 };
107107
108108 /* Deliver pipe data. */
109109 struct deliver_pipe_data {
110 struct replstr cmd;
110 struct replpath cmd;
111111 };
112112
113113 /* Deliver append-string data. */
250250 };
251251 ARRAY_DECL(replstrs, struct replstr);
252252
253 /* Similar to replstr but needs expand_path too. */
254 struct replpath {
255 char *str;
256 };
257
253258 /* Server description. */
254259 struct server {
255260 char *host;
691696 void free_action(struct action *);
692697 void free_rule(struct rule *);
693698 void free_account(struct account *);
699 char *expand_path(char *);
694700
695701 /* fdm.c */
696702 double get_time(void);
795801 const char *match_tag(struct strb *, const char *);
796802 void default_tags(struct strb **, char *, struct account *);
797803 void update_tags(struct strb **);
798 char *replace(struct replstr *, struct strb *, struct mail *,
799 int, regmatch_t [NPMATCH]);
804 char *replace(char *, struct strb *, struct mail *, int,
805 regmatch_t [NPMATCH]);
806 char *replacestr(struct replstr *, struct strb *,
807 struct mail *, int, regmatch_t [NPMATCH]);
808 char *replacepath(struct replpath *, struct strb *,
809 struct mail *, int, regmatch_t [NPMATCH]);
800810
801811 /* io.c */
802812 struct io *io_create(int, SSL *, const char *, int);
107107
108108 /* for any type or name matches, construct the value */
109109 if (data->op == ATTACHOP_ANYTYPE || data->op == ATTACHOP_ANYNAME) {
110 value = replace(&data->value.str,
110 value = replacestr(&data->value.str,
111111 m->tags, m, mctx->pm_valid, mctx->pm);
112112 }
113113
4040 int res;
4141 char *s, *cause;
4242
43 s = replace(&data->str, m->tags, m, mctx->pm_valid, mctx->pm);
43 s = replacestr(&data->str, m->tags, m, mctx->pm_valid, mctx->pm);
4444 log_debug2("%s: matching \"%s\" to \"%s\"", a->name, s, data->re.str);
4545
4646 res = re_simple(&data->re, s, &cause);
3838 struct mail *m = mctx->mail;
3939 char *tag;
4040
41 tag = replace(&data->tag, m->tags, m, mctx->pm_valid, mctx->pm);
41 tag = replacestr(&data->tag, m->tags, m, mctx->pm_valid, mctx->pm);
4242 if (match_tag(m->tags, tag) != NULL) {
4343 xfree(tag);
4444 return (MATCH_TRUE);
9696
9797 /* Match command data. */
9898 struct match_command_data {
99 struct replstr cmd;
99 struct replpath cmd;
100100 uid_t uid;
101101 int pipe; /* pipe mail to command */
102102
368368 return (0);
369369
370370 /* sort out the command */
371 s = replace(&data->cmd, m->tags, m, mctx->pm_valid, mctx->pm);
371 s = replacepath(&data->cmd, m->tags, m, mctx->pm_valid, mctx->pm);
372372 if (s == NULL || *s == '\0') {
373373 log_warnx("%s: empty command", a->name);
374374 goto error;
498498 xfree(a->data);
499499
500500 xfree(a);
501 }
502
503 char *
504 expand_path(char *path)
505 {
506 char *src, *ptr;
507 struct passwd *pw;
508
509 src = path;
510 while (isspace((int) *src))
511 src++;
512 if (src[0] != '~')
513 return (NULL);
514
515 /* ~ */
516 if (src[1] == '\0')
517 return (xstrdup(conf.info.home));
518
519 /* ~/ */
520 if (src[1] == '/') {
521 xasprintf(&ptr, "%s/%s", conf.info.home, src + 2);
522 return (ptr);
523 }
524
525 /* ~user or ~user/ */
526 ptr = strchr(src + 1, '/');
527 if (ptr != NULL)
528 *ptr = '\0';
529
530 pw = getpwnam(src + 1);
531 if (pw == NULL || pw->pw_dir == NULL || *pw->pw_dir == '\0') {
532 endpwent();
533 return (NULL);
534 }
535
536 if (ptr == NULL)
537 ptr = xstrdup(pw->pw_dir);
538 else
539 xasprintf(&ptr, "%s/%s", pw->pw_dir, ptr + 1);
540
541 endpwent();
542
543 return (ptr);
501544 }
502545 %}
503546
576619 %type <replstrs> actions actionslist
577620 %type <rule> perform
578621 %type <server> server
579 %type <string> port to folder strv replstrv retre
622 %type <string> port to folder strv replstrv retre replpathv
580623 %type <strings> domains domainslist headers headerslist accounts accountslist
581624 %type <strings> maildirslist maildirs groupslist groups
582625 %type <users> users userslist
697740 }
698741
699742 rs.str = $1;
700 $$ = replace(&rs, parse_tags, NULL, 0, NULL);
743 $$ = replacestr(&rs, parse_tags, NULL, 0, NULL);
701744 xfree($1);
702745 }
703746
747 replpathv: strv
748 {
749 struct replpath rp;
750
751 if (parse_tags == NULL) {
752 strb_create(&parse_tags);
753 default_tags(&parse_tags, NULL, NULL);
754 }
755
756 rp.str = $1;
757 $$ = replacepath(&rp, parse_tags, NULL, 0, NULL);
758 xfree($1);
759 }
760
704761 /** INCLUDE */
705 include: TOKINCLUDE replstrv
762 include: TOKINCLUDE replpathv
706763 /** [$2: replstrv (char *)] */
707764 {
708765 char *path;
837894 yyerror("fcntl and flock locking cannot be used together");
838895 conf.lock_types = $3;
839896 }
840 | TOKSET TOKLOCKFILE replstrv
897 | TOKSET TOKLOCKFILE replpathv
841898 /** [$3: replstrv (char *)] */
842899 {
843900 if (conf.lock_file != NULL)
11121169 }
11131170
11141171 /** MAILDIRSLIST: <strings> (struct strings *) */
1115 maildirslist: maildirslist replstrv
1172 maildirslist: maildirslist replpathv
11161173 /** [$1: maildirslist (struct strings *)] [$2: replstrv (char *)] */
11171174 {
11181175 if (*$2 == '\0')
11211178 $$ = $1;
11221179 ARRAY_ADD($$, $2, char *);
11231180 }
1124 | replstrv
1181 | replpathv
11251182 /** [$1: replstrv (char *)] */
11261183 {
11271184 if (*$1 == '\0')
11331190 }
11341191
11351192 /** MAILDIRS: <strings> (struct strings *) */
1136 maildirs: TOKMAILDIR replstrv
1193 maildirs: TOKMAILDIR replpathv
11371194 /** [$2: replstrv (char *)] */
11381195 {
11391196 if (*$2 == '\0')
24462503 $$.data = data;
24472504 data->maildirs = $1;
24482505 }
2449 | TOKNNTP server groups TOKCACHE replstrv
2506 | TOKNNTP server groups TOKCACHE replpathv
24502507 /** [$2: server (struct { ... } server)] */
24512508 /** [$3: groups (struct strings *)] [$5: replstrv (char *)] */
24522509 {
157157 }
158158
159159 char *
160 replace(struct replstr *rs, struct strb *tags, struct mail *m, int pm_valid,
160 replacestr(struct replstr *rs, struct strb *tags, struct mail *m,
161 int pm_valid, regmatch_t pm[NPMATCH])
162 {
163 return (replace(rs->str, tags, m, pm_valid, pm));
164 }
165
166 char *
167 replacepath(struct replpath *rp, struct strb *tags, struct mail *m,
168 int pm_valid, regmatch_t pm[NPMATCH])
169 {
170 char *s, *ss;
171
172 s = replace(rp->str, tags, m, pm_valid, pm);
173 ss = expand_path(s);
174 if (ss == NULL)
175 return (s);
176 xfree(s);
177 return (ss);
178 }
179
180 char *
181 replace(char *src, struct strb *tags, struct mail *m, int pm_valid,
161182 regmatch_t pm[NPMATCH])
162183 {
163184 char *ptr, *tend;
164185 const char *tptr, *alias;
165 char *src, *dst, ch;
186 char *dst, ch;
166187 size_t off, len, tlen;
167188 u_int idx;
168189
169 src = rs->str;
170190 if (src == NULL)
171191 return (NULL);
172192 if (*src == '\0')