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