Ticket #12609: 0001-Detect-terminal-input-end-of-file-better-argument-pa.patch

File 0001-Detect-terminal-input-end-of-file-better-argument-pa.patch, 5.0 KB (added by AGMS, 8 years ago)

Fixes several bugs in /bin/mail, now with coding style fixes.

  • src/bin/mail_utils/mail.cpp

    From e9fd0ef9e599d44c9286d41aa95a05a18e530e0d Mon Sep 17 00:00:00 2001
    From: "Alexander G. M. Smith" <agmsmith@ncf.ca>
    Date: Mon, 29 Feb 2016 16:40:11 +0000
    Subject: [PATCH] Detect terminal input, end of file, better argument parsing.
    
    * If the input is a terminal rather than a file or pipe, only then look
      for the single period on a line as end of text.  Also look for end of
      file as an end of the text, so that piped in text works.
    * Parse multiple e-mail addresses properly, adding a comma between them
      (a space doesn't work).  Also allow mixing of "to" e-mail addresses
      and command line switches, previously all "to" addresses had to be
      at the end.
    * Fewer blank lines in the output, make it look nicer, remove things
      like a redundant display of the body text before text was read.  Also
      no output text when just piping in a message.
    * Avoid buffer overrun by using fgets instead of gets.
    ---
     src/bin/mail_utils/mail.cpp | 78 +++++++++++++++++++++++++--------------------
     1 file changed, 43 insertions(+), 35 deletions(-)
    
    diff --git a/src/bin/mail_utils/mail.cpp b/src/bin/mail_utils/mail.cpp
    index f33bc07..aa69935 100644
    a b  
    99 */
    1010
    1111
    12 #include <Application.h>
    13 #include <String.h>
    14 #include <E-mail.h>
    15 
    1612#include <stdio.h>
     13#include <unistd.h>
    1714
     15#include <Application.h>
     16#include <E-mail.h>
     17#include <String.h>
    1818
    19 #define APP_SIG             "application/x-vnd.Haiku-mail_utils-mail"
     19#define APP_SIG "application/x-vnd.Haiku-mail_utils-mail"
    2020
    2121
    2222int main(int argc, char* argv[])
    int main(int argc, char* argv[])  
    2828        fprintf(stdout,"This program can only send mail, not read it.\n");
    2929        fprintf(stdout,"usage: %s [-v] [-s subject] [-c cc-addr] "
    3030            "[-b bcc-addr] to-addr ...\n", argv[0]);
    31         fflush(stdout);
    3231        return 0;
    3332    }
    3433
    35     char *subject = "No title";
     34    char *subject = "No subject";
    3635    char *cc = "";
    3736    char *bcc = "";
    38     BString to = "";
    39     BString body = "";
     37    BString to;
     38    bool verbose = false;
    4039
    41     bool verbose =false;
    4240    // Parse arguments
    4341    for (int i = 1; i < argc; i++) {
    4442        if (strcmp(argv[i], "-v") == 0)
    int main(int argc, char* argv[])  
    5351            bcc = argv[i+1];
    5452            i++;
    5553        } else {
     54            if (to.Length() > 0)
     55                to.Append(", ");
    5656            to.Append(argv[i]);
    57             if (i < argc - 1)
    58                 to.Append(" ");
    59         }
     57        }
    6058    }
    6159
    6260    if (verbose) {
    6361        fprintf(stdout, "\n");
    64         fprintf(stdout, "To:\t<%s> \n", to.String());
    65         fprintf(stdout, "Cc:\t<%s> \n", cc);
    66         fprintf(stdout, "Bcc:\t<%s> \n", bcc);
    67         fprintf(stdout, "Subj:\t<%s> \n", subject);
    68         fprintf(stdout, "Body:\t<%s> \n", body.String());
    69         fprintf(stdout, "\n");
     62        fprintf(stdout, "To:\t%s\n", to.String());
     63        fprintf(stdout, "Cc:\t%s\n", cc);
     64        fprintf(stdout, "Bcc:\t%s\n", bcc);
     65        fprintf(stdout, "Subj:\t%s\n", subject);
     66        fprintf(stdout, "\n");
    7067    }
    7168
    7269    // Check if recipients are valid
    73     if (strcmp(to.String(), "") == 0 &&
    74         strcmp(cc, "") == 0 &&
    75         strcmp(bcc, "") == 0) {
     70    if (strcmp(to.String(), "") == 0 &&
     71        strcmp(cc, "") == 0 &&
     72        strcmp(bcc, "") == 0) {
    7673
    7774        fprintf(stdout, "[Error]: You must specify at least one recipient "
    7875            "in to, cc or bcc fields.\n");
    7976        return -1;
    8077    }
    8178
    82     // Read each line until we get a single dot "." on a line
     79    bool isTerminal = isatty(STDIN_FILENO) != 0;
     80    if (isTerminal) {
     81        printf("Now type your message.\n"
     82            "Type '.' alone on a line to end your text and send it.\n");
     83    }
     84
     85    BString body;
    8386    char line[32768] = "";
    8487
    85     printf("Now type your message.\nType '.' alone on a line to send it.\n");
     88    // Read each line and collect the body text until we get an end of text
     89    // marker.  That's a single dot "." on a line typed in by the user,
     90    // or end of file when reading a file.
    8691    do {
    87         gets(line);
    88 
    89         if (strcmp(line, ".") != 0) {
    90             body.Append(line).Append("\n");
     92        if (fgets(line, sizeof(line), stdin) == NULL) {
     93            // End of file or an error happened, just send collected body text.
     94            break;
    9195        }
    92         // fprintf(stdout,"Line: %s \n",line);
    93     } while (strcmp(line, ".") != 0);
    9496
     97        if (isTerminal && strcmp(line, ".\n") == 0)
     98            break;
     99
     100        body.Append(line);
     101    } while (true);
    95102
    96103    if (verbose)
    97         fprintf(stdout, "\nBody:\n%s\n", body.String());
     104        fprintf(stdout, "\nBody:\n%s\n", body.String());
    98105
    99106    if (verbose)
    100         fprintf(stdout, "\nSending E-mail...\n");
     107        fprintf(stdout, "Sending E-mail...\n");
    101108    fflush(stdout);
    102109
    103110    BMailMessage mail;
    int main(int argc, char* argv[])  
    105112    mail.AddHeaderField(B_MAIL_CC, cc);
    106113    mail.AddHeaderField(B_MAIL_BCC, bcc);
    107114    mail.AddHeaderField(B_MAIL_SUBJECT, subject);
    108     mail.AddContent(body.String(), strlen(body.String()));
     115    mail.AddContent(body.String(), body.Length());
    109116    status_t result = mail.Send();
    110117
    111118    if (result == B_OK) {
    112         fprintf(stdout, "\nMessage was sent successfully.\n");
     119        if (verbose)
     120            fprintf(stdout, "Message was sent successfully.\n");
    113121        return 0;
    114122    }
    115123
    116     fprintf(stdout, "Message failed to send: %s", strerror(result));
     124    fprintf(stdout, "Message failed to send: %s\n", strerror(result));
    117125    return result;
    118126}