home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / cbase.zip / CBASE10B.ZIP / ROLODECK.ZIP / ROLODECK.C < prev    next >
Text File  |  1989-10-31  |  23KB  |  703 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "rolodeck.c    1.2 - 89/10/31" */
  5.  
  6. #include <blkio.h>
  7. #include <cbase.h>
  8. #include <ctype.h>
  9. #include <errno.h>
  10. #include <stdio.h>
  11. #if __STDC__ == 1
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "rolodeck.h"
  15. #else
  16. #ifndef EXIT_SUCCESS
  17. #define EXIT_SUCCESS    (0)
  18. #define EXIT_FAILURE    (1)
  19. #endif
  20. #include "rolodeck.h"
  21. #endif
  22.  
  23. /* function declarations */
  24. #if __STDC__ == 1
  25. int cvtss(char *t, const char *s, int m, size_t n);
  26. int fmltolfm(char *t, const char *s, size_t n);
  27. int lfmtofml(char *t, const char *s, size_t n);
  28. #else
  29. int cvtss();
  30. int fmltolfm();
  31. int lfmtofml();
  32. #endif
  33. #define CVT_X_SP    (0x02)        /* cvtss flags */
  34. #define CVT_X_CTL    (0x04)
  35. #define CVT_X_LEADSP    (0x08)
  36. #define CVT_ONE_SP    (0x10)
  37. #define CVT_X_TRAILSP    (0x80)
  38.  
  39. /* constants */
  40. #define EXPFILE        ("rolodeck.txt")    /* export file */
  41. #define LMAXTRIES    (100)            /* maximum lock tries */
  42.  
  43. /* rolodeck user requests */
  44. #define RD_REQ_NEXT_CARD    ('N')    /* next card */
  45. #define RD_REQ_PREV_CARD    ('P')    /* previous card */
  46. #define RD_REQ_FIRST_CARD    ('F')    /* first card*/
  47. #define RD_REQ_LAST_CARD    ('L')    /* last card */
  48. #define RD_REQ_INS_CARD        ('I')    /* insert card */
  49. #define RD_REQ_DEL_CARD        ('D')    /* delete card */
  50. #define RD_REQ_SRCH_CARD    ('S')    /* search for card */
  51. #define RD_REQ_TOG_SORT        ('T')    /* toggle sort field */
  52. #define RD_REQ_CUR_CARD        ('C')    /* current card */
  53. #define RD_REQ_ALL_CARDS    ('A')    /* all cards */
  54. #define RD_REQ_IMPORT        ('M')    /* import cards */
  55. #define RD_REQ_EXPORT        ('X')    /* export cards */
  56. #define RD_REQ_HELP        ('H')    /* help */
  57. #define RD_REQ_QUIT        ('Q')    /* quit */
  58.  
  59. /*man---------------------------------------------------------------------------
  60. NAME
  61.     rolodeck - card file
  62.  
  63. SYNOPSIS
  64.      rolodeck
  65.  
  66. DESCRIPTION
  67.      rolodeck is an example program for the cbase library.  In order
  68.      to allow it to be compiled without requiring a specific display
  69.      library, only a minimal user interface has been implemented.
  70.  
  71. NOTES
  72.      Below are listed a few of the more important points to note when
  73.      examining the rolodeck source code.
  74.  
  75.           o White space is significant in string data.  For
  76.             instance, " data" != "data".  Leading and
  77.             trailing white space is therefore usually
  78.             removed before storing a string in a database.
  79.             Also, embedded white space may be reduced to a
  80.             single space.  The cvtss function included with
  81.             cbase will perform these string operations.
  82.           o Names are often input and displayed
  83.             first-name-first.  For them to sort correctly in
  84.             a database, however, they must be stored
  85.             last-name-first.  The functions fmltolfm and
  86.             lfmtofml are included with cbase to convert
  87.             between these two formats.
  88.           o bexit is used in place of exit to prevent loss
  89.             of buffered data.
  90.  
  91.      The following notes concern locking.
  92.  
  93.           o Single-tasking applications can simply lock
  94.             a cbase and leave it locked.
  95.           o Locks are held for shortest time possible; a
  96.             lock is never held during user input.
  97.           o A write lock should not be used when only a read
  98.             lock is required.
  99.           o When a database file is unlocked, it may be
  100.             modified by another process.  A record at a
  101.             given file position may be deleted, and the
  102.             empty slot possibly reused for a new record.
  103.             Because of this, each time a file is locked,
  104.             the current record must be located by performing
  105.             a search on a unique key.
  106.           o If locking multiple cbases, deadlock must be
  107.             avoided (see The cbase Programmer's Guide).
  108.  
  109. ------------------------------------------------------------------------------*/
  110. int main(argc, argv)
  111. int argc;
  112. char *argv[];
  113. {
  114.     cbase_t *cbp = NULL;    /* cbase pointer */
  115.     int sf = 0;        /* sort field */
  116.     int rq = 0;        /* user request */
  117.     rolodeck_t rd;        /* cbase record */
  118.     int found = 0;        /* search flag */
  119.     char buf[256];        /* gp input buffer */
  120.  
  121.     /* open rolodeck cbase */
  122.     cbp = cbopen(RDNAME, "r+", RDFLDC, rdfldv);
  123.     if (cbp == NULL) {
  124.         if (errno != ENOENT) {
  125.             fprintf(stderr, "*** Error %d opening rolodeck.\n", errno);
  126.             bexit(EXIT_FAILURE);
  127.         }
  128.         /* create rolodeck cbase */
  129.         printf("Rolodeck does not exist.  Creating...\n");
  130.         if (cbcreate(RDNAME, sizeof(rolodeck_t), RDFLDC, rdfldv) == -1) {
  131.             fprintf(stderr, "*** Error %d creating rolodeck.\n", errno);
  132.             bexit(EXIT_FAILURE);
  133.         }
  134.         cbp = cbopen(RDNAME, "r+", RDFLDC, rdfldv);
  135.         if (cbp == NULL) {
  136.             fprintf(stderr, "*** Error %d opening rolodeck.\n", errno);
  137.             bexit(EXIT_FAILURE);
  138.         }
  139.     }
  140.     if (cbrecsize(cbp) != sizeof(rolodeck_t)) {
  141.         fprintf(stderr, "*** Panic: incorrect record size.\n");
  142.         bexit(EXIT_FAILURE);
  143.     }
  144.  
  145.     printf("\n--------------------------------------------------\n");
  146.     printf("|                    Rolodeck                    |\n");
  147.     printf("--------------------------------------------------\n\n");
  148.  
  149.     /* set sort field */
  150.     sf = RD_CONTACT;
  151.  
  152.     /* display menu */
  153.     putmenu(sf);
  154.  
  155.     /* main loop */
  156.     memset(&rd, 0, sizeof(rd));
  157.     while (1) {
  158.         printf("Enter selection:  ");
  159.         fgets(buf, sizeof(buf), stdin);
  160.         cvtss(buf, buf, CVT_X_SP | CVT_X_CTL, sizeof(buf));
  161.         rq = toupper(buf[0]);
  162.         if (rq == RD_REQ_QUIT) {    /* quit rolodeck */
  163.             break;
  164.         }
  165.         if (rq == '\0') {        /* default to next card */
  166.             rq = RD_REQ_NEXT_CARD;
  167.         }
  168.         switch (rq) {
  169.         case RD_REQ_NEXT_CARD:    /* next card */
  170.             if (rdlock(cbp, CB_RDLCK) == -1) {
  171.                 fprintf(stderr, "*** Error %d read locking rolodeck.\n", errno);
  172.                 bexit(EXIT_FAILURE);
  173.             }
  174.             if (cbreccnt(cbp) == 0) {
  175.                 printf("The rolodeck is empty.\n\n");
  176.                 if (rdlock(cbp, CB_UNLCK) == -1) {
  177.                     fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  178.                     bexit(EXIT_FAILURE);
  179.                 }
  180.                 continue;
  181.             }
  182.             /* use unique key field to set record cursor */
  183.             found = cbkeysrch(cbp, RD_CONTACT, rd.rd_contact);
  184.             if (found == -1) {
  185.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  186.                 bexit(EXIT_FAILURE);
  187.             }
  188.             /* align cursor of sort key */
  189.             if (cbkeyalign(cbp, sf) == -1) {
  190.                 fprintf(stderr, "*** Error %d aligning key.\n", errno);
  191.                 bexit(EXIT_FAILURE);
  192.             }
  193.             if (found == 1) {
  194.                 /* advance key (and rec) cursor 1 position */
  195.                 if (cbkeynext(cbp, sf) == -1) {
  196.                     fprintf(stderr, "*** Error %d finding next card.\n", errno);
  197.                     bexit(EXIT_FAILURE);
  198.                 }
  199.             }
  200.             if (cbrcursor(cbp) == NULL) {
  201.                 printf("End of deck.\n\n");
  202.                 if (rdlock(cbp, CB_UNLCK) == -1) {
  203.                     fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  204.                     bexit(EXIT_FAILURE);
  205.                 }
  206.                 continue;
  207.             }
  208.             if (cbgetr(cbp, &rd) == -1) {
  209.                 fprintf(stderr, "*** Error %d reading card.\n", errno);
  210.                 bexit(EXIT_FAILURE);
  211.             }
  212.             if (rdlock(cbp, CB_UNLCK) == -1) {
  213.                 fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  214.                 bexit(EXIT_FAILURE);
  215.             }
  216.             putcard(&rd);
  217.             break;    /* case RD_REQ_NEXT_CARD: */
  218.         case RD_REQ_PREV_CARD:    /* previous card */
  219.             if (rdlock(cbp, CB_RDLCK) == -1) {
  220.                 fprintf(stderr, "*** Error %d read locking rolodeck.\n", errno);
  221.                 bexit(EXIT_FAILURE);
  222.             }
  223.             if (cbreccnt(cbp) == 0) {
  224.                 printf("The rolodeck is empty.\n\n");
  225.                 if (rdlock(cbp, CB_UNLCK) == -1) {
  226.                     fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  227.                     bexit(EXIT_FAILURE);
  228.                 }
  229.                 continue;
  230.             }
  231.             /* use unique key field to set record cursor */
  232.             found = cbkeysrch(cbp, RD_CONTACT, rd.rd_contact);
  233.             if (found == -1) {
  234.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  235.                 bexit(EXIT_FAILURE);
  236.             }
  237.             /* align cursor of sort key */
  238.             if (cbkeyalign(cbp, sf) == -1) {
  239.                 fprintf(stderr, "*** Error %d aligning key.\n", errno);
  240.                 bexit(EXIT_FAILURE);
  241.             }
  242.             /* retreat key (and rec) cursor 1 position */
  243.             if (cbkeyprev(cbp, sf) == -1) {
  244.                 fprintf(stderr, "*** Error %d finding previous card.\n", errno);
  245.                 bexit(EXIT_FAILURE);
  246.             }
  247.             if (cbrcursor(cbp) == NULL) {
  248.                 printf("Beginning of deck.\n\n");
  249.                 if (rdlock(cbp, CB_UNLCK) == -1) {
  250.                     fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  251.                     bexit(EXIT_FAILURE);
  252.                 }
  253.                 continue;
  254.             }
  255.             if (cbgetr(cbp, &rd) == -1) {
  256.                 fprintf(stderr, "*** Error %d reading card.\n", errno);
  257.                 bexit(EXIT_FAILURE);
  258.             }
  259.             if (rdlock(cbp, CB_UNLCK) == -1) {
  260.                 fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  261.                 bexit(EXIT_FAILURE);
  262.             }
  263.             putcard(&rd);
  264.             break;    /* case RD_REQ_PREV_CARD: */
  265.         case RD_REQ_FIRST_CARD:    /* first card */
  266.             if (rdlock(cbp, CB_RDLCK) == -1) {
  267.                 fprintf(stderr, "*** Error %d read locking rolodeck.\n", errno);
  268.                 bexit(EXIT_FAILURE);
  269.             }
  270.             if (cbreccnt(cbp) == 0) {
  271.                 printf("The rolodeck is empty.\n\n");
  272.                 if(rdlock(cbp, CB_UNLCK) == -1) {
  273.                     fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  274.                     bexit(EXIT_FAILURE);
  275.                 }
  276.                 continue;
  277.             }
  278.             if (cbkeyfirst(cbp, sf) == -1) {
  279.                 fprintf(stderr, "*** Error %d finding first card.\n", errno);
  280.                 bexit(EXIT_FAILURE);
  281.             }
  282.             if (cbgetr(cbp, &rd) == -1) {
  283.                 fprintf(stderr, "*** Error %d reading card.\n", errno);
  284.                 bexit(EXIT_FAILURE);
  285.             }
  286.             if (rdlock(cbp, CB_UNLCK) == -1) {
  287.                 fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  288.                 bexit(EXIT_FAILURE);
  289.             }
  290.             putcard(&rd);
  291.             break;    /* case RD_REQ_FIRST_CARD: */
  292.         case RD_REQ_LAST_CARD:    /* last card */
  293.             if (rdlock(cbp, CB_RDLCK) == -1) {
  294.                 fprintf(stderr, "*** Error %d read locking rolodeck.\n", errno);
  295.                 bexit(EXIT_FAILURE);
  296.             }
  297.             if (cbreccnt(cbp) == 0) {
  298.                 printf("The rolodeck is empty.\n\n");
  299.                 if (rdlock(cbp, CB_UNLCK) == -1) {
  300.                     fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  301.                     bexit(EXIT_FAILURE);
  302.                 }
  303.                 continue;
  304.             }
  305.             if (cbkeylast(cbp, sf) == -1) {
  306.                 fprintf(stderr, "*** Error %d finding last card.\n", errno);
  307.                 bexit(EXIT_FAILURE);
  308.             }
  309.             if (cbgetr(cbp, &rd) == -1) {
  310.                 fprintf(stderr, "*** Error %d reading card.\n", errno);
  311.                 bexit(EXIT_FAILURE);
  312.             }
  313.             if (rdlock(cbp, CB_UNLCK) == -1) {
  314.                 fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  315.                 bexit(EXIT_FAILURE);
  316.             }
  317.             putcard(&rd);
  318.             break;    /* case RD_REQ_LAST_CARD: */
  319.         case RD_REQ_INS_CARD:    /* insert new card */
  320.             getcard(&rd);
  321.             if (strlen(rd.rd_contact) == 0) {
  322.                 printf("Contact name cannot be blank.  Card not inserted.\n\n");
  323.                 memset(&rd, 0, sizeof(rd));
  324.                 continue;
  325.             }
  326.             if (rdlock(cbp, CB_WRLCK) == -1) {
  327.                 fprintf(stderr, "*** Error %d write locking rolodeck.\n", errno);
  328.                 bexit(EXIT_FAILURE);
  329.             }
  330.             if (cbinsert(cbp, &rd) == -1) {
  331.                 if (errno == CBEDUP) {
  332.                     printf("%s is already in the rolodeck.\n\n", rd.rd_contact);
  333.                     if (rdlock(cbp, CB_UNLCK) == -1) {
  334.                         fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  335.                         bexit(EXIT_FAILURE);
  336.                     }
  337.                     continue;
  338.                 }
  339.                 fprintf(stderr, "*** Error %d inserting card.\n", errno);
  340.                 bexit(EXIT_FAILURE);
  341.             }
  342.             if (rdlock(cbp, CB_UNLCK) == -1) {
  343.                 fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  344.                 bexit(EXIT_FAILURE);
  345.             }
  346.             putcard(&rd);
  347.             break;    /* case RD_REQ_INS_CARD: */
  348.         case RD_REQ_DEL_CARD:    /* delete current card */
  349.             if (rdlock(cbp, CB_WRLCK) == -1) {
  350.                 fprintf(stderr, "*** Error %d write locking rolodeck.\n", errno);
  351.                 bexit(EXIT_FAILURE);
  352.             }
  353.             /* use unique key field to set record cursor */
  354.             found = cbkeysrch(cbp, RD_CONTACT, rd.rd_contact);
  355.             if (found == -1) {
  356.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  357.                 bexit(EXIT_FAILURE);
  358.             }
  359.             if (found == 0) {
  360.                 printf("There is no current card.\n\n");
  361.                 if (rdlock(cbp, CB_UNLCK) == -1) {
  362.                     fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  363.                     bexit(EXIT_FAILURE);
  364.                 }
  365.                 continue;
  366.             }
  367.             if (cbdelcur(cbp, sf) == -1) {
  368.                 fprintf(stderr, "*** Error %d deleting current card.\n", errno);
  369.                 bexit(EXIT_FAILURE);
  370.             }
  371.             lfmtofml(buf, rd.rd_contact, sizeof(buf));
  372.             printf("%s deleted from rolodeck.\n\n", buf);
  373.             /* load rd with card following one deleted */
  374.             if (cbrcursor(cbp) == NULL) {
  375.                 memset(&rd, 0, sizeof(rd));
  376.             } else {
  377.                 if (cbgetr(cbp, &rd) == -1) {
  378.                     fprintf(stderr, "*** Error %d reading card.\n", errno);
  379.                     bexit(EXIT_FAILURE);
  380.                 }
  381.             }
  382.             if (rdlock(cbp, CB_UNLCK) == -1) {
  383.                 fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  384.                 bexit(EXIT_FAILURE);
  385.             }
  386.             break;    /* case RD_REQ_DEL_CARD: */
  387.         case RD_REQ_SRCH_CARD:    /* search for card */
  388.             if (sf == RD_CONTACT) {
  389.                 printf("Enter contact name:  ");
  390.             } else {
  391.                 printf("Enter company name:  ");
  392.             }
  393.             if (fgets(buf, sizeof(buf), stdin) == NULL) {
  394.                 fprintf(stderr, "*** Error %d reading input.\n");
  395.                 bexit(EXIT_FAILURE);
  396.             }
  397.             cvtss(buf, buf, CVT_X_LEADSP | CVT_X_TRAILSP | CVT_ONE_SP | CVT_X_CTL, sizeof(buf));
  398.             if (sf == RD_CONTACT) {
  399.                 fmltolfm(buf, buf, sizeof(buf));
  400.             }
  401.             /* don't lock until after user input */
  402.             if (rdlock(cbp, CB_RDLCK) == -1) {
  403.                 fprintf(stderr, "*** Error %d read locking rolodeck.\n", errno);
  404.                 bexit(EXIT_FAILURE);
  405.             }
  406.             if (cbreccnt(cbp) == 0) {
  407.                 printf("The rolodeck is empty.\n\n");
  408.                 if (rdlock(cbp, CB_UNLCK) == -1) {
  409.                     fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  410.                     bexit(EXIT_FAILURE);
  411.                 }
  412.                 continue;
  413.             }
  414.             found = cbkeysrch(cbp, sf, buf);
  415.             if (found == -1) {
  416.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  417.                 bexit(EXIT_FAILURE);
  418.             }
  419.             if (found == 0) {
  420.                 printf("%s not found.\n\n", buf);
  421.                 if (cbrcursor(cbp) == NULL) {
  422.                     if (cbkeylast(cbp, sf) == -1) {
  423.                         fprintf(stderr, "*** Error %d finding last card.\n", errno);
  424.                         bexit(EXIT_FAILURE);
  425.                     }
  426.                 }
  427.             }
  428.             if (cbgetr(cbp, &rd) == -1) {
  429.                 fprintf(stderr, "*** Error %d reading card.\n", errno);
  430.                 bexit(EXIT_FAILURE);
  431.             }
  432.             if (rdlock(cbp, CB_UNLCK) == -1) {
  433.                 fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  434.                 bexit(EXIT_FAILURE);
  435.             }
  436.             putcard(&rd);
  437.             break;    /* case RD_REQ_SRCH_CARD: */
  438.         case RD_REQ_TOG_SORT:    /* toggle sort field */
  439.             switch (sf) {
  440.             case RD_CONTACT:
  441.                 sf = RD_COMPANY;
  442.                 break;
  443.             case RD_COMPANY:
  444.                 sf = RD_CONTACT;
  445.                 break;
  446.             default:
  447.                 sf = RD_CONTACT;
  448.                 break;
  449.             }
  450.             putmenu(sf);
  451.             break;    /* case RD_REQ_TOG_SORT: */
  452.         case RD_REQ_CUR_CARD:    /* display current card */
  453.             if (strlen(rd.rd_contact) == 0) {
  454.                 printf("There is no current card.\n");
  455.                 continue;
  456.             }
  457.             if (rdlock(cbp, CB_RDLCK) == -1) {
  458.                 fprintf(stderr, "*** Error %d read locking rolodeck.\n", errno);
  459.                 bexit(EXIT_FAILURE);
  460.             }
  461.             /* use unique key field to set record cursor */
  462.             found = cbkeysrch(cbp, RD_CONTACT, rd.rd_contact);
  463.             if (found == -1) {
  464.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  465.                 bexit(EXIT_FAILURE);
  466.             }
  467.             /* check if card deleted by other process */
  468.             if (found == 0) {
  469.                 printf("There is no current card.\n\n");
  470.             } else {
  471.                 if (cbgetr(cbp, &rd) == -1) {
  472.                     fprintf(stderr, "*** Error %d reading card.\n", errno);
  473.                     bexit(EXIT_FAILURE);
  474.                 }
  475.                 putcard(&rd);
  476.             }
  477.             if (rdlock(cbp, CB_UNLCK) == -1) {
  478.                 fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  479.                 bexit(EXIT_FAILURE);
  480.             }
  481.             break;    /* case RD_REQ_CUR_CARD: */
  482.         case RD_REQ_ALL_CARDS:    /* display all cards */
  483.             if (rdlock(cbp, CB_RDLCK) == -1) {
  484.                 fprintf(stderr, "*** Error %d read locking rolodeck.\n", errno);
  485.                 bexit(EXIT_FAILURE);
  486.             }
  487.             if (cbreccnt(cbp) == 0) {
  488.                 printf("The rolodeck is empty.\n\n");
  489.                 if (rdlock(cbp, CB_UNLCK) == -1) {
  490.                     fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  491.                     bexit(EXIT_FAILURE);
  492.                 }
  493.                 continue;
  494.             }
  495.             if (cbkeyfirst(cbp, sf) == -1) {
  496.                 fprintf(stderr, "*** Error %d setting key cursor.\n", errno);
  497.                 bexit(EXIT_FAILURE);
  498.             }
  499.             while (cbkcursor(cbp, sf) != NULL) {
  500.                 if (cbgetr(cbp, &rd) == -1) {
  501.                     fprintf(stderr, "*** Error %d reading card.\n", errno);
  502.                     bexit(EXIT_FAILURE);
  503.                 }
  504.                 putcard(&rd);
  505.                 if (cbkeynext(cbp, sf) == -1) {
  506.                     fprintf(stderr, "*** Error %d finding next card.\n", errno);
  507.                     bexit(EXIT_FAILURE);
  508.                 }
  509.             }
  510.             if (rdlock(cbp, CB_UNLCK) == -1) {
  511.                 fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  512.                 bexit(EXIT_FAILURE);
  513.             }
  514.             break;    /* case RD_REQ_ALL_CARDS: */
  515.         case RD_REQ_IMPORT:    /* import cards */
  516.             if (rdlock(cbp, CB_WRLCK) == -1) {
  517.                 fprintf(stderr, "*** Error %d write locking rolodeck.\n", errno);
  518.                 bexit(EXIT_FAILURE);
  519.             }
  520.             printf("Importing cards from %s....\n", EXPFILE);
  521.             if (cbimport(cbp, EXPFILE) == -1) {
  522.                 if (errno == ENOENT) {
  523.                     printf("Printable file not found.\n\n");
  524.                 } else if (errno == CBEDUP) {
  525.                     printf("Duplicate card encountered.  Import terminated.\n\n");
  526.                 } else {
  527.                     fprintf(stderr, "*** Error %d importing rolodeck from %s.\n", errno, EXPFILE);
  528.                     bexit(EXIT_FAILURE);
  529.                 }
  530.             } else {
  531.                 printf("Import complete.\n\n");
  532.             }
  533.             if (rdlock(cbp, CB_UNLCK) == -1) {
  534.                 fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  535.                 bexit(EXIT_FAILURE);
  536.             }
  537.             break;    /* cbase RD_REQ_IMPORT: */
  538.         case RD_REQ_EXPORT:    /* export cards */
  539.             if (rdlock(cbp, CB_RDLCK) == -1) {
  540.                 fprintf(stderr, "*** Error %d read locking rolodeck.\n", errno);
  541.                 bexit(EXIT_FAILURE);
  542.             }
  543.             printf("Exporting cards to %s....\n", EXPFILE);
  544.             if (cbexport(cbp, EXPFILE) == -1) {
  545.                 fprintf(stderr, "*** Error %d exporting rolodeck to %s.\n", errno, EXPFILE);
  546.                 bexit(EXIT_FAILURE);
  547.             }
  548.             printf("Export complete.\n\n");
  549.             if (rdlock(cbp, CB_UNLCK) == -1) {
  550.                 fprintf(stderr, "*** Error %d unlocking rolodeck.\n", errno);
  551.                 bexit(EXIT_FAILURE);
  552.             }
  553.             break;    /* cbase RD_REQ_EXPORT: */
  554.         case RD_REQ_HELP:    /* help */
  555.             putmenu(sf);
  556.             continue;
  557.             break;    /* case RD_REQ_HELP: */
  558.         default:
  559.             putchar('\a');    /* beep */
  560.             continue;
  561.             break;    /* default: */
  562.         }
  563.     }
  564.  
  565.     /* close cbase */
  566.     if (cbclose(cbp) == -1) {
  567.         fprintf(stderr, "*** Error %d closing rolodeck.\n", errno);
  568.         bexit(EXIT_FAILURE);
  569.     }
  570.  
  571.     exit(EXIT_SUCCESS);
  572. }
  573.  
  574. /* rdlock:  lock rolodeck */
  575. int rdlock(cbp, ltype)
  576. cbase_t *cbp;
  577. int ltype;
  578. {
  579.     int i = 0;
  580.  
  581.     for (i = 0; i < LMAXTRIES; i++) {
  582.         if (cblock(cbp, ltype) == -1) {
  583.             if (errno == EAGAIN) {
  584.                 continue;
  585.             }
  586.             return -1;
  587.         } else {
  588.             errno = 0;
  589.             return 0;
  590.         }
  591.     }
  592.  
  593.     errno = EAGAIN;
  594.     return -1;
  595. }
  596.  
  597. /* putmenu:  display menu */
  598. int putmenu(sf)
  599. int sf;
  600. {
  601.     printf("-----------------------MENU-----------------------\n");
  602.     printf("| N - Next card          P - Previous card       |\n");
  603.     printf("| F - First card         L - Last card           |\n");
  604.     printf("| I - Insert new card    D - Delete current card |\n");
  605.     printf("| S - Search for card    T - Toggle sort field   |\n");
  606.     printf("| C - display Current    A - display All cards   |\n");
  607.     printf("| M - iMport cards       X - eXport cards        |\n");
  608.     printf("| H - Help (menu)        Q - Quit                |\n");
  609.     printf("--------------------------------------------------\n");
  610.     printf("current sort field:  ");
  611.     switch (sf) {
  612.     case RD_CONTACT:
  613.         printf("contact");
  614.         break;
  615.     case RD_COMPANY:
  616.         printf("company");
  617.         break;
  618.     default:
  619.         printf("none");
  620.         break;
  621.     }
  622.     printf(".\n\n");
  623.  
  624.     return 0;
  625. }
  626.  
  627. /* getcard:  input card */
  628. int getcard(rdp)
  629. rolodeck_t *rdp;
  630. {
  631.     char buf[256];
  632.     int i = 0;
  633.  
  634.     memset(rdp, 0, sizeof(*rdp));
  635.  
  636.     printf("Contact:  ");
  637.     fgets(buf, sizeof(buf), stdin);
  638.     cvtss(buf, buf, CVT_X_LEADSP | CVT_X_TRAILSP | CVT_ONE_SP | CVT_X_CTL, sizeof(buf));
  639.     fmltolfm(rdp->rd_contact, buf, sizeof(rdp->rd_contact));
  640.     printf("Title:  ");
  641.     fgets(buf, sizeof(buf), stdin);
  642.     cvtss(rdp->rd_title, buf, CVT_X_LEADSP | CVT_X_TRAILSP | CVT_ONE_SP | CVT_X_CTL, sizeof(rdp->rd_title));
  643.     printf("Company:  ");
  644.     fgets(buf, sizeof(buf), stdin);
  645.     cvtss(rdp->rd_company, buf, CVT_X_LEADSP | CVT_X_TRAILSP | CVT_ONE_SP | CVT_X_CTL, sizeof(rdp->rd_company));
  646.     printf("Street Address (2 lines):\n");
  647.     for (i = 0; i < 2; i++) {
  648.         fgets(buf, sizeof(buf), stdin);
  649.         cvtss(buf, buf, CVT_X_LEADSP | CVT_X_TRAILSP | CVT_ONE_SP | CVT_X_CTL, sizeof(buf));
  650.         sprintf(rdp->rd_addr + 40 * i, "%-40.40s", buf);
  651.     }
  652.     printf("City:  ");
  653.     fgets(buf, sizeof(buf), stdin);
  654.     cvtss(rdp->rd_city, buf, CVT_X_LEADSP | CVT_X_TRAILSP | CVT_ONE_SP | CVT_X_CTL, sizeof(rdp->rd_city));
  655.     printf("State:  ");
  656.     fgets(buf, sizeof(buf), stdin);
  657.     cvtss(rdp->rd_state, buf, CVT_X_SP | CVT_X_CTL, sizeof(rdp->rd_state));
  658.     printf("Zip Code:  ");
  659.     fgets(buf, sizeof(buf), stdin);
  660.     cvtss(rdp->rd_zip, buf, CVT_X_SP | CVT_X_CTL, sizeof(rdp->rd_zip));
  661.     printf("Phone:  ");
  662.     fgets(buf, sizeof(buf), stdin);
  663.     cvtss(rdp->rd_phone, buf, CVT_X_SP | CVT_X_CTL, sizeof(rdp->rd_phone));
  664.     printf("Extension:  ");
  665.     fgets(buf, sizeof(buf), stdin);
  666.     cvtss(rdp->rd_ext, buf, CVT_X_SP | CVT_X_CTL, sizeof(rdp->rd_ext));
  667.     printf("Fax:  ");
  668.     fgets(buf, sizeof(buf), stdin);
  669.     cvtss(rdp->rd_fax, buf, CVT_X_SP | CVT_X_CTL, sizeof(rdp->rd_fax));
  670.     printf("Notes (4 lines):\n");
  671.     for (i = 0; i < 4; i++) {
  672.         fgets(buf, sizeof(buf), stdin);
  673.         cvtss(buf, buf, CVT_X_CTL, sizeof(buf));
  674.         sprintf(rdp->rd_notes + 40 * i, "%-40.40s", buf);
  675.     }
  676.  
  677.     return 0;
  678. }
  679.  
  680. /* putcard:  display card */
  681. int putcard(rdp)
  682. rolodeck_t *rdp;
  683. {
  684.     char name[sizeof(rdp->rd_contact)];
  685.  
  686.     lfmtofml(name, rdp->rd_contact, sizeof(name));
  687.     printf("--------------------CARD--------------------\n");
  688.     printf("| %-40.40s |\n", name);
  689.     printf("| %-40.40s |\n", rdp->rd_title);
  690.     printf("| %-40.40s |\n", rdp->rd_company);
  691.     printf("| %-40.40s |\n", rdp->rd_addr);
  692.     printf("| %-40.40s |\n", rdp->rd_addr + 40);
  693.     printf("| %-25.25s, %-2.2s %-10.10s |\n", rdp->rd_city, rdp->rd_state, rdp->rd_zip);
  694.     printf("| %-12.12s x%-4.4s  fax %-12.12s     |\n", rdp->rd_phone, rdp->rd_ext, rdp->rd_fax);
  695.     printf("| %-40.40s |\n", rdp->rd_notes);
  696.     printf("| %-40.40s |\n", rdp->rd_notes + 40);
  697.     printf("| %-40.40s |\n", rdp->rd_notes + 80);
  698.     printf("| %-40.40s |\n", rdp->rd_notes + 120);
  699.     printf("--------------------------------------------\n");
  700.  
  701.     return 0;
  702. }
  703.