/*
* 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/tws.h>
#include <h/utils.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;
static jmp_buf env;
-static char body_file_name[MAXPATHLEN + 1]; /* name of temporary file for body content */
-static char composition_file_name[MAXPATHLEN + 1]; /* name of mhbuild composition temporary file */
+static char body_file_name[PATH_MAX + 1]; /* name of temporary file for body content */
+static char composition_file_name[PATH_MAX + 1]; /* name of mhbuild composition temporary file */
static int field_size; /* size of header field buffer */
static char *field; /* header field buffer */
static FILE *draft_file; /* draft file pointer */
static int attach(char *, char *, int);
static void clean_up_temporary_files(void);
static int get_line(void);
-static void make_mime_composition_file_entry(char *, int);
+static void make_mime_composition_file_entry(char *, int, char *);
/*
* 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 ("sendsbr", "unable to create temporary file");
+ }
+ if (rename (drft, strncpy(file, cp, sizeof(file))) == NOTOK)
adios (file, "unable to rename %s to", drft);
drft = file;
}
attach(char *attachment_header_field_name, char *draft_file_name,
int attachformat)
{
- char buf[MAXPATHLEN + 6]; /* miscellaneous buffer */
+ char buf[PATH_MAX + 6]; /* miscellaneous buffer */
int c; /* current character for body copy */
int has_attachment; /* draft has at least one attachment */
int has_body; /* draft has a message body */
int length; /* length of attachment header field name */
char *p; /* miscellaneous string pointer */
+ FILE *fp; /* pointer for mhn.defaults */
/*
* Open up the draft file.
field = (char *)mh_xmalloc(field_size = 256);
/*
- * Scan the draft file for a header field name that matches the -attach
- * argument. The existence of one indicates that the draft has attachments.
- * Bail out if there are no attachments because we're done. Read to the
- * end of the headers even if we have no attachments.
+ * Scan the draft file for a header field name, with a non-empty
+ * body, that matches the -attach argument. The existence of one
+ * indicates that the draft has attachments. Bail out if there
+ * are no attachments because we're done. Read to the end of the
+ * headers even if we have no attachments.
*/
length = strlen(attachment_header_field_name);
has_attachment = 0;
- while (get_line() != EOF && *field != '\0' && *field != '-')
- if (strncasecmp(field, attachment_header_field_name, length) == 0 && field[length] == ':')
- has_attachment = 1;
+ while (get_line() != EOF && *field != '\0' && *field != '-') {
+ if (strncasecmp(field, attachment_header_field_name, length) == 0 &&
+ field[length] == ':') {
+ for (p = field + length + 1; *p == ' ' || *p == '\t'; p++)
+ ;
+ if (strlen (p) > 0) {
+ has_attachment = 1;
+ }
+ }
+ }
if (has_attachment == 0)
return (DONE);
* Make names for the temporary files.
*/
- (void)strncpy(body_file_name, m_scratch("", m_maildir(invo_name)), sizeof (body_file_name));
- (void)strncpy(composition_file_name, m_scratch("", m_maildir(invo_name)), sizeof (composition_file_name));
+ (void)strncpy(body_file_name,
+ m_mktemp(m_maildir(invo_name), NULL, NULL),
+ sizeof (body_file_name));
+ (void)strncpy(composition_file_name,
+ m_mktemp(m_maildir(invo_name), NULL, NULL),
+ sizeof (composition_file_name));
if (has_body)
body_file = fopen(body_file_name, "w");
}
/*
- * Start at the beginning of the draft file. Copy all non-attachment header fields
- * to the temporary composition file. Then add the dashed line separator.
+ * Start at the beginning of the draft file. Copy all
+ * non-attachment header fields to the temporary composition
+ * file. Then add the dashed line separator.
*/
rewind(draft_file);
while (get_line() != EOF && *field != '\0' && *field != '-')
- if (strncasecmp(field, attachment_header_field_name, length) != 0 || field[length] != ':')
+ if (strncasecmp(field, attachment_header_field_name, length) != 0 ||
+ field[length] != ':')
(void)fprintf(composition_file, "%s\n", field);
(void)fputs("--------\n", composition_file);
/*
* Add a mhbuild MIME composition file line for the body if there was one.
+ * Set the default content type to text/plain so that mhbuild takes care
+ * of any necessary encoding.
*/
if (has_body)
- make_mime_composition_file_entry(body_file_name, attachformat);
+ make_mime_composition_file_entry(body_file_name, attachformat,
+ "text/plain");
/*
- * Now, go back to the beginning of the draft file and look for header fields
- * that specify attachments. Add a mhbuild MIME composition file for each.
+ * Now, go back to the beginning of the draft file and look for
+ * header fields that specify attachments. Add a mhbuild MIME
+ * composition file for each.
*/
+ if ((fp = fopen (p = etcpath ("mhn.defaults"), "r"))) {
+ readconfig ((struct node **) NULL, fp, p, 0);
+ fclose(fp);
+ }
+
rewind(draft_file);
while (get_line() != EOF && *field != '\0' && *field != '-') {
- if (strncasecmp(field, attachment_header_field_name, length) == 0 && field[length] == ':') {
+ if (strncasecmp(field, attachment_header_field_name, length) == 0 &&
+ field[length] == ':') {
for (p = field + length + 1; *p == ' ' || *p == '\t'; p++)
;
- make_mime_composition_file_entry(p, attachformat);
+ /* Skip empty attachment_header_field_name lines. */
+ if (strlen (p) > 0) {
+ struct stat st;
+ if (stat (p, &st) == OK) {
+ if (S_ISREG (st.st_mode)) {
+ /* Don't set the default content type so take
+ make_mime_composition_file_entry() will try
+ to infer it from the file type. */
+ make_mime_composition_file_entry(p, attachformat, 0);
+ } else {
+ adios (NULL, "unable to attach %s, not a plain file",
+ p);
+ }
+ } else {
+ adios (NULL, "unable to access file \"%s\"", p);
+ }
+ }
}
}
(void)fclose(composition_file);
/*
- * We're ready to roll! Run mhbuild on the composition file. Note that mhbuild
- * is in the context as buildmimeproc.
+ * We're ready to roll! Run mhbuild on the composition file.
+ * Note that mhbuild is in the context as buildmimeproc.
*/
(void)sprintf(buf, "%s %s", buildmimeproc, composition_file_name);
}
static void
-make_mime_composition_file_entry(char *file_name, int attachformat)
+make_mime_composition_file_entry(char *file_name, int attachformat,
+ char *default_content_type)
{
int binary; /* binary character found flag */
int c; /* current character */
- char cmd[MAXPATHLEN + 6]; /* file command buffer */
+ char cmd[PATH_MAX + 6]; /* file command buffer */
char *content_type; /* mime content type */
FILE *fp; /* content and pipe file pointer */
struct node *np; /* context scan node pointer */
char *p; /* miscellaneous string pointer */
struct stat st; /* file status buffer */
- content_type = (char *)0;
+ content_type = default_content_type;
/*
* Check the file name for a suffix. Scan the context for that suffix on a
(void)fprintf(composition_file, "#%s; name=\"%s\"; x-unix-mode=0%.3ho",
content_type, ((p = strrchr(file_name, '/')) == (char *)0) ? file_name : p + 1, (unsigned short)(st.st_mode & 0777));
- if (strlen(file_name) > MAXPATHLEN) {
+ if (strlen(file_name) > PATH_MAX) {
clean_up_temporary_files();
adios((char *)0, "attachment file name `%s' too long.", file_name);
}
least. */
(void) fprintf (composition_file, "#%s <>", content_type);
} else {
- /* Suppress Content-Id, insert simple Content-Disposition. */
+ /* Suppress Content-Id, insert simple Content-Disposition
+ and Content-Description with filename. */
+ p = strrchr(file_name, '/');
(void) fprintf (composition_file,
- "#%s; name=\"%s\" <>{attachment}",
+ "#%s; name=\"%s\" <> [%s]{attachment}",
content_type,
- ((p = strrchr(file_name, '/')) == (char *)0) ? file_name : p + 1);
+ (p == (char *)0) ? file_name : p + 1,
+ (p == (char *)0) ? file_name : p + 1);
}
break;
(void) fprintf (composition_file, "#%s <>", content_type);
} else {
/* Suppress Content-Id, insert Content-Disposition with
- modification date. */
+ modification date and Content-Description wtih filename. */
+ p = strrchr(file_name, '/');
(void) fprintf (composition_file,
- "#%s; name=\"%s\" <>{attachment; modification-date=\"%s\"}",
+ "#%s; name=\"%s\" <>[%s]{attachment; modification-date=\"%s\"}",
content_type,
- ((p = strrchr(file_name, '/')) == (char *)0) ? file_name : p + 1,
+ (p == (char *)0) ? file_name : p + 1,
+ (p == (char *)0) ? file_name : p + 1,
dtime (&st.st_mtime, 0));
}
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");
+ char *cp = m_mktemp2(drft, invo_name, NULL, &out);
+ if (cp == NULL) {
+ adios (drft, "unable to create temporary file for");
+ }
+ strncpy(tmpdrf, cp, sizeof(tmpdrf));
chmod (tmpdrf, 0600);
/*
tmp_fd (void)
{
int fd;
- char tmpfil[BUFSIZ];
+ char *tfile = NULL;
+
+ tfile = m_mktemp2(NULL, invo_name, &fd, NULL);
+ if (tfile == NULL) return NOTOK;
+ fchmod(fd, 0600);
- 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 (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);
annoaux (fd);
if (child_id == OK)
_exit (0);
/* reset the signal mask */
- SIGPROCMASK (SIG_SETMASK, &oset, &set);
+ sigprocmask (SIG_SETMASK, &oset, &set);
chdir (cwd);
break;