]>
diplodocus.org Git - nmh/blob - uip/dropsbr.c
1 /* dropsbr.c -- create/read/manipulate mail drops
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
11 #include <h/dropsbr.h>
14 #include "sbr/lock_file.h"
15 #include "sbr/m_mktemp.h"
21 static int mbx_chk_mbox (int);
22 static int mbx_chk_mmdf (int);
26 * Main entry point to open/create and lock
31 mbx_open (char *file
, int mbx_style
, uid_t uid
, gid_t gid
, mode_t mode
)
33 int j
, count
, fd
= NOTOK
;
38 /* attempt to open and lock file */
39 for (count
= 4; count
> 0; count
--) {
40 int failed_to_lock
= 0;
42 if ((fd
= lkopenspool (file
, O_RDWR
| O_CREAT
| O_NONBLOCK
,
43 mode
, &failed_to_lock
)) != NOTOK
)
56 * Return if we still failed after 4 attempts,
57 * or we just want to skip the sanity checks.
59 if (fd
== NOTOK
|| mbx_style
== OTHER_FORMAT
)
63 * Do sanity checks on maildrop.
65 if (fstat (fd
, &st
) == NOTOK
) {
67 * The stat failed. So we make sure file
68 * has right ownership/modes
70 if (chown (file
, uid
, gid
) < 0) {
71 advise (file
, "chown");
73 if (chmod (file
, mode
) < 0) {
74 advise (file
, "chmod");
76 } else if (st
.st_size
> 0) {
79 /* check the maildrop */
83 status
= mbx_chk_mmdf (fd
);
87 status
= mbx_chk_mbox (fd
);
91 /* if error, attempt to close it */
92 if (status
== NOTOK
) {
103 * Check/prepare MBOX style maildrop for appending.
107 mbx_chk_mbox (int fd
)
109 /* just seek to the end */
110 if (lseek(fd
, 0, SEEK_END
) == (off_t
) NOTOK
)
118 * Check/prepare MMDF style maildrop for appending.
122 mbx_chk_mmdf (int fd
)
127 count
= LEN(MMDF_DELIM
);
129 if (lseek (fd
, -count
, SEEK_END
) == (off_t
) NOTOK
)
131 if (read (fd
, ldelim
, count
) != count
)
136 if (strcmp (ldelim
, MMDF_DELIM
)
137 && write (fd
, "\n", 1) != 1
138 && write (fd
, MMDF_DELIM
, count
) != count
)
146 * Append message to end of file or maildrop.
150 mbx_copy (char *mailbox
, int mbx_style
, int md
, int fd
,
154 char *cp
, buffer
[BUFSIZ
+ 1]; /* Space for NUL. */
163 if (write (md
, MMDF_DELIM
, j
) != j
)
168 if (write (md
, text
, i
) != i
)
170 for (cp
= text
; *cp
++; size
++)
175 while ((i
= read (fd
, buffer
, sizeof buffer
- 1)) > 0) {
176 buffer
[i
] = '\0'; /* Terminate for stringdex(). */
178 for ( ; (j
= stringdex (MMDF_DELIM
, buffer
)) >= 0; buffer
[j
]++)
180 for ( ; (j
= stringdex (MMDF_DELIM
, buffer
)) >= 0; buffer
[j
]++)
182 if (write (md
, buffer
, i
) != i
)
187 if (write (md
, MMDF_DELIM
, j
) != j
)
190 return (i
!= NOTOK
? OK
: NOTOK
);
193 if ((j
= dup (fd
)) == NOTOK
)
195 if ((fp
= fdopen (j
, "r")) == NULL
) {
200 /* If text is given, we add it to top of message */
203 if (write (md
, text
, i
) != i
)
205 for (cp
= text
; *cp
++; size
++)
210 for (j
= 0; fgets (buffer
, sizeof(buffer
), fp
) != NULL
; j
++) {
213 * Check the first line, and make some changes.
215 if (j
== 0 && !text
) {
217 * Change the "Return-Path:" field (if in first line)
220 if (has_prefix(buffer
, "Return-Path:")) {
221 char tmpbuffer
[sizeof buffer
];
224 strncpy(tmpbuffer
, buffer
, sizeof(tmpbuffer
));
226 if (!(fp
= strchr(ep
+ 1, ' ')))
227 fp
= strchr(ep
+ 1, '\n');
228 tp
= dctime(dlocaltimenow());
229 snprintf (buffer
, sizeof(buffer
), "From %.*s %s",
230 (int)(fp
- ep
), ep
, tp
);
231 } else if (has_prefix(buffer
, "X-Envelope-From:")) {
233 * Change the "X-Envelope-From:" field
234 * (if first line) back to "From ".
236 char tmpbuffer
[sizeof buffer
];
239 strncpy(tmpbuffer
, buffer
, sizeof(tmpbuffer
));
241 snprintf (buffer
, sizeof(buffer
), "From %s", ep
);
242 } else if (!has_prefix(buffer
, "From ")) {
244 * If there is already a "From " line,
245 * then leave it alone. Else we add one.
247 char tmpbuffer
[sizeof buffer
];
250 strncpy(tmpbuffer
, buffer
, sizeof(tmpbuffer
));
251 ep
= "nobody@nowhere";
252 tp
= dctime(dlocaltimenow());
253 snprintf (buffer
, sizeof(buffer
), "From %s %s%s", ep
, tp
, tmpbuffer
);
258 * If this is not first line, and begins with
259 * "From ", then prepend line with ">".
261 if (j
!= 0 && has_prefix(buffer
, "From ")) {
262 if (write (md
, ">", 1) < 0) {
263 advise (mailbox
, "write");
268 if (write (md
, buffer
, i
) != i
) {
273 if (write (md
, "\n", 1) != 1) {
279 lseek(fd
, 0, SEEK_END
);
287 * Close and unlock file/maildrop.
291 mbx_close (char *mailbox
, int md
)
293 if (lkclosespool (md
, mailbox
) == 0)