+++ /dev/null
-/*
- * 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");
-}
+++ /dev/null
-.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