home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3435 / dumbdb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-01  |  7.5 KB  |  439 lines

  1. /*
  2. ** Dumbdb:
  3. **  A stupid string based database.  It's slow, it's useless.
  4. **  But it does what I want it to.
  5. **
  6. **    This is public domain.
  7. **    Robert Osborne, May 1991
  8. **
  9. **    $Id: dumbdb.c,v 1.5 1991/04/30 19:16:31 robert Exp $
  10. */
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #ifndef __TURBOC__
  16. #include <sys/param.h>
  17. #include <malloc.h>
  18. #endif
  19. #ifndef MAXPATHLEN
  20. #define MAXPATHLEN 512
  21. #endif
  22. #include "dumbdb.h"
  23.  
  24. #define VALID_DUMBDB(ptr) ((ptr) != 0)
  25.  
  26. typedef struct dumbdb {
  27.     FILE *fp;
  28.     char *mode;
  29.     char *path[MAXPATHLEN];
  30. } dumbdb;
  31.  
  32. #define STREQ(a,b) (!strcmp((a),(b)))
  33. dumbDB
  34. open_dumbdb(path,mode)
  35.     char *path;    /* full path to the dumbdb */
  36.     char *mode; /* mode "R","U" */
  37. {
  38.     FILE *fp;
  39.     dumbdb *ret;
  40.     struct stat statbuf;
  41.  
  42.     ret = (dumbdb *)malloc(sizeof(dumbdb));
  43.     if( ! ret )
  44.         return (dumbDB) 0;
  45.  
  46.     strcpy(ret->path,path);
  47.     if( STREQ(mode,"R") )
  48.     {
  49.         ret->mode = "r";
  50.     }
  51.     else if( STREQ(mode,"U") )
  52.     {
  53.         ret->mode = "a+";
  54.     }
  55.     else
  56.     {
  57.         free(ret);
  58.         return (dumbDB) 0;
  59.     }
  60.  
  61.     if( *ret->mode == 'a' && !lock_file(ret->path, 240, 5) )
  62.     {
  63.         free(ret);
  64.         return (dumbDB) 0;
  65.     }
  66.     
  67.     ret->fp = fopen(path, ret->mode);
  68.     if( ret->fp == (FILE *) 0 )
  69.     {
  70.         free(ret);
  71.         return (dumbDB) 0;
  72.     }
  73.     strcpy(ret->path, path);
  74.  
  75.  
  76.     return ret;
  77. }
  78.  
  79. int
  80. close_dumbdb(db)
  81.     dumbDB db;
  82. {
  83.     dumbdb *dbp = (dumbdb *) db;
  84.     int ret;
  85.     char editpath[MAXPATHLEN];
  86.  
  87.     if( ! VALID_DUMBDB(dbp) )
  88.     {
  89.         return -1;
  90.     }
  91.  
  92.     if( dbp->mode[0] == 'a' )
  93.     {
  94.         unlock_file(dbp->path);
  95.     }
  96.     ret = fclose(dbp->fp);
  97.     free(dbp);
  98.     return ret;
  99. }
  100.  
  101.  
  102. /*
  103. ** rewind file, and get first entry
  104. */
  105. dumbdb_first_entry(db, buffer, argc, argv)
  106.     dumbDB db;
  107.     char *buffer;
  108.     int argc;     /* number of '\0' terminated strings to get */
  109.     char *argv[]; /* pointers to strings within working buffer */
  110. {
  111.     dumbdb *dbp = (dumbdb *) db;
  112.  
  113.     if( ! VALID_DUMBDB(dbp) || argc <= 0 )
  114.     {
  115.         return -1;
  116.     }
  117.  
  118.     if( fseek(dbp->fp, 0L, 0) != 0 )
  119.     {
  120.         return -1;
  121.     }
  122.  
  123.     return dumbdb_next_entry(db, buffer, argc, argv);
  124. }
  125. /*
  126. ** parse the next entry
  127. */
  128. int
  129. dumbdb_next_entry(db, buffer, argc,argv)
  130.     dumbDB db;
  131.     char *buffer;
  132.     int argc;     /* number of '\0' terminated strings to get */
  133.     char *argv[]; /* pointers to strings within working buffer */
  134. {
  135.     dumbdb *dbp = (dumbdb *) db;
  136.     int c, count;
  137.  
  138.     if( ! VALID_DUMBDB(dbp) || argc <= 0 )
  139.     {
  140.         return -1;
  141.     }
  142.  
  143.     count = 1;
  144.     argv[0] = buffer;
  145.     while( (c=fgetc(dbp->fp)) != -1 )
  146.     {
  147.         *buffer++ = c;
  148.         if( c == '\0' )
  149.         {
  150.             if( count < argc )
  151.             {
  152.                 argv[count++] = buffer;
  153.             }
  154.             else
  155.             {
  156.                 return 0;
  157.             }
  158.         }
  159.     }
  160.     return -1;
  161. }
  162. static int
  163. eq_entry(argc,argv1,argv2)
  164.     int argc;        /* number of strings to compare */
  165.     char *argv1[];    /* array of strings or null pointers */
  166.     char *argv2[];    /* db entry to compare no modifiers */
  167. {
  168.     int i;
  169.  
  170.     for(i=0; i<argc; i++)
  171.     {
  172.         if( argv1[i] == (char *) 0 )
  173.         {
  174.             continue;
  175.         }
  176.         if( STREQ(argv1[i],argv2[i]) )
  177.         {
  178.             continue;
  179.         }
  180.         return 0;
  181.     }
  182.     return 1;
  183. }
  184. /*
  185. ** find a entry that matches the given fields
  186. */
  187. int
  188. dumbdb_find_first(db,buffer,argc,argv,found)
  189.     dumbDB db;
  190.     char *buffer;
  191.     int argc;     /* number of '\0' terminated strings to add */
  192.     char *argv[]; /* pointers to strings to add */
  193.     char *found[]; /* pointer to found strings */
  194. {
  195.     dumbdb *dbp = (dumbdb *) db;
  196.     int ret;
  197.  
  198.     if( ! VALID_DUMBDB(dbp) || argc <= 0 )
  199.     {
  200.         return -1;
  201.     }
  202.  
  203.     ret = dumbdb_first_entry(db, buffer, argc, found);
  204.     while( ret == 0 )
  205.     {
  206.         if( eq_entry(argc, argv, found) )
  207.         {
  208.             return(0);
  209.         }
  210.         ret = dumbdb_next_entry(db, buffer, argc, found);
  211.     }
  212.     return -1;
  213. }
  214. int
  215. dumbdb_find_next(db,buffer,argc,argv,found)
  216.     dumbDB db;
  217.     char *buffer;
  218.     int argc;     /* number of '\0' terminated strings to add */
  219.     char *argv[]; /* pointers to strings to add */
  220.     char *found[]; /* pointer to found strings */
  221. {
  222.     dumbdb *dbp = (dumbdb *) db;
  223.     int ret;
  224.  
  225.     if( ! VALID_DUMBDB(dbp) || argc <= 0 )
  226.     {
  227.         return -1;
  228.     }
  229.  
  230.     ret = dumbdb_next_entry(db, buffer, argc, found);
  231.     while( ret == 0 )
  232.     {
  233.         if( eq_entry(argc, argv, found) )
  234.         {
  235.             return(0);
  236.         }
  237.         ret = dumbdb_next_entry(db, buffer, argc, found);
  238.     }
  239.     return -1;
  240. }
  241. /*
  242. ** add an entry to the end of the list
  243. ** NB: dumbdb_find_next or dumbdb_next_entry won't work
  244. **     without a intervening call to dumbdb_first_entry or
  245. **     dumbdb_find_first.
  246. */
  247. int
  248. dumbdb_add_entry(db,argc,argv)
  249.     dumbDB db;
  250.     int argc;     /* number of '\0' terminated strings to add */
  251.     char *argv[]; /* pointers to strings to add */
  252. {
  253.     dumbdb *dbp = (dumbdb *) db;
  254.  
  255.     if( ! VALID_DUMBDB(dbp) || argc <= 0 )
  256.     {
  257.         return -1;
  258.     }
  259.     if( ! dbp->mode[0] == 'a' )
  260.     {
  261.         return -1;
  262.     }
  263.  
  264.     if( fseek(dbp->fp, 0L, 2) != 0 )
  265.     {
  266.         return -1;
  267.     }
  268.  
  269.     while( argc )
  270.     {
  271.         if( *argv != (char *) 0 )
  272.         {
  273.             fputs(*argv, dbp->fp);
  274.         }
  275.         fputc('\0', dbp->fp);
  276.         argv++;
  277.         argc--;
  278.     }
  279.     return 0;
  280. }
  281. /*
  282. ** Acts like a filter and removes all entries that match the
  283. ** given entry from the db.
  284. ** NB: dumbdb_find_next or dumbdb_next_entry won't work
  285. **     without a intervening call to dumbdb_first_entry or
  286. **     dumbdb_find_first.
  287. */
  288. int
  289. dumbdb_delete_entries(db,argc,argv)
  290.     dumbDB db;
  291.     int argc;     /* number of '\0' terminated strings to add */
  292.     char *argv[]; /* pointers to entry pattern to delete */
  293. {
  294.     dumbdb *dbp = (dumbdb *) db;
  295.     FILE *newfp;
  296.     int count = 0;
  297.     int ret;
  298.     int i;
  299.     char editpath[MAXPATHLEN];
  300.     char buffer[DUMBDB_MAXENTRY];
  301.     char *found[DUMBDB_MAXFIELDS];
  302.  
  303.     if( ! VALID_DUMBDB(dbp) || argc <= 0 )
  304.     {
  305.         return count;
  306.     }
  307.     if( ! dbp->mode[0] == 'a' )
  308.     {
  309.         return count;
  310.     }
  311.     sprintf(editpath, "%s.new", dbp->path);
  312.     if( (newfp = fopen(editpath, "w+")) == (FILE *) 0 )
  313.     {
  314.         return count;
  315.     }
  316.  
  317.     ret = dumbdb_first_entry(db, buffer, argc, found);
  318.     while( ret == 0 )
  319.     {
  320.         if( ! eq_entry(argc, argv, found) )
  321.         {
  322.             for(i=0; i<argc; i++)
  323.             {
  324.                 if( found[i] != (char *) 0 )
  325.                 {
  326.                     fputs(found[i], newfp);
  327.                 }
  328.                 fputc('\0', newfp);
  329.             }
  330.         }
  331.         else
  332.         {
  333.             count++;
  334.         }
  335.         ret = dumbdb_next_entry(db, buffer, argc, found);
  336.     }
  337.  
  338.     if( count > 0 )
  339.     {
  340.         fclose(dbp->fp);
  341.         dbp->fp = newfp;
  342.         unlink(dbp->path);
  343. #ifdef __TURBOC__
  344.         rename(editpath, dbp->path);
  345. #else
  346.         link(editpath, dbp->path);
  347.         unlink(editpath);
  348. #endif
  349.     }
  350.     else
  351.     {
  352.         fclose(newfp);
  353.         unlink(editpath);
  354.     }
  355.     return count;
  356. }
  357. /*
  358. ** Finds the first entry that matchs the search and replaces it.
  359. ** NB: dumbdb_find_next or dumbdb_next_entry won't work
  360. **     without a intervening call to dumbdb_first_entry or
  361. **     dumbdb_find_first.
  362. */
  363. int
  364. dumbdb_find_and_replace(db,argc,search,replace)
  365.     dumbDB db;
  366.     int argc;     /* number of '\0' terminated strings to add */
  367.     char *search[]; /* pointers to entry pattern to delete */
  368.     char *replace[]; /* pointers to entry pattern to delete */
  369. {
  370.     dumbdb *dbp = (dumbdb *) db;
  371.     FILE *newfp;
  372.     int ret, i, replaced = 1;
  373.     char editpath[MAXPATHLEN];
  374.     char buffer[DUMBDB_MAXENTRY];
  375.     char *found[DUMBDB_MAXFIELDS];
  376.  
  377.     if( ! VALID_DUMBDB(dbp) || argc <= 0 )
  378.     {
  379.         return replaced;
  380.     }
  381.     if( ! dbp->mode[0] == 'a' )
  382.     {
  383.         return replaced;
  384.     }
  385.     sprintf(editpath, "%s.new", dbp->path);
  386.     if( (newfp = fopen(editpath, "w+")) == (FILE *) 0 )
  387.     {
  388.         return replaced;
  389.     }
  390.  
  391.     ret = dumbdb_first_entry(db, buffer, argc, found);
  392.     while( ret == 0 )
  393.     {
  394.         if( !replaced || ! eq_entry(argc, search, found) )
  395.         {
  396.             for(i=0; i<argc; i++)
  397.             {
  398.                 if( found[i] != (char *) 0 )
  399.                 {
  400.                     fputs(found[i], newfp);
  401.                 }
  402.                 fputc('\0', newfp);
  403.             }
  404.         }
  405.         else
  406.         {
  407.             replaced = 0;
  408.             for(i=0; i<argc; i++)
  409.             {
  410.                 if( replace[i] != (char *) 0 )
  411.                 {
  412.                     fputs(replace[i], newfp);
  413.                 }
  414.                 fputc('\0', newfp);
  415.             }
  416.         }
  417.         ret = dumbdb_next_entry(db, buffer, argc, found);
  418.     }
  419.  
  420.     if( !replaced )
  421.     {
  422.         fclose(dbp->fp);
  423.         dbp->fp = newfp;
  424.         unlink(dbp->path);
  425. #ifdef __TURBOC__
  426.         rename(editpath, dbp->path);
  427. #else
  428.         link(editpath, dbp->path);
  429.         unlink(editpath);
  430. #endif
  431.     }
  432.     else
  433.     {
  434.         fclose(newfp);
  435.         unlink(editpath);
  436.     }
  437.     return replaced;
  438. }
  439.