DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T w

⟦8c4ad16d9⟧ TextFile

    Length: 23619 (0x5c43)
    Types: TextFile
    Names: »whois.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« 
        └─⟦de7628f85⟧ 
            └─⟦this⟧ »isode-6.0/others/quipu/uips/fred/whois.c« 

TextFile

/* whois.c - fred whois function */

#ifndef	lint
static char *rcsid = "$Header: /f/osi/others/quipu/uips/fred/RCS/whois.c,v 7.7 90/01/16 20:43:45 mrose Exp $";
#endif

/* 
 * $Header: /f/osi/others/quipu/uips/fred/RCS/whois.c,v 7.7 90/01/16 20:43:45 mrose Exp $
 *
 *
 * $Log:	whois.c,v $
 * Revision 7.7  90/01/16  20:43:45  mrose
 * last check-out
 * 
 * Revision 7.6  90/01/11  18:36:41  mrose
 * real-sync
 * 
 * Revision 7.5  89/12/18  08:44:23  mrose
 * typo
 * 
 * Revision 7.4  89/12/14  18:49:05  mrose
 * KIS project
 * 
 * Revision 7.3  89/12/01  10:45:11  mrose
 * touch-up
 * 
 * Revision 7.2  89/11/26  15:09:32  mrose
 * sync
 * 
 * Revision 7.1  89/11/26  14:25:22  mrose
 * sync
 * 
 * Revision 7.0  89/11/23  22:09:06  mrose
 * Release 6.0
 * 
 */

/*
 *				  NOTICE
 *
 *    Acquisition, use, and distribution of this module and related
 *    materials are subject to the restrictions of a license agreement.
 *    Consult the Preface in the User's Manual for the full terms of
 *    this agreement.
 *
 */


#include <ctype.h>
#include <signal.h>
#include "fred.h"

/* \f

   DATA */

struct whois {
    char   *w_input;
    int	    w_inputype;
#define	W_NULL		0x00
#define	W_HANDLE	0x01
#define	W_MAILBOX	0x02
#define	W_NAME		0x03

    int	    w_nametype;
#define	W_COMMONAME	0x01
#define	W_SURNAME	0x02

    int	    w_record;	/* same values as ag_record */

    char   *w_title;

    char   *w_area;
    int	    w_areatype;
    char   *w_geography;

    int	    w_output;
#define	W_EXPAND	0x01
#define	W_FULL		0x02
#define	W_SUMMARY	0x04
#define	W_SUBDISPLAY	0x08
};


char   *eqstr ();

/* \f

 */

char *whois_help[] = {
    "whois input-field [record-type] [area-designator] [output-control]",
    "    input-field is one of:",
    "\tname NAME\t\te.g., surname \"smith\", or fullname \"john smith\"",
    "\thandle HANDLE\t\te.g., handle @c=US@cn=Manager",
    "\tmailbox LOCAL@DOMAIN\te.g., mailbox postmaster@nisc.nyser.net",
    "    record-type is one of:",
    "\tperson or -title NAME\te.g., -title scientist",
    "\torganization",
    "\tunit (a division under an organization)",
    "\trole (a role within an organization)",
    "\tlocality",
    "\tdsa (white pages server)",
    "    area-designator is one of:",
    "\t-org NAME\t\te.g., -org nyser",
    "\t-unit NAME\t\te.g., -unit engineering",
    "\t-locality NAME\t\te.g., -locality rensselaer",
    "\t-area HANDLE\t\te.g., -area \"@c=US@o=NYSERNet Inc.\"",
    "\t    and may be optionally followed by -geo HANDLE, e.g., -geo @c=GB",
    "    output-control is any of:",
    "\texpand\t   - give a detailed listing, followed by children",
    "\tsubdisplay - give a one-listing listing, followed by children",
    "\tfull\t   - give a detailed listing, even on ambiguous matches",
    "\tsummary\t   - give a one-line listing, even on unique matches",

    NULL
};

