home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / MLABELS / MLABELS.C < prev   
Encoding:
C/C++ Source or Header  |  1997-04-13  |  10.0 KB  |  362 lines

  1. /* MLABELS.C */
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. /* Make mailing labels from Synchronet BBS user database                    */
  6. /* Digital Dynamics - 03/16/93 v1.00                                        */
  7. /* Digital Dynamics - 03/03/94 v2.00                                        */
  8. /* Digital Dynamics - 04/13/95 v2.10                                        */
  9. /* Digital Dynamics - 07/17/95 v2.20                                        */
  10.  
  11. /* For compilation under Borland/Turbo C(++)                                */
  12.  
  13. /* Set tabstops to 4 for viewing/printing                                    */
  14.  
  15. /* This program and source code are public domain. Modified versions may    */
  16. /* note be distributed without consent from Digital Dynamics.                */
  17.  
  18. #include <io.h>
  19. #include <share.h>
  20. #include <fcntl.h>
  21. #include <errno.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <sys\stat.h>
  25. #include "sbbsdefs.h"           /* Synchronet typedefs and macros header */
  26.  
  27. #define DOUBLE_COLUMN    (1<<0)        /* Print double column labels */
  28. #define ATTN_ALIAS        (1<<1)        /* Print ATTN: Alias/Real Name */
  29.  
  30. char *nulstr="";
  31. int  min=0,max=99;
  32. long reqflags[4]={0},reqrest=0,reqexempt=0;
  33.  
  34. char *usage=
  35. "\nusage: mlabels <data\\user path> [[-require] [...]] [/options] <outfile>\n"
  36. "\nwhere require is one of:\n"
  37. "       L#                  set minimum level to # (default=0)\n"
  38. "       M#                  set maximum level to # (default=99)\n"
  39. "       F#<flags>           set required flags from flag set #\n"
  40. "       E<flags>            set required exemptions\n"
  41. "       R<flags>            set required restrictions\n"
  42. "\nwhere options is one or more of:\n"
  43. "       D                   double column labels\n"
  44. "       A                   include ATTN: alias/name on label\n"
  45. "\nexample:\n"
  46. "\nMLABELS \\SBBS\\DATA\\USER -L50 /D PRN\n";
  47.  
  48.  
  49. /****************************************************************************/
  50. /* Converts an ASCII Hex string into an ulong                       */
  51. /****************************************************************************/
  52. ulong ahtoul(char *str)
  53. {
  54.     ulong l,val=0;
  55.  
  56. while((l=(*str++)|0x20)!=0x20)
  57.     val=(l&0xf)+(l>>6&1)*9+val*16;
  58. return(val);
  59. }
  60.  
  61. /****************************************************************************/
  62. /* Truncates white-space chars off end of 'str' and terminates at first tab */
  63. /****************************************************************************/
  64. void truncsp(char *str)
  65. {
  66.     char c;
  67.  
  68. str[strcspn(str,"\t")]=0;
  69. c=strlen(str);
  70. while(c && (uchar)str[c-1]<=SP) c--;
  71. str[c]=0;
  72. }
  73.  
  74. /****************************************************************************/
  75. /* Returns bytes offset into user record for flag set # 'set'               */
  76. /****************************************************************************/
  77. long getflagoff(int set)
  78. {
  79. switch(set) {
  80.     default:
  81.         return(U_FLAGS1);
  82.     case 2:
  83.         return(U_FLAGS2);
  84.     case 3:
  85.         return(U_FLAGS3);
  86.     case 4:
  87.         return(U_FLAGS4); }
  88. }
  89.  
  90. /****************************************************************************/
  91. /* Checks a user record against the requirements set on the command line    */
  92. /* Returns 1 if the user meets the requirements (or no requirements were    */
  93. /* specified) or 0 if the user does not meet any of the requirements.        */
  94. /****************************************************************************/
  95. int chkuser(FILE *stream, long offset)
  96. {
  97.     char str[128];
  98.     int i;
  99.  
  100. if(min || max!=99) {            /* Check security level */
  101.     fseek(stream,offset+U_LEVEL,SEEK_SET);
  102.     fread(str,2,1,stream);
  103.     str[2]=0;
  104.     i=atoi(str);
  105.     if(i<min || i>max)            /* not within range */
  106.         return(0); }            /* so skip this user */
  107.  
  108. for(i=0;i<4;i++)
  109.     if(reqflags[i]) {
  110.         fseek(stream,offset+getflagoff(i+1),SEEK_SET);
  111.         fread(str,8,1,stream);
  112.         str[8]=0;
  113.         truncsp(str);
  114.         if((ahtoul(str)&reqflags[i])!=reqflags[i])
  115.             return(0); }    /* doesn't have 'em all */
  116.  
  117. if(reqrest) {
  118.     fseek(stream,offset+U_REST,SEEK_SET);
  119.     fread(str,8,1,stream);
  120.     str[8]=0;
  121.     truncsp(str);
  122.     if((ahtoul(str)&reqrest)!=reqrest)
  123.         return(0); }
  124.  
  125. if(reqexempt) {
  126.     fseek(stream,offset+U_REST,SEEK_SET);
  127.     fread(str,8,1,stream);
  128.     str[8]=0;
  129.     truncsp(str);
  130.     if((ahtoul(str)&reqexempt)!=reqexempt)
  131.         return(0); }
  132.  
  133. return(1);
  134. }
  135.  
  136. /****************************************************************************/
  137. /* Attempts to lock a user record, retries for up to 10 seconds             */
  138. /* Returns 0 on success, -1 on failure                                        */
  139. /****************************************************************************/
  140. int lockuser(FILE *stream, ulong offset)
  141. {
  142.     time_t start;
  143.  
  144. if(lock(fileno(stream),offset,U_LEN)==0)
  145.     return(0);
  146. start=time(NULL);
  147. while(1) {
  148.     if(lock(fileno(stream),offset,U_LEN)==0)
  149.         return(0);
  150.     if(time(NULL)-start>=10L)
  151.         break; }
  152. return(-1);
  153. }
  154.  
  155. /***************/
  156. /* Entry point *
  157. /***************/
  158. int main(int argc, char **argv)
  159. {
  160.     char    str[256],buf1[U_LEN],buf2[U_LEN],infile[128]="",outfile[128]=""
  161.             ,mode=0;    /* optional modes bits */
  162.     int     i,j,k,file,printed=0;
  163.     long    l,length,offset;
  164.     FILE    *in,*out;
  165.  
  166. printf("\nSynchronet Mailing Labels v2.10\n");
  167. for(i=1;i<argc;i++) {
  168.     if(argv[i][0]=='-')
  169.         switch(toupper(argv[i][1])) {
  170.             case 'L':                       /* Set minimum sec level */
  171.                 min=atoi(argv[i]+2);
  172.                 break;
  173.             case 'M':                       /* Set maximum sec level */
  174.                 max=atoi(argv[i]+2);
  175.                 break;
  176.             case 'F':                       /* Set required flags */
  177.                 j=3;
  178.                 k=1;
  179.                 if(isdigit(argv[i][2]))
  180.                     k=argv[i][2]&0xf;
  181.                 else
  182.                     j=2;
  183.                 for(;argv[i][j];j++)
  184.                     if(isalpha(argv[i][j]))
  185.                         reqflags[k-1]|=FLAG(toupper(argv[i][j]));
  186.                 break;
  187.             case 'R':                       /* Set required restrictions */
  188.                 for(j=2;argv[i][j];j++)
  189.                     if(isalpha(argv[i][j]))
  190.                         reqrest|=FLAG(toupper(argv[i][j]));
  191.                 break;
  192.             case 'E':                       /* Set required exemptions */
  193.                 for(j=2;argv[i][j];j++)
  194.                     if(isalpha(argv[i][j]))
  195.                         reqexempt|=FLAG(toupper(argv[i][j]));
  196.                 break;
  197.             default:                        /* Unrecognized include */
  198.                 printf(usage);
  199.                 exit(1); }
  200.  
  201.     else if(argv[i][0]=='/') {
  202.         k=strlen(argv[i]);
  203.         for(j=1;j<k;j++)
  204.             switch(toupper(argv[i][j])) {
  205.                 case 'D':   /* Double column labels */
  206.                     mode|=DOUBLE_COLUMN;
  207.                     break;
  208.                 case 'A':   /* Attention Alias/Real Name */
  209.                     mode|=ATTN_ALIAS;
  210.                     break;
  211.                 default:
  212.                     printf("\nUnknown option\n");
  213.                 case '?':
  214.                     printf(usage);
  215.                     exit(1); } }
  216.     else if(infile[0])                /* in filename already given */
  217.         strcpy(outfile,argv[i]);
  218.     else
  219.         strcpy(infile,argv[i]); }
  220.  
  221. if(!infile[0] || !outfile[0]) {
  222.     printf("\nFilename not specified\n");
  223.     printf(usage);
  224.     exit(1); }
  225.  
  226. if(infile[strlen(infile)-1]!='\\' && infile[strlen(infile)-1]!=':')
  227.     strcat(infile,"\\");
  228. strcat(infile,"USER.DAT");
  229. if((file=sopen(infile,O_RDONLY|O_BINARY,SH_DENYNO))==-1) {
  230.     printf("\nError opening %s\n",infile);
  231.     exit(1); }
  232. if((in=fdopen(file,"rb"))==NULL) {
  233.     printf("\nError opening %s\n",infile);
  234.     exit(1); }
  235. setvbuf(in,NULL,_IOFBF,2048);
  236. length=filelength(file);
  237.  
  238. if((file=open(outfile,O_WRONLY|O_TRUNC|O_CREAT|O_BINARY
  239.     ,S_IWRITE|S_IREAD))==-1) {
  240.     printf("\nError opening/creating %s\n",outfile);
  241.     exit(1); }
  242. if((out=fdopen(file,"wb"))==NULL) {
  243.     printf("\nError opening %s\n",outfile);
  244.     exit(1); }
  245. setvbuf(out,NULL,_IOFBF,2048);
  246.  
  247. printf("\n");
  248. for(offset=0;offset<length;offset+=U_LEN) {
  249.     printf("%lu of %lu (%u labels)\r"
  250.         ,(offset/U_LEN)+1,length/U_LEN,printed);
  251.     if(lockuser(in,offset)) {
  252.         printf("Error locking offset %lu\n",offset);
  253.         continue; }
  254.  
  255.     if(!chkuser(in,offset)) {
  256.         unlock(fileno(in),offset,U_LEN);
  257.         continue; }
  258.  
  259.     fseek(in,offset,SEEK_SET);
  260.     if(!fread(buf1,U_LEN,1,in)) {
  261.         printf("Couldn't read %lu bytes at %lu\n",U_LEN,offset);
  262.         break; }
  263.     unlock(fileno(in),offset,U_LEN);
  264.     for(i=0;i<U_LEN;i++) {                /* Convert ETX (3) to NULL (0) */
  265.         if(buf1[i]==ETX)
  266.             buf1[i]=NULL; }
  267.  
  268.     buf1[U_MISC+8]=0;
  269.     l=ahtoul(buf1+U_MISC);
  270.     if(l&(DELETED|INACTIVE))             /* skip if deleted or inactive */
  271.         continue;
  272.  
  273.     while(mode&DOUBLE_COLUMN) {          /* double wide - right column */
  274.         offset+=U_LEN;
  275.         printf("%lu of %lu (%u labels)\r"
  276.             ,(offset/U_LEN)+1,length/U_LEN,printed);
  277.         if(lockuser(in,offset)) {
  278.             printf("Error locking offset %lu\n",offset);
  279.             continue; }
  280.         fseek(in,offset,SEEK_SET);
  281.         if(!fread(buf2,U_LEN,1,in)) {
  282.             mode&=~DOUBLE_COLUMN;
  283.             unlock(fileno(in),offset,U_LEN); }
  284.         else {
  285.             if(!chkuser(in,offset)) {
  286.                 unlock(fileno(in),offset,U_LEN);
  287.                 continue; }
  288.             unlock(fileno(in),offset,U_LEN);
  289.             for(i=0;i<U_LEN;i++) {        /* Convert ETX (3) to NULL (0) */
  290.                 if(buf2[i]==ETX)
  291.                     buf2[i]=NULL; }
  292.             buf2[U_MISC+8]=0;
  293.             l=ahtoul(buf2+U_MISC);
  294.             if(l&(DELETED|INACTIVE))    /* skip if deleted or inactive */
  295.                 continue;
  296.             else
  297.                 break; } }
  298.  
  299.     if(mode&DOUBLE_COLUMN) {            /* print two columns */
  300.         fprintf(out,"    %-*.*s%*s%.*s\r\n"
  301.             ,LEN_NAME,LEN_NAME
  302.             ,buf1+U_NAME
  303.             ,41-LEN_NAME,nulstr
  304.             ,LEN_NAME
  305.             ,buf2+U_NAME);
  306.  
  307.         fprintf(out,"    %-*.*s%*s%.*s\r\n"
  308.             ,LEN_ADDRESS,LEN_ADDRESS
  309.             ,buf1+U_ADDRESS
  310.             ,41-LEN_ADDRESS,nulstr
  311.             ,LEN_ADDRESS
  312.             ,buf2+U_ADDRESS);
  313.  
  314.         sprintf(str,"%.*s %.*s"
  315.             ,LEN_LOCATION,buf1+U_LOCATION
  316.             ,LEN_ZIPCODE,buf1+U_ZIPCODE);
  317.  
  318.         fprintf(out,"    %-41s%.*s %.*s\r\n"
  319.             ,str
  320.             ,LEN_LOCATION,buf2+U_LOCATION
  321.             ,LEN_ZIPCODE,buf2+U_ZIPCODE);
  322.  
  323.         sprintf(str,"ATTN: %.*s",LEN_ALIAS,buf1+U_ALIAS);
  324.  
  325.         if(mode&ATTN_ALIAS)
  326.             fprintf(out,"    %-41sATTN: %.*s\r\n\r\n\r\n"
  327.                 ,str,LEN_ALIAS,buf2+U_ALIAS);
  328.         else
  329.             fprintf(out,"\r\n\r\n\r\n");
  330.  
  331.         printed+=2; }
  332.  
  333.     else {                                /* single column labels */
  334.         fprintf(out,"    %.*s\r\n"
  335.             ,LEN_NAME
  336.             ,buf1+U_NAME);
  337.  
  338.         fprintf(out,"    %.*s\r\n"
  339.             ,LEN_ADDRESS
  340.             ,buf1+U_ADDRESS);
  341.  
  342.         fprintf(out,"    %.*s %.*s\r\n"
  343.             ,LEN_LOCATION
  344.             ,buf1+U_LOCATION
  345.             ,LEN_ZIPCODE
  346.             ,buf1+U_ZIPCODE);
  347.  
  348.         if(mode&ATTN_ALIAS)
  349.             fprintf(out,"    ATTN: %.*s\r\n\r\n\r\n"
  350.                 ,LEN_ALIAS,buf1+U_ALIAS);
  351.         else
  352.             fprintf(out,"\r\n\r\n\r\n");
  353.  
  354.         printed++; } }
  355. printf("\nDone.\n");
  356. fclose(in);
  357. fclose(out);
  358. return(0);
  359. }
  360.  
  361. /* end of mlabels.c */
  362.