]>
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.
10 #include "sbr/error.h"
12 #include "h/dropsbr.h"
15 #include "sbr/lock_file.h"
16 #include "sbr/m_mktemp.h"
22 static int mbx_chk_mbox (int);
23 static int mbx_chk_mmdf (int);
27 * Main entry point to open/create and lock
32 mbx_open (char *file
, int mbx_style
, uid_t uid
, gid_t gid
, mode_t mode
)
34 int j
, count
, fd
= NOTOK
;
39 /* attempt to open and lock file */
40 for (count
= 4; count
> 0; count
--) {
41 int failed_to_lock
= 0;
43 if ((fd
= lkopenspool (file
, O_RDWR
| O_CREAT
| O_NONBLOCK
,
44 mode
, &failed_to_lock
)) != NOTOK
)
57 * Return if we still failed after 4 attempts,
58 * or we just want to skip the sanity checks.
60 if (fd
== NOTOK
|| mbx_style
== OTHER_FORMAT
)
64 * Do sanity checks on maildrop.
66 if (fstat (fd
, &st
) == NOTOK
) {
68 * The stat failed. So we make sure file
69 * has right ownership/modes
71 if (chown (file
, uid
, gid
) < 0) {
72 advise (file
, "chown");
74 if (chmod (file
, mode
) < 0) {
75 advise (file
, "chmod");
77 } else if (st
.st_size
> 0) {
80 /* check the maildrop */
84 status
= mbx_chk_mmdf (fd
);
88 status
= mbx_chk_mbox (fd
);
92 /* if error, attempt to close it */
93 if (status
== NOTOK
) {
104 * Check/prepare MBOX style maildrop for appending.
108 mbx_chk_mbox (int fd
)
110 /* just seek to the end */
111 if (lseek(fd
, 0, SEEK_END
) == (off_t
) NOTOK
)
119 * Check/prepare MMDF style maildrop for appending.
123 mbx_chk_mmdf (int fd
)
128 count
= LEN(MMDF_DELIM
);
130 if (lseek (fd
, -count
, SEEK_END
) == (off_t
) NOTOK
)
132 if (read (fd
, ldelim
, count
) != count
)
137 if (strcmp (ldelim
, MMDF_DELIM
)
138 && write (fd
, "\n", 1) != 1
139 && write (fd
, MMDF_DELIM
, count
) != count
)
147 * Append message to end of file or maildrop.
151 mbx_copy (char *mailbox
, int mbx_style
, int md
, int fd
,
155 char *cp
, buffer
[BUFSIZ
+ 1]; /* Space for NUL. */
164 if (write (md
, MMDF_DELIM
, j
) != j
)
169 if (write (md
, text
, i
) != i
)
171 for (cp
= text
; *cp
++; size
++)
176 while ((i
= read (fd
, buffer
, sizeof buffer
- 1)) > 0) {
177 buffer
[i
] = '\0'; /* Terminate for stringdex(). */
179 for ( ; (j
= stringdex (MMDF_DELIM
, buffer
)) >= 0; buffer
[j
]++)
181 for ( ; (j
= stringdex (MMDF_DELIM
, buffer
)) >= 0; buffer
[j
]++)
183 if (write (md
, buffer
, i
) != i
)
188 if (write (md
, MMDF_DELIM
, j
) != j
)
191 return i
== NOTOK
? NOTOK
: OK
;
194 if ((j
= dup (fd
)) == NOTOK
)
196 if ((fp
= fdopen (j
, "r")) == NULL
) {
201 /* If text is given, we add it to top of message */
204 if (write (md
, text
, i
) != i
)
206 for (cp
= text
; *cp
++; size
++)
211 for (j
= 0; fgets (buffer
, sizeof(buffer
), fp
) != NULL
; j
++) {
214 * Check the first line, and make some changes.
216 if (j
== 0 && !text
) {
218 * Change the "Return-Path:" field (if in first line)
221 if (has_prefix(buffer
, "Return-Path:")) {
222 char tmpbuffer
[sizeof buffer
];
225 strncpy(tmpbuffer
, buffer
, sizeof(tmpbuffer
));
227 if (!(fp
= strchr(ep
+ 1, ' ')))
228 fp
= strchr(ep
+ 1, '\n');
229 tp
= dctime(dlocaltimenow());
230 snprintf (buffer
, sizeof(buffer
), "From %.*s %s",
231 (int)(fp
- ep
), ep
, tp
);
232 } else if (has_prefix(buffer
, "X-Envelope-From:")) {
234 * Change the "X-Envelope-From:" field
235 * (if first line) back to "From ".
237 char tmpbuffer
[sizeof buffer
];
240 strncpy(tmpbuffer
, buffer
, sizeof(tmpbuffer
));
242 snprintf (buffer
, sizeof(buffer
), "From %s", ep
);
243 } else if (!has_prefix(buffer
, "From ")) {
245 * If there is already a "From " line,
246 * then leave it alone. Else we add one.
248 char tmpbuffer
[sizeof buffer
];
251 strncpy(tmpbuffer
, buffer
, sizeof(tmpbuffer
));
252 ep
= "nobody@nowhere";
253 tp
= dctime(dlocaltimenow());
254 snprintf (buffer
, sizeof(buffer
), "From %s %s%s", ep
, tp
, tmpbuffer
);
259 * If this is not first line, and begins with
260 * "From ", then prepend line with ">".
262 if (j
!= 0 && has_prefix(buffer
, "From ")) {
263 if (write (md
, ">", 1) < 0) {
264 advise (mailbox
, "write");
269 if (write (md
, buffer
, i
) != i
) {
274 if (write (md
, "\n", 1) != 1) {
280 lseek(fd
, 0, SEEK_END
);
288 * Close and unlock file/maildrop.
292 mbx_close (char *mailbox
, int md
)
294 if (lkclosespool (md
, mailbox
) == 0)