int forwsw = 1;
int inplace = 1;
int pushsw = 0;
-int unique = 0;
int verbsw = 0;
char *altmsg = NULL; /* .. */
/*
** external prototypes
*/
-int sendsbr(char **, int, char *, struct stat *, int, char *, int);
+int sendsbr(char **, int, char *, struct stat *, int);
char *getusername(void);
/*
static void annoaux(int);
static int sendaux(char **, int, char *, struct stat *);
-static int attach(char *, char *, int);
+static int attach(char *);
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
-sendsbr(char **vec, int vecp, char *drft, struct stat *st,
- int rename_drft, char *attachment_header_field_name, int attachformat)
+sendsbr(char **vec, int vecp, char *drft, struct stat *st, int rename_drft)
{
int status;
- char buffer[BUFSIZ], file[BUFSIZ];
+ char buffer[BUFSIZ];
char *original_draft; /* name of original draft file */
char *p; /* string pointer for building file name */
original_draft = drft;
/*
- ** There might be attachments if a header field name for
- ** attachments is supplied. Convert the draft to a MIME message.
+ ** Convert the draft to a MIME message.
** Use the mhbuild composition file for the draft if there was
** a successful conversion because that now contains the MIME
** message. A nice side effect of this is that it leaves the
** original draft file untouched so that it can be retrieved
** and modified if desired.
*/
+ switch (attach(drft)) {
+ case OK:
+ drft = composition_file_name;
+ break;
- if (attachment_header_field_name != NULL) {
- switch (attach(attachment_header_field_name, drft,
- attachformat)) {
- case OK:
- drft = composition_file_name;
- break;
-
- case NOTOK:
- return (NOTOK);
+ case NOTOK:
+ return (NOTOK);
- case DONE:
- break;
- }
+ case DONE:
+ break;
}
done=armed_done;
switch (setjmp(env)) {
case OK:
- /*
- ** If given -push and -unique (which is undocumented), then
- ** rename the draft file. I'm not quite sure why.
- */
- if (pushsw && unique) {
- 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;
- }
-
status = sendaux(vec, vecp, drft, st) ? NOTOK : OK;
-
/* rename the original draft */
if (rename_drft && status == OK &&
rename(original_draft, strncpy(buffer,
}
static int
-attach(char *attachment_header_field_name, char *draft_file_name,
- int attachformat)
+attach(char *draft_file_name)
{
char buf[MAXPATHLEN + 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 non_ascii; /* msg body contains non-ASCII chars */
int length; /* length of attachment header field name */
char *p; /* miscellaneous string pointer */
- /*
- ** Open up the draft file.
- */
-
+ /* Open up the draft file. */
if ((draft_file = fopen(draft_file_name, "r")) == (FILE *)0)
adios(NULL, "can't open draft file `%s'.",
draft_file_name);
** Allocate a buffer to hold the header components as they're read in.
** This buffer might need to be quite large, so we grow it as needed.
*/
-
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
+ ** Scan the draft file for an attachment header field name.
+ ** 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);
+ length = strlen(attach_hdr);
has_attachment = 0;
while (get_line() != EOF && *field != '\0' && *field != '-')
- if (strncasecmp(field, attachment_header_field_name, length)
- == 0 && field[length] == ':')
+ if (strncasecmp(field, attach_hdr, length) == 0 &&
+ field[length] == ':')
has_attachment = 1;
- if (has_attachment == 0)
- return (DONE);
-
/*
** We have at least one attachment. Look for at least one
** non-blank line in the body of the message which indicates
** content in the body.
+ ** Check if body contains at least one non-blank (= not empty)
+ ** and if it contains any non-ASCII chars (= need MIME).
*/
-
has_body = 0;
+ non_ascii = 0;
while (get_line() != EOF) {
for (p = field; *p != '\0'; p++) {
if (*p != ' ' && *p != '\t') {
has_body = 1;
- break;
+ }
+ if (*p > 127 || *p < 0) {
+ non_ascii = 1;
}
}
-
- if (has_body)
+ if (has_body && non_ascii)
break;
}
/*
- ** Make names for the temporary files.
+ ** Bail out if there are no attachments and only ASCII text.
+ ** This means we don't need to convert it to MIME.
*/
+ if (!has_attachment && non_ascii==0) {
+ return DONE;
+ }
+ /*
+ ** Else: mimify
+ */
+
+ /* Make names for the temporary files. */
strncpy(body_file_name,
m_mktemp(toabsdir(invo_name), NULL, NULL),
sizeof (body_file_name));
** 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, attach_hdr, length) != 0 ||
+ field[length] != ':')
fprintf(composition_file, "%s\n", field);
-
fputs("--------\n", composition_file);
/*
** Copy the message body to a temporary file.
*/
-
if (has_body) {
while ((c = getc(draft_file)) != EOF)
putc(c, body_file);
-
fclose(body_file);
}
** Add a mhbuild MIME composition file line for the body if
** there was one.
*/
-
- if (has_body)
- make_mime_composition_file_entry(body_file_name, attachformat);
+ if (has_body) {
+ /* old: make_mime_composition_file_entry(body_file_name); */
+ /* charset will be discovered/guessed by buildmimeproc */
+ fprintf(composition_file, "#text/plain %s\n", body_file_name);
+ }
/*
** 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.
*/
-
rewind(draft_file);
-
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++)
- ;
-
- make_mime_composition_file_entry(p, attachformat);
+ if (strncasecmp(field, attach_hdr, length) == 0 &&
+ field[length] == ':') {
+ for (p = field+length+1; *p==' ' || *p=='\t'; p++) {
+ continue;
+ }
+ if (*p == '+') {
+ /* forwarded message */
+ fprintf(composition_file, "#forw [forwarded message(s)] %s\n", p);
+ } else {
+ make_mime_composition_file_entry(p);
+ }
}
}
** We're ready to roll! Run mhbuild on the composition file.
** Note that mhbuild is in the context as buildmimeproc.
*/
-
sprintf(buf, "%s %s", buildmimeproc, composition_file_name);
if (system(buf) != 0) {
}
static void
-make_mime_composition_file_entry(char *file_name, int attachformat)
+make_mime_composition_file_entry(char *file_name)
{
int binary; /* binary character found flag */
int c; /* current character */
- char cmd[MAXPATHLEN + 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 = NULL;
** (if possible) by running the "file" command on the file.
*/
- if (stat(file_name, &st) == -1 || access(file_name, R_OK) != 0) {
+ if (access(file_name, R_OK) != 0) {
clean_up_temporary_files();
adios(NULL, "unable to access file \"%s\"", file_name);
}
- switch (attachformat) {
- case 0:
- /* Insert name, file mode, and Content-Id. */
- fprintf(composition_file,
- "#%s; name=\"%s\"; x-unix-mode=0%.3ho",
- content_type, ((p = strrchr(file_name, '/'))
- == NULL) ? file_name : p + 1,
- (unsigned short)(st.st_mode & 0777));
-
- if (strlen(file_name) > MAXPATHLEN) {
- clean_up_temporary_files();
- adios(NULL, "attachment file name `%s' too long.",
- file_name);
- }
-
- sprintf(cmd, "file '%s'", file_name);
-
- if ((fp = popen(cmd, "r")) != (FILE *)0 &&
- fgets(cmd, sizeof (cmd), fp) != NULL) {
- *strchr(cmd, '\n') = '\0';
-
- /*
- ** The output of the "file" command is of the form
- **
- ** file: description
- **
- ** Strip off the "file:" and subsequent white space.
- */
-
- for (p = cmd; *p != '\0'; p++) {
- if (*p == ':') {
- for (p++; *p != '\0'; p++) {
- if (*p != '\t')
- break;
- }
- break;
- }
- }
-
- if (*p != '\0')
- /* Insert Content-Description. */
- fprintf(composition_file, " [ %s ]", p);
-
- pclose(fp);
- }
- break;
- case 1:
- if (stringdex(toabsdir(invo_name), file_name) == 0) {
- /*
- ** Content had been placed by send into a temp file.
- ** Don't generate Content-Disposition header, because
- ** it confuses Microsoft Outlook, Build 10.0.6626, at
- ** least.
- */
- fprintf(composition_file, "#%s <>", content_type);
- } else {
- /*
- ** Suppress Content-Id, insert simple
- ** Content-Disposition.
- */
- fprintf(composition_file,
- "#%s; name=\"%s\" <>{attachment}",
- content_type,
- ((p = strrchr(file_name, '/')) == NULL) ?
- file_name : p + 1);
- }
-
- break;
- case 2:
- if (stringdex(toabsdir(invo_name), file_name) == 0) {
- /*
- ** Content had been placed by send into a temp file.
- ** Don't generate Content-Disposition header, because
- ** it confuses Microsoft Outlook, Build 10.0.6626, at
- ** least.
- */
- fprintf(composition_file, "#%s <>", content_type);
- } else {
- /*
- ** Suppress Content-Id, insert Content-Disposition
- ** with modification date.
- */
- fprintf(composition_file,
- "#%s; name=\"%s\" <>{attachment; modification-date=\"%s\"}",
- content_type,
- ((p = strrchr(file_name, '/')) == NULL) ?
- file_name : p + 1, dtime(&st.st_mtime, 0));
- }
-
- break;
- default:
- adios(NULL, "unsupported attachformat %d", attachformat);
+ if (stringdex(toabsdir(invo_name), file_name) == 0) {
+ /*
+ ** Content had been placed by send into a temp file.
+ ** Don't generate Content-Disposition header, because
+ ** it confuses Microsoft Outlook, Build 10.0.6626, at
+ ** least.
+ */
+ fprintf(composition_file, "#%s <>", content_type);
+ } else {
+ /*
+ ** Suppress Content-Id, insert simple
+ ** Content-Disposition.
+ */
+ fprintf(composition_file,
+ "#%s; name=\"%s\" <>{attachment}",
+ content_type,
+ ((p = strrchr(file_name, '/')) == NULL) ?
+ file_name : p + 1);
}
- /*
- ** Finish up with the file name.
- */
-
+ /* Finish up with the file name. */
fprintf(composition_file, " %s\n", file_name);
return;
{
pid_t child_id;
int i, status, fd, fd2;
- char backup[BUFSIZ], buf[BUFSIZ];
+ char backup[BUFSIZ];
fd = pushsw ? tmp_fd() : NOTOK;
fd2 = NOTOK;
vec[vecp++] = drft;
- if (annotext) {
- if ((fd2 = tmp_fd()) != NOTOK) {
- vec[vecp++] = "-idanno";
- snprintf(buf, sizeof(buf), "%d", fd2);
- vec[vecp++] = buf;
- } else {
- admonish(NULL, "unable to create file for annotation list");
- }
+ if (annotext && (fd2 = tmp_fd()) == NOTOK) {
+ admonish(NULL, "unable to create file for annotation list");
}
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) {
sleep(5);
switch (child_id) {
- case NOTOK:
- /* oops -- fork error */
- advise("fork", "unable to");
-
- case OK:
- /* child process -- send it */
- SIGNAL(SIGHUP, SIG_IGN);
- SIGNAL(SIGINT, SIG_IGN);
- SIGNAL(SIGQUIT, SIG_IGN);
- SIGNAL(SIGTERM, SIG_IGN);
- if (forwsw) {
- if ((in = open(file, O_RDONLY)) == NOTOK) {
- admonish(file, "unable to re-open");
- } else {
- lseek(out, (off_t) 0, SEEK_END);
- strncpy(buf, "\nMessage not delivered to anyone.\n", sizeof(buf));
- write(out, buf, strlen(buf));
- strncpy(buf, "\n------- Unsent Draft\n\n", sizeof(buf));
- write(out, buf, strlen(buf));
- cpydgst(in, out, file, "temporary file");
- close(in);
- strncpy(buf, "\n------- End of Unsent Draft\n", sizeof(buf));
- write(out, buf, strlen(buf));
- if (rename(file, strncpy(buf, m_backup(file), sizeof(buf))) == NOTOK)
- admonish(buf, "unable to rename %s to", file);
- }
+ case NOTOK:
+ /* oops -- fork error */
+ advise("fork", "unable to");
+
+ case OK:
+ /* child process -- send it */
+ SIGNAL(SIGHUP, SIG_IGN);
+ SIGNAL(SIGINT, SIG_IGN);
+ SIGNAL(SIGQUIT, SIG_IGN);
+ SIGNAL(SIGTERM, SIG_IGN);
+ if (forwsw) {
+ if ((in = open(file, O_RDONLY)) == NOTOK) {
+ admonish(file, "unable to re-open");
+ } else {
+ lseek(out, (off_t) 0, SEEK_END);
+ strncpy(buf, "\nMessage not delivered to anyone.\n", sizeof(buf));
+ write(out, buf, strlen(buf));
+ strncpy(buf, "\n------- Unsent Draft\n\n", sizeof(buf));
+ write(out, buf, strlen(buf));
+ cpydgst(in, out, file, "temporary file");
+ close(in);
+ strncpy(buf, "\n------- End of Unsent Draft\n", sizeof(buf));
+ write(out, buf, strlen(buf));
+ if (rename(file, strncpy(buf, m_backup(file), sizeof(buf))) == NOTOK)
+ admonish(buf, "unable to rename %s to", file);
}
- lseek(out, (off_t) 0, SEEK_SET);
- dup2(out, fileno(stdin));
- close(out);
- /* create subject for error notification */
- snprintf(buf, sizeof(buf), "send failed on %s",
- forwsw ? "enclosed draft" : file);
-
- execlp(mailproc, mhbasename(mailproc),
- getusername(), "-subject", buf, NULL);
- fprintf(stderr, "unable to exec ");
- perror(mailproc);
- _exit(-1);
-
- default: /* no waiting... */
- break;
+ }
+ lseek(out, (off_t) 0, SEEK_SET);
+ dup2(out, fileno(stdin));
+ close(out);
+ /* create subject for error notification */
+ snprintf(buf, sizeof(buf), "send failed on %s",
+ forwsw ? "enclosed draft" : file);
+
+ execlp(mailproc, mhbasename(mailproc), getusername(),
+ "-subject", buf, NULL);
+ fprintf(stderr, "unable to exec ");
+ perror(mailproc);
+ _exit(-1);
+
+ default: /* no waiting... */
+ break;
}
}
child_id = debugsw ? NOTOK : fork();
switch (child_id) {
- case NOTOK: /* oops */
- if (!debugsw)
- advise(NULL, "unable to fork, so doing annotations by hand...");
- if (cwd == NULL)
- cwd = getcpy(pwd());
-
- case OK:
- /* block a few signals */
- sigemptyset(&set);
- sigaddset(&set, SIGHUP);
- sigaddset(&set, SIGINT);
- sigaddset(&set, SIGQUIT);
- sigaddset(&set, SIGTERM);
- SIGPROCMASK(SIG_BLOCK, &set, &oset);
-
- annoaux(fd);
- if (child_id == OK)
- _exit(0);
-
- /* reset the signal mask */
- SIGPROCMASK(SIG_SETMASK, &oset, &set);
-
- chdir(cwd);
- break;
+ case NOTOK: /* oops */
+ if (!debugsw)
+ advise(NULL, "unable to fork, so doing annotations by hand...");
+ if (cwd == NULL)
+ cwd = getcpy(pwd());
- default: /* no waiting... */
- close(fd);
- break;
+ case OK:
+ /* block a few signals */
+ sigemptyset(&set);
+ sigaddset(&set, SIGHUP);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGQUIT);
+ sigaddset(&set, SIGTERM);
+ SIGPROCMASK(SIG_BLOCK, &set, &oset);
+
+ annoaux(fd);
+ if (child_id == OK)
+ _exit(0);
+
+ /* reset the signal mask */
+ SIGPROCMASK(SIG_SETMASK, &oset, &set);
+
+ chdir(cwd);
+ break;
+
+ default: /* no waiting... */
+ close(fd);
+ break;
}
}
if (is_selected(mp, msgnum)) {
if (debugsw)
advise(NULL, "annotate message %d", msgnum);
- annotate(m_name (msgnum), annotext, cp, inplace,
+ annotate(m_name(msgnum), annotext, cp, inplace,
1, -2, 0);
}
}