home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / comms / network / amigaelm.lzh / f2.c < prev    next >
C/C++ Source or Header  |  1992-02-14  |  15KB  |  524 lines

  1. #include "prefs.h"
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4.  
  5. #ifdef LATTICE
  6. #include <error.h>
  7. #include <proto/dos.h>
  8. #include <proto/exec.h>
  9. #endif
  10. #ifdef DICE
  11. #include <errno.h>
  12. #endif
  13.  
  14.  
  15.  
  16. static void ClearDirDisplay(int);
  17. static void DisplayDirLine(int,int,struct MailItem *,int);
  18. static void DisplayDirectory(int,int,int,int);
  19. Prototype void NewDisplayDirectory(int,int,int,int,int);
  20. Prototype void SaveFolder(BOOL,long,long);
  21. Prototype void get_folder_data(long *,long *);
  22. Prototype BOOL folder_changed(long,long);
  23. Prototype struct MailItem *i_th(int);
  24.  
  25.  
  26.  
  27. extern int errno;
  28.  
  29.  
  30.  
  31. struct MailItem *i_th(int i)
  32. {
  33.   struct MailItem *m = MailList;
  34.   while (--i)
  35.     m = m->next;
  36.   return(m);
  37. }
  38.  
  39.  
  40.  
  41. void
  42. SaveFolder(BOOL ask, long laenge, long datum)
  43. {
  44.     long pos;
  45.     FILE *in,*keep,*store;
  46.     struct MailItem *I;
  47.     char Name[MAX_LINELENGTH];
  48.     char Text[MAX_LINELENGTH];  /* large enough for a single line? */
  49.     BOOL flags_written,folder_has_changed;
  50.     BOOL tmp_AlwaysKeep,tmp_AlwaysDelete;
  51.     int Number;
  52.     int to_delete,to_store,to_keep;
  53.     int save_num=1;
  54.     char buffer[80];
  55.     char TitleString[1024];
  56.  
  57.     tmp_AlwaysKeep = AlwaysKeep;
  58.     tmp_AlwaysDelete = AlwaysDelete;
  59.  
  60.     sprintf(Name,"%s.o",FolderName);     /* name for backup */
  61.     LockFile(Name);
  62.     LockFile(FolderName);
  63.  
  64.     if (folder_changed(laenge,datum)) {
  65.       status_msg("Folder has changed. Resynchronizing...",0L);
  66.       get_folder_data(&laenge,&datum);
  67.       if (!read_home_box() || !laenge || !datum) {
  68.         status_msg("Resync failed. Folder not saved.",200L);
  69.         clean_exit(5);
  70.       }
  71.     }
  72.  
  73.     remove(Name);                        /* remove backup */
  74.  
  75.     /* we need to know if there are none, or one, or more to delete/store */
  76.     for (I=MailList,to_delete=0,to_store=0; I; I=I->next) {
  77.       if (I->Status & DELETED)
  78.         to_delete++;
  79.       else if (I->Status & READ)
  80.         to_store++;
  81.     }
  82.  
  83.     if (ask) {
  84.       if (to_delete) {
  85.         char chr;
  86.         sprintf(TBuffer,"\033[%d;%dH\033[JDelete message%s? (y/n) %c\b",
  87.                          Win_Height-1,Win_Width-27+plural_pix(to_delete),
  88.                          plural_s(to_delete),
  89.                          tmp_AlwaysDelete?'y':'n');
  90.         outline();
  91.         do {
  92.           flush_input();
  93.           chr=getch();
  94.           if (chr=='\r')
  95.             chr=(tmp_AlwaysDelete?'y':'n');
  96.         } while (chr!='y' && chr!='n');
  97.         if (chr=='n') {
  98.           putst("No.");
  99.           tmp_AlwaysDelete = FALSE;
  100.         }
  101.         else {
  102.           tmp_AlwaysDelete = TRUE;
  103.           putst("Yes.");
  104.         }
  105.         Delay(25L);  /* just a moment */
  106.       }
  107.  
  108.       /*
  109.        * We need to determine if read messages
  110.        * are to be stored or kept.
  111.        * (unread messages are always kept)
  112.        */
  113.  
  114.       if (to_store) {
  115.         char chr;
  116.         sprintf(TBuffer,"\033[%d;%dH\033[JMove read message%s to \"received\" folder? (y/n) %c\b",
  117.                          Win_Height-1,Win_Width-51+plural_pix(to_store),
  118.                          plural_s(to_store),
  119.                          tmp_AlwaysKeep?'n':'y');
  120.         outline();
  121.         do {
  122.           flush_input();
  123.           chr=getch();
  124.           if (chr=='\r')
  125.             chr=(tmp_AlwaysKeep?'n':'y');
  126.         } while (chr!='y' && chr!='n');
  127.         if (chr=='n') {
  128.           putst("No.");
  129.           tmp_AlwaysKeep = TRUE;
  130.         }
  131.         else {
  132.           tmp_AlwaysKeep = FALSE;
  133.           putst("Yes.");
  134.         }
  135.         Delay(25L);  /* just a moment */
  136.       }
  137.  
  138.     }
  139.  
  140.     if (tmp_AlwaysKeep)
  141.       to_store = 0;
  142.  
  143.     if (!tmp_AlwaysDelete)
  144.       to_delete = 0;
  145.  
  146.     to_keep=MaxArticle-to_delete-to_store;
  147.  
  148.     /*
  149.      * Formulate message as to number of keeps, stores, and deletes.
  150.      * This is only complex so that the message is good English.
  151.      */
  152.  
  153.     if (to_keep > 0) {
  154.       if (to_store > 0) {
  155.         if (to_delete > 0)
  156.           sprintf(buffer,
  157.                 "Keeping %d message%s, storing %d, and deleting %d.",
  158.                 to_keep, plural_s(to_keep), to_store, to_delete);
  159.         else
  160.           sprintf(buffer, "Keeping %d message%s and storing %d.",
  161.             to_keep, plural_s(to_keep), to_store);
  162.       } else {
  163.         if (to_delete > 0)
  164.           sprintf(buffer, "Keeping %d message%s and deleting %d.",
  165.                   to_keep, plural_s(to_keep), to_delete);
  166.         else
  167.           sprintf(buffer, "Keeping %s.",
  168.                   to_keep > 1 ? "all messages" : "message");
  169.       }
  170.     } else if (to_store > 0) {
  171.       if (to_delete > 0)
  172.         sprintf(buffer, "Storing %d message%s and deleting %d.",
  173.                 to_store, plural_s(to_store), to_delete);
  174.       else
  175.         sprintf(buffer, "Storing %s.",
  176.                 to_store > 1? "all messages" : "message");
  177.  
  178.     } else {
  179.       if (to_delete > 0)
  180.         sprintf(buffer, "Deleting all messages.");
  181.       else
  182.         buffer[0] = '\0';
  183.     }
  184.  
  185.     /* folder has changed? */
  186.  
  187.     folder_has_changed = FALSE;
  188.     for (I=MailList; I; I=I->next) {
  189.       if (I->Status!=I->OldStatus)
  190.         folder_has_changed = TRUE;
  191.     }
  192.  
  193.     if (folder_has_changed)
  194.       status_msg(buffer,0L);
  195.     else {
  196.       status_msg("Folder unchanged.",100L);
  197.       return;
  198.     }
  199.  
  200.     /*
  201.      * Backups der Mailbox machen - auf diese Weise koennen geloeschte
  202.      * Mails von Hand wieder zurueckgeholt werden
  203.      */
  204.  
  205.     if (rename(FolderName,Name)) {
  206.       fprintf(stderr,"elm: cannot rename folder to backup\n");
  207.       UnLockFile(FolderName);
  208.       UnLockFile(Name);
  209.       return;
  210.     }
  211.  
  212.     in=fopen(Name,"r");
  213.     keep=fopen(FolderName,"w");
  214.  
  215.     if (tmp_AlwaysKeep) {
  216.       store=keep;
  217.     }
  218.     else {
  219.       store=fopen(ReceivedFolder,"a");
  220.     }
  221.  
  222.     if ( !in || !keep || !store ) {
  223.         char exec[256];
  224.         fprintf(stderr,"elm: cannot open folder or backup\n");
  225.         sprintf(exec,"COPY %s.o %s",FolderName,FolderName);
  226.         Execute(exec,0L,0L);
  227.         UnLockFile(FolderName);
  228.         UnLockFile(Name);
  229.         return;
  230.     }
  231.  
  232.     for (Number=MaxArticle;Number>0;Number--) {
  233.         FILE *out;
  234.  
  235.         flags_written=FALSE;
  236.  
  237.         if (ReverseSorting)
  238.           I=i_th(Number);
  239.         else
  240.           I=i_th(MaxArticle-Number+1);
  241.  
  242.         /*
  243.          * Wenn die Mail nicht geloescht werden soll, dann die Mail
  244.          * versehen mit dem neuen Status in die Homebox zurueckschreiben
  245.          */
  246.  
  247.         out = ((I->Status & READ) && !tmp_AlwaysKeep)?store:keep;
  248.  
  249.         if (!( (I->Status & DELETED) && tmp_AlwaysDelete )) {
  250.             long todo;  /* bytes to do */
  251.             BOOL goon;  /* go on saving */
  252.             sprintf(TitleString,"Processing %s, message: %d of %d",FolderName,save_num++,to_keep);
  253.             SetScreenTitle(TitleString);
  254.  
  255.             fseek(in,I->ArtikelStart,0);
  256.  
  257. /* -------------------------------------------------------------------------- */
  258.             while((goon=getline(in,Text,&pos)) && (pos<I->TextStart)) {
  259.               if (!flags_written && !strncmp(Text,"X-Status:",9)) {
  260.                 fprintf(out,"X-Status: O");
  261.                 if (I->Status & READ)      putc('R',out);
  262.                 if (I->Status & LOGGED)    putc('L',out);
  263.                 if (I->Status & ANSWERED)  putc('A',out);
  264.                 if (I->Status & FORWARDED) putc('F',out);
  265.                 if (I->Status & BOUNCED)   putc('B',out);
  266.                 putc('\n',out);
  267.                 flags_written=TRUE;
  268.               }
  269.               else if (!flags_written && !strlen(Text)) {
  270.                   fprintf(out,"X-Status: O");
  271.                   if (I->Status & READ)      putc('R',out);
  272.                   if (I->Status & LOGGED)    putc('L',out);
  273.                   if (I->Status & ANSWERED)  putc('A',out);
  274.                   if (I->Status & FORWARDED) putc('F',out);
  275.                   if (I->Status & BOUNCED)   putc('B',out);
  276.                   fprintf(out,"\n\n");
  277.                   flags_written=TRUE;
  278.               }
  279.               else
  280.                 fprintf(out,"%s\n",Text);
  281.             }
  282.  
  283.             if (goon && pos<=I->ArtikelEnd) fprintf(out,"%s\n",Text);
  284. /*
  285.             if (todo = I->ArtikelEnd-I->TextStart) {
  286. */
  287.             if (todo = I->ArtikelEnd-ftell(in)+1L) {
  288.               while(todo>0) {
  289.                 long len = todo>FileBufferSize?FileBufferSize:todo;
  290.                 todo -= len;
  291.                 if (len=fread(FileBuffer,1L,len,in))
  292.                   fwrite(FileBuffer,1L,len,out);
  293.               }
  294.             }
  295. /*
  296.             while(getline(in,Text,&pos) && (pos<=I->ArtikelEnd)) {
  297.                 if (pos<I->ArtikelEnd) {
  298.             /*
  299.              * Status-Zeile gefunden ? Dann in diese Zeile den neuen Status
  300.              * einschreiben.
  301.              */
  302.                     if ((!flags_written) && (strncmp(Text,"X-Status:",9)==0)) {
  303.                         fprintf(out,"X-Status: O");
  304.                         if (I->Status & READ)      putc('R',out);
  305.                         if (I->Status & LOGGED)    putc('L',out);
  306.                         if (I->Status & ANSWERED)  putc('A',out);
  307.                         if (I->Status & FORWARDED) putc('F',out);
  308.                         if (I->Status & BOUNCED)   putc('B',out);
  309.                         putc('\n',out);
  310.                         flags_written=TRUE;
  311.                     }
  312.             /*
  313.              * Noch keine X-Status-Zeile und schon den Message-Body
  314.              * erreicht ? Wenn Status gesetzt ist, dann die X-Status-Zeile
  315.              * schreiben, danach die Body-Zeile
  316.              */
  317.                     else if ((!flags_written) && (pos<=I->TextStart) && (strlen(Text)==0)) {
  318.                         fprintf(out,"X-Status: O");
  319.                         if (I->Status & READ)      putc('R',out);
  320.                         if (I->Status & LOGGED)    putc('L',out);
  321.                         if (I->Status & ANSWERED)  putc('A',out);
  322.                         if (I->Status & FORWARDED) putc('F',out);
  323.                         if (I->Status & BOUNCED)   putc('B',out);
  324.                         putc('\n',out);
  325.                         flags_written=TRUE;
  326.                         fprintf(out,"%s\n",Text);
  327.                     }
  328.                     else
  329.                         fprintf(out,"%s\n",Text);
  330.                 }
  331.             }
  332. */
  333. /* -------------------------------------------------------------------------- */
  334.  
  335.         }
  336.     }
  337.     fclose(in);
  338.     fclose(keep);
  339.     if (!tmp_AlwaysKeep) fclose(store);
  340.  
  341.     UnLockFile(FolderName);
  342.     UnLockFile(Name);
  343.  
  344.     if (!KeepBackup) remove(Name);
  345. }
  346.  
  347.  
  348.  
  349. void
  350. NewDisplayDirectory(int page,int MaxArt,int Akt,int Mode,int MsgPerPage)
  351. {
  352.     static int LastAkt = -1;
  353.     static int LastPage = -1;
  354.     int hi;
  355.     int p20;    /* page*MsgPerPage */
  356.     int f;
  357.  
  358.     if (!MaxArt) return;
  359.  
  360.     putst("\033[0 p");   /* cursor off */
  361.     p20=page*MsgPerPage;
  362.     if ( (p20+MsgPerPage) > MaxArt)                /* Seite nur teilweise gefuellt */
  363.         hi=MaxArt;                         /* Dann nur bis MaxArticle dar- */
  364.     else                                   /* stellen */
  365.         hi=p20+MsgPerPage;
  366.  
  367.     if ((Mode==FULL) || (LastPage!=page)){ /* Seitenwechsel ? */
  368.         DisplayDirectory(page,hi,Akt,MsgPerPage);
  369.         LastPage=page;                     /* Aktuelle position und */
  370.     }
  371.     else {                                 /* Modus update und gleiche Seite */
  372.         if ( (Akt< p20) || (Akt >p20+MsgPerPage))
  373.             DisplayDirectory(page,hi,Akt,MsgPerPage);
  374.         else {
  375.             f=(LastAkt-(p20))+1;
  376.             if(LastAkt>0)                  /* letzten Eintrag normal dar- */
  377.                 DisplayDirLine(f,LastAkt,i_th(LastAkt),0);   /* stellen */
  378.             f=(Akt-(p20))+1;
  379.             DisplayDirLine(f,Akt,i_th(Akt),1); /* Neue Position revers */
  380.         }
  381.     }                                      /* Seite merken          */
  382.     LastAkt=Akt;                           /* darstellen            */
  383.     putst("\033[ p");   /* cursor on */
  384. }
  385.  
  386.  
  387.  
  388. static void
  389. ClearDirDisplay(int MsgPerPage)
  390. {
  391.   register int line=2;
  392.   register int i;
  393.  
  394.   for(i=0;i<MsgPerPage;i++) {
  395.     sprintf(TBuffer,"\033[%d;1H\033[K",line++);
  396.     outline();
  397.   }
  398. }
  399.  
  400.  
  401.  
  402. static void
  403. DisplayDirectory(int page,int hi,int Aktuell,int MsgPerPage)
  404. {
  405.     register int j;
  406.     register int pos=2;
  407.     ClearDirDisplay(MsgPerPage);
  408.     for (j=(page*MsgPerPage);j<hi;j++) {
  409.         if (j==Aktuell-1)
  410.             DisplayDirLine(pos,j+1,i_th(j+1),1);
  411.         else
  412.             DisplayDirLine(pos,j+1,i_th(j+1),0);
  413.         pos++;
  414.     }
  415. }
  416.  
  417.  
  418.  
  419. static void
  420. DisplayDirLine(int Zeile,int Nummer,struct MailItem *I,int Mode)
  421. {
  422.     char linenum[10];
  423.     char stat;
  424.     char *name = NULL;
  425.  
  426.     sprintf(TBuffer,"\033[%d;1H ",Zeile);  /* Goto line pos */
  427.     outline();
  428.  
  429.     if (Mode==1) putst(REVERSE_ON);
  430.  
  431.     sprintf(linenum,"(%ld)",I->Lines);
  432.     if (I->Status&DELETED)
  433.       stat='D';
  434.     else if (I->Status&READ)
  435.       stat=' ';
  436.     else if (I->Status&OLD)
  437.       stat='O';
  438.     else
  439.       stat='N';
  440.  
  441.     if (I->FromName || !I->From) {
  442.       if (I->FromName && strcmp(RealName,I->FromName)) {
  443.         name = I->FromName;
  444.       }
  445.       else {
  446.         if (I->ToName) {
  447.           if (name=malloc(strlen(I->ToName)+4)) {
  448.             sprintf(name,"To %s",I->ToName);
  449.           }
  450.         }
  451.         else if (I->To) {
  452.           if (name=malloc(strlen(I->To)+4)) {
  453.             sprintf(name,"To %s",I->To);
  454.           }
  455.         }
  456.       }
  457.     }
  458.     else
  459.       name = I->From;
  460.  
  461.     if (!name) name = "(none)";
  462.  
  463.     sprintf(TBuffer,"%c%c%c%c%c%c %-3d  %-6.6s  %-20.20s %-6.6s %-*.*s",
  464.             (I->Status & LOGGED)    ? 'L':' ',
  465.             stat,
  466.             (I->Urgent)      ? 'U':' ',
  467.             (I->Status & ANSWERED)  ? 'A':' ',
  468.             (I->Status & FORWARDED) ? 'F':' ',
  469.             (I->Status & BOUNCED)   ? 'B':' ',
  470.             Nummer,
  471.             I->Date,
  472.             name,
  473.             linenum,
  474.             Win_Width-50,
  475.             Win_Width-50,
  476.             I->Subject?I->Subject:"(none)"
  477.            );
  478.  
  479.     outline();
  480.     if (Mode==1) putst(PLAIN_TEXT);
  481. }
  482.  
  483.  
  484.  
  485. void get_folder_data(long *laenge,long *datum)
  486. {
  487.     struct stat s;
  488.     long try = 0L;
  489.     while(stat(FolderName,&s)) {
  490.       char msg[80];
  491.       if (errno!=EBUSY) {          /* resource is busy? */
  492.         fprintf(stderr,"elm: error scanning folder, code %d\n",errno);
  493.         *laenge=0L;
  494.         *datum=0L;
  495.         return;
  496.       }
  497.       sprintf(msg,"Folder is busy. Stand by. Resynchronizing... try #%ld",++try);
  498.       status_msg(msg,0L);
  499.       Delay(100L);
  500.     }
  501.     *laenge=s.st_size;
  502.     *datum=s.st_mtime;
  503. }
  504.  
  505.  
  506.  
  507. BOOL folder_changed(long laenge,long datum)
  508. {
  509.     struct stat s;
  510.     long try = 0L;
  511.     while(stat(FolderName,&s)) {
  512.       char msg[80];
  513.       if (errno!=EBUSY) {          /* resource is busy? */
  514.         fprintf(stderr,"elm: error scanning folder, code %d\n",errno);
  515.         return(TRUE);
  516.       }
  517.       sprintf(msg,"Folder is busy. Stand by. Resynchronizing... try #%ld",++try);
  518.       status_msg(msg,0L);
  519.       Delay(100L);
  520.     }
  521.     return (s.st_size!=laenge || s.st_mtime!=datum);
  522. }
  523.  
  524.