##
## Clients Makefile.in for OpenLDAP
-SUBDIRS= tools ud finger gopher mail500 fax500 rcpt500 maildap
+SUBDIRS= tools ud finger mail500 maildap
+++ /dev/null
-# $OpenLDAP$
-
-UNIX_PRGS = rp500 fax500
-EXEPRGS = $(@PLAT@_PRGS)
-PROGRAMS = xrpcomp.tmp $(EXEPRGS)
-
-SRCS= main.c faxtotpc.c rp500.c
-XSRCS=fax5version.c rpversion.c
-
-FAX5OBJS = main.o faxtotpc.o
-RPOBJS = rp500.o faxtotpc.o
-
-LDAP_INCDIR= ../../include
-LDAP_LIBDIR= ../../libraries
-
-XLIBS = -lldap -llber -llutil
-XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
-
-rp500 : rpversion.o
- $(LTLINK) -o $@ $(RPOBJS) rpversion.o $(LIBS)
-
-fax500 : fax5version.o
- $(LTLINK) -o $@ $(RPOBJS) fax5version.o $(LIBS)
-
-rpversion.c: ${RPOBJS} $(LDAP_LIBDEPEND)
- @-$(RM) $@
- $(MKVERSION) rp500 > $@
-
-fax5version.c: ${FAX5OBJS} $(LDAP_LIBDEPEND)
- @-$(RM) $@
- $(MKVERSION) fax500 > $@
-
-xrpcomp.tmp: xrpcomp
- $(SED) -e 's|%LIBEXECDIR%|$(libexecdir)|' $(srcdir)/xrpcomp > xrpcomp.tmp
-
-install-local: $(PROGRAMS) FORCE
- -$(MKDIR) $(DESTDIR)$(libexecdir)
- @( \
- for prg in $(EXEPRGS); do \
- $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \
- $(DESTDIR)$(libexecdir); \
- done \
- )
- $(INSTALL_SCRIPT) $(INSTALLFLAGS) xrpcomp.tmp \
- $(DESTDIR)$(libexecdir)/xrpcomp
+++ /dev/null
-README file for fax500
-
-xrpcomp
--------
-
-This directory contains a modified version of the rpcomp program, used
-with the Internet remote-printing experiment. More info on the experiment
-can be found in /mrose/tpc on ftp.ics.uci.edu.
-
-The xrpcomp program (it's a shell script) is like rpcomp, except that it
-will look in X.500 if no fax recipients are found in the .rpdb file.
-It still uses .rpdb to extract the originator information.
-
-There are a couple of things in rp500.c you will want to tailor to use
-xrpcomp at your site:
-
- DAPUSER This is the user the rp500 program, called from
- xrpcomp will bind to the directory as. It can
- be set to NULL.
-
- DEFAULT_BASE This is the search base rp500 will use when looking
- in the directory for fax recipients.
-
- DEFAULT_FILTERCONF
- Where to find the ldapfilter.conf file. Should
- make setting this automatic, but for now...
-
- PHONE_PREFIX The prefix of phones in your local area. If
- rp500 finds a fax number in the directory that is
- not fully qualified, it will append as many of
- these digits as necessary to make it fully
- qualified. NB it assumes US-format numbers.
-
- DEFAULT_LDAPHOST
- The host running the default ldap server to
- contact.
-
-Things to note:
-
-The rp500 program knows a little about the US phone number format, in
-an attempt to deal with (evil) people who have not put fully qualified
-international format (e.g. +1 ... ) phone numbers in their entry. If
-your users do not have US-format phone numbers, you'll need to take a
-look at the fax2email() routine in rp500.c and change it around a bit.
-
-7/30/93 -- Tim
-
-
-fax500
-------
-
-This directory also contains the fax500 program. fax500 is just like
-mail500, except that it looks up the facsimileTelephoneNumber
-attribute, constructs an appropriate "remote-printer@blah.tpc.int"
-address, and send the mail there. For example, the facsimile number
-"+1 313 555 1212" corresponds to the address
-"remote-printer@2.1.2.1.5.5.5.3.1.3.1.tpc.int." For a complete
-explanation of the Internet remote-printing experiment, look in
-/mrose/tpc on ftp.ics.uci.edu, or send mail to tpc-faq@town.hall.org.
-
-The general idea is that you can set things up so that mail sent to
-"user@fax.domain" will get printed on the user's fax machine, if
-they've entered a fax number in their X.500 entry.
-
-NOTE: you will need to modify faxtotpc.c if you have any "abbreviated"
-phone number capabilities. For example, our telephone switches allow
-you to dial only the last 5 digits of campus telephone numbers. People,
-therefore, tend to list the last 5 digits of their fax numbers. The
-routine "munge_phone()" takes care of fixing up abbreviated phone
-numbers. You may need to write your own code.
-
-fax500 is not yet complete. In particular, the following work still needs
-to be done:
-
-- If the group entry itself has a fax number, don't send to all the members'
- individual fax numbers. Instead, just send to the group's fax number.
-- The -h flag for fax500 defines both the host name and the search base.
- This causes problems because the host name we want is "fax.umich.edu"
- but we need to search "umich.edu." The workaround is to add an
- Associated Domain corresponding to the domain you want for your fax
- service to each X.500 group which is to be accessible.
-- We're working toward mail500 and fax500 being the same binary. Depending
- on what argv[0] is, you'll get different behavior. Although this
- binary should work just like mail500 if you name it "mail500" it's
- not yet been tested.
-- fax500 currently assumes that incoming messages are plain text, and
- therefore constructs a destination address like
- "remote-printer.user_name@2.1.2.1.5.5.5.3.1.3.1.tpc.int". If
- the message is already MIME-compliant with an "application/remote-printing"
- content type, we lose, since the remote-printing software assumes
- that anything other than "remote-printer" on ther lhs of the address
- means the message is plain text. Not sure about the solution to this.
-- Regarding group support - typically, when we collect all the fax numbers
- for a group, we'll end up either with (a) people who haven't registered
- fax numbers, or (b) "email-only" group members who do not have entries
- in X.500 (they only have an email address associated with the group).
- The question is: what do you do with faxes for these folks? You could
- (1) bounce to the sender (current behavior) or you could (2) send
- email to the members with no fax numbers, informing them that someone
- tried to send them a fax. I tend to prefer solution (2) for case (a),
- and solution (1) for case (b).
-- A configuration file-driven "munge_phone()" would be nice.
-
-8/23/93 - Gordon
+++ /dev/null
-/* $OpenLDAP$ */
-#ifndef FAX500_H
-#define FAX500_H 1
-
-/* in faxtotpc.c */
-void strip_nonnum ( char *str );
-char *remove_parens( char *ibuf, char *obuf );
-char *munge_phone ( char *ibuf, char *obuf );
-char *faxtotpc ( char *phone, char *userinfo );
-
-#endif
+++ /dev/null
-/* $OpenLDAP$ */
-/*
- * Copyright (c) 1993 Regents of the University of Michigan.
- * 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 the University of Michigan at Ann Arbor. The name of the University
- * 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.
- *
- *
- * Routines for parsing the facsimileTelephoneNumber field out of
- * an X.500 entry and converting it to a "tpc.int" domain name.
- *
- * char *faxtotpc( char *str, char *userinfo)
- *
- * faxtotpc() returns a pointer to a string allocated with malloc(3).
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/ctype.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-
-#include "fax500.h"
-
-#define TPCDOMAIN "tpc.int"
-
-/*
- * Remove everything from 'str' which is not a digit
- */
-void
-strip_nonnum( char *str )
-{
- char *p, *q;
- p = q = str;
- for (;;) {
- if (*p == '\0') {
- *q = *p;
- return;
- }
-
- if (isdigit((u_char) *p)) {
- *q = *p;
- p++;
- q++;
- } else {
- p++;
- }
- }
-}
-
-
-
-/*
- * Remove anything of the form (blah) where
- * "blah" contains a non-numeric character.
- */
-char *
-remove_parens( char *ibuf, char *obuf )
-{
- char *p = ibuf;
- char *q = obuf;
-
- while (*p != '\0') {
- char *s;
- char *t;
- if (*p == '(') {
- /* look for a closing paren */
- if (( s = strchr(p, ')')) != NULL) {
- /* Check the string between p and s */
- /* for non-numeric characters */
- t = p + 1;
- while (t < s) {
- if (!isdigit((u_char) *t)) {
- /* garbage, delete */
- p = s + 1;
- t = p;
- break;
- }
- t++;
- }
- /* when we get here, p points to the first */
- /* thing we want to keep, t to the last. */
- strncpy(q, p, t - p);
- q += t - p;
- p = t;
- } else {
- /* no closing paren, what to do? keep it */
- *q = *p;
- p++;
- q++;
- }
- } else {
- /* not a paren - copy out */
- *q = *p;
- p++;
- q++;
- }
- }
- *q = '\0'; /* terminate output string */
- return(obuf);
-}
-
-
-
-
-/*
- * Apply local fixups to phone numbers here. Replace this routine
- * with code to expand common "abbreviations" for phone numbers. For
- * example, on the U-M campus, it's only necessary to dial the last
- * 5 digits of the telephone number, and hence people here tend to
- * give only the last 5 digits of their fax numbers.
- *
- * Local U-M mods:
- * If exactly 5 digits were provided, assume it's a campus
- * phone number and prepend "1313nm" where "mn" are computed
- * according to the following:
- * first digit of
- * 5-digit "Local"
- * phone mn
- * ----- --
- * 3 76 e.g. "31234" -> "7631234"
- * 4 76
- * 7 74
- * 6 93
- * 8 99
- */
-char *
-munge_phone( char *ibuf, char *obuf )
-{
-#define UMAREACODE "1313"
-
- char prefix[3];
-
- if (strlen(ibuf) == 7) {
- /* Assume local number w/o area code */
- sprintf(obuf, "%s%s", UMAREACODE, ibuf);
- return(obuf);
- }
- if (strlen(ibuf) == 10) {
- /* Assume local number with area code */
- sprintf(obuf, "%s%s", "1", ibuf);
- return(obuf);
- }
- if (strlen(ibuf) != 5) {
- /* Not 5 digits - leave alone */
- strcpy(obuf, ibuf);
- return(obuf);
- }
-
- switch (ibuf[0]) {
- case '3' :
- case '4' : strcpy(prefix, "76");
- break;
- case '7' : strcpy(prefix, "74");
- break;
- case '6' : strcpy(prefix, "93");
- break;
- case '8' : strcpy(prefix, "99");
- break;
- default : /* Unknown, leave alone */
- strcpy(obuf, ibuf);
- return(obuf);
- }
- sprintf(obuf, "%s%s%s", UMAREACODE, prefix, ibuf);
- return(obuf);
-}
-
-
-
-/*
- * Convert string to "tpc.int" domain name.
- */
-char *
-faxtotpc( char *phone, char *userinfo )
-{
- char *p;
- char *q;
- char ibuf[255];
- char obuf[255];
-
- /* nuke spaces */
- strcpy(ibuf, phone);
- for (p = ibuf, q = obuf; *p != '\0'; p++) {
- if (*p != ' ') {
- *q = *p;
- q++;
- }
- }
- *q = '\0';
- strcpy(ibuf, obuf);
-
- remove_parens(ibuf, obuf);
- strcpy(ibuf, obuf);
-
- /* Look for "+" - if followed by a number,
- assume it's an international number and leave
- it alone.
- */
- if ((p = strchr(ibuf, '+')) != NULL) {
- if (isdigit((u_char) *(p + 1))) {
- /* strip any non-digits */
- strip_nonnum(ibuf);
- }
- } else {
- strip_nonnum(ibuf);
-
- /* Apply local munges */
- munge_phone(ibuf, obuf);
- strcpy(ibuf, obuf);
- }
-
- /* Convert string of form abcd to remote-printer@d.c.b.a.tpc.int */
- q = obuf;
- for (p = ibuf + strlen(ibuf) - 1; p >= ibuf; p--) {
- *q++ = *p;
- *q++ = '.';
- }
- *q = '\0';
- strcpy(ibuf, obuf);
- strcpy(obuf, "remote-printer");
-
- /* include userinfo if present */
- if (userinfo != NULL && strlen(userinfo)) {
- strcat(obuf, ".");
- strcat(obuf, userinfo);
- }
- strcat(obuf, "@");
- strcat(obuf, ibuf); /* tack on reversed phone number */
- strcat(obuf, TPCDOMAIN); /* tack on domain name */
- p = strdup(obuf);
- return(p);
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/*
- * Copyright (c) 1990 Regents of the University of Michigan.
- * 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 the University of Michigan at Ann Arbor. The name of the University
- * 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.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-
-#include <ac/ctype.h>
-#include <ac/errno.h>
-#include <ac/param.h>
-#include <ac/signal.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/sysexits.h>
-#include <ac/syslog.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
-
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-#include <ldap.h>
-
-#include "fax500.h"
-#include "ldap_defaults.h"
-
-#define USER 0
-#define GROUP_ERRORS 1
-#define GROUP_REQUEST 2
-#define GROUP_MEMBERS 3
-
-#define ERRORS "errors"
-#define REQUEST "request"
-#define MEMBERS "members"
-
-LDAP *ld;
-char *errorsfrom = NULL;
-char *mailfrom = NULL;
-char *host = NULL;
-int hostlen = 0;
-
-int identity;
-#define MAIL500 1
-#define FAX500 2
-
-typedef struct errs {
- int e_code;
-#define E_USERUNKNOWN 1
-#define E_AMBIGUOUS 2
-#define E_NOEMAIL 3
-#define E_NOREQUEST 4
-#define E_NOERRORS 5
-#define E_BADMEMBER 6
-#define E_JOINMEMBERNOEMAIL 7
-#define E_MEMBERNOEMAIL 8
-#define E_NOFAXNUM 9
-#define E_JOINMEMBERNOFAXNUM 10
-#define E_MEMBERNOFAXNUM 11
-#define E_FAXTOEMAILMBR 12
-
- char *e_addr;
- LDAPMessage *e_msg;
-} Error;
-
-typedef struct groupto {
- char *g_dn;
- char *g_errorsto;
- char **g_members;
-} Group;
-
-typedef struct baseinfo {
- char *b_dn; /* dn to start searching at */
- char b_rdnpref; /* give rdn's preference when searching? */
- char *b_filter[3]; /* filter to apply - name substituted for %s */
- /* (up to three of them) */
-} Base;
-
-Base base[] =
- { "ou=People, o=University of Michigan, c=US", 0,
- "uid=%s", "cn=%s", NULL,
- "ou=System Groups, ou=Groups, o=University of Michigan, c=US", 1,
- "(&(cn=%s)(associatedDomain=%h))", NULL, NULL,
- "ou=User Groups, ou=Groups, o=University of Michigan, c=US", 1,
- "(&(cn=%s)(associatedDomain=%h))", NULL, NULL,
- NULL
- };
-
-char *sendmailargs[] = { FAX_SENDMAIL, "-oMrX.500", "-odi", "-oi", "-f", NULL, NULL };
-
-static char *attrs[] = { "objectClass", "title", "postaladdress",
- "telephoneNumber", "mail", "description",
- "errorsTo", "rfc822ErrorsTo", "requestsTo",
- "rfc822RequestsTo", "joinable", "cn", "member",
- "facsimileTelephoneNumber", NULL };
-
-
-static void do_address(char *name, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr, int type);
-static int do_group(LDAPMessage *e, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr);
-static void do_group_members(LDAPMessage *e, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr);
-static void send_message(char **to);
-static void send_errors(Error *err, int nerr);
-static void do_noemailorfax(FILE *fp, Error *err, int namelen, int errtype);
-static void do_ambiguous(FILE *fp, Error *err, int namelen);
-static int count_values(char **list);
-static void add_to(char ***list, int *nlist, char **new);
-static int isgroup(LDAPMessage *e);
-static void add_error(Error **err, int *nerr, int code, char *addr, LDAPMessage *msg);
-static void add_group(char *dn, Group **list, int *nlist);
-static void unbind_and_exit(int rc) LDAP_GCCATTR((noreturn));
-static int group_loop(char *dn);
-static void send_group(Group *group, int ngroup);
-static int has_attributes(LDAPMessage *e, char *attr1, char *attr2);
-static char **get_attributes_mail_dn(LDAPMessage *e, char *attr1, char *attr2);
-static char *canonical(char *s);
-static int connect_to_x500 (void);
-static void do_group_errors (LDAPMessage *e, char *dn, char ***to, int *nto, Error **err, int *nerr);
-static void do_group_request (LDAPMessage *e, char *dn, char ***to, int *nto, Error **err, int *nerr);
-static void add_member (char *gdn, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr);
-
-
-int
-main ( int argc, char **argv )
-{
- char *myname;
- char **tolist;
- Error *errlist;
- Group *togroups;
- int numto, ngroups, numerr, nargs;
- int i, j;
-
- while ( (i = getopt( argc, argv, "f:h:m:" )) != EOF ) {
- switch( i ) {
- case 'f': /* who it's from & where errors should go */
- mailfrom = strdup( optarg );
- for ( j = 0; sendmailargs[j] != NULL; j++ ) {
- if ( strcmp( sendmailargs[j], "-f" ) == 0 ) {
- sendmailargs[j+1] = mailfrom;
- break;
- }
- }
- break;
-
- case 'h': /* hostname */
- host = strdup( optarg );
- hostlen = strlen(host);
- break;
-
- /* mailer-daemon address - who we should */
- case 'm': /* say errors come from */
- errorsfrom = strdup( optarg );
- break;
-
- default:
- syslog( LOG_ALERT, "unknown option" );
- break;
- }
- }
-
- if ( (myname = strrchr( argv[0], '/' )) == NULL )
- myname = strdup( argv[0] );
- else
- myname = strdup( myname + 1 );
- if (!strcmp(myname, "mail500")) {
- identity = MAIL500;
- } else if (!strcmp(myname, "fax500")) {
- identity = FAX500;
- } else {
- /* I give up, I must be mail500 */
- identity = MAIL500;
- }
-
-#ifdef SIGPIPE
- (void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
-
-#ifdef LOG_MAIL
- openlog( myname, OPENLOG_OPTIONS, LOG_MAIL );
-#elif LOG_DEBUG
- openlog( myname, OPENLOG_OPTIONS );
-#endif
-
- if ( mailfrom == NULL ) {
- syslog( LOG_ALERT, "required argument -f not present" );
- exit( EX_TEMPFAIL );
- }
- if ( errorsfrom == NULL ) {
- syslog( LOG_ALERT, "required argument -m not present" );
- exit( EX_TEMPFAIL );
- }
- if ( host == NULL ) {
- syslog( LOG_ALERT, "required argument -h not present" );
- exit( EX_TEMPFAIL );
- }
-
- if ( connect_to_x500() != 0 )
- exit( EX_TEMPFAIL );
-
- setuid( geteuid() );
-/*
-{
- char buf[1024];
- int i;
-
- strcpy( buf, argv[0] );
- for ( i = 1; i < argc; i++ ) {
- strcat( buf, " " );
- strcat( buf, argv[i] );
- }
-
- syslog( LOG_ALERT, "args: (%s)", buf );
-}
-*/
- numto = 0;
- add_to( &tolist, &numto, sendmailargs );
- nargs = numto;
- ngroups = numerr = 0;
- togroups = NULL;
- errlist = NULL;
- for ( i = optind; i < argc; i++ ) {
- char *s;
- int type;
-
- for ( j = 0; argv[i][j] != '\0'; j++ ) {
- if ( argv[i][j] == '.' || argv[i][j] == '_' )
- argv[i][j] = ' ';
- }
-
- type = USER;
- if ( (s = strrchr( argv[i], '-' )) != NULL ) {
- s++;
-
- if ( strcmp( s, ERRORS ) == 0 ) {
- type = GROUP_ERRORS;
- *(--s) = '\0';
- } else if ( strcmp( s, REQUEST ) == 0 ) {
- type = GROUP_REQUEST;
- *(--s) = '\0';
- } else if ( strcmp( s, MEMBERS ) == 0 ) {
- type = GROUP_MEMBERS;
- *(--s) = '\0';
- }
- }
-
- do_address( argv[i], &tolist, &numto, &togroups, &ngroups,
- &errlist, &numerr, type );
- }
-
- /*
- * If we have both errors and successful deliveries to make or if
- * if there are any groups to deliver to, we basically need to read
- * the message twice. So, we have to put it in a tmp file.
- */
-
- if ( numerr > 0 && numto > nargs || ngroups > 0 ) {
- FILE *fp;
- char buf[BUFSIZ];
-
- umask( 077 );
- if ( (fp = tmpfile()) == NULL ) {
- syslog( LOG_ALERT, "could not open tmp file" );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- /* copy the message to a temp file */
- while ( fgets( buf, sizeof(buf), stdin ) != NULL ) {
- if ( fputs( buf, fp ) == EOF ) {
- syslog( LOG_ALERT, "error writing tmpfile" );
- unbind_and_exit( EX_TEMPFAIL );
- }
- }
-
- if ( dup2( fileno( fp ), 0 ) == -1 ) {
- syslog( LOG_ALERT, "could not dup2 tmpfile" );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- fclose( fp );
- }
-
- /* deal with errors */
- if ( numerr > 0 ) {
- (void) rewind( stdin );
- send_errors( errlist, numerr );
- }
-
- (void) ldap_unbind( ld );
-
- /* send to groups with errorsTo */
- if ( ngroups > 0 ) {
- (void) rewind( stdin );
- send_group( togroups, ngroups );
- }
-
- /* send to expanded aliases and groups w/o errorsTo */
- if ( numto > nargs ) {
- (void) rewind( stdin );
- send_message( tolist );
- }
-
- return( EX_OK );
-}
-
-static int
-connect_to_x500( void )
-{
- int sizelimit = FAX_MAXAMBIGUOUS;
- int deref = LDAP_DEREF_ALWAYS;
-
- if ( (ld = ldap_init( NULL, 0 )) == NULL ) {
- syslog( LOG_ALERT, "ldap_init failed" );
- return( -1 );
- }
-
- ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
- ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
-
- if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
- syslog( LOG_ALERT, "ldap_simple_bind_s failed" );
- return( -1 );
- }
-
- return( 0 );
-}
-
-
-static void
-do_address(
- char *name,
- char ***to,
- int *nto,
- Group **togroups,
- int *ngroups,
- Error **err,
- int *nerr,
- int type
-)
-{
- int rc, b, f, match;
- LDAPMessage *e, *res;
- struct timeval timeout;
- char *dn;
- char filter[1024];
- char **mail;
- char **fax;
-
- /*
- * Look up the name in X.500, add the appropriate addresses found
- * to the to list, or to the err list in case of error. Groups are
- * handled by the do_group routine, individuals are handled here.
- * When looking up name, we follow the bases hierarchy, looking
- * in base[0] first, then base[1], etc. For each base, there is
- * a set of search filters to try, in order. If something goes
- * wrong here trying to contact X.500, we exit with EX_TEMPFAIL.
- * If the b_rdnpref flag is set, then we give preference to entries
- * that matched name because it's their rdn, otherwise not.
- */
-
- timeout.tv_sec = FAX_TIMEOUT;
- timeout.tv_usec = 0;
- for ( b = 0, match = 0; !match && base[b].b_dn != NULL; b++ ) {
- for ( f = 0; base[b].b_filter[f] != NULL; f++ ) {
- char *format, *p, *argv[3];
- int argc;
-
- for ( argc = 0; argc < 3; argc++ ) {
- argv[argc] = NULL;
- }
-
- format = strdup( base[b].b_filter[f] );
- for ( argc = 0, p = format; *p; p++ ) {
- if ( *p == '%' ) {
- switch ( *++p ) {
- case 's': /* %s is the name */
- argv[argc] = name;
- break;
-
- case 'h': /* %h is the host */
- *p = 's';
- argv[argc] = host;
- break;
-
- default:
- syslog( LOG_ALERT,
- "unknown format %c", *p );
- break;
- }
-
- argc++;
- }
- }
-
- /* three names ought to do... */
- sprintf( filter, format, argv[0], argv[1], argv[2] );
- free( format );
-
- res = NULL;
- rc = ldap_search_st( ld, base[b].b_dn,
- LDAP_SCOPE_SUBTREE, filter, attrs, 0, &timeout,
- &res );
-
- /* some other trouble - try again later */
- if ( rc != LDAP_SUCCESS &&
- rc != LDAP_SIZELIMIT_EXCEEDED ) {
- syslog( LOG_ALERT, "return %d from X.500", rc );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- if ( (match = ldap_count_entries( ld, res )) != 0 )
- break;
-
- ldap_msgfree( res );
- }
-
- if ( match )
- break;
- }
-
- /* trouble - try again later */
- if ( match == -1 ) {
- syslog( LOG_ALERT, "error parsing result from X.500" );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- /* no matches - bounce with user unknown */
- if ( match == 0 ) {
- add_error( err, nerr, E_USERUNKNOWN, name, NULL );
- return;
- }
-
- /* more than one match - bounce with ambiguous user? */
- if ( match > 1 ) {
- LDAPMessage *next, *tmpres = NULL;
- char *dn;
- char **xdn;
-
- /* not giving rdn preference - bounce with ambiguous user */
- if ( base[b].b_rdnpref == 0 ) {
- add_error( err, nerr, E_AMBIGUOUS, name, res );
- return;
- }
-
- /*
- * giving rdn preference - see if any entries were matched
- * because of their rdn. If so, collect them to deal with
- * later (== 1 we deliver, > 1 we bounce).
- */
-
- for ( e = ldap_first_entry( ld, res ); e != NULL; e = next ) {
- next = ldap_next_entry( ld, e );
- dn = ldap_get_dn( ld, e );
- xdn = ldap_explode_dn( dn, 1 );
-
- /* XXX bad, but how else can we do it? XXX */
- if ( strcasecmp( xdn[0], name ) == 0 ) {
- ldap_delete_result_entry( &res, e );
- ldap_add_result_entry( &tmpres, e );
- }
-
- ldap_value_free( xdn );
- free( dn );
- }
-
- /* nothing matched by rdn - go ahead and bounce */
- if ( tmpres == NULL ) {
- add_error( err, nerr, E_AMBIGUOUS, name, res );
- return;
-
- /* more than one matched by rdn - bounce with rdn matches */
- } else if ( (match = ldap_count_entries( ld, tmpres )) > 1 ) {
- add_error( err, nerr, E_AMBIGUOUS, name, tmpres );
- return;
-
- /* trouble... */
- } else if ( match < 0 ) {
- syslog( LOG_ALERT, "error parsing result from X.500" );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- /* otherwise one matched by rdn - send to it */
- ldap_msgfree( res );
- res = tmpres;
- }
-
- /*
- * if we get this far, it means that we found a single match for
- * name. for a user, we deliver to the mail attribute or bounce
- * with address and phone if no mail attr. for a group, we
- * deliver to all members or bounce to rfc822ErrorsTo if no members.
- */
-
- /* trouble */
- if ( (e = ldap_first_entry( ld, res )) == NULL ) {
- syslog( LOG_ALERT, "error parsing entry from X.500" );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- dn = ldap_get_dn( ld, e );
-
- if ( type == GROUP_ERRORS ) {
- /* sent to group-errors - resend to [rfc822]ErrorsTo attr */
- do_group_errors( e, dn, to, nto, err, nerr );
-
- } else if ( type == GROUP_REQUEST ) {
- /* sent to group-request - resend to [rfc822]RequestsTo attr */
- do_group_request( e, dn, to, nto, err, nerr );
-
- } else if ( type == GROUP_MEMBERS ) {
- /* sent to group-members - expand */
- do_group_members( e, dn, to, nto, togroups, ngroups, err,
- nerr );
-
- } else if ( isgroup( e ) ) {
- /*
- * sent to group - resend from [rfc822]ErrorsTo if it's there,
- * otherwise, expand the group
- */
-
- do_group( e, dn, to, nto, togroups, ngroups, err, nerr );
-
- ldap_msgfree( res );
-
- } else {
- /*
- * sent to user - mail attribute => add it to the to list,
- * otherwise bounce
- */
- switch (identity) {
- case FAX500 :
- if ( (mail = ldap_get_values( ld, e,
- "facsimileTelephoneNumber" )) != NULL ) {
- char *fdn;
- char **ufn;
- int i;
-
- fdn = ldap_get_dn( ld, e );
- ufn = ldap_explode_dn( fdn, 1 );
- /* Convert spaces to underscores for rp */
- for (i = 0; ufn[0][i] != '\0'; i++) {
- if (ufn[0][i] == ' ') {
- ufn[0][i] = '_';
- }
- }
- *mail = faxtotpc(*mail, ufn[0]);
-
- add_to(to, nto, mail);
-
- if (fdn != NULL) {
- free(fdn);
- }
- ldap_value_free( ufn );
- ldap_value_free( mail );
- ldap_msgfree( res );
- } else {
- add_error( err, nerr, E_NOFAXNUM,
- name, res );
- }
- break;
- case MAIL500 :
- if ( (mail = ldap_get_values( ld, e, "mail" ))
- != NULL ) {
- add_to( to, nto, mail );
-
- ldap_value_free( mail );
- ldap_msgfree( res );
- } else {
- add_error( err, nerr, E_NOEMAIL,
- name, res );
- }
- break;
- }
- }
-
- free( dn );
-
- return;
-}
-
-static int
-do_group(
- LDAPMessage *e,
- char *dn,
- char ***to,
- int *nto,
- Group **togroups,
- int *ngroups,
- Error **err,
- int *nerr
-)
-{
- /*
- * If this group has an rfc822ErrorsTo attribute, we need to
- * arrange for errors involving this group to go there, not
- * to the sender. Since sendmail only has the concept of a
- * single sender, we arrange for errors to go to groupname-errors,
- * which we then handle specially when (if) it comes back to us
- * by expanding to all the rfc822ErrorsTo addresses. If it has no
- * rfc822ErrorsTo attribute, we call do_group_members() to expand
- * the group.
- */
-
- if ( group_loop( dn ) ) {
- return( -1 );
- }
-
- if ( has_attributes( e, "rfc822ErrorsTo", "errorsTo" ) ) {
- add_group( dn, togroups, ngroups );
-
- return( 0 );
- }
-
- do_group_members( e, dn, to, nto, togroups, ngroups, err, nerr );
-
- return( 0 );
-}
-
-/* ARGSUSED */
-static void
-do_group_members(
- LDAPMessage *e,
- char *dn,
- char ***to,
- int *nto,
- Group **togroups,
- int *ngroups,
- Error **err,
- int *nerr
-)
-{
- int i, rc;
- char *ndn;
- char **mail, **member, **joinable;
- char filter[256];
- LDAPMessage *ee, *res;
- struct timeval timeout;
-
- /*
- * if all has gone according to plan, we've already arranged for
- * errors to go to the [rfc822]ErrorsTo attributes (if they exist),
- * so all we have to do here is arrange to send to the
- * rfc822Mailbox attribute, the member attribute, and anyone who
- * has joined the group by setting memberOfGroup equal to the
- * group dn.
- */
-
- /* add members in the group itself - mail attribute */
- if ( (mail = ldap_get_values( ld, e, "mail" )) != NULL ) {
- /*
- * These are only email addresses - impossible
- * to have a fax number
- */
- switch (identity) {
- case FAX500 :
- /* XXX How do we want to inform sender that the */
- /* group they sent to has email-only members? */
- break;
- case MAIL500 :
- add_to( to, nto, mail );
- break;
- }
-
- ldap_value_free( mail );
- }
-
- /* add members in the group itself - member attribute */
- if ( (member = ldap_get_values( ld, e, "member" )) != NULL ) {
- for ( i = 0; member[i] != NULL; i++ ) {
- add_member( dn, member[i], to, nto, togroups,
- ngroups, err, nerr );
- }
-
- ldap_value_free( member );
- }
-
- /* add members who have joined by setting memberOfGroup */
- if ( (joinable = ldap_get_values( ld, e, "joinable" )) != NULL ) {
- if ( strcasecmp( joinable[0], "FALSE" ) == 0 ) {
- ldap_value_free( joinable );
- return;
- }
- ldap_value_free( joinable );
-
- sprintf( filter, "(memberOfGroup=%s)", dn );
-
- timeout.tv_sec = FAX_TIMEOUT;
- timeout.tv_usec = 0;
-
- /* for each subtree to look in... */
- {
- int sizelimit = FAX_MAXMEMBERS;
- ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
- }
- for ( i = 0; base[i].b_dn != NULL; i++ ) {
- /* find entries that have joined this group... */
- rc = ldap_search_st( ld, base[i].b_dn,
- LDAP_SCOPE_SUBTREE, filter, attrs, 0, &timeout,
- &res );
-
- if ( rc == LDAP_SIZELIMIT_EXCEEDED ||
- rc == LDAP_TIMELIMIT_EXCEEDED ) {
- syslog( LOG_ALERT,
- "group search limit exceeded %d", rc );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- if ( rc != LDAP_SUCCESS ) {
- syslog( LOG_ALERT, "group search bad return %d",
- rc );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- /* for each entry that has joined... */
- for ( ee = ldap_first_entry( ld, res ); ee != NULL;
- ee = ldap_next_entry( ld, ee ) ) {
- if ( isgroup( ee ) ) {
- ndn = ldap_get_dn( ld, ee );
-
- if ( do_group( e, ndn, to, nto,
- togroups, ngroups, err, nerr )
- == -1 ) {
- syslog( LOG_ALERT,
- "group loop (%s) (%s)",
- dn, ndn );
- }
-
- free( ndn );
-
- continue;
- }
-
- /* add them to the to list */
- switch (identity) {
- case FAX500 :
- if ( (mail = ldap_get_values( ld, ee,
- "facsimileTelephoneNumber" ))
- != NULL ) {
- char *fdn;
- char **ufn;
- int i;
-
- fdn = ldap_get_dn( ld, ee );
- ufn = ldap_explode_dn( fdn, 1 );
- /*
- * Convert spaces to
- * underscores for rp
- */
- for (i = 0; ufn[0][i] != '\0';
- i++) {
- if (ufn[0][i] == ' ') {
- ufn[0][i] = '_';
- }
- }
- *mail = faxtotpc(*mail, ufn[0]);
- add_to(to, nto, mail);
-
- ldap_value_free( mail );
- ldap_msgfree( res );
- } else {
- ndn = ldap_get_dn( ld, ee );
-
- add_error( err, nerr,
- E_JOINMEMBERNOFAXNUM, ndn,
- NULL );
-
- free( ndn );
- }
- break;
- case MAIL500 :
- if ( (mail = ldap_get_values( ld, ee,
- "mail" )) != NULL ) {
- add_to( to, nto, mail );
-
- ldap_value_free( mail );
-
- /* else generate a bounce */
- } else {
- ndn = ldap_get_dn( ld, ee );
-
- add_error( err, nerr,
- E_JOINMEMBERNOEMAIL, ndn,
- NULL );
-
- free( ndn );
- }
- break;
- }
- }
-
- ldap_msgfree( res );
- }
- {
- int sizelimit = FAX_MAXAMBIGUOUS;
- ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
- }
- }
-
- return;
-}
-
-static void
-add_member(
- char *gdn,
- char *dn,
- char ***to,
- int *nto,
- Group **togroups,
- int *ngroups,
- Error **err,
- int *nerr
-)
-{
- char *ndn;
- char **mail;
- int rc;
- LDAPMessage *res, *e;
- struct timeval timeout;
-
- timeout.tv_sec = FAX_TIMEOUT;
- timeout.tv_usec = 0;
- if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, NULL,
- attrs, 0, &timeout, &res )) != LDAP_SUCCESS ) {
- if ( rc == LDAP_NO_SUCH_OBJECT ) {
- add_error( err, nerr, E_BADMEMBER, dn, NULL );
-
- return;
- } else {
- syslog( LOG_ALERT, "member search bad return %d", rc );
-
- unbind_and_exit( EX_TEMPFAIL );
- }
- }
-
- if ( (e = ldap_first_entry( ld, res )) == NULL ) {
- syslog( LOG_ALERT, "member search error parsing entry" );
-
- unbind_and_exit( EX_TEMPFAIL );
- }
- ndn = ldap_get_dn( ld, e );
-
- /* allow groups within groups */
- if ( isgroup( e ) ) {
- if ( do_group( e, ndn, to, nto, togroups, ngroups, err, nerr )
- == -1 ) {
- syslog( LOG_ALERT, "group loop (%s) (%s)", gdn, ndn );
- }
-
- free( ndn );
-
- return;
- }
-
- switch (identity) {
- case FAX500 :
- if ( (mail = ldap_get_values( ld, e,
- "facsimileTelephoneNumber" )) != NULL ) {
- char *fdn;
- char **ufn;
- int i;
- fdn = ldap_get_dn( ld, e );
- ufn = ldap_explode_dn( fdn, 1 );
- /* Convert spaces to underscores for rp */
- for (i = 0; ufn[0][i] != '\0'; i++) {
- if (ufn[0][i] == ' ') {
- ufn[0][i] = '_';
- }
- }
- *mail = faxtotpc(*mail, ufn[0]);
- add_to(to, nto, mail);
-
- ldap_value_free( mail );
- ldap_msgfree( res );
- } else {
- add_error( err, nerr, E_MEMBERNOFAXNUM, ndn, NULL );
- }
- break;
- case MAIL500 :
- /* send to the member's mail attribute */
- if ( (mail = ldap_get_values( ld, e, "mail" )) != NULL ) {
- add_to( to, nto, mail );
-
- ldap_value_free( mail );
-
- /* else generate a bounce */
- } else {
- add_error( err, nerr, E_MEMBERNOEMAIL, ndn, NULL );
- }
-
- free( ndn );
- }
- return;
-}
-
-static void
-do_group_request(
- LDAPMessage *e,
- char *dn,
- char ***to,
- int *nto,
- Error **err,
- int *nerr
-)
-{
- char **requeststo;
-
- if ( (requeststo = get_attributes_mail_dn( e, "rfc822RequestsTo",
- "requestsTo" )) != NULL ) {
- add_to( to, nto, requeststo );
-
- ldap_value_free( requeststo );
- } else {
- add_error( err, nerr, E_NOREQUEST, dn, NULL );
- }
-}
-
-static void
-do_group_errors(
- LDAPMessage *e,
- char *dn,
- char ***to,
- int *nto,
- Error **err,
- int *nerr
-)
-{
- char **errorsto;
-
- if ( (errorsto = get_attributes_mail_dn( e, "rfc822ErrorsTo",
- "errorsTo" )) != NULL ) {
- add_to( to, nto, errorsto );
-
- ldap_value_free( errorsto );
- } else {
- add_error( err, nerr, E_NOERRORS, dn, NULL );
- }
-}
-
-static void
-send_message( char **to )
-{
- int pid;
-#ifndef HAVE_WAITPID
- WAITSTATUSTYPE status;
-#endif
-
-
- /* parent */
- if ( (pid = fork()) != 0 ) {
-#ifdef HAVE_WAITPID
- waitpid( pid, (int *) NULL, 0 );
-#else
- wait4( pid, &status, WAIT_FLAGS, 0 );
-#endif
- /* child */
- } else {
- /* to includes sendmailargs */
- execv( FAX_SENDMAIL, to );
-
- syslog( LOG_ALERT, "execv failed" );
-
- exit( EX_TEMPFAIL );
- }
-}
-
-static void
-send_group( Group *group, int ngroup )
-{
- int i, pid;
- char **argv;
- int argc;
- char *iargv[7];
-#ifndef HAVE_WAITPID
- WAITSTATUSTYPE status;
-#endif
-
- for ( i = 0; i < ngroup; i++ ) {
- (void) rewind( stdin );
-
- iargv[0] = FAX_SENDMAIL;
- iargv[1] = "-f";
- iargv[2] = group[i].g_errorsto;
- iargv[3] = "-oMrX.500";
- iargv[4] = "-odi";
- iargv[5] = "-oi";
- iargv[6] = NULL;
-
- argv = NULL;
- argc = 0;
- add_to( &argv, &argc, iargv );
- add_to( &argv, &argc, group[i].g_members );
-
-
- /* parent */
- if ( (pid = fork()) != 0 ) {
-#ifdef HAVE_WAITPID
- waitpid( pid, (int *) NULL, 0 );
-#else
- wait4( pid, &status, WAIT_FLAGS, 0 );
-#endif
- /* child */
- } else {
- execv( FAX_SENDMAIL, argv );
-
- syslog( LOG_ALERT, "execv failed" );
-
- exit( EX_TEMPFAIL );
- }
- }
-
- return;
-}
-
-static void
-send_errors( Error *err, int nerr )
-{
- int i, namelen;
- FILE *fp;
- char buf[1024];
-
- sprintf( buf, "%s -oMrX.500 -odi -oi -f %s %s", FAX_SENDMAIL, errorsfrom,
- mailfrom );
- if ( (fp = popen( buf, "w" )) == NULL ) {
- syslog( LOG_ALERT, "could not popen sendmail for errs" );
- return;
- }
-
- fprintf( fp, "To: %s\n", mailfrom );
- fprintf( fp, "From: %s\n", errorsfrom );
- fprintf( fp, "Subject: undeliverable mail\n" );
- fprintf( fp, "\n" );
- fprintf( fp, "The following errors occurred when trying to deliver the attached mail:\n" );
- for ( i = 0; i < nerr; i++ ) {
- namelen = strlen( err[i].e_addr );
- fprintf( fp, "\n" );
-
- switch ( err[i].e_code ) {
- case E_USERUNKNOWN:
- fprintf( fp, "%s: User unknown\n", err[i].e_addr );
- break;
-
- case E_BADMEMBER:
- fprintf( fp, "%s: Group member does not exist\n",
- err[i].e_addr );
- break;
-
- case E_NOREQUEST:
- fprintf( fp, "%s: Group exists but has no request address\n",
- err[i].e_addr );
- break;
-
- case E_NOERRORS:
- fprintf( fp, "%s: Group exists but has no errors-to address\n",
- err[i].e_addr );
- break;
-
- case E_AMBIGUOUS:
- do_ambiguous( fp, &err[i], namelen );
- break;
-
- case E_NOEMAIL:
- do_noemailorfax( fp, &err[i], namelen, E_NOEMAIL );
- break;
-
- case E_MEMBERNOEMAIL:
- fprintf( fp, "%s: Group member exists but does not have an email address\n",
- err[i].e_addr );
- break;
-
- case E_JOINMEMBERNOEMAIL:
- fprintf( fp, "%s: User has joined group but does not have an email address\n",
- err[i].e_addr );
- break;
-
- case E_NOFAXNUM:
- do_noemailorfax( fp, &err[i], namelen, E_NOFAXNUM );
- break;
-
- case E_MEMBERNOFAXNUM:
- fprintf( fp, "%s: Group member exists but does not have a fax number\n",
- err[i].e_addr );
- break;
-
- case E_JOINMEMBERNOFAXNUM:
- fprintf( fp, "%s: User has joined group but does not have a fax number\n",
- err[i].e_addr );
- break;
-
- default:
- syslog( LOG_ALERT, "unknown error %d", err[i].e_code );
- unbind_and_exit( EX_TEMPFAIL );
- break;
- }
- }
-
- fprintf( fp, "\n------- The original message sent:\n\n" );
-
- while ( fgets( buf, sizeof(buf), stdin ) != NULL ) {
- fputs( buf, fp );
- }
-
- if ( pclose( fp ) == -1 ) {
- syslog( LOG_ALERT, "pclose failed" );
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- return;
-}
-
-
-static void
-do_noemailorfax( FILE *fp, Error *err, int namelen, int errtype )
-{
- int i, last;
- char *dn, *rdn;
- char **ufn, **vals;
-
- if (errtype == E_NOFAXNUM) {
- fprintf(fp, "%s: User has no facsimile number registered.\n",
- err->e_addr );
- } else if (errtype == E_NOEMAIL) {
- fprintf(fp, "%s: User has no email address registered.\n",
- err->e_addr );
- }
- fprintf( fp, "%*s Name, title, postal address and phone for '%s':\n\n",
- namelen, " ", err->e_addr );
-
- /* name */
- dn = ldap_get_dn( ld, err->e_msg );
- ufn = ldap_explode_dn( dn, 1 );
- rdn = strdup( ufn[0] );
- if ( strcasecmp( rdn, err->e_addr ) == 0 ) {
- if ( (vals = ldap_get_values( ld, err->e_msg, "cn" ))
- != NULL ) {
- for ( i = 0; vals[i]; i++ ) {
- last = strlen( vals[i] ) - 1;
- if ( isdigit((unsigned char) vals[i][last]) ) {
- rdn = strdup( vals[i] );
- break;
- }
- }
-
- ldap_value_free( vals );
- }
- }
- fprintf( fp, "%*s %s\n", namelen, " ", rdn );
- free( dn );
- free( rdn );
- ldap_value_free( ufn );
-
- /* titles or descriptions */
- if ( (vals = ldap_get_values( ld, err->e_msg, "title" )) == NULL &&
- (vals = ldap_get_values( ld, err->e_msg, "description" ))
- == NULL ) {
- fprintf( fp, "%*s No title or description registered\n",
- namelen, " " );
- } else {
- for ( i = 0; vals[i] != NULL; i++ ) {
- fprintf( fp, "%*s %s\n", namelen, " ", vals[i] );
- }
-
- ldap_value_free( vals );
- }
-
- /* postal address */
- if ( (vals = ldap_get_values( ld, err->e_msg, "postalAddress" ))
- == NULL ) {
- fprintf( fp, "%*s No postal address registered\n", namelen,
- " " );
- } else {
- fprintf( fp, "%*s ", namelen, " " );
- for ( i = 0; vals[0][i] != '\0'; i++ ) {
- if ( vals[0][i] == '$' ) {
- fprintf( fp, "\n%*s ", namelen, " " );
- while ( isspace((unsigned char) vals[0][i+1]) )
- i++;
- } else {
- fprintf( fp, "%c", vals[0][i] );
- }
- }
- fprintf( fp, "\n" );
-
- ldap_value_free( vals );
- }
-
- /* telephone number */
- if ( (vals = ldap_get_values( ld, err->e_msg, "telephoneNumber" ))
- == NULL ) {
- fprintf( fp, "%*s No phone number registered\n", namelen,
- " " );
- } else {
- for ( i = 0; vals[i] != NULL; i++ ) {
- fprintf( fp, "%*s %s\n", namelen, " ", vals[i] );
- }
-
- ldap_value_free( vals );
- }
-}
-
-/* ARGSUSED */
-static void
-do_ambiguous( FILE *fp, Error *err, int namelen )
-{
- int i, last;
- char *dn, *rdn;
- char **ufn, **vals;
- LDAPMessage *e;
-
- i = ldap_result2error( ld, err->e_msg, 0 );
-
- fprintf( fp, "%s: Ambiguous user. %s%d matches found:\n\n",
- err->e_addr, i == LDAP_SIZELIMIT_EXCEEDED ? "First " : "",
- ldap_count_entries( ld, err->e_msg ) );
-
- for ( e = ldap_first_entry( ld, err->e_msg ); e != NULL;
- e = ldap_next_entry( ld, e ) ) {
- dn = ldap_get_dn( ld, e );
- ufn = ldap_explode_dn( dn, 1 );
- rdn = strdup( ufn[0] );
- if ( strcasecmp( rdn, err->e_addr ) == 0 ) {
- if ( (vals = ldap_get_values( ld, e, "cn" )) != NULL ) {
- for ( i = 0; vals[i]; i++ ) {
- last = strlen( vals[i] ) - 1;
- if ( isdigit((unsigned char) vals[i][last]) ) {
- rdn = strdup( vals[i] );
- break;
- }
- }
-
- ldap_value_free( vals );
- }
- }
-
- if ( isgroup( e ) ) {
- vals = ldap_get_values( ld, e, "description" );
- } else {
- vals = ldap_get_values( ld, e, "title" );
- }
-
- fprintf( fp, " %-20s %s\n", rdn, vals ? vals[0] : "" );
- for ( i = 1; vals && vals[i] != NULL; i++ ) {
- fprintf( fp, " %s\n", vals[i] );
- }
-
- free( dn );
- free( rdn );
- ldap_value_free( ufn );
- if ( vals != NULL )
- ldap_value_free( vals );
- }
-}
-
-static int
-count_values( char **list )
-{
- int i;
-
- for ( i = 0; list && list[i] != NULL; i++ )
- ; /* NULL */
-
- return( i );
-}
-
-static void
-add_to( char ***list, int *nlist, char **new )
-{
- int i, nnew, oldnlist;
-
- nnew = count_values( new );
-
- oldnlist = *nlist;
- if ( *list == NULL || *nlist == 0 ) {
- *list = (char **) malloc( (nnew + 1) * sizeof(char *) );
- *nlist = nnew;
- } else {
- *list = (char **) realloc( *list, *nlist * sizeof(char *) +
- nnew * sizeof(char *) + sizeof(char *) );
- *nlist += nnew;
- }
-
- for ( i = 0; i < nnew; i++ ) {
- (*list)[i + oldnlist] = strdup( new[i] );
- }
- (*list)[*nlist] = NULL;
-
- return;
-}
-
-static int
-isgroup( LDAPMessage *e )
-{
- int i;
- char **oclist;
-
- oclist = ldap_get_values( ld, e, "objectClass" );
-
- for ( i = 0; oclist[i] != NULL; i++ ) {
- if ( strcasecmp( oclist[i], "rfc822MailGroup" ) == 0 ) {
- ldap_value_free( oclist );
- return( 1 );
- }
- }
- ldap_value_free( oclist );
-
- return( 0 );
-}
-
-static void
-add_error( Error **err, int *nerr, int code, char *addr, LDAPMessage *msg )
-{
- if ( *nerr == 0 ) {
- *err = (Error *) malloc( sizeof(Error) );
- } else {
- *err = (Error *) realloc( *err, (*nerr + 1) * sizeof(Error) );
- }
-
- (*err)[*nerr].e_code = code;
- (*err)[*nerr].e_addr = strdup( addr );
- (*err)[*nerr].e_msg = msg;
- (*nerr)++;
-
- return;
-}
-
-static void
-add_group( char *dn, Group **list, int *nlist )
-{
- int i, namelen;
- char **ufn;
-
- for ( i = 0; i < *nlist; i++ ) {
- if ( strcmp( dn, (*list)[i].g_dn ) == 0 ) {
- syslog( LOG_ALERT, "group loop 2 detected (%s)", dn );
- return;
- }
- }
-
- ufn = ldap_explode_dn( dn, 1 );
- namelen = strlen( ufn[0] );
-
- if ( *nlist == 0 ) {
- *list = (Group *) malloc( sizeof(Group) );
- } else {
- *list = (Group *) realloc( *list, (*nlist + 1) *
- sizeof(Group) );
- }
-
- /* send errors to groupname-errors@host */
- (*list)[*nlist].g_errorsto = (char *) malloc( namelen + sizeof(ERRORS)
- + hostlen + 2 );
- sprintf( (*list)[*nlist].g_errorsto, "%s-%s@%s", ufn[0], ERRORS, host );
- (void) canonical( (*list)[*nlist].g_errorsto );
-
- /* send to groupname-members@host - make it a list for send_group */
- (*list)[*nlist].g_members = (char **) malloc( 2 * sizeof(char *) );
- (*list)[*nlist].g_members[0] = (char *) malloc( namelen +
- sizeof(MEMBERS) + hostlen + 2 );
- sprintf( (*list)[*nlist].g_members[0], "%s-%s@%s", ufn[0], MEMBERS,
- host );
- (void) canonical( (*list)[*nlist].g_members[0] );
- (*list)[*nlist].g_members[1] = NULL;
-
- /* save the group's dn so we can check for loops above */
- (*list)[*nlist].g_dn = strdup( dn );
-
- (*nlist)++;
-
- ldap_value_free( ufn );
-
- return;
-}
-
-static void
-unbind_and_exit( int rc )
-{
- int i;
-
- if ( (i = ldap_unbind( ld )) != LDAP_SUCCESS )
- syslog( LOG_ALERT, "ldap_unbind failed %d\n", i );
-
- exit( rc );
-}
-
-static char *
-canonical( char *s )
-{
- char *saves = s;
-
- for ( ; *s != '\0'; s++ ) {
- if ( *s == ' ' )
- *s = '.';
- }
-
- return( saves );
-}
-
-static int
-group_loop( char *dn )
-{
- int i;
- static char **groups;
- static int ngroups;
-
- for ( i = 0; i < ngroups; i++ ) {
- if ( strcmp( dn, groups[i] ) == 0 )
- return( 1 );
- }
-
- if ( ngroups == 0 )
- groups = (char **) malloc( sizeof(char *) );
- else
- groups = (char **) realloc( groups,
- (ngroups + 1) * sizeof(char *) );
-
- groups[ngroups++] = strdup( dn );
-
- return( 0 );
-}
-
-static int
-has_attributes( LDAPMessage *e, char *attr1, char *attr2 )
-{
- char **attr;
-
- if ( (attr = ldap_get_values( ld, e, attr1 )) != NULL ) {
- ldap_value_free( attr );
- return( 1 );
- }
-
- if ( (attr = ldap_get_values( ld, e, attr2 )) != NULL ) {
- ldap_value_free( attr );
- return( 1 );
- }
-
- return( 0 );
-}
-
-static char **
-get_attributes_mail_dn( LDAPMessage *e, char *attr1, char *attr2 )
-{
- LDAPMessage *ee, *res;
- char **vals, **dnlist, **mail;
- int nto, i, rc;
- struct timeval timeout;
-
- vals = ldap_get_values( ld, e, attr1 );
- for ( nto = 0; vals != NULL && vals[nto] != NULL; nto++ )
- ; /* NULL */
-
- if ( (dnlist = ldap_get_values( ld, e, attr2 )) != NULL ) {
- timeout.tv_sec = FAX_TIMEOUT;
- timeout.tv_usec = 0;
-
- for ( i = 0; dnlist[i] != NULL; i++ ) {
- if ( (rc = ldap_search_st( ld, dnlist[i],
- LDAP_SCOPE_BASE, NULL, attrs, 0,
- &timeout, &res )) != LDAP_SUCCESS ) {
- if ( rc != LDAP_NO_SUCH_OBJECT ) {
- unbind_and_exit( EX_TEMPFAIL );
- }
-
- syslog( LOG_ALERT, "bad (%s) dn (%s)", attr2,
- dnlist[i] );
-
- continue;
- }
-
- if ( (ee = ldap_first_entry( ld, res )) == NULL ) {
- syslog( LOG_ALERT, "error parsing x500 entry" );
- continue;
- }
-
- if ( (mail = ldap_get_values( ld, ee, "mail" ))
- != NULL ) {
- add_to( &vals, &nto, mail );
-
- ldap_value_free( mail );
- }
-
- ldap_msgfree( res );
- }
- }
-
- return( vals );
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/*
- * Copyright (c) 1990 Regents of the University of Michigan.
- * 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 the University of Michigan at Ann Arbor. The name of the University
- * 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.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-
-#include <ac/ctype.h>
-#include <ac/signal.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/syslog.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
-
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-#include <ldap.h>
-
-#include "fax500.h"
-#include "ldap_defaults.h"
-
-#define DEFAULT_PORT 79
-#define DEFAULT_SIZELIMIT 50
-
-int debug;
-char *ldaphost = NULL;
-char *base = NULL;
-int deref = LDAP_DEREF_ALWAYS;
-int sizelimit = DEFAULT_SIZELIMIT;
-LDAPFiltDesc *filtd;
-
-static void print_entry(LDAP *ld, LDAPMessage *e);
-
-static void
-usage( char *name )
-{
- fprintf( stderr, "usage: %s [-d debuglevel] [-x ldaphost] [-b searchbase] [-a] [-z sizelimit] [-f filterfile] searchstring\r\n", name );
- exit( -1 );
-}
-
-int
-main( int argc, char **argv )
-{
- int i, rc, matches;
- char *filterfile = FILTERFILE;
- char buf[10];
- char *key;
- LDAP *ld;
- LDAPMessage *result, *e;
- LDAPFiltDesc *filtd;
- LDAPFiltInfo *fi;
- static char *attrs[] = { "title", "o", "ou", "postalAddress",
- "telephoneNumber", "mail",
- "facsimileTelephoneNumber", NULL };
-
- while ( (i = getopt( argc, argv, "ab:d:f:x:z:" )) != EOF ) {
- switch( i ) {
- case 'a': /* do not deref aliases when searching */
- deref = LDAP_DEREF_FINDING;
- break;
-
- case 'b': /* search base */
- base = strdup( optarg );
- break;
-
- case 'd': /* turn on debugging */
- debug = atoi( optarg );
- break;
-
- case 'f': /* ldap filter file */
- filterfile = strdup( optarg );
- break;
-
- case 'x': /* specify ldap host */
- ldaphost = strdup( optarg );
- break;
-
- case 'z': /* size limit */
- sizelimit = atoi( optarg );
- break;
-
- default:
- usage( argv[0] );
- }
- }
-
- if ( optind == argc ) {
- usage( argv[0] );
- }
- key = argv[optind];
-
- if ( (filtd = ldap_init_getfilter( filterfile )) == NULL ) {
- fprintf( stderr, "Cannot open filter file (%s)\n", filterfile );
- exit( -1 );
- }
-
-#ifdef SIGPIPE
- (void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
-
- if ( (ld = ldap_init( ldaphost, 0 )) == NULL ) {
- perror( "ldap_init" );
- exit( -1 );
- }
-
- ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
- ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
-
- if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
- fprintf( stderr, "X.500 is temporarily unavailable.\n" );
- ldap_perror( ld, "ldap_simple_bind_s" );
- exit( -1 );
- }
-
- result = NULL;
- {
- for ( fi = ldap_getfirstfilter( filtd, "rp500", key );
- fi != NULL; fi = ldap_getnextfilter( filtd ) ) {
- if ( (rc = ldap_search_s( ld, base, LDAP_SCOPE_SUBTREE,
- fi->lfi_filter, attrs, 0, &result ))
- != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
- && rc != LDAP_TIMELIMIT_EXCEEDED )
- {
- ldap_perror( ld, "ldap_search" );
- exit( -1 );
- }
-
- if ( (matches = ldap_count_entries( ld, result )) != 0
- || rc != LDAP_SUCCESS ) {
- break;
- }
- }
- }
-
- if ( matches == 1 ) {
- e = ldap_first_entry( ld, result );
-
- print_entry( ld, e );
- } else if ( matches > 1 ) {
- fprintf( stderr, "%d %s matches for \"%s\":\r\n", matches,
- fi->lfi_desc, key );
-
- for ( i = 1, e = ldap_first_entry( ld, result ); e != NULL;
- i++, e = ldap_next_entry( ld, e ) ) {
- int j;
- char *p, *dn, *rdn;
- char **title;
-
- dn = ldap_get_dn( ld, e );
- rdn = dn;
- if ( (p = strchr( dn, ',' )) != NULL )
- *p = '\0';
- while ( *rdn && *rdn != '=' )
- rdn++;
- if ( *rdn )
- rdn++;
- if ( strcasecmp( rdn, buf ) == 0 ) {
- char **cn;
- int i, last;
-
- cn = ldap_get_values( ld, e, "cn" );
- for ( i = 0; cn[i] != NULL; i++ ) {
- last = strlen( cn[i] ) - 1;
- if ( isdigit((unsigned char) cn[i][last]) ) {
- rdn = strdup( cn[i] );
- break;
- }
- }
- }
-
- title = ldap_get_values( ld, e, "title" );
-
- fprintf( stderr, " %d: %-20s %s\r\n", i, rdn,
- title ? title[0] : "" );
- if ( title != NULL ) {
- for ( j = 1; title[j] != NULL; j++ )
- fprintf( stderr, " %-20s %s\r\n",
- "", title[j] );
- }
- if ( title != NULL )
- ldap_value_free( title );
-
- free( dn );
- }
- if ( rc == LDAP_SIZELIMIT_EXCEEDED
- || rc == LDAP_TIMELIMIT_EXCEEDED ) {
- fprintf( stderr, "(Size or time limit exceeded)\n" );
- }
-
- fprintf( stderr, "Enter the number of the person you want: ");
-
- if ( fgets( buf, sizeof(buf), stdin ) == NULL
- || buf[0] == '\n' ) {
- exit( EXIT_FAILURE );
- }
- i = atoi( buf ) - 1;
- e = ldap_first_entry( ld, result );
- for ( ; i > 0 && e != NULL; i-- ) {
- e = ldap_next_entry( ld, e );
- }
- if ( e == NULL ) {
- fprintf( stderr, "Invalid choice!\n" );
- exit( EXIT_FAILURE );
- }
-
- print_entry( ld, e );
- } else if ( matches == 0 ) {
- fprintf( stderr, "No matches found for \"%s\"\n", key );
- exit( EXIT_FAILURE );
- } else {
- fprintf( stderr, "Error return from ldap_count_entries\n" );
- exit( -1 );
- }
-
- ldap_unbind( ld );
- return( 0 );
-}
-
-static void
-print_entry( LDAP *ld, LDAPMessage *e )
-{
- int i;
- char *dn, *rdn;
- char **ufn;
- char **title, **dept, **addr, **phone, **fax, **mail;
- char *faxmail, *org;
-
- dn = ldap_get_dn( ld, e );
- ufn = ldap_explode_dn( dn, 0 );
- rdn = strchr( ufn[0], '=' ) + 1;
-
- if ( (fax = ldap_get_values( ld, e, "facsimileTelephoneNumber" ))
- == NULL ) {
- fprintf( stderr, "Entry \"%s\" has no fax number.\n", dn );
- exit( EXIT_FAILURE );
- }
- faxmail = faxtotpc( fax[0], NULL );
- title = ldap_get_values( ld, e, "title" );
- phone = ldap_get_values( ld, e, "telephoneNumber" );
- mail = ldap_get_values( ld, e, "mail" );
- dept = ldap_get_values( ld, e, "ou" );
- addr = ldap_get_values( ld, e, "postalAddress" );
- org = "";
- for ( i = 0; ufn[i] != NULL; i++ ) {
- if ( strncmp( "o=", ufn[i], 2 ) == 0 ) {
- org = strdup( strchr( ufn[i], '=' ) + 1 );
- break;
- }
- }
-
- printf( "To: %s\n", faxmail );
- printf( "Subject:\n" );
- printf( "--------\n" );
- printf( "#<application/remote-printing\n" );
- printf( "Recipient: %s\r\n", rdn );
- printf( "Title: %s\r\n", title ? title[0] : "" );
- printf( "Organization: %s\r\n", org );
- printf( "Department: %s\r\n", dept ? dept[0] : "" );
- printf( "Telephone: %s\r\n", phone ? phone[0] : "" );
- printf( "Facsimile: %s\r\n", fax ? fax[0] : "" );
- printf( "Email: %s\r\n", mail ? mail[0] : "" );
-}
+++ /dev/null
-#! /bin/sh
-
-RP500=%LIBEXECDIR%/rp500
-
-NAME="$1"
-if [ -z "$NAME" ]; then
- echo "usage: xrpcomp name [arguments for comp]" 2>&1
- exit 1
-fi
-
-DB=".rpdb"
-if [ ! -s "$DB" ]; then
- DB="$HOME/.rpdb"
-fi
-if [ ! -s "$DB" ]; then
- echo "unable to read $DB" 2>&1
- exit 1
-fi
-
-C=/tmp/rp$$.comp S=/tmp/rp$$.sh O=/tmp/rp$$.orig
-trap "rm -f $C $S $O" 0 1 2 3 13 15
-
-cp /dev/null $S
-gawk -v NAME="$NAME" -v S="$S" -v O="$O" '
-function rev(f) {
- s = ""
- for (l = length(f); l > 0; l--)
- s = s "." substr(f, l, 1)
- return substr(s, 2, length(s) - 1)
-}
-
-BEGIN {
- RS= ""; FS = "\n"
- }
- {
- if (NR == 1) {
- from = $2
- gsub("Recipient[ ]*:", "Originator:", from);
- orig = "\r\n" from
- for (i = 3; i <= NF; i++)
- orig = orig "\r\n" $i;
- printf orig "\r\n" > O
- }
-
- if ($1 != NAME)
- next
- for (i = 2; i <= NF; i++) {
- if (match($i, "Facsimile[ ]*:") > 0) {
- fax = substr($i, RSTART+RLENGTH)
- gsub("[ +-]", "", fax)
-
- printf "ADDR=\"remote-printer@%s.tpc.int\"\n", rev(fax) > S
- printf "To: remote-printer@%s.tpc.int\n", rev(fax)
- printf "Subject:\n"
- printf "--------\n"
- printf "#<application/remote-printing\n"
-
- recip = $2
- for (i = 3; i <= NF; i++)
- recip = recip "\r\n" $i;
- printf "%s\r\n%s\r\n", recip, orig
-
- printf "#\n"
- exit(0)
- }
- }
- }' < $DB > $C
-. $S
-if [ -z "$ADDR" ]; then
- echo "recipient \"$NAME\" not in $DB, checking X.500..." 2>&1
- $RP500 "$NAME" > $C
- RC=$?
- if [ $RC = 1 ]; then
- exit 1
- elif [ $RC = 0 ]; then
- cat $O >> $C
- echo "#" >> $C
- else
- echo "error searching X.500" 2>&1
- exit 1
- fi
-fi
-
-shift
-comp -form $C $* -editor rpprompter
+++ /dev/null
-# $OpenLDAP$
-##
-## Makefile for gopher clients
-##
-
-UNIX_PRGS= go500gw go500
-PROGRAMS = $(@PLAT@_PRGS)
-
-SRCS= go500.c go500gw.c
-
-XSRCS= gwversion.c goversion.c
-GOOBJS = go500.o
-GWOBJS = go500gw.o
-
-LDAP_INCDIR= ../../include
-LDAP_LIBDIR= ../../libraries
-
-XLIBS = -lldap -llber -llutil
-XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
-
-go500 : goversion.o
- $(LTLINK) -o $@ $(GOOBJS) goversion.o $(LIBS)
-
-go500gw : gwversion.o
- $(LTLINK) -o $@ $(GWOBJS) gwversion.o $(LIBS)
-
-goversion.c: ${GOOBJS} $(LDAP_LIBDEPEND)
- @-$(RM) $@
- $(MKVERSION) go500 > $@
-
-gwversion.c: ${GWOBJS} $(LDAP_LIBDEPEND)
- @-$(RM) $@
- $(MKVERSION) go500gw > $@
-
-install-local: $(PROGRAMS) go500gw.help FORCE
- -$(MKDIR) $(DESTDIR)$(libexecdir) $(DESTDIR)$(datadir)
- @( \
- for prg in $(PROGRAMS); do \
- $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \
- $(DESTDIR)$(libexecdir); \
- done \
- )
- -$(MV) $(DESTDIR)$(datadir)/go500gw.help $(DESTDIR)$(datadir)/go500gw.help-
- $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/go500gw.help $(DESTDIR)$(datadir)
-
+++ /dev/null
-This directory contains source for two programs:
-
- go500 A gopher index search server to X.500 gateway
-
- go500gw A more general gopher to X.500 gateway
-
-Both programs use the LDAP protocol to talk to X.500.
-
-What you are trying to set up looks like this:
-
- -------- ----------------- -------- --------
-| gopher | | gopher to| LDAP | | LDAP | | X.500 |
-| client |<- gophr ->| LDAP g/w | API |<- LDAP ->| server |<- DAP ->| server |
-|________| |__________|______| |________| |________|
- go500gw ldapd
- or
- go500
-
-Both go500 and go500gw can be run either from inetd or as stand-alone
-servers.
-
-go500 is useful when you always want to search a fixed portion of the X.500
-tree. It does not let you browse around or change where you search.
-
-go500gw is useful when you want to provide a more general and flexible
-gateway from gopher to X.500. It allows users to browse around anywhere
-in the X.500 tree, doing searches at any point.
-
-**************************************************************************
-* RUNNING go500 *
-**************************************************************************
-
-1) Make and install the ldap distribution if you have not already done so:
-
- (cd ../; make lib-only; make inst-lib)
-
- or
-
- (cd ../; make all; make install)
-
- Use the second form if you don't already have an ldapd running
- somewhere you can connect to. Note that to make an ldap server,
- you will need the ISODE libraries and include files.
-
-2) Tailor go500 to your site before compiling:
-
- vi go500.c
-
- There are a couple of things to change in go500.c:
-
- DAPUSER - This is the DN go500 will bind to the directory as.
- You can specify NULL if you want.
-
- DEFAULT_BASE - This is the DN of the object below which go500
- will conduct its search. You typically want this to
- be the DN or your organization.
-
- DEFAULT_LDAPHOST - This is the host that is running the ldap
- server. If it's not on the localhost, you'll need to
- change this.
-
-3) Make go500:
-
- make
-
-4) Start the ldap daemon:
-
- ldapd [-c dsaname]
-
- You only need to do this if you're not already running one.
-
-5) Start go500 as a stand-alone server:
-
- go500
-
- or arrange to have it start from inetd:
-
- # vi /etc/services /* add the following line */
- go500 5555/tcp go500 # go500 server
-
- # vi /etc/inetd.conf /* add the following line */
- go500 stream tcp nowait nobody $(ETCDIR)/go500 go500 -I
-
- # kill -HUP <inetdpid> /* make inetd notice the change */
-
- where $(ETCDIR) is replaced by the ETCDIR from the top level Makefile
- and <inetdpid> is replaced by the pid of the inetd process.
-
-6) Configure your local gopher server to have an entry for go500.
- A sample .link file is given below, with the things you should
- change given in <>'s:
-
- Name=<Label of your choice>
- Type=7
- Port=5555
- Path=
- Host=<host.running.go500.here>
-
- You may also have to restart your gopher daemon, or remove
- the .cache file.
-
-7) Run a gopher client and try it out.
-
-**************************************************************************
-* RUNNING go500gw *
-**************************************************************************
-
-1) Make the ldap distribution if you have not already done so:
-
- (cd ../; make lib-only)
-
- or
-
- (cd ../; make lib-only ldap-server)
-
- Use the second form if you don't already have an ldapd running
- somewhere you can connect to. Note that to make an ldap server,
- you will need the ISODE libraries and include files.
-
-2) Tailor go500gw to your site before compiling:
-
- vi go500gw.c
-
- There are a couple of things to change in go500gw.c:
-
- GO500DN - This is the DN go500gw will bind to the directory as.
- You can specify NULL if you want.
-
- HELPFILE - This is the pathname of the helpfile (actually, the
- file that's displayed when a user chooses "About the
- Gopher to X.500 Gateway").
-
- LDAPHOST - This is the host that is running the ldap server.
- If it's not on the localhost, you'll need to change this.
-
-3) Make go500gw:
-
- make
-
-4) Start the ldap daemon:
-
- ldapd [-c dsaname]
-
- You only need to do this if you're not already running one.
-
-5) Start go500gw either as a stand-alone server:
-
- go500gw
-
- or arrange to have it start from inetd:
-
- # vi /etc/services /* add the following line */
- go500gw 5555/tcp go500gw # go500gw server
-
- # vi /etc/inetd.conf /* add the following line */
- go500gw stream tcp nowait nobody $(ETCDIR)/go500gw go500gw -I
-
- # kill -HUP <inetdpid> /* make inetd notice the change */
-
- where $(ETCDIR) is replaced by the ETCDIR from the top level Makefile
- and <inetdpid> is replaced by the pid of the inetd process.
-
-6) Configure your local gopher server to have an entry for go500gw.
- A sample .link file is given below, with the things you should
- change given in <>'s:
-
- Name=<Label of your choice>
- Type=1
- Port=7777
- Path=M
- Host=<host.running.go500gw.here>
-
- You may also have to restart your gopher daemon, or remove
- the .cache file.
-
- If you want to start go500gw at some point in the X.500 tree
- other than the root, you can change the Path parameter above
- to something like this, for example:
-
- Path=Mo=University of Michigan,c=US
-
- Of course, you would substitute your own organization's DN.
-
-7) Run a gopher client and try it out.
+++ /dev/null
-/* $OpenLDAP$ */
-/*
- * Copyright (c) 1990 Regents of the University of Michigan.
- * 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 the University of Michigan at Ann Arbor. The name of the University
- * 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.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-
-#include <ac/ctype.h>
-#include <ac/signal.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/syslog.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
-
-#include <ac/param.h>
-#include <ac/setproctitle.h>
-
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-#include <ldap.h>
-#include <disptmpl.h>
-
-#include "ldap_defaults.h"
-
-#define ldap_debug debug
-#include "ldap_log.h"
-
-#include "lutil.h"
-
-
-int debug;
-int dosyslog;
-int ldap_syslog;
-int ldap_syslog_level;
-int inetd;
-int dtblsize;
-
-char *ldaphost = NULL;
-char *base = NULL;
-int rdncount = GO500_RDNCOUNT;
-char *filterfile = FILTERFILE;
-char *templatefile = TEMPLATEFILE;
-
-char myhost[MAXHOSTNAMELEN];
-int myport;
-
-static void usage ( char *name ) LDAP_GCCATTR((noreturn));
-static int set_socket (int port);
-static RETSIGTYPE wait4child(int sig);
-static void do_queries (int s) LDAP_GCCATTR((noreturn));
-static void do_error (FILE *fp, char *s);
-static void do_search (LDAP *ld, FILE *fp, char *buf);
-static void do_read (LDAP *ld, FILE *fp, char *dn);
-
-static void
-usage( char *name )
-{
- fprintf( stderr, "usage: %s [-d debuglevel] [-f filterfile] [-t templatefile]\r\n\t[-a] [-l] [-p port] [-x ldaphost] [-b searchbase] [-c rdncount]\r\n", name );
- exit( EXIT_FAILURE );
-}
-
-int
-main( int argc, char **argv )
-{
- int s, ns, rc;
- int port = -1;
- int i, pid;
- char *myname;
- fd_set readfds;
- struct hostent *hp;
- struct sockaddr_in from;
- socklen_t fromlen;
-
-#if defined( LDAP_PROCTITLE ) && !defined( HAVE_SETPROCTITLE )
- /* for setproctitle */
- Argv = argv;
- Argc = argc;
-#endif
-
- while ( (i = getopt( argc, argv, "b:d:f:lp:c:t:x:I" )) != EOF ) {
- switch( i ) {
- case 'b': /* searchbase */
- base = strdup( optarg );
- break;
-
- case 'd': /* debug level */
- debug |= atoi( optarg );
- break;
-
- case 'f': /* ldap filter file */
- filterfile = strdup( optarg );
- break;
-
- case 'l': /* log via LOG_LOCAL3 */
- dosyslog = 1;
- break;
-
- case 'p': /* port to listen to */
- port = atoi( optarg );
- break;
-
- case 'c': /* number of DN components to show */
- rdncount = atoi( optarg );
- break;
-
- case 't': /* ldap template file */
- templatefile = strdup( optarg );
- break;
-
- case 'x': /* ldap server hostname */
- ldaphost = strdup( optarg );
- break;
-
- case 'I': /* run from inetd */
- inetd = 1;
- break;
-
- default:
- usage( argv[0] );
- }
- }
-
-#ifdef GO500_HOSTNAME
- strcpy( myhost, GO500_HOSTNAME );
-#else
- if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost)-1 )
- == -1 ) {
- perror( "gethostname" );
- exit( EXIT_FAILURE );
- }
- myhost[sizeof(myhost)-1] = '\0';
-#endif
-
-#ifdef HAVE_SYSCONF
- dtblsize = sysconf( _SC_OPEN_MAX );
-#elif HAVE_GETDTABLESIZE
- dtblsize = getdtablesize();
-#else
- dtblsize = FD_SETSIZE;
-#endif
-
-#ifdef FD_SETSIZE
- if (dtblsize > FD_SETSIZE) {
- dtblsize = FD_SETSIZE;
- }
-#endif /* FD_SETSIZE*/
-
- /* detach if stderr is redirected or no debugging */
- if ( inetd == 0 )
- lutil_detach( debug && !isatty( 1 ), 1 );
-
- if ( (myname = strrchr( argv[0], '/' )) == NULL )
- myname = strdup( argv[0] );
- else
- myname = strdup( myname + 1 );
-
- if ( debug ) {
- ber_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
- ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
- }
-
-#ifdef SIGPIPE
- (void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
-
- if ( dosyslog ) {
-#ifdef LOG_LOCAL3
- openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL3 );
-#elif LOG_DEBUG
- openlog( myname, OPENLOG_OPTIONS );
-#endif
- }
- if ( dosyslog )
- syslog( LOG_INFO, "initializing" );
-
- /* set up the socket to listen on */
- if ( inetd == 0 ) {
- s = set_socket( port );
-
- /* arrange to reap children */
- (void) SIGNAL( SIGCHLD, wait4child );
- } else {
- myport = GO500_PORT;
-
- fromlen = sizeof(from);
- if ( getpeername( 0, (struct sockaddr *) &from, &fromlen )
- == 0 ) {
- hp = gethostbyaddr( (char *) &(from.sin_addr),
- sizeof(from.sin_addr), AF_INET );
- Debug( LDAP_DEBUG_ARGS, "connection from %s (%s)\n",
- (hp == NULL) ? "unknown" : hp->h_name,
- inet_ntoa( from.sin_addr ), 0 );
-
- if ( dosyslog ) {
- syslog( LOG_INFO, "connection from %s (%s)",
- (hp == NULL) ? "unknown" : hp->h_name,
- inet_ntoa( from.sin_addr ) );
- }
-
-#ifdef LDAP_PROCTITLE
- setproctitle( "%s", hp == NULL ? inet_ntoa( from.sin_addr ) :
- hp->h_name );
-#endif
- }
-
- do_queries( 0 );
-
- exit( EXIT_SUCCESS );
- }
-
- for ( ;; ) {
- FD_ZERO( &readfds );
- FD_SET( s, &readfds );
-
- if ( (rc = select( dtblsize, &readfds, 0, 0 ,0 )) == -1 ) {
- if ( debug ) perror( "select" );
- continue;
- } else if ( rc == 0 ) {
- continue;
- }
-
- if ( ! FD_ISSET( s, &readfds ) )
- continue;
-
- fromlen = sizeof(from);
- if ( (ns = accept( s, (struct sockaddr *) &from, &fromlen ))
- == -1 ) {
- if ( debug ) perror( "accept" );
- exit( EXIT_FAILURE );
- }
-
- hp = gethostbyaddr( (char *) &(from.sin_addr),
- sizeof(from.sin_addr), AF_INET );
-
- if ( dosyslog ) {
- syslog( LOG_INFO, "TCP connection from %s (%s)",
- (hp == NULL) ? "unknown" : hp->h_name,
- inet_ntoa( from.sin_addr ) );
- }
-
- switch( pid = fork() ) {
- case 0: /* child */
- tcp_close( s );
- do_queries( ns );
- break;
-
- case -1: /* failed */
- perror( "fork" );
- break;
-
- default: /* parent */
- tcp_close( ns );
- if ( debug )
- fprintf( stderr, "forked child %d\n", pid );
- break;
- }
- }
- /* NOT REACHED */
-}
-
-static int
-set_socket( int port )
-{
- int s, one;
- struct sockaddr_in addr;
-
- if ( port == -1 )
- port = GO500_PORT;
- myport = port;
-
- if ( (s = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
- perror( "socket" );
- exit( EXIT_FAILURE );
- }
-
-#ifdef SO_REUSEADDR
- /* set option so clients can't keep us from coming back up */
- one = 1;
- if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
- sizeof(one) ) < 0 ) {
- perror( "setsockopt" );
- exit( EXIT_FAILURE );
- }
-#endif
-#ifdef SO_KEEPALIVE
- /* enable keep alives */
- one = 1;
- if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
- sizeof(one) ) < 0 ) {
- perror( "setsockopt" );
- exit( EXIT_FAILURE );
- }
-#endif
-
- /* bind to a name */
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons( port );
- if ( bind( s, (struct sockaddr *) &addr, sizeof(addr) ) ) {
- perror( "bind" );
- exit( EXIT_FAILURE );
- }
-
- /* listen for connections */
- if ( listen( s, 5 ) == -1 ) {
- perror( "listen" );
- exit( EXIT_FAILURE );
- }
-
- if ( debug ) printf("tcp socket allocated, bound, and listening\n");
-
- return( s );
-}
-
-static RETSIGTYPE
-wait4child( int sig )
-{
-#ifndef HAVE_WAITPID
- WAITSTATUSTYPE status;
-#endif
-
- if ( debug ) printf( "parent: catching child status\n" );
-
-#ifdef HAVE_WAITPID
- while (waitpid ((pid_t) -1, (int *) NULL, WAIT_FLAGS) > 0)
- ; /* NULL */
-#else
- while ( wait4((pid_t) -1, &status, WAIT_FLAGS, 0 ) > 0 )
- ; /* NULL */
-#endif
-
- (void) SIGNAL_REINSTALL ( SIGCHLD, wait4child );
-}
-
-static void
-do_queries( int s )
-{
- char buf[1024], *query;
- int len;
- FILE *fp;
- int rc;
- struct timeval timeout;
- fd_set readfds;
- LDAP *ld;
-
- if ( (fp = fdopen( s, "a+")) == NULL ) {
- exit( EXIT_FAILURE );
- }
-
- timeout.tv_sec = GO500_TIMEOUT;
- timeout.tv_usec = 0;
- FD_ZERO( &readfds );
- FD_SET( fileno( fp ), &readfds );
-
- if ( (rc = select( dtblsize, &readfds, 0, 0, &timeout )) <= 0 )
- exit( EXIT_FAILURE );
-
- if ( fgets( buf, sizeof(buf), fp ) == NULL )
- exit( EXIT_FAILURE );
-
- len = strlen( buf );
- if ( debug ) {
- fprintf( stderr, "got %d bytes\n", len );
-#ifdef LDAP_DEBUG
- ber_bprint( buf, len );
-#endif
- }
-
- /* strip of \r \n */
- if ( buf[len - 1] == '\n' )
- buf[len - 1] = '\0';
- len--;
- if ( buf[len - 1] == '\r' )
- buf[len - 1] = '\0';
- len--;
-
- query = buf;
-
- /* strip off leading white space */
- while ( isspace( (unsigned char) *query )) {
- ++query;
- --len;
- }
-
- rewind(fp);
-
- if ( *query == '~' || *query == '@' ) {
- ld = NULL;
- } else if ( (ld = ldap_init( ldaphost, 0 )) == NULL ) {
- fprintf(fp,
- "0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
- LDAP_SERVER_DOWN, myhost, myport );
- fprintf( fp, ".\r\n" );
- rewind(fp);
- exit( EXIT_FAILURE );
- } else {
- int deref = GO500_DEREF;
- ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
-
- rc = ldap_simple_bind_s( ld, NULL, NULL );
- if ( rc != LDAP_SUCCESS ) {
- fprintf(fp,
- "0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
- rc, myhost, myport );
- fprintf( fp, ".\r\n" );
- rewind(fp);
- exit( EXIT_FAILURE );
- }
- }
-
- switch ( *query ) {
- case '~':
- fprintf( fp, "The query you specified was not specific enough, causing a size limit\r\n" );
- fprintf( fp, "to be exceeded and the first several matches found to be returned.\r\n" );
- fprintf( fp, "If you did not find the match you were looking for, try issuing a more\r\n" );
- fprintf( fp, "specific query, for example one that contains both first and last name.\r\n" );
- fprintf( fp, ".\r\n" );
- break;
-
- case '=':
- do_read( ld, fp, ++query );
- break;
-
- case '@':
- do_error( fp, ++query );
- break;
-
- default:
- do_search( ld, fp, query );
- break;
- }
-
- fprintf( fp, ".\r\n" );
- rewind(fp);
-
- if ( ld != NULL) {
- ldap_unbind( ld );
- }
-
- exit( EXIT_FAILURE );
- /* NOT REACHED */
-}
-
-static void
-do_error( FILE *fp, char *s )
-{
- int code;
-
- code = atoi( s );
-
- fprintf( fp, "An error occurred searching X.500. The error code was %d\r\n", code );
- fprintf( fp, "The corresponding error is: %s\r\n", ldap_err2string( code ) );
- fprintf( fp, "No additional information is available\r\n" );
- fprintf( fp, ".\r\n" );
-}
-
-static void
-do_search( LDAP *ld, FILE *fp, char *buf )
-{
- char *dn, *rdn;
- char **title;
- int rc, matches = 0;
- struct timeval tv;
- LDAPFiltInfo *fi;
- LDAPFiltDesc *filtd;
- LDAPMessage *e, *res;
- static char *attrs[] = { "title", 0 };
-
- if ( (filtd = ldap_init_getfilter( filterfile )) == NULL ) {
- fprintf( stderr, "Cannot open filter file (%s)\n",
- filterfile );
- exit( EXIT_FAILURE );
- }
-
- tv.tv_sec = GO500_TIMEOUT;
- tv.tv_usec = 0;
- for ( fi = ldap_getfirstfilter( filtd, "go500", buf );
- fi != NULL;
- fi = ldap_getnextfilter( filtd ) )
- {
- if ( (rc = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE,
- fi->lfi_filter, attrs, 0, &tv, &res ))
- != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
- fprintf(fp, "0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
- rc, myhost, myport );
- ldap_getfilter_free( filtd );
- return;
- }
-
- if ( (matches = ldap_count_entries( ld, res )) != 0 )
- break;
- }
- ldap_getfilter_free( filtd );
-
- if ( matches <= 0 ) {
- return;
- }
-
-#ifdef GO500_SORT_ATTR
- ldap_sort_entries( ld, &res, GO500_SORT_ATTR, strcasecmp );
-#endif
-
- for ( e = ldap_first_entry( ld, res ); e != NULL;
- e = ldap_next_entry( ld, e ) ) {
- char *s;
-
- dn = ldap_get_dn( ld, e );
- rdn = strdup( dn );
- if ( (s = strchr( rdn, ',' )) != NULL )
- *s = '\0';
-
- if ( (s = strchr( rdn, '=' )) == NULL )
- s = rdn;
- else
- ++s;
-
- title = ldap_get_values( ld, e, "title" );
-
- if ( title != NULL ) {
- char *p;
-
- for ( p = title[0]; *p; p++ ) {
- if ( *p == '/' )
- *p = '\\';
- }
- }
-
- fprintf( fp, "0%-20s %s\t=%s\t%s\t%d\r\n", s,
- title ? title[0] : "", dn, myhost, myport );
-
- if ( title != NULL )
- ldap_value_free( title );
-
- free( rdn );
- free( dn );
- }
-
- if ( ldap_result2error( ld, res, 1 ) == LDAP_SIZELIMIT_EXCEEDED ) {
- fprintf( fp, "0A size limit was exceeded (explanation)\t~\t%s\t%d\r\n",
- myhost, myport );
- }
-}
-
-static int
-entry2textwrite( void *fp, char *buf, ber_len_t len )
-{
- return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
-}
-
-static void
-do_read( LDAP *ld, FILE *fp, char *dn )
-{
- static struct ldap_disptmpl *tmpllist;
-
- ldap_init_templates( templatefile, &tmpllist );
-
- if ( ldap_entry2text_search( ld, dn, base, NULL, tmpllist, NULL, NULL,
- entry2textwrite, (void *) fp, "\r\n", rdncount,
- LDAP_DISP_OPT_DOSEARCHACTIONS ) != LDAP_SUCCESS ) {
- ldap_perror( ld, "ldap_entry2text_search" );
- exit( EXIT_FAILURE );
- }
-
- if ( tmpllist != NULL ) {
- ldap_free_templates( tmpllist );
- }
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/*
- * Copyright (c) 1990 Regents of the University of Michigan.
- * 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 the University of Michigan at Ann Arbor. The name of the University
- * 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.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-
-#include <ac/ctype.h>
-#include <ac/signal.h>
-#include <ac/socket.h>
-#include <ac/string.h>
-#include <ac/syslog.h>
-#include <ac/time.h>
-#include <ac/unistd.h>
-#include <ac/wait.h>
-
-#include <ac/param.h>
-#include <ac/setproctitle.h>
-
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-
-#include <ldap.h>
-#include <disptmpl.h>
-
-#define ldap_debug debug
-#include "ldap_log.h"
-
-#include "lutil.h"
-
-
-#include "ldap_defaults.h"
-
-int debug;
-int ldap_syslog;
-int ldap_syslog_level;
-int dosyslog;
-int inetd;
-int dtblsize;
-
-char *ldaphost = NULL;
-int ldapport = 0;
-int searchaliases = 1;
-char *helpfile = GO500GW_HELPFILE;
-char *filterfile = FILTERFILE;
-char *templatefile = TEMPLATEFILE;
-char *friendlyfile = FRIENDLYFILE;
-int rdncount = GO500GW_RDNCOUNT;
-
-static void usage ( char *name ) LDAP_GCCATTR((noreturn));
-static int set_socket (int port);
-static RETSIGTYPE wait4child(int sig);
-static void do_queries (int s) LDAP_GCCATTR((noreturn));
-static char *pick_oc ( char **oclist );
-static int isnonleaf ( LDAP *ld, char **oclist, char *dn );
-static void do_menu (LDAP *ld, FILE *fp, char *dn);
-static void do_list (LDAP *ld, FILE *fp, char *dn);
-static int isoc ( char **ocl, char *oc );
-static int make_scope ( LDAP *ld, char *dn );
-static void do_search (LDAP *ld, FILE *fp, char *query);
-static int entry2textwrite( void *fp, char *buf, ber_len_t len );
-static void do_read (LDAP *ld, FILE *fp, char *dn);
-static void do_help (FILE *op);
-static void do_sizelimit(FILE *fp, char type);
-static void do_error (FILE *fp, char *s);
-
-char myhost[MAXHOSTNAMELEN];
-int myport = GO500GW_PORT;
-
-static void
-usage( char *name )
-{
- fprintf( stderr, "usage: %s [-d debuglevel] [-I] [-p port] [-P ldapport] [-l]\r\n\t[-x ldaphost] [-a] [-h helpfile] [-f filterfile] [-t templatefile] [-c rdncount]\r\n", name );
- exit( EXIT_FAILURE );
-}
-
-int
-main (int argc, char **argv )
-{
- int s, ns, rc;
- int port = -1;
- int i, pid;
- char *myname;
- fd_set readfds;
- struct hostent *hp;
- struct sockaddr_in from;
- socklen_t fromlen;
-
-#if defined( LDAP_PROCTITLE ) && !defined( HAVE_SETPROCTITLE )
- /* for setproctitle */
- Argv = argv;
- Argc = argc;
-#endif
-
- while ( (i = getopt( argc, argv, "P:ad:f:h:lp:t:x:Ic:" )) != EOF ) {
- switch( i ) {
- case 'a': /* search aliases */
- searchaliases = 0;
- break;
-
- case 'd': /* debugging level */
- debug |= atoi( optarg );
- break;
-
- case 'f': /* ldap filter file */
- filterfile = strdup( optarg );
- break;
-
- case 'h': /* gopher help file */
- helpfile = strdup( optarg );
- break;
-
- case 'l': /* log to LOG_LOCAL3 */
- dosyslog = 1;
- break;
-
- case 'p': /* port to listen on */
- port = atoi( optarg );
- break;
-
- case 'P': /* port to connect to ldap server */
- ldapport = atoi( optarg );
- break;
-
- case 't': /* ldap template file */
- templatefile = strdup( optarg );
- break;
-
- case 'x': /* ldap server hostname */
- ldaphost = strdup( optarg );
- break;
-
- case 'I': /* run from inetd */
- inetd = 1;
- break;
-
- case 'c': /* count of DN components to show */
- rdncount = atoi( optarg );
- break;
-
- default:
- usage( argv[0] );
- }
- }
-
-#ifdef HAVE_SYSCONF
- dtblsize = sysconf( _SC_OPEN_MAX );
-#elif HAVE_GETDTABLESIZE
- dtblsize = getdtablesize();
-#else
- dtblsize = FD_SETSIZE;
-#endif
-
-#ifdef FD_SETSIZE
- if ( dtblsize > FD_SETSIZE ) {
- dtblsize = FD_SETSIZE;
- }
-#endif /* FD_SETSIZE*/
-
-
-
-#ifdef GO500GW_HOSTNAME
- strcpy( myhost, GO500GW_HOSTNAME );
-#else
- if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost)-1 )
- == -1 ) {
- perror( "gethostname" );
- exit( EXIT_FAILURE );
- }
- myhost[sizeof(myhost)-1] = '\0';
-#endif
-
- /* detach if stderr is redirected or no debugging */
- if ( inetd == 0 )
- lutil_detach( debug && !isatty( 1 ), 1 );
-
- if ( (myname = strrchr( argv[0], '/' )) == NULL )
- myname = strdup( argv[0] );
- else
- myname = strdup( myname + 1 );
-
- if ( debug ) {
- ber_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
- ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
- }
-
-#ifdef SIGPIPE
- (void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
-
- if ( dosyslog ) {
-#ifdef LOG_LOCAL3
- openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL3 );
-#elif LOG_DEBUG
- openlog( myname, OPENLOG_OPTIONS );
-#endif
- }
- if ( dosyslog )
- syslog( LOG_INFO, "initializing" );
-
- /* set up the socket to listen on */
- if ( inetd == 0 ) {
- s = set_socket( port );
-
- /* arrange to reap children */
- (void) SIGNAL( SIGCHLD, wait4child );
- }
-
- if ( inetd ) {
- fromlen = sizeof(from);
- if ( getpeername( 0, (struct sockaddr *) &from, &fromlen )
- == 0 ) {
- hp = gethostbyaddr( (char *) &(from.sin_addr),
- sizeof(from.sin_addr), AF_INET );
- Debug( LDAP_DEBUG_ARGS, "connection from %s (%s)\n",
- (hp == NULL) ? "unknown" : hp->h_name,
- inet_ntoa( from.sin_addr ), 0 );
-
- if ( dosyslog ) {
- syslog( LOG_INFO, "connection from %s (%s)",
- (hp == NULL) ? "unknown" : hp->h_name,
- inet_ntoa( from.sin_addr ) );
- }
-
-#ifdef LDAP_PROCTITLE
- setproctitle( "%s", hp == NULL ? inet_ntoa( from.sin_addr ) :
- hp->h_name );
-#endif
- }
-
- do_queries( 0 );
-
- tcp_close( 0 );
-
- exit( EXIT_SUCCESS );
- }
-
- for ( ;; ) {
- FD_ZERO( &readfds );
- FD_SET( s, &readfds );
-
- if ( (rc = select( dtblsize, &readfds, 0, 0 ,0 )) == -1 ) {
- if ( debug ) perror( "select" );
- continue;
- } else if ( rc == 0 ) {
- continue;
- }
-
- if ( ! FD_ISSET( s, &readfds ) )
- continue;
-
- fromlen = sizeof(from);
- if ( (ns = accept( s, (struct sockaddr *) &from, &fromlen ))
- == -1 ) {
- if ( debug ) perror( "accept" );
- exit( EXIT_FAILURE );
- }
-
- hp = gethostbyaddr( (char *) &(from.sin_addr),
- sizeof(from.sin_addr), AF_INET );
-
- if ( dosyslog ) {
- syslog( LOG_INFO, "TCP connection from %s (%s)",
- (hp == NULL) ? "unknown" : hp->h_name,
- inet_ntoa( from.sin_addr ) );
- }
-
- switch( pid = fork() ) {
- case 0: /* child */
- tcp_close( s );
- do_queries( ns );
- break;
-
- case -1: /* failed */
- perror( "fork" );
- break;
-
- default: /* parent */
- tcp_close( ns );
- if ( debug )
- fprintf( stderr, "forked child %d\n", pid );
- break;
- }
- }
- /* NOT REACHED */
-}
-
-static int
-set_socket( int port )
-{
- int s, one;
- struct sockaddr_in addr;
-
- if ( port == -1 )
- port = GO500GW_PORT;
- myport = port;
-
- if ( (s = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
- perror( "socket" );
- exit( EXIT_FAILURE );
- }
-
-#ifdef SO_REUSEADDR
- /* set option so clients can't keep us from coming back up */
- one = 1;
- if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
- sizeof(one) ) < 0 ) {
- perror( "setsockopt" );
- exit( EXIT_FAILURE );
- }
-#endif
-#ifdef SO_KEEPALIVE
- /* enable keep alives */
- one = 1;
- if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
- sizeof(one) ) < 0 ) {
- perror( "setsockopt" );
- exit( EXIT_FAILURE );
- }
-#endif
-
- /* bind to a name */
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons( port );
- if ( bind( s, (struct sockaddr *) &addr, sizeof(addr) ) ) {
- perror( "bind" );
- exit( EXIT_FAILURE );
- }
-
- /* listen for connections */
- if ( listen( s, 5 ) == -1 ) {
- perror( "listen" );
- exit( EXIT_FAILURE );
- }
-
- if ( debug )
- printf( "go500gw listening on port %d\n", port );
-
- return( s );
-}
-
-static RETSIGTYPE
-wait4child( int sig )
-{
-#ifndef HAVE_WAITPID
- WAITSTATUSTYPE status;
-#endif
-
- if ( debug ) printf( "parent: catching child status\n" );
-
-#ifdef HAVE_WAITPID
- while (waitpid ((pid_t) -1, (int *) NULL, WAIT_FLAGS) > 0)
- ; /* NULL */
-#else
- while (wait4( (pid_t) -1, &status, WAIT_FLAGS, 0 ) > 0 )
- ; /* NULL */
-#endif
-
- (void) SIGNAL_REINSTALL ( SIGCHLD, wait4child );
-}
-
-static void
-do_queries( int s )
-{
- char buf[1024], *query;
- int len;
- FILE *fp;
- int rc;
- int deref;
- struct timeval timeout;
- fd_set readfds;
- LDAP *ld;
-
- if ( (fp = fdopen( s, "a+")) == NULL ) {
- perror( "fdopen" );
- exit( EXIT_FAILURE );
- }
-
- timeout.tv_sec = GO500GW_TIMEOUT;
- timeout.tv_usec = 0;
- FD_ZERO( &readfds );
- FD_SET( fileno( fp ), &readfds );
-
- if ( (rc = select( dtblsize, &readfds, 0, 0, &timeout )) <= 0 )
- exit( EXIT_FAILURE );
-
- if ( fgets( buf, sizeof(buf), fp ) == NULL )
- exit( EXIT_FAILURE );
-
- len = strlen( buf );
- if ( debug ) {
- fprintf( stderr, "got %d bytes\n", len );
-#ifdef LDAP_DEBUG
- ber_bprint( buf, len );
-#endif
- }
-
- /* strip of \r \n */
- if ( buf[len - 1] == '\n' )
- buf[len - 1] = '\0';
- len--;
- if ( buf[len - 1] == '\r' )
- buf[len - 1] = '\0';
- len--;
-
- query = buf;
-
- /* strip off leading white space */
- while ( isspace( (unsigned char) *query )) {
- ++query;
- --len;
- }
-
- rewind(fp);
-
- if ( *query == 'H' || *query == 'L' || *query == 'E' ) {
- switch ( *query++ ) {
- case 'H': /* help file */
- do_help( fp );
- break;
-
- case 'L': /* size limit explanation */
- do_sizelimit( fp, *query );
- break;
-
- case 'E': /* error explanation */
- do_error( fp, query );
- break;
- }
-
- fprintf( fp, ".\r\n" );
- rewind(fp);
-
- exit( EXIT_SUCCESS );
- /* NOT REACHED */
- }
-
- if ( (ld = ldap_init( ldaphost, ldapport )) == NULL ) {
- if ( debug ) perror( "ldap_init" );
- fprintf(fp, "0An error occurred (explanation)\tE%d\t%s\t%d\r\n",
- LDAP_SERVER_DOWN, myhost, myport );
- fprintf( fp, ".\r\n" );
- rewind(fp);
- exit( EXIT_FAILURE );
- }
-
- deref = LDAP_DEREF_ALWAYS;
- if ( !searchaliases )
- deref = LDAP_DEREF_FINDING;
-
- ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
-
- if ( (rc = ldap_simple_bind_s( ld, NULL, NULL ))
- != LDAP_SUCCESS ) {
- if ( debug ) ldap_perror( ld, "ldap_simple_bind_s" );
- fprintf(fp, "0An error occurred (explanation)\tE%d\t%s\t%d\r\n",
- rc, myhost, myport );
- fprintf( fp, ".\r\n" );
- rewind(fp);
- exit( EXIT_FAILURE );
- }
-
- switch ( *query++ ) {
- case 'R': /* read an entry */
- do_read( ld, fp, query );
- break;
-
- case 'S': /* search */
- do_search( ld, fp, query );
- break;
-
- case 'M': /* X.500 menu */
- do_menu( ld, fp, query );
- break;
-
- default:
- do_menu( ld, fp, "" );
- break;
- }
-
- fprintf( fp, ".\r\n" );
- rewind(fp);
-
- exit( EXIT_SUCCESS );
- /* NOT REACHED */
-}
-
-static char *
-pick_oc( char **oclist )
-{
- int i;
-
- if ( oclist == NULL )
- return( "unknown" );
-
- for ( i = 0; oclist[i] != NULL; i++ ) {
- if ( strcasecmp( oclist[i], "top" ) != 0 &&
- strcasecmp( oclist[i], "quipuObject" ) != 0 &&
- strcasecmp( oclist[i], "quipuNonLeafObject" ) != 0 )
- return( oclist[i] );
- }
-
- return( "unknown" );
-}
-
-static int
-isnonleaf( LDAP *ld, char **oclist, char *dn )
-{
- int i, quipuobject = 0;
-
- if ( oclist == NULL )
- return( 0 );
-
- for ( i = 0; oclist[i] != NULL; i++ ) {
- if ( strcasecmp( oclist[i], "quipuObject" ) == 0 )
- quipuobject = 1;
- if ( strcasecmp( oclist[i], "quipuNonLeafObject" ) == 0 ||
- strcasecmp( oclist[i], "externalNonLeafObject" ) == 0 )
- return( 1 );
- }
-
- /*
- * not a quipu thang - no easy way to tell leaves from nonleaves
- * except by trying to search or list. ldap only lets us search.
- */
-
- /* expensive - just guess for now */
- return( quipuobject ? 0 : 1 );
-
-#ifdef notdef
- if ( !quipuobject ) {
- int rc, numentries;
- struct timeval timeout;
- LDAPMessage *res = NULL;
- static char *attrs[] = { "objectClass", 0 };
- int sizelimit = 1;
-
- timeout.tv_sec = GO500GW_TIMEOUT;
- timeout.tv_usec = 0;
- ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
- if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_ONELEVEL,
- NULL, attrs, 0, &timeout, &res ))
- == LDAP_SUCCESS || rc == LDAP_SIZELIMIT_EXCEEDED ) {
- sizelimit = LDAP_NO_LIMIT;
- ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
-
- numentries = ldap_count_entries( ld, res );
- if ( res != NULL )
- ldap_msgfree( res );
- return( numentries == 1 ? 1 : 0 );
- }
- }
-
- return( 0 );
-#endif
-}
-
-static void
-do_menu( LDAP *ld, FILE *fp, char *dn )
-{
- char **s;
- char *rdn = NULL;
- LDAPFriendlyMap *fm = NULL;
-
- if ( strcmp( dn, "" ) != 0 ) {
- s = ldap_explode_dn( dn, 1 );
-
- if ( s[1] == NULL )
- rdn = ldap_friendly_name( friendlyfile, s[0], &fm );
- else
- rdn = s[0];
- fprintf( fp, "0Read %s entry\tR%s\t%s\t%d\r\n", rdn ? rdn: s[0],
- dn, myhost, myport );
-
- ldap_value_free( s );
- } else {
- fprintf( fp, "0About the Gopher to X.500 Gateway\tH\t%s\t%d\r\n",
- myhost, myport );
- }
-
- fprintf( fp, "7Search %s\tS%s\t%s\t%d\r\n", rdn ? rdn : "root", dn,
- myhost, myport );
-
- do_list( ld, fp, dn );
-
- ldap_free_friendlymap( &fm );
-}
-
-static void
-do_list( LDAP *ld, FILE *fp, char *dn )
-{
- int rc;
- LDAPMessage *e, *res;
- struct timeval timeout;
- LDAPFriendlyMap *fm = NULL;
- static char *attrs[] = { "objectClass", 0 };
- int deref = LDAP_DEREF_FINDING;
-
- timeout.tv_sec = GO500GW_TIMEOUT;
- timeout.tv_usec = 0;
-
- ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
-
- if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_ONELEVEL,
- "(!(objectClass=dSA))", attrs, 0, &timeout, &res )) != LDAP_SUCCESS
- && rc != LDAP_SIZELIMIT_EXCEEDED ) {
- fprintf(fp, "0An error occurred (explanation)\tE%d\t%s\t%d\r\n",
- rc, myhost, myport );
- return;
- }
-
- deref = LDAP_DEREF_ALWAYS;
- ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
-
- if ( ldap_count_entries( ld, res ) < 1 ) {
- return;
- }
-
-#ifdef GO500GW_SORT_ATTR
- ldap_sort_entries( ld, &res, GO500GW_SORT_ATTR, strcasecmp );
-#endif
-
- fm = NULL;
- for ( e = ldap_first_entry( ld, res ); e != NULL;
- e = ldap_next_entry( ld, e ) ) {
- char **s, **oc;
- char *rdn, *doc;
-
- dn = ldap_get_dn( ld, e );
- s = ldap_explode_dn( dn, 1 );
- oc = ldap_get_values( ld, e, "objectClass" );
-
- doc = pick_oc( oc );
- if ( strcasecmp( doc, "country" ) == 0 ) {
- rdn = ldap_friendly_name( friendlyfile, s[0], &fm );
- } else {
- rdn = s[0];
- }
- if ( rdn == NULL ) {
- rdn = s[0];
- }
-
- if ( strncasecmp( rdn, "{ASN}", 5 ) != 0 ) {
- if ( isnonleaf( ld, oc, dn ) ) {
- fprintf( fp, "1%s (%s)\tM%s\t%s\t%d\r\n", rdn,
- doc, dn, myhost, myport );
- } else {
- fprintf( fp, "0%s (%s)\tR%s\t%s\t%d\r\n", rdn,
- doc, dn, myhost, myport );
- }
- }
-
- free( dn );
- ldap_value_free( s );
- ldap_value_free( oc );
- }
- ldap_free_friendlymap( &fm );
-
- if ( ldap_result2error( ld, res, 1 ) == LDAP_SIZELIMIT_EXCEEDED ) {
- fprintf( fp, "0A size limit was exceeded (explanation)\tLL\t%s\t%d\r\n",
- myhost, myport );
- }
-}
-
-static int
-isoc( char **ocl, char *oc )
-{
- int i;
-
- for ( i = 0; ocl[i] != NULL; i++ ) {
- if ( strcasecmp( ocl[i], oc ) == 0 )
- return( 1 );
- }
-
- return( 0 );
-}
-
-static int
-make_scope( LDAP *ld, char *dn )
-{
- int scope;
- char **oc;
- LDAPMessage *res;
- struct timeval timeout;
- static char *attrs[] = { "objectClass", 0 };
-
- if ( strcmp( dn, "" ) == 0 )
- return( LDAP_SCOPE_ONELEVEL );
-
- timeout.tv_sec = GO500GW_TIMEOUT;
- timeout.tv_usec = 0;
- if ( ldap_search_st( ld, dn, LDAP_SCOPE_BASE, NULL,
- attrs, 0, &timeout, &res ) != LDAP_SUCCESS ) {
- return( -1 );
- }
-
- oc = ldap_get_values( ld, ldap_first_entry( ld, res ), "objectClass" );
-
- if ( isoc( oc, "organization" ) || isoc( oc, "organizationalUnit" ) )
- scope = LDAP_SCOPE_SUBTREE;
- else
- scope = LDAP_SCOPE_ONELEVEL;
-
- ldap_value_free( oc );
- ldap_msgfree( res );
-
- return( scope );
-}
-
-static void
-do_search( LDAP *ld, FILE *fp, char *query )
-{
- int deref;
- int scope;
- char *base, *filter;
- char *filtertype;
- int count, rc;
- struct timeval timeout;
- LDAPFiltInfo *fi;
- LDAPMessage *e, *res;
- LDAPFiltDesc *filtd;
- static char *attrs[] = { "objectClass", 0 };
-
- if ( (filter = strchr( query, '\t' )) == NULL ) {
- fprintf( fp, "3Missing filter!\r\n" );
- exit( EXIT_FAILURE );
- }
- *filter++ = '\0';
- base = query;
-
- if ( (scope = make_scope( ld, base )) == -1 ) {
- fprintf( fp, "3Bad scope\r\n" );
- exit( EXIT_FAILURE );
- }
-
- filtertype = (scope == LDAP_SCOPE_ONELEVEL ?
- "go500gw onelevel" : "go500gw subtree");
- deref = (scope == LDAP_SCOPE_ONELEVEL ?
- LDAP_DEREF_FINDING : LDAP_DEREF_ALWAYS);
- ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
- timeout.tv_sec = GO500GW_TIMEOUT;
- timeout.tv_usec = 0;
-
- if ( (filtd = ldap_init_getfilter( filterfile )) == NULL ) {
- fprintf( stderr, "Cannot open filter file (%s)\n",
- filterfile );
- exit( EXIT_FAILURE );
- }
-
- count = 0;
- res = NULL;
- for ( fi = ldap_getfirstfilter( filtd, filtertype, filter );
- fi != NULL; fi = ldap_getnextfilter( filtd ) )
- {
- if ( (rc = ldap_search_st( ld, base, scope,
- fi->lfi_filter, attrs, 0, &timeout, &res ))
- != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
- fprintf(fp, "0An error occurred (explanation)\tE%d\t%s\t%d\r\n",
- rc, myhost, myport );
- return;
- }
- if ( (count = ldap_count_entries( ld, res )) != 0 )
- break;
- }
- deref = LDAP_DEREF_ALWAYS;
- ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
- ldap_getfilter_free( filtd );
-
- if ( count == 0 ) {
- return;
- }
-
- if ( count == 1 ) {
- char *dn, **oc;
-
- e = ldap_first_entry( ld, res );
- oc = ldap_get_values( ld, e, "objectClass" );
- dn = ldap_get_dn( ld, e );
-
- if ( isnonleaf( ld, oc, dn ) ) {
- do_menu( ld, fp, dn );
-
- free( dn );
- return;
- }
-
- free( dn );
- ldap_value_free( oc );
- }
-
-#ifdef GO500GW_SORT_ATTR
- ldap_sort_entries( ld, &res, GO500GW_SORT_ATTR, strcasecmp );
-#endif
-
- for ( e = ldap_first_entry( ld, res ); e != NULL;
- e = ldap_next_entry( ld, e ) ) {
- char **s, **oc;
- char *dn;
-
- dn = ldap_get_dn( ld, e );
- s = ldap_explode_dn( dn, 1 );
- oc = ldap_get_values( ld, e, "objectClass" );
-
- if ( isnonleaf( ld, oc, dn ) )
- fprintf( fp, "1%s (%s)\tM%s\t%s\t%d\r\n", s[0],
- pick_oc( oc ), dn, myhost, myport );
- else
- fprintf( fp, "0%s (%s)\tR%s\t%s\t%d\r\n", s[0],
- pick_oc( oc ), dn, myhost, myport );
-
- free( dn );
- ldap_value_free( s );
- ldap_value_free( oc );
- }
-
- if ( ldap_result2error( ld, res, 1 ) == LDAP_SIZELIMIT_EXCEEDED ) {
- fprintf( fp, "0A size limit was exceeded (explanation)\tLS\t%s\t%d\r\n",
- myhost, myport );
- }
-}
-
-
-static int
-entry2textwrite( void *fp, char *buf, ber_len_t len )
-{
- return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
-}
-
-static void
-do_read( LDAP *ld, FILE *fp, char *dn )
-{
- static struct ldap_disptmpl *tmpllist;
-
- ldap_init_templates( templatefile, &tmpllist );
-
- if ( ldap_entry2text_search( ld, dn, NULL, NULL, tmpllist, NULL, NULL,
- entry2textwrite,(void *) fp, "\r\n", rdncount, 0 )
- != LDAP_SUCCESS ) {
- int ld_errno = 0;
- ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
-
- fprintf(fp,
- "0An error occurred (explanation)\t@%s\t%s\t%d\r\n",
- ldap_err2string( ld_errno ), myhost, myport );
- }
-
- if ( tmpllist != NULL ) {
- ldap_free_templates( tmpllist );
- }
-}
-
-static void
-do_help( FILE *op )
-{
- FILE *fp;
- char line[BUFSIZ];
-
- if ( (fp = fopen( helpfile, "r" )) == NULL ) {
- fprintf( op, "Cannot access helpfile (%s)\r\n", helpfile );
- return;
- }
-
- while ( fgets( line, sizeof(line), fp ) != NULL ) {
- line[ strlen( line ) - 1 ] = '\0';
-
- fprintf( op, "%s\r\n", line );
- }
-
- fclose( fp );
-}
-
-static void
-do_sizelimit( FILE *fp, char type )
-{
- if ( type == 'S' ) {
- fprintf( fp, "The query you specified was not specific enough, causing a size limit\r\n" );
- fprintf( fp, "to be exceeded and the first several matches found to be returned.\r\n" );
- fprintf( fp, "If you did not find the match you were looking for, try issuing a more\r\n" );
- fprintf( fp, "specific query, for example one that contains both first and last name.\r\n" );
- } else {
- fprintf( fp, "Not all entries could be returned because a size limit was exceeded.\r\n" );
- fprintf( fp, "There is no way to defeat this feature, but if you know who you are\r\n" );
- fprintf( fp, "looking for, try choosing the \"Search\" option listed above and\r\n" );
- fprintf( fp, "specifying the name of the person you want.\r\n" );
- }
- fprintf( fp, ".\r\n" );
-}
-
-static void
-do_error( FILE *fp, char *s )
-{
- int code;
-
- code = atoi( s );
-
- fprintf( fp, "An error occurred searching X.500. The error code was %d\r\n", code );
- fprintf( fp, "The corresponding error is: %s\r\n", ldap_err2string( code ) );
- fprintf( fp, "No additional information is available\r\n" );
- fprintf( fp, ".\r\n" );
-}
+++ /dev/null
-This is a second pass at a general Gopher to X.500 gateway. It is
-somewhat tailored to white pages usage, but is pretty general.
-
-There are two modes of operation that the gateway supports: browsing
-and searching. To browse, simply choose one of the countries,
-organizations, etc. that appear in gopher as menu items. The next
-level of the X.500 DIT will then be displayed. To search, choose the
-search item (second choice in all menus) and type the name of whatever
-it is you're looking for. At the upper levels of the tree (i.e. root
-or country level) searches are assumed to be for organizations or
-localities and are one-level in scope. At the lower levels of the tree
-(i.e. organization or organizationalunit level) searches are assumed to
-be for people and are subtree in scope. What sort of search is done
-depends on what you type, but a variety of things are tried.
-
-We would appreciate any feedback you can provide. If you have
-problems, report them using our Issue Tracking System:
- http://www.OpenLDAP.com/its/
-or by sending e-mail to:
- OpenLDAP-its@OpenLDAP.org
-Additional mailing lists are available. Please see:
- http://www.OpenLDAP.com/lists/
+++ /dev/null
-# $OpenLDAP$
-
-UNIX_PRGS = rcpt500
-PROGRAMS = $(@PLAT@_PRGS)
-
-SRCS= main.c cmds.c help.c query.c
-XSRCS= version.c
-OBJS= main.o cmds.o help.o query.o
-HDRS= rcpt500.h
-
-LDAP_INCDIR= ../../include
-LDAP_LIBDIR= ../../libraries
-
-XLIBS = -lldap -llber -llutil
-XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
-
-rcpt500 : version.o
- $(LTLINK) -o $@ version.o $(OBJS) $(LIBS)
-
-version.c: ${OBJS} $(LDAP_LIBDEPEND)
- @-$(RM) $@
- $(MKVERSION) rcpt500 > $@
-
-install-local: $(PROGRAMS) rcpt500.help FORCE
- -$(MKDIR) $(DESTDIR)$(libexecdir) $(DESTDIR)$(datadir)
- @( \
- for prg in $(PROGRAMS); do \
- $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \
- $(DESTDIR)$(libexecdir); \
- done \
- )
- -$(MV) $(DESTDIR)$(datadir)/rcpt500.help $(DESTDIR)$(datadir)/rcpt500.help-
- $(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/rcpt500.help $(DESTDIR)$(datadir)
-
+++ /dev/null
-OpenLDAP rcpt500 mail query server README
-
-OVERVIEW
-
-This is a mail-query server that answers LDAP white pages queries.
-It is designed to be run out of your mail systems alias file, or the
-equivalent. It expects to be fed the entire contents (including
-headers) of an RFC822 message via standard input. It parses the
-message, looking in the Subject: field or the body of the message
-for a command that it recognizes.
-
-The commands currently recognized are listed in the file cmd.c. They
-all map into two actual operations the server performs: an X.500 query
-or a help command. If no recognizable command is found in the
-Subject: or body of the message, help is assumed. An appropriate
-reply is sent to the sender of the message in response to the command.
-
-The help command returns the contents of the file rcpt500.help. You
-can modify the contents as appropriate for your local site.
-
-The query command performs a series of LDAP searches to try to find
-a person that matches the object of the query. If more than one
-X.500 entry matches, a list is returned. If exactly one is matched,
-detailed information is returned. Here is an example message and rcpt500
-generated reply:
-
-Query message:
- Mail ldap-query@example.com
- Subject: find tim howes
- .
-
-Reply from rcpt500:
- Message-Id: <199209161526.AA12041@example.com>
- Date: Wed, 16 Sep 1992 11:26:17 -0400
- From: "LDAP Query Program" <ldap-query@example.com>
- Subject: Re: find tim howes
- In-Reply-To: Your message of "Wed, 16 Sep 1992 11:26:12 -0400"
- <199209161526.AA26144@terminator.cc.example.com>
- To: "Mark Smith" <mcs@terminator.cc.example.com>
-
- One exact match was found for 'tim howes':
- "Timothy A Howes, Information Technology Division, Faculty and Staff"
- Also known as:
- Timothy Howes
- Timothy A Howes 1
- Timothy A Howes
- Tim Howes
- E-mail address:
- tim@terminator.cc.umich.edu
- Fax number:
- +1 313 764 5140 (argus building)
- Business phone:
- +1 313 747-4454
- Business address:
- ITD Research Systems
- 535 W William St.
- Ann Arbor, MI 48103-4943
- Title:
- Systems Research Programmer II, Research Systems
- Uniqname:
- tim
-
-If you want to try out rcpt500 yourself before installing it at your site,
-send a message to ldap-query@umich.edu (we have a server running
-there that serves University of Michigan white pages information).
-
-
-CONFIGURING AND RUNNING rcpt500 AT YOUR LOCAL SITE
-You will probably need to make changes to the file ldapconfig.h.edit to
-configure rcpt500 for your local site. There are comments in the file
-describing each variable you might need to change. Then type make in
-the rcpt500 directory to make sure things are up to date. You will
-need to install the rcpt500 binary and help files (make install). This
-all assumes you have built the LDAP libraries already. If in doubt,
-just do a make from the top of the LDAP distribution.
-
-You will then need to set up an alias that your users can send mail
-to that will feed the messages to rcpt500. At our site, we run sendmail
-so the alias is in /usr/lib/aliases and looks like:
-
- ldap-query: "|/usr/local/etc/rcpt500 -l"
-
-The available command line options for rcpt500 are:
- -l enable logging of requests via the syslog
- LOG_DAEMON facility
- -h ldaphost specify LDAP server host to connect to
- -b searchbase specify starting point of LDAP searches
- -a don't deference aliases during searches
- -s stripcount remove "stripcount" DN components from user
- friendly form names that are displayed
- -z sizelimit return at most "sizelimit" entries
- -u dapuser DN to bind to LDAP as when searching
-
-The search and display behavior is defined in the ldapfilter.conf and
-ldaptemplates.conf files.
-
-
-FEEDBACK / PROBLEM REPORTS / DISCUSSIONS
-
- The software is provided as is without any express or implied
- warranty, but you can report problems using our Issue Tracking
- System:
-
- http://www.OpenLDAP.com/its/
-
- or by sending e-mail to:
-
- OpenLDAP-its@OpenLDAP.org
-
- Mailing lists are available. Please see:
-
- http://www.OpenLDAP.com/lists/
+++ /dev/null
-/* $OpenLDAP$ */
-/*
- * cmds.c: command table for rcpt500 (X.500 email query responder)
- *
- * 18 June 1992 by Mark C Smith
- * Copyright (c) 1992 The Regents of The University of Michigan
- * All Rights Reserved
- */
-
-#include "portable.h"
-
-#include <ac/stdlib.h>
-#include "rcpt500.h"
-
-struct command rcpt_cmds[] = {
- "help", help_cmd, /* help must be the first command */
- "query for", query_cmd, /* must come before "query for" */
- "query", query_cmd,
- "find", query_cmd,
- "read", query_cmd,
- "search for", query_cmd, /* must come before "search" */
- "search", query_cmd,
- "lookup", query_cmd,
- "look up", query_cmd,
- "show", query_cmd,
- "finger", query_cmd,
- "whois", query_cmd,
- "who is", query_cmd,
- "locate", query_cmd,
- NULL, NULL /* end of command list */
-};
+++ /dev/null
-/* $OpenLDAP$ */
-/*
- * help.c: for rcpt500 (X.500 email query responder)
- *
- * 16 June 1992 by Mark C Smith
- * Copyright (c) 1992 The Regents of The University of Michigan
- * All Rights Reserved
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/syslog.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#include "ldap_defaults.h"
-#include "rcpt500.h"
-
-
-int
-help_cmd(struct msginfo *msgp, char *reply)
-{
- int fd, len;
-
- if (( fd = open( RCPT500_HELPFILE, O_RDONLY )) == -1 ) {
- if ( dosyslog ) {
- syslog( LOG_ERR, "open help file: %m" );
- }
- strcat( reply, "Unable to access the help file. Sorry!\n" );
- return( 0 );
- }
-
- len = read( fd, reply + strlen( reply ), MAXSIZE );
- close( fd );
-
- if ( len == -1 ) {
- if ( dosyslog ) {
- syslog( LOG_ERR, "read help file: %m" );
- }
- strcat( reply, "Unable to read the help file. Sorry!\n" );
- return( 0 );
- }
-
- *(reply + len ) = '\0';
- return( 0 );
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/*
- * main.c: for rcpt500 (X.500 email query responder)
- *
- * 16 June 1992 by Mark C Smith
- * Copyright (c) 1992 The Regents of The University of Michigan
- * All Rights Reserved
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdlib.h>
-
-#include <ac/ctype.h>
-#include <ac/signal.h>
-#include <ac/string.h>
-#include <ac/syslog.h>
-#include <ac/unistd.h>
-
-#include "ldap_defaults.h"
-#include "rcpt500.h"
-
-int dosyslog = 0;
-
-int derefaliases = 1;
-int sizelimit = RCPT500_SIZELIMIT;
-int rdncount = RCPT500_RDNCOUNT;
-int ldapport = 0;
-char *ldaphost = NULL;
-char *searchbase = NULL;
-char *dapuser = NULL;
-char *filterfile = FILTERFILE;
-char *templatefile = TEMPLATEFILE;
-static char reply[ MAXSIZE * RCPT500_LISTLIMIT ];
-
-
-/*
- * functions
- */
-static int read_msg(FILE *fp, struct msginfo *msgp);
-static char *read_hdr(FILE *fp, int off, char *buf, int MAXSIZEe, char **ln_p);
-static int send_reply(struct msginfo *msgp, char *body);
-static int find_command(char *text, char **argp);
-
-/*
- * main is invoked by sendmail via the alias file
- * the entire incoming message gets piped to our standard input
- */
-int
-main( int argc, char **argv )
-{
- char *prog, *usage = "%s [-l] [-U] [-h ldaphost] [-p ldapport] [-b searchbase] [-a] [-z sizelimit] [-u dapuser] [-f filterfile] [-t templatefile] [-c rdncount]\n";
- struct msginfo msg;
- int c, errflg;
-
- *reply = '\0';
-
- if (( prog = strrchr( argv[ 0 ], '/' )) == NULL ) {
- prog = strdup( argv[ 0 ] );
- } else {
- prog = strdup( prog + 1 );
- }
-
- errflg = 0;
- while (( c = getopt( argc, argv, "alh:b:s:z:f:t:p:c:" )) != EOF ) {
- switch( c ) {
- case 'a':
- derefaliases = 0;
- break;
- case 'l':
- dosyslog = 1;
- break;
- case 'b':
- searchbase = optarg;
- break;
- case 'h':
- ldaphost = optarg;
- break;
- case 'p':
- ldapport = atoi( optarg );
- break;
- case 'z':
- sizelimit = atoi( optarg );
- break;
- case 'u':
- dapuser = optarg;
- break;
- case 'f':
- filterfile = optarg;
- break;
- case 't':
- templatefile = optarg;
- break;
- case 'c':
- rdncount = atoi( optarg );
- break;
- default:
- ++errflg;
- }
- }
- if ( errflg || optind < argc ) {
- fprintf( stderr, usage, prog );
- exit( EXIT_FAILURE );
- }
-
-#ifdef SIGPIPE
- (void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
-
- if ( dosyslog ) {
- /*
- * if syslogging requested, initialize
- */
-#ifdef LOG_DAEMON
- openlog( prog, OPENLOG_OPTIONS, LOG_DAEMON );
-#elif LOG_DEBUG
- openlog( prog, OPENLOG_OPTIONS );
-#endif
- }
-
- if ( read_msg( stdin, &msg ) < 0 ) {
- if ( dosyslog ) {
- syslog( LOG_INFO, "unparseable message ignored" );
- }
- exit( 0 ); /* so as not to give sendmail an error */
- }
-
- if ( dosyslog ) {
- syslog( LOG_INFO, "processing command \"%s %s\" from %s",
- ( msg.msg_command < 0 ) ? "Unknown" :
- rcpt_cmds[ msg.msg_command ].cmd_text,
- ( msg.msg_arg == NULL ) ? "" : msg.msg_arg, msg.msg_replyto );
- }
-
- if ( msg.msg_command < 0 ) {
- msg.msg_command = 0; /* unknown command == help command */
- }
-
-/*
- sprintf( reply, "Your request was interpreted as: %s %s\n\n",
- rcpt_cmds[ msg.msg_command ].cmd_text, msg.msg_arg );
-*/
-
- (*rcpt_cmds[ msg.msg_command ].cmd_handler)( &msg, reply );
-
- if ( send_reply( &msg, reply ) < 0 ) {
- if ( dosyslog ) {
- syslog( LOG_INFO, "reply failed: %m" );
- }
- exit( 0 ); /* so as not to give sendmail an error */
- }
-
- if ( dosyslog ) {
- syslog( LOG_INFO, "reply OK" );
- }
-
- exit( 0 );
-}
-
-
-static int
-read_msg( FILE *fp, struct msginfo *msgp )
-{
- char buf[ MAXSIZE ], *line;
- int command = -1;
-
- msgp->msg_replyto = msgp->msg_date = msgp->msg_subject = NULL;
-
- line = NULL;
- while( 1 ) {
- if ( line == NULL ) {
- if (( line = fgets( buf, MAXSIZE, fp )) == NULL ) {
- break;
- }
- buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
- }
-
- if ( *buf == '\0' ) { /* start of message body */
- break;
- }
- if ( strncasecmp( buf, "Reply-To:", 9 ) == 0 ) {
- if ( msgp->msg_replyto != NULL ) {
- free( msgp->msg_replyto );
- }
- msgp->msg_replyto = read_hdr( fp, 9, buf, MAXSIZE, &line );
- } else if ( strncasecmp( buf, "From:", 5 ) == 0 &&
- msgp->msg_replyto == NULL ) {
- msgp->msg_replyto = read_hdr( fp, 5, buf, MAXSIZE, &line );
- } else if ( strncasecmp( buf, "Date:", 5 ) == 0 ) {
- msgp->msg_date = read_hdr( fp, 5, buf, MAXSIZE, &line );
- } else if ( strncasecmp( buf, "Message-ID:", 5 ) == 0 ) {
- msgp->msg_messageid = read_hdr( fp, 11, buf, MAXSIZE, &line );
- } else if ( strncasecmp( buf, "Subject:", 8 ) == 0 ) {
- if (( msgp->msg_subject =
- read_hdr( fp, 8, buf, MAXSIZE, &line )) != NULL ) {
- command = find_command( msgp->msg_subject, &msgp->msg_arg );
- }
- } else {
- line = NULL; /* discard current line */
- }
- }
-
- while ( command < 0 && line != NULL ) {
- /*
- * read the body of the message, looking for commands
- */
- if (( line = fgets( buf, MAXSIZE, fp )) != NULL ) {
- buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
- command = find_command( buf, &msgp->msg_arg );
- }
- }
-
- if ( msgp->msg_replyto == NULL ) {
- return( -1 );
- }
-
- msgp->msg_command = command;
- return( 0 );
-}
-
-
-static char *
-read_hdr( FILE *fp, int offset, char *buf, int MAXSIZEe, char **linep )
-{
- char *hdr;
-
- for ( hdr = buf + offset; isspace( (unsigned char) *hdr ); ++hdr ) {
- ;
- }
- if (( hdr = strdup( hdr )) == NULL ) {
- if ( dosyslog ) {
- syslog( LOG_ERR, "strdup: %m" );
- }
- exit( EXIT_FAILURE );
- }
-
- while ( 1 ) {
- *linep = fgets( buf, MAXSIZE, fp );
- buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
- if ( *linep == NULL || !isspace( (unsigned char) **linep )) {
- break;
- }
- if (( hdr = realloc( hdr, strlen( hdr ) +
- strlen( *linep ) + 3 )) == NULL) {
- if ( dosyslog ) {
- syslog( LOG_ERR, "realloc: %m" );
- }
- exit( EXIT_FAILURE );
- }
- strcat( hdr, "\n" );
- strcat( hdr, *linep );
- }
-
- return( hdr );
-}
-
-
-static int
-send_reply( struct msginfo *msgp, char *body )
-{
- char buf[ MAXSIZE ];
- FILE *cmdpipe;
- int rc;
-
- if (( cmdpipe = popen( RCPT500_PIPEMAILCMD, "w" )) == NULL ) {
- if ( dosyslog ) {
- syslog( LOG_ERR, "popen pipemailcmd failed: %m" );
- }
- return( -1 );
- }
-
- /*
- * send the headers
- */
-
- sprintf( buf, "From: %s\n", RCPT500_FROM );
- rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
-
- if ( rc == 1 ) {
- if ( msgp->msg_subject != NULL ) {
- sprintf( buf, "Subject: Re: %s\n", msgp->msg_subject );
- } else {
- sprintf( buf, "Subject: query response\n" );
- }
- rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
- }
-
- if ( rc == 1 && msgp->msg_date != NULL ) {
- /*
- * add "In-reply-to:" header
- */
- if ( msgp->msg_messageid == NULL ) {
- sprintf( buf, "In-reply-to: Your message of \"%s\"\n",
- msgp->msg_date );
- } else {
- sprintf( buf,
- "In-reply-to: Your message of \"%s\"\n %s\n",
- msgp->msg_date, msgp->msg_messageid );
- }
- rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
- }
-
- if ( rc == 1 ) {
- sprintf( buf, "To: %s\n", msgp->msg_replyto );
- rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
- }
-
- /*
- * send the header/body separator (blank line)
- */
- if ( rc == 1 ) {
- rc = fwrite( "\n", 1, 1, cmdpipe );
- }
-
- /*
- * send the body
- */
- if ( rc == 1 ) {
- rc = fwrite( body, strlen( body ), 1, cmdpipe );
- }
-
- if ( rc != 1 && dosyslog ) {
- syslog( LOG_ERR, "write to binmail failed: %m" );
- }
-
- if ( pclose( cmdpipe ) < 0 ) {
- if ( dosyslog ) {
- syslog( LOG_ERR, "pclose binmail failed: %m" );
- }
- return( -1 );
- }
-
- return( rc == 1 ? 0 : -1 );
-}
-
-
-static int
-find_command( char *text, char **argp )
-{
- int i;
- char *s, *p;
- static char argbuf[ MAXSIZE ];
-
- p = text;
- for ( s = argbuf; *p != '\0'; ++p ) {
- *s++ = TOLOWER( (unsigned char) *p );
- }
- *s = '\0';
-
- for ( i = 0; rcpt_cmds[ i ].cmd_text != NULL; ++i ) {
- if (( s = strstr( argbuf, rcpt_cmds[ i ].cmd_text )) != NULL
- && isspace( (unsigned char) s[ strlen( rcpt_cmds[ i ].cmd_text ) ] )) {
- strcpy( argbuf, text + (s - argbuf) + strlen( rcpt_cmds[ i ].cmd_text ));
- *argp = argbuf;
- while ( isspace( (unsigned char) **argp )) {
- ++(*argp);
- }
- return( i );
- }
- }
-
- return( -1 );
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/*
- * query.c: for rcpt500 (X.500 email query responder)
- *
- * 18 June 1992 by Mark C Smith
- * Copyright (c) 1992 The Regents of The University of Michigan
- * All Rights Reserved
- */
-
-#include "portable.h"
-
-#include <ac/stdlib.h>
-
-#include <ac/ctype.h>
-#include <ac/string.h>
-#include <ac/syslog.h>
-#include <ac/time.h>
-
-#include <stdio.h>
-
-#include <ldap.h>
-#include <disptmpl.h>
-
-#include "rcpt500.h"
-#include "ldap_defaults.h"
-
-static char buf[ MAXSIZE ];
-static char *errpreface = "Your query failed: ";
-
-static void close_ldap(LDAP *ld);
-static void append_entry_list(char *rep, char *qu, LDAP *ld, LDAPMessage *msg);
-static int append_text(void *reply, char *text, ber_len_t len);
-static int do_read (LDAP *ld, char *dn, char *rep, struct ldap_disptmpl *tmp);
-static void report_ldap_err (LDAP *ldp, char *reply);
-static void remove_trailing_space (char *s);
-
-
-int
-query_cmd( struct msginfo *msgp, char *reply )
-{
- LDAP *ldp;
- LDAPMessage *ldmsgp, *entry;
- char *dn;
- int matches, rc, ld_errno;
- LDAPFiltDesc *lfdp;
- LDAPFiltInfo *lfi;
- struct ldap_disptmpl *tmpllist = NULL;
- static char *attrs[] = { "cn", "title",
-#ifdef RCPT500_SORT_ATTR
- RCPT500_SORT_ATTR,
-#endif
- NULL };
-
- if ( msgp->msg_arg == NULL ) {
- return( help_cmd( msgp, reply ));
- }
-
- remove_trailing_space( msgp->msg_arg );
- if ( *msgp->msg_arg == '\0' ) {
- return( help_cmd( msgp, reply ));
- }
-
- if (( lfdp = ldap_init_getfilter( filterfile )) == NULL ) {
- strcat( reply, errpreface );
- strcat( reply, "filter file configuration error. Try again later." );
- return( 0 );
- }
-
- /*
- * open connection to LDAP server and bind as dapuser
- */
- ldp = ldap_init( ldaphost, ldapport );
-
- if ( ldp == NULL ) {
- strcat( reply, errpreface );
- strcat( reply, "X.500 service unavailable. Try again later." );
- ldap_getfilter_free( lfdp );
- return( 0 );
- }
-
- if ( ldap_simple_bind_s( ldp, dapuser, NULL ) != LDAP_SUCCESS ) {
- report_ldap_err( ldp, reply );
- close_ldap( ldp );
- ldap_getfilter_free( lfdp );
- return( 0 );
- }
-
- /*
- * set options for search and build filter
- */
- ldap_set_option(ldp, LDAP_OPT_DEREF, &derefaliases);
- ldap_set_option(ldp, LDAP_OPT_SIZELIMIT, &sizelimit);
-
- matches = 0;
-
- for ( lfi = ldap_getfirstfilter( lfdp, "rcpt500", msgp->msg_arg );
- lfi != NULL; lfi = ldap_getnextfilter( lfdp )) {
- rc = ldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
- lfi->lfi_filter, attrs, 0, &ldmsgp );
-
- if ( rc != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
- && rc != LDAP_TIMELIMIT_EXCEEDED ) {
- report_ldap_err( ldp, reply );
- close_ldap( ldp );
- ldap_getfilter_free( lfdp );
- return( 0 );
- }
-
- if (( matches = ldap_count_entries( ldp, ldmsgp )) != 0 ) {
- break;
- }
-
- if ( ldmsgp != NULL ) {
- ldap_msgfree( ldmsgp );
- }
- }
-
- if ( matches == 0 ) {
- sprintf( buf, "No matches were found for '%s'\n", msgp->msg_arg );
- strcat( reply, buf );
- close_ldap( ldp );
- ldap_getfilter_free( lfdp );
- return( 0 );
- }
-
- ld_errno = 0;
- ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
-
- if ( ld_errno == LDAP_TIMELIMIT_EXCEEDED
- || ld_errno == LDAP_SIZELIMIT_EXCEEDED ) {
- strcat( reply, "(Partial results only - a limit was exceeded)\n" );
- }
-
- if ( matches <= RCPT500_LISTLIMIT ) {
- sprintf( buf, "%d %s match%s found for '%s':\n\n", matches,
- lfi->lfi_desc,
- ( matches > 1 ) ? "es" : "", msgp->msg_arg );
- strcat( reply, buf );
-
- if (( rc = ldap_init_templates( templatefile, &tmpllist )) != 0 ) {
- sprintf( buf, "%s ldap_init_templates( %s ) failed (error %d)\n",
- errpreface, templatefile, rc );
- strcat( reply, buf );
- }
-
- for ( entry = ldap_first_entry( ldp, ldmsgp ); entry != NULL; ) {
- dn = ldap_get_dn( ldp, entry );
- if ( do_read( ldp, dn, reply, tmpllist ) != LDAP_SUCCESS ) {
- report_ldap_err( ldp, reply );
- }
- free( dn );
- if (( entry = ldap_next_entry( ldp, entry )) != NULL ) {
- strcat( reply, "\n-------\n\n" );
- }
- }
-
- if ( tmpllist != NULL ) {
- ldap_free_templates( tmpllist );
- }
- ldap_msgfree( ldmsgp );
-
- } else {
- sprintf( buf, "%d %s matches were found for '%s':\n",
- matches, lfi->lfi_desc, msgp->msg_arg );
- strcat( reply, buf );
- append_entry_list( reply, msgp->msg_arg, ldp, ldmsgp );
- ldap_msgfree( ldmsgp );
- }
-
- close_ldap( ldp );
- ldap_getfilter_free( lfdp );
- return( 0 );
-}
-
-
-static void
-close_ldap( LDAP *ld )
-{
- ldap_unbind( ld );
-}
-
-
-static void
-append_entry_list( char *reply, char *query, LDAP *ldp, LDAPMessage *ldmsgp )
-{
- LDAPMessage *e;
- char *dn, *rdn, *s, **title;
- int free_rdn = 0;
-
-#ifdef RCPT500_SORT_ATTR
- ldap_sort_entries( ldp, &ldmsgp, RCPT500_SORT_ATTR, strcasecmp );
-#endif
-
- for ( e = ldap_first_entry( ldp, ldmsgp ); e != NULL;
- e = ldap_next_entry( ldp, e )) {
- dn = ldap_get_dn( ldp, e );
- if (( s = strchr( dn, ',' )) != NULL ) {
- *s = '\0';
- }
- if (( s = strchr( dn, '=' )) == NULL ) {
- rdn = dn;
- } else {
- rdn = s + 1;
- }
-
-#ifdef UOFM
- /*
- * if this entry's rdn is an exact match for the thing looked up, we
- * return the CN that has a digit after it, so that the user is
- * returned something guaranteed to yield exactly one match if they
- * pick it from the list and query it
- */
-
- if ( strcasecmp( rdn, query ) == 0 ) {
- char **cn;
- int i;
-
- if (( cn = ldap_get_values( ldp, e, "cn" )) != NULL ) {
- for ( i = 0; cn[i] != NULL; i++ ) {
- if ( isdigit((unsigned char) cn[i][strlen( cn[i] ) - 1])) {
- rdn = strdup( cn[i] );
- free_rdn = 1;
- break;
- }
- }
- ldap_value_free( cn );
- }
- }
-#endif /* UOFM */
-
- title = ldap_get_values( ldp, e, "title" );
- sprintf( buf, " %-20s %s\n", rdn, title ? title[0] : "" );
- strcat( reply, buf );
- if ( title != NULL ) {
- ldap_value_free( title );
- }
- free( dn );
- if ( free_rdn ) {
- free( rdn );
- }
- }
-}
-
-
-static int
-append_text( void *reply, char *text, ber_len_t len )
-{
- strcat( (char *) reply, text );
- return( len );
-}
-
-
-static int
-do_read( LDAP *ldp, char *dn, char *reply, struct ldap_disptmpl *tmpll )
-{
- int rc;
- static char *maildefvals[] = { "None registered in this service", NULL };
- static char *defattrs[] = { "mail", NULL };
- static char **defvals[] = { maildefvals, NULL };
-
-
- rc = ldap_entry2text_search( ldp, dn, searchbase, NULL, tmpll,
- defattrs, defvals, append_text, (void *)reply, "\n",
- rdncount, LDAP_DISP_OPT_DOSEARCHACTIONS );
-
- return( rc );
-}
-
-
-static void
-report_ldap_err( LDAP *ldp, char *reply )
-{
- int ld_errno = 0;
- ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
-
- strcat( reply, errpreface );
- strcat( reply, ldap_err2string( ld_errno ));
- strcat( reply, "\n" );
-}
-
-
-static void
-remove_trailing_space( char *s )
-{
- char *p = s + strlen( s ) - 1;
-
- while ( isspace( (unsigned char) *p ) && p > s ) {
- --p;
- }
- *(++p) = '\0';
-}
+++ /dev/null
-/* $OpenLDAP$ */
-/*
- * rcpt500.h: includes for rcpt500 (X.500 email query responder)
- *
- * 16 June 1992 by Mark C Smith
- * Copyright (c) 1992 The Regents of The University of Michigan
- * All Rights Reserved
- */
-
-#include <ldap_cdefs.h>
-
-LDAP_BEGIN_DECL
-
-struct msginfo {
- char *msg_subject;
- char *msg_replyto; /* actually could be from From: line */
- char *msg_date;
- char *msg_messageid;
- int msg_command;
- char *msg_arg;
-};
-
-struct command {
- char *cmd_text; /* text for command, e.g. "HELP" */
- /* pointer to handler function */
- int (*cmd_handler) LDAP_P((struct msginfo *msgp, char *reply));
-};
-
-
-#define MAXSIZE 8096
-
-
-/*
- * functions
- */
-int help_cmd LDAP_P((struct msginfo *msgp, char *reply));
-int query_cmd LDAP_P((struct msginfo *msgp, char *reply));
-
-/*
- * externs
- */
-
-/* cmds.c */
-extern struct command rcpt_cmds[];
-/* main.c */
-extern int dosyslog;
-extern int derefaliases;
-extern int sizelimit;
-extern int rdncount;
-extern int ldapport;
-extern char *ldaphost;
-extern char *searchbase;
-extern char *dapuser;
-extern char *filterfile;
-extern char *templatefile;
-
-LDAP_END_DECL
+++ /dev/null
-How to use the OpenLDAP LDAP Email Query Service
-
-By sending electronic mail to the address:
-
- ldap-query@example.com
-
-you can access the campus LDAP Directory. The Directory contains
-information about all faculty, staff, and students of the University,
-including phone numbers, mailing addresses, job titles, email
-addresses, and more.
-
-To query the service, send a piece of email to this address with a
-command similar to:
-
- find <name>
-
- e.g. find robert jones
-
-somewhere in the Subject: field or anywhere in the body (text) of the
-message. You will receive a reply that contains information about the
-target of your query (in the above example, you would get information
-on all "robert jones" who are at the University). The <name> can be
-a person's full name, last name, or uniqname. An search for exact
-matches is first tried; if there are no exact matches, an approximate
-search (using soundex rules) is done.
-
-If your query matches exactly one person, you will receive detailed
-information about that person. If more than one is matched, a list will
-be returned that should hopefully provide you with enough information
-to be able to determine which individual you really want. Another
-query can then be made to obtain the detailed information.
-
-This service understands a number of synonyms for the "find" command,
-including: "whois", "search", "look up", "show." You can also send
-a message with the word "help" in it to get this text returned to you.
-
-Note that this service is entirely automated -- no humans will respond
-to requests or other email sent here.
-
-We would appreciate any feedback you can provide.
-If you have problems, report them using our Issue Tracking System:
- http://www.OpenLDAP.com/its/
-or by sending e-mail to:
- OpenLDAP-its@OpenLDAP.org
-Additional mailing lists are available. Please see:
- http://www.OpenLDAP.com/lists/
-
-This is the end of the help text.