home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / CONTRIB / MBASE / MBASE50.TAR / mbase / src / mbase.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-25  |  12.4 KB  |  484 lines

  1. /*   ********************************************************************   *
  2.   ***                                                   unix compatible! ***
  3.  *    MetalBase 5.0.....................................................    *
  4.  *                                                                          *
  5.  *    Simultaneous multi-user use of multiple relations!                    *
  6.  *    Users may have many relations open at once, even the same one!        *
  7.  *    Environmentally safe--no chloroflourocarbons to destroy the ozone!    *
  8.  *    Loads of wonderful utilities, like data entry and report writing!     *
  9.  *    Unlimited indicies per relation/Up to 999 fields per composite index! *
  10.  *    Up to 4.2 billion records per relation (that's a lot, friend...)      *
  11.  *    Bizarre intermittent bugs (NOT), just like the expensive programs!    *
  12.  *    Portable to most any small-scale platform you can think of!           *
  13.  *    And, unless they're weird, your kids will eat it.                     *
  14.  *                                                               /\         *
  15.  *    Released October 1st, 1992 by Huan-Ti                  rj /  \        *
  16.  *                                                             /    \       *
  17.  *   "Ye hath mushrooms for $1.99 a pound.  Ye art             \    /       *
  18.  *    truly a Calvinist."                                       \  / tp     *
  19.  *                       -- II Calvin 7:1                        \/         *
  20.  *                                                                          *
  21.  *          206/881-2624 <-----= May 26, 1996 =-----> 615/494-0445          *
  22.   ***       t-richj@microsoft.com / / virtual!root@owlnet.rice.edu       ***
  23.  *   ********************************************************************   */
  24.  
  25. #define MBASE_C
  26. #include "mbase.h"
  27. #include "internal.h"
  28.  
  29. int       _started = 0;
  30. int       _really  = 1;
  31. relation *_list [MAX_REL];
  32.  
  33. #ifndef linux
  34. #ifndef MSDOS
  35. #ifdef LONGARGS
  36.    extern char *getenv (char _FAR_ *);
  37. #else
  38.    extern char *getenv();
  39. #endif
  40. #endif
  41. #endif
  42.  
  43. relation *
  44. mb_open (filename, key, useold)
  45. char    *filename;
  46. int                key, useold;
  47. {
  48.    relation     *rel;
  49.    int           i, rc, fZero = 0;
  50.    char          buf[256], *pch;
  51.    long          fld, idx, tlong;
  52.    short         tshort;
  53.  
  54.    _really = 0;
  55.    if (mb_test (filename, useold) != MB_OKAY)
  56.     { if (_really != 0)
  57.        { if (_really < 0)  close (0-_really);
  58.          else              close (_really);
  59.        }
  60.       _really = 1;
  61.       relerr (mb_errno, RNULL);
  62.     }
  63.    if ((rel = New (relation)) == RNULL)
  64.     { if (_really != 0)
  65.        { if (_really < 0)  close (0-_really);
  66.          else              close (_really);
  67.        }
  68.       _really = 1;
  69.       relerr (MB_NO_MEMORY, RNULL);
  70.     }
  71.  
  72.    rel->rdonly = (_really < 0) ? 1 : 0;
  73.    if (_really < 0)  _really = 0-_really;
  74.    rel->relcode = rc = _really;  _really = 1;
  75.  
  76.    lseek (rel->relcode, 0L, 0);
  77.    readx (rel->relcode, buf, 1);
  78.  
  79.    rel->pos = 0L;
  80.    rel->exc = 0;
  81.    rel->pid = getpid();
  82.    rel->ver = (int)buf[0];
  83.  
  84.    for (i=0; i<MAX_REL; i++)
  85.       if (_list[i] == RNULL)
  86.          break;
  87.    _list[i] = rel;        /* Assign it so mb_rmv()/mb_die() can find it */
  88.  
  89.    if ((pch = strrchr (filename, DIRSEP)) == NULL)
  90.       pch = filename;
  91.    else
  92.       pch++;
  93.    strcpy (buf, pch);
  94.  
  95.    if ((pch = strrchr (buf, '.')) != NULL)
  96.       *pch = 0;
  97.    strcpy (rel->relname, buf);
  98.  
  99.    lseek (rel->relcode, POS_FIELDPTR(rel->ver), 0);
  100.  
  101.    readx (rc, &fld,        4);
  102.    readx (rc, &idx,        4);
  103.    readx (rc, &rel->recz,  4);
  104.    readx (rc, &tlong,      4);
  105.    readx (rc, &tlong,      4);
  106.    readx (rc, &tshort,     2);  rel->num_f = tshort;
  107.    readx (rc, &tshort,     2);  rel->num_i = tshort;
  108.  
  109.    _divine_mask (rel, key);
  110.  
  111.    if (rel->ver == verCURRENT && ! rel->rdonly)
  112.       {
  113.       if ((pch = getenv ("TMP")) != NULL ||
  114.           (pch = getenv ("TEMP")) != NULL)
  115.          {
  116.          strcpy (buf, pch);  /* If they define a directory, use it. */
  117.          }
  118.       else                   /* Otherwise, try to guess a default directory. */
  119.          {
  120. #ifdef UNIX
  121.          strcpy (buf, "/tmp");
  122. #endif
  123.          }
  124.       if (! buf[0])
  125.          {
  126.          close (rel->relcode);
  127.          free (rel);
  128.          relerr (MB_TMPDIR, RNULL);
  129.          }
  130.       if (buf[(i = strlen(buf))-1] != DIRSEP)
  131.          {
  132.          buf[i] = DIRSEP;
  133.          buf[i+1] = 0;
  134.          }
  135.       strcat (buf, rel->relname);
  136.       strcat (buf, ".lck");
  137.  
  138.       if (access (buf, 0) == -1)
  139.          if ((rel->lckcode = creatx (buf)) > 0)
  140.             {
  141.             close (rel->lckcode);
  142.             fZero = 1;
  143.             rel->lckcode = -1;
  144.             }
  145.  
  146.       rel->lckcode = openx (buf, OPENMODE);
  147.  
  148.       if (rel->lckcode <= 0)
  149.          {
  150.          close (rel->relcode);
  151.          free (rel);
  152.          relerr (MB_TMPERR, RNULL);
  153.          }
  154.  
  155.       if (fZero)
  156.          {
  157.          modex (buf, 0666);              /* The 100 bytes consist of:    */
  158.          for (i = 0; i < 100; i++)       /*   2 : Number of users in rel */
  159.             buf[i] = 0;                  /*   2 : Exclustive lock        */
  160.          lseek (rel->lckcode, 0L, 0);    /*   6 : 3 Hacklock positions   */
  161.          writx (rel->lckcode, buf, 100); /*  60 : 30 Queue positions     */
  162.          }                               /*  30 : 30 Strobe positions    */
  163.  
  164. /*
  165.  * Lock file has been created; keep going.
  166.  *
  167.  */
  168.  
  169.       if (_set_lck (rel) || _chk_elck (rel))
  170.          {
  171.          if (rel->exc & 2)
  172.             _clr_lck (rel);
  173.          close (rel->relcode);
  174.          free (rel);
  175.          relerr (mb_errno, RNULL);
  176.          }
  177.       }
  178.  
  179.    return _fill_info (rel, fld, idx);
  180. }
  181.  
  182. mb_err
  183. mb_test (filename, useold)
  184. char    *filename;
  185. int                useold;
  186. {
  187.    int     i, rc, rdonly = 0;
  188.    int     ver;
  189.    char    buffer[256];
  190.  
  191.    if (_started == 0)
  192.       {
  193.       _started = 1;
  194.       for (_started=1, i=0; i<MAX_REL; i++)  /* Initialize list */
  195.          _list[i] = RNULL;                   /* (oh boy fun!)   */
  196.       }
  197.  
  198.    for (i=0; i<MAX_REL; i++)
  199.       if (_list[i] == RNULL)  break;
  200.  
  201.    if (i == MAX_REL)
  202.       {
  203.       _really = 0;
  204.       reterr (MB_NO_ROOM, -1);
  205.       }
  206.  
  207.    strcpy (buffer, filename);
  208.    if (strcmp (&buffer[strlen(buffer)-4], ".rel"))
  209.       strcat (buffer, ".rel");
  210.  
  211.    if ((rc = openx (buffer, OPENMODE)) == -1)
  212.       {
  213.       if ((rc = openx (buffer, READMODE)) == -1)
  214.          {
  215.          if (_really)  close (rc);
  216.          else         _really = 0;
  217.          reterr (MB_NO_OPEN, -1);                    /* Can we open it? */
  218.          }
  219.       rdonly = 1;
  220.       }
  221.    if (readx (rc, buffer, 2) != 2)
  222.       {
  223.       if (_really)  close (rc);  else _really = 0;
  224.       reterr (MB_NO_READ, -1);                    /* Can we read it? */
  225.       }
  226.  
  227.    ver = (int)buffer[0];
  228.  
  229.    if (useold   && (ver < 40 || ver > verCURRENT))
  230.       ver = 0;
  231.    if (! useold && ver != verCURRENT)
  232.       ver = 0;
  233.  
  234.    if (!ver)
  235.       {
  236.       if (_really)  close (rc); else _really = 0;
  237.       reterr (MB_FORMAT, -1);             /* Is it a 5.0 relation? */
  238.       }
  239.  
  240. #ifndef UNIX_LOCKS
  241.    if (ver == verCURRENT && !rdonly && ((int)((uchar)buffer[1]) == 255))
  242.       {
  243.       if (_really)  close (rc);  else _really = 0;
  244.       reterr (MB_BUSY, -1);                   /* Are there 255 users already? */
  245.       }
  246. #endif
  247.  
  248.    if (_really)  close (rc);
  249.    else          _really = (rdonly) ? 0-rc : rc;    /* - == readonly */
  250.  
  251.    reterr (MB_OKAY, MB_OKAY);
  252. }
  253.  
  254. mb_err
  255. mb_add   (rel, rec)
  256. relation *rel;
  257. dataptr        rec;
  258. {
  259.    int     i;
  260.    long    rcd;
  261.    int     err;
  262.  
  263.    if (_identify (rel) < 0)            reterr (MB_BAD_REL,  -1);
  264.    if (rel->rdonly)                    reterr (MB_NO_WRITE, -1);
  265.  
  266.    if (_format (rel, rec, 1))          reterr (mb_errno,    -1);
  267.    if (_set_lck (rel))                 reterr (mb_errno,    -1);
  268.    if (_chk_elck (rel))                lckerr (rel, MB_LOCKED, -1);
  269.  
  270.    _crypt (rel, rec);
  271.    for (i=0; i<rel->num_i; i++)
  272.       if (_check_dup (rel, rec, i, 0L))  lckerr (rel, mb_errno, -1);
  273.  
  274.    _format (rel, rec, 2);
  275.  
  276.    if (! (rcd = _append (rel, rec)))  lckerr (rel, MB_NO_WRITE, -1);
  277.    if (_link (rel, rcd))              lckerr (rel, MB_CORRUPT,  -1);
  278.  
  279.    rel->pos = rcd;
  280.  
  281.    _crypt (rel, rec);
  282.    err = MB_OKAY;
  283.  
  284.    lckerr (rel, MB_OKAY, MB_OKAY);
  285. }
  286.  
  287. mb_err
  288. mb_upd   (rel, rec)
  289. relation *rel;
  290. dataptr        rec;
  291. {
  292.    int     i;
  293.    long    rcd;
  294.  
  295.    if (_identify (rel) < 0)            reterr (MB_BAD_REL, -1);
  296.    if ((rcd = rel->pos) == 0L)         reterr (MB_NO_CURR, -1);
  297.    if (_format (rel, rec, 1))          reterr (mb_errno,   -1);
  298.    if (rel->rdonly)                    reterr (MB_NO_WRITE,-1);
  299.    if (_chk_elck (rel))                reterr (MB_LOCKED,  -1);
  300.  
  301.    if (rel->iser < rel->num_f)
  302.       {
  303.       if (*(long *)((char *)rec + rel->start[rel->iser]) != rel->serial)
  304.          reterr (MB_BAD_SERIAL, -1);
  305.       }
  306.    _crypt (rel, rec);
  307.    for (i=0; i<rel->num_i; i++)
  308.       if (_check_dup (rel, rec, i, rcd)) reterr (mb_errno, -1);
  309.    if (_set_lck (rel))                   reterr (mb_errno, -1);
  310.  
  311.    if (_delete (rel, rel->pos) <= 0L)
  312.       if (mb_errno != MB_OKAY)         lckerr (rel, mb_errno, -1);
  313.  
  314.    GO_RECID (rel, rel->pos);
  315.    writx (rel->relcode, rec, rel->rec_len);
  316.  
  317.    if (_link (rel, rel->pos))          lckerr (rel, MB_CORRUPT,  -1);
  318.  
  319.    _crypt (rel, rec);
  320.    lckerr (rel, MB_OKAY, MB_OKAY);
  321. }
  322.  
  323. mb_err
  324. mb_del   (rel)
  325. relation *rel;
  326. {
  327.    if (_identify (rel) < 0)    reterr (MB_BAD_REL, -1);
  328.    if (rel->pos == 0L)         reterr (MB_NO_CURR, -1);
  329.    if (_chk_elck (rel))        reterr (MB_LOCKED,  -1);
  330.    if (rel->rdonly)            reterr (MB_NO_WRITE,-1);
  331.    if (_set_lck (rel))         reterr (mb_errno,   -1);
  332.  
  333.    if (_delete (rel, rel->pos) <= 0L)
  334.       if (mb_errno != MB_OKAY)  lckerr (rel, mb_errno, -1);
  335.  
  336.    _remove (rel, rel->pos);
  337.  
  338.    rel->pos = 0L;
  339.  
  340.    lckerr (rel, MB_OKAY, MB_OKAY);
  341. }
  342.  
  343. mb_err
  344. mb_rmv   (rel)
  345. relation *rel;
  346. {
  347.    int  i;
  348.  
  349.    if ((i = _identify (rel)) == -1)  reterr (MB_BAD_REL, -1);
  350.    _list[i] = RNULL;
  351.    _close_proc (rel);
  352.    baderr (MB_OKAY);
  353. }
  354.  
  355. void
  356. mb_exit (x)
  357. int      x;
  358. {
  359.    mb_die ();
  360.    exit   (x);
  361. }
  362.  
  363. void
  364. mb_die ()
  365. {
  366.    int  i;
  367.    if (_started)
  368.       for (i=0; i<MAX_REL; i++)
  369.          if (_list[i] != RNULL)
  370.           { _close_proc (_list[i]);
  371.             _list[i] = RNULL;
  372.           }
  373.    _seterr (MB_OKAY);
  374. }
  375.  
  376. long
  377. mb_num   (rel)
  378. relation *rel;
  379. {
  380.    long    x;
  381.    if (_identify (rel) < 0)  longerr (MB_BAD_REL, -1);
  382.    if (lseek (rel->relcode, POS_NUMREC, 0) != POS_NUMREC)
  383.       longerr (MB_FORMAT, -1);
  384.    readx (rel->relcode, &x, 4);
  385.    longerr (MB_OKAY, x);
  386. }
  387.  
  388. int
  389. strtokey (str)
  390. char     *str;
  391. {
  392.    char *a;
  393.    int   x;
  394.    for (x=0, a=str; a && *a; a++)
  395.       x = (x + (int)*a) % 240 + 15;
  396.    return x;
  397. }
  398.  
  399. void
  400. strzcpy (new, old, num)
  401. char    *new,*old;
  402. int                num;
  403. {
  404.    int  i;
  405.    char         *a,*b;
  406.  
  407.    if (!new || !old)  return;
  408.    for (a=new,b=old,i=0; i<num && *b; a++,b++,i++)
  409.       *a = *b;
  410.    *a = 0;
  411. }
  412.  
  413. mb_err
  414. mb_sel   (rel, idx, buf, act, comp)
  415. relation *rel;
  416. int            idx;
  417. mb_action                act;
  418. dataptr             buf,      comp;
  419. {
  420.    dataptr rec;
  421.    long    off, top;
  422.  
  423.    _free_cache ();
  424.  
  425.    if (_identify (rel) < 0)                            baderr (MB_BAD_REL);
  426.    if (act != CURR && (idx < 0 || idx >= rel->num_i))  baderr (MB_BAD_IDX);
  427.    if (_chk_elck (rel))                                baderr (MB_LOCKED);
  428.    if (_set_lck (rel))                                 baderr (mb_errno);
  429.  
  430.    rec = (comp == NULL) ? buf : comp;
  431.    if (rec != NULL)  _crypt (rel, rec);
  432.  
  433.    if (rel->pos == 0L)
  434.       {
  435.       if (act == NEXT)  act = FRST;
  436.       if (act == PREV)  act = LAST;
  437.       }
  438.  
  439.    switch (act)
  440.       {
  441.       case FRST:
  442.       case LAST:  off = _find_ends (rel, idx, (act == FRST) ? -1 : 1);
  443.                  break;
  444.       case CURR:  off = rel->pos;
  445.                  break;
  446.       case NEXT:
  447.       case PREV:  off = _find_seq (rel, 0L, rel->pos, idx, (act == NEXT)?1:-1);
  448.                  break;
  449.       case GTEQ:
  450.       case GTHN:
  451.       case LTEQ:
  452.       case LTHN:
  453.       case EQUL:  GO_TOP (rel, idx);  readx (rel->relcode, &top, 4);
  454.                   off = _search (rel, top, idx, act, rec);
  455.                  break;
  456.       default  :  baderr (MB_UNKNOWN);
  457.                  break;
  458.       }
  459.  
  460.    if (off == 0L)
  461.       {
  462.       _seterr (MB_NO_SUCH);
  463.       }
  464.    else
  465.       {
  466.       _seterr (MB_OKAY);
  467.       rel->pos = off;
  468.       }
  469.  
  470.    _crypt  (rel, rec);           /* Reverse-encrypt the comparison buffer */
  471.    _memrec (rel, rel->pos, buf); /* Read in the output buffer, encrypted  */
  472.    _crypt  (rel, buf);           /* Decrypt the output buffer             */
  473.  
  474.    if (rel->pos && rel->iser < rel->num_f)
  475.       {
  476.       rel->serial = *(long *)((char *)buf + rel->start[rel->iser]);
  477.       }
  478.  
  479.    _clr_lck (rel);
  480.  
  481.    return mb_errno;
  482. }
  483.  
  484.