00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifdef CONFIG_TEST
00013
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016
00017 #include <fcntl.h>
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <tcl.h>
00021 #endif
00022
00023 #define DB_DBM_HSEARCH 1
00024
00025 #include "db_int.h"
00026 #include "dbinc/tcl_db.h"
00027
00028
00029
00030
00031
00032
00033
00034 int
00035 bdb_HCommand(interp, objc, objv)
00036 Tcl_Interp *interp;
00037 int objc;
00038 Tcl_Obj *CONST objv[];
00039 {
00040 static const char *hcmds[] = {
00041 "hcreate",
00042 "hdestroy",
00043 "hsearch",
00044 NULL
00045 };
00046 enum hcmds {
00047 HHCREATE,
00048 HHDESTROY,
00049 HHSEARCH
00050 };
00051 static const char *srchacts[] = {
00052 "enter",
00053 "find",
00054 NULL
00055 };
00056 enum srchacts {
00057 ACT_ENTER,
00058 ACT_FIND
00059 };
00060 ENTRY item, *hres;
00061 ACTION action;
00062 int actindex, cmdindex, nelem, result, ret;
00063 Tcl_Obj *res;
00064
00065 result = TCL_OK;
00066
00067
00068
00069
00070
00071 if (Tcl_GetIndexFromObj(interp,
00072 objv[1], hcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
00073 return (IS_HELP(objv[1]));
00074
00075 res = NULL;
00076 switch ((enum hcmds)cmdindex) {
00077 case HHCREATE:
00078
00079
00080
00081 if (objc != 3) {
00082 Tcl_WrongNumArgs(interp, 2, objv, "nelem");
00083 return (TCL_ERROR);
00084 }
00085 result = Tcl_GetIntFromObj(interp, objv[2], &nelem);
00086 if (result == TCL_OK) {
00087 _debug_check();
00088 ret = hcreate((size_t)nelem) == 0 ? 1: 0;
00089 (void)_ReturnSetup(
00090 interp, ret, DB_RETOK_STD(ret), "hcreate");
00091 }
00092 break;
00093 case HHSEARCH:
00094
00095
00096
00097 if (objc != 5) {
00098 Tcl_WrongNumArgs(interp, 2, objv, "key data action");
00099 return (TCL_ERROR);
00100 }
00101 item.key = Tcl_GetStringFromObj(objv[2], NULL);
00102 item.data = Tcl_GetStringFromObj(objv[3], NULL);
00103 if (Tcl_GetIndexFromObj(interp, objv[4], srchacts,
00104 "action", TCL_EXACT, &actindex) != TCL_OK)
00105 return (IS_HELP(objv[4]));
00106 switch ((enum srchacts)actindex) {
00107 case ACT_ENTER:
00108 action = ENTER;
00109 break;
00110 default:
00111 case ACT_FIND:
00112 action = FIND;
00113 break;
00114 }
00115 _debug_check();
00116 hres = hsearch(item, action);
00117 if (hres == NULL)
00118 Tcl_SetResult(interp, "-1", TCL_STATIC);
00119 else if (action == FIND)
00120 Tcl_SetResult(interp, (char *)hres->data, TCL_STATIC);
00121 else
00122
00123 Tcl_SetResult(interp, "0", TCL_STATIC);
00124
00125 break;
00126 case HHDESTROY:
00127
00128
00129
00130 if (objc != 2) {
00131 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00132 return (TCL_ERROR);
00133 }
00134 _debug_check();
00135 hdestroy();
00136 res = Tcl_NewIntObj(0);
00137 break;
00138 }
00139
00140
00141
00142
00143 if (result == TCL_OK && res)
00144 Tcl_SetObjResult(interp, res);
00145 return (result);
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 int
00158 bdb_NdbmOpen(interp, objc, objv, dbpp)
00159 Tcl_Interp *interp;
00160 int objc;
00161 Tcl_Obj *CONST objv[];
00162 DBM **dbpp;
00163 {
00164 static const char *ndbopen[] = {
00165 "-create",
00166 "-mode",
00167 "-rdonly",
00168 "-truncate",
00169 "--",
00170 NULL
00171 };
00172 enum ndbopen {
00173 NDB_CREATE,
00174 NDB_MODE,
00175 NDB_RDONLY,
00176 NDB_TRUNC,
00177 NDB_ENDARG
00178 };
00179
00180 int endarg, i, mode, open_flags, optindex, read_only, result, ret;
00181 char *arg, *db;
00182
00183 result = TCL_OK;
00184 endarg = mode = open_flags = read_only = 0;
00185
00186 if (objc < 2) {
00187 Tcl_WrongNumArgs(interp, 2, objv, "?args?");
00188 return (TCL_ERROR);
00189 }
00190
00191
00192
00193
00194
00195 i = 2;
00196 while (i < objc) {
00197 if (Tcl_GetIndexFromObj(interp, objv[i], ndbopen, "option",
00198 TCL_EXACT, &optindex) != TCL_OK) {
00199 arg = Tcl_GetStringFromObj(objv[i], NULL);
00200 if (arg[0] == '-') {
00201 result = IS_HELP(objv[i]);
00202 goto error;
00203 } else
00204 Tcl_ResetResult(interp);
00205 break;
00206 }
00207 i++;
00208 switch ((enum ndbopen)optindex) {
00209 case NDB_CREATE:
00210 open_flags |= O_CREAT;
00211 break;
00212 case NDB_RDONLY:
00213 read_only = 1;
00214 break;
00215 case NDB_TRUNC:
00216 open_flags |= O_TRUNC;
00217 break;
00218 case NDB_MODE:
00219 if (i >= objc) {
00220 Tcl_WrongNumArgs(interp, 2, objv,
00221 "?-mode mode?");
00222 result = TCL_ERROR;
00223 break;
00224 }
00225
00226
00227
00228
00229
00230
00231 result = Tcl_GetIntFromObj(interp, objv[i++], &mode);
00232 break;
00233 case NDB_ENDARG:
00234 endarg = 1;
00235 break;
00236 }
00237
00238
00239
00240
00241
00242 if (result != TCL_OK)
00243 goto error;
00244 if (endarg)
00245 break;
00246 }
00247 if (result != TCL_OK)
00248 goto error;
00249
00250
00251
00252
00253
00254
00255 db = NULL;
00256 if (i != objc && i != objc - 1) {
00257 Tcl_WrongNumArgs(interp, 2, objv, "?args? ?file?");
00258 result = TCL_ERROR;
00259 goto error;
00260 }
00261 if (i != objc)
00262 db = Tcl_GetStringFromObj(objv[objc - 1], NULL);
00263
00264
00265
00266
00267
00268
00269
00270
00271 if (read_only)
00272 open_flags |= O_RDONLY;
00273 else
00274 open_flags |= O_RDWR;
00275 _debug_check();
00276 if ((*dbpp = dbm_open(db, open_flags, mode)) == NULL) {
00277 ret = Tcl_GetErrno();
00278 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00279 "db open");
00280 goto error;
00281 }
00282 return (TCL_OK);
00283
00284 error:
00285 *dbpp = NULL;
00286 return (result);
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 int
00299 bdb_DbmCommand(interp, objc, objv, flag, dbm)
00300 Tcl_Interp *interp;
00301 int objc;
00302 Tcl_Obj *CONST objv[];
00303 int flag;
00304 DBM *dbm;
00305 {
00306 static const char *dbmcmds[] = {
00307 "dbmclose",
00308 "dbminit",
00309 "delete",
00310 "fetch",
00311 "firstkey",
00312 "nextkey",
00313 "store",
00314 NULL
00315 };
00316 enum dbmcmds {
00317 DBMCLOSE,
00318 DBMINIT,
00319 DBMDELETE,
00320 DBMFETCH,
00321 DBMFIRST,
00322 DBMNEXT,
00323 DBMSTORE
00324 };
00325 static const char *stflag[] = {
00326 "insert", "replace",
00327 NULL
00328 };
00329 enum stflag {
00330 STINSERT, STREPLACE
00331 };
00332 datum key, data;
00333 void *dtmp, *ktmp;
00334 u_int32_t size;
00335 int cmdindex, freedata, freekey, stindex, result, ret;
00336 char *name, *t;
00337
00338 result = TCL_OK;
00339 freekey = freedata = 0;
00340 dtmp = ktmp = NULL;
00341
00342
00343
00344
00345
00346
00347 if (Tcl_GetIndexFromObj(interp,
00348 objv[1], dbmcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
00349 return (IS_HELP(objv[1]));
00350
00351 switch ((enum dbmcmds)cmdindex) {
00352 case DBMCLOSE:
00353
00354
00355
00356 if (objc != 2) {
00357 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00358 return (TCL_ERROR);
00359 }
00360 _debug_check();
00361 if (flag == DBTCL_DBM)
00362 ret = dbmclose();
00363 else {
00364 Tcl_SetResult(interp,
00365 "Bad interface flag for command", TCL_STATIC);
00366 return (TCL_ERROR);
00367 }
00368 (void)_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "dbmclose");
00369 break;
00370 case DBMINIT:
00371
00372
00373
00374 if (objc != 3) {
00375 Tcl_WrongNumArgs(interp, 2, objv, "file");
00376 return (TCL_ERROR);
00377 }
00378 name = Tcl_GetStringFromObj(objv[2], NULL);
00379 if (flag == DBTCL_DBM)
00380 ret = dbminit(name);
00381 else {
00382 Tcl_SetResult(interp, "Bad interface flag for command",
00383 TCL_STATIC);
00384 return (TCL_ERROR);
00385 }
00386 (void)_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "dbminit");
00387 break;
00388 case DBMFETCH:
00389
00390
00391
00392 if (objc != 3) {
00393 Tcl_WrongNumArgs(interp, 2, objv, "key");
00394 return (TCL_ERROR);
00395 }
00396 if ((ret = _CopyObjBytes(
00397 interp, objv[2], &ktmp, &size, &freekey)) != 0) {
00398 result = _ReturnSetup(interp, ret,
00399 DB_RETOK_STD(ret), "dbm fetch");
00400 goto out;
00401 }
00402 key.dsize = (int)size;
00403 key.dptr = (char *)ktmp;
00404 _debug_check();
00405 if (flag == DBTCL_DBM)
00406 data = fetch(key);
00407 else if (flag == DBTCL_NDBM)
00408 data = dbm_fetch(dbm, key);
00409 else {
00410 Tcl_SetResult(interp,
00411 "Bad interface flag for command", TCL_STATIC);
00412 result = TCL_ERROR;
00413 goto out;
00414 }
00415 if (data.dptr == NULL ||
00416 (ret = __os_malloc(NULL, (size_t)data.dsize + 1, &t)) != 0)
00417 Tcl_SetResult(interp, "-1", TCL_STATIC);
00418 else {
00419 memcpy(t, data.dptr, (size_t)data.dsize);
00420 t[data.dsize] = '\0';
00421 Tcl_SetResult(interp, t, TCL_VOLATILE);
00422 __os_free(NULL, t);
00423 }
00424 break;
00425 case DBMSTORE:
00426
00427
00428
00429 if (objc != 4 && flag == DBTCL_DBM) {
00430 Tcl_WrongNumArgs(interp, 2, objv, "key data");
00431 return (TCL_ERROR);
00432 }
00433 if (objc != 5 && flag == DBTCL_NDBM) {
00434 Tcl_WrongNumArgs(interp, 2, objv, "key data action");
00435 return (TCL_ERROR);
00436 }
00437 if ((ret = _CopyObjBytes(
00438 interp, objv[2], &ktmp, &size, &freekey)) != 0) {
00439 result = _ReturnSetup(interp, ret,
00440 DB_RETOK_STD(ret), "dbm fetch");
00441 goto out;
00442 }
00443 key.dsize = (int)size;
00444 key.dptr = (char *)ktmp;
00445 if ((ret = _CopyObjBytes(
00446 interp, objv[3], &dtmp, &size, &freedata)) != 0) {
00447 result = _ReturnSetup(interp, ret,
00448 DB_RETOK_STD(ret), "dbm fetch");
00449 goto out;
00450 }
00451 data.dsize = (int)size;
00452 data.dptr = (char *)dtmp;
00453 _debug_check();
00454 if (flag == DBTCL_DBM)
00455 ret = store(key, data);
00456 else if (flag == DBTCL_NDBM) {
00457 if (Tcl_GetIndexFromObj(interp, objv[4], stflag,
00458 "flag", TCL_EXACT, &stindex) != TCL_OK)
00459 return (IS_HELP(objv[4]));
00460 switch ((enum stflag)stindex) {
00461 case STINSERT:
00462 flag = DBM_INSERT;
00463 break;
00464 case STREPLACE:
00465 flag = DBM_REPLACE;
00466 break;
00467 }
00468 ret = dbm_store(dbm, key, data, flag);
00469 } else {
00470 Tcl_SetResult(interp,
00471 "Bad interface flag for command", TCL_STATIC);
00472 return (TCL_ERROR);
00473 }
00474 (void)_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "store");
00475 break;
00476 case DBMDELETE:
00477
00478
00479
00480 if (objc != 3) {
00481 Tcl_WrongNumArgs(interp, 2, objv, "key");
00482 return (TCL_ERROR);
00483 }
00484 if ((ret = _CopyObjBytes(
00485 interp, objv[2], &ktmp, &size, &freekey)) != 0) {
00486 result = _ReturnSetup(interp, ret,
00487 DB_RETOK_STD(ret), "dbm fetch");
00488 goto out;
00489 }
00490 key.dsize = (int)size;
00491 key.dptr = (char *)ktmp;
00492 _debug_check();
00493 if (flag == DBTCL_DBM)
00494 ret = delete(key);
00495 else if (flag == DBTCL_NDBM)
00496 ret = dbm_delete(dbm, key);
00497 else {
00498 Tcl_SetResult(interp,
00499 "Bad interface flag for command", TCL_STATIC);
00500 return (TCL_ERROR);
00501 }
00502 (void)_ReturnSetup(interp, ret, DB_RETOK_STD(ret), "delete");
00503 break;
00504 case DBMFIRST:
00505
00506
00507
00508 if (objc != 2) {
00509 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00510 return (TCL_ERROR);
00511 }
00512 _debug_check();
00513 if (flag == DBTCL_DBM)
00514 key = firstkey();
00515 else if (flag == DBTCL_NDBM)
00516 key = dbm_firstkey(dbm);
00517 else {
00518 Tcl_SetResult(interp,
00519 "Bad interface flag for command", TCL_STATIC);
00520 return (TCL_ERROR);
00521 }
00522 if (key.dptr == NULL ||
00523 (ret = __os_malloc(NULL, (size_t)key.dsize + 1, &t)) != 0)
00524 Tcl_SetResult(interp, "-1", TCL_STATIC);
00525 else {
00526 memcpy(t, key.dptr, (size_t)key.dsize);
00527 t[key.dsize] = '\0';
00528 Tcl_SetResult(interp, t, TCL_VOLATILE);
00529 __os_free(NULL, t);
00530 }
00531 break;
00532 case DBMNEXT:
00533
00534
00535
00536 _debug_check();
00537 if (flag == DBTCL_DBM) {
00538 if (objc != 3) {
00539 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00540 return (TCL_ERROR);
00541 }
00542 if ((ret = _CopyObjBytes(
00543 interp, objv[2], &ktmp, &size, &freekey)) != 0) {
00544 result = _ReturnSetup(interp, ret,
00545 DB_RETOK_STD(ret), "dbm fetch");
00546 goto out;
00547 }
00548 key.dsize = (int)size;
00549 key.dptr = (char *)ktmp;
00550 data = nextkey(key);
00551 } else if (flag == DBTCL_NDBM) {
00552 if (objc != 2) {
00553 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00554 return (TCL_ERROR);
00555 }
00556 data = dbm_nextkey(dbm);
00557 } else {
00558 Tcl_SetResult(interp,
00559 "Bad interface flag for command", TCL_STATIC);
00560 return (TCL_ERROR);
00561 }
00562 if (data.dptr == NULL ||
00563 (ret = __os_malloc(NULL, (size_t)data.dsize + 1, &t)) != 0)
00564 Tcl_SetResult(interp, "-1", TCL_STATIC);
00565 else {
00566 memcpy(t, data.dptr, (size_t)data.dsize);
00567 t[data.dsize] = '\0';
00568 Tcl_SetResult(interp, t, TCL_VOLATILE);
00569 __os_free(NULL, t);
00570 }
00571 break;
00572 }
00573
00574 out: if (dtmp != NULL && freedata)
00575 __os_free(NULL, dtmp);
00576 if (ktmp != NULL && freekey)
00577 __os_free(NULL, ktmp);
00578 return (result);
00579 }
00580
00581
00582
00583
00584
00585
00586
00587 int
00588 ndbm_Cmd(clientData, interp, objc, objv)
00589 ClientData clientData;
00590 Tcl_Interp *interp;
00591 int objc;
00592 Tcl_Obj *CONST objv[];
00593 {
00594 static const char *ndbcmds[] = {
00595 "clearerr",
00596 "close",
00597 "delete",
00598 "dirfno",
00599 "error",
00600 "fetch",
00601 "firstkey",
00602 "nextkey",
00603 "pagfno",
00604 "rdonly",
00605 "store",
00606 NULL
00607 };
00608 enum ndbcmds {
00609 NDBCLRERR,
00610 NDBCLOSE,
00611 NDBDELETE,
00612 NDBDIRFNO,
00613 NDBERR,
00614 NDBFETCH,
00615 NDBFIRST,
00616 NDBNEXT,
00617 NDBPAGFNO,
00618 NDBRDONLY,
00619 NDBSTORE
00620 };
00621 DBM *dbp;
00622 DBTCL_INFO *dbip;
00623 Tcl_Obj *res;
00624 int cmdindex, result, ret;
00625
00626 Tcl_ResetResult(interp);
00627 dbp = (DBM *)clientData;
00628 dbip = _PtrToInfo((void *)dbp);
00629 result = TCL_OK;
00630 if (objc <= 1) {
00631 Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
00632 return (TCL_ERROR);
00633 }
00634 if (dbp == NULL) {
00635 Tcl_SetResult(interp, "NULL db pointer", TCL_STATIC);
00636 return (TCL_ERROR);
00637 }
00638 if (dbip == NULL) {
00639 Tcl_SetResult(interp, "NULL db info pointer", TCL_STATIC);
00640 return (TCL_ERROR);
00641 }
00642
00643
00644
00645
00646
00647 if (Tcl_GetIndexFromObj(interp,
00648 objv[1], ndbcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
00649 return (IS_HELP(objv[1]));
00650
00651 res = NULL;
00652 switch ((enum ndbcmds)cmdindex) {
00653 case NDBCLOSE:
00654 _debug_check();
00655 dbm_close(dbp);
00656 (void)Tcl_DeleteCommand(interp, dbip->i_name);
00657 _DeleteInfo(dbip);
00658 res = Tcl_NewIntObj(0);
00659 break;
00660 case NDBDELETE:
00661 case NDBFETCH:
00662 case NDBFIRST:
00663 case NDBNEXT:
00664 case NDBSTORE:
00665 result = bdb_DbmCommand(interp, objc, objv, DBTCL_NDBM, dbp);
00666 break;
00667 case NDBCLRERR:
00668
00669
00670
00671 if (objc > 2) {
00672 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00673 return (TCL_ERROR);
00674 }
00675 _debug_check();
00676 ret = dbm_clearerr(dbp);
00677 if (ret)
00678 (void)_ReturnSetup(
00679 interp, ret, DB_RETOK_STD(ret), "clearerr");
00680 else
00681 res = Tcl_NewIntObj(ret);
00682 break;
00683 case NDBDIRFNO:
00684
00685
00686
00687 if (objc > 2) {
00688 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00689 return (TCL_ERROR);
00690 }
00691 _debug_check();
00692 ret = dbm_dirfno(dbp);
00693 res = Tcl_NewIntObj(ret);
00694 break;
00695 case NDBPAGFNO:
00696
00697
00698
00699 if (objc > 2) {
00700 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00701 return (TCL_ERROR);
00702 }
00703 _debug_check();
00704 ret = dbm_pagfno(dbp);
00705 res = Tcl_NewIntObj(ret);
00706 break;
00707 case NDBERR:
00708
00709
00710
00711 if (objc > 2) {
00712 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00713 return (TCL_ERROR);
00714 }
00715 _debug_check();
00716 ret = dbm_error(dbp);
00717 Tcl_SetErrno(ret);
00718 Tcl_SetResult(interp,
00719 (char *)Tcl_PosixError(interp), TCL_STATIC);
00720 break;
00721 case NDBRDONLY:
00722
00723
00724
00725 if (objc > 2) {
00726 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00727 return (TCL_ERROR);
00728 }
00729 _debug_check();
00730 ret = dbm_rdonly(dbp);
00731 if (ret)
00732 (void)_ReturnSetup(
00733 interp, ret, DB_RETOK_STD(ret), "rdonly");
00734 else
00735 res = Tcl_NewIntObj(ret);
00736 break;
00737 }
00738
00739
00740
00741
00742
00743 if (result == TCL_OK && res)
00744 Tcl_SetObjResult(interp, res);
00745 return (result);
00746 }
00747 #endif