home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / hamradio / bm332c.zip / SEND.C < prev    next >
C/C++ Source or Header  |  1993-02-24  |  14KB  |  578 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <time.h>
  4. #include <ctype.h>
  5.  
  6. #include "bm.h"
  7.  
  8. struct addr *addrecip(),*expandalias();
  9. char *ptime();
  10. FILE *tofile;
  11.  
  12. int
  13. ftprintf(fmt,val)
  14. char *fmt,*val;
  15. {
  16.     if(tty)    printf(fmt,val);
  17.     return(fprintf(tofile,fmt,val));
  18. }
  19.  
  20. void
  21. warnump(where)
  22. char *where;
  23. {
  24.     if(tty) printf("WARNING: unmatched parenthesis in %s\n",where);
  25. }
  26.  
  27. /* send a message */
  28. int dosmtpsend(FILE *mfp, char *toargs[], int nargs, char *subject)
  29. {
  30.     char    smtp_subject[LINELEN],
  31.         tstring[LINELEN];
  32.     char    *tmpnam();
  33.     FILE     *fpin;
  34.     char    *p;
  35.     char     *tf = "bmXXXXXX";        /* temp file name */
  36.     int    tlength;
  37.     int    c;
  38.     int    n;
  39.     long    sequence;
  40.     struct    addr *tolist,*tp;
  41.     register FILE    *tfile;
  42.     time_t    t;
  43.  
  44.  
  45.     if (nargs == 0) {
  46.         printf("No recpients\n");
  47.         return 0;
  48.     }
  49.     fpin = mfp;
  50.     if ((tolist = make_tolist(nargs,toargs)) == NULLADDR) {
  51.         printf("Send aborted\n");
  52.         return 0;
  53.     }
  54.  
  55.     sequence = get_msgid();
  56.  
  57.     time(&t);
  58.     mktemp(tf);
  59.         /* open textfile for write */
  60.     if ((tofile = tfile = fopen(tf,"w+")) == NULLFILE) {
  61.         perror(tf);
  62.         del_addrlist(tolist);
  63.         return 1;
  64.     }
  65.  
  66.     if (!qflag) {
  67.         /* write RFC822-compatible headers using above information */
  68.         fprintf(tfile,"Date: %s",ptime(&t));
  69.         fprintf(tfile,"Message-Id: <%ld@%s>\n",sequence,hostname);
  70.         fprintf(tfile,"From: %s@%s",username,hostname);
  71.         if (fullname != NULLCHAR && *fullname != '\0')
  72.             fprintf(tfile," (%s)",fullname);
  73.         fprintf(tfile,"\n");
  74.         if(organization != NULLCHAR)        /* added by SV1XV */
  75.             fprintf(tfile,"Organization: %s\n",organization);
  76.         if (replyto != NULLCHAR && *replyto != '\0')
  77.             fprintf(tfile,"Reply-To: %s\n",replyto);
  78.         ftprintf("To:",NULLCHAR);
  79.         tlength=0;
  80.         for (tp = tolist; tp != NULLADDR; tp = tp->next) {
  81.             strcpy(tstring,tp->user);
  82.             if (tp->host != NULLCHAR && *tp->host != '\0') {
  83.                 strcat(tstring,"@");
  84.                 strcat(tstring,tp->host);
  85.             }
  86.             if (tp->name != NULLCHAR && *tp->name != '\0') {
  87.                 strcat(tstring," (");
  88.                 strcat(tstring,tp->name);
  89.                 strcat(tstring,")");
  90.             }
  91.             if (tp->next != NULLADDR)
  92.                 strcat(tstring,",");
  93.             n = strlen(tstring);
  94.             if(tlength != 0 && tlength+n > 76){
  95.                 ftprintf("\n   ",NULLCHAR);
  96.                 tlength=0;
  97.             }
  98.             tlength+=ftprintf(" %s",tstring);
  99.         }
  100.         ftprintf("\n",NULLCHAR);
  101.  
  102.         *smtp_subject = '\0';
  103.         if (subject == NULLCHAR && tty) {
  104.             /* prompt and get Subject: */
  105.             printf("Subject: ");
  106.             gets(smtp_subject);
  107.         } else {
  108.             strcpy(smtp_subject,subject);
  109.             if(tty) printf("Subject: %s\n",smtp_subject);
  110.         }
  111.         fprintf(tfile,"Subject: %s\n",smtp_subject);
  112.         fprintf(tfile,"\n");       /* add empty line as separator */
  113.     }
  114.  
  115.     if (!tty && fpin == NULLFILE)
  116.         fpin = stdin;
  117.  
  118.     if (fpin != NULLFILE ) {
  119.         while((c = getc(fpin)) != EOF)
  120.             if(putc(c,tfile) == EOF)
  121.                 break;
  122.         if (ferror(tfile)) {
  123.             perror("tmp file");
  124.             (void) fclose(tfile);
  125.             (void) unlink(tf);
  126.             return 1;
  127.         }
  128.     } else {
  129.         /* sending a message not from a file */
  130.         /* copy text from console to the file */
  131.         printf("\nType message text.  Enter a '.' or ctrl/D in column one to end.");
  132.         printf("\nCommands: ~p - redisplay msg, ~e - invoke editor, ~? - help\n\n");
  133.         for(;;) {
  134.             /* read line from console  ie stdin */
  135.             if (gets(tstring) == NULLCHAR)
  136.                 break;
  137.             rip(tstring);
  138.             if(strcmp(tstring,".") == 0 || tstring[0] == '\004')
  139.                 break;
  140.             if (*tstring == '~' ) {
  141.                 switch(tstring[1]) {
  142.                 case 'p':
  143.                     /* Print the message so far */
  144.                     fseek(tfile,0L,0);
  145.                     while (fgets(tstring,sizeof(tstring),tfile) != NULLCHAR)
  146.                         fputs(tstring,stdout);
  147.                     break;
  148.                 case 'e':
  149.                     /* Drop into editor */
  150.                     (void) fclose(tfile);
  151.                     if (editor == NULLCHAR) {
  152.                         printf("No editor defined\n");
  153.                         break;
  154.                     }
  155.                     sprintf(tstring,"%s %s",editor,tf);
  156.                     /* call editor to enter message text */
  157.                     if (system(tstring))
  158.                         printf("unable to invoke editor\n");
  159.                     tfile = fopen(tf,"a+");
  160.                     break;
  161.                 case 'q':
  162.                     (void) fclose(tfile);
  163.                     (void) unlink(tf);
  164.                     printf("Abort\n");
  165.                     return 0;
  166.                 case 'r': 
  167.                     {
  168.                         FILE  *infl;
  169.                         p = &tstring[2];
  170.                         while(*p == ' ' || *p == '\t')
  171.                             p++;
  172.                         if (*p == '\0')
  173.                             printf("No file name specified\n");
  174.                         else
  175.                             if((infl = fopen(p,"r")) == NULLFILE)
  176.                                 printf("No such file\n");
  177.                             else {
  178.                                 printf("Reading file %s\n",p);
  179.                                 while((c = getc(infl)) != EOF)
  180.                                     if(putc(c,tfile) == EOF)
  181.                                         break;
  182.                                 if (ferror(tfile)) {
  183.                                     perror("tmp file");
  184.                                     (void) fclose(tfile);
  185.                                     (void) unlink(tf);
  186.                                     return 1;
  187.                                 }
  188.                                 (void) fclose(infl);
  189.                             }
  190.  
  191.                         break;
  192.                     }
  193.                 case 'm': 
  194.                     {
  195.                         int    msg;
  196.                         p = &tstring[2];
  197.                         while(*p == ' ' || *p == '\t')
  198.                             p++;
  199.                         if (*p == '\0')
  200.                             msg = current;
  201.                         else
  202.                             msg = atoi(p);
  203.                         if (mfile == NULLFILE || msg < 1 || msg > nmsgs)
  204.                             printf("no such message\n");
  205.                         else {
  206.                             printf("Inserting message %d\n",msg);
  207.                             msgtofile(msg,tfile,0);
  208.                         }
  209.                         break;
  210.                     }
  211.                 case '~':
  212.                     fprintf(tfile,"%s\n",&tstring[1]);
  213.                     break;
  214.                 case '?':
  215.                     printf("~e - Invoke Editor\n");
  216.                     printf("~p - Display message buffer\n");
  217.                     printf("~q - Abort this message\n");
  218.                     printf("~r file - Read file into buffer\n");
  219.                     printf("~m msg - message into buffer\n");
  220.                     printf("~~ - Enter a ~ into message\n");
  221.                     break;
  222.                 default:
  223.                     printf("Unknown ~ escape. ~? for help\n");
  224.                 }
  225.                 printf("(continue)\n");
  226.             } else
  227.                 fprintf(tfile,"%s\n",tstring);
  228.         }
  229.         printf("EOF\n");
  230.  
  231.     }
  232.     queuejob(tfile,tolist);
  233.     recordmsg(tfile,tolist->user);     /* save copy for sender */
  234.     (void) fclose(tfile);
  235.     del_addrlist(tolist);
  236.     (void) unlink(tf);
  237.     return 0;
  238. }
  239.  
  240. /* forward a message in its orginal form */
  241. int bouncemsg(FILE *mfp, char *toargs[], int nargs)
  242. {
  243.     struct    addr *list;
  244.     if (nargs == 0) {
  245.         printf("No recpients\n");
  246.     } else if ((list = make_tolist(nargs,toargs)) == NULLADDR) {
  247.         printf("Bad to list\n");
  248.     } else {
  249.         queuejob(mfp,list);
  250.         del_addrlist(list);
  251.     }
  252.     return 0;
  253. }
  254.  
  255. /* Return Date/Time in Arpanet format in passed string */
  256. /* Print out the time and date field as
  257.  *        "DAY, day MONTH year hh:mm:ss ZONE"
  258.  */
  259. char *ptime(long *t)
  260. {
  261.     register struct tm *ltm;
  262.     struct tm *localtime();
  263.     static char tz[4];
  264.     static char str[40];
  265.     extern char *getenv(char *);
  266.     char *p;
  267.     static char *days[7] = {
  268.     "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
  269.  
  270.     static char *months[12] = {
  271.         "Jan","Feb","Mar","Apr","May","Jun",
  272.         "Jul","Aug","Sep","Oct","Nov","Dec" };
  273.  
  274.     /* Read the system time */
  275.     ltm = localtime(t);
  276.  
  277.     if (*tz == '\0')
  278.         if ((p = getenv("TZ")) == NULLCHAR)
  279.             strcpy(tz,"GMT");
  280.         else
  281.             strncpy(tz,p,3);
  282.  
  283.     /* rfc 822 format */
  284.     sprintf(str,"%s, %.2d %s %02d %02d:%02d:%02d %.3s\n",
  285.         days[ltm->tm_wday],
  286.         ltm->tm_mday,
  287.         months[ltm->tm_mon],
  288.         ltm->tm_year,
  289.         ltm->tm_hour,
  290.         ltm->tm_min,
  291.         ltm->tm_sec,
  292.         tz);
  293.     return(str);
  294. }
  295.  
  296. /* save copy in the record file */
  297. int recordmsg(FILE *dfile, char *to) 
  298. {
  299.     register int c;
  300.     FILE     *fp;
  301.     time_t    t;
  302.  
  303.     if (record == NULLCHAR)
  304.         return 1;
  305.     fseek(dfile,0L,0);
  306.     if ((fp = fopen(record,"a")) == NULLFILE) {
  307.         printf("Unable to append to %s\n",record);
  308.     } else {
  309.         (void) time(&t);
  310.         fprintf(fp,"From %s %s",to,ctime(&t));
  311.         while((c = getc(dfile)) != EOF)
  312.             if(putc(c,fp) == EOF)
  313.                 break;
  314.         if (ferror(fp)) {
  315.             (void) fclose(fp);
  316.             return 1;
  317.         }
  318.         (void) fclose(fp);
  319.     }
  320.     return 0;
  321. }
  322.  
  323. /* place a mail job in the outbound queue */
  324. int
  325. queuejob(FILE *dfile, struct addr *tolist)
  326. {
  327.     FILE *fp;
  328.     char tmpstring[50];
  329.     register struct addr *tp,*sp;
  330.     char prefix[9];
  331.     int c;
  332.     long id;
  333.  
  334.     for (tp = tolist; tp != NULLADDR; tp = tp->next) {
  335.         if (tp->sent)
  336.             continue;
  337.         fseek(dfile,0L,0);
  338.         id = get_msgid();
  339.         sprintf(prefix,"%ld",id);
  340.         (void) mlock(mqueue,prefix);
  341.         sprintf(tmpstring,"%s/%s.txt",mqueue,prefix);
  342.         if((fp = fopen(tmpstring,"w")) == NULLFILE) {
  343.             printf("unable to open %s\n",tmpstring);
  344.             (void) rmlock(mqueue,prefix);
  345.             return 1;
  346.         }
  347.         while((c = getc(dfile)) != EOF)
  348.             if(putc(c,fp) == EOF)
  349.                 break;
  350.         if (ferror(fp)) {
  351.             (void) fclose(fp);
  352.             (void) rmlock(mqueue,prefix);
  353.             return 1;
  354.         }
  355.         (void) fclose(fp);
  356.         sprintf(tmpstring,"%s/%s.wrk",mqueue,prefix);
  357.         if((fp = fopen(tmpstring,"w")) == NULLFILE) {
  358.             (void) rmlock(mqueue,prefix);
  359.             return 1;
  360.         }
  361.         fprintf(fp,"%s\n%s@%s\n",tp->host,username,hostname);
  362.         fprintf(fp,"%s@%s\n",tp->user,tp->host);
  363.         tp->sent++;
  364.         /* find and other addresses to the same host */
  365.         for (sp = tp->next; sp != NULLADDR; sp = sp->next) {
  366.             if (sp->sent)
  367.                 continue;
  368.             if (strcmp(tp->host,sp->host) == 0) {
  369.                 fprintf(fp,"%s@%s\n",sp->user,sp->host);
  370.                 sp->sent++;
  371.             }
  372.         }
  373.         (void) fclose(fp);
  374.         (void) rmlock(mqueue,prefix);
  375.     }
  376.     return 0;
  377. }
  378.  
  379. #define SKIPWORD(X) while(*X && *X!=' ' && *X!='\t' && *X!='\n' && *X!= ',') X++;
  380. #define SKIPSPACE(X) while(*X ==' ' || *X =='\t' || *X =='\n' || *X == ',') X++;
  381.  
  382. static char *
  383. getname(char **pp)
  384. {    /* extract user's full name from alias line */
  385.     char *n,*p;
  386.     if (*(n = *pp) != '(') return(NULLCHAR);
  387.     if ((p=strchr(n,')')) == NULLCHAR){
  388.         warnump("alias file");
  389.         p=n+strlen(n);
  390.     } else    *p++ = '\0';
  391.     SKIPSPACE(p);
  392.     *pp=p;
  393.     return(n+1);
  394. }
  395.  
  396. /* check for and alias and expand alais into a address list */
  397. struct addr *
  398. expandalias(struct addr **head, char *user)
  399. {
  400.     FILE *fp;
  401.     register char *s,*p,*h,*n;
  402.     int inalias;
  403.     struct addr *tp;
  404.     char buf[LINELEN],*m;
  405.  
  406.     if(aliases != NULLCHAR)            /* 1992 Dec 25  SV1XV  */
  407.         fp = fopen(aliases, "r");
  408.     else
  409.         fp = fopen(alias, "r");
  410.     printf("alias=\"%s\", aliases=\"%s\"\n",alias,aliases);
  411.         /* no alias file found */
  412.     if (fp == NULLFILE)
  413.         return addrecip(head, user, hostname, NULLCHAR);
  414.  
  415.     inalias = 0;
  416.     while (fgets(buf,LINELEN,fp) != NULLCHAR) {
  417.         p = buf;
  418.         if ( *p == '#' || *p == '\0')
  419.             continue;
  420.         rip(p);
  421.  
  422.         /* if not in an matching entry skip continuation lines */
  423.         if (!inalias && isspace(*p))
  424.             continue;
  425.  
  426.         /* when processing an active alias check for a continuation */
  427.         if (inalias) {
  428.             if (!isspace(*p)) 
  429.                 break;    /* done */
  430.         } else {
  431.             s = p;
  432.             SKIPWORD(p);
  433.             *p++ = '\0';    /* end the alias name */
  434.             if (strcmp(s,user) != 0)
  435.                 continue;    /* no match go on */
  436.             inalias = 1;
  437.             printf("ALIAS: %s = %s\n",s,p);
  438.         }
  439.  
  440.         /* process the recipients on the alias line */
  441.         SKIPSPACE(p);
  442.         while(*p != '\0' && *p != '#') {
  443.             n = NULLCHAR;
  444.             m = p;
  445.             while (*p == '(') {
  446.                 n = getname(&m);
  447.                 p = m;
  448.             }
  449.             s = p;
  450.             SKIPWORD(p);
  451.             if (*p != '\0')
  452.                 *p++ = '\0';
  453.             /* find hostname */
  454.             if ((h = strchr(s,'@')) != NULLCHAR)
  455.                 *h++ = '\0';
  456.             else
  457.                 h = hostname;
  458.             SKIPSPACE(p);
  459.             if (n == NULLCHAR && *p == '(') {
  460.                 m = p;
  461.                   n = getname(&m);
  462.                 p = m;
  463.             }
  464.             tp = addrecip(head,s,h,n);
  465.         }
  466.     }
  467.     (void) fclose(fp);
  468.  
  469.     if (inalias)    /* found and processed and alias. */
  470.         return tp;
  471.  
  472.     /* no alias found treat as a local address */
  473.     return addrecip(head, user, hostname, NULLCHAR);
  474. }
  475.  
  476. /* convert a arg list to an list of address structures */
  477. struct addr *
  478. make_tolist(int argc, char *argv[])
  479. {
  480.     struct addr *tolist, *tp, *ptl=NULLADDR;
  481.     char *user, *host, name[LINELEN];
  482.     int i,inpar=0;
  483.     tolist = NULLADDR;
  484.     for (i = 0; i < argc; i++) {
  485.         user = argv[i];
  486.         if (!inpar)
  487.             if (*user == '(') {
  488.                 inpar=2;
  489.                 *name = '\0';
  490.                 user++;
  491.             } else {
  492.                 ptl = tolist;
  493.                 if ((host = strchr(user ,'@')) == NULLCHAR)
  494.                     /* a local address - may be alias */
  495.                     tp = expandalias(&tolist,user);
  496.                 else {    /* a remote address */
  497.                     *host++ = '\0';
  498.                     /* if it matches our host name */
  499.                     if (stricmp(host,hostname) == 0)
  500.                         host = NULLCHAR;
  501.                     tp = addrecip(&tolist, user, host,
  502.                             NULLCHAR);
  503.                 }
  504.                 if (tp == NULLADDR)    goto memfail;
  505.             }
  506.         if (inpar) {
  507.             host = user+strlen(user)-1;
  508.             if (inpar==1) strcat(name," ");
  509.             if ((inpar = *host != ')') == 0)
  510.                 *host = '\0';
  511.             strcat(name,user);
  512.             if (!inpar)
  513.                 for (tp=tolist; tp!=ptl; tp=tp->next) {
  514.                     if (tp->name != NULLCHAR)
  515.                         free(tp->name);
  516.                     if ((tp->name = strdup(name))
  517.                         == NULLCHAR)    goto memfail;
  518.                     }
  519.         }
  520.     }
  521.     if (inpar)    warnump("args");
  522.     return tolist;
  523. memfail:
  524.     printf("Out of memory\n");
  525.     del_addrlist(tolist);
  526.     return NULLADDR;
  527. }
  528.  
  529. /* delete a list of mail addresses */
  530. del_addrlist(list)
  531. struct addr *list;
  532. {
  533.     struct addr *tp, *tp1;;
  534.     for (tp = list; tp != NULLADDR; tp = tp1) {
  535.         tp1 = tp->next;
  536.         if (tp->user != NULLCHAR);
  537.             free(tp->user);
  538.         if (tp->host != NULLCHAR);
  539.             free(tp->host);
  540.         if (tp->name != NULLCHAR);
  541.             free(tp->name);
  542.         free((char *)tp);
  543.     }
  544. }
  545.  
  546. /* add an address to the from of the list pointed to by head 
  547. ** return NULLADDR if out of memory.
  548. */
  549. struct addr *
  550. addrecip(head,user,host,name)
  551. struct addr **head;
  552. char *user, *host, *name;
  553. {
  554.     register struct addr *tp;
  555.  
  556.     tp = (struct addr *)calloc(1,sizeof(struct addr));
  557.     if (tp != NULLADDR){
  558.         /* copy user's login name */
  559.         if ((tp->user = strdup(user)) != NULLCHAR) {
  560.             /* copy host name */
  561.             if (host != NULLCHAR)
  562.                 if ((tp->host = strdup(host)) == NULLCHAR)
  563.                     goto memfail;
  564.             /* copy user full name */
  565.             if (name != NULLCHAR)
  566.                 if ((tp->name = strdup(name)) == NULLCHAR)
  567.                     goto memfail;
  568.             /* add entry to front of existing list */
  569.             tp->next = *head;
  570.             return(*head = tp);
  571. memfail:        if(tp->host != NULLCHAR) free(tp->host);
  572.             free(tp->user);
  573.         }
  574.         free((char *)tp);
  575.     }
  576.     return NULLADDR;
  577. }
  578.