mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-31 19:09:42 -05:00
Move saucer to the Attic. Has not been updated to support LDAPv3.
This commit is contained in:
parent
9b35077ede
commit
5e7336fcf1
8 changed files with 0 additions and 1027 deletions
|
|
@ -2657,8 +2657,6 @@ servers/slapd/tools/Makefile:build/top.mk:servers/slapd/tools/Makefile.in \
|
|||
servers/slurpd/Makefile:build/top.mk:servers/slurpd/Makefile.in:build/srv.mk \
|
||||
tests/Makefile:build/top.mk:tests/Makefile.in:build/dir.mk \
|
||||
tests/progs/Makefile:build/top.mk:tests/progs/Makefile.in:build/rules.mk \
|
||||
contrib/Makefile:build/top.mk:contrib/Makefile.in:build/dir.mk \
|
||||
contrib/saucer/Makefile:build/top.mk:contrib/saucer/Makefile.in:build/rules.mk \
|
||||
,[
|
||||
date > stamp-h
|
||||
echo Please \"make depend\" to build dependencies
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
# $OpenLDAP$
|
||||
## Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
|
||||
## COPYING RESTRICTIONS APPLY, See COPYRIGHT file
|
||||
##
|
||||
## contrib Makefile.in for OpenLDAP
|
||||
|
||||
SUBDIRS= saucer web_ldap
|
||||
|
|
@ -14,12 +14,6 @@ Current contributions:
|
|||
ldaptcl
|
||||
TCL API from NeoSoft
|
||||
|
||||
saucer
|
||||
General purpose command-line LDAP client, modeled
|
||||
after ISODE's DISH (DIrectory SHell) client.
|
||||
Contributed by Eric Rosenquist. See saucer/README
|
||||
and its man page for more information.
|
||||
|
||||
Please submit your contributions using the OpenLDAP Issue
|
||||
Tracking System <http://www.openldap.org/>.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
PROGRAMS= saucer
|
||||
|
||||
SRCS= main.c
|
||||
OBJS= main.o
|
||||
|
||||
LDAP_INCDIR= ../../include
|
||||
LDAP_LIBDIR= ../../libraries
|
||||
|
||||
READLINE_LIBS = @READLINE_LIBS@
|
||||
|
||||
XLIBS = -lldap -llber -llutil
|
||||
XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS) $(READLINE_LIBS) $(TERMCAP_LIBS)
|
||||
|
||||
MANDIR=$(mandir)/man1
|
||||
|
||||
saucer: ${OBJS} $(LDAP_LIBDEPEND)
|
||||
$(LTLINK) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
install-local: $(PROGRAMS) FORCE
|
||||
-$(MKDIR) $(DESTDIR)$(bindir)
|
||||
$(LTINSTALL) $(INSTALLFLAGS) -m 755 saucer $(DESTDIR)$(bindir)
|
||||
-$(MKDIR) $(DESTDIR)$(MANDIR)
|
||||
$(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/saucer.1 $(DESTDIR)$(MANDIR)/saucer.1
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
This directory contains a set of files that build a simple LDAP client
|
||||
program. The program is command-line oriented and uses a syntax and
|
||||
command set roughly similar to ISODE's DISH program, hence it is
|
||||
named "saucer" (i.e. a very small "dish" :-)
|
||||
|
||||
To build saucer, you must first build OpenLDAP, and then say
|
||||
cd contrib/saucer
|
||||
make depend
|
||||
make
|
||||
You can then install it by doing an "su" and typing "make install".
|
||||
This will copy the binary to the directory you specified for LDAP
|
||||
binaries, and the man page will be placed in the appropriate man
|
||||
directory.
|
||||
|
||||
If you wish saucer to use GNU Readline, you must have set CPPFLAGS and
|
||||
LDFLAGS so that <readline/readline.h> and -lreadline will be found when
|
||||
you configured OpenLDAP, e.g.
|
||||
env CPPFLAGS="-I/usr/gnu/include" LDFLAGS="-L/usr/gnu/lib" ./configure
|
||||
|
||||
|
||||
Saucer runs from the Unix command line with the following arguments:
|
||||
|
||||
saucer [-h host] [-p portnumber] [-u 'X500UserName']
|
||||
[-c credentials] [-d debug-level]
|
||||
|
||||
If no options are given, saucer will attempt to connect to an LDAP
|
||||
daemon on the local host and default port (389), and will attempt to
|
||||
bind anonymously.
|
||||
|
||||
Typing "help" at saucer's command prompt will yield:
|
||||
|
||||
saucer dn=> help
|
||||
Supported commands are:
|
||||
help
|
||||
list
|
||||
moveto
|
||||
quit
|
||||
search
|
||||
set
|
||||
show
|
||||
|
||||
You can get syntactical help for a command by typing "help <command>".
|
||||
Detailed instructions are available from the saucer man page.
|
||||
|
||||
Any comments or questions should be directed to:
|
||||
|
||||
Eric.Rosenquist@strataware.com
|
||||
|
||||
or to an OpenLDAP mailinglist, see <URL:http://www.openldap.org/lists/>.
|
||||
|
|
@ -1,752 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1994, Strata Software Limited, Ottawa, Ontario, Canada.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that this notice is preserved and that due credit is given
|
||||
* to Eric Rosenquist and Strata Software Limited. The SSL name
|
||||
* may not be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission. This software
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* 'saucer' LDAP command-line client source code.
|
||||
*
|
||||
* Author: Eric Rosenquist, 1994.
|
||||
*
|
||||
* 07-Mar-1999 readline support added: O. Steffensen (oddbjorn@tricknology.org)
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/stdlib.h>
|
||||
|
||||
#ifdef HAVE_READLINE
|
||||
# include <readline/readline.h>
|
||||
# ifdef HAVE_READLINE_HISTORY_H
|
||||
# include <readline/history.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <ac/ctype.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/unistd.h>
|
||||
|
||||
#include <lber.h>
|
||||
#include <ldap.h>
|
||||
#include <ldap_log.h>
|
||||
|
||||
#define DN_MAXLEN 4096
|
||||
|
||||
typedef struct {
|
||||
const char *cmd;
|
||||
int (*func) (char **, int);
|
||||
const char *help_msg;
|
||||
} CMDTABLE;
|
||||
|
||||
typedef enum {
|
||||
CMD_HELP,
|
||||
CMD_LIST,
|
||||
CMD_MOVETO,
|
||||
CMD_QUIT,
|
||||
CMD_SEARCH,
|
||||
CMD_SET,
|
||||
CMD_SHOW
|
||||
} COMMAND;
|
||||
|
||||
char *attrs_null[] = { "0.10", NULL };
|
||||
char *credentials;
|
||||
char default_dn[DN_MAXLEN];
|
||||
char *hostname = "127.0.0.1";
|
||||
LDAP *ld;
|
||||
extern char *optarg;
|
||||
extern int opterr;
|
||||
extern int optind;
|
||||
int option;
|
||||
int portnum = LDAP_PORT;
|
||||
char *progname;
|
||||
char true_filter[] = "(objectClass=*)"; /* Always succeeds */
|
||||
char *username;
|
||||
|
||||
int cmd_help(char **cmdargv, int cmdargc);
|
||||
int cmd_list(char **cmdargv, int cmdargc);
|
||||
int cmd_moveto(char **cmdargv, int cmdargc);
|
||||
int cmd_quit(char **cmdargv, int cmdargc);
|
||||
int cmd_search(char **cmdargv, int cmdargc);
|
||||
int cmd_set(char **cmdargv, int cmdargc);
|
||||
int cmd_show(char **cmdargv, int cmdargc);
|
||||
|
||||
int bind_user(void);
|
||||
void display_search_results(LDAPMessage *result);
|
||||
int do_command(char *cmd);
|
||||
void do_commands(FILE *file);
|
||||
int is_whitespace(register char *s);
|
||||
char *make_dn(char *dn, int relative);
|
||||
void show_syntax(unsigned int cmdnum);
|
||||
char *skip_to_char(register char *s, register int c);
|
||||
char *skip_to_whitespace(register char *s);
|
||||
char *skip_whitespace(register char *s);
|
||||
int table_lookup(const char *, const char *const *, int);
|
||||
FILE *user_tailor(void);
|
||||
|
||||
static const char *const binary_attrs[] = {
|
||||
"audio", "jpegPhoto", "personalSignature", "photo"
|
||||
};
|
||||
|
||||
const CMDTABLE cmdtable[] = {
|
||||
"help" , cmd_help , "[command]",
|
||||
"list" , cmd_list , "[RDN-or-DN] [-absolute]",
|
||||
"moveto", cmd_moveto, "[RDN-or-DN] [-absolute]",
|
||||
"quit" , cmd_quit , "",
|
||||
"search", cmd_search, "<filter> [-object RDN-or-DN] [-absolute]\n\t\t[-scope base|onelevel|subtree]",
|
||||
"set" , cmd_set , "[-aliasderef never|search|find|always] [-sizelimit N] [-timelimit seconds]",
|
||||
"show" , cmd_show , "[RDN-or-DN] [-absolute]"
|
||||
};
|
||||
|
||||
|
||||
int bind_user(void)
|
||||
{
|
||||
if (ldap_simple_bind_s(ld, username, credentials) != LDAP_SUCCESS) {
|
||||
ldap_perror(ld, progname);
|
||||
return 0;
|
||||
}
|
||||
if (username)
|
||||
printf("Bound to ldap server as `%s' (%s authentication)\n", username,
|
||||
credentials ? "simple" : "no");
|
||||
else
|
||||
puts("Bound anonymously to ldap server");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cmd_help(char **cmdargv, int cmdargc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (cmdargc == 2) {
|
||||
for (i = 0; i < sizeof(cmdtable) / sizeof(cmdtable[0]); i++)
|
||||
if (strncasecmp(cmdargv[1], cmdtable[i].cmd, strlen(cmdargv[1])) == 0) {
|
||||
show_syntax(i);
|
||||
return 0;
|
||||
}
|
||||
cmdargc = 1; /* Command not found - make it display the list of commands */
|
||||
}
|
||||
|
||||
if (cmdargc == 1) {
|
||||
puts("\nType 'help <command>' for help on a particular command.\n\n"
|
||||
"Supported commands are:");
|
||||
for (i = 0; i < sizeof(cmdtable) / sizeof(cmdtable[0]); i++)
|
||||
printf(" %s\n", cmdtable[i].cmd);
|
||||
puts("\nArguments to commands are separated by whitespace. Single (')\n"
|
||||
"or double (\") quotes must be used around arguments that contain\n"
|
||||
"embedded whitespace characters.\n");
|
||||
} else
|
||||
show_syntax(CMD_HELP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_list(char **cmdargv, int cmdargc)
|
||||
{
|
||||
char *dn = NULL;
|
||||
int errflag = 0;
|
||||
int i;
|
||||
static const char *const opts[] = { "absolute" };
|
||||
int relative = 1;
|
||||
LDAPMessage *result;
|
||||
|
||||
for (i = 1; i < cmdargc; i++) {
|
||||
if (cmdargv[i][0] == '-') {
|
||||
switch (table_lookup(cmdargv[i] + 1, opts, sizeof(opts) / sizeof(opts[0]))) {
|
||||
case 0:
|
||||
relative = 0;
|
||||
break;
|
||||
default:
|
||||
errflag = 1;
|
||||
}
|
||||
} else {
|
||||
if (dn)
|
||||
errflag = 1;
|
||||
else
|
||||
dn = cmdargv[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (errflag) {
|
||||
show_syntax(CMD_LIST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ldap_search(ld, make_dn(dn, relative), LDAP_SCOPE_ONELEVEL,
|
||||
true_filter, attrs_null, 1) == -1) {
|
||||
ldap_perror(ld, progname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ldap_result(ld, LDAP_RES_ANY, 1, (struct timeval *)0, &result) == -1) {
|
||||
ldap_perror(ld, progname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
display_search_results(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_moveto(char **cmdargv, int cmdargc)
|
||||
{
|
||||
char *dn = NULL;
|
||||
int errflag = 0;
|
||||
char **exploded_dn;
|
||||
int i;
|
||||
static const char *const opts[] = { "absolute" };
|
||||
int relative = 1;
|
||||
|
||||
for (i = 1; i < cmdargc; i++) {
|
||||
if (cmdargv[i][0] == '-') {
|
||||
switch (table_lookup(cmdargv[i] + 1, opts, sizeof(opts) / sizeof(opts[0]))) {
|
||||
case 0:
|
||||
relative = 0;
|
||||
break;
|
||||
default:
|
||||
errflag = 1;
|
||||
}
|
||||
} else {
|
||||
if (dn)
|
||||
errflag = 1;
|
||||
else
|
||||
dn = cmdargv[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (errflag) {
|
||||
show_syntax(CMD_MOVETO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dn) {
|
||||
if (is_whitespace(dn))
|
||||
default_dn[0] = 0;
|
||||
else {
|
||||
if (strcmp(dn, "..") == 0) {
|
||||
/* Move up one level */
|
||||
if (exploded_dn = ldap_explode_dn(default_dn, 0)) {
|
||||
if (exploded_dn[0]) {
|
||||
char **rdn;
|
||||
|
||||
default_dn[0] = 0;
|
||||
for (rdn = exploded_dn + 1; *rdn; rdn++) {
|
||||
if (default_dn[0])
|
||||
strcat(default_dn, ", ");
|
||||
strcat(default_dn, *rdn);
|
||||
}
|
||||
}
|
||||
ldap_value_free(exploded_dn);
|
||||
}
|
||||
} else {
|
||||
/* Use ldap_explode_dn() to parse the string & test its syntax */
|
||||
if (exploded_dn = ldap_explode_dn(dn, 1)) {
|
||||
if (relative && !is_whitespace(default_dn)) {
|
||||
char buf[DN_MAXLEN];
|
||||
|
||||
strcpy(default_dn, strcat(strcat(strcpy(buf, dn), ", "), default_dn));
|
||||
} else
|
||||
strcpy(default_dn, dn);
|
||||
ldap_value_free(exploded_dn);
|
||||
} else
|
||||
puts("Invalid distinguished name.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Distinguished name suffix is `%s'\n", default_dn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_quit(char **cmdargv, int cmdargc)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cmd_search(char **cmdargv, int cmdargc)
|
||||
{
|
||||
char *dn = NULL;
|
||||
int errflag = 0;
|
||||
char *filter = NULL;
|
||||
int i, j;
|
||||
static const char *const opts[] = { "absolute", "object", "scope" };
|
||||
int relative = 1;
|
||||
LDAPMessage *result;
|
||||
static const char *const scope_opts[]= { "base","onelevel","subtree" };
|
||||
static const int scope_vals[] = { LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE };
|
||||
static int search_scope = LDAP_SCOPE_ONELEVEL;
|
||||
|
||||
for (i = 1; i < cmdargc; i++) {
|
||||
if (cmdargv[i][0] == '-') {
|
||||
switch (table_lookup(cmdargv[i] + 1, opts, sizeof(opts) / sizeof(opts[0]))) {
|
||||
case 0:
|
||||
relative = 0;
|
||||
break;
|
||||
case 1:
|
||||
if (++i < cmdargc)
|
||||
dn = cmdargv[i];
|
||||
else
|
||||
errflag = 1;
|
||||
break;
|
||||
case 2:
|
||||
if ((++i < cmdargc) &&
|
||||
(j = table_lookup(cmdargv[i], scope_opts, sizeof(scope_opts) / sizeof(scope_opts[0]))) >= 0)
|
||||
search_scope = scope_vals[j];
|
||||
else
|
||||
errflag = 1;
|
||||
break;
|
||||
default:
|
||||
errflag = 1;
|
||||
}
|
||||
} else {
|
||||
if (filter)
|
||||
errflag = 1;
|
||||
else
|
||||
filter = cmdargv[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (errflag || !filter) {
|
||||
show_syntax(CMD_SEARCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ldap_search(ld, make_dn(dn, relative), search_scope, filter, attrs_null, 0) == -1) {
|
||||
ldap_perror(ld, progname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ldap_result(ld, LDAP_RES_ANY, 1, (struct timeval *)0, &result) == -1) {
|
||||
ldap_perror(ld, progname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
display_search_results(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_set(char **cmdargv, int cmdargc)
|
||||
{
|
||||
static const char *const alias_opts[] = {
|
||||
"never", "search", "find", "always"
|
||||
};
|
||||
int errflag = 0;
|
||||
int i, j;
|
||||
static const char *const opts[] = {
|
||||
"aliasderef", "sizelimit", "timelimit"
|
||||
};
|
||||
|
||||
for (i = 1; i < cmdargc; i++) {
|
||||
if (cmdargv[i][0] == '-') {
|
||||
switch (table_lookup(cmdargv[i] + 1, opts, sizeof(opts) / sizeof(opts[0]))) {
|
||||
case 0:
|
||||
if ((++i < cmdargc) &&
|
||||
(j = table_lookup(cmdargv[i], alias_opts, sizeof(alias_opts) / sizeof(alias_opts[0]))) >= 0)
|
||||
ldap_set_option(ld, LDAP_OPT_DEREF, &j);
|
||||
else
|
||||
errflag = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (++i < cmdargc) {
|
||||
j = atoi(cmdargv[i]);
|
||||
ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &j);
|
||||
} else
|
||||
errflag = 1;
|
||||
break;
|
||||
case 2:
|
||||
if (++i < cmdargc) {
|
||||
j = atoi(cmdargv[i]);
|
||||
ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &j);
|
||||
} else
|
||||
errflag = 1;
|
||||
break;
|
||||
default:
|
||||
errflag = 1;
|
||||
}
|
||||
} else
|
||||
errflag = 1;
|
||||
}
|
||||
|
||||
if (errflag)
|
||||
show_syntax(CMD_SET);
|
||||
else {
|
||||
int opt_a, opt_s, opt_t;
|
||||
ldap_get_option(ld, LDAP_OPT_DEREF, &opt_a);
|
||||
ldap_get_option(ld, LDAP_OPT_SIZELIMIT, &opt_s);
|
||||
ldap_get_option(ld, LDAP_OPT_TIMELIMIT, &opt_t);
|
||||
printf("Alias dereferencing is %s, Sizelimit is %d entr%s, Timelimit is %d second%s.\n",
|
||||
alias_opts[opt_a],
|
||||
opt_s, opt_s == 1 ? "y" : "ies",
|
||||
opt_t, opt_t == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_show(char **cmdargv, int cmdargc)
|
||||
{
|
||||
char *dn = NULL;
|
||||
int errflag = 0;
|
||||
int i;
|
||||
static const char *const opts[] = { "absolute" };
|
||||
int relative = 1;
|
||||
LDAPMessage *result;
|
||||
|
||||
for (i = 1; i < cmdargc; i++) {
|
||||
if (cmdargv[i][0] == '-') {
|
||||
switch (table_lookup(cmdargv[i] + 1, opts, sizeof(opts) / sizeof(opts[0]))) {
|
||||
case 0:
|
||||
relative = 0;
|
||||
break;
|
||||
default:
|
||||
errflag = 1;
|
||||
}
|
||||
} else {
|
||||
if (dn)
|
||||
errflag = 1;
|
||||
else
|
||||
dn = cmdargv[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (errflag) {
|
||||
show_syntax(CMD_SHOW);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ldap_search(ld, make_dn(dn, relative), LDAP_SCOPE_BASE, true_filter, NULL, 0) == -1) {
|
||||
ldap_perror(ld, progname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ldap_result(ld, LDAP_RES_ANY, 1, (struct timeval *)0, &result) == -1) {
|
||||
ldap_perror(ld, progname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
display_search_results(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void display_search_results(LDAPMessage *result)
|
||||
{
|
||||
BerElement *cookie;
|
||||
int i;
|
||||
LDAPMessage *entry;
|
||||
int maxname;
|
||||
char *s;
|
||||
|
||||
for (entry = ldap_first_entry(ld, result); entry; entry = ldap_next_entry(ld, entry)) {
|
||||
if (s = ldap_get_dn(ld, entry)) {
|
||||
printf(" %s\n", s);
|
||||
ldap_memfree(s);
|
||||
}
|
||||
|
||||
/* Make one pass to calculate the length of the longest attribute name */
|
||||
maxname = 0;
|
||||
for (s = ldap_first_attribute(ld, entry, &cookie); s; s = ldap_next_attribute(ld, entry, cookie))
|
||||
if ((i = strlen(s)) > maxname)
|
||||
maxname = i;
|
||||
|
||||
/* Now print the attributes and values */
|
||||
for (s = ldap_first_attribute(ld, entry, &cookie); s; s = ldap_next_attribute(ld, entry, cookie)) {
|
||||
char **values;
|
||||
|
||||
if (table_lookup(s, binary_attrs, sizeof(binary_attrs) / sizeof(binary_attrs[0])) >= 0)
|
||||
continue; /* Skip this attribute - it's binary */
|
||||
|
||||
printf(" %-*s - ", maxname, s);
|
||||
|
||||
/* Now print each of the values for the given attribute */
|
||||
if (values = ldap_get_values(ld, entry, s)) {
|
||||
char **val;
|
||||
|
||||
for (val = values; *val; ) {
|
||||
char *nl;
|
||||
char *v = *val;
|
||||
|
||||
/* Watch out for values that have embedded \n characters */
|
||||
while (nl = strchr(v, '\n')) {
|
||||
*nl = 0;
|
||||
puts(v);
|
||||
v = nl + 1;
|
||||
if (*v)
|
||||
printf(" %*s", maxname + 3, "");
|
||||
}
|
||||
if (*v)
|
||||
puts(v);
|
||||
if (*++val)
|
||||
printf(" %*s", maxname + 3, "");
|
||||
}
|
||||
ldap_value_free(values);
|
||||
} else
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
if (ldap_result2error(ld, result, 0))
|
||||
ldap_perror(ld, progname);
|
||||
}
|
||||
|
||||
int do_command(char *cmd)
|
||||
{
|
||||
char *cmdargv[128];
|
||||
int cmdargc = 0;
|
||||
int i;
|
||||
|
||||
/* Tokenize the input command, allowing for quoting */
|
||||
for (;;) {
|
||||
cmd = skip_whitespace(cmd);
|
||||
if (!cmd || !*cmd)
|
||||
break; /* end of input */
|
||||
|
||||
cmdargv[cmdargc++] = cmd;
|
||||
if (*cmd == '\'' || *cmd == '"') {
|
||||
cmdargv[cmdargc - 1]++; /* Skip over the opening quote */
|
||||
cmd = skip_to_char(cmd + 1, *cmd);
|
||||
if (!cmd || !*cmd) {
|
||||
puts("Command is missing a trailing quote");
|
||||
return 0;
|
||||
}
|
||||
*cmd++ = 0;
|
||||
} else {
|
||||
cmd = skip_to_whitespace(cmd);
|
||||
if (cmd && *cmd)
|
||||
*cmd++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("cmdargc = %d\n", cmdargc);
|
||||
for (i = 0; i < cmdargc; i++)
|
||||
puts(cmdargv[i]);
|
||||
#endif
|
||||
|
||||
if (cmdargv[0][0] == '?')
|
||||
return cmd_help(cmdargv, cmdargc);
|
||||
|
||||
for (i = 0; i < sizeof(cmdtable) / sizeof(cmdtable[0]); i++)
|
||||
if (strncasecmp(cmdargv[0], cmdtable[i].cmd, strlen(cmdargv[0])) == 0)
|
||||
return (*cmdtable[i].func)(cmdargv, cmdargc);
|
||||
|
||||
if (!is_whitespace(cmdargv[0])) {
|
||||
printf("Unrecognized command - %s\n", cmdargv[0]);
|
||||
cmd_help(cmdargv, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void do_commands(FILE *file)
|
||||
{
|
||||
char cmd_buf[BUFSIZ];
|
||||
int tty = isatty(fileno(file));
|
||||
char *buf = cmd_buf;
|
||||
int status;
|
||||
|
||||
for (;;) {
|
||||
if (tty)
|
||||
{
|
||||
char prompt[40];
|
||||
sprintf(prompt, (strlen(default_dn) < 18
|
||||
? "saucer dn=%s> "
|
||||
: "saucer dn=%.15s..> "), default_dn);
|
||||
#ifndef HAVE_READLINE
|
||||
fputs (prompt, stdout);
|
||||
#else
|
||||
buf = readline (prompt);
|
||||
if (!buf)
|
||||
break;
|
||||
add_history (buf);
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_READLINE
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (!fgets(cmd_buf, sizeof(cmd_buf), file))
|
||||
break;
|
||||
}
|
||||
|
||||
status = do_command(buf);
|
||||
#ifdef HAVE_READLINE
|
||||
if (tty)
|
||||
free(buf);
|
||||
#endif
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int is_whitespace(register char *s)
|
||||
{
|
||||
if (!s)
|
||||
return 1;
|
||||
|
||||
while (*s && isspace((unsigned char) *s))
|
||||
++s;
|
||||
|
||||
return !*s;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int error_flag = 0;
|
||||
int tmp;
|
||||
FILE *rc;
|
||||
|
||||
progname = argv[0];
|
||||
while ((option = getopt(argc, argv, "h:p:u:c:d:")) != EOF)
|
||||
switch (option) {
|
||||
case 'c':
|
||||
credentials = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
#ifdef LDAP_DEBUG
|
||||
tmp = atoi(optarg);
|
||||
ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &tmp);
|
||||
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &tmp);
|
||||
#endif
|
||||
break;
|
||||
case 'h':
|
||||
hostname = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
portnum = atoi(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
username = optarg;
|
||||
break;
|
||||
case '?':
|
||||
error_flag = 1;
|
||||
}
|
||||
|
||||
if (error_flag) {
|
||||
fprintf(stderr, "usage: %s [-h host] [-p portnumber] [-u X500UserName]\n\t[-c credentials] [-d debug-level]\n",
|
||||
progname);
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
rc = user_tailor();
|
||||
|
||||
if (!(ld = ldap_init(hostname, portnum))) {
|
||||
fprintf(stderr, "%s: unable to initialize LDAP session (%s:%d)\n",
|
||||
progname, hostname, portnum);
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
if (!bind_user())
|
||||
return 1;
|
||||
|
||||
if (rc) {
|
||||
do_commands(rc);
|
||||
fclose(rc);
|
||||
}
|
||||
do_commands(stdin);
|
||||
|
||||
ldap_unbind(ld);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *make_dn(char *dn, int relative)
|
||||
{
|
||||
static char dn_buf[DN_MAXLEN];
|
||||
|
||||
if (!dn)
|
||||
dn = "";
|
||||
|
||||
if (!default_dn[0] || !relative)
|
||||
return dn;
|
||||
|
||||
if (!dn[0])
|
||||
return default_dn;
|
||||
|
||||
return strcat(strcat(strcpy(dn_buf, dn), ", "), default_dn);
|
||||
}
|
||||
|
||||
void show_syntax(unsigned int cmdnum)
|
||||
{
|
||||
printf("Syntax: %s %s\n", cmdtable[cmdnum].cmd, cmdtable[cmdnum].help_msg);
|
||||
}
|
||||
|
||||
char *skip_to_char(register char *s, register int c)
|
||||
{
|
||||
if (!s)
|
||||
return s;
|
||||
|
||||
while (*s && *s != c)
|
||||
++s;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
char *skip_to_whitespace(register char *s)
|
||||
{
|
||||
if (!s)
|
||||
return s;
|
||||
|
||||
while (*s && !isspace((unsigned char) *s))
|
||||
++s;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
char *skip_whitespace(register char *s)
|
||||
{
|
||||
if (!s)
|
||||
return s;
|
||||
|
||||
while (*s && isspace((unsigned char) *s))
|
||||
++s;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int table_lookup(const char *word, const char *const *table, int table_count)
|
||||
{
|
||||
register int i;
|
||||
int wordlen;
|
||||
|
||||
if (!word || !*word)
|
||||
return -1;
|
||||
|
||||
wordlen = strlen(word);
|
||||
|
||||
for (i = 0; i < table_count; i++)
|
||||
if (strncasecmp(word, table[i], wordlen) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *user_tailor(void)
|
||||
{
|
||||
char rcfile[BUFSIZ];
|
||||
|
||||
rcfile[0] = 0;
|
||||
|
||||
#ifdef unix
|
||||
{
|
||||
#include <pwd.h>
|
||||
struct passwd *pwent;
|
||||
|
||||
if (pwent = getpwuid(getuid()))
|
||||
strcat(strcpy(rcfile, pwent->pw_dir), "/");
|
||||
strcat(rcfile, ".saucerrc");
|
||||
}
|
||||
#else
|
||||
strcpy(rcfile, "saucer.rc");
|
||||
#endif
|
||||
|
||||
return fopen(rcfile, "r");
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
set -aliasderef always -sizelimit 25 -timelimit 30
|
||||
moveto "o=Enterprise Solutions Limited, c=CA"
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
.TH SAUCER 1 "March 1999" "OpenLDAP"
|
||||
.UC 6
|
||||
.SH NAME
|
||||
saucer \- interactive X.500 Directory client program
|
||||
.SH SYNOPSIS
|
||||
\fBsaucer\fR [-h \fIhost\fR] [-p \fIportnumber\fR] [-u \fIX500UserName\fR]
|
||||
[-c \fIcredentials\fR] [-d \fIdebug-level\fR]
|
||||
.SH DESCRIPTION
|
||||
\fIsaucer\fR is used to navigate and perform searches on an X.500
|
||||
Directory via the Lightweight Directory Access Protocol (LDAP).
|
||||
.SH OPTIONS
|
||||
.TP 5
|
||||
.B \-h hostname
|
||||
Used to specify the name or IP number of an LDAP host to which saucer
|
||||
should connect. If this flag is omitted, \fI127.0.0.1\fR is used.
|
||||
.TP 5
|
||||
.B \-p portnumber
|
||||
Used to specify the TCP port number of the LDAP daemon on the server
|
||||
host. If this flag is omitted, the LDAP default port number
|
||||
(\fI389\fR) is used.
|
||||
.TP 5
|
||||
.B \-u X500UserName
|
||||
Specifies the X.500 name to be used when binding to the directory
|
||||
server. It must be in the form specified by RFC 1485, for example:
|
||||
|
||||
\fB"cn=George Castanza, o=Vandelay Industries, c=US"\fR
|
||||
|
||||
Don't forget to put quotes around the name if it contains blanks.
|
||||
.TP 5
|
||||
.B \-c credentials
|
||||
Specifies the credentials, i.e. the password, to be used when binding
|
||||
to the directory server. If this flag is omitted but a name is given
|
||||
with the \fB-u\fR flag, an unauthenticated bind will be attempted. If
|
||||
neither flag is given, an anonymous bind will be attempted.
|
||||
.TP 5
|
||||
.B \-d debug-level
|
||||
Sets the LDAP debug mask to the numeric value specified. This flag is
|
||||
only used if saucer was compiled with the LDAP_DEBUG flag.
|
||||
.SH COMMANDS
|
||||
\fIsaucer\fR commands consist of a keyword followed by zero or more
|
||||
arguments. Commands and arguments can be shortened to any number of
|
||||
characters; the entered text is matched against the available keywords
|
||||
in ascending alphabetical order. For example, entering the command
|
||||
\fB"s"\fR will be interpreted by \fIsaucer\fR as the \fBsearch\fR
|
||||
command, and \fB"sh"\fR will be interpreted as the \fBshow\fR command.
|
||||
The \fBset\fR command cannot be abbreviated since both \fB"s"\fR and
|
||||
\fB"se"\fR will be interpreted as the \fBsearch\fR command.
|
||||
|
||||
Arguments to commands are separated by whitespace (blanks or tabs), so
|
||||
any values that contain whitespace (such as X.500 names) need to be
|
||||
enclosed in single or double quotes.
|
||||
|
||||
Arguments can be entered in any order. If the same argument appears
|
||||
more than once in a command, the last value is used and the others are
|
||||
ignored.
|
||||
|
||||
Directory names are by default assumed to be relative to the
|
||||
\fIcurrent location\fR, which is set with the \fBmoveto\fR command.
|
||||
All commands that accept a directory name have an optional
|
||||
\fI-absolute\fR flag which causes \fIsaucer\fR to interpret the name
|
||||
as a complete X.500 name rather than one that is relative to the
|
||||
current location.
|
||||
.SS "help [command]"
|
||||
Provides brief online help giving the available commands and their syntax.
|
||||
|
||||
If \fIcommand\fR is specified, the syntax for the command is shown.
|
||||
``help'' by itself simply provides a list of the available commands.
|
||||
.SS "list [RDN/DN] [-absolute]"
|
||||
Displays the names of a directory node's subordinates.
|
||||
|
||||
If an \fIRDN/DN\fR is given, it specifies the entry whose subordinates
|
||||
are to be listed. In its absence, the current location (see the
|
||||
\fBmoveto\fR command) is used. The \fI-absolute\fR argument controls
|
||||
whether the \fIRDN/DN\fR is a complete directory name or is relative
|
||||
to the current location.
|
||||
.SS "moveto [RDN/DN] [-absolute]"
|
||||
Displays or modifies \fIsaucer\fR's \fIcurrent location\fR in the
|
||||
directory. Without arguments, the current location is displayed.
|
||||
If an \fIRDN/DN\fR is given, the current location is modified
|
||||
and the new value is displayed.
|
||||
|
||||
The \fI-absolute\fR flag causes \fIsaucer\fR to treat the entered
|
||||
\fIRDN/DN\fR as a complete directory name and to use it as the
|
||||
new current location. Without the \fI-absolute\fR flag, the
|
||||
name is assumed to be relative to the previous location.
|
||||
|
||||
The special value \fB".."\fR is recognized by \fIsaucer\fR as a
|
||||
valid name and causes the current location to be moved one level
|
||||
up (towards the root) in the directory.
|
||||
.SS quit
|
||||
Unbinds from the directory and exits \fIsaucer\fR.
|
||||
.SS "search <filter> [-object RDN/DN] [-absolute] [-scope <scope>]"
|
||||
Searches the directory for entries which match the \fI<filter>\fR
|
||||
expression. For more information on the syntax of the \fI<filter>\fR
|
||||
argument, see "RFC 1588 - A String Representation of LDAP Search
|
||||
Filters".
|
||||
|
||||
If the \fI-object\fR argument is used, it specifies the base of the
|
||||
directory search. In its absence, the current location (see the
|
||||
\fBmoveto\fR command) is used as the search base. The \fI-absolute\fR
|
||||
argument controls whether the \fIRDN/DN\fR given with the
|
||||
\fI-object\fR flag is a complete directory name or is relative to the
|
||||
current location.
|
||||
|
||||
The \fI-scope\fR argument controls the depth of the search. It
|
||||
accepts one of the keywords \fIbase\fR, \fIonelevel\fR, or
|
||||
\fIsubtree\fR to search within the base object, its immediate
|
||||
children, or all of its subordinates respectively. The search depth
|
||||
is preserved across commands, so subsequent searches will use the
|
||||
previously entered depth setting if a new one is not given.
|
||||
\fISaucer\fR defaults to a \fIonelevel\fR search depth at startup.
|
||||
.SS "set [-aliasderef <deref>] [-sizelimit N] [-timelimit seconds]"
|
||||
Displays or modifies settings which apply to all directory operations
|
||||
issued by \fIsaucer\fR. Without arguments, the current settings are
|
||||
displayed. If options are given, the settings are changed and the new
|
||||
values are displayed.
|
||||
|
||||
The \fI-aliasderef <deref>\fR argument controls how the directory
|
||||
handles alias entries that it encounters. The value of \fI<deref>\fR
|
||||
must be one of \fInever\fR, \fIsearch\fR, \fIfind\fR, or \fIalways\fR.
|
||||
|
||||
A value of \fInever\fR tells the directory not to follow through any
|
||||
aliases it encounters.
|
||||
|
||||
A value of \fIfind\fR tells the directory to follow through an alias
|
||||
if it occurs as the base of a \fBlist\fR, \fBsearch\fR, or \fBshow\fR
|
||||
command.
|
||||
|
||||
A value of \fIsearch\fR tells the directory to follow through an alias
|
||||
when performing a \fBsearch\fR command. In other words, when
|
||||
performing a search, the attributes of the entry an alias points to
|
||||
will be tested against the filter expression rather than the alias
|
||||
itself.
|
||||
|
||||
A value of \fIalways\fR combines the meanings of the \fIfind\fR and
|
||||
\fIsearch\fR values, i.e., aliases are always dereferenced before
|
||||
being acted upon.
|
||||
|
||||
The \fI-sizelimit N\fR argument sets the maximum number of entries
|
||||
that will be returned by directory for \fBlist\fR and \fBsearch\fR
|
||||
commands to \fIN\fR. The directory server itself may impose a limit,
|
||||
in which case the lesser of the two limits is used. A value of
|
||||
\fI0\fR may be used to request as many entries as possible.
|
||||
|
||||
The \fI-timelimit seconds\fR argument sets the maximum amount of time
|
||||
allowed for a \fBlist\fR, \fBsearch\fR, or \fBshow\fR command. Note
|
||||
that this value is simply passed to the directory server, so the
|
||||
enforcement of the time limit is up to the server. A value of \fI0\fR
|
||||
may be used to request no time limit.
|
||||
.SS "show [RDN/DN] [-absolute]"
|
||||
Displays the attributes of a directory entry.
|
||||
|
||||
If an \fIRDN/DN\fR is given, it specifies the entry whose attributes
|
||||
are to be shown. In its absence, the current location (see the
|
||||
\fBmoveto\fR command) is used. The \fI-absolute\fR argument controls
|
||||
whether the \fIRDN/DN\fR is a complete directory name or is relative
|
||||
to the current location.
|
||||
|
||||
The attributes \fIaudio\fR, \fIjpegPhoto\fR, \fIpersonalSignature\fR,
|
||||
and \fIphoto\fR are known by \fIsaucer\fR to be binary values and are
|
||||
therefore not displayed. Other attributes which have binary encodings
|
||||
will be displayed by \fIsaucer\fR and will probably appear as garbage
|
||||
on the screen.
|
||||
.SH FILES
|
||||
~/.saucerrc The saucer startup command file.
|
||||
.SH "SEE ALSO"
|
||||
ldap(3), RFC 1485, RFC 1588
|
||||
.SH DIAGNOSTICS
|
||||
\fIsaucer\fR uses the ldap_perror() routine to print a message
|
||||
whenever an error is returned by the Directory server or the LDAP
|
||||
library.
|
||||
.SH "TO DO"
|
||||
The new LDAP 3.1 ldap_XXX2text() routines should be used instead of
|
||||
the code built into saucer.
|
||||
|
||||
The ability to read the X500UserName and credentials from the
|
||||
~/.saucerrc file should be added. There should also be a way to have
|
||||
saucer prompt the user for their password.
|
||||
|
||||
Attribute types which are binary are hard-coded into saucer. Ideally
|
||||
saucer should also try to detect which ones aren't displayable at
|
||||
runtime.
|
||||
.SH AUTHOR
|
||||
Eric Rosenquist, Enterprise Solutions Limited.
|
||||
.br
|
||||
Eric.Rosenquist@esltd.com
|
||||
Loading…
Reference in a new issue