drsuapi.idl: fix source_dsa spelling
[samba4-gss.git] / lib / ldb / tools / cmdline.c
blobff25fe05ec7cd5ef59a8138fc7de11908f4d4fb5
1 /*
2 ldb database library - command line handling for ldb tools
4 Copyright (C) Andrew Tridgell 2005
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
8 ** under the LGPL
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "replace.h"
25 #include "system/filesys.h"
26 #include "system/time.h"
27 #include "ldb.h"
28 #include "ldb_module.h"
29 #include "tools/cmdline.h"
31 static struct ldb_cmdline options; /* needs to be static for older compilers */
33 enum ldb_cmdline_options { CMDLINE_RELAX=1 };
35 static struct poptOption builtin_popt_options[] = {
36 POPT_AUTOHELP
38 .longName = "url",
39 .shortName = 'H',
40 .argInfo = POPT_ARG_STRING,
41 .arg = &options.url,
42 .val = 0,
43 .descrip = "database URL",
44 .argDescrip = "URL"
47 .longName = "basedn",
48 .shortName = 'b',
49 .argInfo = POPT_ARG_STRING,
50 .arg = &options.basedn,
51 .val = 0,
52 .descrip = "base DN",
53 .argDescrip = "DN"
56 .longName = "editor",
57 .shortName = 'e',
58 .argInfo = POPT_ARG_STRING,
59 .arg = &options.editor,
60 .val = 0,
61 .descrip = "external editor",
62 .argDescrip = "PROGRAM"
65 .longName = "scope",
66 .shortName = 's',
67 .argInfo = POPT_ARG_STRING,
68 .arg = NULL,
69 .val = 's',
70 .descrip = "search scope",
71 .argDescrip = "SCOPE"
74 .longName = "verbose",
75 .shortName = 'v',
76 .argInfo = POPT_ARG_NONE,
77 .arg = NULL,
78 .val = 'v',
79 .descrip = "increase verbosity",
80 .argDescrip = NULL
83 .longName = "trace",
84 .shortName = 0,
85 .argInfo = POPT_ARG_NONE,
86 .arg = &options.tracing,
87 .val = 0,
88 .descrip = "enable tracing",
89 .argDescrip = NULL
92 .longName = "interactive",
93 .shortName = 'i',
94 .argInfo = POPT_ARG_NONE,
95 .arg = &options.interactive,
96 .val = 0,
97 .descrip = "input from stdin",
98 .argDescrip = NULL
101 .longName = "recursive",
102 .shortName = 'r',
103 .argInfo = POPT_ARG_NONE,
104 .arg = &options.recursive,
105 .val = 0,
106 .descrip = "recursive delete",
107 .argDescrip = NULL
110 .longName = "modules-path",
111 .shortName = 0,
112 .argInfo = POPT_ARG_STRING,
113 .arg = &options.modules_path,
114 .val = 0,
115 .descrip = "modules path",
116 .argDescrip = "PATH"
119 .longName = "num-searches",
120 .shortName = 0,
121 .argInfo = POPT_ARG_INT,
122 .arg = &options.num_searches,
123 .val = 0,
124 .descrip = "number of test searches",
125 .argDescrip = NULL
128 .longName = "num-records",
129 .shortName = 0,
130 .argInfo = POPT_ARG_INT,
131 .arg = &options.num_records,
132 .val = 0,
133 .descrip = "number of test records",
134 .argDescrip = NULL
137 .longName = "all",
138 .shortName = 'a',
139 .argInfo = POPT_ARG_NONE,
140 .arg = &options.all_records,
141 .val = 0,
142 .descrip = "(|(objectClass=*)(distinguishedName=*))",
143 .argDescrip = NULL
146 .longName = "nosync",
147 .shortName = 0,
148 .argInfo = POPT_ARG_NONE,
149 .arg = &options.nosync,
150 .val = 0,
151 .descrip = "non-synchronous transactions",
152 .argDescrip = NULL
155 .longName = "sorted",
156 .shortName = 'S',
157 .argInfo = POPT_ARG_NONE,
158 .arg = &options.sorted,
159 .val = 0,
160 .descrip = "sort attributes",
161 .argDescrip = NULL
164 .longName = NULL,
165 .shortName = 'o',
166 .argInfo = POPT_ARG_STRING,
167 .arg = NULL,
168 .val = 'o',
169 .descrip = "ldb_connect option",
170 .argDescrip = "OPTION"
173 .longName = "controls",
174 .shortName = 0,
175 .argInfo = POPT_ARG_STRING,
176 .arg = NULL,
177 .val = 'c',
178 .descrip = "controls",
179 .argDescrip = NULL
182 .longName = "show-binary",
183 .shortName = 0,
184 .argInfo = POPT_ARG_NONE,
185 .arg = &options.show_binary,
186 .val = 0,
187 .descrip = "display binary LDIF",
188 .argDescrip = NULL
191 .longName = "paged",
192 .shortName = 0,
193 .argInfo = POPT_ARG_NONE,
194 .arg = NULL,
195 .val = 'P',
196 .descrip = "use a paged search",
197 .argDescrip = NULL
200 .longName = "show-deleted",
201 .shortName = 0,
202 .argInfo = POPT_ARG_NONE,
203 .arg = NULL,
204 .val = 'D',
205 .descrip = "show deleted objects",
206 .argDescrip = NULL
209 .longName = "show-recycled",
210 .shortName = 0,
211 .argInfo = POPT_ARG_NONE,
212 .arg = NULL,
213 .val = 'R',
214 .descrip = "show recycled objects",
215 .argDescrip = NULL
218 .longName = "show-deactivated-link",
219 .shortName = 0,
220 .argInfo = POPT_ARG_NONE,
221 .arg = NULL,
222 .val = 'd',
223 .descrip = "show deactivated links",
224 .argDescrip = NULL
227 .longName = "reveal",
228 .shortName = 0,
229 .argInfo = POPT_ARG_NONE,
230 .arg = NULL,
231 .val = 'r',
232 .descrip = "reveal ldb internals",
233 .argDescrip = NULL
236 .longName = "relax",
237 .shortName = 0,
238 .argInfo = POPT_ARG_NONE,
239 .arg = NULL,
240 .val = CMDLINE_RELAX,
241 .descrip = "pass relax control",
242 .argDescrip = NULL
245 .longName = "cross-ncs",
246 .shortName = 0,
247 .argInfo = POPT_ARG_NONE,
248 .arg = NULL,
249 .val = 'N',
250 .descrip = "search across NC boundaries",
251 .argDescrip = NULL
254 .longName = "extended-dn",
255 .shortName = 0,
256 .argInfo = POPT_ARG_NONE,
257 .arg = NULL,
258 .val = 'E',
259 .descrip = "show extended DNs",
260 .argDescrip = NULL
262 POPT_TABLEEND
265 void ldb_cmdline_help(struct ldb_context *ldb, const char *cmdname, FILE *f)
267 poptContext pc;
268 struct poptOption **popt_options = ldb_module_popt_options(ldb);
269 pc = poptGetContext(cmdname, 0, NULL, *popt_options,
270 POPT_CONTEXT_KEEP_FIRST);
271 poptPrintHelp(pc, f, 0);
275 add a control to the options structure
277 static bool add_control(TALLOC_CTX *mem_ctx, const char *control)
279 unsigned int i;
281 /* count how many controls we already have */
282 for (i=0; options.controls && options.controls[i]; i++) ;
284 options.controls = talloc_realloc(mem_ctx, options.controls, const char *, i + 2);
285 if (options.controls == NULL) {
286 return false;
288 options.controls[i] = control;
289 options.controls[i+1] = NULL;
290 return true;
294 process command line options
296 static struct ldb_cmdline *ldb_cmdline_process_internal(struct ldb_context *ldb,
297 int argc, const char **argv,
298 void (*usage)(struct ldb_context *),
299 bool dont_create,
300 bool search)
302 struct ldb_cmdline *ret=NULL;
303 poptContext pc;
304 int num_options = 0;
305 int opt;
306 unsigned int flags = 0;
307 int rc;
308 struct poptOption **popt_options;
310 /* make the ldb utilities line buffered */
311 setlinebuf(stdout);
313 ret = talloc_zero(ldb, struct ldb_cmdline);
314 if (ret == NULL) {
315 fprintf(stderr, "Out of memory!\n");
316 goto failed;
319 options = *ret;
321 /* pull in URL */
322 options.url = getenv("LDB_URL");
324 /* and editor (used by ldbedit) */
325 options.editor = getenv("VISUAL");
326 if (!options.editor) {
327 options.editor = getenv("EDITOR");
329 if (!options.editor) {
330 options.editor = "vi";
333 options.scope = LDB_SCOPE_DEFAULT;
335 popt_options = ldb_module_popt_options(ldb);
336 (*popt_options) = builtin_popt_options;
338 rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_OPTIONS);
339 if (rc != LDB_SUCCESS) {
340 fprintf(stderr, "ldb: failed to run command line hooks : %s\n", ldb_strerror(rc));
341 goto failed;
344 pc = poptGetContext(argv[0], argc, argv, *popt_options,
345 POPT_CONTEXT_KEEP_FIRST);
347 while((opt = poptGetNextOpt(pc)) != -1) {
348 switch (opt) {
349 case 's': {
350 const char *arg = poptGetOptArg(pc);
351 if (strcmp(arg, "base") == 0) {
352 options.scope = LDB_SCOPE_BASE;
353 } else if (strcmp(arg, "sub") == 0) {
354 options.scope = LDB_SCOPE_SUBTREE;
355 } else if (strcmp(arg, "one") == 0) {
356 options.scope = LDB_SCOPE_ONELEVEL;
357 } else {
358 fprintf(stderr, "Invalid scope '%s'\n", arg);
359 goto failed;
361 break;
364 case 'v':
365 options.verbose++;
366 break;
368 case 'o':
369 options.options = talloc_realloc(ret, options.options,
370 const char *, num_options+3);
371 if (options.options == NULL) {
372 fprintf(stderr, "Out of memory!\n");
373 goto failed;
375 options.options[num_options] = poptGetOptArg(pc);
376 options.options[num_options+1] = NULL;
377 num_options++;
378 break;
380 case 'c': {
381 const char *cs = poptGetOptArg(pc);
382 const char *p;
384 for (p = cs; p != NULL; ) {
385 const char *t, *c;
387 t = strchr(p, ',');
388 if (t == NULL) {
389 c = talloc_strdup(options.controls, p);
390 p = NULL;
391 } else {
392 c = talloc_strndup(options.controls, p, t-p);
393 p = t + 1;
395 if (c == NULL || !add_control(ret, c)) {
396 fprintf(stderr, __location__ ": out of memory\n");
397 goto failed;
401 break;
403 case 'P':
404 if (!add_control(ret, "paged_results:1:1024")) {
405 fprintf(stderr, __location__ ": out of memory\n");
406 goto failed;
408 break;
409 case 'D':
410 if (!add_control(ret, "show_deleted:1")) {
411 fprintf(stderr, __location__ ": out of memory\n");
412 goto failed;
414 break;
415 case 'R':
416 if (!add_control(ret, "show_recycled:0")) {
417 fprintf(stderr, __location__ ": out of memory\n");
418 goto failed;
420 break;
421 case 'd':
422 if (!add_control(ret, "show_deactivated_link:0")) {
423 fprintf(stderr, __location__ ": out of memory\n");
424 goto failed;
426 break;
427 case 'r':
428 if (!add_control(ret, "reveal_internals:0")) {
429 fprintf(stderr, __location__ ": out of memory\n");
430 goto failed;
432 break;
433 case CMDLINE_RELAX:
434 if (!add_control(ret, "relax:0")) {
435 fprintf(stderr, __location__ ": out of memory\n");
436 goto failed;
438 break;
439 case 'N':
440 if (!add_control(ret, "search_options:1:2")) {
441 fprintf(stderr, __location__ ": out of memory\n");
442 goto failed;
444 break;
445 case 'E':
446 if (!add_control(ret, "extended_dn:1:1")) {
447 fprintf(stderr, __location__ ": out of memory\n");
448 goto failed;
450 break;
451 default:
452 fprintf(stderr, "Invalid option %s: %s\n",
453 poptBadOption(pc, 0), poptStrerror(opt));
454 if (usage) usage(ldb);
455 goto failed;
459 /* setup the remaining options for the main program to use */
460 options.argv = poptGetArgs(pc);
461 if (options.argv) {
462 options.argv++;
463 while (options.argv[options.argc]) options.argc++;
466 *ret = options;
468 /* all utils need some option */
469 if (ret->url == NULL) {
470 fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n");
471 if (usage) usage(ldb);
472 goto failed;
475 if (strcmp(ret->url, "NONE") == 0) {
476 return ret;
479 if (options.nosync) {
480 flags |= LDB_FLG_NOSYNC;
483 if (search) {
484 flags |= LDB_FLG_DONT_CREATE_DB;
486 if (options.show_binary) {
487 flags |= LDB_FLG_SHOW_BINARY;
491 if (options.tracing) {
492 flags |= LDB_FLG_ENABLE_TRACING;
495 if (options.modules_path != NULL) {
496 ldb_set_modules_dir(ldb, options.modules_path);
499 rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_PRECONNECT);
500 if (rc != LDB_SUCCESS) {
501 fprintf(stderr, "ldb: failed to run preconnect hooks : %s\n", ldb_strerror(rc));
502 goto failed;
505 /* now connect to the ldb */
506 if (ldb_connect(ldb, ret->url, flags, ret->options) != LDB_SUCCESS) {
507 fprintf(stderr, "Failed to connect to %s - %s\n",
508 ret->url, ldb_errstring(ldb));
509 goto failed;
512 rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_POSTCONNECT);
513 if (rc != LDB_SUCCESS) {
514 fprintf(stderr, "ldb: failed to run post connect hooks : %s\n", ldb_strerror(rc));
515 goto failed;
518 return ret;
520 failed:
521 talloc_free(ret);
522 exit(LDB_ERR_OPERATIONS_ERROR);
523 return NULL;
526 struct ldb_cmdline *ldb_cmdline_process_search(struct ldb_context *ldb,
527 int argc, const char **argv,
528 void (*usage)(struct ldb_context *))
530 return ldb_cmdline_process_internal(ldb, argc, argv, usage, true, true);
533 struct ldb_cmdline *ldb_cmdline_process_edit(struct ldb_context *ldb,
534 int argc, const char **argv,
535 void (*usage)(struct ldb_context *))
537 return ldb_cmdline_process_internal(ldb, argc, argv, usage, false, true);
540 struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb,
541 int argc, const char **argv,
542 void (*usage)(struct ldb_context *))
544 return ldb_cmdline_process_internal(ldb, argc, argv, usage, false, false);
547 /* this function check controls reply and determines if more
548 * processing is needed setting up the request controls correctly
550 * returns:
551 * -1 error
552 * 0 all ok
553 * 1 all ok, more processing required
555 int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request)
557 unsigned int i, j;
558 int ret = 0;
560 if (reply == NULL || request == NULL) return -1;
562 for (i = 0; reply[i]; i++) {
563 if (strcmp(LDB_CONTROL_VLV_RESP_OID, reply[i]->oid) == 0) {
564 struct ldb_vlv_resp_control *rep_control;
566 rep_control = talloc_get_type(reply[i]->data, struct ldb_vlv_resp_control);
567 if (rep_control == NULL) {
568 fprintf(stderr,
569 "Warning VLV reply OID received "
570 "with no VLV data\n");
571 continue;
574 /* check we have a matching control in the request */
575 for (j = 0; request[j]; j++) {
576 if (strcmp(LDB_CONTROL_VLV_REQ_OID, request[j]->oid) == 0)
577 break;
579 if (! request[j]) {
580 fprintf(stderr, "Warning VLV reply received but no request have been made\n");
581 continue;
584 /* check the result */
585 if (rep_control->vlv_result != 0) {
586 fprintf(stderr, "Warning: VLV not performed with error: %d\n", rep_control->vlv_result);
587 } else {
588 fprintf(stderr, "VLV Info: target position = %d, content count = %d\n", rep_control->targetPosition, rep_control->contentCount);
591 continue;
594 if (strcmp(LDB_CONTROL_ASQ_OID, reply[i]->oid) == 0) {
595 struct ldb_asq_control *rep_control;
597 rep_control = talloc_get_type(reply[i]->data, struct ldb_asq_control);
598 if (rep_control == NULL) {
599 fprintf(stderr,
600 "Warning ASQ reply OID received "
601 "with no ASQ data\n");
602 continue;
605 /* check the result */
606 if (rep_control->result != 0) {
607 fprintf(stderr, "Warning: ASQ not performed with error: %d\n", rep_control->result);
610 continue;
613 if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, reply[i]->oid) == 0) {
614 struct ldb_paged_control *rep_control, *req_control;
616 rep_control = talloc_get_type(reply[i]->data, struct ldb_paged_control);
617 if (rep_control == NULL) {
618 fprintf(stderr,
619 "Warning PAGED_RESULTS reply OID "
620 "received with no data\n");
621 continue;
624 if (rep_control->cookie_len == 0) { /* we are done */
625 break;
628 /* more processing required */
629 /* let's fill in the request control with the new cookie */
631 for (j = 0; request[j]; j++) {
632 if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, request[j]->oid) == 0)
633 break;
635 /* if there's a reply control we must find a request
636 * control matching it */
637 if (! request[j]) return -1;
639 req_control = talloc_get_type(request[j]->data, struct ldb_paged_control);
641 if (req_control->cookie)
642 talloc_free(req_control->cookie);
643 req_control->cookie = (char *)talloc_memdup(
644 req_control, rep_control->cookie,
645 rep_control->cookie_len);
646 req_control->cookie_len = rep_control->cookie_len;
648 ret = 1;
650 continue;
653 if (strcmp(LDB_CONTROL_SORT_RESP_OID, reply[i]->oid) == 0) {
654 struct ldb_sort_resp_control *rep_control;
656 rep_control = talloc_get_type(reply[i]->data, struct ldb_sort_resp_control);
657 if (rep_control == NULL) {
658 fprintf(stderr,
659 "Warning SORT reply OID "
660 "received with no data\n");
661 continue;
664 /* check we have a matching control in the request */
665 for (j = 0; request[j]; j++) {
666 if (strcmp(LDB_CONTROL_SERVER_SORT_OID, request[j]->oid) == 0)
667 break;
669 if (! request[j]) {
670 fprintf(stderr, "Warning Server Sort reply received but no request found\n");
671 continue;
674 /* check the result */
675 if (rep_control->result != 0) {
676 fprintf(stderr, "Warning: Sorting not performed with error: %d\n", rep_control->result);
679 continue;
682 if (strcmp(LDB_CONTROL_DIRSYNC_OID, reply[i]->oid) == 0) {
683 struct ldb_dirsync_control *rep_control, *req_control;
684 char *cookie;
686 rep_control = talloc_get_type(reply[i]->data, struct ldb_dirsync_control);
687 if (rep_control == NULL) {
688 fprintf(stderr,
689 "Warning DIRSYNC reply OID "
690 "received with no data\n");
691 continue;
693 if (rep_control->cookie_len == 0) /* we are done */
694 break;
696 /* more processing required */
697 /* let's fill in the request control with the new cookie */
699 for (j = 0; request[j]; j++) {
700 if (strcmp(LDB_CONTROL_DIRSYNC_OID, request[j]->oid) == 0)
701 break;
703 /* if there's a reply control we must find a request
704 * control matching it */
705 if (! request[j]) return -1;
707 req_control = talloc_get_type(request[j]->data, struct ldb_dirsync_control);
709 if (req_control->cookie)
710 talloc_free(req_control->cookie);
711 req_control->cookie = (char *)talloc_memdup(
712 req_control, rep_control->cookie,
713 rep_control->cookie_len);
714 req_control->cookie_len = rep_control->cookie_len;
716 cookie = ldb_base64_encode(req_control, rep_control->cookie, rep_control->cookie_len);
717 printf("# DIRSYNC cookie returned was:\n# %s\n", cookie);
719 continue;
721 if (strcmp(LDB_CONTROL_DIRSYNC_EX_OID, reply[i]->oid) == 0) {
722 struct ldb_dirsync_control *rep_control, *req_control;
723 char *cookie;
725 rep_control = talloc_get_type(reply[i]->data, struct ldb_dirsync_control);
726 if (rep_control == NULL) {
727 fprintf(stderr,
728 "Warning DIRSYNC_EX reply OID "
729 "received with no data\n");
730 continue;
732 if (rep_control->cookie_len == 0) /* we are done */
733 break;
735 /* more processing required */
736 /* let's fill in the request control with the new cookie */
738 for (j = 0; request[j]; j++) {
739 if (strcmp(LDB_CONTROL_DIRSYNC_EX_OID, request[j]->oid) == 0)
740 break;
742 /* if there's a reply control we must find a request
743 * control matching it */
744 if (! request[j]) return -1;
746 req_control = talloc_get_type(request[j]->data, struct ldb_dirsync_control);
748 if (req_control->cookie)
749 talloc_free(req_control->cookie);
750 req_control->cookie = (char *)talloc_memdup(
751 req_control, rep_control->cookie,
752 rep_control->cookie_len);
753 req_control->cookie_len = rep_control->cookie_len;
755 cookie = ldb_base64_encode(req_control, rep_control->cookie, rep_control->cookie_len);
756 printf("# DIRSYNC_EX cookie returned was:\n# %s\n", cookie);
758 continue;
761 /* no controls matched, throw a warning */
762 fprintf(stderr, "Unknown reply control oid: %s\n", reply[i]->oid);
765 return ret;