4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
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 2 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, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Component: ldbsearch
30 * Description: utility for ldb search - modelled on ldapsearch
32 * Author: Andrew Tridgell
36 #include "ldb/include/includes.h"
37 #include "ldb/tools/cmdline.h"
39 static void usage(void)
41 printf("Usage: ldbsearch <options> <expression> <attrs...>\n");
43 printf(" -H ldb_url choose the database (or $LDB_URL)\n");
44 printf(" -s base|sub|one choose search scope\n");
45 printf(" -b basedn choose baseDN\n");
46 printf(" -i read search expressions from stdin\n");
47 printf(" -S sort returned attributes\n");
48 printf(" -o options pass options like modules to activate\n");
49 printf(" e.g: -o modules:timestamps\n");
53 static int do_compare_msg(struct ldb_message
**el1
,
54 struct ldb_message
**el2
,
57 struct ldb_context
*ldb
= talloc_get_type(opaque
, struct ldb_context
);
58 return ldb_dn_compare(ldb
, (*el1
)->dn
, (*el2
)->dn
);
61 struct search_context
{
62 struct ldb_control
**req_ctrls
;
66 struct ldb_message
**store
;
76 static int store_message(struct ldb_message
*msg
, struct search_context
*sctx
) {
78 sctx
->store
= talloc_realloc(sctx
, sctx
->store
, struct ldb_message
*, sctx
->num_stored
+ 2);
80 fprintf(stderr
, "talloc_realloc failed while storing messages\n");
84 sctx
->store
[sctx
->num_stored
] = talloc_move(sctx
->store
, &msg
);
86 sctx
->store
[sctx
->num_stored
] = NULL
;
91 static int store_referral(char *referral
, struct search_context
*sctx
) {
93 sctx
->refs_store
= talloc_realloc(sctx
, sctx
->refs_store
, char *, sctx
->refs
+ 2);
94 if (!sctx
->refs_store
) {
95 fprintf(stderr
, "talloc_realloc failed while storing referrals\n");
99 sctx
->refs_store
[sctx
->refs
] = talloc_move(sctx
->refs_store
, &referral
);
101 sctx
->refs_store
[sctx
->refs
] = NULL
;
106 static int display_message(struct ldb_context
*ldb
, struct ldb_message
*msg
, struct search_context
*sctx
) {
107 struct ldb_ldif ldif
;
110 printf("# record %d\n", sctx
->entries
);
112 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
117 * Ensure attributes are always returned in the same
118 * order. For testing, this makes comparison of old
119 * vs. new much easier.
121 ldb_msg_sort_elements(ldif
.msg
);
124 ldb_ldif_write_file(ldb
, stdout
, &ldif
);
129 static int display_referral(char *referral
, struct search_context
*sctx
)
133 printf("# Referral\nref: %s\n\n", referral
);
138 static int search_callback(struct ldb_context
*ldb
, void *context
, struct ldb_reply
*ares
)
140 struct search_context
*sctx
= talloc_get_type(context
, struct search_context
);
143 switch (ares
->type
) {
145 case LDB_REPLY_ENTRY
:
147 ret
= store_message(ares
->message
, sctx
);
149 ret
= display_message(ldb
, ares
->message
, sctx
);
153 case LDB_REPLY_REFERRAL
:
155 ret
= store_referral(ares
->referral
, sctx
);
157 ret
= display_referral(ares
->referral
, sctx
);
162 if (ares
->controls
) {
163 if (handle_controls_reply(ares
->controls
, sctx
->req_ctrls
) == 1)
170 fprintf(stderr
, "unknown Reply Type\n");
171 return LDB_ERR_OTHER
;
174 if (talloc_free(ares
) == -1) {
175 fprintf(stderr
, "talloc_free failed\n");
177 return LDB_ERR_OPERATIONS_ERROR
;
181 return LDB_ERR_OPERATIONS_ERROR
;
187 static int do_search(struct ldb_context
*ldb
,
188 const struct ldb_dn
*basedn
,
189 struct ldb_cmdline
*options
,
190 const char *expression
,
191 const char * const *attrs
)
193 struct ldb_request
*req
;
194 struct search_context
*sctx
;
197 req
= talloc(ldb
, struct ldb_request
);
200 sctx
= talloc(req
, struct search_context
);
201 if (!sctx
) return -1;
203 sctx
->sort
= options
->sorted
;
204 sctx
->num_stored
= 0;
206 sctx
->req_ctrls
= parse_controls(ldb
, options
->controls
);
207 if (options
->controls
!= NULL
&& sctx
->req_ctrls
== NULL
) return -1;
211 if (basedn
== NULL
) {
212 basedn
= ldb_get_default_basedn(ldb
);
215 req
->operation
= LDB_SEARCH
;
216 req
->op
.search
.base
= basedn
;
217 req
->op
.search
.scope
= options
->scope
;
218 req
->op
.search
.tree
= ldb_parse_tree(req
, expression
);
219 if (req
->op
.search
.tree
== NULL
) return -1;
220 req
->op
.search
.attrs
= attrs
;
221 req
->controls
= sctx
->req_ctrls
;
223 req
->callback
= &search_callback
;
224 ldb_set_timeout(ldb
, req
, 0); /* TODO: make this settable by command line */
229 ret
= ldb_request(ldb
, req
);
230 if (ret
!= LDB_SUCCESS
) {
231 printf("search failed - %s\n", ldb_errstring(ldb
));
235 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
236 if (ret
!= LDB_SUCCESS
) {
237 printf("search error - %s\n", ldb_errstring(ldb
));
244 if (sctx
->sort
&& sctx
->num_stored
!= 0) {
247 ldb_qsort(sctx
->store
, ret
, sizeof(struct ldb_message
*),
248 ldb
, (ldb_qsort_cmp_fn_t
)do_compare_msg
);
251 fprintf(stderr
, "An error occurred while sorting messages\n");
255 for (i
= 0; i
< sctx
->num_stored
; i
++) {
256 display_message(ldb
, sctx
->store
[i
], sctx
);
259 for (i
= 0; i
< sctx
->refs
; i
++) {
260 display_referral(sctx
->refs_store
[i
], sctx
);
264 printf("# returned %d records\n# %d entries\n# %d referrals\n",
265 sctx
->entries
+ sctx
->refs
, sctx
->entries
, sctx
->refs
);
272 int main(int argc
, const char **argv
)
274 struct ldb_context
*ldb
;
275 struct ldb_dn
*basedn
= NULL
;
276 const char * const * attrs
= NULL
;
277 struct ldb_cmdline
*options
;
279 const char *expression
= "(|(objectClass=*)(distinguishedName=*))";
283 ldb
= ldb_init(NULL
);
285 options
= ldb_cmdline_process(ldb
, argc
, argv
, usage
);
287 /* the check for '=' is for compatibility with ldapsearch */
288 if (!options
->interactive
&&
290 strchr(options
->argv
[0], '=')) {
291 expression
= options
->argv
[0];
296 if (options
->argc
> 0) {
297 attrs
= (const char * const *)(options
->argv
);
300 if (options
->basedn
!= NULL
) {
301 basedn
= ldb_dn_explode(ldb
, options
->basedn
);
302 if (basedn
== NULL
) {
303 fprintf(stderr
, "Invalid Base DN format\n");
308 if (options
->interactive
) {
310 while (fgets(line
, sizeof(line
), stdin
)) {
311 if (do_search(ldb
, basedn
, options
, line
, attrs
) == -1) {
316 ret
= do_search(ldb
, basedn
, options
, expression
, attrs
);