/* \f

 */

static int seqno = 0;
static char fredseq[10];


char   *limits ();
FILE   *capture ();

/* \f

   WHOIS */

int	f_whois (vec)
char  **vec;
{
    int	    c,
	    didany,
	    multiple,
	    result;
    register char *bp,
		  *cp,
		  *dp;
    char    buffer[BUFSIZ],
	    onehit[BUFSIZ],
	    orgname[BUFSIZ],
	   *args[NVEC + 1];
    register struct area_guide *ag;
    struct whois ws;
    register struct whois *w = &ws;
    FILE   *fp;

    bzero ((char *) w, sizeof *w);

    if (strcmp (*vec, "whois") == 0)
	vec++;
    while (cp = *vec++) {
postscan: ;

	switch (*cp) {
	    case '.':
	        if (w -> w_inputype != W_NULL) {
too_many_fields: ;
		    advise (NULLCP,
			   "only one of NAME, HANDLE, or MAILBOX allowed");
		    goto you_really_lose;
		}
		if (*++cp == NULL) {
		    advise (NULLCP, "expecting NAME after \".\"");
		    goto you_really_lose;
		}
		w -> w_inputype = W_NAME;
		w -> w_input = cp;
		break;

	    case '!':
		if (w -> w_inputype != W_NULL)
		    goto too_many_fields;
		if (*++cp == NULL) {
		    advise (NULLCP, "expecting HANDLE after \"!\"");
		    goto you_really_lose;
		}
		goto got_handle;

	    case '*':
		if (cp[1] == '*') {
		    cp++;
		    goto name_or_something;
		}
		w -> w_output |= W_EXPAND;
	        if (*++cp)
		    goto postscan;
		break;
		
	    case '~':
		w -> w_output &= ~W_EXPAND;
	        if (*++cp)
		    goto postscan;
		break;
		
	    case '|':
		w -> w_output |= W_FULL;
	        if (*++cp)
		    goto postscan;
		break;
		
	    case '$':
		w -> w_output |= W_SUMMARY;
	        if (*++cp)
		    goto postscan;
		break;
		
	    case '%':
		w -> w_output |= W_SUBDISPLAY;
	        if (*++cp)
		    goto postscan;
		break;
		
	    case '-':
		if (test_arg (cp, "-area", 4)) {
		    result = W_NULL;

stuff_area: ;
		    if (w -> w_area != NULL) {
			advise (NULLCP, "only one AREA specification allowed");
			goto you_really_lose;
		    }
		    if (*vec == NULL) {
			advise (NULLCP, "expecting %s after \"%s\"",
				result != W_NULL ? "NAME" : "HANDLE", cp);
			goto you_really_lose;
		    }
		    if (*(dp = *vec) == '!')
			result = W_NULL;
		    else {
			for (; *dp; dp++)
			    if (!isdigit (*dp))
				break;
			if (!*dp)
			    result = NULL;
		    }
		    w -> w_area = *vec++, w -> w_areatype = result;
		    break;

		}
		if (test_arg (cp, "-expand", 4)) {
		    w -> w_output |= W_EXPAND;
		    break;
		}
		if (test_arg (cp, "-full", 4)) {
		    w -> w_output |= W_FULL;
		    break;
		}
		if (test_arg (cp, "-geography", 4)) {
		    if (*vec == NULL) {
			advise (NULLCP,
				"expecting location after \"-geography\"");
			goto you_really_lose;
		    }
		    w -> w_geography = *vec++;
		    break;
		}
		if (test_arg (cp, "-help", 5))
		    goto print_help;
		if (test_arg (cp, "-locality", 4)) {
		    result = W_LOCALITY;
		    goto stuff_area;
		}
		if (test_arg (cp, "-organization", 4)) {
		    result = W_ORGANIZATION;
		    goto stuff_area;
		}
		if (test_arg (cp, "-summary", 4)) {
		    w -> w_output |= W_SUMMARY;
		    break;
		}
		if (test_arg (cp, "-subdisplay", 4)) {
		    w -> w_output |= W_SUBDISPLAY;
		    break;
		}
		if (test_arg (cp, "-title", 4)) {
		    if (*vec == NULL) {
			advise (NULLCP,
				"expecting something after \"-title\"");
			goto you_really_lose;
		    }
		    w -> w_title = *vec++;
		    break;
		}
		if (test_arg (cp, "-unit", 4)) {
		    result = W_UNIT;
		    goto stuff_area;
		}

		advise (NULLCP, "unknown switch: %s", cp);
you_really_lose: ;
		if (mail) {
		    fprintf (stdfp, "\n\n");
		    goto print_help;
		}
		return NOTOK;

	    case 'd':
		if (strcmp (cp, "dsa"))
		    goto name_or_something;
		if (w -> w_record != W_NULL)
		    goto too_many_fields;
		w -> w_record = W_DSA;
		break;
		
	    case 'e':
		if (strcmp (cp, "expand"))
		    goto name_or_something;
		w -> w_output |= W_EXPAND;
		break;
		
	    case 'f':
		if (strcmp (cp, "full") == 0) {
		    w -> w_output |= W_FULL;
		    break;
		}
		if (strcmp (cp, "fullname") == 0) {
		    w -> w_nametype = W_COMMONAME;
		    goto name;
		}
		goto name_or_something;
		
	    case 'h':
		if (strcmp (cp, "handle"))
		    goto name_or_something;
		if (w -> w_inputype != W_NULL)
		    goto too_many_fields;
		if ((cp = *vec++) == NULL) {
		    advise (NULLCP, "expecting HANDLE after \"handle\"");
		    goto you_really_lose;
		}
got_handle: ;
		if (!mail && strcmp (cp, "me") == 0) {
		    if (mydn == NULL) {
			advise (NULLCP,
				"who are you?  use the \"thisis\" command first...");
			return NOTOK;
		    }
		    cp = mydn;
		}
		w -> w_inputype = W_HANDLE;
		w -> w_input = cp;
		break;

	    case 'l':
		if (strcmp (cp, "locality"))
		    goto name_or_something;
		if (w -> w_record != W_NULL)
		    goto too_many_fields;
		w -> w_record = W_LOCALITY;
		break;
		
	    case 'm':
		if (strcmp (cp, "mailbox"))
		    goto name_or_something;
		if (w -> w_inputype != W_NULL)
		    goto too_many_fields;
		if ((cp = *vec++) == NULL) {
		    advise (NULLCP, "expecting MAILBOX after \"mailbox\"");
		    goto you_really_lose;
		}
		w -> w_inputype = W_MAILBOX;
		w -> w_input = cp;
		break;

	    case 'n':
		if (strcmp (cp, "name"))
		    goto name_or_something;
name: ;
		if (w -> w_inputype != W_NULL)
		    goto too_many_fields;
		if ((cp = *vec++) == NULL) {
		    advise (NULLCP, "expecting NAME after \"%sname\"",
			    w -> w_nametype == W_COMMONAME ? "full"
			  : w -> w_nametype == W_SURNAME ? "sur" : "");
		    goto you_really_lose;
		}
		w -> w_inputype = W_NAME;
		w -> w_input = cp;
		break;

	    case 'o':
		if (strcmp (cp, "organization") && strcmp (cp, "org"))
		    goto name_or_something;
		if (w -> w_record != W_NULL)
		    goto too_many_fields;
		w -> w_record = W_ORGANIZATION;
		break;
		
	    case 'p':
		if (strcmp (cp, "person"))
		    goto name_or_something;
		if (w -> w_record != W_NULL)
		    goto too_many_fields;
		w -> w_record = W_PERSON;
		break;
		
	    case 'r':
		if (strcmp (cp, "role"))
		    goto name_or_something;
		if (w -> w_record != W_NULL)
		    goto too_many_fields;
		w -> w_record = W_ROLE;
		break;
		
	    case 's':
		if (strcmp (cp, "subdisplay") == 0) {
		    w -> w_output |= W_SUBDISPLAY;
		    break;
		}
		if (strcmp (cp, "summary") == 0) {
		    w -> w_output |= W_SUMMARY;
		    break;
		}
		if (strcmp (cp, "surname") == 0) {
		    w -> w_nametype = W_SURNAME;
		    goto name;
		}
		goto name_or_something;
		
	    case 'u':
		if (strcmp (cp, "unit"))
		    goto name_or_something;
		if (w -> w_record != W_NULL)
		    goto too_many_fields;
		w -> w_record = W_UNIT;
		break;
		
	    default:
name_or_something: ;
		if (w -> w_inputype != W_NULL)
		    goto too_many_fields;
		for (dp = cp; *dp; dp++)
		    if (!isdigit (*dp))
			break;
		if (!*dp)
		    goto got_handle;
		if ((dp = index (cp, '@')) == NULL) {
		    w -> w_inputype = W_NAME;
		    w -> w_input = cp;
		    break;
		}
		if (index (dp + 1, '@') || index (dp + 1, '=')) {
		    w -> w_inputype = W_HANDLE;
		    w -> w_input = cp;
		    break;
		}
		w -> w_inputype = W_MAILBOX;
		w -> w_input = cp;
		break;
	}
    }

    if (w -> w_nametype != W_NULL)
	switch (w -> w_record) {
	    default:
	        advise (NULLCP, "record-type ignored with \"%sname\"",
			w -> w_nametype == W_COMMONAME ? "full" : "sur");
		/* and fall... */

	    case W_NULL:
		w -> w_record = W_PERSON;
		/* and fall... */

	    case W_PERSON:
		break;
	}

    if (w -> w_input && strcmp (w -> w_input, "*") == 0)
	w -> w_input = NULL, w -> w_inputype = W_NULL;
    if (w -> w_title && strcmp (w -> w_title, "*") == 0)
	w -> w_title = NULL;
    if ((w -> w_input || w -> w_title)
	    && w -> w_area
	    && strcmp (w -> w_area, "*") == 0)
	w -> w_area = NULL, w -> w_areatype = W_NULL;

    if (w -> w_title) {
	if (w -> w_inputype == W_NULL)
	    w -> w_inputype = W_NAME;
	if (w -> w_inputype != W_NAME) {
	    advise (NULLCP, "title specification ignored with %s",
		    w -> w_inputype == W_HANDLE ? "HANDLE" : "MAILBOX");
	    w -> w_title = NULL;
	}
	else
	    if (w -> w_record == W_NULL)
		w -> w_record = W_PERSON;
    }

    if (w -> w_inputype == W_HANDLE && w -> w_geography) {
	advise (NULLCP, "geography specification ignored with HANDLE");
	w -> w_geography = NULL;
    }
    if (w -> w_geography)
	if (w -> w_area == NULL) {
	    w -> w_area = w -> w_geography, w -> w_areatype = W_LOCALITY;
	    w -> w_geography = NULL;
	}
	else
	    if (*w -> w_geography == '!')
		w -> w_geography++;

    if (w -> w_inputype == W_HANDLE && w -> w_area) {
	advise (NULLCP, "area specification ignored with HANDLE");
	w -> w_area = NULL, w -> w_areatype = W_NULL;
    }
    if (w -> w_area)
	if (w -> w_inputype == W_NULL) {
	    if (*w -> w_area != '!') {
		for (dp = w -> w_area; *dp; dp++)
		    if (!isdigit (*dp))
			break;
		w -> w_inputype = *dp ? W_NAME : W_HANDLE,
		w -> w_input = w -> w_area;
	    }
	    else
		w -> w_inputype = W_HANDLE, w -> w_input = w -> w_area + 1;
	    w -> w_record = w -> w_areatype;
	    w -> w_area = NULL, w -> w_areatype = W_NULL;
	}
	else
	    if (*w -> w_area == '!')
		w -> w_area++;

    if (w -> w_inputype == W_NULL) {
	register char **ap;

	if (w -> w_record != W_NULL || w -> w_output != W_NULL) {
	     advise (NULLCP, "input-field missing");
	     return NOTOK;
	}

print_help: ;
	for (ap = whois_help; *ap; ap++)
	    fprintf (stdfp, "%s%s", *ap, EOLN);

	return OK;
    }
    else
	if (w -> w_inputype == W_NAME && w -> w_nametype == W_NULL)
	    w -> w_nametype = nametype ? W_SURNAME : W_COMMONAME;

    (void) sprintf (fredseq, "fred%d", seqno++);

    bp = buffer;

    if (w -> w_areatype == W_NULL) {
	if (w -> w_inputype == W_MAILBOX
	        && w -> w_area == NULL
	        && (cp = index (w -> w_input, '@'))
		&& !index (++cp, '*')) {
	    (void) sprintf (bp, "fred -dm2dn %s", cp);
	    bp += strlen (bp);

	    goto multiple_searching;
	}

	result = whois_aux (w);
	if (ifd == NOTOK)
	    return result;
	goto check_wp;
    }

    (void) sprintf (bp,
		    "search %s -norelative -singlelevel -dontdereference -sequence default ",
		    limits (-1));
    bp += strlen (bp);

    for (ag = areas; ag -> ag_record; ag++)
	if (ag -> ag_record == w -> w_areatype)
	    break;
    if (w -> w_geography) {
	(void) sprintf (bp, "\"%s\" ", w -> w_geography);
	bp += strlen (bp);

	w -> w_geography = NULL;
    }
    else
	if (ag -> ag_area) {
	    (void) sprintf (bp, "\"%s\" ", ag -> ag_area);
	    bp += strlen (bp);
	}

    (void) sprintf (bp, "-filter \"objectClass=%s & %s%s\"",
		    ag -> ag_class, ag -> ag_rdn, eqstr (w -> w_area, 0));
    bp += strlen (bp);

multiple_searching: ;
    if ((fp = capture (buffer)) == NULL)
	return NOTOK;

    if (interrupted) {
you_lose: ;
	(void) fclose (fp);
	return NOTOK;
    }

    w -> w_area = orgname, w -> w_areatype = W_NULL;

    multiple = 0;
    while (fgets (buffer, sizeof buffer, fp) && !interrupted) {
	if ((cp = index (buffer, '\n')) == NULL) {
	    advise (NULLCP, "internal error(1)");
	    goto you_lose;
	}
	*cp = NULL;
    
	if (!isdigit (*buffer)) {
	    fprintf (stderr, "%s\n", buffer);
	    continue;
	}

	if ((cp = index (buffer, ' ')) == NULL) {
	    advise (NULLCP, "internal error(2)");
	    goto you_lose;
	}
	*cp++ = NULL;
	while (*cp == ' ')
	    cp++;
	
	if (multiple == 0 && (c = getc (fp)) != EOF) {
	    (void) ungetc (c, fp);
	    multiple = 1;
	}

	if (multiple && query && !network)
	    switch (ask ("try %s", cp)) {
		case NOTOK:
		    continue;

	       case OK:
	       default:
		    break;

	       case DONE:
		    goto out;
	    }
	else
	    if (verbose) {
		fprintf (stdfp, "Trying @%s ...\n", cp);
		(void) fflush (stdfp);
	    }

	(void) sprintf (orgname, "@%s", cp);
	(void) whois_aux (w);

	fprintf (stdfp, EOLN);
	(void) fflush (stdfp);
    }

out: ;
    (void) fclose (fp);

    if (ifd == NOTOK)
	return OK;

check_wp: ;
    (void) sprintf (buffer, "squid -sequence %s", fredseq);

    if ((fp = capture (buffer)) == NULL)
	return NOTOK;

    didany = 0;
    while (fgets (buffer, sizeof buffer, fp)) {
	char    disher[BUFSIZ];

	if ((cp = index (buffer, '\n')) == NULL) {
	    advise (NULLCP, "internal error(3)");
	    goto you_lose;
	}
	*cp = NULL;
    
	if (strncmp (buffer, "Sequence ", sizeof "Sequence " - 1) == 0)
	    continue;

	if ((cp = index (buffer, ' ')) == NULL) {
	    advise (NULLCP, "internal error(4)");
	    goto you_lose;
	}
	*cp++ = NULL;
	while (*cp == ' ')
	    cp++;
	
	if (!didany++) {
	    fprintf (stdfp, "-------\n\n");

	    if ((c = getc (fp)) != EOF) {
		(void) ungetc (c, fp);
		fprintf (stdfp, "Select one of:\n\n");
	    }
	    else
		fprintf (stdfp, "One entry matched:\n\n");

	    (void) strcpy (onehit, buffer);
	}

	(void) sprintf (disher,
			"showentry \"%s\" -fred -dontdereference -summary",
			cp);
	dontpage = 1;
	(void) dish (disher, 0);
	dontpage = 0;

	fprintf (stdfp, "     %s\n\n", cp);
	(void) fflush (stdfp);
    }
    (void) fclose (fp);

    if (!didany) {
	fprintf (stdfp,
		 "\nenter new \"whois\" command to continue searching (or \"quit\" to abort)\n");
	return OK;
    }

    if (didany == 1) {
	if (getline ("enter RETURN to use this entry (or \"no\" to look some more): ",
		     buffer) == NOTOK
	        || (str2vec (buffer, args) > 0 && *args[0] != 'y'))
	    return OK;
	args[0] = onehit;
    }
    else
	if (getline ("enter number (or RETURN to look some more): ", buffer)
	            == NOTOK
	        || str2vec (buffer, args) < 1)
	    return OK;

    if (sscanf (args[0], "%d", &result) != 1) {
	advise (NULLCP, "invalid number \"%s\"", args[0]);
	return OK;
    }

    (void) sprintf (buffer, "show -sequence %s %d -types rfc822Mailbox -value",
		    fredseq, result);

    if ((fp = capture (buffer)) == NULL)
	return NOTOK;

    if (fgets (buffer, sizeof buffer, fp) == NULL
	    || (cp = index (buffer, '\n')) == NULL) {
	advise (NULLCP, "internal error(5)");
	goto you_lose;
    }
    (void) fclose (fp);

    if (strncmp (buffer, "Invalid sequence number",
		 sizeof "Invalid sequence number" - 1) == 0) {
	advise (NULLCP, "invalid selection \"%d\"", result);
	return OK;
    }
    if (strncmp (buffer, "No attributes", sizeof "No attributes" - 1) == 0) {
	advise (NULLCP, "no rfc822Mailbox attribute for this entry!");
	return OK;
    }
    if (strncmp (buffer, "rfc822Mailbox", sizeof "rfc822Mailbox" - 1) == 0) {
	if ((cp = index (buffer, '-')) == NULL) {
	    advise (NULLCP, "internal error(6)");
	    return NOTOK;
	}
	for (cp++; isspace (*cp); cp++)
	    continue;
	if (verbose)
	    fprintf (stdfp, "using %s\n", cp);
	result = strlen (cp);

	if (write (ofd, cp, result) != result)
	    adios ("failed", "write to UA");

	istat = signal (SIGINT, SIG_IGN);
	qstat = signal (SIGQUIT, SIG_IGN);

	if (watch) {
	    fprintf (stderr, "---> %s", cp);
	    (void) fflush (stderr);
	}

	usetty = 0;

	return OK;
    }

    advise (NULLCP, "internal error(7): \"%s\"", buffer);
    return NOTOK;
}
    
