2 * Copyright (c) 1994, Strata Software Limited, Ottawa, Ontario, Canada.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to Eric Rosenquist and Strata Software Limited. The SSL name
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided "as is" without express or implied warranty.
13 * 'saucer' LDAP command-line client source code.
15 * Author: Eric Rosenquist, 1994.
26 #define DN_MAXLEN 4096
44 char *attrs_null[] = { "0.10", NULL };
46 char default_dn[DN_MAXLEN];
47 char *hostname = "127.0.0.1";
53 int portnum = LDAP_PORT;
55 char true_filter[] = "objectClass=*"; /* Always succeeds */
58 int cmd_help(char **cmdargv, int cmdargc);
59 int cmd_list(char **cmdargv, int cmdargc);
60 int cmd_moveto(char **cmdargv, int cmdargc);
61 int cmd_quit(char **cmdargv, int cmdargc);
62 int cmd_search(char **cmdargv, int cmdargc);
63 int cmd_set(char **cmdargv, int cmdargc);
64 int cmd_show(char **cmdargv, int cmdargc);
65 char *make_dn(char *dn, int relative);
66 char *skip_to_char(register char *s, register int c);
67 char *skip_to_whitespace(register char *s);
68 char *skip_whitespace(register char *s);
69 FILE *user_tailor(void);
71 static char *binary_attrs[] = { "audio", "jpegPhoto", "personalSignature", "photo" };
73 CMDTABLE cmdtable[] = {
74 "help" , cmd_help , "[command]",
75 "list" , cmd_list , "[RDN-or-DN] [-absolute]",
76 "moveto", cmd_moveto, "[RDN-or-DN] [-absolute]",
77 "quit" , cmd_quit , "",
78 "search", cmd_search, "<filter> [-object RDN-or-DN] [-absolute]\n\t\t[-scope base|onelevel|subtree]",
79 "set" , cmd_set , "[-aliasderef never|search|find|always] [-sizelimit N] [-timelimit seconds]",
80 "show" , cmd_show , "[RDN-or-DN] [-absolute]"
86 if (ldap_simple_bind_s(ld, username, credentials) != LDAP_SUCCESS) {
87 ldap_perror(ld, progname);
91 printf("Bound to ldap server as `%s' (%s authentication)\n", username,
92 credentials ? "simple" : "no");
94 puts("Bound anonymously to ldap server");
99 int cmd_help(char **cmdargv, int cmdargc)
104 for (i = 0; i < sizeof(cmdtable) / sizeof(cmdtable[0]); i++)
105 if (strncasecmp(cmdargv[1], cmdtable[i].cmd, strlen(cmdargv[1])) == 0) {
109 cmdargc = 1; /* Command not found - make it display the list of commands */
113 puts("\nType 'help <command>' for help on a particular command.\n\n"
114 "Supported commands are:");
115 for (i = 0; i < sizeof(cmdtable) / sizeof(cmdtable[0]); i++)
116 printf(" %s\n", cmdtable[i].cmd);
117 puts("\nArguments to commands are separated by whitespace. Single (')\n"
118 "or double (\") quotes must be used around arguments that contain\n"
119 "embedded whitespace characters.\n");
121 show_syntax(CMD_HELP);
126 int cmd_list(char **cmdargv, int cmdargc)
131 static char *opts[] = { "absolute" };
135 for (i = 1; i < cmdargc; i++) {
136 if (cmdargv[i][0] == '-') {
137 switch (table_lookup(cmdargv[i] + 1, opts, sizeof(opts) / sizeof(opts[0]))) {
153 show_syntax(CMD_LIST);
157 if (ldap_search(ld, make_dn(dn, relative), LDAP_SCOPE_ONELEVEL,
158 true_filter, attrs_null, 1) == -1) {
159 ldap_perror(ld, progname);
163 if (ldap_result(ld, LDAP_RES_ANY, 1, (struct timeval *)0, &result) == -1) {
164 ldap_perror(ld, progname);
168 display_search_results(result);
173 int cmd_moveto(char **cmdargv, int cmdargc)
179 static char *opts[] = { "absolute" };
182 for (i = 1; i < cmdargc; i++) {
183 if (cmdargv[i][0] == '-') {
184 switch (table_lookup(cmdargv[i] + 1, opts, sizeof(opts) / sizeof(opts[0]))) {
200 show_syntax(CMD_MOVETO);
205 if (is_whitespace(dn))
208 if (strcmp(dn, "..") == 0) {
209 /* Move up one level */
210 if (exploded_dn = ldap_explode_dn(default_dn, 0)) {
211 if (exploded_dn[0]) {
215 for (rdn = exploded_dn + 1; *rdn; rdn++) {
217 strcat(default_dn, ", ");
218 strcat(default_dn, *rdn);
221 ldap_value_free(exploded_dn);
224 /* Use ldap_explode_dn() to parse the string & test its syntax */
225 if (exploded_dn = ldap_explode_dn(dn, 1)) {
226 if (relative && !is_whitespace(default_dn)) {
229 strcpy(default_dn, strcat(strcat(strcpy(buf, dn), ", "), default_dn));
231 strcpy(default_dn, dn);
232 ldap_value_free(exploded_dn);
234 puts("Invalid distinguished name.");
239 printf("Distinguished name suffix is `%s'\n", default_dn);
244 int cmd_quit(char **cmdargv, int cmdargc)
249 int cmd_search(char **cmdargv, int cmdargc)
255 static char *opts[] = { "absolute", "object", "scope" };
258 static char *scope_opts[] = { "base", "onelevel", "subtree" };
259 static int scope_vals[] = { LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE };
260 static int search_scope = LDAP_SCOPE_ONELEVEL;
262 for (i = 1; i < cmdargc; i++) {
263 if (cmdargv[i][0] == '-') {
264 switch (table_lookup(cmdargv[i] + 1, opts, sizeof(opts) / sizeof(opts[0]))) {
275 if ((++i < cmdargc) &&
276 (j = table_lookup(cmdargv[i], scope_opts, sizeof(scope_opts) / sizeof(scope_opts[0]))) >= 0)
277 search_scope = scope_vals[j];
292 if (errflag || !filter) {
293 show_syntax(CMD_SEARCH);
297 if (ldap_search(ld, make_dn(dn, relative), search_scope, filter, attrs_null, 0) == -1) {
298 ldap_perror(ld, progname);
302 if (ldap_result(ld, LDAP_RES_ANY, 1, (struct timeval *)0, &result) == -1) {
303 ldap_perror(ld, progname);
307 display_search_results(result);
312 int cmd_set(char **cmdargv, int cmdargc)
314 static char *alias_opts[] = { "never", "search", "find", "always" };
317 static char *opts[] = { "aliasderef", "sizelimit", "timelimit" };
319 for (i = 1; i < cmdargc; i++) {
320 if (cmdargv[i][0] == '-') {
321 switch (table_lookup(cmdargv[i] + 1, opts, sizeof(opts) / sizeof(opts[0]))) {
323 if ((++i < cmdargc) &&
324 (j = table_lookup(cmdargv[i], alias_opts, sizeof(alias_opts) / sizeof(alias_opts[0]))) >= 0)
331 ld->ld_sizelimit = atoi(cmdargv[i]);
337 ld->ld_timelimit = atoi(cmdargv[i]);
349 show_syntax(CMD_SET);
351 printf("Alias dereferencing is %s, Sizelimit is %d entr%s, Timelimit is %d second%s.\n",
352 alias_opts[ld->ld_deref],
353 ld->ld_sizelimit, ld->ld_sizelimit == 1 ? "y" : "ies",
354 ld->ld_timelimit, ld->ld_timelimit == 1 ? "" : "s");
359 int cmd_show(char **cmdargv, int cmdargc)
365 static char *opts[] = { "absolute" };
369 for (i = 1; i < cmdargc; i++) {
370 if (cmdargv[i][0] == '-') {
371 switch (table_lookup(cmdargv[i] + 1, opts, sizeof(opts) / sizeof(opts[0]))) {
387 show_syntax(CMD_SHOW);
391 if (ldap_search(ld, make_dn(dn, relative), LDAP_SCOPE_BASE, true_filter, NULL, 0) == -1) {
392 ldap_perror(ld, progname);
396 if (ldap_result(ld, LDAP_RES_ANY, 1, (struct timeval *)0, &result) == -1) {
397 ldap_perror(ld, progname);
401 display_search_results(result);
406 display_search_results(LDAPMessage *result)
414 for (entry = ldap_first_entry(ld, result); entry; entry = ldap_next_entry(ld, entry)) {
415 if (s = ldap_get_dn(ld, entry)) {
420 /* Make one pass to calculate the length of the longest attribute name */
422 for (s = ldap_first_attribute(ld, entry, &cookie); s; s = ldap_next_attribute(ld, entry, cookie))
423 if ((i = strlen(s)) > maxname)
426 /* Now print the attributes and values */
427 for (s = ldap_first_attribute(ld, entry, &cookie); s; s = ldap_next_attribute(ld, entry, cookie)) {
430 if (table_lookup(s, binary_attrs, sizeof(binary_attrs) / sizeof(binary_attrs[0])) >= 0)
431 continue; /* Skip this attribute - it's binary */
433 printf(" %-*s - ", maxname, s);
435 /* Now print each of the values for the given attribute */
436 if (values = ldap_get_values(ld, entry, s)) {
439 for (val = values; *val; ) {
443 /* Watch out for values that have embedded \n characters */
444 while (nl = strchr(v, '\n')) {
449 printf(" %*s", maxname + 3, "");
454 printf(" %*s", maxname + 3, "");
456 ldap_value_free(values);
462 if (ldap_result2error(ld, result, 0))
463 ldap_perror(ld, progname);
466 int do_command(char *cmd)
472 /* Tokenize the input command, allowing for quoting */
474 cmd = skip_whitespace(cmd);
476 break; /* end of input */
478 cmdargv[cmdargc++] = cmd;
479 if (*cmd == '\'' || *cmd == '"') {
480 cmdargv[cmdargc - 1]++; /* Skip over the opening quote */
481 cmd = skip_to_char(cmd + 1, *cmd);
483 puts("Command is missing a trailing quote");
488 cmd = skip_to_whitespace(cmd);
495 printf("cmdargc = %d\n", cmdargc);
496 for (i = 0; i < cmdargc; i++)
500 if (cmdargv[0][0] == '?')
501 return cmd_help(cmdargv, cmdargc);
503 for (i = 0; i < sizeof(cmdtable) / sizeof(cmdtable[0]); i++)
504 if (strncasecmp(cmdargv[0], cmdtable[i].cmd, strlen(cmdargv[0])) == 0)
505 return (*cmdtable[i].func)(cmdargv, cmdargc);
507 if (!is_whitespace(cmdargv[0])) {
508 printf("Unrecognized command - %s\n", cmdargv[0]);
509 cmd_help(cmdargv, 1);
515 void do_commands(FILE *file)
517 char cmd_buf[BUFSIZ];
518 int tty = isatty(fileno(file));
523 if (!fgets(cmd_buf, sizeof(cmd_buf), file))
525 if (do_command(cmd_buf))
530 int is_whitespace(register char *s)
535 while (*s && isspace((unsigned char) *s))
541 int main(int argc, char **argv)
547 while ((option = getopt(argc, argv, "h:p:u:c:d:")) != EOF)
550 credentials = optarg;
554 lber_debug = atoi(optarg);
555 ldap_debug = atoi(optarg);
562 portnum = atoi(optarg);
572 fprintf(stderr, "usage: %s [-h host] [-p portnumber] [-u X500UserName]\n\t[-c credentials] [-d debug-level]\n",
579 if (!(ld = ldap_open(hostname, portnum))) {
580 fprintf(stderr, "%s: unable to connect to server at host `%s' on port %d\n",
581 progname, hostname, portnum);
599 char *make_dn(char *dn, int relative)
601 static char dn_buf[DN_MAXLEN];
607 if (!default_dn[0] || !relative)
613 return strcat(strcat(strcpy(dn_buf, dn), ", "), default_dn);
616 show_syntax(int cmdnum)
618 printf("Syntax: %s %s\n", cmdtable[cmdnum].cmd, cmdtable[cmdnum].help_msg);
621 char *skip_to_char(register char *s, register int c)
626 while (*s && *s != c)
632 char *skip_to_whitespace(register char *s)
637 while (*s && !isspace((unsigned char) *s))
643 char *skip_whitespace(register char *s)
648 while (*s && isspace((unsigned char) *s))
654 int table_lookup(char *word, char **table, int table_count)
662 wordlen = strlen(word);
664 for (i = 0; i < table_count; i++)
665 if (strncasecmp(word, table[i], wordlen) == 0)
670 FILE *user_tailor(void)
679 struct passwd *pwent;
681 if (pwent = getpwuid(getuid()))
682 strcat(strcpy(rcfile, pwent->pw_dir), "/");
683 strcat(rcfile, ".saucerrc");
686 strcpy(rcfile, "saucer.rc");
689 return fopen(rcfile, "r");