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

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

Now with stderr for certain messages (mostly stuff you need to see when stdout is sent to a file, stdout used for things you might want to save in a file), and style changes as suggested by Axel.

  • src/bin/mail_utils/mail.cpp

    From f75390e7aaae7ae6abfa7d8857d8c9814a5922d2 Mon Sep 17 00:00:00 2001
    From: "Alexander G. M. Smith" <agmsmith@ncf.ca>
    Date: Wed, 2 Mar 2016 18:45:08 +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.
    * Use stderr for text the user likely doesn't want to save, and for
      prompts that would be invisible if stdout was redirected to a file.
    ---
     src/bin/mail_utils/mail.cpp | 81 +++++++++++++++++++++++++--------------------
     1 file changed, 45 insertions(+), 36 deletions(-)
    
    diff --git a/src/bin/mail_utils/mail.cpp b/src/bin/mail_utils/mail.cpp
    index f33bc07..97aff49 100644
    a b  
    66 *      Santiago (Jacques) Lema
    77 *      Jérôme Duval, jerome.duval@gmail.com
    88 *      Augustin Cavalier, <waddlesplash>
     9 *      Alexander G. M. Smith <agmsmith@ncf.ca>
    910 */
    1011
    1112
    12 #include <Application.h>
    13 #include <String.h>
    14 #include <E-mail.h>
    15 
    1613#include <stdio.h>
     14#include <unistd.h>
    1715
     16#include <Application.h>
     17#include <E-mail.h>
     18#include <String.h>
    1819
    19 #define APP_SIG             "application/x-vnd.Haiku-mail_utils-mail"
     20#define APP_SIG "application/x-vnd.Haiku-mail_utils-mail"
    2021
    2122
    2223int main(int argc, char* argv[])
    int main(int argc, char* argv[])  
    2829        fprintf(stdout,"This program can only send mail, not read it.\n");
    2930        fprintf(stdout,"usage: %s [-v] [-s subject] [-c cc-addr] "
    3031            "[-b bcc-addr] to-addr ...\n", argv[0]);
    31         fflush(stdout);
    3232        return 0;
    3333    }
    3434
    35     char *subject = "No title";
     35    char *subject = "No subject";
    3636    char *cc = "";
    3737    char *bcc = "";
    38     BString to = "";
    39     BString body = "";
     38    BString to;
     39    bool verbose = false;
    4040
    41     bool verbose =false;
    4241    // Parse arguments
    4342    for (int i = 1; i < argc; i++) {
    4443        if (strcmp(argv[i], "-v") == 0)
    int main(int argc, char* argv[])  
    5352            bcc = argv[i+1];
    5453            i++;
    5554        } else {
     55            if (to.Length() > 0)
     56                to.Append(", ");
    5657            to.Append(argv[i]);
    57             if (i < argc - 1)
    58                 to.Append(" ");
    59         }
     58        }
    6059    }
    6160
    6261    if (verbose) {
    6362        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");
     63        fprintf(stdout, "To:\t%s\n", to.String());
     64        fprintf(stdout, "Cc:\t%s\n", cc);
     65        fprintf(stdout, "Bcc:\t%s\n", bcc);
     66        fprintf(stdout, "Subj:\t%s\n", subject);
     67        fprintf(stdout, "\n");
    7068    }
    7169
    7270    // Check if recipients are valid
    73     if (strcmp(to.String(), "") == 0 &&
    74         strcmp(cc, "") == 0 &&
    75         strcmp(bcc, "") == 0) {
     71    if (strcmp(to.String(), "") == 0 &&
     72        strcmp(cc, "") == 0 &&
     73        strcmp(bcc, "") == 0) {
    7674
    77         fprintf(stdout, "[Error]: You must specify at least one recipient "
     75        fprintf(stderr, "[Error]: You must specify at least one recipient "
    7876            "in to, cc or bcc fields.\n");
    7977        return -1;
    8078    }
    8179
    82     // Read each line until we get a single dot "." on a line
     80    bool isTerminal = isatty(STDIN_FILENO) != 0;
     81    if (isTerminal) {
     82        fprintf(stderr, "Now type your message.\n"
     83            "Type '.' alone on a line to end your text and send it.\n");
     84    }
     85
     86    BString body;
    8387    char line[32768] = "";
    8488
    85     printf("Now type your message.\nType '.' alone on a line to send it.\n");
     89    // Read each line and collect the body text until we get an end of text
     90    // marker.  That's a single dot "." on a line typed in by the user,
     91    // or end of file when reading a file.
    8692    do {
    87         gets(line);
    88 
    89         if (strcmp(line, ".") != 0) {
    90             body.Append(line).Append("\n");
     93        if (fgets(line, sizeof(line), stdin) == NULL) {
     94            // End of file or an error happened, just send collected body text.
     95            break;
    9196        }
    92         // fprintf(stdout,"Line: %s \n",line);
    93     } while (strcmp(line, ".") != 0);
    9497
     98        if (isTerminal && strcmp(line, ".\n") == 0)
     99            break;
     100
     101        body.Append(line);
     102    } while (true);
    95103
    96104    if (verbose)
    97         fprintf(stdout, "\nBody:\n%s\n", body.String());
     105        fprintf(stdout, "\nBody:\n%s\n", body.String());
    98106
    99107    if (verbose)
    100         fprintf(stdout, "\nSending E-mail...\n");
     108        fprintf(stderr, "Sending E-mail...\n");
    101109    fflush(stdout);
    102110
    103111    BMailMessage mail;
    int main(int argc, char* argv[])  
    105113    mail.AddHeaderField(B_MAIL_CC, cc);
    106114    mail.AddHeaderField(B_MAIL_BCC, bcc);
    107115    mail.AddHeaderField(B_MAIL_SUBJECT, subject);
    108     mail.AddContent(body.String(), strlen(body.String()));
     116    mail.AddContent(body.String(), body.Length());
    109117    status_t result = mail.Send();
    110118
    111119    if (result == B_OK) {
    112         fprintf(stdout, "\nMessage was sent successfully.\n");
     120        if (verbose)
     121            fprintf(stderr, "Message was sent successfully.\n");
    113122        return 0;
    114123    }
    115124
    116     fprintf(stdout, "Message failed to send: %s", strerror(result));
     125    fprintf(stderr, "Message failed to send: %s\n", strerror(result));
    117126    return result;
    118127}