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 54 2004-08-31 10:40:22Z 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 */
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 *argData=0;
00070 char *argKeyName=0;
00071 char *argDomain=0;
00072 uid_t *argUID=0;
00073 uid_t *argGID=0;
00074 int argCommand=0;
00075 int argRecursive=0;
00076 int argLong=0;
00077 int argValue=0;
00078 int argAll=0;
00079 int argSort=1;
00080 int argDescriptive=0;
00081 int argFullName=0;
00082 int argShow=1;
00083 int argShell=0;
00084 int argXML=0;
00085 mode_t argMode=0;
00086 int argType=KEY_TYPE_UNDEFINED;
00087 
00088 
00089 int parseCommandLine(int argc, char *argv[]) {
00090     char sargType[ARGSIZE],argUser[ARGSIZE],argGroup[ARGSIZE];
00091     char sargMode[ARGSIZE],sargCommand[ARGSIZE];
00092 
00093     int opt;
00094 
00095     int test;
00096 
00097     *sargType=*argUser=*argGroup=*sargCommand=*sargMode=0;
00098 
00099     while ((opt=getopt(argc,argv,"-t:c:u:g:m:raflvRdxsi"))!=-1) {
00100         switch (opt) {
00101             case 't':
00102                 strncpy(sargType,optarg,ARGSIZE);
00103                 break;
00104             case 'c':
00105                 argComment=realloc(argComment,strlen(optarg)+1);
00106                 strcpy(argComment,optarg);
00107                 break;
00108             case 'u':
00109                 strncpy(argUser,optarg,ARGSIZE);
00110                 break;
00111             case 'g':
00112                 strncpy(argGroup,optarg,ARGSIZE);
00113                 break;
00114             case 'm':
00115                 strncpy(sargMode,optarg,ARGSIZE);
00116                 break;
00117             case 'R':
00118                 argRecursive=KDB_O_RECURSIVE;
00119                 break;
00120             case 'l':
00121                 argLong=1;
00122                 break;
00123             case 'v':
00124                 argValue=1;
00125                 break;
00126             case 'd':
00127                 argDescriptive=1;
00128                 argLong=1;
00129                 break;
00130             case 'a':
00131                 argAll=1;
00132                 break;
00133             case 's':
00134                 argShell=1;
00135                 break;
00136             case 'f':
00137                 argFullName=1;
00138                 break;
00139             case 'n':
00140                 argSort=0;
00141                 break;
00142             case 'i':
00143                 argShow=0;
00144                 break;
00145             case 'x':
00146                 argXML=1;
00147                 break;
00148             case 1: { /* handle non '-x' args */
00149                 test=optind;
00150                 if (*sargCommand==0) { /* parse sub-command */
00151                     strncpy(sargCommand,optarg,ARGSIZE);
00152                 } else if (!argKeyName) { /* parse key name */
00153                     argKeyName=realloc(argKeyName,strlen(optarg)+1);
00154                     strcpy(argKeyName,optarg);
00155                 } else if (!argData) { /* parse value */
00156                     argData=realloc(argData,strlen(optarg)+1);
00157                     strcpy(argData,optarg);
00158                 }
00159                 break;
00160             }
00161         }
00162     }
00163     test=optind;
00164 
00165     /* Now check if we have the '--' argument, and get all its values */
00166     if (!strcmp(argv[optind-1],"--") && optind<argc) {
00167         int wordind=optind;
00168         size_t valueLength=0;
00169 
00170         while (wordind<argc) valueLength+=strlen(argv[wordind++])+1;
00171         argData=realloc(argData,valueLength);
00172         strcpy(argData,argv[optind++]);
00173         /* very ugly */
00174         while (optind<argc) sprintf(argData,"%s %s",argData,argv[optind++]);
00175     }
00176 
00177     /* End of command line argument reading. Now parse and finalize */
00178 
00179     /* Check parsed command */
00180     if (!strcmp(sargCommand,"ls")) argCommand=CMD_LIST;
00181     else if (!strcmp(sargCommand,"set")) argCommand=CMD_SET;
00182     else if (!strcmp(sargCommand,"get")) argCommand=CMD_GET;
00183     else if (!strcmp(sargCommand,"ln")) argCommand=CMD_LINK;
00184     else if (!strcmp(sargCommand,"rm")) argCommand=CMD_REMOVE;
00185     else if (!strcmp(sargCommand,"vi")) argCommand=CMD_EDIT;
00186     else if (!strcmp(sargCommand,"edit")) argCommand=CMD_EDIT;
00187     else if (!strcmp(sargCommand,"load")) argCommand=CMD_LOAD;
00188     else if (!strcmp(sargCommand,"import")) argCommand=CMD_LOAD;
00189     else if (!strcmp(sargCommand,"save")) argCommand=CMD_SAVE;
00190     else if (!strcmp(sargCommand,"export")) argCommand=CMD_SAVE;
00191     else if (!strcmp(sargCommand,"mon")) argCommand=CMD_MONITOR;
00192     else if (!strcmp(sargCommand,"monitor")) argCommand=CMD_MONITOR;
00193     else {
00194         fprintf(stderr,"Invalid subcommand\n");
00195         exit(1);
00196     }
00197 
00198     /* Parse type */
00199     if (*sargType!=0) {
00200         /* TODO: use regex */
00201         if (!strcmp(sargType,"string")) argType=KEY_TYPE_STRING;
00202         else if (!strcmp(sargType,"bin")) argType=KEY_TYPE_BINARY;
00203         else if (!strcmp(sargType,"binary")) argType=KEY_TYPE_BINARY;
00204         else if (!strcmp(sargType,"dir")) argType=KEY_TYPE_DIR;
00205         else if (!strcmp(sargType,"link")) argType=KEY_TYPE_LINK;
00206     } else if (argCommand==CMD_SET) { /* We must have a type */
00207         argType=KEY_TYPE_STRING;
00208     }
00209 
00210 
00211     /* Parse UID */
00212     if (*argUser) {
00213         if (isdigit(*argUser)) {
00214             argUID=malloc(sizeof(uid_t));
00215             *argUID=atoi(argUser);
00216         } else {
00217             struct passwd *pwd;
00218             pwd=getpwnam(argUser);
00219             if (pwd) {
00220                 argUID=malloc(sizeof(uid_t));
00221                 *argUID=pwd->pw_uid;
00222             } else {
00223                 fprintf(stderr,"kdb: Invalid user %s. Ignoring\n", argUser);
00224             }
00225         }
00226     }
00227 
00228 
00229     /* Parse GID */
00230     if (*argGroup) {
00231         if (isdigit(*argGroup)) {
00232             argGID=malloc(sizeof(gid_t));
00233             *argGID=atoi(argGroup);
00234         } else {
00235             struct group *grp;
00236             grp=getgrnam(argGroup);
00237             if (grp) {
00238                 argGID=malloc(sizeof(gid_t));
00239                 *argGID=grp->gr_gid;
00240             } else {
00241                 fprintf(stderr,"kdb: Invalid group %s. Ignoring\n",argGroup);
00242             }
00243         }
00244     }
00245 
00246 
00247 
00248     /* Parse permissions */
00249     if (*sargMode!=0) argMode=strtol(sargMode,0,8);
00250 
00251     return argCommand;
00252 }
00253 
00254 
00255 void listAccess(Key *key,char *readable) {
00256     mode_t mode=keyGetAccess(key);
00257 
00258     if (S_ISDIR(mode)) readable[0]='d';
00259     else if (S_ISLNK(mode)) readable[0]='l';
00260     else readable[0]='-';
00261 
00262     readable[1] = mode & S_IRUSR ? 'r' : '-';
00263     readable[2] = mode & S_IWUSR ? 'w' : '-';
00264     readable[3] = mode & S_IXUSR ? 'x' : '-';
00265     readable[4] = mode & S_IRGRP ? 'r' : '-';
00266     readable[5] = mode & S_IWGRP ? 'w' : '-';
00267     readable[6] = mode & S_IXGRP ? 'x' : '-';
00268     readable[7] = mode & S_IROTH ? 'r' : '-';
00269     readable[8] = mode & S_IWOTH ? 'w' : '-';
00270     readable[9] = mode & S_IXOTH ? 'x' : '-';
00271     readable[10]= 0;
00272 }
00273 
00274 
00275 void listTime(time_t when,char *readable) {
00276     time_t current_time=time(0);
00277     char buf[400];
00278     time_t six_months_ago;
00279     int recent;
00280 
00281     /* If the file appears to be in the future, update the current
00282        time, in case the file happens to have been modified since
00283        the last time we checked the clock.  */
00284 
00285     /* Consider a time to be recent if it is within the past six
00286        months.  A Gregorian year has 365.2425 * 24 * 60 * 60 ==
00287        31556952 seconds on the average.  Write this value as an
00288        integer constant to avoid floating point hassles.  */
00289     six_months_ago = current_time - 31556952 / 2;
00290     recent = (six_months_ago <= when) && (when <= current_time);
00291 
00292     ctime_r(&when,buf); /* buf will become "Wed Jun 30 21:49:08 1993\n" */
00293     memcpy(readable,buf+4,7); /* take only month and day */
00294     if (recent) {
00295         memcpy(readable,buf+4,12);
00296         readable[12]=0;
00297     } else {
00298         memcpy(readable,buf+4,7);
00299         readable[7]=' ';
00300         memcpy(readable+8,buf+20,4);
00301         readable[12]=0;
00302     }
00303 }
00304 
00305 
00306 
00307 void listSingleKey(Key *key) {
00308     char buffer[400];
00309     char *p=buffer;
00310 
00311     if (argLong) {
00312         struct passwd *pwd;
00313         struct group *grp;
00314 
00315         listAccess(key,p);
00316         p+=strlen(p);
00317         *p=' '; p++;
00318         *p=' '; p++;
00319         *p=' '; p++;
00320 
00321         pwd=getpwuid(keyGetUID(key));
00322         strcpy(p,pwd->pw_name);
00323         p+=strlen(p);
00324         *p=' '; p++;
00325         *p=' '; p++;
00326 
00327         grp=getgrgid(keyGetGID(key));
00328         strcpy(p,grp->gr_name);
00329         p+=strlen(p);
00330         *p=' '; p++;
00331 
00332         sprintf(p,"%*d ",5,keyGetRecordSize(key));
00333         p+=strlen(p);
00334 
00335         listTime(keyGetMTime(key),p);
00336         p+=strlen(p);
00337         *p=' '; p++;
00338     }
00339     if (argFullName) keyGetFullName(key,p,sizeof(buffer)-(p-buffer));
00340     else keyGetName(key,p,sizeof(buffer)-(p-buffer));
00341     if (argValue && (keyGetDataSize(key)>0)) {
00342         u_int8_t ktype;
00343 
00344         p+=strlen(p);
00345         *p='='; p++;
00346 
00347         ktype=keyGetType(key);
00348         if (ktype >= KEY_TYPE_STRING)
00349             p+=keyGetString(key,p,sizeof(buffer)-(p-buffer));
00350         else if (ktype >= KEY_TYPE_BINARY)
00351             p+=sprintf(p,"<BINARY VALUE>");
00352         else if (ktype == KEY_TYPE_LINK)
00353             p+=keyGetLink(key,p,sizeof(buffer)-(p-buffer));
00354 
00355         *p=0;
00356     }
00357     puts(buffer);
00358 }
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00377 int commandRemove() {
00378     if (!argKeyName) {
00379         fprintf(stderr,"kdb rm: No key name\n");
00380         return -1;
00381     }
00382 
00383     if (kdbRemove(argKeyName)) {
00384         perror("kdb rm");
00385         return -1;
00386     }
00387     return 0;
00388 }
00389 
00390 
00391 
00392 
00393 
00394 
00413 int commandSet() {
00414     Key key;
00415     int ret;
00416     char error[200];
00417 
00418 
00419     /* Consistency */
00420     if (!argKeyName) {
00421         fprintf(stderr,"kdb set: No key name\n");
00422         return -1;
00423     }
00424 
00425     keyInit(&key);
00426     keySetName(&key,argKeyName);
00427     ret=kdbGetKey(&key);
00428     if (!ret) { /* key already exist. good. */
00429         if (argComment) keySetComment(&key,argComment);
00430         if (argType==KEY_TYPE_UNDEFINED) argType=keyGetType(&key);
00431     } else if (errno!=KDB_RET_NOTFOUND) {
00432         sprintf(error,"kdb set: %s",argKeyName);
00433         perror(error);
00434     }
00435 
00436     if (argUID) keySetUID(&key,*argUID);
00437     if (argGID) keySetGID(&key,*argGID);
00438 
00439     if (argMode) keySetAccess(&key,argMode);
00440 
00441     switch (argType) {
00442         case KEY_TYPE_DIR: keySetType(&key,KEY_TYPE_DIR);
00443             break;
00444         case KEY_TYPE_STRING:
00445             if (argData) keySetString(&key,argData);
00446             break;
00447         case KEY_TYPE_BINARY:
00448             if (argData) keySetBinary(&key,argData,strblen(argData));
00449             break;
00450         case KEY_TYPE_LINK: keySetLink(&key,argData);
00451             break;
00452     }
00453 
00454     ret=kdbSetKey(&key);
00455     if (ret) {
00456         sprintf(error,"kdb set: %s",argKeyName);
00457         perror(error);
00458     }
00459     return ret;
00460 }
00461 
00462 
00463 
00464 
00465 
00466 
00480 int commandLink() {
00481     int rc;
00482 
00483     /* Consistency */
00484     if (!argKeyName) {
00485         fprintf(stderr,"kdb ln: No target specified\n");
00486         return -1;
00487     }
00488 
00489     if (!argData) {
00490         fprintf(stderr,"kdb ln: %s: No destination specified",argKeyName);
00491         return -1;
00492     }
00493 
00494     if ((rc=kdbLink(argKeyName,argData))) {
00495         perror("kdb ln");
00496     }
00497 
00498     return rc;
00499 }
00500 
00501 
00502 
00503 
00504 
00505 
00506 
00507 
00508 
00509 
00510 
00511 
00512 
00513 
00537 int commandList() {
00538     KeySet ks;
00539     Key *key=0;
00540     int ret;
00541 
00542     ksInit(&ks);
00543 
00544     if (!argKeyName) {
00545         KeySet roots;
00546         /* User don't want a specific key, so list the root keys */
00547 
00548         ksInit(&roots);
00549         kdbGetRootKeys(&roots);
00550 
00551         if (argRecursive) {
00552             key=roots.start;
00553             while (key) {
00554                 char rootName[200];
00555                 KeySet thisRoot;
00556                 Key *temp;
00557 
00558                 ksInit(&thisRoot);
00559                 keyGetFullName(key,rootName,sizeof(rootName));
00560                 if (argValue) ret=kdbGetChildKeys(rootName,&thisRoot,
00561                     (argSort?KDB_O_SORT:0) | argRecursive | KDB_O_DIR |
00562                     (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00563                 else ret=kdbGetChildKeys(rootName,&thisRoot,
00564                     (argSort?KDB_O_SORT:0) | KDB_O_STATONLY | argRecursive |
00565                     KDB_O_DIR | (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00566                 temp=key->next;
00567                 ksAppend(&ks,key);
00568                 ksAppendKeys(&ks,&thisRoot);
00569                 key=temp;
00570             }
00571         } else ksAppendKeys(&ks,&roots);
00572     } else {
00573         /* User gave us a specific key to start with */
00574 
00575         if (argValue) ret=kdbGetChildKeys(argKeyName,&ks,
00576             (argSort?KDB_O_SORT:0) | argRecursive | KDB_O_DIR |
00577             (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00578         else ret=kdbGetChildKeys(argKeyName,&ks,
00579             (argSort?KDB_O_SORT:0) | KDB_O_STATONLY | argRecursive |
00580             KDB_O_DIR | (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00581     
00582         if (ret) {
00583                 /* We got an error. Check if it is because its not a folder key */
00584             if (errno==ENOTDIR) {
00585                 /* We still have a chance, since there is something there */
00586                 key=(Key *)malloc(sizeof(Key));
00587                 keyInit(key);
00588                 keySetName(key,argKeyName);
00589                 if (argValue) ret=kdbGetKey(key);
00590                 else ret=kdbStatKey(key);
00591                 if (ret) {
00592                     char error[200];
00593 
00594                     keyClose(key); free(key);
00595                     ksClose(&ks);
00596                     
00597                     sprintf(error,"kdb ls: %s",argKeyName);
00598                     perror(error);
00599                     return ret;
00600                 }
00601             } else { /* A real error */
00602                 char error[200];
00603                 
00604                 ksClose(&ks);
00605 
00606                 sprintf(error,"kdb ls: %s",argKeyName);
00607                 perror(error);
00608                 return ret;
00609             }
00610         }
00611     }
00612 
00613     if (argShow) {
00614         if (argXML) {
00615             if (key) keyToStream(key,stdout,0);
00616             else if (ks.size)
00617                 ksToStream(&ks,stdout,KDB_O_XMLHEADERS);
00618         } else {
00619             if (key) listSingleKey(key);
00620             else if (ks.size) {
00621                 ksRewind(&ks);
00622                 while ((key=ksNext(&ks)))
00623                     listSingleKey(key);
00624             }
00625         }
00626     }
00627 
00628     ksClose(&ks);
00629     if (key) {
00630             keyClose(key);
00631             free(key);
00632     }
00633     return 0;
00634 }
00635 
00636 
00637 
00638 
00639 
00640 
00641 
00664 int commandGet() {
00665     int ret;
00666     Key key;
00667     char *buffer;
00668     char *p;
00669     size_t size,cs=0;
00670 
00671     if (!argKeyName) {
00672         fprintf(stderr,"kdb get: No key name\n");
00673         return -1;
00674     }
00675 
00676     keyInit(&key);
00677     keySetName(&key,argKeyName);
00678 
00679     ret=kdbGetKey(&key);
00680     if (ret) {
00681         char error[200];
00682 
00683         sprintf(error,"kdb get: %s",argKeyName);
00684         perror(error);
00685         return ret;
00686     }
00687     size=keyGetDataSize(&key);
00688     if (argDescriptive) {
00689         cs=keyGetCommentSize(&key);
00690         if (cs) size+=cs+3;
00691     }
00692     if (argShell) {
00693         size+=keyGetBaseNameSize(&key);
00694         size+=2; /* for 2 '"' to surround the value */
00695     } else if (argLong) {
00696         if (argFullName) size+=keyGetFullNameSize(&key);
00697         else size+=keyGetNameSize(&key);
00698     }
00699 
00700 
00701     if (keyGetType(&key)<=KEY_TYPE_BINARY) p=buffer=malloc(size+1);
00702     else p=buffer=malloc(size);
00703 
00704 
00705     if (argDescriptive) {
00706         if (cs) {
00707             p+=sprintf(p,"# ");
00708             p+=keyGetComment(&key,p,size-(p-buffer));
00709             *--p='\n'; p++;
00710         }
00711     }
00712     if (argShell) {
00713         p+=keyGetBaseName(&key,p,size-(p-buffer));
00714         *--p='='; p++;
00715         *p='\"'; p++;
00716     } else if (argLong) {
00717         if (argFullName) p+=keyGetFullName(&key,p,size-(p-buffer));
00718         else p+=keyGetName(&key,p,size-(p-buffer));
00719         *--p='='; p++;
00720     }
00721 
00722     p+=keyGetString(&key,p,size-(p-buffer));
00723     if (argShell) {
00724         *--p='\"'; p++;
00725         *p=0;
00726     }
00727     if (keyGetType(&key)<=KEY_TYPE_BINARY) {
00728         p+=keyGetDataSize(&key);
00729         *p=0;
00730     }
00731 
00732     printf("%s\n",buffer);
00733     free(buffer);
00734 
00735     return 0;
00736 }
00737 
00738 
00739 
00740 
00741 
00742 
00743 
00744 
00745 
00746 
00747 
00748 /*
00749  * This function is completelly dependent on libxml.
00750  */
00751 int processNode(KeySet *ks, xmlTextReaderPtr reader) {
00752     xmlChar *nodeName=0;
00753     xmlChar *buffer=0;
00754     Key *newKey=0;
00755     
00756     nodeName=xmlTextReaderName(reader);
00757     if (!strcmp(nodeName,"key")) {
00758         int end=0;
00759         
00760         newKey=malloc(sizeof(Key));
00761         keyInit(newKey);
00762         
00763         xmlFree(nodeName); nodeName=0;
00764         
00765         buffer=xmlTextReaderGetAttribute(reader,"name");
00766         keySetName(newKey,(char *)buffer);
00767         xmlFree(buffer); buffer=0;
00768         
00769         buffer=xmlTextReaderGetAttribute(reader,"type");
00770         if (!strcmp(buffer,"string"))
00771             keySetType(newKey,KEY_TYPE_STRING);
00772         else if (!strcmp(buffer,"binary"))
00773             keySetType(newKey,KEY_TYPE_BINARY);
00774         else if (!strcmp(buffer,"link"))
00775             keySetType(newKey,KEY_TYPE_LINK);
00776         else if (!strcmp(buffer,"directory"))
00777             keySetType(newKey,KEY_TYPE_DIR);
00778         xmlFree(buffer); buffer=0;
00779 
00780         
00781         /* Parse UID */
00782         buffer=xmlTextReaderGetAttribute(reader,"uid");
00783         if (isdigit(*buffer)) {
00784             keySetUID(newKey,atoi(buffer));
00785         } else {
00786             struct passwd *pwd;
00787             pwd=getpwnam(buffer);
00788             if (pwd) keySetUID(newKey,pwd->pw_uid);
00789             else fprintf(stderr,"kdb: Ignoring invalid user %s.\n", buffer);
00790         }
00791         xmlFree(buffer); buffer=0;
00792 
00793         
00794         /* Parse GID */
00795         buffer=xmlTextReaderGetAttribute(reader,"gid");
00796         if (isdigit(*buffer)) {
00797             keySetGID(newKey,atoi(buffer));
00798         } else {
00799             struct group *grp;
00800             grp=getgrnam(buffer);
00801             if (grp) keySetGID(newKey,grp->gr_gid);
00802             else fprintf(stderr,"kdb: Ignoring invalid group %s.\n",buffer);
00803         }
00804         xmlFree(buffer); buffer=0;
00805 
00806 
00807         /* Parse permissions */
00808         buffer=xmlTextReaderGetAttribute(reader,"mode");
00809         if (buffer) keySetAccess(newKey,strtol(buffer,0,8));
00810         xmlFree(buffer); buffer=0;
00811 
00812 
00813         /* Parse everything else */
00814         while (!end) {
00815             xmlFree(nodeName); nodeName=0;
00816             xmlTextReaderRead(reader);
00817             nodeName=xmlTextReaderName(reader);
00818 
00819             if (!strcmp(nodeName,"value")) {
00820                 if (xmlTextReaderIsEmptyElement(reader) ||
00821                     xmlTextReaderNodeType(reader)==15) continue;
00822                 xmlTextReaderRead(reader);
00823                 buffer=xmlTextReaderValue(reader);
00824                 if (buffer) {
00825                     switch (keyGetType(newKey)) {
00826                         case KEY_TYPE_STRING:
00827                             keySetString(newKey,buffer);
00828                             break;
00829                         case KEY_TYPE_BINARY:
00830                             keySetBinary(newKey,buffer,strlen(buffer)+1);
00831                             break;
00832                         case KEY_TYPE_LINK:
00833                             keySetLink(newKey,buffer);
00834                             break;
00835                     }
00836                 }
00837             } else if (!strcmp(nodeName,"comment")) {
00838                 if (xmlTextReaderIsEmptyElement(reader) ||
00839                     xmlTextReaderNodeType(reader)==15) continue;
00840                 xmlTextReaderRead(reader);
00841                 buffer=xmlTextReaderValue(reader);
00842 
00843                 keySetComment(newKey,buffer);
00844             } else if (!strcmp(nodeName,"key")) {
00845                 if (xmlTextReaderNodeType(reader)==15) end=1;
00846             }
00847 
00848             xmlFree(buffer); buffer=0;
00849         }
00850     }
00851 
00852     if (nodeName) xmlFree(nodeName),nodeName=0;
00853 
00854     if (newKey) ksAppend(ks,newKey);
00855     return 0;
00856 }
00857 
00858 
00859 
00860 
00861 
00862 
00863 /*
00864  * This function is completelly dependent on libxml.
00865  * It is the workhorse for ksFromXML() and ksFromXMLfile()
00866  */
00867 int ksFromXMLReader(KeySet *ks,xmlTextReaderPtr reader) {
00868     int ret;
00869 
00870     ret = xmlTextReaderRead(reader); /* <keyset> */
00871     ret = xmlTextReaderRead(reader); /* first <key> */
00872     while (ret == 1) {
00873         processNode(ks, reader);
00874         ret = xmlTextReaderRead(reader);
00875     }
00876     xmlFreeTextReader(reader);
00877     if (ret) fprintf(stderr,"kdb: Failed to parse XML input\n");
00878 
00879     return ret;
00880 }
00881 
00882 
00883 
00884 
00885 
00886 
00887 
00888 
00889 
00890 int ksFromXMLfile(KeySet *ks,char *filename) {
00891     xmlTextReaderPtr reader;
00892     int ret;
00893 
00894     reader = xmlNewTextReaderFilename(filename);
00895     if (reader) {
00896         ret=ksFromXMLReader(ks,reader);
00897     } else {
00898         perror("kdb");
00899         return 1;
00900     }
00901     return ret;
00902 }
00903 
00904 
00905 
00906 
00907 
00908 
00909 int ksFromXML(KeySet *ks,int fd) {
00910     /* Support for old XML library, that doesn't have xmlReaderForFd() */
00911     char filename[]="/var/tmp/rgeditXXXXXX";
00912     FILE *xmlfile=0;
00913     xmlfile=fdopen(mkstemp(filename),"rw+");
00914     while (! feof(xmlfile)) {
00915         char buffer[1000];
00916         ssize_t readed, writen;
00917 
00918         readed=read(fd,buffer,sizeof(buffer));
00919         if (readed<0) {
00920             perror("kdb");
00921             fclose(xmlfile);
00922             remove(filename);
00923             return 1;
00924         }
00925 
00926         writen=write(fileno(xmlfile),buffer,readed);
00927         if (writen<0) {
00928             perror("kdb");
00929             fclose(xmlfile);
00930             remove(filename);
00931             return 1;
00932         }
00933     }
00934     fclose(xmlfile);
00935     return ksFromXMLfile(ks,filename);
00936     /* end of support */
00937 
00938     /* This code requires a newer version of XML library. Don't use it yet
00939     // a complete XML document is expected
00940     xmlTextReaderPtr reader=0;
00941     int ret;
00942     reader=xmlReaderForFd(fd,"file:/tmp/imp.xml",0,0);
00943     if (reader) {
00944         ret=ksFromXMLReader(ks,reader);
00945     } else {
00946         printf("kdb: Unable to open file descriptor %d for XML reading\n", fd);
00947         return 1;
00948     }
00949     return ret;
00950     // end of newer code */
00951 }
00952 
00953 
00954 
00955 
00956 
00957 
00958 
00959 
00960 
00961 
00962 
00963 
00964 
00965 
00966 
00967 
00968 
00999 int commandEdit() {
01000     KeySet ks;
01001     KeySet ksEdited;
01002     KeySet toRemove;
01003     Key *current;
01004     char filename[]="/var/tmp/rgeditXXXXXX";
01005     char command[300];
01006     FILE *xmlfile=0;
01007 
01008     ksInit(&ks);
01009 
01010     kdbGetChildKeys(argKeyName,&ks, KDB_O_SORT | KDB_O_NFOLLOWLINK |
01011         (argAll?KDB_O_INACTIVE:0) | (argRecursive?KDB_O_RECURSIVE:0));
01012 
01013     if (!ks.size) {
01014         /* Maybe the user parameter is not a parent key, but a single key */
01015         current=malloc(sizeof(Key));
01016         keyInit(current);
01017         keySetName(current,argKeyName);
01018         if (kdbGetKey(current)) {
01019             /* Failed. Cleanup */
01020             keyClose(current);
01021             free(current);
01022             current=0;
01023         } else {
01024             /* We have something. */
01025             ksAppend(&ks,current);
01026             current=0;
01027         }
01028     }
01029 
01030 /*
01031     for (current=ks.start; current; current=current->next) {
01032         if (keyNeedsSync(current)) {
01033             printf("%s needs sync\n",current->key);
01034         }
01035     }
01036 */
01037 
01038     xmlfile=fdopen(mkstemp(filename),"rw+");
01039 
01040     ksToStream(&ks,xmlfile,KDB_O_XMLHEADERS);
01041     fclose(xmlfile);
01042 
01043     sprintf(command,"[ -z \"$EDITOR\" ] && EDITOR=vi; $EDITOR %s",filename);
01044     system(command);
01045 
01046     ksInit(&toRemove);
01047     ksInit(&ksEdited);
01048 
01049     /* ksFromXML is not a library function.
01050      * It is implemented in and for this program only.
01051    *       It is pretty reusable code, though.
01052      */
01053     ksFromXMLfile(&ksEdited,filename);
01054     remove(filename);
01055 
01056     ksCompare(&ks,&ksEdited,&toRemove);
01057 
01058     kdbSetKeys(&ks);
01059 
01060     ksRewind(&toRemove);
01061     while ((current=ksNext(&toRemove))) {
01062         char keyName[800];
01063 
01064         keyGetFullName(current,keyName,sizeof(keyName));
01065         kdbRemove(keyName);
01066     }
01067 
01068     return 0;
01069 }
01070 
01071 
01072 
01073 
01088 int commandImport() {
01089     KeySet ks;
01090 
01091     ksInit(&ks);
01092     /* The command line parsing function will put the XML filename
01093        in the argKeyName global, so forget the variable name. */
01094     if (argKeyName) ksFromXMLfile(&ks,argKeyName);
01095     else ksFromXML(&ks,fileno(stdin) /* more elegant then just '0' */);
01096 
01097     return kdbSetKeys(&ks);
01098 }
01099 
01100 
01101 
01102 
01103 
01121 int commandExport() {
01122 
01123     /* Equivalent to 'kdb ls -xRv
01124        So lets mimic and reuse code */
01125 
01126     argSort=1;
01127     argRecursive=1;
01128     argAll=1;
01129     argXML=1;
01130     argShow=1;
01131     argValue=1;
01132     argFullName=1;
01133 
01134     /* force UTF-8 */
01135     setlocale(LC_ALL,"en_US.UTF-8");
01136 
01137     return commandList();
01138 }
01139 
01140 
01155 int commandMonitor() {
01156     Key toMonitor;
01157     u_int32_t diff;
01158     char *newData=0;
01159     size_t dataSize;
01160     
01161     keyInit(&toMonitor);
01162     keySetName(&toMonitor,argKeyName);
01163     kdbGetKey(&toMonitor);
01164     
01165     diff=kdbMonitorKey(
01166         &toMonitor,          /* key to monitor */
01167         KEY_FLAG_HASDATA,    /* particular info from the key we are interested */
01168         0,                   /* how many times to poll. 0 = ad-infinitum */
01169         500                  /* usecs between polls. 0 defaults to 1 second */);
01170 
01171     /*
01172      * Since in our case we'll hang completelly until we get a key's
01173      * value change, we don't have to check diff.
01174      * So if method returned, the value has changed, and toMonitor has it.
01175      */
01176     newData=malloc(dataSize=keyGetDataSize(&toMonitor));
01177     keyGetString(&toMonitor,newData,dataSize);
01178     printf("New value is %s\n",newData);
01179     return 0;
01180 }
01181 
01182 
01183 int doCommand(int command) {
01184     switch (command) {
01185         case CMD_SET:             return commandSet();
01186         case CMD_LIST:            return commandList();
01187         case CMD_LINK:            return commandLink();
01188         case CMD_GET:             return commandGet();
01189         case CMD_REMOVE:          return commandRemove();
01190         case CMD_EDIT:            return commandEdit();
01191         case CMD_LOAD:            return commandImport();
01192         case CMD_SAVE:            return commandExport();
01193         case CMD_MONITOR:         return commandMonitor();
01194     }
01195     return 0;
01196 }
01197 
01198 
01199 int main(int argc, char **argv) {
01200     int command=0;
01201     int ret=0;
01202 
01203     command=parseCommandLine(argc,argv);
01204 
01205     kdbOpen();
01206     ret=doCommand(command);
01207     kdbClose();
01208 
01209     return ret;
01210 }
01211 

Generated on Tue Aug 31 08:40:42 2004 for Elektra Project by doxygen 1.3.6