00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 #include "config.h"
00028 #endif
00029 #include "kdb.h"
00030
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include <stdio.h>
00034 #include <time.h>
00035 #include <locale.h>
00036 #include <unistd.h>
00037 #include <string.h>
00038 #include <stdlib.h>
00039 #ifdef HAVE_GRP_H
00040 #include <grp.h>
00041 #endif
00042 #ifdef HAVE_PWD_H
00043 #include <pwd.h>
00044 #endif
00045 #include <ctype.h>
00046 #include <ltdl.h>
00047 #include <assert.h>
00048
00049 #ifdef HAVE_WIN32
00050 #include <fcntl.h>
00051 #endif
00052
00053 #include "kdbLibLoader.h"
00054
00055 #define CMD_GET 1
00056 #define CMD_SET 2
00057 #define CMD_REMOVE 3
00058 #define CMD_LIST 4
00059 #define CMD_LINK 5
00060 #define CMD_EDIT 6
00061 #define CMD_LOAD 7
00062 #define CMD_SAVE 8
00063 #define CMD_MONITOR 9
00064 #define CMD_MOVE 10
00065 #define CMD_INFO 25
00066 #define CMD_HELP 30
00067
00068 #define ARGSIZE 30
00069
00070
00071 #ifdef HAVE_WIN32
00072 #define mkstemp(m) open(mktemp(m), O_RDWR)
00073 #endif
00074
00075
00076 ssize_t unencode(char *encoded, void *returned);
00077
00078
00079
00080 int (*ksFromXMLfile)(KeySet *ks,char *filename);
00081 int (*ksFromXML)(KeySet *ks,int fd);
00082
00083
00084
00090 char *argComment=0;
00091 char *argFile=0;
00092 char *argData=0;
00093 char *argKeyName=0;
00094 char *argDomain=0;
00095 uid_t *argUID=0;
00096 uid_t *argGID=0;
00097 int argCommand=0;
00098 int argRecursive=0;
00099 int argLong=0;
00100 int argValue=0;
00101 int argAll=0;
00102 int argSort=1;
00103 int argDescriptive=0;
00104 int argFullName=0;
00105 int argShow=1;
00106 int argShell=0;
00107 int argXML=0;
00108 int argHelp=0;
00109 mode_t argMode=0;
00110 int argType=KEY_TYPE_UNDEFINED;
00111
00112
00113
00114 int commandHelp();
00115
00116
00117 int parseCommandLine(int argc, char *argv[]) {
00118 char sargType[ARGSIZE],argUser[ARGSIZE],argGroup[ARGSIZE];
00119 char sargMode[ARGSIZE],sargCommand[ARGSIZE];
00120 char * keyEnv;
00121 size_t keyEnvLength=0, keyOptLength=0, keyOldLength;
00122
00123 int opt;
00124
00125 *sargType=*argUser=*argGroup=*sargCommand=*sargMode=0;
00126
00127 while ((opt=getopt(argc,argv,"ab:c:dfg:hilm:nrRst:u:vx"))!=-1)
00128 {
00129 if (opt == EOF)
00130 break;
00131 switch (opt)
00132 {
00133 case 'a':
00134 argAll=1;
00135 break;
00136 case 'b':
00137 argFile=realloc(argFile,strlen(optarg)+1);
00138 assert(argFile!=NULL);
00139 strcpy(argFile,optarg);
00140 break;
00141 case 'c':
00142 argComment=realloc(argComment,strlen(optarg)+1);
00143 assert(argComment!=NULL);
00144 strcpy(argComment,optarg);
00145 break;
00146 case 'd':
00147 argDescriptive=1;
00148 argLong=1;
00149 break;
00150 case 'f':
00151 argFullName=1;
00152 break;
00153 case 'g':
00154 strncpy(argGroup,optarg,ARGSIZE);
00155 break;
00156 case 'h':
00157 argHelp=1;
00158 break;
00159 case 'i':
00160 argShow=0;
00161 break;
00162 case 'l':
00163 argLong=1;
00164 break;
00165 case 'm':
00166 strncpy(sargMode,optarg,ARGSIZE);
00167 break;
00168 case 'n':
00169 argSort=0;
00170 break;
00171 case 'R':
00172 case 'r':
00173 argRecursive=KDB_O_RECURSIVE;
00174 break;
00175 case 's':
00176 argShell=1;
00177 break;
00178 case 't':
00179 strncpy(sargType,optarg,ARGSIZE);
00180 break;
00181 case 'u':
00182 strncpy(argUser,optarg,ARGSIZE);
00183 break;
00184 case 'v':
00185 argValue=1;
00186 break;
00187 case 'x':
00188 argXML=1;
00189 break;
00190 default:
00191 fprintf(stderr, "Unknown error (%d %c) in parsing arguments\n",
00192 opt,opt);
00193 break;
00194 }
00195 }
00196
00197 if (optind < argc)
00198 {
00199 strncpy(sargCommand,argv[optind],ARGSIZE);
00200 optind ++;
00201 } else {
00202 commandHelp();
00203 exit(0);
00204 }
00205
00207 keyEnv = getenv ("KDB_ROOT");
00208 if (keyEnv) keyEnvLength = strblen (keyEnv);
00209 else keyEnvLength = 0;
00210 if (optind < argc)
00211 {
00212 keyOptLength = strblen (argv[optind]);
00213 argKeyName=realloc(argKeyName,
00214 keyEnvLength + keyOptLength + 1);
00215 assert(argKeyName!=NULL);
00216 if (keyEnv) strncpy (argKeyName, keyEnv, keyEnvLength);
00217 strncpy(argKeyName + keyEnvLength, argv[optind], keyOptLength);
00218 if (keyEnv) *(argKeyName+keyEnvLength-1) = '/';
00219 optind ++;
00220 } else if (keyEnv) {
00221 argKeyName=realloc(argKeyName, keyEnvLength + 1);
00222 assert(argKeyName!=NULL);
00223 if (keyEnv) strncpy (argKeyName, keyEnv, keyEnvLength);
00224 }
00225
00226
00227 keyOptLength = 0;
00228 keyOldLength = 0;
00229 while (optind < argc)
00230 {
00231 keyOptLength += strblen(argv[optind]);
00232 argData=realloc(argData,keyOptLength + 1);
00233 assert(argData!=NULL);
00234 if (keyOldLength > 0) *(argData+keyOldLength-1) = ' ';
00235 strcpy(argData+keyOldLength, argv[optind]);
00236 optind ++;
00237 keyOldLength = keyOptLength;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 if (!strcmp(sargCommand,"ls")) argCommand=CMD_LIST;
00251 else if (!strcmp(sargCommand,"set")) argCommand=CMD_SET;
00252 else if (!strcmp(sargCommand,"get")) argCommand=CMD_GET;
00253 else if (!strcmp(sargCommand,"ln")) argCommand=CMD_LINK;
00254 else if (!strcmp(sargCommand,"rm")) argCommand=CMD_REMOVE;
00255 else if (!strcmp(sargCommand,"vi")) argCommand=CMD_EDIT;
00256 else if (!strcmp(sargCommand,"edit")) argCommand=CMD_EDIT;
00257 else if (!strcmp(sargCommand,"load")) argCommand=CMD_LOAD;
00258 else if (!strcmp(sargCommand,"import")) argCommand=CMD_LOAD;
00259 else if (!strcmp(sargCommand,"save")) argCommand=CMD_SAVE;
00260 else if (!strcmp(sargCommand,"export")) argCommand=CMD_SAVE;
00261 else if (!strcmp(sargCommand,"mon")) argCommand=CMD_MONITOR;
00262 else if (!strcmp(sargCommand,"monitor")) argCommand=CMD_MONITOR;
00263 else if (!strcmp(sargCommand,"mv")) argCommand=CMD_MOVE;
00264 else if (!strcmp(sargCommand,"info")) argCommand=CMD_INFO;
00265 else if (!strcmp(sargCommand,"help")) argCommand=CMD_HELP;
00266 else {
00267 fprintf(stderr,"kdb: Invalid subcommand.\n");
00268 exit(1);
00269 }
00270
00271
00272 if (*sargType!=0) {
00273
00274 if (!strcmp(sargType,"string")) argType=KEY_TYPE_STRING;
00275 else if (!strcmp(sargType,"bin")) argType=KEY_TYPE_BINARY;
00276 else if (!strcmp(sargType,"binary")) argType=KEY_TYPE_BINARY;
00277 else if (!strcmp(sargType,"dir")) argType=KEY_TYPE_DIR;
00278 else if (!strcmp(sargType,"link")) argType=KEY_TYPE_LINK;
00279 else {
00280 argType=strtol(sargType,0,10);
00281 if (errno == ERANGE || errno == EINVAL)
00282
00283 argType=KEY_TYPE_UNDEFINED;
00284 }
00285 } else if (argCommand==CMD_SET) {
00286 argType=KEY_TYPE_STRING;
00287 }
00288
00289 #ifdef HAVE_PWD_H
00290
00291 if (*argUser) {
00292 if (isdigit(*argUser)) {
00293 argUID=malloc(sizeof(uid_t));
00294 *argUID=atoi(argUser);
00295 } else {
00296 struct passwd *pwd;
00297 pwd=getpwnam(argUser);
00298 if (pwd) {
00299 argUID=malloc(sizeof(uid_t));
00300 *argUID=pwd->pw_uid;
00301 } else {
00302 fprintf(stderr,"kdb: Invalid user \'%s\'. Ignoring\n", argUser);
00303 }
00304 }
00305 }
00306 #endif
00307 #ifdef HAVE_GRP_H
00308
00309 if (*argGroup) {
00310 if (isdigit(*argGroup)) {
00311 argGID=malloc(sizeof(gid_t));
00312 *argGID=atoi(argGroup);
00313 } else {
00314 struct group *grp;
00315 grp=getgrnam(argGroup);
00316 if (grp) {
00317 argGID=malloc(sizeof(gid_t));
00318 *argGID=grp->gr_gid;
00319 } else {
00320 fprintf(stderr,"kdb: Invalid group \'%s\'. Ignoring\n",argGroup);
00321 }
00322 }
00323 }
00324 #endif
00325
00326
00327
00328 if (*sargMode!=0) argMode=strtol(sargMode,0,8);
00329
00330 return argCommand;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 void listAccess(Key *key,char *readable) {
00343 mode_t mode=keyGetAccess(key);
00344
00345 if (S_ISDIR(mode)) readable[0]='d';
00346 #ifdef S_ISLNK
00347 else if (S_ISLNK(mode)) readable[0]='l';
00348 #endif
00349 else readable[0]='-';
00350
00351 readable[1] = mode & S_IRUSR ? 'r' : '-';
00352 readable[2] = mode & S_IWUSR ? 'w' : '-';
00353 readable[3] = mode & S_IXUSR ? 'x' : '-';
00354 #ifdef HAVE_WIN32
00355 readable[4] = 0;
00356 #else
00357 readable[4] = mode & S_IRGRP ? 'r' : '-';
00358 readable[5] = mode & S_IWGRP ? 'w' : '-';
00359 readable[6] = mode & S_IXGRP ? 'x' : '-';
00360 readable[7] = mode & S_IROTH ? 'r' : '-';
00361 readable[8] = mode & S_IWOTH ? 'w' : '-';
00362 readable[9] = mode & S_IXOTH ? 'x' : '-';
00363 readable[10]= 0;
00364 #endif
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374 void listTime(time_t when,char *readable) {
00375 time_t current_time=time(0);
00376 char buf[400];
00377 #ifndef HAVE_CTIME_R
00378 char *ctimep = NULL;
00379 #endif
00380 time_t six_months_ago;
00381 int recent;
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 six_months_ago = current_time - 31556952 / 2;
00392 recent = (six_months_ago <= when) && (when <= current_time);
00393 #ifdef HAVE_CTIME_R
00394 ctime_r(&when,buf);
00395 #else
00396 ctimep = ctime(&when);
00397 strncpy(buf, ctimep, sizeof(buf));
00398 #endif
00399 memcpy(readable,buf+4,7);
00400 if (recent) {
00401 memcpy(readable,buf+4,12);
00402 readable[12]=0;
00403 } else {
00404 memcpy(readable,buf+4,7);
00405 readable[7]=' ';
00406 memcpy(readable+8,buf+20,4);
00407 readable[12]=0;
00408 }
00409 }
00410
00411
00412
00413
00414
00415
00416
00417 void listSingleKey(Key *key) {
00418 char buffer[400];
00419 char *p=buffer;
00420
00421 if (argLong) {
00422 struct passwd *pwd;
00423 struct group *grp;
00424
00425 listAccess(key,p);
00426 p+=strlen(p);
00427 *p=' '; p++;
00428 *p=' '; p++;
00429 *p=' '; p++;
00430 #ifdef HAVE_PWD_H
00431 if ( (pwd=getpwuid(keyGetUID(key))) != NULL ) {
00432 strcpy(p,pwd->pw_name);
00433 p+=strlen(p);
00434 *p=' '; p++;
00435 *p=' '; p++;
00436 } else {
00437 strcpy(p, "<unknown>");
00438 p+=strlen(p);
00439 *p=' '; p++;
00440 *p=' '; p++;
00441 }
00442 #endif
00443 #ifdef HAVE_GRP_H
00444 if ( (grp=getgrgid(keyGetGID(key))) != NULL ) {
00445 strcpy(p,grp->gr_name);
00446 p+=strlen(p);
00447 *p=' '; p++;
00448 } else {
00449 strcpy(p, "<unknow>");
00450 p+=strlen(p);
00451 *p=' '; p++;
00452 *p=' '; p++;
00453 }
00454 #endif
00455 sprintf(p,"%*d ",5,keyGetRecordSize(key));
00456 p+=strlen(p);
00457
00458 listTime(keyGetMTime(key),p);
00459 p+=strlen(p);
00460 *p=' '; p++;
00461 }
00462 if (argFullName) keyGetFullName(key,p,sizeof(buffer)-(p-buffer));
00463 else keyGetName(key,p,sizeof(buffer)-(p-buffer));
00464 if (argValue && (keyGetValueSize(key)>0)) {
00465 uint8_t ktype;
00466
00467 p+=strlen(p);
00468 *p='='; p++;
00469
00470 ktype=keyGetType(key);
00471 if (ktype >= KEY_TYPE_STRING)
00472 p+=keyGetString(key,p,sizeof(buffer)-(p-buffer));
00473 else if (ktype >= KEY_TYPE_BINARY)
00474 p+=sprintf(p,"<BINARY VALUE>");
00475 else if (ktype == KEY_TYPE_LINK)
00476 p+=keyGetLink(key,p,sizeof(buffer)-(p-buffer));
00477
00478 *p=0;
00479 }
00480 puts(buffer);
00481 }
00482
00483
00484
00485
00486
00487
00488
00489
00500 int commandRemove() {
00501 if (!argKeyName) {
00502 fprintf(stderr,"kdb rm: No key name\n");
00503 return -1;
00504 }
00505
00506 if (kdbRemove(argKeyName)) {
00507 char error[300];
00508
00509 sprintf(error,"kdb rm: \'%s\'",argKeyName);
00510 perror(error);
00511 return -1;
00512 }
00513 return 0;
00514 }
00515
00516
00517
00531 int commandMove() {
00532 Key *key;
00533 size_t size=0;
00534 int rc;
00535
00536
00537 if (!argKeyName) {
00538 fprintf(stderr,"kdb mv: No target specified\n");
00539 return -1;
00540 }
00541
00542 if (!argData) {
00543 fprintf(stderr,"kdb mv: \'%s\': No destination specified\n",argKeyName);
00544 return -1;
00545 }
00546
00547 key=keyNew(argKeyName,KEY_SWITCH_END);
00548 size=keyGetNameSize(key);
00549
00550 if (size == 0) {
00551 char error[100];
00552
00553 sprintf(error,"kdb mv: \'%s\'", argKeyName);
00554 perror(error);
00555
00556 keyDel(key);
00557 return 1;
00558 }
00559
00560 rc=kdbRename(key,argData);
00561 if (rc != 0) {
00562
00563 switch (errno) {
00564
00565 }
00566 }
00567
00568 keyDel(key);
00569
00570 return rc;
00571 }
00572
00573
00574
00594 int commandSet() {
00595 Key *key;
00596 int ret;
00597 char error[200];
00598 size_t offset=0;
00599
00600
00601
00602 if (!argKeyName) {
00603 fprintf(stderr,"kdb set: No key name\n");
00604 return -1;
00605 }
00606
00607 key=keyNew(argKeyName,KEY_SWITCH_END);
00608 ret=kdbGetKey(key);
00609 if (ret == 0) {
00610
00611 if (argType==KEY_TYPE_UNDEFINED) argType=keyGetType(key);
00612 } else if (errno!=KDB_RET_NOTFOUND) {
00613
00614 sprintf(error,"kdb set: %s",argKeyName);
00615 perror(error);
00616 }
00617
00618
00619
00620 if (argUID) keySetUID(key,*argUID);
00621 if (argGID) keySetGID(key,*argGID);
00622 if (argMode) keySetAccess(key,argMode);
00623
00624 if (argComment) keySetComment(key,argComment);
00625
00626 if (argFile) {
00627 FILE *f;
00628 int end=0;
00629
00630 if (argData) free(argData);
00631 argData=0;
00632 f=fopen(argFile,"r");
00633
00634 if (!f) {
00635 sprintf(error,"kdb set: \'%s\'",argFile);
00636 perror(error);
00637 return -1;
00638 }
00639 while (! end) {
00640 char buffer[100];
00641 ssize_t r;
00642
00643 r=read(fileno(f),buffer,sizeof(buffer));
00644 if (r == 0) {
00645 r=lseek(fileno(f),0,SEEK_END)-offset;
00646 end=1;
00647 }
00648 argData=realloc(argData,offset+r);
00649 assert(argData!=NULL);
00650 memcpy(argData+offset,buffer,r);
00651 offset+=r;
00652 }
00653 fclose(f);
00654 }
00655
00656
00657
00658 if (argType == KEY_TYPE_UNDEFINED)
00659 keySetString(key,argData);
00660 else if (argType == KEY_TYPE_DIR)
00661 keySetType(key,KEY_TYPE_DIR);
00662 else if (argType == KEY_TYPE_LINK)
00663 keySetLink(key,argData);
00664 else if (argData) {
00665
00666
00667 if (offset) keySetRaw(key,argData,offset);
00668 else if (KEY_TYPE_BINARY <= argType && argType < KEY_TYPE_STRING)
00669
00670 keySetRaw(key,argData,strblen(argData)-1);
00671 else keySetRaw(key,argData,strblen(argData));
00672
00673
00674 keySetType(key,argType);
00675 }
00676
00677
00678 ret=kdbSetKey(key);
00679 if (ret) {
00680 sprintf(error,"kdb set: \'%s\'",argKeyName);
00681 perror(error);
00682 }
00683
00684 keyDel(key);
00685
00686 return ret;
00687 }
00688
00689
00690
00691
00692
00693
00706 int commandLink() {
00707 int rc;
00708
00709
00710 if (!argKeyName) {
00711 fprintf(stderr,"kdb ln: No target specified\n");
00712 return -1;
00713 }
00714
00715 if (!argData) {
00716 fprintf(stderr,"kdb ln: \'%s\': No destination specified\n",argKeyName);
00717 return -1;
00718 }
00719
00720 if ((rc=kdbLink(argKeyName,argData))) {
00721 perror("kdb ln");
00722 }
00723
00724 return rc;
00725 }
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00760 int commandList() {
00761 KeySet *ks;
00762 ssize_t ret;
00763 if (!argKeyName) {
00764 fprintf(stderr,"kdb ls: No key name\n");
00765 return -1;
00766 }
00767
00768
00769 ks=ksNew();
00770
00771 if (!argKeyName) {
00772 KeySet *roots;
00773
00774
00775 roots=ksNew();
00776 kdbGetRootKeys(roots);
00777
00778 if (argRecursive) {
00779 Key *walker=0;
00780
00781 while ((walker=ksPop(roots))) {
00782
00783
00784
00785 KeySet *thisRoot=ksNew();
00786
00787 if (argValue) ret=kdbGetKeyChildKeys(walker,thisRoot,
00788 (argSort?KDB_O_SORT:0) | (argRecursive?KDB_O_RECURSIVE:0) |
00789 KDB_O_DIR | (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00790 else ret=kdbGetKeyChildKeys(walker,thisRoot,
00791 (argSort?KDB_O_SORT:0) | KDB_O_STATONLY |
00792 (argRecursive?KDB_O_RECURSIVE:0) | KDB_O_DIR |
00793 (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00794
00795
00796
00797
00798 ksAppend(ks,walker);
00799 ksAppendKeys(ks,thisRoot);
00800 ksDel(thisRoot);
00801 }
00802 } else ksAppendKeys(ks,roots);
00803 ksDel(roots);
00804 } else {
00805
00806
00807 if (argValue) ret=kdbGetChildKeys(argKeyName,ks,
00808 (argSort?KDB_O_SORT:0) | (argRecursive?KDB_O_RECURSIVE:0) |
00809 KDB_O_DIR | (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00810 else ret=kdbGetChildKeys(argKeyName,ks,
00811 (argSort?KDB_O_SORT:0) | KDB_O_STATONLY |
00812 (argRecursive?KDB_O_RECURSIVE:0) | KDB_O_DIR |
00813 (argAll?KDB_O_INACTIVE:0) | KDB_O_NFOLLOWLINK);
00814
00815 if (ret<0) {
00816
00817 if (errno==ENOTDIR) {
00818
00819 Key *key=keyNew(argKeyName,KEY_SWITCH_END);
00820
00821 if (argValue) ret=kdbGetKey(key);
00822 else ret=kdbStatKey(key);
00823
00824 if (ret == 0) ksAppend(ks,key);
00825 else {
00826
00827 char error[200];
00828
00829 keyDel(key);
00830 ksDel(ks);
00831
00832 sprintf(error,"kdb ls: %s",argKeyName);
00833 perror(error);
00834 return ret;
00835 }
00836
00837 } else {
00838 char error[200];
00839
00840 ksDel(ks);
00841
00842 sprintf(error,"kdb ls: %s",argKeyName);
00843 perror(error);
00844 return ret;
00845 }
00846 }
00847 }
00848
00849 if (argShow) {
00850 size_t listSize=ksGetSize(ks);
00851
00852 if (argXML) ksToStream(ks,stdout,KDB_O_XMLHEADERS |
00853 (argFullName?(KDB_O_FULLNAME | KDB_O_FULLUGID):0));
00854 else {
00855 if (listSize == 1) listSingleKey(ksHead(ks));
00856 else if (listSize > 1) {
00857 Key *walker;
00858
00859 ksRewind(ks);
00860 while ((walker=ksNext(ks)))
00861 listSingleKey(walker);
00862 }
00863 }
00864 }
00865
00866 ksClose(ks);
00867 return 0;
00868 }
00869
00870
00871
00872
00873
00874
00875
00895 int commandGet() {
00896 int ret;
00897 Key *key;
00898 char *buffer;
00899 char *p;
00900 size_t size,cs=0;
00901 uint8_t keyType;
00902
00903 if (!argKeyName) {
00904 fprintf(stderr,"kdb get: No key name\n");
00905 return -1;
00906 }
00907
00908 key=keyNew(argKeyName,KEY_SWITCH_END);
00909
00910 ret=kdbGetKey(key);
00911
00912 if (ret) {
00913 char error[200];
00914
00915 keyDel(key);
00916 sprintf(error,"kdb get: %s",argKeyName);
00917 perror(error);
00918 return ret;
00919 }
00920 size=keyGetValueSize(key);
00921 if (argDescriptive) {
00922 cs=keyGetCommentSize(key);
00923 if (cs) size+=cs+3;
00924 }
00925 if (argShell) {
00926 size+=keyGetBaseNameSize(key);
00927 size+=2;
00928 } else if (argLong) {
00929 if (argFullName) size+=keyGetFullNameSize(key);
00930 else size+=keyGetNameSize(key);
00931 }
00932
00933
00934 p=buffer=malloc(size);
00935
00936
00937 if (argDescriptive) {
00938 if (cs) {
00939 p+=sprintf(p,"# ");
00940 p+=keyGetComment(key,p,size-(p-buffer));
00941 *--p='\n'; p++;
00942 }
00943 }
00944 if (argShell) {
00945 p+=keyGetBaseName(key,p,size-(p-buffer));
00946 *--p='='; p++;
00947 *p='\"'; p++;
00948 } else if (argLong) {
00949 if (argFullName) p+=keyGetFullName(key,p,size-(p-buffer));
00950 else p+=keyGetName(key,p,size-(p-buffer));
00951 *--p='='; p++;
00952 }
00953
00954 keyType=keyGetType(key);
00955
00956 if (keyIsBin(key)) p+=keyGetBinary(key,p,size-(p-buffer));
00957 else p+=keyGetString(key,p,size-(p-buffer));
00958 if (argShell) {
00959 *--p='\"'; p++;
00960 *p=0;
00961 }
00962 if (keyIsBin(key)) fwrite(buffer,size,1,stdout);
00963 else printf("%s\n",buffer);
00964
00965
00966 free(buffer);
00967 keyDel(key);
00968
00969 return 0;
00970 }
00971
00972
00973
00974
00975
00976
00989 int commandHelp() {
00990 printf("Usage: kdb [OPTION] <command> [<key> [value ...]]\n");
00991 printf("Use kdb to manipulate the Key Database.\n");
00992 printf("\n");
00993
00994 printf("ARGUMENTS\n");
00995 printf("Commands are explained with kdb -h command\n");
00996 printf("<key> is the name of the key. It can be prefixed\n");
00997 printf(" with environment KDB_ROOT. The slash between will\n");
00998 printf("be inserted.\n");
00999 printf(" export KDB_ROOT=\"user/test/dir\"\n");
01000 printf(" kdb get file/key ... will expand to user/test/dir/file/key\n");
01001 printf("[value ...] hold the value which should be set\n");
01002 printf("\n");
01003
01004 printf("COMMANDS\n");
01005 printf(" kdb get [-dlr] key/name\n");
01006 printf(" kdb set [-t type] [-c \"A comment about this key\"] [-m mode] [-u uid]\n");
01007 printf(" [-g gid] key/name \"the value\"\n");
01008 printf(" kdb set [-t type] [-m mode] [-c \"A comment\"] key/name -- \"the value\"\n");
01009 printf(" kdb set [-t type] [-b file] key/name\n");
01010 printf(" kdb ls [-lRfv] [key/dir | key/name]\n");
01011 printf(" kdb ls [-lRfvx] [key/dir | key/name] > keys.xml\n");
01012 printf(" kdb edit [-R] [key/dir | key/name]\n");
01013 printf(" kdb rm key/name\n");
01014 printf(" kdb mv key/src key/dest\n");
01015 printf(" kdb ln key/src key/dest\n");
01016 printf(" kdb export system/some/tree.root > file.xml\n");
01017 printf(" kdb import < file.xml\n");
01018 printf(" kdb import file.xml\n");
01019 printf(" kdb monitor some/key/name\n");
01020 printf(" kdb info\n");
01021 printf("\n");
01022 }
01023
01024 void optionr()
01025 {
01026 printf("-R -r\n");
01027 printf(" Causes to work recursively. In ls, will list recursively. \n");
01028 printf("\n");
01029 }
01030
01031 void optionx()
01032 {
01033 printf("-x\n");
01034 printf(" Makes ls output an XML representation of the keys, instead of an ls-compatible output. \n");
01035 printf("\n");
01036 }
01037
01038 void optionl()
01039 {
01040 printf("-l\n");
01041 printf(" Causes to display long results. With ls, will generate lists similar to ls -l. With get, will show also the key name. \n");
01042 printf("\n");
01043 }
01044
01045 void optiona()
01046 {
01047 printf("-a\n");
01048 printf(" Causes ls to display also inactive keys. Generate lists similar to ls -a. Inactive keys are keys which basename begins with a '.' (dot). An example of inactive key: system/sw/XFree/current/Monitor/.Monitor1 \n");
01049 printf("\n");
01050 }
01051
01052 void optionf()
01053 {
01054 printf("-f\n");
01055 printf(" Causes to work with full key names. A full key name makes sense only on user/* keys, and differentiate from the regular key names in specifying the owner user. If the current user is someuser, the user/some/key full name is user:someuser/some/key. Makes effect in ls, export and get subcommands. \n");
01056 printf("\n");
01057 }
01058
01059 void optiond()
01060 {
01061 printf("-d\n");
01062 printf(" Causes get to work descriptivelly. When requesting a key it will show the comment, key name and its value in a fancy format \n");
01063 printf("\n");
01064 }
01065
01066 void options()
01067 {
01068 printf("-s\n");
01069 printf(" Causes get to be more friendly to Shell scripts. For example, when requesting user/env/env2/PATH, the output will be PATH=\"the value\", that is, only the basename of the key will be showed and the value will be surrounded by \".\n");
01070 printf("\n");
01071 }
01072
01073 void optiont()
01074 {
01075 printf("-t type\n");
01076 printf(" When setting a key's value, you can specify the type with this switch. Currently accepted types are string for plain text, bin for binary as-is values, dir to create folder keys and link to create symbolic links between keys. Plain text are always stored as UTF-8(7) in Elektra, regardeless of your current encoding ($LANG). If you want to force a value to be stored without the UTF-8(7) encoding (a bad idea), you can set it as binary. Binary values should be avoided, because they are black boxes for system administrators. \n");
01077 printf("\n");
01078 }
01079
01080 void optionb()
01081 {
01082 printf("-b filename\n");
01083 printf(" Set the key value as the content of file filename. This option is more usefull when setting binary keys. \n");
01084 printf("\n");
01085 }
01086
01087 void optionm()
01088 {
01089 printf("-m mode\n");
01090 printf(" For the set command. Will set the key access permission to mode, which must be an octal number as for chmod(1). \n");
01091 printf("\n");
01092 }
01093
01094 void optionu()
01095 {
01096 printf("-u uid\n");
01097 printf(" Create the key with uid user ID. It can be a user name or a uid number. \n");
01098 printf("\n");
01099 }
01100
01101 void optiong()
01102 {
01103 printf("-g gid\n");
01104 printf(" Create the key with gid group ID. It can be a group name or a gid number \n");
01105 printf("\n");
01106 }
01107
01108 void optionc()
01109 {
01110 printf("-c comment\n");
01111 printf(" When setting keys, you can use this argument to set a descriptive comment for it. This comment is exactly as a comment in a plain text configuration file. The comment is stored as UTF-8(7) regardeless of your current encoding ($LANG). \n");
01112 printf("\n");
01113 }
01114
01115
01116 void optionv()
01117 {
01118 printf("-v\n");
01119 printf(" With the ls subcommand, will make it show also the value stored in the key. \n");
01120 printf("\n");
01121 }
01122
01123 void commandGetHelp ()
01124 {
01125 printf("get\n");
01126 printf(" Get the value from the specified key. Accepts options: -d, -l, -f, -s \n");
01127 printf("\n");
01128 optiond();
01129 optionl();
01130 optionf();
01131 options();
01132 }
01133
01134 void commandSetHelp ()
01135 {
01136 printf("set\n");
01137 printf(" Set the value to the specified key. Accepts options: -c, -t, -m, -b \n");
01138 printf("\n");
01139 optionc();
01140 optiont();
01141 optionm();
01142 optionb();
01143 }
01144
01145 void commandListHelp ()
01146 {
01147 printf("ls\n");
01148 printf(" As the ls(1) command, list key names for the specified key, or children keys, if specified a folder key. The -v argument will make it show also the values of each key. The -d (descriptive) will make it show the comment, key name and its value, as you are watching a plain text file. Accepts options: -x, -d, -l, -f, -v, -R \n");
01149 printf("\n");
01150 optionx();
01151 optiond();
01152 optionl();
01153 optionf();
01154 optionv();
01155 optionr();
01156 }
01157
01158 void commandLinkHelp ()
01159 {
01160 printf("ln\n");
01161 printf("Creates a key that is a symbolic links to another key. \n");
01162 printf("\n");
01163 }
01164
01165 void commandMoveHelp()
01166 {
01167 printf("mv\n");
01168 printf("Move, or renames a key. Currently it can't move keys across different filesystems.\n");
01169 printf("\n");
01170 }
01171
01172 void commandRemoveHelp()
01173 {
01174 printf("rm\n");
01175 printf("As the rm(1) command, removes the key specified. \n");
01176 printf("\n");
01177 }
01178
01179 void commandEditHelp()
01180 {
01181 printf("edit\n");
01182 printf("A very powerfull subcommand that lets you edit an XML representation of the keys. The parameters it accepts is usually a parent key, so its child keys will be gathered. Can be used with the -R flag to work recursively. The editor used is the one set in the $EDITOR environment variable, or vi. After editing the keys, kdb edit will analyze them and commit only the changed keys, remove the keys removed, and add the keys added. \n");
01183 printf("\n");
01184 }
01185
01186 void commandExportHelp()
01187 {
01188 printf("export, save \n");
01189 printf("Export a subtree of keys to XML. If no subtree is defined right after the export command, system and current user trees will be exported. Output is written to standard output. The output encoding will allways be UTF-8, regardeless of your system encoding. UTF-8 is the most universal charset you can get when exchanging data between multiple systems. Accepts -f. \n");
01190 printf("\n");
01191 optionf();
01192 }
01193
01194 void commandImportHelp()
01195 {
01196 printf("import, load \n");
01197 printf("Import an XML representation of keys and save it to the keys database. If no filename is passed right after the import command, standard input is used. \n");
01198 printf("\n");
01199 }
01200
01201 void commandInfoHelp()
01202 {
01203 printf("info\n");
01204 printf("Displays some information about the Elektra library being used, version, backends, etc.\n");
01205 printf("\n");
01206 }
01207
01208 void commandMonitorHelp()
01209 {
01210 printf("monitor, mon, \n");
01211 printf("Monitor a key for some value change. It will block your command line until a change in the key value is detected, then return its new value.\n");
01212 printf("\n");
01213 }
01214
01215
01244 int commandEdit() {
01245 KeySet *ks;
01246 KeySet *ksEdited;
01247 KeySet *toRemove;
01248 Key *current;
01249 int ret;
01250 char filename[]="/var/tmp/kdbeditXXXXXX";
01251 char command[300];
01252 FILE *xmlfile=0;
01253 char choice[5];
01254
01255 if (!ksFromXMLfile) return 1;
01256
01257 ks=ksNew();
01258
01259 kdbGetChildKeys(argKeyName,ks, KDB_O_SORT | KDB_O_NFOLLOWLINK |
01260 (argAll?KDB_O_INACTIVE:0) | (argRecursive?KDB_O_RECURSIVE:0));
01261
01262 if (! ksGetSize(ks)) {
01263
01264 current=keyNew(argKeyName,KEY_SWITCH_END);
01265 if (kdbGetKey(current)) {
01266
01267 keyDel(current);
01268 current=0;
01269 } else {
01270
01271 ksAppend(ks,current);
01272 current=0;
01273 }
01274 }
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284 xmlfile=fdopen(mkstemp(filename),"rw+");
01285
01286 ksToStream(ks,xmlfile,KDB_O_XMLHEADERS |
01287 (argFullName?(KDB_O_FULLNAME | KDB_O_FULLUGID):0));
01288 fclose(xmlfile);
01289
01290 do
01291 {
01292
01293 sprintf(command,"[ -z \"$EDITOR\" ] && EDITOR=vi; $EDITOR %s",filename);
01294 system(command);
01295
01296 toRemove=ksNew();
01297 ksEdited=ksNew();
01298
01299
01300
01301
01302
01303 ret=ksFromXMLfile(ksEdited,filename);
01304 if (ret!=0)
01305 {
01306 printf("kdb cannot import this file, because it is not valid !\n");
01307 strcpy(choice,"");
01308 while (choice[0]!='E' && choice[0]!='C')
01309 {
01310 printf("Do you want to edit it again or to cancel ? (E/C) : ");
01311 fgets(choice,4, stdin );
01312 }
01313 }
01314 }
01315 while (ret!=0 && choice[0]=='E');
01316 remove(filename);
01317
01318 if (ret==0)
01319 {
01320
01321 ksCompare(ks,ksEdited,toRemove);
01322
01323
01324
01325 ksDel(ksEdited);
01326
01327
01328 ksRewind(ks);
01329 while ((ret=kdbSetKeys(ks))) {
01330
01331 Key *problem;
01332 char error[500];
01333 char keyname[300]="";
01334
01335 problem=ksCurrent(ks);
01336 if (problem) keyGetFullName(problem,keyname,sizeof(keyname));
01337 sprintf(error,"kdb edit: while setting/updating %s", keyname);
01338 perror(error);
01339
01340
01341
01342 if (ksNext(ks) == 0) break;
01343 }
01344
01345 ksDel(ks);
01346
01347
01348 ksRewind(toRemove);
01349 while ((current=ksNext(toRemove))) {
01350 char keyName[800];
01351
01352 keyGetFullName(current,keyName,sizeof(keyName));
01353 ret=kdbRemove(keyName);
01354 if (ret != 0) {
01355 char error[850];
01356
01357 sprintf(error,"kdb edit: while removing %s",keyName);
01358 perror(error);
01359 }
01360 }
01361
01362
01363 ksDel(toRemove);
01364 }
01365
01366 return 0;
01367 }
01368
01369
01381 int commandInfo() {
01382 KDBInfo *libraryInfo;
01383 char textInfo[200];
01384
01385 libraryInfo=kdbGetInfo();
01386 kdbInfoToString(libraryInfo, textInfo, sizeof(textInfo));
01387
01388 printf("%s\n", textInfo);
01389
01390 return 0;
01391 }
01392
01393
01407 int commandImport() {
01408 KeySet *ks;
01409 int ret;
01410
01411 if (!ksFromXMLfile || !ksFromXML) return 1;
01412
01413
01414 ks=ksNew();
01415
01416
01417 if (argKeyName) ksFromXMLfile(ks,argKeyName);
01418 else ksFromXML(ks,fileno(stdin) );
01419
01420 ksRewind(ks);
01421 while ((ret=kdbSetKeys(ks))) {
01422
01423 Key *problem;
01424 char error[500]="";
01425 char keyname[300]="";
01426
01427 problem=ksCurrent(ks);
01428 if (problem) keyGetFullName(problem,keyname,sizeof(keyname));
01429 sprintf(error,"kdb import: while importing %s", keyname);
01430 perror(error);
01431
01432
01433
01434 if (ksNext(ks) == 0) break;
01435 }
01436
01437 return ret;
01438 }
01439
01440
01441
01442
01443
01460 int commandExport() {
01461
01462
01463
01464
01465 argSort=1;
01466 argRecursive=1;
01467 argAll=1;
01468 argXML=1;
01469 argShow=1;
01470 argValue=1;
01471
01472
01473
01474
01475 putenv("LANG=en_US.UTF-8");
01476
01477
01478 kdbClose();
01479 kdbOpen();
01480
01481 return commandList();
01482 }
01483
01484
01498 int commandMonitor() {
01499 Key *toMonitor;
01500 uint32_t diff;
01501
01502 toMonitor=keyNew(argKeyName,KEY_SWITCH_NEEDSYNC,KEY_SWITCH_END);
01503
01504 diff=kdbMonitorKey(
01505 toMonitor,
01506 KEY_SWITCH_VALUE,
01507 0,
01508 500 );
01509
01510
01511
01512
01513
01514
01515 printf("New value is %s\n",(char *)keyStealValue(toMonitor));
01516
01517 keyDel(toMonitor);
01518 return 0;
01519 }
01520
01521
01522 int loadToolsLib(void) {
01523 kdbLibHandle dlhandle=0;
01524
01525 kdbLibInit();
01526
01527 dlhandle=kdbLibLoad("libelektratools");
01528 if (dlhandle == 0) {
01529 return 1;
01530 }
01531
01532 ksFromXMLfile=kdbLibSym(dlhandle,"ksFromXMLfile");
01533 ksFromXML=kdbLibSym(dlhandle,"ksFromXML");
01534
01535 return 0;
01536 }
01537
01538 int doCommand(int command) {
01539 switch (command) {
01540 case CMD_SET: return commandSet();
01541 case CMD_LIST: return commandList();
01542 case CMD_LINK: return commandLink();
01543 case CMD_GET: return commandGet();
01544 case CMD_REMOVE: return commandRemove();
01545 case CMD_EDIT: return commandEdit();
01546 case CMD_LOAD: return commandImport();
01547 case CMD_SAVE: return commandExport();
01548 case CMD_MONITOR: return commandMonitor();
01549 case CMD_MOVE: return commandMove();
01550 case CMD_INFO: return commandInfo();
01551 case CMD_HELP: return commandHelp();
01552 }
01553 return 0;
01554 }
01555
01556 int helpCommand(int command) {
01557 switch (command) {
01558 case CMD_SET: commandSetHelp(); break;
01559 case CMD_LIST: commandListHelp(); break;
01560 case CMD_LINK: commandLinkHelp(); break;
01561 case CMD_GET: commandGetHelp(); break;
01562 case CMD_REMOVE: commandRemoveHelp(); break;
01563 case CMD_EDIT: commandEditHelp(); break;
01564 case CMD_LOAD: commandImportHelp(); break;
01565 case CMD_SAVE: commandExportHelp(); break;
01566 case CMD_MONITOR: commandMonitorHelp(); break;
01567 case CMD_MOVE: commandMoveHelp(); break;
01568 case CMD_INFO: commandInfoHelp(); break;
01569 }
01570 exit (0);
01571 }
01572
01573 void cleanup()
01574 {
01575 kdbClose();
01576 }
01577
01578 int main(int argc, char **argv) {
01579 int command=0;
01580 int ret=0;
01581
01582
01583 if (loadToolsLib())
01584 fprintf(stderr,"kdb: XML importing and editing disabled\n");
01585
01586 command=parseCommandLine(argc,argv);
01587
01588 if (argHelp) helpCommand(command);
01589
01590 kdbOpen();
01591 atexit(cleanup);
01593 ret=doCommand(command);
01594
01595 exit(ret);
01596 }
01597