long bezerk_cache_append (MAILSTREAM *stream,char *mailbox,
char *flags,char *date,
STRING *message)
{
struct stat sbuf;
int i,fd,ti,zn;
char *s,*x,buf[BUFLEN],file[MAILTMPLEN],lock[MAILTMPLEN];
time_t tp[2];
MESSAGECACHE elt;
char c = '\n';
unsigned long j,n,ok = T;
time_t t = time (0);
unsigned long size = SIZE (message);
unsigned long uf;
long f = mail_parse_flags (stream ? stream : &bezerkproto,flags,&uf);
/* parse date if given */
if (date && !mail_parse_date (&elt,date)) {
sprintf (buf,"Bad date in append: %s",date);
mm_log (buf,ERROR);
return NIL;
}
/* make sure valid mailbox */
if (!bezerk_isvalid (mailbox,buf)) switch (errno) {
case ENOENT: /* no such file? */
if (strcmp (ucase (strcpy (buf,mailbox)),"INBOX")) {
mm_notify (stream,"[TRYCREATE] Must create mailbox before append",NIL);
return NIL;
}
else break;
case 0: /* merely empty file? */
break;
case EINVAL:
sprintf (buf,"Invalid Berkeley-format mailbox name: %s",mailbox);
mm_log (buf,ERROR);
return NIL;
default:
sprintf (buf,"Not a Berkeley-format mailbox: %s",mailbox);
mm_log (buf,ERROR);
return NIL;
}
if ((fd = bezerk_lock (dummy_file (file,mailbox),O_WRONLY|O_APPEND|O_CREAT,
S_IREAD|S_IWRITE,lock,LOCK_EX)) < 0) {
sprintf (buf,"Can't open append mailbox: %s",strerror (errno));
mm_log (buf,ERROR);
return NIL;
}
mm_critical (stream); /* go critical */
fstat (fd,&sbuf); /* get current file size */
sprintf (buf,"From %s@%s ",myusername (),mylocalhost ());
/* write the date given */
if (date) mail_cdate (buf + strlen (buf),&elt);
else strcat (buf,ctime (&t)); /* otherwise write the time now */
i = strlen (buf); /* initial buffer space used */
while (ok && size--) { /* copy text, tossing out CR's */
/* if at start of line */
if ((c == '\n') && (size > 5)) {
n = GETPOS (message); /* prepend a broket if needed */
if ((SNX (message) == 'F') && (SNX (message) == 'r') &&
(SNX (message) == 'o') && (SNX (message) == 'm') &&
(SNX (message) == ' ')) {
/* always write widget if unconditional */
if (bezerk_fromwidget) ok = bezerk_append_putc (fd,buf,&i,'>');
else { /* hairier test, count length of this line */
for (j = 6; (j < size) && (SNX (message) != '\n'); j++);
if (j < size) { /* copy line */
SETPOS (message,n); /* restore position */
x = s = (char *) fs_get (j + 1);
while (j--) if ((c = SNX (message)) != '\015') *x++ = c;
*x = '\0'; /* tie off line */
VALID (s,x,ti,zn); /* see if looks like need a widget */
if (ti) ok = bezerk_append_putc (fd,buf,&i,'>');
fs_give ((void **) &s);
}
}
}
SETPOS (message,n); /* restore position as needed */
}
/* copy another character */
if ((c = SNX (message)) != '\015') ok = bezerk_append_putc (fd,buf,&i,c);
}
/* write trailing newline */
if (ok) ok = bezerk_append_putc (fd,buf,&i,'\n');
if (!(ok && (ok = (write (fd,buf,i) >= 0)) && (ok = !fsync (fd)))) {
sprintf (buf,"Message append failed: %s",strerror (errno));
mm_log (buf,ERROR);
ftruncate (fd,sbuf.st_size);
}
tp[0] = sbuf.st_atime; /* preserve atime */
tp[1] = time (0); /* set mtime to now */
utime (file,tp); /* set the times */
bezerk_unlock (fd,NIL,lock); /* unlock and close mailbox */
mm_nocritical (stream); /* release critical */
return ok; /* return success */
}
syntax highlighted by Code2HTML, v. 0.9.1