Section 25.5. Example

   


25.5. Example

To help make all of this more concrete, here is a sample application that makes use of most of qdbm's features. It is intended as a simple phone database, although it can be used to store any simple name/value pairs. It stores its database in the user's home directory as .phonedb.

The -a flag adds an entry to the database. If -f is specified, any existing entry is overwritten with the new data. The next parameter is the key value to use, and the last parameter is the data (usually a phone number).

The -q flag queries the database for a particular key, which should be the only other parameter specified. Entries are removed from the database through the -d flag, which takes the key value to remove as the only other parameter.

If -l is specified, all the key/value pairs in the database are listed.

Here is an example of using phones:

 $ ./phones -a Erik 374-5876 $ ./phones -a Michael 642-4235 $ ./phones -a Larry 527-7976 $ ./phones -a Barbara 227-2272 $ ./phones -q Larry Larry 527-7976 $ ./phones -l Larry 527-7976 Erik 374-5876 Michael 642-4235 Barbara 227-2272 $ ./phones -d Michael $ ./phones -l Larry 527-7976 Erik 374-5876 Barbara 227-2272 


This program does something quite useful, has fewer than 200 lines of source code, and is well suited to managing large numbers of key/value pairs, clearly illustrating the value of the qdbm library.

   1: /* phones.c */   2:   3: /* This implements a very simple phone database. Full usage   4:    information is given in the text. */   5:   6: #include <alloca.h>   7: #include <depot.h>   8: #include <errno.h>   9: #include <fcntl.h>  10: #include <stdio.h>  11: #include <stdlib.h>  12: #include <string.h>  13: #include <unistd.h>  14:  15: void usage(void) {  16:     fprintf(stderr, "usage: phones -a [-f] <name> <phone>\n");  17:     fprintf(stderr, "              -d <name>\n");  18:     fprintf(stderr, "              -q <name>\n");  19:     fprintf(stderr, "              -l\n");  20:     exit(1);  21: }  22:  23: /* Opens the database $HOME/.phonedb. If writeable is nonzero,  24:    the database is opened for updating. If writeable is 0, the  25:    database is opened read-only. */  26: DEPOT * openDatabase(int writeable) {  27:     DEPOT * dp;  28:     char * filename;  29:     int flags;  30:  31:     /* Set the open mode */  32:     if (writeable) {  33:         flags = DP_OWRITER | DP_OCREAT;  34:     } else {  35:         flags = DP_OREADER;  36:     }  37:  38:     filename = alloca(strlen(getenv("HOME")) + 20);  39:     strcpy(filename, getenv("HOME"));  40:     strcat(filename, "/.phonedb");  41:  42:     dp = dpopen(filename, flags, 0);  43:     if (!dp) {  44:         fprintf(stderr, "failed to open %s: %s\n", filename,  45:                 dperrmsg(dpecode));  46:         return NULL;  47:     }  48:  49:     return dp;  50: }  51:  52: /* add a new record to the database; this parses the  53:    command-line arguments directly */  54: int addRecord(int argc, char ** argv) {  55:     DEPOT * dp;  56:     char * name, * phone;  57:     int rc = 0;  58:     int overwrite = 0;  59:     int flag;  60:  61:     /* check for our parameters; -f means overwrite an  62:        existing entry, and the name and phone number should  63:        be all that remains */  64:     if (!argc) usage();  65:     if (!strcmp(argv[0], "-f")) {  66:         overwrite = 1;  67:         argc--, argv++;  68:     }  69:  70:     if (argc != 2) usage();  71:  72:     name = argv[0];  73:     phone = argv[1];  74:  75:     /* open the database for writing */  76:     if (!(dp = openDatabase(1))) return 1;  77:  78:     /* if we shouldn't overwrite an existing entry, check  79:        to see if this name is already used */  80:     if (!overwrite) {  81:         flag = DP_DKEEP;  82:     } else {  83:         flag = DP_DOVER;  84:     }  85:  86:     if (!dpput(dp, name, -1, phone, -1, flag)) {  87:         if (dpecode == DP_EKEEP) {  88:             fprintf(stderr, "%s already has a listing\n", name);  89:         } else {  90:             fprintf(stderr, "put failed: %s\n", dperrmsg(dpecode));  91:         }  92:  93:         rc = 1;  94:     }  95:  96:     dpclose(dp);  97:  98:     return rc;  99: } 100: 101: /* looks up a name, and prints the phone number associated 102:    with it; parses the command line directly */ 103: int queryRecord(int argc, char ** argv) { 104:     DEPOT * dp; 105:     int rc; 106:     char * phone; 107: 108:     /* only one argument is expected, a name to look up */ 109:     if (argc != 1) usage(); 110: 111:     /* open the database for reading */ 112:     if (!(dp = openDatabase(0))) return 1; 113: 114:     phone = dpget(dp, argv[0], -1, 0, -1, NULL); 115:     if (!phone) { 116:         if (dpecode == DP_ENOITEM) 117:             fprintf(stderr, "%s is not listed\n", argv[0]); 118:         else 119:             fprintf(stderr, "error reading database: %s\n", 120:                     dperrmsg(dpecode)); 121: 122:         rc = 1; 123:     } else { 124:         printf("%s %s\n", argv[0], (char *) phone); 125:         rc = 0; 126:     } 127: 128:     dpclose(dp); 129: 130:     return rc; 131: } 132: 133: /* delete the specified record; the name is passed as a 134:    command-line argument */ 135: int delRecord(int argc, char ** argv) { 136:     DEPOT * dp; 137:     int rc; 138: 139:     /* only a single argument is expected */ 140:     if (argc != 1) usage(); 141: 142:     /* open the database for updating */ 143:     if (!(dp = openDatabase(1))) return 1; 144: 145:     if (!(rc = dpout(dp, argv[0], -1))) { 146:         if (dpecode == DP_ENOITEM) 147:             fprintf(stderr, "%s is not listed\n", argv[0]); 148:         else 149:             fprintf(stderr, "error removing item: %s\n", 150:                     dperrmsg(dpecode)); 151: 152:         rc = 1; 153:     } 154: 155:     dpclose(dp); 156: 157:     return rc; 158: } 159: 160: /* lists all of the records in the database */ 161: int listRecords(void) { 162:     DEPOT * dp; 163:     char * key, * value; 164: 165:     /* open the database read-only */ 166:     if (!(dp = openDatabase(0))) return 1; 167: 168:     dpiterinit(dp); 169: 170:     /* iterate over all of the records */ 171:     while ((key = dpiternext(dp, NULL))) { 172:         value = dpget(dp, key, -1, 0, -1, NULL); 173:         printf("%s %s\n", key, value); 174:     } 175: 176:     dpclose(dp); 177: 178:     return 0; 179: } 180: 181: int main(int argc, char ** argv) { 182:     if (argc == 1) usage(); 183: 184:     /* look for a mode flag, and call the appropriate function 185:        with the remainder of the arguments */ 186:     if (!strcmp(argv[1], "-a")) 187:         return addRecord(argc - 2, argv + 2); 188:     else if (!strcmp(argv[1], "-q")) 189:         return queryRecord(argc - 2, argv + 2); 190:     else if (!strcmp(argv[1], "-d")) 191:         return delRecord(argc - 2, argv + 2); 192:     else if (!strcmp(argv[1], "-l")) { 193:         if (argc != 2) usage(); 194:         return listRecords(); 195:     } 196: 197:     usage();  /* did not recognize any options */ 198:     return 0; /* doesn't get here due to usage() */ 199: } 



       
    top
     


    Linux Application Development
    Linux Application Development (paperback) (2nd Edition)
    ISBN: 0321563220
    EAN: 2147483647
    Year: 2003
    Pages: 168

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net