/[mailutils]/mailutils/mail/send.c
ViewVC logotype

Diff of /mailutils/mail/send.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.28 by gray, Wed Oct 2 14:39:29 2002 UTC revision 1.29 by gray, Thu Oct 3 14:31:32 2002 UTC
# Line 15  Line 15 
15     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
17    
   
 /* FIXME: Those headers should be in "mail.h".  */  
18  #include <sys/types.h>  #include <sys/types.h>
19  #include <sys/stat.h>  #include <sys/stat.h>
20  #include <fcntl.h>  #include <fcntl.h>
# Line 30  static void msg_to_pipe __P ((const char Line 28  static void msg_to_pipe __P ((const char
28  /*  /*
29   * m[ail] address...   * m[ail] address...
30   if address is starting with   if address is starting with
31   '/' it is consider a file and the message is save to a file.  
32   '.' by extension dot is consider relative path.      '/'        it is considered a file and the message is saveed to a file;
33   '|' a pipe the message is writent to the pipe.      '.'        it is considered to be a relative path;
34        '|'        it is considered to be a pipe, and the message is written to
35                   there;
36                  
37   example:   example:
38   mail joe '| cat >/tmp/save'  
39   mail will be send to joe and the message save in /tmp/save.     mail joe '| cat >/tmp/save'
40   */  
41     mail will be sent to joe and the message saved in /tmp/save. */
42    
43  int  int
44  mail_send (int argc, char **argv)  mail_send (int argc, char **argv)
45  {  {
46    compose_env_t env;    compose_env_t env;
47    int status;    int status;
48      int save_to = isupper (argv[0][0]);
49    compose_init (&env);    compose_init (&env);
50    
51    if (argc < 2)    if (argc < 2)
52      compose_header_set (&env, MU_HEADER_TO, ml_readline ((char *)"To: "),      compose_header_set (&env, MU_HEADER_TO, ml_readline ("To: "),
53                          COMPOSE_REPLACE);                          COMPOSE_REPLACE);
54    else    else
55      {      {
56        while (--argc)        while (--argc)
57          {          {
58            char *p = alias_expand (*++argv);            char *p = *++argv;
59            if (isfilename(p))            if (isfilename (p))
60              {              {
61                env.outfiles = realloc (env.outfiles,                env.outfiles = realloc (env.outfiles,
62                                        (env.nfiles+1)*sizeof (*(env.outfiles)));                                        (env.nfiles + 1) *
63                                          sizeof (*(env.outfiles)));
64                if (env.outfiles)                if (env.outfiles)
65                  {                  {
66                    env.outfiles[env.nfiles] = p;                    env.outfiles[env.nfiles] = p;
# Line 66  mail_send (int argc, char **argv) Line 69  mail_send (int argc, char **argv)
69              }              }
70            else            else
71              {              {
72                compose_header_set (&env, MU_HEADER_TO, p,                compose_header_set (&env, MU_HEADER_TO, p, COMPOSE_SINGLE_LINE);
                                   COMPOSE_SINGLE_LINE);  
73                free (p);                free (p);
74              }              }
75          }          }
# Line 75  mail_send (int argc, char **argv) Line 77  mail_send (int argc, char **argv)
77    
78    if (util_getenv (NULL, "askcc", Mail_env_boolean, 0) == 0)    if (util_getenv (NULL, "askcc", Mail_env_boolean, 0) == 0)
79      compose_header_set (&env, MU_HEADER_CC,      compose_header_set (&env, MU_HEADER_CC,
80                          ml_readline ((char *)"Cc: "),                          ml_readline ("Cc: "), COMPOSE_REPLACE);
                         COMPOSE_REPLACE);  
81    if (util_getenv (NULL, "askbcc", Mail_env_boolean, 0) == 0)    if (util_getenv (NULL, "askbcc", Mail_env_boolean, 0) == 0)
82      compose_header_set (&env, MU_HEADER_BCC,      compose_header_set (&env, MU_HEADER_BCC,
83                          ml_readline ((char *)"Bcc: "),                          ml_readline ("Bcc: "), COMPOSE_REPLACE);
                         COMPOSE_REPLACE);  
84    
85    if (util_getenv (NULL, "asksub", Mail_env_boolean, 0) == 0)    if (util_getenv (NULL, "asksub", Mail_env_boolean, 0) == 0)
86      compose_header_set (&env, MU_HEADER_SUBJECT,      compose_header_set (&env, MU_HEADER_SUBJECT,
87                          ml_readline ((char *)"Subject: "),                          ml_readline ("Subject: "), COMPOSE_REPLACE);
                         COMPOSE_REPLACE);  
88    else    else
89      {      {
90        char *p;        char *p;
91        if (util_getenv (&p, "subject", Mail_env_string, 0) == 0)        if (util_getenv (&p, "subject", Mail_env_string, 0) == 0)
92          compose_header_set (&env, MU_HEADER_SUBJECT,          compose_header_set (&env, MU_HEADER_SUBJECT, p, COMPOSE_REPLACE);
                             p,  
                             COMPOSE_REPLACE);  
93      }      }
94    
95    status = mail_send0 (&env, isupper(argv[0][0]));    status = mail_send0 (&env, save_to);
96    compose_destroy (&env);    compose_destroy (&env);
97    return status;    return status;
98  }  }
99    
100  void  void
101  compose_init (compose_env_t *env)  compose_init (compose_env_t * env)
102  {  {
103    memset (env, 0, sizeof (*env));    memset (env, 0, sizeof (*env));
104  }  }
105    
106  int  int
107  compose_header_set (compose_env_t *env, char *name, char *value,  compose_header_set (compose_env_t * env, char *name, char *value, int mode)
                     int mode)  
108  {  {
109    int status;    int status;
110    char *old_value;    char *old_value;
# Line 122  compose_header_set (compose_env_t *env, Line 118  compose_header_set (compose_env_t *env,
118    
119    switch (mode)    switch (mode)
120      {      {
121      case COMPOSE_REPLACE:          case COMPOSE_REPLACE:
122      case COMPOSE_APPEND:      case COMPOSE_APPEND:
123        status = header_set_value (env->header, name, value, mode);        status = header_set_value (env->header, name, value, mode);
124        break;        break;
125          
126      case COMPOSE_SINGLE_LINE:      case COMPOSE_SINGLE_LINE:
127        if (!value || value[0] == 0)        if (!value || value[0] == 0)
128          return EINVAL;          return EINVAL;
129          
130        if (header_aget_value (env->header, name, &old_value) == 0        if (header_aget_value (env->header, name, &old_value) == 0
131            && old_value[0])            && old_value[0])
132          {          {
# Line 147  compose_header_set (compose_env_t *env, Line 143  compose_header_set (compose_env_t *env,
143  }  }
144    
145  char *  char *
146  compose_header_get (compose_env_t *env, char *name, char *defval)  compose_header_get (compose_env_t * env, char *name, char *defval)
147  {  {
148    char *p;    char *p;
149      
150    if (header_aget_value (env->header, name, &p))    if (header_aget_value (env->header, name, &p))
151      p = defval;      p = defval;
152    return p;    return p;
153  }        }
154    
155  void  void
156  compose_destroy (compose_env_t *env)  compose_destroy (compose_env_t * env)
157  {  {
158    header_destroy (&env->header, NULL);    header_destroy (&env->header, NULL);
159    if (env->outfiles)    if (env->outfiles)
# Line 182  compose_destroy (compose_env_t *env) Line 178  compose_destroy (compose_env_t *env)
178     mail. You must manually set the default for this environment variable     mail. You must manually set the default for this environment variable
179     by editing ROOTDIR/etc/mailx.rc to specify the mail agent of your     by editing ROOTDIR/etc/mailx.rc to specify the mail agent of your
180     choice. The default is sendmail, but it can be any command that takes     choice. The default is sendmail, but it can be any command that takes
181     addresses on the command line and message contents on standard input.     addresses on the command line and message contents on standard input. */
 */  
182    
183  int  int
184  mail_send0 (compose_env_t *env, int save_to)  mail_send0 (compose_env_t * env, int save_to)
185  {  {
186    int done = 0;    int done = 0;
187    int fd;    int fd;
# Line 215  mail_send0 (compose_env_t *env, int save Line 210  mail_send0 (compose_env_t *env, int save
210    while (!done)    while (!done)
211      {      {
212        char *buf;        char *buf;
213        buf = ml_readline ((char *)" \b");        buf = ml_readline (" \b");
214    
215        if (ml_got_interrupt ())        if (ml_got_interrupt ())
216          {          {
# Line 253  mail_send0 (compose_env_t *env, int save Line 248  mail_send0 (compose_env_t *env, int save
248            && util_getenv (NULL, "dot", Mail_env_boolean, 0) == 0)            && util_getenv (NULL, "dot", Mail_env_boolean, 0) == 0)
249          done = 1;          done = 1;
250        else if (util_getenv (&escape, "escape", Mail_env_string, 0) == 0        else if (util_getenv (&escape, "escape", Mail_env_string, 0) == 0
251                 && buf[0] == escape[0])                 && buf[0] == escape[0])
252          {          {
253            if (buf[1] == buf[0])            if (buf[1] == buf[0])
254              fprintf (env->file, "%s\n", buf+1);              fprintf (env->file, "%s\n", buf + 1);
255            else if (buf[1] == '.')            else if (buf[1] == '.')
256              done = 1;              done = 1;
257            else if (buf[1] == 'x')            else if (buf[1] == 'x')
# Line 272  mail_send0 (compose_env_t *env, int save Line 267  mail_send0 (compose_env_t *env, int save
267    
268                ofile = env->file;                ofile = env->file;
269    
270                if (argcv_get (buf+1, "", NULL, &argc, &argv) == 0)                if (argcv_get (buf + 1, "", NULL, &argc, &argv) == 0)
271                  {                  {
272                    struct mail_command_entry entry;                    struct mail_command_entry entry;
273                    entry = util_find_entry (mail_escape_table, argv[0]);                    entry = util_find_entry (mail_escape_table, argv[0]);
274    
275                    if (entry.escfunc)                    if (entry.escfunc)
276                      status = (*entry.escfunc)(argc, argv, env);                      status = (*entry.escfunc) (argc, argv, env);
277                    else                    else
278                      util_error ("Unknown escape %s", argv[0]);                      util_error ("Unknown escape %s", argv[0]);
279                  }                  }
# Line 288  mail_send0 (compose_env_t *env, int save Line 283  mail_send0 (compose_env_t *env, int save
283                  }                  }
284                argcv_free (argc, argv);                argcv_free (argc, argv);
285    
286                ofile =  env->ofile;                ofile = env->ofile;
287              }              }
288          }          }
289        else        else
# Line 304  mail_send0 (compose_env_t *env, int save Line 299  mail_send0 (compose_env_t *env, int save
299          {          {
300            FILE *fp = fopen (getenv ("DEAD"),            FILE *fp = fopen (getenv ("DEAD"),
301                              util_getenv (NULL, "appenddeadletter",                              util_getenv (NULL, "appenddeadletter",
302                                           Mail_env_boolean, 0) == 0 ?                                           Mail_env_boolean, 0) == 0 ?
303                              "a" : "w");                              "a" : "w");
304    
305            if (!fp)            if (!fp)
306              {              {
307                util_error ("can't open file %s: %s", getenv ("DEAD"),                util_error ("can't open file %s: %s", getenv ("DEAD"),
308                           strerror (errno));                            strerror (errno));
309              }              }
310            else            else
311              {              {
# Line 330  mail_send0 (compose_env_t *env, int save Line 325  mail_send0 (compose_env_t *env, int save
325        return 1;        return 1;
326      }      }
327    
328    fclose (env->file); /* FIXME: freopen would be better */    fclose (env->file);           /* FIXME: freopen would be better */
329    
330    file = fopen (filename, "r");    /* Prepare the header */
331    if (file != NULL)    header_set_value (env->header, "X-Mailer", argp_program_version, 1);
332    
333      if (util_header_expand (&env->header) == 0)
334      {      {
335        mailer_t mailer;        file = fopen (filename, "r");
336        message_t msg = NULL;        if (file != NULL)
337            {
338              mailer_t mailer;
339              message_t msg = NULL;
340    
341              message_create (&msg, NULL);
342    
343        message_create (&msg, NULL);            message_set_header (msg, env->header, NULL);
344    
345        /* Fill the header */            /* Fill the body.  */
       header_set_value (env->header, "X-Mailer", argp_program_version, 1);  
       message_set_header (msg, env->header, NULL);  
   
       /* Fill the body.  */  
       {  
         body_t body = NULL;  
         stream_t stream = NULL;  
         off_t offset = 0;  
         char *buf = NULL;  
         size_t n = 0;  
         message_get_body (msg, &body);  
         body_get_stream (body, &stream);  
         while (getline (&buf, &n, file) >= 0)  
346            {            {
347              size_t len = strlen (buf);              body_t body = NULL;
348              stream_write (stream, buf, len, offset, &n);              stream_t stream = NULL;
349              offset += len;              off_t offset = 0;
350                char *buf = NULL;
351                size_t n = 0;
352                message_get_body (msg, &body);
353                body_get_stream (body, &stream);
354                while (getline (&buf, &n, file) >= 0)
355                  {
356                    size_t len = strlen (buf);
357                    stream_write (stream, buf, len, offset, &n);
358                    offset += len;
359                  }
360                
361                if (offset == 0)
362                  util_error ("Null message body; hope that's ok\n");
363                if (buf)
364                  free (buf);
365            }            }
366    
367          if (offset == 0)            fclose (file);
           util_error("Null message body; hope that's ok\n");  
         if (buf)  
           free (buf);  
       }  
   
       fclose (file);  
368    
369        /* Save outgoing message */            /* Save outgoing message */
370        if (save_to)            if (save_to)
         {  
           savefile = compose_header_get (env, MU_HEADER_TO, NULL);  
           if (savefile)  
371              {              {
372                char *p = strchr (savefile, '@');                char *tmp = compose_header_get (env, MU_HEADER_TO, NULL);
373                if (p)                address_t addr = NULL;
374                  *p = 0;                
375                  address_create (&addr, tmp);
376                  address_aget_email (addr, 1, &savefile);
377                  address_destroy (&addr);
378                  if (savefile)
379                    {
380                      char *p = strchr (savefile, '@');
381                      if (p)
382                        *p = 0;
383                    }
384              }              }
385          }            util_save_outgoing (msg, savefile);
386        util_save_outgoing (msg, savefile);            if (savefile)
387        if (savefile)              free (savefile);
         free (savefile);  
388    
389        /* Check if we need to save the message to files or pipes.  */            /* Check if we need to save the message to files or pipes.  */
390        if (env->outfiles)            if (env->outfiles)
         {  
           int i;  
           for (i = 0; i < env->nfiles; i++)  
391              {              {
392                /* Pipe to a cmd.  */                int i;
393                if (env->outfiles[i][0] == '|')                for (i = 0; i < env->nfiles; i++)
                 msg_to_pipe (&(env->outfiles[i][1]), msg);  
               /* Save to a file.  */  
               else  
394                  {                  {
395                    int status;                    /* Pipe to a cmd.  */
396                    mailbox_t mbx = NULL;                    if (env->outfiles[i][0] == '|')
397                    status = mailbox_create_default (&mbx, env->outfiles[i]);                      msg_to_pipe (&(env->outfiles[i][1]), msg);
398                    if (status == 0)                    /* Save to a file.  */
399                      else
400                      {                      {
401                        status = mailbox_open (mbx, MU_STREAM_WRITE                        int status;
402                                               | MU_STREAM_CREAT);                        mailbox_t mbx = NULL;
403                          status = mailbox_create_default (&mbx, env->outfiles[i]);
404                        if (status == 0)                        if (status == 0)
405                          {                          {
406                            mailbox_append_message (mbx, msg);                            status = mailbox_open (mbx, MU_STREAM_WRITE
407                            mailbox_close (mbx);                                                   | MU_STREAM_CREAT);
408                              if (status == 0)
409                                {
410                                  mailbox_append_message (mbx, msg);
411                                  mailbox_close (mbx);
412                                }
413                              mailbox_destroy (&mbx);
414                          }                          }
415                        mailbox_destroy (&mbx);                        if (status)
416                            util_error ("can't create mailbox %s", env->outfiles[i]);
417                      }                      }
                   if (status)  
                     util_error("can't create mailbox %s", env->outfiles[i]);  
418                  }                  }
419              }              }
         }  
420    
421        /* Do we need to Send the message on the wire?  */            /* Do we need to Send the message on the wire?  */
422        if (compose_header_get (env, "to", NULL)            if (compose_header_get (env, MU_HEADER_TO, NULL)
423            || compose_header_get (env, "cc", NULL)                || compose_header_get (env, MU_HEADER_CC, NULL)
424            || compose_header_get (env, "bcc", NULL))                || compose_header_get (env, MU_HEADER_BCC, NULL))
         {  
           char *sendmail;  
           if (util_getenv (&sendmail, "sendmail", Mail_env_string, 0) == 0)  
425              {              {
426                int status = mailer_create (&mailer, sendmail);                char *sendmail;
427                if (status == 0)                if (util_getenv (&sendmail, "sendmail", Mail_env_string, 0) == 0)
428                  {                  {
429                    if (util_getenv (NULL, "verbose", Mail_env_boolean, 0) == 0)                    int status = mailer_create (&mailer, sendmail);
                     {  
                       mu_debug_t debug = NULL;  
                       mailer_get_debug (mailer, &debug);  
                       mu_debug_set_level (debug, MU_DEBUG_TRACE|MU_DEBUG_PROT);  
                     }  
                   status = mailer_open (mailer, MU_STREAM_RDWR);  
430                    if (status == 0)                    if (status == 0)
431                      {                      {
432                        mailer_send_message (mailer, msg, NULL, NULL);                        if (util_getenv (NULL, "verbose", Mail_env_boolean, 0)
433                        mailer_close (mailer);                            == 0)
434                            {
435                              mu_debug_t debug = NULL;
436                              mailer_get_debug (mailer, &debug);
437                              mu_debug_set_level (debug,
438                                                  MU_DEBUG_TRACE | MU_DEBUG_PROT);
439                            }
440                          status = mailer_open (mailer, MU_STREAM_RDWR);
441                          if (status == 0)
442                            {
443                              mailer_send_message (mailer, msg, NULL, NULL);
444                              mailer_close (mailer);
445                            }
446                          mailer_destroy (&mailer);
447                      }                      }
448                    mailer_destroy (&mailer);                    if (status != 0)
449                        msg_to_pipe (sendmail, msg);
450                  }                  }
451                if (status != 0)                else
452                  msg_to_pipe (sendmail, msg);                  util_error ("variable sendmail not set: no mailer");
453              }              }
454            else            message_destroy (&msg, NULL);
455              util_error ("variable sendmail not set: no mailer");            remove (filename);
456              free (filename);
457              return 0;
458          }          }
       message_destroy (&msg, NULL);  
       remove (filename);  
       free (filename);  
       return 0;  
459      }      }
460    
461    remove (filename);    remove (filename);
# Line 469  isfilename (const char *p) Line 475  isfilename (const char *p)
475  }  }
476    
477  /* FIXME: Should probably be in util.c.  */  /* FIXME: Should probably be in util.c.  */
478  /* Call pope(cmd) and write the message to it.  */  /* Call popen(cmd) and write the message to it.  */
479  static void  static void
480  msg_to_pipe (const char *cmd, message_t msg)  msg_to_pipe (const char *cmd, message_t msg)
481  {  {

Legend:
Removed from v.1.28  
changed lines
  Added in v.1.29

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26