/* \f

 */

static whois_aux (w)
register struct whois *w;
{
    register char *bp,
		  *cp;
    char   *handle,
	    buffer[BUFSIZ];
    register struct area_guide *ag;

    for (ag = areas; ag -> ag_record; ag++)
	if (ag -> ag_record == w -> w_record)
	    break;

    bp = buffer;
    switch (w -> w_inputype) {
	case W_NULL:
	default:
	    advise (NULLCP, "internal error(8)");
	    return NOTOK;

	case W_HANDLE:
	    (void) sprintf (bp, "showentry \"%s\" %s -fred -dontdereference",
			    w -> w_input, limits (0));
	    bp += strlen (bp);
	    goto options;

	case W_MAILBOX:
	    (void) sprintf (bp, "search %s -fred ", limits (1));
	    bp += strlen (bp);

	    if (w -> w_area) {
		(void) sprintf (bp, "\"%s\" ", w -> w_area);
		bp += strlen (bp);
	    }

	    (void) sprintf (bp, "-subtree -filter \"");
	    bp += strlen (bp);

	    cp = w -> w_input;
	    if (*cp == '@')
		(void) sprintf (bp, "mail=*%s", cp);
	    else
		if (*(cp + strlen (cp) - 1) == '@' || !index (cp, '@'))
		    (void) sprintf (bp, "mail=%s*", cp);
	        else
		    (void) sprintf (bp, "(mail=%s | otherMailbox=internet$%s)",
				    cp, cp);
	    bp += strlen (bp);
	    break;

	case W_NAME:
	    if (cp = w -> w_input) {
		cp += strlen (cp) - 1;
		if (*cp == '.')
		    *cp = '*';
	    }

	    (void) sprintf (bp, "search %s -%s ", limits (1),
			    kflag ? "show" : "fred");
	    bp += strlen (bp);

	    if (w -> w_area) {
		(void) sprintf (bp, "\"%s\" -subtree ", w -> w_area);
		bp += strlen (bp);
	    }
	    else
		if (w -> w_geography) {
		    (void) sprintf (bp, "\"%s\" ", w -> w_geography);
		    bp += strlen (bp);
		}
		else
		    if (ag -> ag_area) {
			(void) sprintf (bp, "\"%s\" %s ", ag -> ag_area,
					ag -> ag_search);
			bp += strlen (bp);
		    }
		    else {
			(void) sprintf (bp, "-subtree ");
			bp += strlen (bp);
		    }
	    (void) sprintf (bp, "-filter \"");
	    bp += strlen (bp);

	    handle = eqstr (w -> w_input, 0);
	    switch (w -> w_record) {
		case W_NULL:
		case W_PERSON:
		    if (handle) {
			if (w -> w_title
			        && (w -> w_record == W_NULL
				    || w -> w_nametype == W_SURNAME)) {
			    (void) sprintf (bp, "( ");
			    bp += strlen (bp);
			}
			if (w -> w_record == W_NULL) {
			    (void) sprintf (bp, "o%s | ou%s | l%s | ",
					    handle, handle, handle, handle);
			    bp += strlen (bp);
			}

			if (w -> w_nametype == W_SURNAME) {
			    if (w -> w_record == W_PERSON && !w -> w_title) {
				(void) sprintf (bp, "( ");
				bp += strlen (bp);
			    }
			    (void) sprintf (bp, "surname%s | mail=%s@* ",
					    eqstr (w -> w_input, 1),
					    w -> w_input);
			    bp += strlen (bp);
			    if (w -> w_record == W_PERSON && !w -> w_title) {
				(void) sprintf (bp, ") ");
				bp += strlen (bp);
			    }
			}
			else {
			    (void) sprintf (bp, "cn%s ", handle);
			    bp += strlen (bp);
			}

			if (w -> w_title
			        && (w -> w_record == W_NULL
				    || w -> w_nametype == W_SURNAME)) {
			    (void) sprintf (bp, ") ");
			    bp += strlen (bp);
			}
		    }
		    if (w -> w_title) {
			(void) sprintf (bp, "%stitle%s",
					handle ? "& " : "",
					eqstr (w -> w_title, 1));
			bp += strlen (bp);
		    }
		    break;

		default:
		    if (strcmp (handle, "=*")) {
			(void) sprintf (bp, "%s%s", ag -> ag_rdn, handle);
			bp += strlen (bp);
		    }
		    break;
	    }
	    break;
    }

    if (w -> w_record == W_PERSON
	    || (w -> w_record != W_NULL && strcmp (handle, "=*"))) {
	(void) sprintf (bp, " & ");
	bp += strlen (bp);
    }

    if (w -> w_record != W_NULL) {
	(void) sprintf (bp, "objectClass=%s", ag -> ag_class);
	bp += strlen (bp);
    }

    (void) sprintf (bp, "\"");
    bp += strlen (bp);
    
options: ;
    if (w -> w_output & W_EXPAND) {
	(void) sprintf (bp, " -expand");
	bp += strlen (bp);
    }
    if (w -> w_output & W_FULL) {
	(void) sprintf (bp, " -full");
	bp += strlen (bp);
    }
    if (w -> w_output & W_SUMMARY) {
	(void) sprintf (bp, " -summary");
	bp += strlen (bp);
    }
    if (w -> w_output & W_SUBDISPLAY) {
	(void) sprintf (bp, " -subdisplay");
	bp += strlen (bp);
    }

    (void) sprintf (bp, " -sequence %s", ifd != NOTOK ? fredseq : "default");
    bp += strlen (bp);

    return dish (buffer, 0);
}

