]>
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.
12 #include <h/dropsbr.h>
15 #include "../sbr/lock_file.h"
16 #include "../sbr/m_mktemp.h"
19 # include <netinet/in.h>
30 static int mbx_chk_mbox (int);
31 static int mbx_chk_mmdf (int);
35 * Main entry point to open/create and lock
40 mbx_open (char *file
, int mbx_style
, uid_t uid
, gid_t gid
, mode_t mode
)
42 int j
, count
, fd
= NOTOK
;
47 /* attempt to open and lock file */
48 for (count
= 4; count
> 0; count
--) {
49 int failed_to_lock
= 0;
51 if ((fd
= lkopenspool (file
, O_RDWR
| O_CREAT
| O_NONBLOCK
,
52 mode
, &failed_to_lock
)) != NOTOK
)
65 * Return if we still failed after 4 attempts,
66 * or we just want to skip the sanity checks.
68 if (fd
== NOTOK
|| mbx_style
== OTHER_FORMAT
)
72 * Do sanity checks on maildrop.
74 if (fstat (fd
, &st
) == NOTOK
) {
76 * The stat failed. So we make sure file
77 * has right ownership/modes
79 if (chown (file
, uid
, gid
) < 0) {
80 advise (file
, "chown");
82 if (chmod (file
, mode
) < 0) {
83 advise (file
, "chmod");
85 } else if (st
.st_size
> 0) {
88 /* check the maildrop */
92 status
= mbx_chk_mmdf (fd
);
96 status
= mbx_chk_mbox (fd
);
100 /* if error, attempt to close it */
101 if (status
== NOTOK
) {
112 * Check/prepare MBOX style maildrop for appending.
116 mbx_chk_mbox (int fd
)
118 /* just seek to the end */
119 if (lseek(fd
, 0, SEEK_END
) == (off_t
) NOTOK
)
127 * Check/prepare MMDF style maildrop for appending.
131 mbx_chk_mmdf (int fd
)
136 count
= strlen (mmdlm2
);
138 if (lseek (fd
, -count
, SEEK_END
) == (off_t
) NOTOK
)
140 if (read (fd
, ldelim
, count
) != count
)
145 if (strcmp (ldelim
, mmdlm2
)
146 && write (fd
, "\n", 1) != 1
147 && write (fd
, mmdlm2
, count
) != count
)
155 * Append message to end of file or maildrop.
159 mbx_copy (char *mailbox
, int mbx_style
, int md
, int fd
,
163 char *cp
, buffer
[BUFSIZ
+ 1]; /* Space for NUL. */
172 if (write (md
, mmdlm1
, j
) != j
)
177 if (write (md
, text
, i
) != i
)
179 for (cp
= text
; *cp
++; size
++)
184 while ((i
= read (fd
, buffer
, sizeof buffer
- 1)) > 0) {
185 buffer
[i
] = '\0'; /* Terminate for stringdex(). */
187 for ( ; (j
= stringdex (mmdlm1
, buffer
)) >= 0; buffer
[j
]++)
189 for ( ; (j
= stringdex (mmdlm2
, buffer
)) >= 0; buffer
[j
]++)
191 if (write (md
, buffer
, i
) != i
)
196 if (write (md
, mmdlm2
, j
) != j
)
199 return (i
!= NOTOK
? OK
: NOTOK
);
202 if ((j
= dup (fd
)) == NOTOK
)
204 if ((fp
= fdopen (j
, "r")) == NULL
) {
209 /* If text is given, we add it to top of message */
212 if (write (md
, text
, i
) != i
)
214 for (cp
= text
; *cp
++; size
++)
219 for (j
= 0; fgets (buffer
, sizeof(buffer
), fp
) != NULL
; j
++) {
222 * Check the first line, and make some changes.
224 if (j
== 0 && !text
) {
226 * Change the "Return-Path:" field (if in first line)
229 if (has_prefix(buffer
, "Return-Path:")) {
230 char tmpbuffer
[sizeof buffer
];
233 strncpy(tmpbuffer
, buffer
, sizeof(tmpbuffer
));
235 if (!(fp
= strchr(ep
+ 1, ' ')))
236 fp
= strchr(ep
+ 1, '\n');
237 tp
= dctime(dlocaltimenow());
238 snprintf (buffer
, sizeof(buffer
), "From %.*s %s",
239 (int)(fp
- ep
), ep
, tp
);
240 } else if (has_prefix(buffer
, "X-Envelope-From:")) {
242 * Change the "X-Envelope-From:" field
243 * (if first line) back to "From ".
245 char tmpbuffer
[sizeof buffer
];
248 strncpy(tmpbuffer
, buffer
, sizeof(tmpbuffer
));
250 snprintf (buffer
, sizeof(buffer
), "From %s", ep
);
251 } else if (!has_prefix(buffer
, "From ")) {
253 * If there is already a "From " line,
254 * then leave it alone. Else we add one.
256 char tmpbuffer
[sizeof buffer
];
259 strncpy(tmpbuffer
, buffer
, sizeof(tmpbuffer
));
260 ep
= "nobody@nowhere";
261 tp
= dctime(dlocaltimenow());
262 snprintf (buffer
, sizeof(buffer
), "From %s %s%s", ep
, tp
, tmpbuffer
);
267 * If this is not first line, and begins with
268 * "From ", then prepend line with ">".
270 if (j
!= 0 && has_prefix(buffer
, "From ")) {
271 if (write (md
, ">", 1) < 0) {
272 advise (mailbox
, "write");
277 if (write (md
, buffer
, i
) != i
) {
282 if (write (md
, "\n", 1) != 1) {
288 lseek(fd
, 0, SEEK_END
);
296 * Close and unlock file/maildrop.
300 mbx_close (char *mailbox
, int md
)
302 if (lkclosespool (md
, mailbox
) == 0)