Main Page | Modules | File List

kdb.c

00001 /***************************************************************************
00002                           kdb.c  -  Tool for the kdb administration
00003                              -------------------
00004     begin                : Mon Mar 02 2003
00005     copyright            : (C) 2003 by Avi Alkalay
00006     email                : avi@unix.sh
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 
00019 /* Subversion stuff
00020 
00021 $Id: kdb.c 98 2004-10-24 21:49:05Z aviram $
00022 $LastChangedBy: aviram $
00023 
00024 */
00025 
00026 
00038 #include "kdb.h"
00039 
00040 #include <sys/types.h>
00041 #include <sys/stat.h>
00042 #include <unistd.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045 #include <stdio.h>
00046 #include <grp.h>
00047 #include <pwd.h>
00048 #include <time.h>
00049 #include <ctype.h>
00050 #include <locale.h>
00051 
00052 /* FIXME: remove libXML dependencies for kdb command */
00053 #include <libxml/xmlreader.h>
00054 
00055 
00056 #define CMD_GET       1
00057 #define CMD_SET       2
00058 #define CMD_REMOVE    3
00059 #define CMD_LIST      4
00060 #define CMD_LINK      5
00061 #define CMD_EDIT      6
00062 #define CMD_LOAD      7
00063 #define CMD_SAVE      8
00064 #define CMD_MONITOR   9
00065 
00066 #define ARGSIZE      30
00067 
00068 char *argComment=0;
00069 char *argFile=0;
00070 char *argData=0;
00071 char *argKeyName=0;
00072 char *argDomain=0;
00073 uid_t *argUID=0;
00074 uid_t *argGID=0;
00075 int argCommand=0;
00076 int argRecursive=0;
00077 int argLong=0;
00078 int argValue=0;
00079 int argAll=0;
00080 int argSort=1;
00081 int argDescriptive=0;
00082 int argFullName=0;
00083 int argShow=1;
00084 int argShell=0;
00085 int argXML=0;
00086 mode_t argMode=0;
00087 int argType=KEY_TYPE_UNDEFINED;
00088 
00089 
00090 int parseCommandLine(int argc, char *argv[]) {
00091     char sargType[ARGSIZE],argUser[ARGSIZE],argGroup[ARGSIZE];
00092     char sargMode[ARGSIZE],sargCommand[ARGSIZE];
00093 
00094     int opt;
00095 
00096     int test;
00097 
00098     *sargType=*argUser=*argGroup=*sargCommand=*sargMode=0;
00099 
00100     while ((opt=getopt(argc,argv,"-t:c:u:g:m:b:raflvRdxsi"))!=-1) {
00101         switch (opt) {
00102             case 't':
00103                 strncpy(sargType,optarg,ARGSIZE);
00104                 break;
00105             case 'c':
00106                 argComment=realloc(argComment,strlen(optarg)+1);
00107                 strcpy(argComment,optarg);
00108                 break;
00109             case 'b':
00110                 argFile=realloc(argFile,strlen(optarg)+1);
00111                 strcpy(argFile,optarg);
00112                 break;
00113             case 'u':
00114                 strncpy(argUser,optarg,ARGSIZE);
00115                 break;
00116             case 'g':
00117                 strncpy(argGroup,optarg,ARGSIZE);
00118                 break;
00119             case 'm':
00120                 strncpy(sargMode,optarg,ARGSIZE);
00121                 break;
00122             case 'R':
00123                 argRecursive=KDB_O_RECURSIVE;
00124                 break;
00125             case 'l':
00126                 argLong=1;
00127                 break;
00128             case 'v':
00129                 argValue=1;
00130                 break;
00131             case 'd':
00132                 argDescriptive=1;
00133                 argLong=1;
00134                 break;
00135             case 'a':
00136                 argAll=1;
00137                 break;
00138             case 's':
00139                 argShell=1;
00140                 break;
00141             case 'f':
00142                 argFullName=1;
00143                 break;
00144             case 'n':
00145                 argSort=0;
00146                 break;
00147             case 'i':
00148                 argShow=0;
00149                 break;
00150             case 'x':
00151                 argXML=1;
00152                 break;
00153             case 1: { /* handle non '-x' args */
00154                 test=optind;
00155                 if (*sargCommand==0) { /* parse sub-command */
00156                     strncpy(sargCommand,optarg,ARGSIZE);
00157                 } else if (!argKeyName) { /* parse key name */
00158                     argKeyName=realloc(argKeyName,strlen(optarg)+1);
00159                     strcpy(argKeyName,optarg);
00160                 } else if (!argData) { /* parse value */
00161                     argData=realloc(argData,strlen(optarg)+1);
00162                     strcpy(argData,optarg);
00163                 }
00164                 break;
00165             }
00166         }
00167     }
00168     test=optind;
00169 
00170     /* Now check if we have the '--' argument, and get all its values */
00171     if (!strcmp(argv[optind-1],"--") && optind<argc) {
00172         int wordind=optind;
00173         size_t valueLength=0;
00174 
00175         while (wordind<argc) valueLength+=strlen(argv[wordind++])+1;
00176         argData=realloc(argData,valueLength);
00177         strcpy(argData,argv[optind++]);
00178         /* very ugly */
00179         while (optind<argc) sprintf(argData,"%s %s",argData,argv[optind++]);
00180     }
00181 
00182     /* End of command line argument reading. Now parse and finalize */
00183 
00184     /* Check parsed command */
00185     if (!strcmp(sargCommand,"ls")) argCommand=CMD_LIST;
00186     else if (!strcmp(sargCommand,"set")) argCommand=CMD_SET;
00187     else if (!strcmp(sargCommand,"get")) argCommand=CMD_GET;
00188     else if (!strcmp(sargCommand,"ln")) argCommand=CMD_LINK;
00189     else if (!strcmp(sargCommand,"rm")) argCommand=CMD_REMOVE;
00190     else if (!strcmp(sargCommand,"vi")) argCommand=CMD_EDIT;
00191     else if (!strcmp(sargCommand,"edit")) argCommand=CMD_EDIT;
00192     else if (!strcmp(sargCommand,"load")) argCommand=CMD_LOAD;
00193     else if (!strcmp(sargCommand,"import")) argCommand=CMD_LOAD;
00194     else if (!strcmp(sargCommand,"save")) argCommand=CMD_SAVE;
00195     else if (!strcmp(sargCommand,"export")) argCommand=CMD_SAVE;
00196     else if (!strcmp(sargCommand,"mon")) argCommand=CMD_MONITOR;
00197     else if (!strcmp(sargCommand,"monitor")) argCommand=CMD_MONITOR;
00198     else {
00199         fprintf(stderr,"Invalid subcommand\n");
00200         exit(1);
00201     }
00202 
00203     /* Parse type */
00204     if (*sargType!=0) {
00205         /* TODO: use regex */
00206         if (!strcmp(sargType,"string")) argType=KEY_TYPE_STRING;
00207         else if (!strcmp(sargType,"bin")) argType=KEY_TYPE_BINARY;
00208         else if (!strcmp(sargType,"binary")) argType=KEY_TYPE_BINARY;
00209         else if (!strcmp(sargType,"dir")) argType=KEY_TYPE_DIR;
00210         else if (!strcmp(sargType,"link")) argType=KEY_TYPE_LINK;
00211     } else if (argCommand==CMD_SET) { /* We must have a type */
00212         argType=KEY_TYPE_STRING;
00213     }
00214 
00215 
00216     /* Parse UID */
00217     if (*argUser) {
00218         if (isdigit(*argUser)) {
00219             argUID=malloc(sizeof(uid_t));
00220             *argUID=atoi(argUser);
00221         } else {
00222             struct passwd *pwd;
00223             pwd=getpwnam(argUser);
00224             if (pwd) {
00225                 argUID=malloc(sizeof(uid_t));
00226                 *argUID=pwd->pw_uid;
00227             } else {
00228                 fprintf(stderr,"kdb: Invalid user %s. Ignoring\n", argUser);
00229             }
00230         }
00231     }
00232 
00233 
00234     /* Parse GID */
00235     if (*argGroup) {
00236         if (isdigit(*argGroup)) {
00237             argGID=malloc(sizeof(gid_t));
00238             *argGID=atoi(argGroup);
00239         } else {
00240             struct group *grp;
00241             grp=getgrnam(argGroup);
00242             if (grp) {
00243                 argGID=malloc(sizeof(gid_t));
00244                 *argGID=grp->gr_gid;
00245             } else {
00246                 fprintf(stderr,"kdb: Invalid group %s. Ignoring\n",argGroup);
00247             }
00248         }
00249     }
00250 
00251 
00252 
00253     /* Parse permissions */
00254     if (*sargMode!=0) argMode=strtol(sargMode,0,8);
00255 
00256     return argCommand;
00257 }
00258 
00259 
00260 
00261 
00262 
00263 
00264 /*
00265  * Helper for the 'kdb ls' command
00266  *
00267  */
00268 void listAccess(Key *key,char *readable) {
00269     mode_t mode=keyGetAccess(key);
00270 
00271     if (S_ISDIR(mode)) readable[0]='d';
00272     else if (S_ISLNK(mode)) readable[0]='l';
00273     else readable[0]='-';
00274 
00275     readable[1] = mode & S_IRUSR ? 'r' : '-';
00276     readable[2] = mode & S_IWUSR ? 'w' : '-';
00277     readable[3] = mode & S_IXUSR ? 'x' : '-';
00278     readable[4] = mode & S_IRGRP ? 'r' : '-';
00279     readable[5] = mode & S_IWGRP ? 'w' : '-';
00280     readable[6] = mode & S_IXGRP ? 'x' : '-';
00281     readable[7] = mode & S_IROTH ? 'r' : '-';
00282     readable[8] = mode & S_IWOTH ? 'w' : '-';
00283     readable[9] = mode & S_IXOTH ? 'x' : '-';
00284     readable[10]= 0;
00285 }
00286 
00287 
00288 
00289 
00290 /*
00291  * Helper for the 'kdb ls' command
00292  *
00293  */
00294 void listTime(time_t when,char *readable) {
00295     time_t current_time=time(0);
00296     char buf[400];
00297     time_t six_months_ago;
00298     int recent;
00299 
00300     /* If the file appears to be in the future, update the current
00301        time, in case the file happens to have been modified since
00302        the last time we checked the clock.  */
00303 
00304     /* Consider a time to be recent if it is within the past six
00305        months.  A Gregorian year has 365.2425 * 24 * 60 * 60 ==
00306        31556952 seconds on the average.  Write this value as an
00307        integer constant to avoid floating point hassles.  */
00308     six_months_ago = current_time - 31556952 / 2;
00309     recent = (six_months_ago <= when) && (when <= current_time);
00310 
00311     ctime_r(&when,buf); /* buf will become "Wed Jun 30 21:49:08 1993\n" */
00312     memcpy(readable,buf+4,7); /* take only month and day */
00313     if (recent) {
00314         memcpy(readable,buf+4,12);
00315         readable[12]=0;
00316     } else {
00317         memcpy(readable,buf+4,7);
00318         readable[7]=' ';
00319         memcpy(readable+8,buf+20,4);
00320         readable[12]=0;
00321     }
00322 }
00323 
00324 
00325 
00326 /*
00327  * Helper for the 'kdb ls' command
00328  *
00329  */
00330 void listSingleKey(Key *key) {
00331     char buffer[400];
00332     char *p=buffer;
00333 
00334     if (argLong) {
00335         struct passwd *pwd;
00336         struct group *grp;
00337 
00338         listAccess(key,p);
00339         p+=strlen(p);
00340         *p=' '; p++;
00341         *p=' '; p++;
00342         *p=' '; p++;
00343 
00344         pwd=getpwuid(keyGetUID(key));
00345         strcpy(p,pwd->pw_name);
00346         p+=strlen(p);
00347         *p=' '; p++;
00348         *p=' '; p++;
00349 
00350         grp=getgrgid(keyGetGID(key));
00351         strcpy(p,grp->gr_name);
00352         p+=strlen(p);
00353         *p=' '; p++;
00354 
00355         sprintf(p,"%*d ",5,keyGetRecordSize(key));
00356         p+=strlen(p);
00357 
00358         listTime(keyGetMTime(key),p);
00359         p+=strlen(p);
00360         *p=' '; p++;
00361     }
00362     if (argFullName) keyGetFullName(key,p,sizeof(buffer)-(p-buffer));
00363     else keyGetName(key,p,sizeof(buffer)-(p-buffer));
00364     if (argValue && (keyGetDataSize(key)>0)) {
00365         u_int8_t ktype;
00366 
00367         p+=strlen(p);
00368         *p='='; p++;
00369 
00370         ktype=keyGetType(key);
00371         if (ktype >= KEY_TYPE_STRING)
00372             p+=keyGetString(key,p,sizeof(buffer)-(p-buffer));
00373         else if (ktype >= KEY_TYPE_BINARY)
00374             p+=sprintf(p,"<BINARY VALUE>");
00375         else if (ktype == KEY_TYPE_LINK)
00376             p+=keyGetLink(key,p,sizeof(buffer)-(p-buffer));
00377 
00378         *p=0;
00379     }
00380     puts(buffer);
00381 }
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00400 int commandRemove() {
00401     if (!argKeyName) {
00402         fprintf(stderr,"kdb rm: No key name\n");
00403         return -1;
00404     }
00405 
00406     if (kdbRemove(argKeyName)) {
00407         perror("kdb rm");
00408         return -1;
00409     }
00410     return 0;
00411 }
00412 
00413 
00414 
00415 
00416 
00417 
00437 int commandSet() {
00438     Key key;
00439     int ret;
00440     char error[200];
00441     size_t offset=0;
00442 
00443 
00444     /* Consistency */
00445     if (!argKeyName) {
00446         fprintf(stderr,"kdb set: No key name\n");
00447         return -1;
00448     }
00449 
00450     keyInit(&key);
00451     keySetName(&key,argKeyName);
00452     ret=kdbGetKey(&key);
00453     if (!ret) { /* key already exist. good. */
00454         if (argComment) keySetComment(&key,argComment);
00455         if (argType==KEY_TYPE_UNDEFINED) argType=keyGetType(&key);
00456     } else if (errno!=KDB_RET_NOTFOUND) {
00457         sprintf(error,"kdb set: %s",argKeyName);
00458         perror(error);
00459     }
00460 
00461     if (argUID) keySetUID(&key,*argUID);
00462     if (argGID) keySetGID(&key,*argGID);
00463 
00464     if (argMode) keySetAccess(&key,argMode);
00465 
00466     if (argFile) {
00467         FILE *f;
00468         int end=0;
00469         
00470         if (argData) free(argData);
00471         argData=0;
00472         f=fopen(argFile,"r");
00473         
00474         if (!f) {
00475             sprintf(error,"kdb set: %s",argFile);
00476             perror(error);
00477             return -1;
00478         }
00479         while (! end) {
00480             char buffer[100];
00481             ssize_t r;
00482             
00483             r=read(fileno(f),buffer,sizeof(buffer));
00484             if (r == 0) {
00485                 r=lseek(fileno(f),0,SEEK_END)-offset;
00486                 end=1;
00487             }
00488             argData=realloc(argData,offset+r);
00489             memcpy(argData+offset,buffer,r);
00490             offset+=r;
00491         }
00492         fclose(f);
00493     }
00494     
00495     switch (argType) {
00496         case KEY_TYPE_DIR: keySetType(&key,KEY_TYPE_DIR);
00497             break;
00498         case KEY_TYPE_STRING:
00499             if (argData) keySetString(&key,argData);
00500             break;
00501         case KEY_TYPE_BINARY:
00502             if (argData) {
00503                 if (offset) keySetBinary(&key,argData,offset);
00504                 else keySetBinary(&key,argData,strblen(argData));
00505             }
00506             break;
00507         case KEY_TYPE_LINK: keySetLink(&key,argData);
00508             break;
00509     }
00510 
00511     ret=kdbSetKey(&key);
00512     if (ret) {
00513         sprintf(error,"kdb set: %s",argKeyName);
00514         perror(error);
00515     }
00516     return ret;
00517 }
00518 
00519 
00520 
00521 
00522 
00523 
00537 int commandLink() {
00538     int rc;
00539 
00540     /* Consistency */
00541     if (!argKeyName) {
00542         fprintf(stderr,"kdb ln: No target specified\n");
00543         return -1;
00544     }
00545 
00546     if (!argData) {
00547         fprintf(stderr,"kdb ln: %s: No destination specified",argKeyName);
00548         return -1;
00549     }
00550 
00551     if ((rc=kdbLink(argKeyName,argData))) {
00552         perror("kdb ln");
00553     }
00554 
00555     return rc;
00556 }
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00594 int commandList() {
00595     KeySet ks;
00596     Key *key=0;
00597     int ret;
00598 
00599     ksInit(&ks);
00600 
00601     if (!argKeyName) {
00602         KeySet roots;
00603         /* User don't want a specific key, so list the root keys */
00604 
00605         ksInit(&roots);
00606         kdbGetRootKeys(&roots);
00607 
00608         if (argRecursive) {
00609             key=roots.start;
00610             while (key) {
00611                 char rootName[200];
00612                 KeySet thisRoot;
00613                 Key *temp;
00614 
00615                 ksInit(&thisRoot);
00616                 keyGetFullName(key,rootName,sizeof(rootName));
00617                 if (argValue) ret=kdbGetChildKeys(rootName,&thisRoot,
00618                     (argSort?KDB_O_SORT:0) | argRecursive | KDB_O_DIR |
00619                     (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00620                 else ret=kdbGetChildKeys(rootName,&thisRoot,
00621                     (argSort?KDB_O_SORT:0) | KDB_O_STATONLY | argRecursive |
00622                     KDB_O_DIR | (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00623                 temp=key->next;
00624                 ksAppend(&ks,key);
00625                 ksAppendKeys(&ks,&thisRoot);
00626                 key=temp;
00627             }
00628         } else ksAppendKeys(&ks,&roots);
00629     } else {
00630         /* User gave us a specific key to start with */
00631 
00632         if (argValue) ret=kdbGetChildKeys(argKeyName,&ks,
00633             (argSort?KDB_O_SORT:0) | argRecursive | KDB_O_DIR |
00634             (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00635         else ret=kdbGetChildKeys(argKeyName,&ks,
00636             (argSort?KDB_O_SORT:0) | KDB_O_STATONLY | argRecursive |
00637             KDB_O_DIR | (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00638     
00639         if (ret) {
00640                 /* We got an error. Check if it is because its not a folder key */
00641             if (errno==ENOTDIR) {
00642                 /* We still have a chance, since there is something there */
00643                 key=(Key *)malloc(sizeof(Key));
00644                 keyInit(key);
00645                 keySetName(key,argKeyName);
00646                 if (argValue) ret=kdbGetKey(key);
00647                 else ret=kdbStatKey(key);
00648                 if (ret) {
00649                     char error[200];
00650 
00651                     keyClose(key); free(key);
00652                     ksClose(&ks);
00653                     
00654                     sprintf(error,"kdb ls: %s",argKeyName);
00655                     perror(error);
00656                     return ret;
00657                 }
00658             } else { /* A real error */
00659                 char error[200];
00660                 
00661                 ksClose(&ks);
00662 
00663                 sprintf(error,"kdb ls: %s",argKeyName);
00664                 perror(error);
00665                 return ret;
00666             }
00667         }
00668     }
00669 
00670     if (argShow) {
00671         if (argXML) {
00672             if (key) keyToStream(key,stdout,0);
00673             else if (ks.size)
00674                 ksToStream(&ks,stdout,KDB_O_XMLHEADERS);
00675         } else {
00676             if (key) listSingleKey(key);
00677             else if (ks.size) {
00678                 ksRewind(&ks);
00679                 while ((key=ksNext(&ks)))
00680                     listSingleKey(key);
00681             }
00682         }
00683     }
00684 
00685     ksClose(&ks);
00686     if (key) {
00687             keyClose(key);
00688             free(key);
00689     }
00690     return 0;
00691 }
00692 
00693 
00694 
00695 
00696 
00697 
00698 
00721 int commandGet() {
00722     int ret;
00723     Key key;
00724     char *buffer;
00725     char *p;
00726     size_t size,cs=0;
00727     u_int8_t keyType;
00728 
00729     if (!argKeyName) {
00730         fprintf(stderr,"kdb get: No key name\n");
00731         return -1;
00732     }
00733 
00734     keyInit(&key);
00735     keySetName(&key,argKeyName);
00736 
00737     ret=kdbGetKey(&key);
00738     if (ret) {
00739         char error[200];
00740 
00741         sprintf(error,"kdb get: %s",argKeyName);
00742         perror(error);
00743         return ret;
00744     }
00745     size=keyGetDataSize(&key);
00746     if (argDescriptive) {
00747         cs=keyGetCommentSize(&key);
00748         if (cs) size+=cs+3;
00749     }
00750     if (argShell) {
00751         size+=keyGetBaseNameSize(&key);
00752         size+=2; /* for 2 '"' to wrap the value */
00753     } else if (argLong) {
00754         if (argFullName) size+=keyGetFullNameSize(&key);
00755         else size+=keyGetNameSize(&key);
00756     }
00757 
00758 
00759     p=buffer=malloc(size);
00760 
00761 
00762     if (argDescriptive) {
00763         if (cs) {
00764             p+=sprintf(p,"# ");
00765             p+=keyGetComment(&key,p,size-(p-buffer));
00766             *--p='\n'; p++;
00767         }
00768     }
00769     if (argShell) {
00770         p+=keyGetBaseName(&key,p,size-(p-buffer));
00771         *--p='='; p++;
00772         *p='\"'; p++;
00773     } else if (argLong) {
00774         if (argFullName) p+=keyGetFullName(&key,p,size-(p-buffer));
00775         else p+=keyGetName(&key,p,size-(p-buffer));
00776         *--p='='; p++;
00777     }
00778     
00779     keyType=keyGetType(&key);
00780 
00781     if (keyType<KEY_TYPE_STRING) p+=keyGetBinary(&key,p,size-(p-buffer));
00782     else p+=keyGetString(&key,p,size-(p-buffer));
00783     if (argShell) {
00784         *--p='\"'; p++;
00785         *p=0;
00786     }
00787     if (keyType<KEY_TYPE_STRING) fwrite(buffer,size,1,stdout);
00788     else printf("%s\n",buffer);
00789 
00790 
00791     free(buffer);
00792 
00793     return 0;
00794 }
00795 
00796 
00797 
00798 
00799 
00800 
00801 
00802 
00803 
00804 
00805 
00806 /*
00807  * This function is completelly dependent on libxml.
00808  */
00809 int processNode(KeySet *ks, xmlTextReaderPtr reader) {
00810     xmlChar *nodeName=0;
00811     xmlChar *buffer=0;
00812     Key *newKey=0;
00813     
00814     nodeName=xmlTextReaderName(reader);
00815     if (!strcmp(nodeName,"key")) {
00816         int end=0;
00817         
00818         newKey=malloc(sizeof(Key));
00819         keyInit(newKey);
00820         
00821         xmlFree(nodeName); nodeName=0;
00822         
00823         buffer=xmlTextReaderGetAttribute(reader,"name");
00824         keySetName(newKey,(char *)buffer);
00825         xmlFree(buffer); buffer=0;
00826         
00827         buffer=xmlTextReaderGetAttribute(reader,"type");
00828         if (!strcmp(buffer,"string"))
00829             keySetType(newKey,KEY_TYPE_STRING);
00830         else if (!strcmp(buffer,"binary"))
00831             keySetType(newKey,KEY_TYPE_BINARY);
00832         else if (!strcmp(buffer,"link"))
00833             keySetType(newKey,KEY_TYPE_LINK);
00834         else if (!strcmp(buffer,"directory"))
00835             keySetType(newKey,KEY_TYPE_DIR);
00836         xmlFree(buffer); buffer=0;
00837 
00838         
00839         /* Parse UID */
00840         buffer=xmlTextReaderGetAttribute(reader,"uid");
00841         if (isdigit(*buffer)) {
00842             keySetUID(newKey,atoi(buffer));
00843         } else {
00844             struct passwd *pwd;
00845             pwd=getpwnam(buffer);
00846             if (pwd) keySetUID(newKey,pwd->pw_uid);
00847             else fprintf(stderr,"kdb: Ignoring invalid user %s.\n", buffer);
00848         }
00849         xmlFree(buffer); buffer=0;
00850 
00851         
00852         /* Parse GID */
00853         buffer=xmlTextReaderGetAttribute(reader,"gid");
00854         if (isdigit(*buffer)) {
00855             keySetGID(newKey,atoi(buffer));
00856         } else {
00857             struct group *grp;
00858             grp=getgrnam(buffer);
00859             if (grp) keySetGID(newKey,grp->gr_gid);
00860             else fprintf(stderr,"kdb: Ignoring invalid group %s.\n",buffer);
00861         }
00862         xmlFree(buffer); buffer=0;
00863 
00864 
00865         /* Parse permissions */
00866         buffer=xmlTextReaderGetAttribute(reader,"mode");
00867         if (buffer) keySetAccess(newKey,strtol(buffer,0,8));
00868         xmlFree(buffer); buffer=0;
00869 
00870 
00871         /* Parse everything else */
00872         while (!end) {
00873             xmlFree(nodeName); nodeName=0;
00874             xmlTextReaderRead(reader);
00875             nodeName=xmlTextReaderName(reader);
00876 
00877             if (!strcmp(nodeName,"value")) {
00878                 if (xmlTextReaderIsEmptyElement(reader) ||
00879                     xmlTextReaderNodeType(reader)==15) continue;
00880                 xmlTextReaderRead(reader);
00881                 buffer=xmlTextReaderValue(reader);
00882                 if (buffer) {
00883                     switch (keyGetType(newKey)) {
00884                         case KEY_TYPE_STRING:
00885                             keySetString(newKey,buffer);
00886                             break;
00887                         case KEY_TYPE_BINARY:
00888                             keySetBinary(newKey,buffer,strlen(buffer)+1);
00889                             break;
00890                         case KEY_TYPE_LINK:
00891                             keySetLink(newKey,buffer);
00892                             break;
00893                     }
00894                 }
00895             } else if (!strcmp(nodeName,"comment")) {
00896                 if (xmlTextReaderIsEmptyElement(reader) ||
00897                     xmlTextReaderNodeType(reader)==15) continue;
00898                 xmlTextReaderRead(reader);
00899                 buffer=xmlTextReaderValue(reader);
00900 
00901                 keySetComment(newKey,buffer);
00902             } else if (!strcmp(nodeName,"key")) {
00903                 if (xmlTextReaderNodeType(reader)==15) end=1;
00904             }
00905 
00906             xmlFree(buffer); buffer=0;
00907         }
00908     }
00909 
00910     if (nodeName) xmlFree(nodeName),nodeName=0;
00911 
00912     if (newKey) ksAppend(ks,newKey);
00913     return 0;
00914 }
00915 
00916 
00917 
00918 
00919 
00920 
00921 /*
00922  * This function is completelly dependent on libxml.
00923  * It is the workhorse for ksFromXML() and ksFromXMLfile()
00924  */
00925 int ksFromXMLReader(KeySet *ks,xmlTextReaderPtr reader) {
00926     int ret;
00927 
00928     ret = xmlTextReaderRead(reader); /* <keyset> */
00929     ret = xmlTextReaderRead(reader); /* first <key> */
00930     while (ret == 1) {
00931         processNode(ks, reader);
00932         ret = xmlTextReaderRead(reader);
00933     }
00934     xmlFreeTextReader(reader);
00935     if (ret) fprintf(stderr,"kdb: Failed to parse XML input\n");
00936 
00937     return ret;
00938 }
00939 
00940 
00941 
00942 
00943 
00944 
00945 
00946 
00947 
00948 int ksFromXMLfile(KeySet *ks,char *filename) {
00949     xmlTextReaderPtr reader;
00950     int ret;
00951 
00952     reader = xmlNewTextReaderFilename(filename);
00953     if (reader) {
00954         ret=ksFromXMLReader(ks,reader);
00955     } else {
00956         perror("kdb");
00957         return 1;
00958     }
00959     return ret;
00960 }
00961 
00962 
00963 
00964 
00965 
00966 /* FIXME: its not working when fd is stdin */
00967 int ksFromXML(KeySet *ks,int fd) {
00968     /* Support for old XML library, that doesn't have xmlReaderForFd() */
00969     char filename[]="/var/tmp/rgeditXXXXXX";
00970     FILE *xmlfile=0;
00971     xmlfile=fdopen(mkstemp(filename),"rw+");
00972     while (! feof(xmlfile)) {
00973         char buffer[1000];
00974         ssize_t readed, writen;
00975 
00976         readed=read(fd,buffer,sizeof(buffer));
00977         if (readed<0) {
00978             perror("kdb");
00979             fclose(xmlfile);
00980             remove(filename);
00981             return 1;
00982         }
00983 
00984         writen=write(fileno(xmlfile),buffer,readed);
00985         if (writen<0) {
00986             perror("kdb");
00987             fclose(xmlfile);
00988             remove(filename);
00989             return 1;
00990         }
00991     }
00992     fclose(xmlfile);
00993     return ksFromXMLfile(ks,filename);
00994     /* end of support */
00995 
00996     /* This code requires a newer version of XML library. Don't use it yet
00997     // a complete XML document is expected
00998     xmlTextReaderPtr reader=0;
00999     int ret;
01000     reader=xmlReaderForFd(fd,"file:/tmp/imp.xml",0,0);
01001     if (reader) {
01002         ret=ksFromXMLReader(ks,reader);
01003     } else {
01004         printf("kdb: Unable to open file descriptor %d for XML reading\n", fd);
01005         return 1;
01006     }
01007     return ret;
01008     // end of newer code */
01009 }
01010 
01011 
01012 
01013 
01014 
01015 
01016 
01017 
01018 
01019 
01020 
01021 
01022 
01023 
01024 
01025 
01026 
01057 int commandEdit() {
01058     KeySet ks;
01059     KeySet ksEdited;
01060     KeySet toRemove;
01061     Key *current;
01062     int ret;
01063     char filename[]="/var/tmp/rgeditXXXXXX";
01064     char command[300];
01065     FILE *xmlfile=0;
01066 
01067     ksInit(&ks);
01068 
01069     kdbGetChildKeys(argKeyName,&ks, KDB_O_SORT | KDB_O_NFOLLOWLINK |
01070         (argAll?KDB_O_INACTIVE:0) | (argRecursive?KDB_O_RECURSIVE:0));
01071 
01072     if (!ks.size) {
01073         /* Maybe the user parameter is not a parent key, but a single key */
01074         current=malloc(sizeof(Key));
01075         keyInit(current);
01076         keySetName(current,argKeyName);
01077         if (kdbGetKey(current)) {
01078             /* Failed. Cleanup */
01079             keyClose(current);
01080             free(current);
01081             current=0;
01082         } else {
01083             /* We have something. */
01084             ksAppend(&ks,current);
01085             current=0;
01086         }
01087     }
01088 
01089 /*
01090     for (current=ks.start; current; current=current->next) {
01091         if (keyNeedsSync(current)) {
01092             printf("%s needs sync\n",current->key);
01093         }
01094     }
01095 */
01096 
01097     xmlfile=fdopen(mkstemp(filename),"rw+");
01098 
01099     ksToStream(&ks,xmlfile,KDB_O_XMLHEADERS);
01100     fclose(xmlfile);
01101 
01102     sprintf(command,"[ -z \"$EDITOR\" ] && EDITOR=vi; $EDITOR %s",filename);
01103     system(command);
01104 
01105     ksInit(&toRemove);
01106     ksInit(&ksEdited);
01107 
01108     /* ksFromXML is not a library function.
01109      * It is implemented in and for this program only.
01110    *       It is pretty reusable code, though.
01111      */
01112     ksFromXMLfile(&ksEdited,filename);
01113     remove(filename);
01114 
01115     ksCompare(&ks,&ksEdited,&toRemove);
01116 
01117     ksRewind(&ks);
01118     ret=kdbSetKeys(&ks);
01119     if (ret != 0) {
01120         Key *problem;
01121         char error[500];
01122         char keyname[300]="";
01123         
01124         problem=ksCurrent(&ks);
01125         if (problem) keyGetFullName(problem,keyname,sizeof(keyname));
01126         sprintf(error,"kdb edit: when commiting %s",keyname);
01127         perror(error);
01128     }
01129 
01130     ksRewind(&toRemove);
01131     while ((current=ksNext(&toRemove))) {
01132         char keyName[800];
01133 
01134         keyGetFullName(current,keyName,sizeof(keyName));
01135         kdbRemove(keyName);
01136     }
01137 
01138     return 0;
01139 }
01140 
01141 
01142 
01143 
01158 int commandImport() {
01159     KeySet ks;
01160     int ret;
01161 
01162     ksInit(&ks);
01163     /* The command line parsing function will put the XML filename
01164        in the argKeyName global, so forget the variable name. */
01165     if (argKeyName) ksFromXMLfile(&ks,argKeyName);
01166     else ksFromXML(&ks,fileno(stdin) /* more elegant then just '0' */);
01167 
01168     ksRewind(&ks);
01169     ret=kdbSetKeys(&ks);
01170     
01171     if (ret != 0) {
01172         Key *problem;
01173         char error[500];
01174         char keyname[300]="";
01175         
01176         problem=ksCurrent(&ks);
01177         if (problem) keyGetFullName(problem,keyname,sizeof(keyname));
01178         sprintf(error,"kdb import: when commiting %s",keyname);
01179         perror(error);
01180     }
01181     
01182     return ret;
01183 }
01184 
01185 
01186 
01187 
01188 
01206 int commandExport() {
01207 
01208     /* Equivalent to 'kdb ls -xRv
01209        So lets mimic and reuse code */
01210 
01211     argSort=1;
01212     argRecursive=1;
01213     argAll=1;
01214     argXML=1;
01215     argShow=1;
01216     argValue=1;
01217     argFullName=1;
01218 
01219     /* force UTF-8 for a superuniversal charset */
01220     setenv("LANG","en_US.UTF-8",1);
01221     
01222     /* reopen key database to forced charset to take effect */
01223     kdbClose();
01224     kdbOpen();
01225 
01226     return commandList();
01227 }
01228 
01229 
01244 int commandMonitor() {
01245     Key toMonitor;
01246     u_int32_t diff;
01247     char *newData=0;
01248     size_t dataSize;
01249     
01250     keyInit(&toMonitor);
01251     keySetName(&toMonitor,argKeyName);
01252     kdbGetKey(&toMonitor);
01253     
01254     diff=kdbMonitorKey(
01255         &toMonitor,          /* key to monitor */
01256         KEY_FLAG_HASDATA,    /* particular info from the key we are interested */
01257         0,                   /* how many times to poll. 0 = ad-infinitum */
01258         500                  /* usecs between polls. 0 defaults to 1 second */);
01259 
01260     /*
01261      * Since in our case we'll hang completelly until we get a key's
01262      * value change, we don't have to check diff.
01263      * So if method returned, the value has changed, and toMonitor has it.
01264      */
01265     newData=malloc(dataSize=keyGetDataSize(&toMonitor));
01266     keyGetString(&toMonitor,newData,dataSize);
01267     printf("New value is %s\n",newData);
01268     return 0;
01269 }
01270 
01271 
01272 int doCommand(int command) {
01273     switch (command) {
01274         case CMD_SET:             return commandSet();
01275         case CMD_LIST:            return commandList();
01276         case CMD_LINK:            return commandLink();
01277         case CMD_GET:             return commandGet();
01278         case CMD_REMOVE:          return commandRemove();
01279         case CMD_EDIT:            return commandEdit();
01280         case CMD_LOAD:            return commandImport();
01281         case CMD_SAVE:            return commandExport();
01282         case CMD_MONITOR:         return commandMonitor();
01283     }
01284     return 0;
01285 }
01286 
01287 
01288 int main(int argc, char **argv) {
01289     int command=0;
01290     int ret=0;
01291 
01292     command=parseCommandLine(argc,argv);
01293 
01294     kdbOpen();
01295     ret=doCommand(command);
01296     kdbClose();
01297 
01298     return ret;
01299 }
01300 

Generated on Thu Aug 4 03:37:07 2005 for Elektra Project by doxygen 1.3.5