/* \f

 */

static int  test_arg (user, full, minlen)
char   *user,
       *full;
int	minlen;
{
    int	    i;

    if ((i = strlen (user)) < minlen
	    || i > strlen (full)
	    || strncmp (user, full, i))
	return 0;

    return 1;
}

/* \f

 */

static char *eqstr (s, exact)
char   *s;
int	exact;
{
    static char buffer[BUFSIZ];

    if (s == NULL)
	return NULL;

    if (index (s, '*'))
	(void) sprintf (buffer, "=%s", s);
    else
	if (soundex)
	    (void) sprintf (buffer, "~=%s", s);
	else
	    if (exact)
		(void) sprintf (buffer, "=%s", s);
	    else
		(void) sprintf (buffer, "=*%s*", s);

    return buffer;
}

/* \f

 */

static char  *limits (isearch)
int	isearch;
{
    register char *bp;
    static char buffer[100];

    bp = buffer;

#ifdef	notdef	/* don't do this! */
    if (isearch) {
	(void) strcpy (bp, "-searchalias ");
	bp += strlen (bp);
    }
#endif

    (void) strcpy (bp, "-nosizelimit ");
    bp += strlen (bp);

    if (timelimit > 0)
	(void) sprintf (bp, "-timelimit %d", timelimit);
    else
	(void) strcpy (bp, "-notimelimit");
    bp += strlen (bp);

    if (isearch >= 0 && (network || oneshot)) {
	(void) strcpy (bp, " -nofredseq");
	bp += strlen (bp);
    }

    return buffer;
}

/* \f

 */

static FILE *capture (command)
char   *command;
{
    char    tmpfil[BUFSIZ];
    FILE   *fp,
    	   *savfp;

    (void) sprintf (tmpfil, "/tmp/fredXXXXXX");
    (void) unlink (mktemp (tmpfil));
    
    if ((fp = fopen (tmpfil, "w+")) == NULL) {
	advise (tmpfil, "unable to create");
	return NULL;
    }
    (void) unlink (tmpfil);

    savfp = stdfp, stdfp = fp;
    
    (void) dish (command, 0);

    stdfp = savfp;

    rewind (fp);

    return fp;
}