/*
* sendsbr.c -- routines to help WhatNow/Send along
*
- * $Id$
- *
* This code is Copyright (c) 2002, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
* complete copyright information.
#include <h/mh.h>
#include <h/signals.h>
#include <setjmp.h>
-#include <signal.h>
#include <fcntl.h>
#include <h/mime.h>
+#include <h/tws.h>
+#include <h/utils.h>
+#include <h/mts.h>
-#ifdef TIME_WITH_SYS_TIME
+#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
-# include <time.h>
-#else
-# ifdef TM_IN_SYS_TIME
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
#endif
+#include <time.h>
int debugsw = 0; /* global */
int forwsw = 1;
char *annotext = NULL;
char *distfile = NULL;
-static int armed = 0;
static jmp_buf env;
-/*
- * external prototypes
- */
-int sendsbr (char **, int, char *, struct stat *, int);
-int done (int);
-char *getusername (void);
-
/*
* static prototypes
*/
+static void armed_done (int) NORETURN;
static void alert (char *, int);
static int tmp_fd (void);
static void anno (int, struct stat *);
static void annoaux (int);
-static int splitmsg (char **, int, char *, struct stat *, int);
-static int sendaux (char **, int, char *, struct stat *);
+static int splitmsg (char **, int, char *, char *, struct stat *, int);
+static int sendaux (char **, int, char *, char *, struct stat *);
/*
*/
int
-sendsbr (char **vec, int vecp, char *drft, struct stat *st, int rename_drft)
+sendsbr (char **vec, int vecp, char *program, char *draft, struct stat *st,
+ int rename_drft)
{
- int status;
+ int status, i;
+ pid_t child;
char buffer[BUFSIZ], file[BUFSIZ];
struct stat sts;
+ char **buildvec, *buildprogram;
+ char *volatile drft = draft;
+
+ /*
+ * Run the mimebuildproc (which is by default mhbuild) on the message
+ * with the addition of the "-auto" flag
+ */
+
+ switch (child = fork()) {
+ case NOTOK:
+ adios("fork", "unable to");
+ break;
- armed++;
+ case OK:
+ buildvec = argsplit(buildmimeproc, &buildprogram, &i);
+ buildvec[i++] = "-auto";
+ if (distfile)
+ buildvec[i++] = "-dist";
+ buildvec[i++] = (char *) drft;
+ buildvec[i] = NULL;
+ execvp(buildprogram, buildvec);
+ fprintf(stderr, "unable to exec ");
+ perror(buildmimeproc);
+ _exit(-1);
+ break;
+
+ default:
+ if (pidXwait(child, buildmimeproc))
+ return NOTOK;
+ break;
+ }
+
+ done=armed_done;
switch (setjmp (env)) {
case OK:
/*
* rename the draft file. I'm not quite sure why.
*/
if (pushsw && unique) {
- if (rename (drft, strncpy (file, m_scratch (drft, invo_name), sizeof(file)))
- == NOTOK)
+ char *cp = m_mktemp2(drft, invo_name, NULL, NULL);
+ if (cp == NULL) {
+ adios(NULL, "unable to create temporary file in %s",
+ get_temp_dir());
+ }
+ if (rename (drft, strncpy(file, cp, sizeof(file))) == NOTOK)
adios (file, "unable to rename %s to", drft);
drft = file;
}
* Check if we need to split the message into
* multiple messages of type "message/partial".
*/
- if (splitsw >= 0 && !distfile && stat (drft, &sts) != NOTOK
+ if (splitsw >= 0 && !distfile && stat ((char *) drft, &sts) != NOTOK
&& sts.st_size >= CPERMSG) {
- status = splitmsg (vec, vecp, drft, st, splitsw) ? NOTOK : OK;
+ status = splitmsg (vec, vecp, program, drft,
+ st, splitsw) ? NOTOK : OK;
} else {
- status = sendaux (vec, vecp, drft, st) ? NOTOK : OK;
+ status = sendaux (vec, vecp, program, drft, st) ? NOTOK : OK;
}
/* rename the original draft */
if (rename_drft && status == OK &&
- rename (drft, strncpy (buffer, m_backup (drft), sizeof(buffer))) == NOTOK)
+ rename (drft, strncpy (buffer, m_backup (drft),
+ sizeof(buffer))) == NOTOK)
advise (buffer, "unable to rename %s to", drft);
break;
break;
}
- armed = 0;
+ done=exit;
if (distfile)
- unlink (distfile);
+ (void) m_unlink (distfile);
return status;
}
-
/*
* Split large message into several messages of
* type "message/partial" and send them.
*/
static int
-splitmsg (char **vec, int vecp, char *drft, struct stat *st, int delay)
+splitmsg (char **vec, int vecp, char *program, char *drft,
+ struct stat *st, int delay)
{
int compnum, nparts, partno, state, status;
long pos, start;
char subject[BUFSIZ];
char name[NAMESZ], partnum[BUFSIZ];
FILE *in;
+ m_getfld_state_t gstate = 0;
if ((in = fopen (drft, "r")) == NULL)
adios (drft, "unable to open for reading");
* Scan through the message and examine the various header fields,
* as well as locate the beginning of the message body.
*/
- for (compnum = 1, state = FLD;;) {
- switch (state = m_getfld (state, name, buffer, sizeof(buffer), in)) {
+ m_getfld_track_filepos (&gstate, in);
+ for (compnum = 1;;) {
+ int bufsz = sizeof buffer;
+ switch (state = m_getfld (&gstate, name, buffer, &bufsz, in)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
compnum++;
/*
* This header field is discarded.
*/
if (!strcasecmp (name, "Message-ID")) {
- while (state == FLDPLUS)
- state = m_getfld (state, name, buffer, sizeof(buffer), in);
+ while (state == FLDPLUS) {
+ bufsz = sizeof buffer;
+ state = m_getfld (&gstate, name, buffer, &bufsz, in);
+ }
} else if (uprf (name, XXX_FIELD_PRF)
|| !strcasecmp (name, VRSN_FIELD)
|| !strcasecmp (name, "Subject")
dp = add (concat (name, ":", buffer, NULL), dp);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buffer, sizeof(buffer), in);
+ bufsz = sizeof buffer;
+ state = m_getfld (&gstate, name, buffer, &bufsz, in);
dp = add (buffer, dp);
}
} else {
*/
cp = add (concat (name, ":", buffer, NULL), cp);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buffer, sizeof(buffer), in);
+ bufsz = sizeof buffer;
+ state = m_getfld (&gstate, name, buffer, &bufsz, in);
cp = add (buffer, cp);
}
}
- if (state != FLDEOF) {
- start = ftell (in) + 1;
- continue;
- }
- /* else fall... */
+ start = ftell (in) + 1;
+ continue;
case BODY:
- case BODYEOF:
case FILEEOF:
break;
break;
}
+ m_getfld_state_destroy (&gstate);
if (cp == NULL)
adios (NULL, "headers missing from draft");
free (dp);
fclose (in);
- return sendaux (vec, vecp, drft, st);
+ return sendaux (vec, vecp, program, drft, st);
}
if (!pushsw) {
vec[vecp++] = "-queued";
time (&clock);
- snprintf (msgid, sizeof(msgid), "<%d.%ld@%s>",
- (int) getpid(), (long) clock, LocalName());
+ snprintf (msgid, sizeof(msgid), "%s", message_id (clock, 0));
fseek (in, start, SEEK_SET);
for (partno = 1; partno <= nparts; partno++) {
char tmpdrf[BUFSIZ];
FILE *out;
- strncpy (tmpdrf, m_scratch (drft, invo_name), sizeof(tmpdrf));
- if ((out = fopen (tmpdrf, "w")) == NULL)
- adios (tmpdrf, "unable to open for writing");
- chmod (tmpdrf, 0600);
+ char *cp = m_mktemp2(drft, invo_name, NULL, &out);
+ if (cp == NULL) {
+ adios(NULL, "unable to create temporary file in %s",
+ get_temp_dir());
+ }
+ strncpy(tmpdrf, cp, sizeof(tmpdrf));
/*
* Output the header fields
}
snprintf (partnum, sizeof(partnum), "%d", partno);
- status = sendaux (vec, vecp, tmpdrf, st);
- unlink (tmpdrf);
+ status = sendaux (vec, vecp, program, tmpdrf, st);
+ (void) m_unlink (tmpdrf);
if (status != OK)
break;
/*
* Annotate original message, and
- * call `postproc' to send message.
+ * call `postproc' (which is passed down in "program") to send message.
*/
static int
-sendaux (char **vec, int vecp, char *drft, struct stat *st)
+sendaux (char **vec, int vecp, char *program, char *drft, struct stat *st)
{
pid_t child_id;
int i, status, fd, fd2;
snprintf (buf, sizeof(buf), "%d", fd2);
vec[vecp++] = buf;
} else {
- admonish (NULL, "unable to create file for annotation list");
+ admonish (NULL, "unable to create temporary file in %s "
+ "for annotation list", get_temp_dir());
}
}
if (distfile && distout (drft, distfile, backup) == NOTOK)
done (1);
vec[vecp] = NULL;
- for (i = 0; (child_id = vfork()) == NOTOK && i < 5; i++)
+ for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++)
sleep (5);
switch (child_id) {
dup2 (fd, fileno (stderr));
close (fd);
}
- execvp (postproc, vec);
+ execvp (program, vec);
fprintf (stderr, "unable to exec ");
perror (postproc);
_exit (-1);
- break; /* NOT REACHED */
default:
/*
if (annotext && fd2 != NOTOK)
close (fd2);
if (distfile) {
- unlink (drft);
+ (void) m_unlink (drft);
if (rename (backup, drft) == NOTOK)
advise (drft, "unable to rename %s to", backup);
}
alert (char *file, int out)
{
pid_t child_id;
- int i, in;
+ int i, in, argp;
char buf[BUFSIZ];
+ char *program;
+ char **arglist;
for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++)
sleep (5);
} else {
lseek (out, (off_t) 0, SEEK_END);
strncpy (buf, "\nMessage not delivered to anyone.\n", sizeof(buf));
- write (out, buf, strlen (buf));
+ if (write (out, buf, strlen (buf)) < 0) {
+ advise (file, "write");
+ }
strncpy (buf, "\n------- Unsent Draft\n\n", sizeof(buf));
- write (out, buf, strlen (buf));
+ if (write (out, buf, strlen (buf)) < 0) {
+ advise (file, "write");
+ }
cpydgst (in, out, file, "temporary file");
close (in);
strncpy (buf, "\n------- End of Unsent Draft\n", sizeof(buf));
- write (out, buf, strlen (buf));
+ if (write (out, buf, strlen (buf)) < 0) {
+ advise (file, "write");
+ }
if (rename (file, strncpy (buf, m_backup (file), sizeof(buf))) == NOTOK)
admonish (buf, "unable to rename %s to", file);
}
snprintf (buf, sizeof(buf), "send failed on %s",
forwsw ? "enclosed draft" : file);
- execlp (mailproc, r1bindex (mailproc, '/'), getusername (),
- "-subject", buf, NULL);
+ arglist = argsplit(mailproc, &program, &argp);
+
+ arglist[argp++] = getusername();
+ arglist[argp++] = "-subject";
+ arglist[argp++] = buf;
+ arglist[argp] = NULL;
+
+ execvp (program, arglist);
fprintf (stderr, "unable to exec ");
perror (mailproc);
_exit (-1);
tmp_fd (void)
{
int fd;
- char tmpfil[BUFSIZ];
+ char *tfile;
+
+ if ((tfile = m_mktemp2(NULL, invo_name, &fd, NULL)) == NULL) return NOTOK;
- strncpy (tmpfil, m_tmpfil (invo_name), sizeof(tmpfil));
- if ((fd = open (tmpfil, O_RDWR | O_CREAT | O_TRUNC, 0600)) == NOTOK)
- return NOTOK;
if (debugsw)
- advise (NULL, "temporary file %s selected", tmpfil);
+ advise (NULL, "temporary file %s selected", tfile);
else
- if (unlink (tmpfil) == NOTOK)
- advise (tmpfil, "unable to remove");
+ if (m_unlink (tfile) == NOTOK)
+ advise (tfile, "unable to remove");
return fd;
}
sigaddset (&set, SIGINT);
sigaddset (&set, SIGQUIT);
sigaddset (&set, SIGTERM);
- SIGPROCMASK (SIG_BLOCK, &set, &oset);
+ sigprocmask (SIG_BLOCK, &set, &oset);
+
+ unregister_for_removal(0);
annoaux (fd);
if (child_id == OK)
_exit (0);
/* reset the signal mask */
- SIGPROCMASK (SIG_SETMASK, &oset, &set);
+ sigprocmask (SIG_SETMASK, &oset, &set);
- chdir (cwd);
+ if (chdir (cwd) < 0) {
+ advise (cwd, "chdir");
+ }
break;
default: /* no waiting... */
admonish (maildir, "unable to change directory to");
return;
}
- if (!(mp = folder_read (folder))) {
+ if (!(mp = folder_read (folder, 0))) {
if (debugsw)
- admonish (NULL, "unable to read folder %s");
+ admonish (NULL, "unable to read folder %s", folder);
return;
}
if (is_selected(mp, msgnum)) {
if (debugsw)
advise (NULL, "annotate message %d", msgnum);
- annotate (m_name (msgnum), annotext, cp, inplace, 1);
+ annotate (m_name (msgnum), annotext, cp, inplace, 1, -2, 0);
}
}
}
-int
-done (int status)
+static void
+armed_done (int status)
{
- if (armed)
- longjmp (env, status ? status : NOTOK);
-
- exit (status);
- return 1; /* dead code to satisfy the compiler */
+ longjmp (env, status ? status : NOTOK);
}