home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / comm / Mail+News / UMS11 / Tools / SUMSTools / Source / sumsprint.c < prev    next >
C/C++ Source or Header  |  1995-08-03  |  13KB  |  562 lines

  1.  
  2. #include <utility/hooks.h>
  3.  
  4. #include "sumstl.h"
  5.  
  6. #include <proto/locale.h>
  7.  
  8. #include <stdio.h>
  9. #include <ctype.h>
  10.  
  11. #ifdef __SASC
  12. #include <dos.h>
  13. #endif
  14.  
  15. #include "umsfilter.h"
  16. #include "date.h"
  17.  
  18. /* SMAKE */
  19.  
  20.  
  21. struct MyHook    {
  22.     struct MinNode    h_MinNode;
  23.     ULONG        (*h_Entry)();    /* assembler entry point    */
  24.     ULONG        (*h_SubEntry)();/* often HLL entry point    */
  25.     char    *h_Data;    /* owner specific        */
  26. };
  27.  
  28.  
  29. // Version String
  30. // --------------
  31.  
  32. static char VersionString[] = "$VER: sumsprint "VERSION;
  33.  
  34. static char UsageString[] = "\
  35.      U=User       : user name.\n\
  36.      P=Password   : user's password.\n\
  37.     FI=Filter     : filter specification.\n\
  38.     FO=Format     : format string (see documentation for details).\n\
  39.   FILE=Formatfile : file that contains a format string.\n\
  40.      O=SetOldFlag : if existing, read messages become old.\n\
  41.      B=Backwards  : if existing, messages are scanned backwards.\n\
  42.      S=Server     : server name.\n\n\
  43. ";
  44.  
  45.  
  46. // Template
  47. // --------
  48.  
  49. static char *TemplateString = "U=User=Name/A,P=Password/A,FI=Filter/A,FO=Format,FILE=Formatfile/K,O=SetOldFlag/S,B=Backwards/S,S=Server/K";
  50. enum opts {
  51.     OPT_USER, OPT_PASSWORD, OPT_FILTER, OPT_FORMAT, OPT_FORMATFILE, OPT_SETOLDFLAG, OPT_BACKWARDS, OPT_SERVER,
  52.     OPT_COUNT};
  53. static LONG opts[OPT_COUNT];
  54.  
  55.  
  56. // Globals
  57. // -------
  58.  
  59. extern struct DosLibrary *DOSBase;
  60.  
  61. struct Library *UMSBase = NULL;
  62. struct Library *LocaleBase = NULL;
  63. struct Locale *Locale = NULL;
  64. UMSAccount acc = NULL;
  65. char *TextFields[UMSNUMFIELDS];
  66. struct MyMessageInfo
  67. {
  68.     LONG      msgi_HeaderLength; // 0  (offsets for keyword table)
  69.     LONG      msgi_TextLength;   // 1
  70.     LONG      msgi_Date;         // 2
  71.     UMSMsgNum msgi_ChainUp;      // 3
  72.     UMSMsgNum msgi_ChainDn;      // 4
  73.     UMSMsgNum msgi_ChainLt;      // 5
  74.     UMSMsgNum msgi_ChainRt;      // 6
  75.     UMSSet    msgi_GlobalStatus; // 7
  76.     UMSSet    msgi_UserStatus;   // 8
  77.     UMSSet    msgi_LoginStatus;  // 9
  78.     UMSMsgNum msgi_HardLink;     // 10
  79.     UMSMsgNum msgi_SoftLink;     // 11
  80.     LONG      msgi_MsgNum;       // 12
  81. } MessageInfo;
  82.  
  83.  
  84. #define KW_STRING 0
  85. #define KW_NUMBER 1
  86. #define KW_DATE   2
  87. #define KW_QTEXT  3
  88. #define KW_FLAG   4
  89.  
  90. struct Keyword
  91. {
  92.     char *name;
  93.     char *format;
  94.     LONG type;
  95.     LONG code;
  96. } Keywords[] =
  97. {
  98.     { "MsgText"      ,"%s",KW_STRING,UMSCODE_MsgText      },
  99.  
  100.     { "FromName"     ,"%s",KW_STRING,UMSCODE_FromName     },
  101.     { "FromAddr"     ,"%s",KW_STRING,UMSCODE_FromAddr     },
  102.     { "ToName"       ,"%s",KW_STRING,UMSCODE_ToName       },
  103.     { "ToAddr"       ,"%s",KW_STRING,UMSCODE_ToAddr       },
  104.     { "MsgID"        ,"%s",KW_STRING,UMSCODE_MsgID        },
  105.     { "CreationDate" ,"%s",KW_STRING,UMSCODE_CreationDate },
  106.     { "ReceiveDate"  ,"%s",KW_STRING,UMSCODE_ReceiveDate  },
  107.     { "ReferID"      ,"%s",KW_STRING,UMSCODE_ReferID      },
  108.     { "Group"        ,"%s",KW_STRING,UMSCODE_Group        },
  109.     { "Subject"      ,"%s",KW_STRING,UMSCODE_Subject      },
  110.     { "Attributes"   ,"%s",KW_STRING,UMSCODE_Attributes   },
  111.     { "Comments"     ,"%s",KW_STRING,UMSCODE_Comments     },
  112.     { "Organization" ,"%s",KW_STRING,UMSCODE_Organization },
  113.     { "Distribution" ,"%s",KW_STRING,UMSCODE_Distribution },
  114.     { "Folder"       ,"%s",KW_STRING,UMSCODE_Folder       },
  115.     { "FidoID"       ,"%s",KW_STRING,UMSCODE_FidoID       },
  116.     { "MausID"       ,"%s",KW_STRING,UMSCODE_MausID       },
  117.     { "ReplyGroup"   ,"%s",KW_STRING,UMSCODE_ReplyGroup   },
  118.     { "ReplyName"    ,"%s",KW_STRING,UMSCODE_ReplyName    },
  119.     { "ReplyAddr"    ,"%s",KW_STRING,UMSCODE_ReplyAddr    },
  120.     { "LogicalToName","%s",KW_STRING,UMSCODE_LogicalToName},
  121.     { "LogicalToAddr","%s",KW_STRING,UMSCODE_LogicalToAddr},
  122.     { "RFCMsgNum"    ,"%s",KW_STRING,UMSCODE_RFCMsgNum    },
  123.  
  124.     { "FidoText"     ,"%s",KW_STRING,UMSCODE_FidoText     },
  125.     { "ErrorText"    ,"%s",KW_STRING,UMSCODE_ErrorText    },
  126.     { "Newsreader"   ,"%s",KW_STRING,UMSCODE_Newsreader   },
  127.  
  128.     { "RFCAttr"      ,"%s",KW_STRING,UMSCODE_RfcAttr      },
  129.     { "FTNAttr"      ,"%s",KW_STRING,UMSCODE_FtnAttr      },
  130.     { "ZerAttr"      ,"%s",KW_STRING,UMSCODE_ZerAttr      },
  131.     { "MausAttr"     ,"%s",KW_STRING,UMSCODE_MausAttr     },
  132.  
  133.     { "CDate","%d-%b-%y %X",KW_DATE,UMSCODE_CreationDate },
  134.     { "IDate","%d-%b-%y %X",KW_DATE,UMSCODE_ReceiveDate  },
  135.  
  136.     { "MsgNum"      ,"%ld"  ,KW_NUMBER,12 },
  137.     { "ChainUp"     ,"%ld"  ,KW_NUMBER, 3 },
  138.     { "ChainDown"   ,"%ld"  ,KW_NUMBER, 4 },
  139.     { "ChainLeft"   ,"%ld"  ,KW_NUMBER, 5 },
  140.     { "ChainRight"  ,"%ld"  ,KW_NUMBER, 6 },
  141.     { "HardLink"    ,"%ld"  ,KW_NUMBER,10 },
  142.     { "SoftLink"    ,"%ld"  ,KW_NUMBER,11 },
  143.  
  144.     { "GlobalStatus","%08lx",KW_FLAG, 7 },
  145.     { "UserStatus"  ,"%08lx",KW_FLAG, 8 },
  146.     { "LoginStatus" ,"%08lx",KW_FLAG, 9 },
  147.  
  148.     { "QuoteText","> ",KW_QTEXT,UMSCODE_MsgText },
  149.  
  150.     { NULL,0,0 }
  151. };
  152.  
  153. char *DefaultFormat = "\
  154. Group..: <Group>\n\
  155. From...: <FromName> (<FromAddr>)\n\
  156. To.....: <ToName> (<ToAddr>)\n\
  157. Subject: <Subject>\n\
  158. \n\
  159. <MsgText>\n\
  160. ";
  161.  
  162. static char filteradd[] = " AND readaccess=1 AND viewaccess=1";
  163.  
  164. #define FILTERADDSTR  filteradd
  165. #define NULLFILTERSTR (&filteradd[5])
  166. #define FILTERADDLEN  35
  167.  
  168.  
  169. // Functions
  170. // ---------
  171.  
  172. LONG PrintMessage(char *format);
  173.  
  174.  
  175. // CTRL-C Stuff
  176. // ------------
  177.  
  178. int brk(void)
  179. {
  180.     return(0);
  181. }
  182.  
  183. #define ABORTED (SetSignal(0,0) & SIGBREAKF_CTRL_C)
  184.  
  185.  
  186. // Main Function
  187. // -------------
  188.  
  189. int main(int argc,char *argv[])
  190. {
  191.     char *filter;
  192.     char *format = DefaultFormat;
  193.     char *language=NULL;
  194.     int erg = RETURN_ERROR, umserr;
  195.     int nr=0;
  196.     int oldtag = UMSTAG_RNoUpdate;
  197.     int direction = 1;
  198.     int fi;
  199.     struct RDArgs *args_ptr;
  200.  
  201.     onbreak(brk);
  202.  
  203.     if (argc<2 || *argv[1] == '?')
  204.     {
  205.         fprintf(stderr,"\33[1m%s\33[0m, written by Stefan Stuntz, Public Domain.\n\nTemplate: %s\n%s",&VersionString[6],TemplateString,UsageString);
  206.     }
  207.  
  208.     {
  209.         int i;
  210.  
  211.         for (i=0; i<OPT_COUNT; i++)
  212.         opts[i]=NULL;
  213.     }
  214.  
  215.     if (args_ptr = ReadArgs(TemplateString, opts, NULL))
  216.     {
  217.         if (opts[OPT_FORMATFILE])
  218.         {
  219.             FILE *f;
  220.             int len;
  221.             if (f=fopen((char *)opts[OPT_FORMATFILE],"rb"))
  222.             {
  223.                 fseek(f,0,2);
  224.                 len=ftell(f);
  225.                 fseek(f,0,0);
  226.                 if (!(len>0 && (format=calloc(1,len+1)) && fread(format,1,len,f)==len))
  227.                     format = DefaultFormat;
  228.                 fclose(f);
  229.             }
  230.             else
  231.             {
  232.                 fprintf(stderr,"\7Format file \"%s\" not found.\n",opts[OPT_FORMATFILE]);
  233.                 FreeArgs(args_ptr);
  234.                 return(20);
  235.             }
  236.         }
  237.         else
  238.             if (opts[OPT_FORMAT])
  239.                 format = (char *)opts[OPT_FORMAT];
  240.  
  241.         if (opts[OPT_SETOLDFLAG])
  242.             oldtag    = TAG_IGNORE;
  243.  
  244.         if (opts[OPT_BACKWARDS])
  245.             direction = -1;
  246.  
  247.         if (!strnicmp(format,"LANGUAGE: ",10))
  248.         {
  249.             language = format+10;
  250.             if (!(format=strchr(language,'\n')))
  251.             {
  252.                 fprintf(stderr,"\7Invalid language spec in format file.");
  253.                 FreeArgs(args_ptr);
  254.                 return(20);
  255.             }
  256.             *format++=0;
  257.         }
  258.  
  259.         if (!(filter = malloc(strlen((char *)(opts[OPT_FILTER]))+FILTERADDLEN)))
  260.         {
  261.             fprintf(stderr,"\7Out of memory.\n");
  262.             FreeArgs(args_ptr);
  263.             return(20);
  264.         }
  265.  
  266.         if (opts[OPT_FILTER] && *(char *)opts[OPT_FILTER])
  267.         {
  268.             strcpy(filter,(char *)opts[OPT_FILTER]);
  269.             strcat(filter,FILTERADDSTR);
  270.         }
  271.         else
  272.         {
  273.             strcpy(filter,NULLFILTERSTR);
  274.         }
  275.  
  276.         if (LocaleBase = OpenLibrary("locale.library",38))
  277.             Locale = OpenLocale(language);
  278.  
  279.         if (UMSBase = OpenLibrary(UMSNAME,UMSVERSION))
  280.         {
  281.             if (acc = UMSRLogin((char *)opts[OPT_SERVER],(char *)opts[OPT_USER],(char *)opts[OPT_PASSWORD]))
  282.             {
  283.                 if (!(fi = UmsFilterExpression(filter,acc,0,0,1)))
  284.                 {
  285.                     erg = RETURN_OK;
  286.                     while (nr = UMSSearchTags(acc,
  287.                                 UMSTAG_SearchLast     ,nr,
  288.                                 UMSTAG_SearchLocal    ,TRUE,
  289.                                 UMSTAG_SearchMask     ,1,
  290.                                 UMSTAG_SearchMatch    ,1,
  291.                                     UMSTAG_SearchDirection,direction,
  292.                                 TAG_DONE))
  293.                     {
  294.                         if (ABORTED)
  295.                         {
  296.                             fprintf(stderr,"\7*** User break.\n");
  297.                             erg = RETURN_WARN;
  298.                             break;
  299.                         }
  300.  
  301.                         if (umserr=UMSReadMsgTags(acc,
  302.                             UMSTAG_RMsgNum    ,nr,
  303.                             UMSTAG_RMsgInfo   ,&MessageInfo,
  304.                             UMSTAG_RTextFields,TextFields,
  305.                             UMSTAG_RReadAll   ,TRUE,
  306.                             oldtag            ,TRUE,
  307.                             TAG_DONE))
  308.                         {
  309.                             if (!TextFields[UMSCODE_Group] || !*TextFields[UMSCODE_Group])
  310.                                 TextFields[UMSCODE_Group]="Netmail";
  311.                             MessageInfo.msgi_MsgNum = nr;
  312.                             if ( PrintMessage(format) ) {
  313.                                 erg = RETURN_WARN;
  314.                                 UMSFreeMsg(acc,nr);
  315.                                 break;
  316.                             }
  317.                             UMSFreeMsg(acc,nr);
  318.                         }
  319.                         else
  320.                         {
  321.                             fprintf(stderr,"UMS-Error %d: %s\n",UMSErrNum(acc),UMSErrTxt(acc));
  322.                             erg = RETURN_WARN;
  323.                             /* kludge for bad behavior of UMSSearchTags() */
  324.                             if ( umserr==UMSERR_ServerTerminated ) {
  325.                                 erg = RETURN_ERROR;
  326.                                 break;
  327.                             }
  328.                         }
  329.                     }
  330.                 }
  331.                 else printf("\7Expression Error %ld\n",fi);
  332.  
  333.                 UMSLogout(acc);
  334.             }
  335.             else fprintf(stderr,"\7UMS-Login failed.\n");
  336.  
  337.             CloseLibrary(UMSBase);
  338.         }
  339.         else fprintf(stderr,"\7Could not open ums.library V10.\n");
  340.  
  341.         if (LocaleBase)
  342.         {
  343.             if (Locale) CloseLocale(Locale);
  344.             CloseLibrary(LocaleBase);
  345.         }
  346.  
  347.         FreeArgs(args_ptr);
  348.     }
  349.     else
  350.     {
  351.         PrintFault(IoErr(), NULL);
  352.         return(RETURN_ERROR);
  353.     }
  354.  
  355.     return(erg);
  356. }
  357.  
  358.  
  359. struct Keyword *FindKeyword(char *name)
  360. {
  361.     struct Keyword *k;
  362.  
  363.     for (k=Keywords;k->name;k++)
  364.     {
  365.         if (!stricmp(name,k->name)) return(k);
  366.     }
  367.     return(NULL);
  368. }
  369.  
  370.  
  371. #ifdef _DCC
  372. VOID DatePutCharFunc(__A0 struct MyHook *h, __A1 UBYTE c, __A2 struct Locale *loc)
  373. {
  374.     *h->h_Data++=c;
  375. }
  376. #else
  377. VOID __asm DatePutCharFunc(register __a0 struct MyHook *h,register __a1 UBYTE c,register __a2 struct Locale *loc)
  378. {
  379.     *h->h_Data++ = c;
  380. }
  381. #endif
  382.  
  383.  
  384. LONG PrintMessage(char *format)
  385. {
  386.     static char buf[50];
  387.     char *c = format;
  388.     char *ob,*cb,*fmt;
  389.     int len;
  390.     struct Keyword *k;
  391.  
  392.     while (*c)
  393.     {
  394.         if (*c=='<')
  395.         {
  396.             ob=c;
  397.             if (!(cb=strchr(ob+1,'>'))) break;
  398.             c=cb+1;
  399.             if ((len=cb-ob-1)>49) break;
  400.             strncpy(buf,ob+1,len); buf[len]=0;
  401.             if (fmt=strchr(buf,',')) *fmt++=0;
  402.             if (k=FindKeyword(buf))
  403.             {
  404.                 if (!fmt) fmt=k->format;
  405.                 if (k->type==KW_STRING)
  406.                 {
  407.                     printf(fmt,TextFields[k->code] ? TextFields[k->code] : "");
  408.                 }
  409.                 else if (k->type==KW_NUMBER)
  410.                 {
  411.                     printf(fmt,((LONG *)&MessageInfo)[k->code]);
  412.                 }
  413.                 else if (k->type==KW_FLAG)
  414.                 {
  415.                     if ( *fmt!='%' )
  416.                     {
  417.                         char    *scan,*cfstart=fmt,output[34],*pptr;
  418.                         ULONG    p,flags=((LONG *)&MessageInfo)[k->code];
  419.  
  420.                         if ( pptr=strchr(fmt,'%') )
  421.                         {
  422.                             scan=pptr-1;
  423.                             fmt=pptr;
  424.                         }
  425.                         else
  426.                         {
  427.                             scan=fmt+strlen(fmt)-1;
  428.                             fmt="%s";
  429.                         }
  430.  
  431.                         pptr=output;
  432.                         p=1;
  433.                         while ( scan>=cfstart )
  434.                         {
  435.                             if ( *scan!='-' )
  436.                             {
  437.                                 if ( flags&p )
  438.                                 {
  439.                                     *pptr++=toupper(*scan);
  440.                                 }
  441.                                 else
  442.                                 {
  443.                                     if ( isupper(*scan) )
  444.                                         *pptr++='-';
  445.                                 }
  446.                             }
  447.                             scan--;
  448.                             p<<=1;
  449.                         }
  450.                         *pptr='\0';
  451.                         printf(fmt,output);
  452.                     }
  453.                     else
  454.                     {
  455.                         printf(fmt,((LONG *)&MessageInfo)[k->code]);
  456.                     }
  457.                 }
  458.                 else if (k->type==KW_DATE && Locale)
  459.                 {
  460.                     LONG secs;
  461.                     char *dstr = TextFields[UMSCODE_CreationDate] ? TextFields[UMSCODE_CreationDate] : "";
  462.  
  463.                     if (k->code == UMSCODE_CreationDate)
  464.                     {
  465.                         secs = DateToSeconds(dstr);
  466.                     }
  467.                     else
  468.                     {
  469.                         if (!(secs = MessageInfo.msgi_Date)) secs=1;
  470.                     }
  471.  
  472.                     if (secs)
  473.                     {
  474.                         struct DateStamp ds;
  475.                         static char buf[256];
  476.                         struct MyHook hook = {{0,0},(APTR)DatePutCharFunc,NULL,buf };
  477.  
  478.                         ds.ds_Days   = secs/(24*60*60);
  479.                         ds.ds_Minute = (secs%(24*60*60))/60;
  480.                         ds.ds_Tick   = (secs%60)*50;
  481.  
  482.                         FormatDate(Locale,fmt,&ds,&hook);
  483.                         printf("%s",buf);
  484.                     }
  485.                     else
  486.                         printf("%s",dstr);
  487.                 }
  488.                 else if (k->type==KW_QTEXT)
  489.                 {
  490.                     char *str = TextFields[k->code] ? TextFields[k->code] : "";
  491.                     int pos=0,npos;
  492.  
  493.                     while (*str)
  494.                     {
  495.                         if (pos==0) printf("%s",fmt);
  496.  
  497.                         switch (*str)
  498.                         {
  499.                             case '\r':    putchar('\n');
  500.                                             pos=0;
  501.                                             if (*++str=='\n') str++;
  502.                                             break;
  503.  
  504.                             case '\n':    putchar('\n');
  505.                                             pos=0;
  506.                                             if (*++str=='\r') str++;
  507.                                             break;
  508.  
  509.                             case '\t':  npos = pos + 8 - (pos%8);
  510.                                             while (pos!=npos) { putchar(' '); pos++; }
  511.                                             str++;
  512.                                             if (++pos>79) { putchar('\n'); pos=0; }
  513.                                             break;
  514.  
  515.                             default:        putchar(*str);
  516.                                             str++;
  517.                                             if (++pos>79) { putchar('\n'); pos=0; }
  518.                                             break;
  519.                         }
  520.                     }
  521.                 }
  522.             }
  523.             else
  524.                 fprintf(stderr,"\7Unknown Keyword: %s\n",buf);
  525.         }
  526.         else if (*c=='\\')
  527.         {
  528.             if (!(*++c)) break;
  529.             switch (*c)
  530.             {
  531.                 case '\^': putchar('^');  break;
  532.                 case '\\': putchar('\\'); break;
  533.                 case 'n' : putchar('\n'); break;
  534.                 case 'r' : putchar('\r'); break;
  535.                 case 't' : putchar('\t'); break;
  536.                 case 'f' : putchar('\f'); break;
  537.                 case '<' : putchar('<');  break;
  538.                 case '>' : putchar('>');  break;
  539.                 case 'e' : putchar(27);   break;
  540.                 default  : putchar(*c);   break;
  541.             }
  542.             c++;
  543.         }
  544.         else if (*c=='^')
  545.         {
  546.             if (!(*++c)) break;
  547.             putchar(*c & (~64));
  548.             c++;
  549.         }
  550.         else
  551.         {
  552.             putchar(*c);
  553.             c++;
  554.         }
  555.         if ( ABORTED ) {
  556.             puts("\n*** User break");
  557.             return 5;
  558.         }
  559.     }
  560.     return 0;
  561. }
  562.