mhl and mhbuild ignore to long lines
[mmh] / uip / dropsbr.c
1 /*
2 ** dropsbr.c -- append to mbox files
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <h/utils.h>
11 #include <h/dropsbr.h>
12 #include <h/tws.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <sys/stat.h>
18
19
20 /*
21 ** Main entry point to open/create and lock
22 ** a file or maildrop.
23 */
24 int
25 mbox_open(char *file, uid_t uid, gid_t gid, mode_t mode)
26 {
27         int i, count, fd;
28         struct stat st;
29
30         i = 0;
31
32         /* attempt to open and lock file */
33         for (count = 4; count > 0; count--) {
34                 if ((fd = lkopen(file, O_RDWR | O_CREAT | O_NONBLOCK, mode))
35                                 == NOTOK) {
36                         switch (errno) {
37 #if defined(FCNTL_LOCKING) || defined(LOCKF_LOCKING)
38                         case EACCES:
39                         case EAGAIN:
40 #endif
41
42 #ifdef FLOCK_LOCKING
43                         case EWOULDBLOCK:
44 #endif
45                         case ETXTBSY:
46                                 i = errno;
47                                 sleep(1);
48                                 continue;
49
50                         default:
51                                 /* just return error */
52                                 return NOTOK;
53                         }
54                 }
55
56                 /* good file descriptor */
57                 break;
58         }
59
60         errno = i;
61
62         /*
63         ** Return if we still failed after 4 attempts,
64         ** or we just want to skip the sanity checks.
65         */
66         if (fd == NOTOK)
67                 return fd;
68
69         /* Do sanity checks on maildrop. */
70         if (fstat(fd, &st) == NOTOK) {
71                 /*
72                 ** The stat failed.  So we make sure file
73                 ** has right ownership/modes
74                 */
75                 chown(file, uid, gid);
76                 chmod(file, mode);
77         } else if (st.st_size > (off_t) 0) {
78                 int status;
79
80                 /* Check/prepare MBOX style maildrop for appending. */
81                 if (lseek(fd, (off_t) 0, SEEK_END) == (off_t) NOTOK) {
82                         status = NOTOK;
83                 } else {
84                         status = OK;
85                 }
86
87                 /* if error, attempt to close it */
88                 if (status == NOTOK) {
89                         close(fd);
90                         return NOTOK;
91                 }
92         }
93
94         return fd;
95 }
96
97
98 /*
99 ** Append message to end of mbox.
100 */
101 int
102 mbox_copy(int to, int from)
103 {
104         int i;
105         char buffer[BUFSIZ];
106         FILE *fp;
107
108         if ((i = dup(from)) == NOTOK)
109                 return NOTOK;
110         if ((fp = fdopen(i, "r")) == NULL) {
111                 close(i);
112                 return NOTOK;
113         }
114
115         for (i = 0; fgets(buffer, sizeof(buffer), fp) != NULL; i++) {
116                 /*
117                 ** Check the first line, and make some changes.
118                 */
119                 if (i == 0) {
120                         /*
121                         ** Change the "Return-Path:" field
122                         ** (if in first line) back to "From ".
123                         */
124                         if (strncmp(buffer, "Return-Path:", 12)==0) {
125                                 char tmpbuffer[BUFSIZ];
126                                 char *tp, *ep, *fp;
127
128                                 strncpy(tmpbuffer, buffer, sizeof(tmpbuffer));
129                                 ep = tmpbuffer + 13;
130                                 if (!(fp = strchr(ep + 1, ' ')))
131                                         fp = strchr(ep + 1, '\n');
132                                 tp = dctime(dlocaltimenow());
133                                         snprintf(buffer, sizeof(buffer),
134                                                         "From %.*s %s",
135                                                         (int)(fp-ep), ep, tp);
136                         } else if (strncmp(buffer, "X-Envelope-From:",
137                                         16)==0) {
138                                 /*
139                                 ** Change the "X-Envelope-From:" field
140                                 ** (if first line) back to "From ".
141                                 */
142                                 char tmpbuffer[BUFSIZ];
143                                 char *ep;
144
145                                 strncpy(tmpbuffer, buffer, sizeof(tmpbuffer));
146                                 ep = tmpbuffer + 17;
147                                 snprintf(buffer, sizeof(buffer), "From %s",
148                                                 ep);
149                         } else if (strncmp(buffer, "From ", 5)!=0) {
150                                 /*
151                                 ** If there is already a "From " line,
152                                 ** then leave it alone.  Else we add one.
153                                 */
154                                 char tmpbuffer[BUFSIZ];
155                                 char *tp, *ep;
156
157                                 strncpy(tmpbuffer, buffer, sizeof(tmpbuffer));
158                                 ep = "nobody@nowhere";
159                                 tp = dctime(dlocaltimenow());
160                                 snprintf(buffer, sizeof(buffer),
161                                                 "From %s %s%s", ep, tp,
162                                                 tmpbuffer);
163                         }
164                 }
165
166                 /*
167                 ** If this is not first line, and begins with "From ",
168                 ** then prepend line with ">". (`mboxo' format is used.)
169                 */
170                 if (i != 0 && strncmp(buffer, "From ", 5) == 0) {
171                         write(to, ">", 1);
172                 }
173                 if (write(to, buffer, strlen(buffer)) != (int)strlen(buffer)) {
174                         fclose(fp);
175                         return NOTOK;
176                 }
177         }
178
179         if (write(to, "\n", 1) != 1) {
180                 fclose(fp);
181                 return NOTOK;
182         }
183         fclose(fp);
184         lseek(from, (off_t) 0, SEEK_END);
185
186         return OK;
187 }
188
189
190 /*
191 ** Close and unlock file/maildrop.
192 */
193 int
194 mbox_close(char *mailbox, int md)
195 {
196         if (lkclose(md, mailbox) == 0)
197                 return OK;
198         return NOTOK;
199 }