home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / philmail.lzh / basicmail.c next >
Text File  |  1992-06-27  |  12KB  |  493 lines

  1. /* UGG!!
  2.  * Okay, I FINALLY split up the durn philmail package.
  3.  * SHEESH, it was getting large...
  4.  * This file has the "simple" utility routines....
  5.  */
  6.  
  7.  
  8. #include <stdio.h>
  9. #include <ctype.h>
  10. #include <time.h>
  11. #include <strings.h>
  12.  
  13.  
  14. typedef struct article ARTICLE;
  15.  
  16. struct article {
  17.     long position;
  18.     char From[512];
  19.     char Subject[512];
  20.     char Cc[1024];
  21. };
  22.  
  23. #define MAXARTICLES    50
  24. #define TRUE        1
  25. #define FALSE        0
  26.  
  27. extern FILE *fp;
  28. extern ARTICLE *articles[MAXARTICLES];
  29. extern char buf[1024];
  30. extern int numofarticles,currentarticle,lastread;
  31. extern char *includestring;
  32. extern char *progname;
  33. extern ARTICLE *newarticle();
  34.  
  35.  
  36. usage()
  37. {
  38.     fprintf(stderr,"  [ philmail v1.01]\n");
  39.     fprintf(stderr,"%s is an off-line mail reader for UNIX mail\n",progname);
  40.     fprintf(stderr,"The idea being, you grab your /usr/spool/mail file to your home machine\n");
  41.     fprintf(stderr,"   and invoke this program on it\n\n");
  42.     fprintf(stderr,"It will read your mail for you, and ask whether to reply or not.\n");
  43.     fprintf(stderr,"  NOTE: to reply, your EDITOR env. variable Must be defined appropriately\n");
  44.     fprintf(stderr,"It SHOULD offer inclusion of original message, \n");
  45.     fprintf(stderr,"   and reply to original sender, or ALL recipients \n");
  46.     fprintf(stderr,"It is meant to be used in conjunction with a shell-script that\n");
  47.     fprintf(stderr,"   takes first and second lines of a file as recipient and subject,\n");
  48.     fprintf(stderr,"   and then mails the file. [on the UNIX end]\n");
  49.     fprintf(stderr,"WARINING: this version can only handle %d messages\n",MAXARTICLES);
  50.  
  51.     fprintf(stderr,"\nThis will check the $MAIL file if non is specified.\n");
  52.     fprintf(stderr,"   It will also allow you to make a mailfile to send  \n");
  53.     fprintf(stderr,"  ie: \"philmail machine\!blah\!person \"  \n");
  54.     fprintf(stderr,"FURTHER NOTE:  the ~ escape is recognised (while composing without editor),\n");
  55.     fprintf(stderr,"   but doesn't do much currently\n");
  56. }
  57. format(){
  58.     fprintf(stderr,"Oops.. format for mail files should be:\n");
  59.     fprintf(stderr,"All articles start with:\n");
  60.     fprintf(stderr,"   'From<space>Address_goes_here'\n");
  61.     fprintf(stderr,"as first line,\n");
  62.     fprintf(stderr,"with optional\n");
  63.     fprintf(stderr,"   'Subject: <blah blah>' \n\n");
  64. }
  65. /* readmsg:
  66.     Prints out message on given file pointer thing.
  67.     Has special handling for stdout. (and NON-stdout )
  68.     sets "lastread", appropriately enough.
  69. */
  70.  
  71. void readmsg(out)
  72. FILE *out;
  73. {
  74.     char *checkforeof;
  75.     long endofarticle;
  76.     if(currentarticle >= numofarticles){
  77.         fprintf(stdout,"No more messages\n");
  78.         return;
  79.     }
  80.     if(currentarticle == numofarticles - 1)
  81.         endofarticle = 0x7fffffff;
  82.     else
  83.         endofarticle = articles[currentarticle+1]->position;
  84.  
  85.     /* find beginning of message */
  86.     fseek(fp,articles[currentarticle]->position,0);
  87.     fgets(buf,1023,fp); 
  88.  
  89.     /* now file pointer is automatically positioned around the
  90.      * proper place!!
  91.      * So print out pre-read header, then message body
  92.      */
  93.  
  94.     if(out == stdout){
  95.         fprintf(out,"From %s\n",articles[currentarticle]->From);
  96.         fprintf(out,"Subject: %s",articles[currentarticle]->Subject);
  97.         fprintf(out,"      ---------------------------------------   \n");
  98.     } else {
  99.         fprintf(out,"%s[From %s]\n",includestring,articles[currentarticle]->From);
  100.     }
  101.  
  102.     /* skip over ALL headers now... */
  103.     while(buf[0] != 13){
  104.         if(fgets(buf,1023,fp)== NULL) {
  105.             puts("\n\n[empty message?]\n\n");
  106.             return;
  107.         }
  108.     }
  109.     /* have read blank line marker. now read until beginning of
  110.      * next message
  111.      */
  112.     do{
  113.         checkforeof = fgets(buf,1023,fp);
  114.         if(out == stdout)
  115.             fprintf(out,"%s",buf);
  116.         else    /* want to make quoted article stand out!! */
  117.             fprintf(out,"%s%s",includestring,buf);
  118.  
  119.     } while((ftell(fp) <endofarticle ) && (checkforeof != NULL));
  120.  
  121.     if(out == stdout){
  122.         printf("\n[end of message %d]\n",currentarticle);
  123.         lastread = currentarticle;
  124.         currentarticle++;
  125.     }
  126. }
  127. /*  writemessage():
  128.     Pass writemessage a file pointer to a file,
  129.     With the headers already set up. 
  130.     It will let the user write a message.
  131.  
  132.      ***writemessage will then close the file pointer ***
  133.     FURTHER HACK:
  134.       I am attempting to support philmail as a replacement mailer
  135.       for standard "mail". TO this end, after we close the file,
  136.       IF it is appropriate, we attempt to actually send the
  137.       mail, and delete the file.
  138. */
  139. extern char *sendmail;
  140. void writemessage(filep,filename)
  141. FILE *filep;
  142. char *filename;
  143. {    
  144.     char *editor;
  145.     char forkstring[1024];
  146.  
  147.     editor = (char *) getenv("EDITOR");
  148.     if( editor != NULL){
  149.         fclose(filep);
  150.         /* Fork off EDITOR now !! */
  151.         sprintf(forkstring,"%s %s",editor,filename);
  152.         if(system(forkstring) != 0){
  153.             fflush(stdout);
  154.             fprintf(stderr,"Error forking editor\n");
  155.             fprintf(stderr,"continue with line-by-line?\n");
  156.             fgets(buf,1023,stdin);
  157.             if((buf[0] == 'y') || (buf[0] == 'Y')){
  158.                 editor = NULL;
  159.                 if((filep = fopen(filename,"a+")) == NULL){
  160.                     fprintf(stderr,"Sorry.. cannot reopen file\n");
  161.                     return;
  162.                 }
  163.             } else {
  164.                 fprintf(stderr,"Please delete file %s\n",filename);
  165.                 return;
  166.             }
  167.             /* line-mode will then fall through to below */
  168.         }
  169.     }
  170.  
  171.     /* MUST KEEP THIS TEST, so that if editor fork fails, we can 
  172.      * fall through to line-mode
  173.      */
  174.     if(editor == NULL){
  175.         puts("Input body of message now.");
  176.         puts("\".\" at beginning of line, or EOF, to end");
  177.         while(fgets(buf,1023,stdin) != NULL){
  178.             if(buf[0] == '.')
  179.                 break;
  180.             /* handle UNIX type escapes.... */
  181.             /* Except that I only care about ~e, and
  182.              * we do that by default!!!
  183.              */
  184.             if(buf[0] == '~'){
  185.                 switch(buf[1]){
  186.                     case 'e':
  187.                         fclose(filep);
  188.                         sprintf(forkstring,"%s %s",&buf[2],filename);
  189.                         if(system(forkstring) != 0){
  190.                             fprintf(stderr,"Error attempting to fork editor\n");
  191.                         }
  192.                         /* try append, THEN create */
  193.                         filep=fopen(filename,"a+");
  194.                         if (filep == NULL){
  195.                             fprintf(stderr,"Error: cannot reopen file\n");
  196.                             return;
  197.                         }
  198.                     case '?':
  199.                       puts("possible \"~\" escapes:");
  200.                       puts("~e <editorname> to edit message");
  201.                       puts("~?: help");
  202.                       puts(" Sorry.. that's all we do for now! ");
  203.                     break;
  204.                     default:
  205.                       fputs(buf,filep);
  206.                 }
  207.             } else 
  208.                 fputs(buf,filep);
  209.         }
  210.         fclose(filep);
  211.     } 
  212.     /* and now try to SEND FILE?!!! */
  213.     if(sendmail != NULL){
  214.         char tempbuf[512];
  215.         filep= fopen(filename,"r");
  216.         if(filep == NULL){
  217.             fprintf(stderr,"error sending mail: could not open file %s\n",filename);
  218.             return;
  219.         }
  220.         fgets(buf,1023,filep);
  221.         fclose(filep);
  222.         /* the "To:" thing should be nicely set up as FIRST line*/
  223.         sprintf(tempbuf,"%s %s <%s",sendmail,&buf[3],filename);
  224.         /* this line forks off "sendmail" or something */
  225.         system(tempbuf);
  226.     
  227.         /*and now delete mail file!*/
  228.         sprintf(tempbuf,"del %s",filename);
  229.         system(tempbuf);
  230.     }
  231.     return;
  232. }
  233.  
  234. /* reply:
  235.     sets up editor, etc for replying.
  236.     includes Cc: line IFF all is true
  237. */
  238. void reply(all)
  239. int all;
  240. {
  241.     char filename[100];
  242.     char *parse;
  243.     long timeval;
  244.     FILE *replyfile;
  245.     
  246.     /* _getsys() is an OS9 specific. basically, gets the number of ticks
  247.      * since system started. Just to "ensure" unique files.
  248.      * the UNIX equivalent would be _secsince70() or something
  249.      */
  250.     timeval = _getsys(D_Ticks,4);
  251.  
  252.     sprintf(filename,"mail.%d",timeval);
  253.     if((replyfile=fopen(filename,"w")) == NULL){
  254.         fprintf(stderr,"Error: could not open file to send mail\n");
  255.         return;
  256.     }
  257.     printf("Successfully opened \"%s\" for reply\n",filename);
  258.  
  259.     /* FIRST do "To: " header */
  260.     /* note: CANNOT use printheader for this */
  261.     
  262.     parse=articles[currentarticle]->From;
  263.     fprintf(replyfile,"To: %s\n",parse);
  264.  
  265.     /* now handle "Subject: " header..
  266.      * add "Re:" if not already there.
  267.      */
  268.     if(articles[currentarticle]->Subject[0] != 0){
  269.         parse=articles[currentarticle]->Subject;
  270.         if((parse[0] == 'R') && ((parse[1] &0xdf) == 'E') && (parse[2] == ':'))
  271.             fprintf(replyfile,"Subject: %s",parse);
  272.         else {
  273.             fprintf(replyfile,"Subject: Re: %s",parse);
  274.         }
  275.     } else
  276.         fprintf(replyfile,"Subject: <None>\n");
  277.  
  278.     if(all){
  279.         if(articles[currentarticle]->Cc[0] != 0)
  280.         fprintf(replyfile,"Cc: %s",articles[currentarticle]->Cc);
  281.         else fprintf(stderr,"No CC to add\n");
  282.     }
  283.     fprintf(replyfile,"X-Mailer: philmail\n");
  284.     
  285.     /* and don't forget header terminator */
  286.     fprintf(replyfile,"\n");
  287.  
  288.  
  289.     fprintf(stdout,"Include original article? "); fflush(stdout);
  290.     fgets(buf,1023,stdin);
  291.     if((buf[0] == 'y') || (buf[0] == 'Y')){
  292.         readmsg(replyfile);
  293.         /* "reads" message INTO replyfile */
  294.     }
  295.  
  296.     writemessage(replyfile,filename);
  297.     /* note that "readmsg" also set lastread, etc, again. ug */
  298.     /* but.. but.. should increment curentarticle again?? !! */
  299.     /* YES! So I have decided.. ;-)*/
  300.     currentarticle++;
  301.     /* does not matter if overrun.. readmsg is only way we view
  302.      * articles, I think, and that checks for overrun
  303.      */
  304.  
  305.     /* we MUST close replyfile ABOVE[ in writemessage() ]!!! */
  306.     return;
  307. }
  308.  
  309. /* saves "lastread" article in file "name".
  310.  *  (note that command interface sets lastread, if given number )
  311.  * saves WHOLE article, headers and all
  312.  *  need to check for overrun!!
  313.  */
  314. void save(name)
  315. char *name;
  316. {
  317.     int lastflag=0;
  318.     FILE *savefile;
  319.     char filenam[512];
  320.  
  321.     strcpy(filenam,name); 
  322.     name = filenam;
  323.     if(lastread >= numofarticles){
  324.         puts("past last article");
  325.         return;
  326.     }
  327.     if(lastread == numofarticles-1) lastflag = 1;
  328.     if((savefile = fopen(name,"w+")) == NULL){
  329.         fprintf(stderr,"Error: cannot open %s for saving message\n",name);
  330.         return;
  331.     }
  332.     printf("file is %s\n",name);
  333.  
  334.     fseek(fp,articles[lastread]->position,0);
  335.     /* write first "From " line, stupid!! */
  336.     fgets(buf,1023,fp);
  337.     fputs(buf,savefile);
  338.  
  339.     while(fgets(buf,1023,fp) != NULL){
  340.         if(lastflag == 0){ /* NOT last article, then... */
  341.             if(strncmp("From ",buf,5) == 0){
  342.                 break;
  343.             }
  344.             /* we hit next article */
  345.         }/* otherwise, read until end-of-file */
  346.  
  347.         fputs(buf,savefile);
  348.     }
  349.  
  350.     fclose(savefile);
  351.     printf("saved message %d to file %s\n",lastread,name);
  352. }
  353.  
  354.  
  355. /* setfrom:
  356.  * sets the From line properly, given a header to the "From: " thing.
  357.  *
  358.  * header  is ASSUMED to be AFTER the "From:" header, thus
  359.  * "CLEAN"
  360.  */
  361.  
  362. void setfrom(From,header)
  363. char *From,*header;
  364. {
  365.     char *place;
  366.  
  367.     /* header is after "From: ", and could be
  368.      *     "from me" <eric@gloriantha>
  369.      *     person@address (my name here)
  370.      *     <boring@person.dumb.place>
  371.      *    real!address@this.time
  372.      */
  373.     /* ergo, either there's a "<>" in there, or the first
  374.      * string is the address?? !!
  375.      */
  376.     place = index(header,'<');
  377.     if(place == NULL) {
  378.         /* no strange brackets */
  379.         place = header;
  380.         while(*++place != ' '){
  381.             if(*place == 0) break;
  382.             if((*place == 10) || (*place == 13))
  383.                 break;
  384.         }
  385.         *place = '\0';
  386.         strcpy(From,header);
  387.         return;        
  388.     }
  389.     else /* we can now assume that there is the funky bracket thing */
  390.     {
  391.         char *start = ++place;
  392.         while(*++place != '>') {
  393.             switch(*place){
  394.                 case 0:
  395.                 case 10:
  396.                 case 13:
  397.                 fprintf(stderr,"Error! Error! bad From line [no closing '>'] !\n");
  398.                 fprintf(stderr,"%s",start);
  399.                 exit(-1);
  400.                 default:
  401.                     break;
  402.             }
  403.         }
  404.         *place = '\0';
  405.         strcpy(From,start);
  406.     }
  407.     return;
  408. }
  409.  
  410. /*
  411. *  "printheader" really only prints subject and from lines,
  412. *    as seen ONLY from "header" command.
  413. */
  414.  
  415. printheader(out,i)
  416. FILE *out;
  417. int i;
  418. {
  419.  
  420.     fprintf(out," %s ",articles[i]->From);
  421.     if(articles[i]->Subject[0] != 0L){
  422.         fprintf(out," |:  %s",articles[i]->Subject);
  423.     }
  424. }        
  425.  
  426. /* restart: 
  427.  * reset things, so we can use readfile on another mail folder
  428.  */
  429.  
  430. void restart(){
  431. int i;
  432.     for(i=0; i<numofarticles; i++){
  433.         free(articles[i]);
  434.     }
  435.     numofarticles = 0;
  436.     currentarticle = lastread = 0;
  437. }
  438.  
  439. /* readfile:
  440.  * given a name of a mail folder, 
  441.  * reads it , sets "fp", and initialises stuff.
  442.  */
  443.  
  444. readfile(file)
  445. char *file;
  446. {
  447.     char filenam[512];
  448.     strcpy(filenam,file); 
  449.     file = filenam;
  450.  
  451.     if( (fp=fopen(file,"r")) == NULL){
  452.         fprintf(stderr,"Error: could not open mail file %s\n",file);
  453.         exit(0);
  454.     }
  455.     printf("successfully opened %s\n",file);
  456.     if(fgets(buf,1023,fp) == NULL) {
  457.         puts("Mail file empty!!");
  458.         exit(0);
  459.     }
  460.     if( strncmp("From ",buf,5) != 0){
  461.         format();
  462.         exit(-1);
  463.     }
  464.     
  465.     articles[0] = newarticle();
  466.     
  467.     /* now find all the subjects and stuffs. */
  468.     getpositions();
  469.  
  470.     puts("File seems to be okay\n");
  471.  
  472. }
  473. /* setarticle:
  474.     Given a char pointer with ascii number,
  475.     ( and FIRST CHAR being a diget!! )
  476.     sets currentarticle appropriately.
  477.     DOES set lastread.
  478.     assumed max of two digits;
  479. */
  480. void setarticle(parse)
  481. char *parse;
  482. {
  483.     if(isdigit(parse[1])){
  484.         currentarticle =10 * (parse[0] - '0') + parse[1] - '0';
  485.     } else 
  486.         currentarticle= parse[0] - '0';
  487.  
  488.     if(currentarticle >numofarticles)
  489.         currentarticle = numofarticles;
  490.     lastread = currentarticle;
  491. }
  492.  
  493.