Initial revision

This commit is contained in:
Kurt Zeilenga 1998-08-09 00:43:13 +00:00
commit 42e0d83cb3
644 changed files with 118767 additions and 0 deletions

90
ANNOUNCEMENT Normal file
View File

@ -0,0 +1,90 @@
A N N O U N C E M E N T
LDAP 3.3
The University of Michigan is pleased to announce release 3.3 of
UM-LDAP, an implementation of the Lightweight Directory Access
Protocol. LDAP is a draft Internet standard directory service
protocol that runs over TCP/IP. It can be used to provide a
stand-alone directory service, or to provide lightweight access to
the X.500 directory. LDAP is defined by RFC 1777 and RFC 1778.
This release includes the following components:
- slapd - a stand-alone LDAP directory server
- slurpd - a stand-alone LDAP replication server
- ldapd - an LDAP-to-X.500 gateway server
- centipede - an LDAP centroid generation and maintenance program
- libldap - an LDAP client library
- liblber - a lightweight BER/DER encoding/decoding library
- ldif tools - data conversion tools for use with slapd
- in.xfingerd - a finger-to-LDAP gateway server
- go500 - a gopher-to-LDAP gateway server for searching
- go500gw - a gopher-to-LDAP gateway server for searching and browsing
- rcpt500 - an email-to-LDAP query responder
- mail500 - an LDAP-capable mailer
- fax500 - an LDAP-capable mailer that supports remote printing
- LDAP tools - A collection of shell-based LDAP utility programs
In addition, there are some contributed components:
- web500 - an HTTP-to-LDAP gateway
- whois++d - a WHOIS++-to-LDAP gateway
- saucer - a simple command-line oriented client program
CHANGES
Changes since release 3.2 of LDAP include
- slurpd has been rewritten as a single process threaded daemon
- ldaptools (ldapsearch, etc) now support the LDIF format
- support for LDAP URLs added to libldap
- improved support for LDAP referrals in libldap
- preliminary test scripts included
- support for additional platforms
- various bug fixes and build fixes
See the CHANGES file in the distribution for more details.
AVAILABILITY
This software is freely available to anyone for any lawful purpose,
subject to the U-M copyright notice and disclaimer. The software is
available for anonymous ftp from the following location:
ftp://terminator.rs.itd.umich.edu/ldap/ldap-3.3.tar.Z
SUPPORT
The software is provided as is without any express or implied
warranty, but there is a bug reporting mail address which is
responded to on a best-effort basis:
ldap-support@umich.edu
In addition, there is a discussion list for issues relating to this
implementation of ldap:
ldap@umich.edu -- discussion list
ldap-request@umich.edu -- to join the list
Comments or questions about the LDAP protocol in general should be
sent to the IETF ASID discussion group:
ietf-asid@umich.edu -- discussion list
ietf-asid-request@umich.edu -- to join the list
An LDAP home page containing lots of interesting information and
online documentation is available at this URL:
http://www.umich.edu/~rsug/ldap/
SUPPORTED PLATFORMS
This release has been ported to many UNIX platforms, including
SunOS 4.1.x, Solaris 2.x, Ultrix 4.3, HP-UX 9.05, AIX 3.2.5,
SCO, FreeBSD, NetBSD, LINUX, IRIX, Digital Unix (OSF/1), and
NeXTSTEP 3.2. This release has also been ported to VMS.
The client libraries and some clients have also been ported to
MacOS 7.x, MSDOS (some TCP stacks), and MS Windows 3.1/95/NT.

545
CHANGES Normal file
View File

@ -0,0 +1,545 @@
Changes since 3.3b1
Various Make-template files - update by doing 'make depend'
include/disptmpl.h - add LDAP_DISP_OPT_HTMLBODYONLY option
libraries/liblber/io.c - under MacOS, limit tcpwrite() calls to a
maximum of 64K bytes; ber_flush() int/long fix
libraries/libldap/friendly.c - don't use errno on MacOS or DOS
libraries/libldap/regex.c - fix re_exec() to that ".*" matches ""
libraries/libldap/result.c - eliminate memory leak in wait4msg()
libraries/libldap/request.c - eliminate double-free impurity
libraries/libldap/tmplout.c - add LDAP_DISP_OPT_HTMLBODYONLY option
libraries/libldap/ufn.c - purify: avoid bad frees; plug memory leaks
libraries/libldif/line64.c - str_parse_line() now 0-terminates base64 vals.
libraries/macintosh/* - tcpwrite()/OpenTransport bug fixes
- better error checking for MacTCP driver opens
- don't use old routine names any more
libraries/msdos/winsock/* - various bugs fixes & improvements
servers/slapd/modify.c - fix bug causing unnormalized attr names
servers/slapd/monitor.c - return new "version" attribute
servers/slapd/regex.c - fix re_exec() to that ".*" matches ""
servers/slapd/tools/ldbmcat.c - make -n option work (don't open file "-n" )
servers/slapd/tools/ldif2id2entry.c - include ids in stored entries
servers/slapd/schema.c - log some information useful in tracking
down schema-check problems
servers/slapd/dn.c - dn_upcase() was not returning anything (doh!)
servers/slapd/backend.c - pass unbind request to all backends
servers/slapd/unbind.c - pass unbind request to all backends
servers/slapd/Version.c - remove leading spaces from Versionstr[]
servers/slapd/back-ldbm/unbind.c - make arguments consistent
servers/slapd/back-ldbm/bind.c - fix bug which allowed anyone to bind as
anyone else using kerberos, if there was
at least one krbName in an entry
servers/slurpd/replog.c - do all replog copying with buffered i/o
servers/slurpd/fm.c - fix inconsistency in arguments
servers/slurpd/main.c - fix inconsistency in arguments
clients/tools/ldapdelete.c - add -K flag - only does LDAP_AUTH_KRBV41
clients/tools/ldapmodify.c - add -K flag - only does LDAP_AUTH_KRBV41
clients/tools/ldapmodrdn.c - add -K flag - only does LDAP_AUTH_KRBV41
clients/tools/ldapsearch.c - add -K flag - only does LDAP_AUTH_KRBV41
doc/man/man1/ldapdelete.1 - add -K flag - only does LDAP_AUTH_KRBV41
doc/man/man1/ldapmodify.1 - add -K flag - only does LDAP_AUTH_KRBV41
doc/man/man1/ldapmodrdn.1 - add -K flag - only does LDAP_AUTH_KRBV41
doc/man/man1/ldapsearch.1 - add -K flag - only does LDAP_AUTH_KRBV41
doc/man/man3/ldap_entry2text.3 - document LDAP_DISP_OPT_HTMLBODYONLY option
doc/man/man8/slapd.8 - add BUGS section and document modrdn bug
----------------------------------------------------------------------------
Changes since 3.2
Makefile - added support for IRIX (SGI)
- make depend improvements
tests/ - all new test scripts -- make test
include/lber.h - use short include file names #ifdef WINSOCK
include/ldap.h - change LDAPCache struct definition to reduce
cache overhead
- use short include file names #ifdef WINSOCK
- LDAP URL support
- add lr_conn to LDAPRequest (needed by abandon)
- add LDAP_OPT_RESTART for select() restart
- revised Debug() macro #ifdef WINSOCK
include/ldbm.h - under NDBM, use O_RDWR instead of O_CREAT
- in LDBM_WRCREAT and LDBM_NEWDB
include/proto-lber.h - changes for WIN32
include/proto-ldap.h - changes for WIN32
- added LDAP URL routines
include/disptmpl.h - changes for WIN32
include/ldif.h - includes for new libldif library
include/srchpref.h - changes for WIN32
libraries/liblber/decode.c - vararg changes for WIN32
libraries/liblber/encode.c - vararg changes for WIN32
libraries/libldap/abandon.c - make ldap_abandon() work with referrals
libraries/libldap/bind.c - added new ldap_set_rebind_proc() routine
libraries/libldap/cache.c - reduce cache overhead
- fix small cache size infinite loop bug
- clarify debugging messages
libraries/libldap/charset.c - new routines: ldap_translate_from_t61,
ldap_translate_to_t61,
ldap_enable_translation
libraries/libldap/cldap.c - changes to support referral re-bind w/auth
libraries/libldap/getfilter.c - ldap_build_filter: don't use NULL value
libraries/libldap/kbind.c - changes to support referral re-bind w/auth
libraries/libldap/ldap-int.h - changes to support referral re-bind w/auth
- rename do_select() to do_ldap_select()
libraries/libldap/open.c - changes to support referral re-bind w/auth
- ld_options = LDAP_OPT_REFERRALS by default
libraries/libldap/os-ip.c - include <sys/time.h> to fix HP/UX gcc builds
- rename do_select() to do_ldap_select()
libraries/libldap/result.c - wait4msg debugging now shows timeout values
- changes to support referral re-bind w/auth
- rename do_select() to do_ldap_select()
- buf fix in ldap_msgdelete() -- update prev
- support LDAP_OPT_RESTART option
libraries/libldap/request.c - changes to support referral re-bind w/auth
- initialize new lr_conn field (for abandon)
libraries/libldap/test.c - changes to support referral re-bind w/auth
libraries/libldap/tmplout.c - searchact uses "-dnt" and "-dnb", not "-dn"
libraries/libldap/url.c - new routines: ldap_is_ldap_url,
ldap_parse_url, ldap_url_search
ldap_url_search_s, ldap_url_search_st
libraries/libldif/ - new library that contains line64 routines
clients/tools/ldapmodify.c - preferred input format is now slapd.replog
clients/tools/ldapsearch.c - added -L option (output in LDIF format)
- don't print initial blank line when -f used
- support "-f -" for reading filters from stdin
clients/ud/*.c - various bug fixes & auth. streamlining
doc/man/man3/ldap.3 - add several new routines
doc/man/man3/ldap_bind.3/.links - add new ldap_set_rebind_proc() routine
doc/man/man3/ldap_charset.3/.links - add new routines
doc/man/man3/ldap_disptmpl.3 - added missing *'s in ldap_init... arg. lists
doc/man/man3/ldap_result.3 - add details r.e. timeout parameter
doc/man/man3/ldap_open.3 - document LDAP_OPT_REFERRALS default to on
doc/man/man3/ldap_url.3/.links - document new LDAP URL routines
Make-common.dist and .um - add LDBMINCLUDE variable
- use ISODEPACKAGE and ICRELEASE in place of
ICR1 and XTISODE defines
- remove LDAP_DNS stuff
build/Make-append - add LDBMINCLUDE variable
- add NO_SETPROCTITLE to SERVERDEFS
- use ISODEPACKAGE and ICRELEASE in place of
ICR1 and XTISODE defines
build/mkdep - use compiler passed in, not always cc
- remove system dependencies when gcc is used
build/platforms/attsvr4-cc/ - AT&T SVR4 support
build/platforms/irix-cc/ - SGI IRIX support
build/platforms/irix-gcc/ - SGI IRIX support
servers/ldapd/common.h - add missing extern function declarations
servers/ldapd/association.c - use ISODEPACKAGE test instead of ICR1, etc.
servers/ldapd/certificate.c - add missing extern declaration
servers/ldapd/error.c - use ISODEPACKAGE test instead of ICR1, etc.
servers/ldapd/kerberos.c - use ISODEPACKAGE test instead of ICR1, etc.
servers/ldapd/request.c - use ISODEPACKAGE test instead of ICR1, etc.
servers/ldapd/main.c - set proctitle to calling host (bug fix)
- CLDAP: don't timeout/exit prematurely
servers/ldapd/proctitle.c - don't compile file if NO_SETPROCTITLE is on
servers/ldapd/Make-template - don't try to make depend if don't have isode
servers/ldap - bug fixes, support ICR3
servers/slapd/tools/ldif.c - use correct pointer when calling realloc
servers/slapd/tools/edb2ldif.c - properly #ifdef code to handle potential
lack of file_attr_dir and turbo disk stuff
- add RDN attribute values to entries
- don't pre-pend './' to EDB files on cmd. line
servers/slapd/tools/ldapsyntax.c- use static buffer to speed things up
servers/slapd/tools/Make-template - don't try to make depend some tools
- if we don't have isode
servers/slapd - fix acl handling
servers/slapd - fix race condition setting o_dn
servers/slapd - bug fixes
servers/slurpd - complete re-write
tests/ - new - test scripts to verify basic
functionality of libraries, slapd, slurpd
----------------------------------------------------------------------------
Changes since 3.2b3
slapd admin guide - document ldbmtest changes
- clarify quick-start instructions
include/ldapconfig.h.dist - move likely-to-change things to top
Make-common.dist - add phonetic algorithm config lines
build/Make-append - add def for phonetic algorithm config lines
libraries/libldbm/ldbm.c - fix bug with gdbm cache size handling
libraries/liblber/encode.c - cap lengths at 32-bits for Alpha compatibility
libraries/libldap/disptmpl.c - recognize both "addact" and "adddnact"
libraries/libldap/getdn.c - handle \ escapes in DNs better
clients/tools/ldapsearch.c - added -S option to sort results
- print results as they are received (if no -S)
servers/slapd/* - added function prototypes
servers/slapd/phonetic.c - make phonetic alg settable in Make-common
servers/slapd/tools/ldbmtest.c - fix bugs, use dbcache routines (like slapd)
- add 'b' and 'B' commands
servers/slapd/tools/edb2ldif.c - include quipu/config.h & quipu/entry.h
- this fixes TURBO_DISK problems
servers/ldapd/* - misc. fixes for VMS and OSF/1
- added function prototypes
----------------------------------------------------------------------------
Changes since 3.2b2
servers/slapd/* - lots of changes/fixes/improvements
servers/slapd/tools/* - add ldif program
- add centipede program
- numerous fixes/improvements
clients/tools/ldapmodify.c - add -b option (read binary vals from a file)
- add trailing \ feature for iattr, etc.
clients/tools/ldapsearch.c - add -z sizelimit and -l timelimit options
- add -B (allow non-ascii values_ option
- change /tmp template used with -t
include/lber.h - add LBER_MAX_INCOMING_SIZE option
libraries/liblber/io.c - support LBER_MAX_INCOMING_SIZE option
- new ber_init() and ber_reset() routines
libraries/libldap/* - various improvements to LDAP_REFERRALS code
- minor changes for Mac re-port
libraries/libldap/disptmpl.c - "addact" is now "adddnact"
libraries/libldap/cache.c - we now cache compare results that have error
of LDAP_NO_SUCH_ATTRIBUTE
libraries/libldap/open.c - support :port on ldap_open() hosts
libraries/libldap/charset.c - new T.61 to ISO-8859 conversion support
- thanks to enrique.silvestre@uv.es
libraries/libldap/kbind.c - a few changes for MS Windows
libraries/msdos/winsock/* - a few changes for Kerberos support
servers/ldapd/modify.c - added support for JPEG non-file attrs.
- added support for octetstring attrs.
servers/ldapd/syntax.c - DN syntax fixes (OID. and replace {ASN} w/#)
- don't escape '$' in DeliveryMethod attrs.
- added support for JPEG non-file attrs.
- added support for octetstring attrs.
----------------------------------------------------------------------------
Changes since 3.2b1
servers/slapd/ - add better database concurrency
- remove multiple dn support
- add stats logging
- fix syslogging
- add include config file option
- add dbcachesize option
- add abandon
- add lastmod/creator attrs
- add monitoring capability
- normalize dns properly
- base 64 value encoding support
- add schema checking
- fix various bugs
- add srvtab config option
servers/slapd/tools - whole new set of db creation/conversion tools
clients/finger/main.c - added -c option & use of FINGER_RDNCOUNT
clients/gopher/go500.c - added -c option & use of GO500_RDNCOUNT
clients/gopher/go500gw.c - added -c option & use of GO500GW_RDNCOUNT
- removed non-functional -s option
clients/rcpt500/main.c - added -c option & use of RCPT500_RDNCOUNT
clients/rcpt500/query.c - use rdncount instead of hard-coded 2
include/ldapconfig.h.edit - added _RDNCOUNT #defines
libraries/libldap/tmplout.c - made rdncount of 0 show all DN components
libraries/libldap/getdn.c - added ldap_is_dns_dn() routine
libraries/libldap/* - many #ifndef NO_REFERRALS changes
- new ldap_init() routine
----------------------------------------------------------------------------
Changes since 3.1 final
General/various files - incorporated changes for Borland C 3.1
Makefile - added support for NeXTSTEP
libraries/liblber/io.c - add ability to save ldap session to a file
include/lber.h - add ability to save ldap session to a file
build/platforms/nextstep-cc/Make-platform
- added -all_load option for ld
build/platforms/sunos5-cc/Make-platform
- define SYSEXITSPATH as for sunos5-gcc
build/uname.sh - new replacement uname for NeXTSTEP, etc.
clients/finger/main.c - don't use fprintf for entry2text
clients/gopher/go500.c - use GO500_HOSTNAME (bug fix)
- don't use fprintf for entry2text
clients/gopher/go500gw.c - use GO500GW_HOSTNAME (bug fix)
- don't use fprintf for entry2text
clients/mail500/main.c - improved error logging
- fixed "errors-to is a group" bug
- don't look in people space for groups
- don't bounce loop messages back to sender
- misc. fixes
clients/tools/ldapdelete.c - add -c option to continue after errors occur
clients/tools/ldapmodify.c - add -c option to continue after errors occur
clients/tools/ldapmodrdn.c - add -c option to continue after errors occur
clients/tools/ldapsearch.c - added -t option to write values to tmp files
- added -A option for "attributes only"
clients/ud/print.c - make sure ldap_count_values() returns > 0
- before trying to use returned values
doc/man/man1/ldapdelete.1 - updated to mention new -c option
doc/man/man1/ldapmodify.1 - updated to mention new -c option
doc/man/man1/ldapmodrdn.1 - updated to mention new -c option
doc/man/man1/ldapsearch.1 - updated to mention new -A & -t options
doc/man/man3/ldap_friendly.3 - fixed typo in ldap_free_friendlymap()
doc/man/man5/ldapfilter.conf.5 - add missing part of example config file
include/disptmpl.h - appended 'L' to long #defined contants
- added entry2html family of routines
include/lber.h - added sb_options to allow copy to file
- added ber_wptr to re-start partial writes
include/ldap.h - added debug levels for sldapd
- added LDAP_SYSLOG to send debug using syslog
include/ldapconfig.h.edit - added GO500GW_HOSTNAME
include/ldapconfig.h.dist - added GO500GW_HOSTNAME
include/portable.h - select() macro fix for HP/UX /bin/cc
include/proto-lber.h - Borland C fixes
- added ber_bvdup() prototype
include/sysexits-compat.h - new file, in case we ever need it
libraries/libavl/* - new library; used in sldapd
libraries/liblber/decode.c - new 'o' feature for ber_scanf()
- new ber_bvdup() routine
- Borland C fixes
libraries/liblber/encode.c - Borland C fixes
libraries/liblber/io.c - ensure that write size <= 64K under VMS
- use ber_wptr to restart partial writes
- added LBER_TO_FILE/FILE_ONLY option support
libraries/libldap/abandon.c - use correct message id in abandon requests
libraries/libldap/cache.c - use time() in a more portable manner
libraries/libldap/cldap.c - retry correct number of times (off by one)
libraries/libldap/error.c - define empty ldap_perror if NO_USERINTERFACE
libraries/libldap/getdn.c - ldap_dn2ufn() now returns dn if no '='
- ldap_explode_dn handles DNs without '='
libraries/libldap/open.c - "host" can now be a space-separated list
libraries/libldap/sort.c - make function declarations more portable
libraries/libldap/srchpref.c - fixed memory leak in options parsing
libraries/libldap/test.c - added -t & -T options for ber output to file
- added 'E' command to explode a DN
libraries/libldap/tmplout.c - added entry2html()
- added entry2html_search()
- added entry2vals()
- remove extraneous ber_free when not using tmpl
- fix non-ASCII core dump bugs
libraries/libldap/ldapfriendly - added EE & RU
libraries/libldap/ldapfilter.conf
- remove '\' inside [] in reg exprs.
- add web500gw to filter tags
- added xax500-auth section
libraries/libldap/ldapsearchprefs.conf
- changed xax500 tags
libraries/libldap/ldaptemplates.conf
- added co to Country template
- add missing types & options to comments
- add "Last Modified" attrs. to all templates
- make "Last Modified" attrs. read-only
libraries/libldbm/* - new library; used in sldapd
libraries/liblthread/* - new library; used in sldapd
libraries/msdos/README.WSA - updated to include Borland C instructions
libraries/vms/README.VMS - fixed pathname typo
servers/ldapd/add.c - make BER tags unsigned long everywhere
servers/ldapd/certificate.c - make parsing consistent with printing code
servers/ldapd/main.c - moved openlog() after detach() call
servers/ldapd/modify.c - correct tag usage in ber_first/next loop
- output all debugging to stderr
- pass and use Sockbuf * in modify_result() call
servers/ldapd/result.c - change to always use DER encoding
servers/ldapd/search.c - change to always use DER encoding
servers/ldapd/syntax.c - add support for telexNumber
servers/sldapd - all new "standalone LDAP server"
----------------------------------------------------------------------------
Changes since 3.1b8
Make-common - added note r.e. -DNO_USERINTERFACE
servers/ldapd/association.c - don't include filio.h under AIX
build/platforms/aix-cc and -gcc - add _BSD to defines
include/portable.h - define OPENLOG_OPTIONS
clients/*/*.c - use OPENLOG_OPTIONS
servers/ldapd/main.c - use OPENLOG_OPTIONS
servers/ldapd/syntax.c - add iattr support (from craig watkins)
----------------------------------------------------------------------------
Changes since 3.1b7
Many System V portability fixes....
A few fixes for VMS....
Makefile - support Linux & NetBSD
Make-common - add support for NEXOR version of isode
- add ISODEBASELIBS
include/Make-template - make ldapconfig.h depend on Makefile
include/ldapconfig.h.edit - add RCPT500_LISTLIMIT, RCPT500_UFN
- add GO500_TIMEOUT, GO500_UFN
- add FINGER_UFN, FINGER_TIMEOUT,
- add GO500GW_UFN
- change *_DEREF to be LDAP_DEREF_FINDING
include/regex.h - use NEED_BSDREGEX
include/portable.h - SYSV changes & general re-vamping
include/disptmpl.h - fix typo in ldap_name2template() prototype
- add LDAP_SYN_RFC822ADDR
libraries/liblber/io.c - make ber_alloc actually use BER
libraries/libldap/cldap.c - preserve old log DN if NULL is passed
libraries/libldap/regex.c - use NEED_BSDREGEX
libraries/libldap/disptmpl.c - add support for LDAP_SYN_RFC822ADDR
libraries/libldap/tmplout.c - add support for LDAP_SYN_RFC822ADDR
libraries/libldap/getfilter.c - always #include "regex.h"
servers/ldapd/main.c - don't check openlog return code
servers/ldapd/request.c - only do syslog if dosyslog is set
servers/ldapd/syntax.c - add support for user certificates (from ER)
servers/ldapd/certificate.c - add support for user certificates (new file)
clients/finger/main.c - add -t disptmplfile option
- add -p port option
- add ufn support
clients/gopher/go500.c - add -t disptmplfile option
- add ufn support
clients/gopher/go500gw.c - add -t disptmplfile option
- add ufn support
clients/mail500/main.c - add -t disptmplfile option
- add support for mail to -owner
clients/rcpt500/main.c,query.c - add support for RCPT500_LISTLIMIT
- support -p ldapport option
- add ufn support
clients/tools/ldapsearch.c - recognize -w option properly
clients/tools/ldapdelete.c - recognize -k option properly
clients/tools/ldapmodrdn.c - new program
clients/ud/edit.c - use execlp() instead of execle()
clients/ud/main.c - include sys/ioctl.h under NetBSD
clients/ud/print.c - updated time2text() from libldap/tmplout.c
contrib/saucer - new contributed client from Eric Rosenquist
build/platforms - added netbsd-cc & netbsd-gcc
- updated sunos5-cc and sunos5-gcc
- added missing CC=gcc in hpux-gcc
- added vms
build/Make-append - change ISODELIBS
doc/man/man8/rcpt500.8 - new manual page
doc/man/man3/ldap.3 - add (3) to routine names in INDEX section
doc/man/man3/ldap_search.3 - remove reference to ldap_parse(3)
doc/man/man3/ldap_modrdn.3 - new manual page
doc/man/man3/ldap_modrdn.3.links- new links file
doc/man/man3/ldap_disptmpl.3 - re-word ldap_octemplate description
- document LDAP_SYN_RFC822ADDR
doc/man/man5/ldap_searchprefs.5 - fix formatting
doc/man/man5/ldaptemplatesconf.5- document "mail" syntax type
doc/man/* - use ETCDIR everywhere (was %ETCDIR%)
-------
ldap-3.1b7 CHANGES file - summary of major changes to each component
since the last release
source tree - completely reorganized for your convenience
- makes full use of ansi-style prototypes
- supports non-ansi compilers through unproto utility
configuration - all client configuration has been moved to ldapconfig.h.edit
(no need to edit multiple source code files)
build procedure - completely revamped for your convenience
- automaticly figures out your platform/compiler
- supports multiple objects from a single source tree
liblbdap - added support for display templates
- added support for search preferences
- added ldap_sort routines for sorting entries
- rearranged some routines/source files to allow
better incremental linking to reduce code bloat
- added support for CLDAP
liblber - added O option to ber_scanf: allocate octet string w/length
- big tags (greater than 31) now supported
- distinguished encoding rules supported (runtime choice
between ber and der)
in.xfingerd - now uses display template routines
- now uses ldap sorting routines
- editable configuration info moved to ldapconfig.h.edit
go500 - now uses display template routines
- now uses ldap sorting routines
- editable configuration info moved to ldapconfig.h.edit
go500gw - now uses display template routines
- now uses ldap sorting routines
- editable configuration info moved to ldapconfig.h.edit
rcpt500 - now uses display template routines
- now uses ldap sorting routines
- editable configuration info moved to ldapconfig.h.edit
mail500 - addition of a new "vacation" feature
- editable configuration info moved to ldapconfig.h.edit
ldap tools - new addition of some shell-based tools
whois++ g/w - moved to contrib/ directory
web500 - new addition, in contrib/ directory
ldapd - lots of bug fixes
- bring CLDAP code in line with latest Internet Draft
documentation - library man pages have been completely re-done, split
into separate manuals, with new pages for each set of
routines.
- new man pages for most client programs (more on the way)
windows ldap - support for Win32 (unfinished?)
- added VERSIONINFO resource to dll
- check for > 64K response packet and don't crash
macintosh ldap - support Apple's new Universal Header files

9
COPYRIGHT Normal file
View File

@ -0,0 +1,9 @@
Copyright (c) 1992-1996 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.

136
INSTALL Normal file
View File

@ -0,0 +1,136 @@
Making and Installing the U-M LDAP Distribution
** It is recommended that you read or at least skim through ALL of the
** instructions in this file before attempting to build the software.
If you want to build binaries for more than one platform from a single
source tree, skip ahead to the "Building LDAP For More Than One Platform"
section near the end of this file. If you are planning to run slapd,
you should read the "SLAPD and SLURPD Administrator's Guide", found in
the doc/guides/ directory within the distribution.
If you simply want to build LDAP for a single machine platform, follow
these steps:
1. untar the distribution and cd to the top:
% zcat ldap-3.3.tar.Z | tar xf -
% cd ldap-3.3
If you are reading this file, you probably have already done this!
2. edit the files Make-common and include/ldapconfig.h.edit to configure
the software for your site (the files are well-commented):
% vi Make-common
% vi include/ldapconfig.h.edit
Note that you should NOT need to edit the Makefile located at the
top of the distribution.
If you just want to see if things will build, you can leave the
configuration alone and change it later.
If you have the ISODE package built and want to build the
LDAP-to-X.500 server (ldapd), be sure to uncomment the appropriate
lines near the end of the Make-common file. By default only the
stand-alone server, LDAP libraries and client software are built.
3. make the software:
% make
If all goes well, then make will figure out what platform you are on,
pick a compiler to use, construct Makefiles, and build everything.
If you see a message like "unknown platform..." LDAP has probably not
been set up to build on your machine. See the file build/PORTS for
hints on what to do in that case.
Note that if your make does not use the Bourne (sh) shell by
default when executing internal scripts (reportedly the case on SGI
machines at least), you will need to run the make explicitly from
within a Bourne shell. If you a syntax error such as "Missing ]"
when you do the make under your usual shell, try this:
% sh
$ make
If you don't like the some of the platform-specific options chosen
by the automatic build process (such as the compiler to use, etc),
you can intervene and edit them before anything is actually compiled
by explicitly doing a "make platform" step, editing the .make-platform
file (actually a link to the file to be edited), and then doing a
regular make:
% make platform
% vi .make-platform
% make
If you want to choose the build platform yourself from among those that
the distribution supports, cd to the appropriate directory underneath
build/platforms and make from there. For example, if you are on a
machine running SunOS 4.1.4 and you want to force the use of the cc
compiler, you would do this:
% cd build/platforms/sunos4-cc
% make
If you want to run some simple tests after the build is complete, you
can do this:
% make test
4. install the binaries and man pages. You may need to be superuser to
do this (depending on where you are installing things):
% su
# make install
That's it! See the man pages for the individual clients for information
on configuring and using them. Eventually you will probably want to
edit the configuration files used by the various clients (installed in
the LDAP etc directory). The files are:
ldapfilter.conf - search filter configuration
ldapfriendly - mapping of X.500 names to human-friendly names
ldapsearchprefs.conf - search object definitions
ldaptemplates.conf - display template definitions
There are section 5 man pages for all of these files.
Building LDAP For More Than One Platform
It is now possible to build LDAP for more than one platform from the same
source tree. This is accomplished by some rules in the Makefiles that
create a shadow (linked) directory tree where the binaries are placed.
Follow these steps for each different platform:
1. move to the directory that matches the platform and compiler you
want to build for and type make. The directories are all located
underneath the build/platforms directory. If your platform is not
there, you may need to do a port - see the build/PORTS file for
more information. For a Sun running SunOS 4.1.4, you might do
this:
% cd build/platforms/sunos4-cc
% make links
This will create a linked source area.
2. move to the new directory and make as for a single platform. Follow steps
1-4 above to accomplish this. For example:
% cd obj-sunos4-cc
% make
That's all there is to it. You can also create the linked source area(s)
by just typing "make links" at the top of the distribution, in which case
the Makefile will try to automatically determine the platform and
compiler.
End of LDAP INSTALL file.

200
Make-common Normal file
View File

@ -0,0 +1,200 @@
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# LDAP common Make defines (included in all but top-level Makefile)
#
#-----------------------------------------------------------------------------
#############################################################################
## Edit the following variables to have appropriate values for your system ##
#############################################################################
#############################################################################
## LDAP install paths ##
#############################################################################
#
# by default, everything is installed below INSTROOT
# servers, config files, etc. are put in ETCDIR
# include files get put in INCLUDEDIR
# libraries are put in LIBDIR
# man pages are put under MANDIR
# programs end-users will run are put in BINDIR
#
INSTROOT=/usr/local
ETCDIR= $(INSTROOT)/etc
INCLUDEDIR= $(INSTROOT)/include
LIBDIR= $(INSTROOT)/lib
MANDIR= $(INSTROOT)/man
BINDIR= $(INSTROOT)/bin
#
# if you want things to run in a different directory from where they
# are installed, set this accordingly (this path gets compiled into a
# few binaries). otherwise, leave it alone.
RUNTIMEETCDIR= $(ETCDIR)
#############################################################################
## General compiler options ##
#############################################################################
# Passed to every compile (cc or gcc). This is where you put -O or -g, etc.
#EXTRACFLAGS=-g
# Passed to every link (ld). Include -g here if you did in EXTRACFLAGS.
#EXTRALDFLAGS=-g
#############################################################################
## If you are NOT using Kerberos authentication, you can skip this section.##
#############################################################################
#
# Otherwise, to enable kerberos authentication, uncomment KERBEROS (and
# AFSKERBEROS if you are running the AFS version of kerberos). Also
# uncomment and change the various KRB* lines to point to where the
# kerberos libraries and include files are installed at your site.
#
#KERBEROS=-DKERBEROS
#AFSKERBEROS=-DAFSKERBEROS
#KRBINCLUDEFLAG = -I/usr/local/kerberos/include
#KRBLIBFLAG = -L/usr/local/kerberos/lib
#KRBLIBS = -lkrb -ldes
#############################################################################
## ISODE is required ONLY to build the ldap <-> X.500 server (ldapd) ##
## If you don't want to build it, you can skip this section. ##
#############################################################################
#
# To build the ldap server, uncomment the HAVEISODE line,
# and the section describing build settings for your version of isode.
#
#HAVEISODE = yes
# If you compiled ISODE with TURBO_DISK defined, uncomment this
#ISODETURBOLIBS = -lgdbm
# uncomment these to have ldapd "pretty print" protocol elements w/debugging
#PEPSY_DUMP=-DPEPSY_DUMP
#PEPSY=/usr/local/ic/bin/pepsy
# uncommment this line to have ldapd load PP syntax handlers
# you'll also need to add -lpp to ISODEBASELIBS below
#LDAP_USE_PP=-DLDAP_USE_PP
# uncomment NO_SETPROCTITLE to have ldapd NOT change its title
#NO_SETPROCTITLE=-DNOSETPROCTITLE
#
# ISODE Consortium release build settings
# You should change the next line so that ICRELEASE matches the (integer)
# version number of whatever IC release you have, e.g. 1, 2, or 3 and
# also uncomment the next 5 lines.
#ICRELEASE=-DICRELEASE=1
#ISODEPACKAGE=-DISODEPACKAGE=IC
#ISODEINCLUDEFLAG= -I/usr/local/ic/include/isode -I/usr/local/ic/include
#ISODELIBFLAG = -L/usr/local/ic/lib
#ISODEBASELIBS = -lisode
#
# Freely available ISODE 8.0 release build settings (uncomment the next 4 lines)
#ISODEPACKAGE=-DISODEPACKAGE
#ISODEINCLUDEFLAG= -I/usr/local/isode/include
#ISODELIBFLAG = -L/usr/local/isode/lib
#ISODEBASELIBS = -ldsap -lisode
#
# NEXOR ISODE release build settings (uncomment the next 4 lines)
#ISODEPACKAGE=-DISODEPACKAGE=XT
#ISODEINCLUDEFLAG= -I/usr/include/isode
#ISODELIBFLAG = -L/usr/local/lib -L/usr/sunlink/osi/lib
#ISODEBASELIBS = -lxtpp -lresolv -lxtdsap -lxtisode -losi
#############################################################################
## If you don't want to run slapd, skip this section. ##
#############################################################################
#
# To build slapd (the stand-alone ldap daemon), uncomment the MAKESLAPD
# line and select the SLAPD_BACKENDS you want to use. If you enable the
# LDBM backend, also select one of the LDBM backends.
MAKESLAPD= yes
#
# remove the defines for backends you don't want to enable
SLAPD_BACKENDS= -DLDAP_LDBM -DLDAP_SHELL -DLDAP_PASSWD
#
# If you have included -DLDAP_LDBM in the SLAPD_BACKENDS line you need
# to specify which low-level database package to use. There are
# four choices: Berkeley db b-tree, Berkeley db hash, GNU dbm, or ndbm.
#
# berkeley db btree package
#LDBMBACKEND=-DLDBM_USE_DBBTREE
#LDBMINCLUDE=-I/usr/local/db/include
#LDBMLIB=-ldb
# berkeley db hash package
#LDBMBACKEND=-DLDBM_USE_DBHASH
#LDBMINCLUDE=-I/usr/local/db/include
#LDBMLIB=-ldb
# gnu dbm (gdbm)
#LDBMBACKEND=-DLDBM_USE_GDBM
#LDBMINCLUDE=-I/usr/local/gdbm/include
#LDBMLIB=-lgdbm
# standard unix ndbm
LDBMBACKEND=-DLDBM_USE_NDBM
#
# if you want to use a non-default threads package change these lines
#THREADS=-DNO_THREADS
#THREADSLIB=
#############################################################################
## The following options are used by the xax500 client. If you haven't ##
## retrieved the xax500 source and dropped it into the "clients" ##
## directory, you can skip this section. ##
#############################################################################
#
# location of your X include files
#XINCLUDES= -I/usr/X11/include
#
# location of your X libraries
#XLIBDIRS=-L/usr/X11/lib
#
# include any extra X libraries you need here
# the following works with sunos 4 and X11R5
#XLIBS = $(XLIBDIRS) -lXm -lXt -lX11
# the following has been known to work with Solaris 2.4 and X11R6
#XLIBS = $(XLIBDIRS) -lXm -lXext -lSM -lICE -lXpm -lXt -lX11
#############################################################################
## If you don't want to do auto-translation of character sets, skip this ##
#############################################################################
#
# Otherwise, uncomment this line and set the following options.
#STR_TRANSLATION=-DSTR_TRANSLATION
#
# remove the defines for LDAP client library T.61 character translation
# you do not need. If you use LDAP_CHARSET_8859, replace the '1' in "88591"
# with the number of the particular character set you use. E.g., use "88594"
# if you use the ISO 8859-4 chracter set.
#LIBLDAP_CHARSETS=-DLDAP_CHARSET_8859="88591"
#
# uncomment one these lines to enable automatic T.61 translation by default
#LIBLDAP_DEF_CHARSET=-DLDAP_DEFAULT_CHARSET=LDAP_CHARSET_8859
#############################################################################
## General options ##
#############################################################################
# uncomment this line to enable debugging code (a good idea)
LDAP_DEBUG=-DLDAP_DEBUG
# uncomment this line to turn on a few U of Michigan specific things
#UOFM=-DUOFM
# uncomment this line to delete a few printfs in the lber and ldap libraries.
#NO_USERINTERFACE=-DNO_USERINTERFACE
# uncomment this line to include Connectionless LDAP support
#CLDAP=-DCLDAP
# uncomment this line to eliminate local caching support in the libldap
#NO_CACHE=-DNO_CACHE
# uncomment this line to enable support for LDAP referrals in libldap
LDAP_REFERRALS=-DLDAP_REFERRALS
# uncomment this line to use soundex for approximate matches in slapd.
# the default is to use the metaphone algorithm.
#PHONETIC=-DSOUNDEX

200
Make-common.um Normal file
View File

@ -0,0 +1,200 @@
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# LDAP common Make defines (included in all but top-level Makefile)
#
#-----------------------------------------------------------------------------
#############################################################################
## Edit the following variables to have appropriate values for your system ##
#############################################################################
#############################################################################
## LDAP install paths ##
#############################################################################
#
# by default, everything is installed below INSTROOT
# servers, config files, etc. are put in ETCDIR
# include files get put in INCLUDEDIR
# libraries are put in LIBDIR
# man pages are put under MANDIR
# programs end-users will run are put in BINDIR
#
INSTROOT=/usr/local
ETCDIR= $(INSTROOT)/etc
INCLUDEDIR= $(INSTROOT)/include
LIBDIR= $(INSTROOT)/lib
MANDIR= $(INSTROOT)/man
BINDIR= $(INSTROOT)/bin
#
# if you want things to run in a different directory from where they
# are installed, set this accordingly (this path gets compiled into a
# few binaries). otherwise, leave it alone.
RUNTIMEETCDIR= $(ETCDIR)
#############################################################################
## General compiler options ##
#############################################################################
# Passed to every compile (cc or gcc). This is where you put -O or -g, etc.
EXTRACFLAGS=-g
# Passed to every link (ld). Include -g here if you did in EXTRACFLAGS.
EXTRALDFLAGS=-g
#############################################################################
## If you are NOT using Kerberos authentication, you can skip this section.##
#############################################################################
#
# Otherwise, to enable kerberos authentication, uncomment KERBEROS (and
# AFSKERBEROS if you are running the AFS version of kerberos). Also
# uncomment and change the various KRB* lines to point to where the
# kerberos libraries and include files are installed at your site.
#
KERBEROS=-DKERBEROS
AFSKERBEROS=-DAFSKERBEROS
KRBINCLUDEFLAG = -I/usr/local/kerberos/include
KRBLIBFLAG = -L/usr/local/kerberos/lib
KRBLIBS = -lkrb -ldes
#############################################################################
## ISODE is required ONLY to build the ldap <-> X.500 server (ldapd) ##
## If you don't want to build it, you can skip this section. ##
#############################################################################
#
# To build the ldap server, uncomment the HAVEISODE line,
# and the section describing build settings for your version of isode.
#
HAVEISODE = yes
# If you compiled ISODE with TURBO_DISK defined, uncomment this
#ISODETURBOLIBS = -lgdbm
# uncomment these to have ldapd "pretty print" protocol elements w/debugging
PEPSY_DUMP=-DPEPSY_DUMP
PEPSY=/usr/local/ic/bin/pepsy
# uncommment this line to have ldapd load PP syntax handlers
# you'll also need to add -lpp to ISODEBASELIBS below
#LDAP_USE_PP=-DLDAP_USE_PP
# uncomment NO_SETPROCTITLE to have ldapd NOT change its title
#NO_SETPROCTITLE=-DNOSETPROCTITLE
#
# ISODE Consortium release build settings
# You should change the next line so that ICRELEASE matches the (integer)
# version number of whatever IC release you have, e.g. 1, 2, or 3 and
# also uncomment the next 5 lines.
ICRELEASE=-DICRELEASE=2
ISODEPACKAGE=-DISODEPACKAGE=IC
ISODEINCLUDEFLAG= -I/usr/local/ic/include
ISODELIBFLAG = -L/usr/local/ic/lib
ISODEBASELIBS = -lisode
#
# Freely available ISODE 8.0 release build settings (uncomment the next 4 lines)
#ISODEPACKAGE=-DISODEPACKAGE
#ISODEINCLUDEFLAG= -I/usr/local/isode/include
#ISODELIBFLAG = -L/usr/local/isode/lib
#ISODEBASELIBS = -ldsap -lisode
#
# NEXOR ISODE release build settings (uncomment the next 4 lines)
#ISODEPACKAGE=-DISODEPACKAGE=XT
#ISODEINCLUDEFLAG= -I/usr/include/isode
#ISODELIBFLAG = -L/usr/local/lib -L/usr/sunlink/osi/lib
#ISODEBASELIBS = -lxtpp -lresolv -lxtdsap -lxtisode -losi
#############################################################################
## If you don't want to run slapd, skip this section. ##
#############################################################################
#
# To build slapd (the stand-alone ldap daemon), uncomment the MAKESLAPD
# line and select the SLAPD_BACKENDS you want to use. If you enable the
# LDBM backend, also select one of the LDBM backends.
MAKESLAPD= yes
#
# remove the defines for backends you don't want to enable
SLAPD_BACKENDS= -DLDAP_LDBM -DLDAP_SHELL -DLDAP_PASSWD
#
# If you have included -DLDAP_LDBM in the SLAPD_BACKENDS line you need
# to specify which low-level database package to use. There are
# four choices: Berkeley db b-tree, Berkeley db hash, GNU dbm, or ndbm.
#
# berkeley db btree package
LDBMBACKEND=-DLDBM_USE_DBBTREE
LDBMINCLUDE=-I/usr/local/include
LDBMLIB=-ldb
# berkeley db hash package
#LDBMBACKEND=-DLDBM_USE_DBHASH
#LDBMINCLUDE=-I/usr/local/include
#LDBMLIB=-ldb
# gnu dbm (gdbm)
#LDBMBACKEND=-DLDBM_USE_GDBM
#LDBMINCLUDE=-I/usr/local/include
#LDBMLIB=-lgdbm
# standard unix ndbm
#LDBMBACKEND=-DLDBM_USE_NDBM
#
# if you want to use a non-default threads package change these lines
#THREADS=-DNO_THREADS
#THREADSLIB=
#############################################################################
## The following options are used by the xax500 client. If you haven't ##
## retrieved the xax500 source and dropped it into the "clients" ##
## directory, you can skip this section. ##
#############################################################################
#
# location of your X include files
#XINCLUDES= -I/usr/local/X11/include
#
# location of your X libraries
#XLIBDIRS=-L/usr/local/X11/lib
#
# include any extra X libraries you need here
# the following works with sunos 4 and X11R5
#XLIBS = $(XLIBDIRS) -lXm -lXt -lX11
# the following has been known to work with Solaris 2.4 and X11R6
#XLIBS = $(XLIBDIRS) -lXm -lXext -lSM -lICE -lXpm -lXt -lX11
#############################################################################
## If you don't want to do auto-translation of character sets, skip this ##
#############################################################################
#
# Otherwise, uncomment this line and set the following options.
#STR_TRANSLATION=-DSTR_TRANSLATION
#
# remove the defines for LDAP client library T.61 character translation
# you do not need. If you use LDAP_CHARSET_8859, replace the '1' in "88591"
# with the number of the particular character set you use. E.g., use "88594"
# if you use the ISO 8859-4 chracter set.
#LIBLDAP_CHARSETS=-DLDAP_CHARSET_8859="88591"
#
# uncomment one these lines to enable automatic T.61 translation by default
#LIBLDAP_DEF_CHARSET=-DLDAP_DEFAULT_CHARSET=LDAP_CHARSET_8859
#############################################################################
## General options ##
#############################################################################
# uncomment this line to enable debugging code (a good idea)
LDAP_DEBUG=-DLDAP_DEBUG
# uncomment this line to turn on a few U of Michigan specific things
UOFM=-DUOFM
# uncomment this line to delete a few printfs in the lber and ldap libraries.
#NO_USERINTERFACE=-DNO_USERINTERFACE
# uncomment this line to include Connectionless LDAP support
CLDAP=-DCLDAP
# uncomment this line to eliminate local caching support in the libldap
#NO_CACHE=-DNO_CACHE
# uncomment this line to enable support for LDAP referrals in libldap
LDAP_REFERRALS=-DLDAP_REFERRALS
# uncomment this line to use soundex for approximate matches in slapd.
# the default is to use the metaphone algorithm.
#PHONETIC=-DSOUNDEX

392
Makefile Normal file
View File

@ -0,0 +1,392 @@
#
# You will usually NOT need to edit this file at all: instead, edit the
# Make-common file. See the LDAP INSTALL file for more information.
#
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# LDAP lightweight X.500 Directory access top level makefile
#
#-----------------------------------------------------------------------------
#
############################################################################
# #
# Usually you will not need to edit anything in this file #
# #
############################################################################
#
# Note that these definitions of standard Unix utilities are only used
# in this Makefile. The Make-common (and .make-platform) files have a
# similar set of definitions that are used in all the other LDAP Makefiles.
#
RM=rm -f
MV=mv -f
CP=cp
CAT=cat
PWD=pwd
TAIL=tail
CHMOD=chmod
FIND=find
SED=sed
LN=ln -s
MKDIR=mkdir
GREP=grep
DIRNAME=dirname
BASENAME=basename
TAR=tar
COMPRESS=compress
CO=co
CI=ci
SRCDIRS= include libraries clients servers doc
TESTDIR= tests
#
# LDAPSRC is used by the links rule
#
LDAPSRC= ..
#
# rules to make the software
#
all: makeconfig
@echo "making all"
@for i in $(SRCDIRS); do \
echo; echo " cd $$i; $(MAKE) $(MFLAGS) all"; \
( cd $$i; $(MAKE) $(MFLAGS) all ); \
done
lib-only: makeconfig
@echo "making libraries only"
@echo " cd include; $(MAKE) $(MFLAGS) all"; \
cd include; $(MAKE) $(MFLAGS) all
@echo " cd libraries; $(MAKE) $(MFLAGS) all"; \
cd libraries; $(MAKE) $(MFLAGS) all
#
# rules to install the software
#
install: makeconfig
@for i in $(SRCDIRS); do \
echo; echo "cd $$i; $(MAKE) $(MFLAGS) install"; \
( cd $$i; $(MAKE) $(MFLAGS) install ); \
done
inst-lib: makeconfig
@echo "cd libraries; $(MAKE) $(MFLAGS) install"
@( cd libraries; $(MAKE) $(MFLAGS) install )
#
# rules to test the LDAP software
#
test: all
@echo " cd $(TESTDIR); $(MAKE) $(MFLAGS) all"; \
( cd $(TESTDIR); $(MAKE) $(MFLAGS) all );
#
# rules to make clean
#
clean: FORCE
@if [ -f .makefiles ]; then \
for i in $(SRCDIRS) $(TESTDIR); do \
echo; echo "cd $$i; $(MAKE) $(MFLAGS) clean"; \
( cd $$i; $(MAKE) $(MFLAGS) clean ); \
done; \
fi; \
( for d in ./obj-*; do \
if [ $$d != "./obj-*" ]; then \
( echo "making clean in $$d..."; \
cd $$d; $(MAKE) $(MFLAGS) clean; ) \
else \
exit 0; \
fi; \
done )
veryclean: FORCE
@echo; echo "cd build; $(MAKE) $(MFLAGS) -f Make-template veryclean"; \
( cd build; $(MAKE) $(MFLAGS) -f Make-template veryclean ); \
if [ -f .makefiles ]; then \
for i in $(SRCDIRS) $(TESTDIR); do \
echo; echo "cd $$i; $(MAKE) $(MFLAGS) veryclean"; \
( cd $$i; $(MAKE) $(MFLAGS) veryclean ); \
done; \
echo "finding and removing Makefiles..."; \
for i in `$(FIND) . -type d -print`; do \
if [ -f $$i/Make-template ]; then \
echo "removing file $$i/Makefile"; \
$(RM) $$i/Makefile; \
fi; \
done; \
echo "removing file .makefiles"; \
$(RM) .makefiles; \
fi; \
( for d in ./obj-*; do \
if [ $$d != "./obj-*" ]; then \
echo "removing $$d..."; $(RM) -r $$d; \
else \
exit 0; \
fi; \
done ); \
if [ -f .make-platform ]; then \
echo "removing link .make-platform"; \
$(RM) .make-platform; \
else \
exit 0; \
fi
#
# rules to make depend
#
#
depend: makeconfig
@echo "making depend everywhere"; \
echo " cd include; $(MAKE) $(MFLAGS) all"; \
( cd include; $(MAKE) $(MFLAGS) all ); \
for i in $(SRCDIRS); do \
echo; echo "cd $$i; $(MAKE) $(MFLAGS) depend"; \
( cd $$i; $(MAKE) $(MFLAGS) depend ); \
done; \
$(MAKE) $(MFLAGS) makefiles
#
# rules to check out and in Make-template files
#
co-mktmpls: FORCE
@echo "checking out Make-template files..."; \
for mkfile in `$(FIND) . -name Make-template -type f -print`; do \
$(CO) -l $$mkfile; \
done
ci-mktmpls: FORCE
@echo "enter a one-word log message:"; \
read logmsg; \
echo "checking in Make-template files..."; \
for mkfile in `$(FIND) . -name Make-template -type f -print`; do \
$(CI) -m$$logmsg -u $$mkfile; \
done
lib-depend: makeconfig
@echo "cd libraries; $(MAKE) $(MFLAGS) depend"
@( cd libraries; $(MAKE) $(MFLAGS) depend )"
#
# rules to cut a new ldap distribution
#
distribution: makeconfig checkin tar
checkin: FORCE
@-VERSION=V`cat ./build/version | $(SED) -e 's/\.//'` ; \
echo "Checking in version $$VERSION"; \
for i in `$(FIND) . -name \*,v -print | \
$(SED) -e 's%RCS/%%' -e 's%,v%%'`; \
do ( \
ci -m"pre-version $$VERSION check-in" -u $$i; \
rcs -N$$VERSION: $$i ) \
done
tar: veryclean
@PWD=`pwd`; \
$(RM) ./Make-common; \
$(CP) ./Make-common.dist ./Make-common; \
$(CHMOD) 644 ./Make-common; \
$(RM) ./include/ldapconfig.h.edit; \
$(CP) ./include/ldapconfig.h.dist ./include/ldapconfig.h.edit; \
$(CHMOD) 644 ./include/ldapconfig.h.edit; \
BASE=`$(BASENAME) $$PWD`; XFILE=/tmp/ldap-x.$$$$; \
( cd .. ; $(CAT) $$BASE/exclude >$$XFILE; \
$(FIND) $$BASE -name RCS -print >> $$XFILE ; \
$(FIND) $$BASE -name obj-\* -print >> $$XFILE ; \
$(FIND) $$BASE -name tags -print >> $$XFILE ; \
$(TAR) cvfX ./$$BASE.tar $$XFILE $$BASE; \
); \
$(RM) $$XFILE; \
echo "compressing ../$$BASE.tar..."; \
$(COMPRESS) ../$$BASE.tar
#
# rule to force check for change of platform
#
platform: FORCE
@if [ -f .make-platform ]; then \
echo "removing old link .make-platform"; \
$(RM) .make-platform; \
fi; \
$(MAKE) $(MFLAGS) .make-platform
makeconfig: .makefiles buildtools
.make-platform:
@if [ -f /usr/bin/swconfig ]; then \
UNAME=./build/uname.sh; \
elif [ -f /bin/uname ]; then \
UNAME=/bin/uname; \
elif [ -f /usr/bin/uname ]; then \
UNAME=/usr/bin/uname; \
else \
UNAME=./build/uname.sh; \
fi; \
if [ -z "$$UNAME" ]; then \
echo "unknown platform (no $$UNAME or /usr/bin/uname)"; \
echo "see the file build/PORTS for more information."; \
exit 1; \
else \
OS=`$$UNAME -s` ; OSRELEASE=`$$UNAME -r` ; \
OSVERSION=`$$UNAME -v` ; \
case $$OS in \
SunOS) \
if [ $$OSRELEASE -gt "5" -o $$OSRELEASE -lt "4" ]; then \
echo "SunOS release $$OSRELEASE unknown..."; exit 1; \
fi; \
if [ $$OSRELEASE -ge "5" ]; then \
PLATFORM="sunos5"; \
else \
PLATFORM="sunos4"; \
fi; \
;; \
ULTRIX) \
PLATFORM="ultrix" \
;; \
OSF1) \
PLATFORM="osf1" \
;; \
AIX) \
PLATFORM="aix" \
;; \
HP-UX) \
PLATFORM="hpux" \
;; \
Linux) \
PLATFORM="linux" \
;; \
NetBSD) \
PLATFORM="netbsd" \
;; \
FreeBSD) \
PLATFORM="freebsd" \
;; \
NeXTSTEP) \
PLATFORM="nextstep" \
;; \
SCO) \
PLATFORM="sco" \
;; \
IRIX|IRIX64) \
PLATFORM="irix" \
;; \
*) echo "unknown platform ($$OS $$OSVERSION $$OSRELEASE)..."; \
echo "see the file build/PORTS for more information."; \
exit 1; \
;; \
esac; \
fi; \
CC=$(CC); \
OLDIFS="$$IFS"; \
IFS=":"; \
for dir in $$PATH; do \
if [ -f $$dir/gcc ]; then \
CC=gcc; \
break; \
fi; \
done; \
IFS="$$OLDIFS"; \
$(LN) ./build/platforms/$$PLATFORM-$$CC/Make-platform .make-platform; \
echo ""; \
echo "** Set platform to $$PLATFORM with compiler $$CC..."; \
echo ""
#
# rule to build Makefiles by concatenating Make-template file in each
# subdirectory with global Make-common, .make-platform, and
# build/Make-append files
#
.makefiles: Make-common .make-platform build/Make-append
@echo "making Makefiles..."; \
HDRFILE=/tmp/Makehdr.$$$$; \
DEFSFILE=/tmp/Makedefs.$$$$; \
$(CAT) build/Make-append ./.make-platform ./Make-common > $$DEFSFILE; \
echo "# --------------------------------------------------------" > $$HDRFILE; \
echo "# This file was automatically generated. Do not edit it." >> $$HDRFILE; \
echo "# Instead, edit the Make-common file (located in the root" >> $$HDRFILE; \
echo "# (of the LDAP distribution). See the LDAP INSTALL file" >> $$HDRFILE; \
echo "# for more information." >> $$HDRFILE; \
echo "# --------------------------------------------------------" >> $$HDRFILE; \
echo "#" >> $$HDRFILE; \
for i in `$(FIND) . -type d -print`; do \
if [ -f $$i/Make-template ]; then \
echo " creating $$i/Makefile"; \
$(RM) $$i/Makefile; \
$(CAT) $$HDRFILE $$i/Make-template $$DEFSFILE > $$i/Makefile; \
$(CHMOD) 444 $$i/Makefile; \
fi; \
done; \
$(RM) .makefiles; \
touch .makefiles; \
$(RM) $$HDRFILE $$DEFSFILE
#
# rule to always build makefiles
#
makefiles: FORCE
$(RM) .makefiles
$(MAKE) $(MFLAGS) .makefiles
#
# rule to create any tools we need to build everything else
#
buildtools: FORCE
@echo "making buildtools"
@echo " cd build; $(MAKE) $(MFLAGS)"
@( cd build; $(MAKE) $(MFLAGS) )
#
# rule to make a shadow (linked) build area
#
links: FORCE
@if [ -f /usr/bin/swconfig ]; then \
UNAME=./build/uname.sh; \
elif [ -f /bin/uname ]; then \
UNAME=/bin/uname; \
elif [ -f /usr/bin/uname ]; then \
UNAME=/usr/bin/uname; \
else \
UNAME=./build/uname.sh; \
fi; \
if [ ! -z "$(DEST)" ]; then \
DEST="$(DEST)"; \
else \
DEST=./obj-`$$UNAME -s`-`$$UNAME -r` ; \
fi; \
echo "making links in $$DEST..."; \
LINKLIST=/tmp/ldaplinklist.$$$$; \
$(RM) $$LINKLIST; \
$(MKDIR) $$DEST; \
cd $$DEST; $(LN) $(LDAPSRC) .src; \
$(LN) .src/Makefile . ; \
$(CP) .src/Make-common . ; $(CHMOD) 644 ./Make-common; \
for d in build $(SRCDIRS) $(TESTDIR); do \
( $(MKDIR) $$d; cd $$d; $(LN) ../.src/$$d .src; \
$(LN) .src/Make-template . ; \
$(MAKE) $(MFLAGS) MKDIR="$(MKDIR)" LN="$(LN)" \
-f Make-template links ) ; \
done; \
echo ""; echo "Now type:"; echo " cd $$DEST"; echo "and make there"
FORCE:

59
README Normal file
View File

@ -0,0 +1,59 @@
UM-LDAP 3.3 README file
This is the UM-LDAP version 3.3 distribution. For a description of
what this distribution contains, see the ANNOUNCEMENT file in this
directory. For a description of changes from previous releases,
see the CHANGES file in this directory. For a more detailed
description of how to make and install the distribution, see the
INSTALL file in this directory. For more information on making and
installing slapd, see the "SLAPD and SLURPD Administrator's Guide"
in the doc/guides/ directory.
MAKING AND INSTALLING THE DISTRIBUTION
You should be able to make and install the distribution with a pretty
standard default configuration by typing the following commands
% make
% su
# make install
in this directory. This should produce something that basically
works.
You will probably want to do a little configuration to suit your
site, though. There are two files you might want to edit:
Make-common This file contains definitions for
where things will be installed, where
to find various things, etc. If you
want to build an ldap server, you'll
definitely need to edit this file
include/ldapconfig.h.edit This file contains #defines used
by many parts of the distribution.
You'll at least want to change
DEFAULT_BASE.
See the INSTALL file in this directory for more information.
DOCUMENTATION
There are man pages for most programs in the distribution and
routines in the various libraries. See ldap(3) for details.
There is a postscript version of an administrator's guide for
slapd in doc/guides/slapd.ps.
There is an LDAP homepage available that contains the latest
LDAP news, releases announcements, pointers to other LDAP resources,
etc. You can access it at this URL:
http://www.umich.edu/~rsug/ldap/
FEEDBACK / PROBLEM REPORTS
We would appreciate any feedback you can provide. If you have
problems, report them to this address:
ldap-support@umich.edu

78
build/Make-append Normal file
View File

@ -0,0 +1,78 @@
#
# Do NOT edit this file -- it is automatically appended to all Makefiles
# except the LDAP top-level Makefile. See the LDAP INSTALL file for more
# information.
#
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# LDAP standard Make defines (appended to all but top-level Makefile)
#
#-----------------------------------------------------------------------------
# DEFS are included in CFLAGS
DEFS = $(PLATFORMCFLAGS) $(LDAP_DEBUG) $(KERBEROS) $(AFSKERBEROS) \
$(UOFM) $(UOFA) $(NO_USERINTERFACE) $(CLDAP) $(NO_CACHE) \
$(LDAP_REFERRALS) $(LDAP_DNS) $(STR_TRANSLATION) \
$(LIBLDAP_CHARSETS) $(LIBLDAP_DEF_CHARSET) \
$(SLAPD_BACKENDS) $(LDBMBACKEND) $(LDBMINCLUDE) $(PHONETIC)
# SERVERDEFS are added to server builds CFLAGS (in addition to DEFS)
SERVERDEFS = $(ISODEPACKAGE) $(ICRELEASE) $(LDAP_USE_PP) \
$(NO_SETPROCTITLE) $(PEPSY_DUMP)
#
# ISODELIBS are used in server/ldapd builds
#
ISODELIBS = $(ISODEBASELIBS) -lm $(ISODETURBOLIBS)
# ACFLAGS are added to CFLAGS but not passed to mkdep, lint, etc
ACFLAGS = $(EXTRACFLAGS) $(UNPROTOCFLAGS)
# ALDFLAGS are always placed near the beginning of all linker (cc -o) commands
ALDFLAGS = $(EXTRALDFLAGS) $(PLATFORMLDFLAGS)
# ALIBS are always placed at the end of all linker (cc -o) commands
ALIBS = $(PLATFORMLIBS)
#
# default definitions for Unix utilities (may be over-ridden in Make-platform)
CC = cc
MAKE = make
RANLIB = ranlib
AR = ar
RM = rm -f
MV = mv -f
CP = cp
CHMOD = chmod
CAT = cat
LN = ln -s
HARDLN = ln
TAIL = tail
SED = sed
LINT = lint
5LINT = lint
MKDIR = mkdir
INSTALL = install
INSTALLFLAGS = -c
BASENAME= basename
DIRNAME = dirname
MKDEP = $(LDAPSRC)/build/mkdep -s -f Make-template
PWD = pwd
DATE = date
HOSTNAME= hostname
#
# empty target used to force rules to be invoked
#
FORCE:

38
build/Make-template Normal file
View File

@ -0,0 +1,38 @@
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# LDAP buildtools makefile
#
#-----------------------------------------------------------------------------
all: FORCE
@if [ ! -z "$(NEEDUNPROTO)" ]; then \
cd unproto; $(MAKE) $(MFLAGS) CC=$(CC); \
else \
exit 0; \
fi
install: FORCE
clean:
cd unproto; $(MAKE) $(MFLAGS) clean
cd platforms; $(MAKE) $(MFLAGS) clean
veryclean:
cd unproto; $(MAKE) $(MFLAGS) clean
cd platforms; $(MAKE) $(MFLAGS) veryclean
links:
@echo "making links in `$(PWD)`"; \
$(LN) .src/version .src/platforms .src/Make-append .src/install.sh . ; \
( $(MKDIR) unproto; cd unproto; $(LN) ../.src/unproto .src; \
$(LN) .src/Makefile .src/*.[ch] . )

98
build/PORTS Normal file
View File

@ -0,0 +1,98 @@
This file gives some helpful hints for building LDAP on various machines.
LDAP has been built and tested on the following platforms. It will
probably build fine under similar versions of the OS (e.g. it has
been built and tested under SunOS 4.1.4, but probably builds fine
under all SunOS 4.1.x systems).
If you port LDAP to a new platform, let us know so we can add it here.
See the end of this file for some hints on doing a port. The following
tables give some indication of the level of support there is for various
platforms where the LDAP release has been built. Key:
X - all pieces are known to build and work
B - all pieces build and are believed to work
S - some pieces build and work
O - an older LDAP release has been ported here; current status unknown
? - unknown
- - does not build and/or work at all
** Unix and Unix-like platforms:
OS Version libraries clients ldapd slapd slurpd
---------- --------- ------- ----- ----- ------
AIX 3.2.5 X X B B -(1)
HP-UX 9.05 X X ? B -(1)
Linux 1.3.76 X X O X -(1)
FreeBSD 2.0.5 X X ? B ?
NETBSD 0.9a O O ? ? ?
NeXTSTEP 3.2 O O ? ? ?
SunOS 4.1.4 X X X X X
SunOS 5.5 X X B X X
(Solaris 2.5)
Ultrix 4.3 X X B B ?
OSF/1 3.2 X X X X ?
IRIX 5.x/6.x B B ? B ?
NCR MP-RAS 2.3 X X ? ? ?
(1) - required threads support not provided by vendor
** Non-Unix Platforms:
OS Version libraries clients ldapd slapd slurpd
---------- --------- ------- ----- ----- ------
MacOS 7.5 X - - - -
(see the file libraries/macintosh/README for build instructions)
MSDOS O S - - -
(see the file libraries/msdos/README for build instructions)
MS-Windows 3.x O - - - -
(see the file libraries/msdos/README.WSA for build instructions)
MS-Win NT & 95 O ? ? ? ?
VMS X S X X ?
(see the file libraries/vms/README.VMS for build instructions)
** Hints on Porting LDAP to a New Platform
If your platform is not listed here, you will need to do a port. The
place to start for Unix systems is by creating a new directory under
the LDAP build/platforms directory and creating an appropriate
Make-platform file. It is probably easiest to start by duplicating a
directory there that is for a platform similar to yours.
Variables commonly set in the Make-platform files include:
CC - compiler to use, e.g. CC=cc or CC=gcc
PLATFORMCFLAGS - flags added to every compile
PLATFORMLDFLAGS - flags added to every link
PLATFORMLIBS - extra libraries needed (added to the end of all link commands)
LDBMLIB - ndbm library, needed if not in libc (e.g. LDBMLIB=-lndbm)
NEEDUNPROTO=yes - set if your compiler doesn't understand prototypes; see the
sunos4-cc and hpux-cc files for example usage
INSTALL - BSD-like install command; if necessary, you can use a script
we provide: INSTALL=$(LDAPSRC)/build/install.sh
RANLIB - command to convert libraries for efficient random access;
if your system has no ranlib, use RANLIB = ""
other commands - see the file build/Make-append for a list
You will also need to modify the top-level LDAP Makefile .make-platform
rule to know about your platform. Finally, you should look through the
include/portable.h file and make any necessary adjustments.
Please send changes via e-mail to: ldap-support@umich.edu so they can be
incorporated into future releases.

3
build/README-unproto Normal file
View File

@ -0,0 +1,3 @@
The unproto code was obtained from:
ftp://ftp.win.tue.nl/pub/unix/unproto5.shar.Z

158
build/db.1.85.patch Normal file
View File

@ -0,0 +1,158 @@
*** ./hash/hash.h.bak Fri May 12 11:00:42 1995
--- ./hash/hash.h Fri May 12 11:01:07 1995
***************
*** 103,109 ****
BUFHEAD *cpage; /* Current page */
int cbucket; /* Current bucket */
int cndx; /* Index of next item on cpage */
! int errno; /* Error Number -- for DBM
* compatability */
int new_file; /* Indicates if fd is backing store
* or no */
--- 103,109 ----
BUFHEAD *cpage; /* Current page */
int cbucket; /* Current bucket */
int cndx; /* Index of next item on cpage */
! int h_errno; /* Error Number -- for DBM
* compatability */
int new_file; /* Indicates if fd is backing store
* or no */
*** ./hash/hash.c.bak Fri May 12 11:02:03 1995
--- ./hash/hash.c Fri May 12 11:02:42 1995
***************
*** 505,511 ****
else
if (wsize != sizeof(HASHHDR)) {
errno = EFTYPE;
! hashp->errno = errno;
return (-1);
}
for (i = 0; i < NCACHED; i++)
--- 505,511 ----
else
if (wsize != sizeof(HASHHDR)) {
errno = EFTYPE;
! hashp->h_errno = errno;
return (-1);
}
for (i = 0; i < NCACHED; i++)
***************
*** 536,542 ****
hashp = (HTAB *)dbp->internal;
if (flag) {
! hashp->errno = errno = EINVAL;
return (ERROR);
}
return (hash_access(hashp, HASH_GET, (DBT *)key, data));
--- 536,542 ----
hashp = (HTAB *)dbp->internal;
if (flag) {
! hashp->h_errno = errno = EINVAL;
return (ERROR);
}
return (hash_access(hashp, HASH_GET, (DBT *)key, data));
***************
*** 553,563 ****
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_NOOVERWRITE) {
! hashp->errno = errno = EINVAL;
return (ERROR);
}
if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
! hashp->errno = errno = EPERM;
return (ERROR);
}
return (hash_access(hashp, flag == R_NOOVERWRITE ?
--- 553,563 ----
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_NOOVERWRITE) {
! hashp->h_errno = errno = EINVAL;
return (ERROR);
}
if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
! hashp->h_errno = errno = EPERM;
return (ERROR);
}
return (hash_access(hashp, flag == R_NOOVERWRITE ?
***************
*** 574,584 ****
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_CURSOR) {
! hashp->errno = errno = EINVAL;
return (ERROR);
}
if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
! hashp->errno = errno = EPERM;
return (ERROR);
}
return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
--- 574,584 ----
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_CURSOR) {
! hashp->h_errno = errno = EINVAL;
return (ERROR);
}
if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
! hashp->h_errno = errno = EPERM;
return (ERROR);
}
return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
***************
*** 729,735 ****
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_FIRST && flag != R_NEXT) {
! hashp->errno = errno = EINVAL;
return (ERROR);
}
#ifdef HASH_STATISTICS
--- 729,735 ----
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_FIRST && flag != R_NEXT) {
! hashp->h_errno = errno = EINVAL;
return (ERROR);
}
#ifdef HASH_STATISTICS
*** ./hash/ndbm.c.bak Fri May 12 11:02:06 1995
--- ./hash/ndbm.c Fri May 12 11:02:54 1995
***************
*** 180,186 ****
HTAB *hp;
hp = (HTAB *)db->internal;
! return (hp->errno);
}
extern int
--- 180,186 ----
HTAB *hp;
hp = (HTAB *)db->internal;
! return (hp->h_errno);
}
extern int
***************
*** 190,196 ****
HTAB *hp;
hp = (HTAB *)db->internal;
! hp->errno = 0;
return (0);
}
--- 190,196 ----
HTAB *hp;
hp = (HTAB *)db->internal;
! hp->h_errno = 0;
return (0);
}

45
build/install.sh Executable file
View File

@ -0,0 +1,45 @@
#!/bin/sh
# simple BSD-like install replacement
#
# Copyright (c) 1994 The Regents of the University of Michigan
#
MODE=0755
USAGE="usage: $0 [-c] [-m mode] file dir"
while [ $# != 0 ]; do
case "$1" in
-c)
;;
-m)
MODE=$2
shift
;;
-*)
echo "$USAGE"
exit 1
;;
*)
break
;;
esac
shift
done
if [ $# != 2 ]; then
echo "$USAGE"
exit 1
fi
FILE=$1
DIR=$2
cp $FILE $DIR
if [ -d $DIR ]; then
chmod $MODE $DIR/`basename $FILE`
else
#
# DIR is really the destination file
#
chmod $MODE $DIR
fi

133
build/mkdep Executable file
View File

@ -0,0 +1,133 @@
#!/bin/sh -
#
# Copyright (c) 1987 Regents of the University of California.
# All rights reserved.
#
# Redistribution and use in source and binary forms are permitted
# provided that the above copyright notice and this paragraph are
# duplicated in all such forms and that any documentation,
# advertising materials, and other materials related to such
# distribution and use acknowledge that the software was developed
# by the University of California, Berkeley. 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'' AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# @(#)mkdep.sh 5.12 (Berkeley) 6/30/88
#
# We now use whatever path is already set by the invoker
#PATH=/bin:/usr/bin:/usr/ucb
#export PATH
set -e # exit immediately if any errors occur
MAKE=Makefile # default makefile name is "Makefile"
NOSLASH="no" # by default, / dependencies are included
CC=cc # default compiler is cc
while :
do case "$1" in
# -f allows you to select a makefile name
-f)
MAKE=$2
shift; shift ;;
# -c allows you to select a compiler to use (default is cc)
-c)
CC=$2
shift; shift ;;
# the -p flag produces "program: program.c" style dependencies
# so .o's don't get produced
-p)
SED='s;\.o;;'
shift ;;
# the -s flag removes dependencies to files that begin with /
-s)
NOSLASH=yes;
shift ;;
# -*) shift ;;
*)
break ;;
esac
done
if [ $# = 0 ] ; then
echo 'usage: mkdep [-p] [-f makefile] [flags] file ...'
exit 1
fi
if [ ! -w $MAKE ]; then
echo "mkdep: no writeable file \"$MAKE\""
exit 1
fi
TMP=/tmp/mkdep$$
trap 'rm -f $TMP ; exit 1' 1 2 3 13 15
cp $MAKE ${MAKE}.bak
sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $TMP
cat << _EOF_ >> $TMP
# DO NOT DELETE THIS LINE -- mkdep uses it.
# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
_EOF_
# If your compiler doesn't have -M, add it. If you can't, the next two
# lines will try and replace the "cc -M". The real problem is that this
# hack can't deal with anything that requires a search path, and doesn't
# even try for anything using bracket (<>) syntax.
#
# egrep '^#include[ ]*".*"' /dev/null $* |
# sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' |
$CC -M $* |
sed "
s; \./; ;g
$SED" |
awk '
$1 ~ /:/ {
filenm=$1
dep=$2
}
$1 !~ /:/ {
dep=$1
}
/.*/ {
if ( noslash = "yes" && dep ~ /^\// ) next
if (filenm != prev) {
if (rec != "")
print rec;
rec = filenm " " dep;
prev = filenm;
}
else {
if (length(rec dep) > 78) {
print rec;
rec = filenm " " dep;
}
else
rec = rec " " dep
}
}
END {
print rec
}' noslash="$NOSLASH" >> $TMP
cat << _EOF_ >> $TMP
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
_EOF_
# copy to preserve permissions
cp $TMP $MAKE
rm -f ${MAKE}.bak $TMP
exit 0

View File

@ -0,0 +1,68 @@
#
# You should NOT need to edit this file at all: if you just type make
# in this directory, LDAP will be built for this platform using this
# compiler. If you type make links a build area will be created for
# you under ./obj. You should # cd in there and edit the Make-common file
# before building. See the LDAP INSTALL file for more information.
#
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# LDAP lightweight X.500 Directory access platform setup makefile
#
#-----------------------------------------------------------------------------
#
############################################################################
# #
# You should not have to edit anything in this file #
# #
############################################################################
LN=ln -s
RM=rm -f
SED=sed
PWD=pwd
LDAPSRC= ../../..
all: platform
( cd $(LDAPSRC); $(MAKE) $(MFLAGS) )
install: platform
( cd $(LDAPSRC); $(MAKE) $(MFLAGS) install )
platform: FORCE
@PWD=`$(PWD)`; \
PLATFORMCC=`basename $$PWD`; \
PLATFORM=`echo $$PLATFORMCC | $(SED) 's/-.*$$//'`; \
CC=`echo $$PLATFORMCC | $(SED) 's/^.*-//'`; \
echo "** Setting platform to $$PLATFORM and compiler $$CC"; \
( cd $(LDAPSRC); \
$(RM) .make-platform; \
$(LN) build/platforms/$$PLATFORMCC/Make-platform .make-platform )
links: FORCE
@PWD=`$(PWD)`; \
PLATFORMCC=`basename $$PWD`; \
DEST=./obj-$$PLATFORMCC; \
PLATFORM=`echo $$PLATFORMCC | $(SED) 's/-.*$$//'`; \
CC=`echo $$PLATFORMCC | $(SED) 's/^.*-//'`; \
echo "** Setting platform to $$PLATFORM and compiler $$CC"; \
( cd $(LDAPSRC); $(MAKE) $(MFLAGS) DEST=$$DEST links; \
cd $$DEST; \
$(LN) .src/build/platforms/$$PLATFORMCC/Make-platform .make-platform ); \
$(LN) $(LDAPSRC)/$$DEST .
clean: FORCE
veryclean:
-$(RM) -r ./obj-*
FORCE:

46
build/platforms/Makefile Normal file
View File

@ -0,0 +1,46 @@
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# LDAP build/platforms Makefile
#
#-----------------------------------------------------------------------------
############################################################################
# #
# You should not have to edit anything below this point #
# #
############################################################################
all: FORCE
install: FORCE
clean: FORCE
@echo "making clean in `pwd`"
@for i in *; do \
if [ -d $$i -a $$i != "RCS" ]; then \
echo; echo " cd $$i; $(MAKE) $(MFLAGS) clean"; \
( cd $$i; $(MAKE) $(MFLAGS) clean ); \
fi; \
done
veryclean: FORCE
@echo "making veryclean in `pwd`"
@for i in *; do \
if [ -d $$i -a $$i != "RCS" ]; then \
echo; echo " cd $$i; $(MAKE) $(MFLAGS) veryclean"; \
( cd $$i; $(MAKE) $(MFLAGS) veryclean ); \
fi; \
done
FORCE:

View File

@ -0,0 +1,18 @@
#
# LDAP AIX standard cc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
# install with BSD semantics
INSTALL=/usr/ucb/install
PLATFORMCFLAGS= -Daix

View File

@ -0,0 +1,19 @@
#
# LDAP AIX standard cc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
CC = gcc
# install with BSD commandline
INSTALL=/usr/ucb/install
PLATFORMCFLAGS= -Daix

View File

@ -0,0 +1,16 @@
#
# LDAP FreeBSD GNU C Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
CC = gcc
PLATFORMCFLAGS= -Dfreebsd

View File

@ -0,0 +1,27 @@
#
# HP-UX optional c89 Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
CC=c89
# ranlib not needed under HP-UX
RANLIB = ""
# install under HP-UX is not like on BSD systems, so we use our own script
INSTALL=$(LDAPSRC)/build/install.sh
# we need to link a separate library to get ndbm routines under HP/UX
LDBMLIB=-lndbm
# we need to link in the V3 library to get sigset()
PLATFORMLIBS= -lV3
PLATFORMCFLAGS= -Dhpux -Aa -D_HPUX_SOURCE

View File

@ -0,0 +1,33 @@
#
# LDAP HP-UX standard cc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
# ranlib not needed under HP-UX
RANLIB = ""
# install under HP-UX is not like on BSD systems, so we use our own script
INSTALL=$(LDAPSRC)/build/install.sh
# we need to link a separate library to get ndbm routines under HP/UX
LDBMLIB=-lndbm
PLATFORMCFLAGS= -Dhpux
# we need to link in the V3 library to get sigset()
PLATFORMLIBS= -lV3
#
# the HP-UX cc compiler doesn't understand function prototypes, so we
# need the unproto preprocessor
#
NEEDUNPROTO=yes
UNPROTOCFLAGS=-tp,$(LDAPSRC)/build/unproto/cpp

View File

@ -0,0 +1,28 @@
#
# LDAP HP-UX gcc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
CC=gcc
# ranlib not needed under HP-UX
RANLIB = ""
# install under HP-UX is not like on BSD systems, so we use our own script
INSTALL=$(LDAPSRC)/build/install.sh
# we need to link a separate library to get ndbm routines under HP/UX
LDBMLIB=-lndbm
# we need to link in the V3 library to get sigset()
PLATFORMLIBS= -lV3
PLATFORMCFLAGS= -Dhpux

View File

@ -0,0 +1,29 @@
#
# LDAP IRIX standard cc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
# ranlib not needed under IRIX
RANLIB = ""
# be explicit about which CC to use
CC=cc
# give full path to hostname since it may not be in user's path
HOSTNAME=/usr/bsd/hostname
# don't count on a BSD install being present or first in path
INSTALL=$(LDAPSRC)/build/install.sh
PLATFORMCFLAGS=-DUSE_WAITPID
PLATFORMLIBS=
THREADS=
THREADSLIB=

View File

@ -0,0 +1,29 @@
#
# LDAP IRIX standard cc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
# ranlib not needed under IRIX
RANLIB = ""
# be explicit about which CC to use
CC=gcc
# give full path to hostname since it may not be in user's path
HOSTNAME=/usr/bsd/hostname
# don't count on a BSD install being present or first in path
INSTALL=$(LDAPSRC)/build/install.sh
PLATFORMCFLAGS=-DUSE_WAITPID
PLATFORMLIBS=
THREADS=
THREADSLIB=

View File

@ -0,0 +1,17 @@
#
# LDAP Linux GNU C Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
CC = gcc
RANLIB = "ranlib"
PLATFORMCFLAGS= -Dlinux

View File

@ -0,0 +1,34 @@
#
# LDAP SVR4 standard cc Make-platform file
#
# Uses the std SVR4 stuff whenever possible.
# Some references to the BSD compatibility required.
#
#
# add any platform-specific overrides below here
#
# compiler to use, e.g. CC=cc or CC=gcc
CC = cc
# flags added to every compile
# Use the BSD include files but only after the SVR4 files.
PLATFORMCFLAGS= -DSYSV -DSVR4 -I/usr/include -I/usr/ucbinclude
# flags added to every link
PLATFORMLDFLAGS =
# extra libraries needed (added to the end of all link commands)
PLATFORMLIBS = -lnsl -lnet -lsocket
# ndbm library, needed if not in libc (e.g. LDBMLIB=-lndbm)
LDBMLIB = -L/usr/ucblib -lucb
# BSD-like install command; if necessary, you can use a script
INSTALL = /usr/ucb/install
# command to convert libraries for efficient random access;
RANLIB = ""
# other commands - see the file build/Make-append for a list

View File

@ -0,0 +1,17 @@
#
# LDAP NetBSD cc Make-platform file
# on NetBSD, cc is gcc
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
CC = gcc
PLATFORMCFLAGS= -Dnetbsd

View File

@ -0,0 +1,16 @@
#
# LDAP NetBSD GNU C Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
CC = gcc
PLATFORMCFLAGS= -Dnetbsd

View File

@ -0,0 +1,15 @@
#
# LDAP NeXTSTEP cc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
PLATFORMCFLAGS= -Dnextstep
PLATFORMLDFLAGS= -all_load

View File

@ -0,0 +1,24 @@
#
# LDAP OSF1 standard cc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
# Even though prototypes are supported by the compiler, OSF's CC doesn't
# seem to define __STDC__ so we explicitly defined NEEDPROTOS here.
PLATFORMCFLAGS= -Dosf1 -DNEEDPROTOS
PLATFORMLDFLAGS=
THREADS= -DTHREAD_DCE_PTHREADS
THREADSLIB= -lpthreads
# the BSD-like install under OSF/1 is called installbsd
INSTALL=installbsd

View File

@ -0,0 +1,23 @@
#
# LDAP SCO standard cc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
# ranlib not needed under SCO
RANLIB = ""
# be explicit about which CC to use
CC=/bin/cc
# don't count on /usr/ucb/install being present or first in path
INSTALL=$(LDAPSRC)/build/install.sh
PLATFORMCFLAGS= -DSCO -DNEED_BSDREGEX -DSYSV -DNOTERMCAP
PLATFORMLIBS= -lsocket -lnsl_s

View File

@ -0,0 +1,22 @@
#
# LDAP SCO gcc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
# ranlib not needed under SCO
RANLIB = ""
CC=gcc
# don't count on /usr/ucb/install being present or first in path
INSTALL=$(LDAPSRC)/build/install.sh
PLATFORMCFLAGS= -DSCO -DNEED_BSDREGEX -DSYSV -DNOTERMCAP
PLATFORMLIBS= -lsocket -lnsl_s

View File

@ -0,0 +1,25 @@
#
# LDAP SunOS standard cc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
5LINT = /usr/5bin/lint
PLATFORMCFLAGS= -Dsunos4
THREADS= -DTHREAD_SUNOS4_LWP
THREADSLIB=-llwp
#
# the SunOS 4 cc compiler doesn't understand function prototypes, so we
# need the unproto preprocessor
#
NEEDUNPROTO=yes
UNPROTOCFLAGS=-Qpath $(LDAPSRC)/build/unproto

View File

@ -0,0 +1,19 @@
#
# LDAP SunOS GNU C Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
CC = gcc
5LINT = /usr/5bin/lint
PLATFORMCFLAGS= -Dsunos4
THREADS= -DTHREAD_SUNOS4_LWP
THREADSLIB=-llwp

View File

@ -0,0 +1,29 @@
#
# LDAP SunOS5 standard cc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
# ranlib not needed under SunOS5
RANLIB = ""
# be explicit about which CC to use
CC=cc
# give full path to hostname since it may not be in user's path
HOSTNAME=/usr/ucb/hostname
# don't count on /usr/ucb/install being present or first in path
INSTALL=$(LDAPSRC)/build/install.sh
PLATFORMCFLAGS= -Dsunos5 -D_REENTRANT
PLATFORMLIBS= -lsocket -lnsl -lgen
THREADS= -DTHREAD_SUNOS5_LWP
THREADSLIB=-lthread

View File

@ -0,0 +1,28 @@
#
# LDAP SunOS5 GNU C Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
CC = gcc
# ranlib not needed under SunOS5
RANLIB = ""
# give full path to hostname since it may not be in user's path
HOSTNAME=/usr/ucb/hostname
# don't count on /usr/ucb/install being present or first in path
INSTALL=$(LDAPSRC)/build/install.sh
PLATFORMCFLAGS= -Dsunos5 -D_REENTRANT
PLATFORMLIBS= -lsocket -lnsl -lgen
THREADS= -DTHREAD_SUNOS5_LWP
THREADSLIB=-lthread

View File

@ -0,0 +1,16 @@
#
# LDAP Ultrix standard cc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
PLATFORMCFLAGS= -Dultrix -YSYSTEM_FIVE
PLATFORMLDFLAGS= -YSYSTEM_FIVE

View File

@ -0,0 +1,16 @@
#
# LDAP Ultrix standard gcc Make-platform file
#
#
# add any platform-specific overrides below here
#
#
# -------------------------------------------------------------------------
# you will probably not need to edit anything below this point
# -------------------------------------------------------------------------
CC= gcc
PLATFORMCFLAGS= -Dultrix

View File

@ -0,0 +1,31 @@
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# LDAP build/platforms/vms Makefile (do nothing)
#
#-----------------------------------------------------------------------------
#
############################################################################
# #
# You should not have to edit anything in this file #
# #
############################################################################
LDAPSRC= ../../..
all: FORCE
links: FORCE
clean: FORCE
veryclean: FORCE
FORCE:

View File

@ -0,0 +1,95 @@
$! 30-Nov-1995 ldap V3.2 Craig Watkins Innosoft International, Inc.
$!
$! This is a crude make procedure to build the ldap libraries and the test
$! program. This should work with DECC or VAXC compilers.
$!
$! This links with UCX libraries so that it should work on any TCP/IP
$! package that has UCX emulation. This has been tested with MultiNet.
$! You may have to change the LINK to find your copy of UCX$IPC.OLB.
$!
$ ARCH = "VAX"
$ if f$getsyi("hw_model") .GE. 1024 then ARCH = "ALPHA"
$ !
$ ! If we are on an alpha/axp, we need to use DECC -- otherwise, your choice
$ COMPILER = "VAXC"
$ if ARCH .eqs. "ALPHA" then COMPILER = "DECC"
$ !
$ if COMPILER .eqs. "VAXC"
$ then
$ define arpa sys$library:
$ define sys sys$library:
$ define netinet sys$library:
$! This assumes your default compiler is VAXC; if not, add /VAXC below
$ cc_switches = "/include=([---.include],[---.libraries.vms])/define=(LDAP_DEBUG,CLDAP,LDAP_REFERRALS,STR_TRANSLATION,LDAP_CHARSET_8859=88591)"
$!
$ else
$!
$ cc_switches = "/decc/standard=vaxc/include=([---.include],[---.libraries.vms])/define=(__STDC__,LDAP_DEBUG,CLDAP,LDAP_REFERRALS,STR_TRANSLATION,LDAP_CHARSET_8859=88591)
$ endif
$ !
$ cc 'CC_SWITCHES' 'P1' [---.libraries.liblber]io
$ cc 'CC_SWITCHES' 'P1' [---.libraries.liblber]encode
$ cc 'CC_SWITCHES' 'P1' [---.libraries.liblber]decode
$ cc 'CC_SWITCHES' 'P1' [---.libraries.liblber]version
$ !
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]ABANDON
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]ADD
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]ADDENTRY
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]BIND
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]CACHE
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]CHARSET
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]CLDAP
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]COMPARE
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]DELETE
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]DISPTMPL
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]DSPARSE
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]ERROR
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]FREE
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]FRIENDLY
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]GETATTR
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]GETDN
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]GETDXBYNAME
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]GETENTRY
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]GETFILTER
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]GETVALUES
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]KBIND
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]MODIFY
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]MODRDN
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]OPEN
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]OS-IP
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]REGEX
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]REQUEST
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]RESULT
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]SBIND
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]SEARCH
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]SORT
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]SRCHPREF
$ cc 'CC_SWITCHES' 'P1' /define="TEMPLATEFILE=""LDAP_ETC:ldaptemplates.conf""" -
[---.libraries.libldap]TMPLOUT
$!CC 'CC_SWITCHES' 'P1' [---.libraries.libldap]TMPLTEST
$ cc 'CC_SWITCHES' 'P1' /define="FILTERFILE=""LDAP_ETC:ldapfilter.conf""" -
[---.libraries.libldap]UFN
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]UNBIND
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]VERSION
$ !
$ cc 'CC_SWITCHES' 'P1' [---.libraries.vms]getopt
$ cc 'CC_SWITCHES' 'P1' [---.libraries.vms]strings
$ !
$ library/create/log ldap.olb *.obj
$ !
$ cc 'CC_SWITCHES' 'P1' [---.libraries.libldap]TEST
$ !
$ if COMPILER .eqs. "VAXC"
$ then
$!
$ link test, sys$input/opt
ldap.olb/lib
sys$library:ucx$ipc.olb/lib
sys$share:vaxcrtl.exe/share
$!
$ else
$!
$ link test, sys$input/opt
ldap.olb/lib
$ endif
$!

109
build/uname.sh Normal file
View File

@ -0,0 +1,109 @@
#!/bin/sh
# simple BSD-like uname replacement for those systems without it
#
# Copyright (c) 1995 The Regents of the University of Michigan
#
#
# if /bin/uname or /usr/bin/uname exists, just use it
# ...unless we are on SCO, where the provided uname is bad
#
if [ ! -f /usr/bin/swconfig ]; then
if [ -f /bin/uname ]; then
exec /bin/uname $*
fi
if [ -f /usr/bin/uname ]; then
exec /usr/bin/uname $*
fi
fi
#
# flags to keep track of what to output
#
PRINT_SYSTEM=0
PRINT_VERSION=0
PRINT_RELEASE=0
#
# process arguments
#
USAGE="usage: $0 [-s] [-v] [-r]"
while [ $# != 0 ]; do
case "$1" in
-s)
PRINT_SYSTEM=1
;;
-v)
PRINT_VERSION=1
;;
-r)
PRINT_RELEASE=1
;;
*)
echo "$USAGE"
exit 1
;;
esac
shift
done
#
# print system name by default
#
if [ $PRINT_VERSION = "0" -a $PRINT_RELEASE = "0" ]; then
PRINT_SYSTEM=1
fi
#
# default to unknown everything...
#
SYSTEM="Unknown-System"
VERSION="Unknown-Version"
RELEASE="Unknown-Release"
#
# check to see if we are on a machine that runs NextSTEP or SCO
#
if [ -r /NextApps ]; then
SYSTEM="NeXTSTEP"
elif [ -f /usr/bin/swconfig ]; then
SYSTEM="SCO"
fi
#
# output requested information
#
OUTPUT=0
if [ $PRINT_SYSTEM = "1" ]; then
echo -n "$SYSTEM"
OUTPUT=1
fi
if [ $PRINT_VERSION = "1" ]; then
if [ $OUTPUT = "1" ]; then
echo -n " $VERSION"
else
echo -n "$VERSION"
OUTPUT=1
fi
fi
if [ $PRINT_RELEASE = "1" ]; then
if [ $OUTPUT = "1" ]; then
echo -n " $RELEASE"
else
echo -n "$RELEASE"
OUTPUT=1
fi
fi
echo
exit 0

123
build/unproto/Makefile Normal file
View File

@ -0,0 +1,123 @@
# @(#) Makefile 1.6 93/06/18 22:29:40
## BEGIN CONFIGURATION STUFF
# In the unlikely case that your compiler has no hooks for alternate
# compiler passes, use a "cc cflags -E file.c | unproto >file.i"
# pipeline, then "cc cflags -c file.i" to compile the resulting
# intermediate file.
#
# Otherwise, the "/lib/cpp | unproto" pipeline can be packaged as an
# executable shell script (see the provided "cpp.sh" script) that should
# be installed as "/whatever/cpp". This script should then be specified
# to the C compiler as a non-default preprocessor.
#
# PROG = unproto
# PIPE =
# The overhead and problems of shell script interpretation can be
# eliminated by having the unprototyper program itself open the pipe to
# the preprocessor. In that case, define the PIPE_THROUGH_CPP macro as
# the path name of the default C preprocessor (usually "/lib/cpp"),
# install the unprototyper as "/whatever/cpp" and specify that to the C
# compiler as a non-default preprocessor.
#
PROG = cpp
PIPE = -DPIPE_THROUGH_CPP=\"/lib/cpp\"
# Some compilers complain about some #directives. The following is only a
# partial solution, because the directives are still seen by /lib/cpp.
# Be careful with filtering out #pragma, because some pre-ANSI compilers
# (SunOS) rely on its use.
#
# SKIP = -DIGNORE_DIRECTIVES=\"pragma\",\"foo\",\"bar\"
#
SKIP =
# The bell character code depends on the character set. With ASCII, it is
# 7. Specify a string constant with exactly three octal digits. If you
# change this definition, you will have to update the example.out file.
#
BELL = -DBELL=\"007\"
# Some C compilers have problems with "void". The nature of the problems
# depends on the age of the compiler.
#
# If your compiler does not understand "void" at all, compile with
# -DMAP_VOID. The unprototyper will replace "void *" by "char *", a
# (void) argument list by an empty one, and will replace all other
# instances of "void" by "int".
#
# If your compiler has problems with "void *" only, compile with
# -DMAP_VOID_STAR. The unprototyper will replace "void *" by "char *",
# and will replace a (void) argument list by an empty one. All other
# instances of "void" will be left alone.
#
# If neither of these are defined, (void) argument lists will be replaced
# by empty ones.
#
# MAP = -DMAP_VOID_STAR
# Now that we have brought up the subject of antique C compilers, here's
# a couple of aliases that may be useful, too.
#
# ALIAS = -Dstrchr=index
# If you need support for functions that implement ANSI-style variable
# length argument lists, edit the stdarg.h file provided with this
# package so that it contains the proper definitions for your machine.
## END CONFIGURATION STUFF
SHELL = /bin/sh
CFILES = unproto.c tok_io.c tok_class.c tok_pool.c vstring.c symbol.c error.c \
hash.c strsave.c
HFILES = error.h token.h vstring.h symbol.h
SCRIPTS = cpp.sh acc.sh
SAMPLES = stdarg.h stddef.h stdlib.h varargs.c example.c example.out
SOURCES = README $(CFILES) $(HFILES) Makefile $(SCRIPTS) $(SAMPLES)
FILES = $(SOURCES) unproto.1
OBJECTS = tok_io.o tok_class.o tok_pool.o unproto.o vstring.o symbol.o error.o \
hash.o strsave.o
CFLAGS = -O $(PIPE) $(SKIP) $(BELL) $(MAP) $(ALIAS)
#CFLAGS = -O $(PIPE) $(SKIP) $(BELL) $(MAP) $(ALIAS) -p -Dstatic=
#CFLAGS = -g $(PIPE) $(SKIP) $(BELL) $(MAP) $(ALIAS) -DDEBUG
$(PROG): $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $(OBJECTS) $(MALLOC)
# For linting, enable all bells and whistles.
lint:
lint -DPIPE_THROUGH_CPP=\"foo\" -DIGNORE_DIRECTIVES=\"foo\",\"bar\" \
$(BELL) -DMAP_VOID $(ALIAS) $(CFILES)
# Testing requires that the program is compiled with -DDEBUG.
test: $(PROG) cpp example.c example.out
./cpp example.c >example.tmp
@echo the following diff command should produce no output
diff -b example.out example.tmp
rm -f example.tmp
shar: $(FILES)
@shar $(FILES)
archive:
$(ARCHIVE) $(SOURCES)
clean:
rm -f *.o core cpp unproto mon.out varargs.o varargs example.tmp
error.o : error.c token.h error.h Makefile
hash.o : hash.c Makefile
strsave.o : strsave.c error.h Makefile
symbol.o : symbol.c error.h token.h symbol.h Makefile
tok_class.o : tok_class.c error.h vstring.h token.h symbol.h Makefile
tok_io.o : tok_io.c token.h vstring.h error.h Makefile
tok_pool.o : tok_pool.c token.h vstring.h error.h Makefile
unproto.o : unproto.c vstring.h stdarg.h token.h error.h symbol.h Makefile
varargs.o : varargs.c stdarg.h Makefile
vstring.o : vstring.c vstring.h Makefile

160
build/unproto/README Normal file
View File

@ -0,0 +1,160 @@
@(#) README 1.6 93/06/18 22:29:34
unproto - Compile ANSI C with traditional UNIX C compiler
Description:
------------
This is a filter that sits in between the UNIX C preprocessor and the
next UNIX C compiler stage, on the fly transforming ANSI C syntax to
old C syntax. Line number information is preserved so that compiler
diagnostics still make sense. It runs at roughly the same speed as
/lib/cpp, so it has negligible impact on compilation time.
Typically, the program is invoked by the native UNIX C compiler as an
alternate preprocessor. The unprototyper in turn invokes the native C
preprocessor and massages its output. Similar tricks can be used with
the lint(1) command. Details are given below.
The filter rewrites ANSI-style function headings, function pointer
types and type casts, function prototypes, and combinations thereof.
Unlike some other unprototypers, this one is fully recursive and does
not depend on source file layout (see the example.c file).
Besides the rewriting of argument lists, the program does the following
transformations: string concatenation, conversion of \a and \x escape
sequences to their octal equivalents, translation of the __TIME__ and
__DATE__ macros, optional mapping of `void *' to `char *', and optional
mapping of plain `void' to `int'.
The unprototyper provides hooks for compilers that require special
tricks for variadic functions (fortunately, many don't). <stdarg.h>
support is provided for sparc, mips, mc68k, 80x86, vax, and others.
The program has been tested with SunOS 4.1.1 (sparc), Ultrix 4.0 and
4.2 (mips), and Microport System V Release 2 (80286). It should work
with almost every PCC-based UNIX C compiler.
Restrictions:
-------------
A description of restrictions and workarounds can be found in the
unproto.1 manual page.
Problems fixed with this release:
---------------------------------
Prototypes and definitions of functions returning pointer to function
were not rewritten to old style.
Operation:
----------
This package implements a non-default C preprocessor (the output from
the default C preprocessor being piped through the unprototyper). How
one tells the C compiler to use a non-default preprocessor program is
somewhat compiler-dependent:
SunOS 4.x: cc -Qpath directory_with_alternate_cpp ...
Ultrix 4.x: cc -tp -hdirectory_with_alternate_cpp -B ...
System V.2: cc -Bdirectory_with_alternate_cpp/ -tp ...
Examples of these, and others, can be found in the acc.sh shell script
that emulates an ANSI C compiler. Your C compiler manual page should
provide the necessary information.
A more portable, but less efficient, approach relies on the observation
that almost every UNIX C compiler supports the -E (write preprocessor
output to stdout) and -P options (preprocess file.c into file.i). Just
add the following lines to your Makefiles:
.c.o:
$(CC) $(CFLAGS) -E $*.c | unproto >$*.i # simulate -P option
$(CC) $(CFLAGS) -c $*.i
rm -f $*.i
On some systems the lint(1) command is just a shell script, and writing
a version that uses the unprototyper should not be too hard. With SunOS
4.x, /usr/bin/lint is not a shell script, but it does accept the same
syntax as the cc(1) command for the specification of a non-default
compiler pass.
You may have to do some research on the lint command provided with your
own machine.
Configuration:
--------------
Check the contents of the `stdarg.h' file provided with this package.
This file serves a dual purpose: (1) on systems that do not provide a
stdarg.h file, it should be included by C source files that implements
ANSI-style variadic functions; (2) it is also used to configure the
unprototyper so that it emits the proper magic when it sees `...'.
The `stdarg.h' file has support for sparc, mips, and for compilers that
pass arguments via the stack (typical for 80*86, mc68k and vax). It
gives general hints for other compilers.
The other sample header files (stddef.h and stdlib.h) are not required
to build the unprototyper.
The `varargs.c' file provided with this package can be used to verify
that the `stdarg.h' file has been set up correctly.
If your C compiler has no hooks for an alternate preprocessor (the
unprototyper will be used as: `cc cflags -E file.c | unproto >file.i'),
build the `unproto' executable without the `PIPE_THROUGH_CPP' feature.
Details are given in the Makefile.
Otherwise, the `cpp.sh' shell script can be used to set up the pipe
between the native C preprocessor and the unprototyper command. The
script assumes that the unprototyper binary is called `unproto', and
that it was compiled without the `PIPE_THROUGH_CPP' feature. See the
Makefile and the `cpp.sh' script for details and for a description of
possible problems with this approach.
The overhead and problems of shell-script interpretation can be avoided
by letting the unprototyper itself pipe its standard input through the
C preprocessor. For this mode of operation, the unprototyper binary
should be called `cpp', and the `unproto.c' source file should be
compiled with the `PIPE_THROUGH_CPP' macro defined as the absolute
pathname of the native C preprocessor (usually `/lib/cpp'). See the
Makefile for details.
Installation:
-------------
Install the `unproto.1' manual page in a suitable place. If your system
does not provide a `stdarg.h' file, find a suitable place for the one
provided with the unprototyper and install it there. The same goes for
the sample stddef.h and stdlib.h files; make sure that the definitions
in there apply to your environment. Most or all of the latter files are
already part of Ultrix 4.x and SunOS 4.1.1.
The ANSI float.h and limits.h files can be generated with the config
program by Steve Pemberton (comp.sources.misc volume 10, issue 62,
available from ftp.uu.net as comp.sources.misc/volume10/config42.Z).
If you run the unprototyper with "cc -E" just install the `unproto'
binary; the `cpp' and `acc' shell scripts will not be needed.
If you use the `cpp' shell script to pipe the preprocessor output
through the unprototyper program, install the `unproto' binary in a
place where the `cpp' shell script can find it, and install the `cpp'
shell script in a suitable place. Edit the `acc' shell script and
install it in a suitable place. From now on, type `acc' instead of
`cc'.
If the unprototyper itself opens the pipe to the C preprocessor (i.e.
the unprototyper was built with the `PIPE_THROUGH_CPP' macro defined),
install the `cpp' unprototyper binary in a suitable place. Edit the
`acc' shell script and install it in a suitable place. From now on,
type `acc' instead of `cc'.
Wietse Venema
wietse@wzv.win.tue.nl
Mathematics and Computing Science
Eindhoven University of Technology
The Netherlands

35
build/unproto/acc.sh Executable file
View File

@ -0,0 +1,35 @@
#!/bin/sh
# @(#) acc.sh 1.1 93/06/18 22:29:42
#
# Script to emulate most of an ANSI C compiler with a traditional UNIX
# C compiler.
# INCDIR should be the directory with auxiliary include files from the
# unproto source distribution (stdarg.h, stdlib.h, stddef.h, and other
# stuff that is missing from your compilation environment). With Ultrix
# 4.[0-2] you need unproto's stdarg.h even though the system provides
# one.
#
INCDIR=.
# CPPDIR should be the directory with the unprototypeing cpp filter
# (preferably the version with the PIPE_THROUGH_CPP feature).
#
CPPDIR=.
# DEFINES: you will want to define volatile and const, and maybe even
# __STDC__.
#
DEFINES="-Dvolatile= -Dconst= -D__STDC__"
# Possible problem: INCDIR should be listed after the user-specified -I
# command-line options, not before them as we do here. This is a problem
# only if you attempt to redefine system libraries.
#
# Choose one of the commands below that is appropriate for your system.
#
exec cc -Qpath ${CPPDIR} -I${INCDIR} ${DEFINES} "$@" # SunOS 4.x
exec cc -tp -h${CPPDIR} -B -I${INCDIR} ${DEFINES} "$@" # Ultrix 4.2
exec cc -Yp,${CPPDIR} -I${INCDIR} ${DEFINES} "$@" # M88 SysV.3
exec cc -B${CPPDIR}/ -tp -I${INCDIR} ${DEFINES} "$@" # System V.2

35
build/unproto/cpp.sh Executable file
View File

@ -0,0 +1,35 @@
#!/bin/sh
# @(#) cpp.sh 1.3 92/01/15 21:53:22
# Unprototypeing preprocessor for pre-ANSI C compilers. On some systems,
# this script can be as simple as:
#
# /lib/cpp "$@" | unproto
#
# However, some cc(1) drivers specify output file names on the
# preprocessor command line, so this shell script must be prepared to
# intercept them. Depending on the driver program, the cpp options may
# even go before or after the file name argument(s). The script below
# tries to tackle all these cases.
#
# You may want to add -Ipath_to_stdarg.h_file, -Dvoid=, -Dvolatile=,
# and even -D__STDC__.
cpp_args=""
while :
do
case $1 in
"") break;;
-*) cpp_args="$cpp_args $1";;
*) cpp_args="$cpp_args $1"
case $2 in
""|-*) ;;
*) exec 1> $2 || exit 1; shift;;
esac;;
esac
shift
done
/lib/cpp $cpp_args | unproto

97
build/unproto/error.c Normal file
View File

@ -0,0 +1,97 @@
/*++
/* NAME
/* error 3
/* SUMMARY
/* diagnostics
/* PACKAGE
/* unproto
/* SYNOPSIS
/* #include "error.h"
/*
/* int errcount;
/*
/* void error(text)
/* char *text;
/*
/* void error_where(path, line, text)
/* char *path;
/* int line;
/* char *text;
/*
/* void fatal(text)
/* char *text;
/* DESCRIPTION
/* The routines in this file print a diagnostic (text). Some also
/* terminate the program. Upon each error*() call, the errcount variable
/* is incremented.
/*
/* error() provides a default context, i.e. the source-file
/* coordinate of the last read token.
/*
/* error_where() allows the caller to explicitly specify context: path
/* is a source-file name, and line is a line number.
/*
/* fatal() is like error() but terminates the program with a non-zero
/* exit status.
/*
/* context is ignored if the line number is zero or if the path
/* is an empty string.
/* AUTHOR(S)
/* Wietse Venema
/* Eindhoven University of Technology
/* Department of Mathematics and Computer Science
/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
/* LAST MODIFICATION
/* 92/01/15 21:53:10
/* VERSION/RELEASE
/* 1.2
/*--*/
static char error_sccsid[] = "@(#) error.c 1.2 92/01/15 21:53:10";
/* C library */
#include <stdio.h>
extern void exit();
/* Application-specific stuff */
#include "token.h"
#include "error.h"
int errcount = 0; /* error counter */
/* error - report problem (implicit context) */
void error(text)
char *text;
{
error_where(in_path, in_line, text);
}
/* error_where - report problem (explicit context) */
void error_where(path, line, text)
char *path;
int line;
char *text;
{
errcount++;
/* Suppress context info if there is none. */
if (line && path[0])
fprintf(stderr, "%s, line %d: ", path, line);
fprintf(stderr, "%s\n", text);
}
/* fatal - report problem and terminate unsuccessfully */
void fatal(text)
char *text;
{
error(text);
exit(1);
}

6
build/unproto/error.h Normal file
View File

@ -0,0 +1,6 @@
/* @(#) error.h 1.2 92/01/15 21:53:14 */
extern int errcount; /* error counter */
extern void error(); /* default context */
extern void error_where(); /* user-specified context */
extern void fatal(); /* fatal error */

222
build/unproto/example.c Normal file
View File

@ -0,0 +1,222 @@
/*
* @(#) example.c 1.5 93/06/18 22:29:46
*
* Examples of things that can be done with the unproto package
*/
typedef char *charstar;
/*
* New-style argument list with structured argument, one field being pointer
* to function returning pointer to function with function-pointer argument
*/
x(struct {
struct {
int (*(*foo) (int (*arg1) (double))) (float arg2);
} foo;
} baz) {
return (0);
}
/* New-style function-pointer declaration. */
int (*(*bar0) (float)) (int);
/* Old-style argument list with new-style argument type. */
baz0(bar)
int (*(*bar) (float)) (int);
{}
/*
* New-style argument list with new-style argument type, declaration
* embedded within block. Plus a couple assignments with function calls that
* look like casts.
*/
foo(int (*(*bar) (float)) (int))
{
int (*baz) (int) = (int (*) (int)) 0,
y = (y * (*baz) (y)),
*(*z) (int) = (int *(*) (int)) 0;
struct { int (*foo)(int); } *(*s)(int) =
(struct { int (*foo)(int); } *(*)(int)) 0;
{
y = (y * (*baz) (y));
}
{
z = (int *(*) (int)) 0;
}
{
s = (struct { int (*foo)(int); } *(*)(int)) 0;
}
return (0);
}
/* Multiple declarations in one statement */
test1()
{
int foo2,*(*(*bar)(int))(float),*baz(double);
}
/* Discriminate declarations from executable statements */
test2(charstar y)
{
int foo = 5,atoi(charstar);
foo = 5,atoi(y);
}
/* Declarations without explicit type */
test3,test4(int);
test5(int y)
{
{
test3;
}
{
test4(y);
}
}
test6[1],test7(int);
test7(int x)
{
{
test6[1];
}
{
test7(x);
}
}
/* Checking a complicated cast */
struct {
struct {
int (*f)(int), o;
} bar;
} (*baz2)(int) = (struct { struct { int (*f)(int), o; } bar; } (*)(int)) 0;
/* Distinguish things with the same shape but with different meaning */
test8(x)
{
{
struct {
int foo;
} bar(charstar);
}
{
do {
int foo;
} while (x);
}
}
/* Do not think foo(*bar) is a function pointer declaration */
test9(char *bar)
{
foo(*bar);
}
/* another couple of special-cased words. */
test10(int x)
{
{
int test10(int);
do test10(x);
while (x);
}
{
return test10(x);
}
}
test11(int *x)
{
while (*x)
(putchar(*x++));
}
test11a(int *x)
{
for (*x;;)
(putchar(*x++));
}
/* #include directive between stuff that requires lookahead */
test12()
{
char *x = "\xf\0002\002\02\2" /* foo */
#include "/dev/null"
"\abar";
printf("foo" /* 1 */ "bar" /* 2 */ "baz");
*x = '\a';
*x = '\xff';
}
int test13(void);
/* line continuations in the middle of tokens */
te\
st14();
charstar test15 = "foo\
bar";
char test16 = "foo\\
abar";
/* Array dimensions with unexpanded macros */
test17(charstar foo[bar]){}
int (*(*test18[bar])(charstar))(charstar) = \
(int (*(*[bar])(charstar))(charstar)) 0;
/* Function returning pointer to function */
int (*(*test19(long))(int))(double);
/* GCC accepts the following stuff, K&R C does not... */
void test20(int test21(double)) {}
void test22(struct { int foo; } test23(short)) {}
/* Do not blindly rewrite (*name(stuff))(otherstuff) */
void test23()
{
int (*test24(int)) (int),
y = (*test24(2)) (3),
z = ((*test24(2)) (3));
}
/* Function returning pointer to function */
int (*(*test25(long foo))(int bar))(double baz){ /* body */ }
int (*(*test26(foo))())()
long foo;
{ /* body */ }
#define ARGSTR() struct {int l; char c[1];}
void functie(ARGSTR() *cmdlin, ARGSTR() *c1)
{
}

271
build/unproto/example.out Normal file
View File

@ -0,0 +1,271 @@
# 1 "example.c"
typedef char *charstar;
x(
baz)
# 14 "example.c"
struct {
struct {
int (*(*foo)())();
} foo;
} baz;
# 18 "example.c"
{/*1*/
/* end dcls */return (0);
}/*1*/
int (*(*bar0)())();
baz0(bar)
int (*(*bar)())();
{/*1*/}/*1*/
foo(bar)
# 38 "example.c"
int (*(*bar)())();
{/*1*/
int (*baz)()= (int (*)()) 0,
y = (y * (*baz)(y)),
*(*z)()= (int *(*)()) 0;
struct {/*2*/ int (*foo)(); }/*2*/ *(*s)()=
(struct { int (*foo)(); } *(*)()) 0;
/* end dcls */{/*2*/
y /* end dcls */= (y * (*baz)(y));
}/*2*/
{/*2*/
z /* end dcls */= (int *(*)()) 0;
}/*2*/
{/*2*/
s /* end dcls */= (struct { int (*foo)(); } *(*)()) 0;
}/*2*/
return (0);
}/*1*/
test1()
{/*1*/
int foo2,*(*(*bar)())(),*baz();
}/*1*/
test2(y)
# 69 "example.c"
charstar y;
{/*1*/
int foo = 5,atoi();
foo /* end dcls */= 5,atoi(y);
}/*1*/
test3,test4();
test5(y)
# 80 "example.c"
int y;
{/*1*/
/* end dcls */{/*2*/
test3/* end dcls */;
}/*2*/
{/*2*/
test4/* end dcls */(y);
}/*2*/
}/*1*/
test6[1],test7();
test7(x)
# 92 "example.c"
int x;
{/*1*/
/* end dcls */{/*2*/
test6/* end dcls */[1];
}/*2*/
{/*2*/
test7/* end dcls */(x);
}/*2*/
}/*1*/
struct {/*1*/
struct {/*2*/
int (*f)(), o;
}/*2*/ bar;
}/*1*/ (*baz2)()= (struct { struct { int (*f)(), o; } bar; } (*)()) 0;
test8(x)
{/*1*/
/* end dcls */{/*2*/
struct {/*3*/
int foo;
}/*3*/ bar();
}/*2*/
{/*2*/
/* end dcls */do {/*3*/
int foo;
}/*3*/ while (x);
}/*2*/
}/*1*/
test9(bar)
# 128 "example.c"
char *bar;
{/*1*/
foo/* end dcls */(*bar);
}/*1*/
test10(x)
# 135 "example.c"
int x;
{/*1*/
/* end dcls */{/*2*/
int test10();
/* end dcls */do test10(x);
while (x);
}/*2*/
{/*2*/
/* end dcls */return test10(x);
}/*2*/
}/*1*/
test11(x)
# 147 "example.c"
int *x;
{/*1*/
/* end dcls */while (*x)
(putchar(*x++));
}/*1*/
test11a(x)
# 153 "example.c"
int *x;
{/*1*/
/* end dcls */for (*x;;)
(putchar(*x++));
}/*1*/
test12()
{/*1*/
char *x =
# 1 "/dev/null" 1
# 165 "example.c" 2
# 163 "example.c"
"\017\0002\002\002\002\007bar"
;
printf/* end dcls */("foobarbaz" );
*x = '\007';
*x = '\377';
}/*1*/
int test13();
test14();
charstar test15 = "foobar";
char test16 = "foo\007bar";
test17(foo)
# 186 "example.c"
charstar foo[bar];
# 186 "example.c"
{/*1*/}/*1*/
int (*(*test18[bar])())()= (int (*(*[bar])())()) 0;
int (*(*test19())())();
void test20(test21)
# 197 "example.c"
int test21();
# 197 "example.c"
{/*1*/}/*1*/
void test22(test23)
# 199 "example.c"
struct { int foo; } test23();
# 199 "example.c"
{/*1*/}/*1*/
void test23()
{/*1*/
int (*test24())(),
y = (*test24(2)) (3),
z = ((*test24(2))(3));
}/*1*/
int (*(*test25(foo))())()
# 212 "example.c"
long foo;
# 212 "example.c"
{/*1*/ }/*1*/
int (*(*test26(foo))())()
long foo;
{/*1*/ }/*1*/
void functie(cmdlin,c1)
# 220 "example.c"
struct {int l; char c[1];} *cmdlin;
# 220 "example.c"
struct {int l; char c[1];} *c1;
{/*1*/
}/*1*/

54
build/unproto/hash.c Normal file
View File

@ -0,0 +1,54 @@
/*++
/* NAME
/* hash 3
/* SUMMARY
/* compute hash value for string
/* SYNOPSIS
/* int hash(string, size)
/* char *string;
/* int size;
/* DESCRIPTION
/* This function computes for the given null-terminated string an
/* integer hash value in the range 0..size-1.
/* SEE ALSO
/* .fi
/* Alfred V. Aho, Ravi Sethi and Jeffrey D. Ullman: Compilers:
/* principles, techniques and tools; Addison-Wesley, Amsterdam, 1986.
/* AUTHOR(S)
/* Wietse Venema
/* Eindhoven University of Technology
/* Department of Mathematics and Computer Science
/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
/*
/* Originally written by: P. J. Weinberger at Bell Labs.
/* LAST MODIFICATION
/* 92/01/15 21:53:12
/* VERSION/RELEASE
/* %I
/*--*/
static char hash_sccsid[] = "@(#) hash.c 1.1 92/01/15 21:53:12";
/* hash - hash a string; original author: P. J. Weinberger at Bell Labs. */
int hash(s, size)
register char *s;
unsigned size;
{
register unsigned long h = 0;
register unsigned long g;
/*
* For a performance comparison with the hash function presented in K&R,
* first edition, see the "Dragon" book by Aho, Sethi and Ullman.
*/
while (*s) {
h = (h << 4) + *s++;
if (g = (h & 0xf0000000)) {
h ^= (g >> 24);
h ^= g;
}
}
return (h % size);
}

90
build/unproto/stdarg.h Normal file
View File

@ -0,0 +1,90 @@
/*
* @(#) stdarg.h 1.4 93/06/18 22:29:44
*
* Sample stdarg.h file for use with the unproto filter.
*
* This file serves two purposes.
*
* 1 - On systems that do not have a /usr/include/stdarg.h file, it should be
* included by C source files that implement ANSI-style variadic functions.
* Ultrix 4.[0-2] comes with stdarg.h but still needs the one that is
* provided with the unproto filter.
*
* 2 - To configure the unprototyper itself. If the _VA_ALIST_ macro is
* defined, its value will appear in the place of the "..." at the end of
* argument lists of variadic function *definitions* (not declarations).
* Some compilers (such as Greenhills m88k) have a non-empty va_dcl
* definition in the system header file varargs.h. If that is the case,
* define "_VA_DCL_" with the same value as va_dcl. If _VA_DCL_ is defined,
* the unprototyper will emit its value just before the opening "{".
*
* Compilers that always pass arguments via the stack can use the default code
* at the end of this file (this usually applies for the vax, mc68k and
* 80*86 architectures).
*
* Special tricks are needed for compilers that pass some or all function
* arguments via registers. Examples of the latter are given for the mips
* and sparc architectures. Usually the compiler special-cases an argument
* declaration such as "va_alist" or "__builtin_va_alist". For inspiration,
* see the local /usr/include/varargs.h file.
*
* You can use the varargs.c program provided with the unproto package to
* verify that the stdarg.h file has been set up correctly.
*/
#ifdef sparc /* tested with SunOS 4.1.1 */
#define _VA_ALIST_ "__builtin_va_alist"
typedef char *va_list;
#define va_start(ap, p) (ap = (char *) &__builtin_va_alist)
#define va_arg(ap, type) ((type *) __builtin_va_arg_incr((type *) ap))[0]
#define va_end(ap)
#else
#ifdef mips /* tested with Ultrix 4.0 and 4.2 */
#define _VA_ALIST_ "va_alist"
#include "/usr/include/stdarg.h"
#else
#ifdef m88k /* Motorola SYSTEM V/88 R32V3 */
#define _VA_ALIST_ "va_alist"
#define _VA_DCL_ "va_type va_alist;"
typedef struct _va_struct {
int va_narg;
int *va_stkaddr;
int *va_iregs;
} va_list;
#define va_start(ap, p) \
((ap).va_narg=(int *)&va_alist-va_stkarg, \
(ap).va_stkaddr=va_stkarg, \
(ap).va_iregs=(int *)va_intreg)
#define va_end(p)
#if defined(LittleEndian)
#define va_arg(p,mode) \
(*(mode *)_gh_va_arg(&p, va_align(mode), va_regtyp(mode), sizeof(mode)))
#else /* defined(LittleEndian) */
#define va_arg(p,mode) ( \
(p).va_narg += ((p).va_narg & (va_align(mode) == 8)) + \
(sizeof(mode)+3)/4, \
((mode *)((va_regtyp(mode) && (p).va_narg <= 8 ? \
(p).va_iregs: \
(p).va_stkaddr) + (p).va_narg))[-1])
#endif /* defined(LittleEndian) */
#else
#ifdef hpux
#include <stdarg.h>
#else /* vax, mc68k, 80*86 */
typedef char *va_list;
#define va_start(ap, p) (ap = (char *) (&(p)+1))
#define va_arg(ap, type) ((type *) (ap += sizeof(type)))[-1]
#define va_end(ap)
#endif /* hpux */
#endif /* m88k */
#endif /* mips */
#endif /* sparc */

23
build/unproto/stddef.h Normal file
View File

@ -0,0 +1,23 @@
/* @(#) stddef.h 1.1 92/02/15 17:25:46 */
#ifndef _stddef_h_
#define _stddef_h_
/* NULL is also defined in <stdio.h> */
#ifndef NULL
#define NULL 0
#endif
/* Structure member offset - some compilers barf on this. */
#define offsetof(type, member) ((size_t) &((type *)0)->member)
/* Some of the following types may already be defined in <sys/types.h>. */
/* #include <sys/types.h> */
/* typedef long ptrdiff_t; /* type of pointer difference */
/* typedef unsigned short wchar_t; /* wide character type */
/* typedef unsigned size_t; /* type of sizeof */
#endif /* _stddef_h_ */

53
build/unproto/stdlib.h Normal file
View File

@ -0,0 +1,53 @@
/* @(#) stdlib.h 1.1 92/02/15 17:25:45 */
#ifndef _stdlib_h_
#define _stdlib_h_
/* NULL is also defined in <stdio.h> */
#ifndef NULL
#define NULL 0
#endif
/*
* Some functions in this file will be missing from the typical pre-ANSI
* UNIX library. Some pre-ANSI UNIX library functions have return types
* that differ from what ANSI requires.
*/
extern double atof();
extern int atoi();
extern long atol();
extern double strtod();
extern long strtol();
extern unsigned long strtoul();
extern int rand();
extern void srand();
extern char *calloc();
extern char *malloc();
extern char *realloc();
extern void free();
extern void abort();
extern void exit();
extern int atextit();
extern int system();
extern char *getenv();
extern char *bsearch();
extern void qsort();
extern int abs();
extern long labs();
typedef struct {
int quot;
int rem;
} div_t;
typedef struct {
long quot;
long rem;
} ldiv_t;
extern div_t div();
extern ldiv_t ldiv();
#endif /* _stdlib_h_ */

71
build/unproto/strsave.c Normal file
View File

@ -0,0 +1,71 @@
/*++
/* NAME
/* strsave 3
/* SUMMARY
/* maintain unique copy of a string
/* SYNOPSIS
/* char *strsave(string)
/* char *string;
/* DESCRIPTION
/* This function returns a pointer to an unique copy of its
/* argument.
/* DIAGNOSTISC
/* strsave() calls fatal() when it runs out of memory.
/* AUTHOR(S)
/* Wietse Venema
/* Eindhoven University of Technology
/* Department of Mathematics and Computer Science
/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
/* LAST MODIFICATION
/* 92/01/15 21:53:13
/* VERSION/RELEASE
/* 1.1
/*--*/
static char strsave_sccsid[] = "@(#) strsave.c 1.1 92/01/15 21:53:13";
/* C library */
extern char *strcpy();
extern char *malloc();
/* Application-specific stuff */
#include "error.h"
#define STR_TABSIZE 100
struct string {
char *strval; /* unique string copy */
struct string *next; /* next one in hash chain */
};
static struct string *str_tab[STR_TABSIZE] = {0,};
/* More string stuff. Maybe it should go to an #include file. */
#define STREQ(x,y) (*(x) == *(y) && strcmp((x),(y)) == 0)
/* strsave - save unique copy of string */
char *strsave(str)
register char *str;
{
register struct string *s;
register int where = hash(str, STR_TABSIZE);
/* Look for existing entry. */
for (s = str_tab[where]; s; s = s->next)
if (STREQ(str, s->strval))
return (s->strval);
/* Add new entry. */
if ((s = (struct string *) malloc(sizeof(*s))) == 0
|| (s->strval = malloc(strlen(str) + 1)) == 0)
fatal("out of memory");
s->next = str_tab[where];
str_tab[where] = s;
return (strcpy(s->strval, str));
}

144
build/unproto/symbol.c Normal file
View File

@ -0,0 +1,144 @@
/*++
/* NAME
/* symbol 3
/* SUMMARY
/* rudimentary symbol table package
/* SYNOPSIS
/* #include "symbol.h"
/*
/* void sym_init()
/*
/* void sym_enter(name, type)
/* char *name;
/* int type;
/*
/* struct symbol *sym_find(name)
/* char *name;
/* DESCRIPTION
/* This is a rudimentary symbol-table package, just enough to
/* keep track of a couple of C keywords.
/*
/* sym_init() primes the table with C keywords. At present, most of
/* the keywords that have to do with types are left out.
/* We need a different strategy to detect type definitions because
/* we do not keep track of typedef names.
/*
/* sym_enter() adds an entry to the symbol table.
/*
/* sym_find() locates a symbol table entry (it returns 0 if
/* it is not found).
/* AUTHOR(S)
/* Wietse Venema
/* Eindhoven University of Technology
/* Department of Mathematics and Computer Science
/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
/* LAST MODIFICATION
/* 92/02/15 18:59:56
/* VERSION/RELEASE
/* 1.4
/*--*/
static char symbol_sccsid[] = "@(#) symbol.c 1.4 92/02/15 18:59:56";
/* C library */
extern char *strcpy();
extern char *malloc();
/* Application-specific stuff */
#include "error.h"
#include "token.h"
#include "symbol.h"
#define SYM_TABSIZE 20
static struct symbol *sym_tab[SYM_TABSIZE] = {0,};
/* More string stuff. Maybe it should go to an #include file. */
#define STREQ(x,y) (*(x) == *(y) && strcmp((x),(y)) == 0)
/* sym_enter - enter symbol into table */
void sym_enter(name, type)
char *name;
int type;
{
struct symbol *s;
int where;
if ((s = (struct symbol *) malloc(sizeof(*s))) == 0
|| (s->name = malloc(strlen(name) + 1)) == 0)
fatal("out of memory");
(void) strcpy(s->name, name);
s->type = type;
where = hash(name, SYM_TABSIZE);
s->next = sym_tab[where];
sym_tab[where] = s;
}
/* sym_find - locate symbol definition */
struct symbol *sym_find(name)
register char *name;
{
register struct symbol *s;
/*
* This function is called for almost every "word" token, so it better be
* fast.
*/
for (s = sym_tab[hash(name, SYM_TABSIZE)]; s; s = s->next)
if (STREQ(name, s->name))
return (s);
return (0);
}
/*
* Initialization data for symbol table. We do not enter keywords for types.
* We use a different strategy to detect type declarations because we do not
* keep track of typedef names.
*/
struct sym {
char *name;
int tokno;
};
static struct sym syms[] = {
"if", TOK_CONTROL,
"else", TOK_CONTROL,
"for", TOK_CONTROL,
"while", TOK_CONTROL,
"do", TOK_CONTROL,
"switch", TOK_CONTROL,
"case", TOK_CONTROL,
"default", TOK_CONTROL,
"return", TOK_CONTROL,
"continue", TOK_CONTROL,
"break", TOK_CONTROL,
"goto", TOK_CONTROL,
"struct", TOK_COMPOSITE,
"union", TOK_COMPOSITE,
"__DATE__", TOK_DATE,
"__TIME__", TOK_TIME,
#if defined(MAP_VOID_STAR) || defined(MAP_VOID)
"void", TOK_VOID,
#endif
"asm", TOK_OTHER,
0,
};
/* sym_init - enter known keywords into symbol table */
void sym_init()
{
register struct sym *p;
for (p = syms; p->name; p++)
sym_enter(p->name, p->tokno);
}

11
build/unproto/symbol.h Normal file
View File

@ -0,0 +1,11 @@
/* @(#) symbol.h 1.1 91/09/22 21:21:42 */
struct symbol {
char *name; /* symbol name */
int type; /* symbol type */
struct symbol *next;
};
extern void sym_enter(); /* add symbol to table */
extern struct symbol *sym_find(); /* locate symbol */
extern void sym_init(); /* prime the table */

432
build/unproto/tok_class.c Normal file
View File

@ -0,0 +1,432 @@
/*++
/* NAME
/* tok_class 3
/* SUMMARY
/* token classification
/* PACKAGE
/* unproto
/* SYNOPSIS
/* #include "token.h"
/*
/* void tok_unget(t)
/* struct token *t;
/*
/* struct token *tok_class()
/* DESCRIPTION
/* tok_class() collects single and composite tokens, and
/* recognizes keywords.
/* At present, the only composite tokens are ()-delimited,
/* comma-separated lists, and non-whitespace tokens with attached
/* whitespace or comment tokens.
/*
/* Source transformations are: __DATE__ and __TIME__ are rewritten
/* to string constants with the current date and time, respectively.
/* Multiple string constants are concatenated. Optionally, "void *"
/* is mapped to "char *", and plain "void" to "int".
/*
/* tok_unget() implements an arbitrary amount of token pushback.
/* Only tokens obtained through tok_class() should be given to
/* tok_unget(). This function accepts a list of tokens in
/* last-read-first order.
/* DIAGNOSTICS
/* The code complains if input terminates in the middle of a list.
/* BUGS
/* Does not preserve white space at the beginning of a list element
/* or after the end of a list.
/* AUTHOR(S)
/* Wietse Venema
/* Eindhoven University of Technology
/* Department of Mathematics and Computer Science
/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
/* LAST MODIFICATION
/* 92/01/15 21:53:02
/* VERSION/RELEASE
/* 1.4
/*--*/
static char class_sccsid[] = "@(#) tok_class.c 1.4 92/01/15 21:53:02";
/* C library */
#include <stdio.h>
extern char *strcpy();
extern long time();
extern char *ctime();
/* Application-specific stuff */
#include "error.h"
#include "vstring.h"
#include "token.h"
#include "symbol.h"
static struct token *tok_list();
static void tok_list_struct();
static void tok_list_append();
static void tok_strcat();
static void tok_time();
static void tok_date();
static void tok_space_append();
#if defined(MAP_VOID_STAR) || defined(MAP_VOID)
static void tok_void(); /* rewrite void keyword */
#endif
static struct token *tok_buf = 0; /* token push-back storage */
/* TOK_PREPEND - add token to LIFO queue, return head */
#define TOK_PREPEND(list,t) (t->next = list, list = t)
/* tok_space_append - append trailing space except at start of or after list */
static void tok_space_append(list, t)
register struct token *list;
register struct token *t;
{
/*
* The head/tail fields of a token do triple duty. They are used to keep
* track of the members that make up a (list); to keep track of the
* non-blank tokens that make up one list member; and, finally, to tack
* whitespace and comment tokens onto the non-blank tokens that make up
* one list member.
*
* Within a (list), white space and comment tokens are always tacked onto
* the non-blank tokens to avoid parsing complications later on. For this
* reason, blanks and comments at the beginning of a list member are
* discarded because there is no token to tack them onto. (Well, we could
* start each list member with a dummy token, but that would mess up the
* whole unprototyper).
*
* Blanks or comments that follow a (list) are discarded, because the
* head/tail fields of a (list) are already being used for other
* purposes.
*
* Newlines within a (list) are discarded because they can mess up the
* output when we rewrite function headers. The output routines will
* regenerate discarded newlines, anyway.
*/
if (list == 0 || list->tokno == TOK_LIST) {
tok_free(t);
} else {
tok_list_append(list, t);
}
}
/* tok_class - discriminate single tokens, keywords, and composite tokens */
struct token *tok_class()
{
register struct token *t;
register struct symbol *s;
/*
* Use push-back token, if available. Push-back tokens are already
* canonical and can be passed on to the caller without further
* inspection.
*/
if (t = tok_buf) {
tok_buf = t->next;
t->next = 0;
return (t);
}
/* Read a new token and canonicalize it. */
if (t = tok_get()) {
switch (t->tokno) {
case '(': /* beginning of list */
t = tok_list(t);
break;
case TOK_WORD: /* look up keyword */
if ((s = sym_find(t->vstr->str))) {
switch (s->type) {
case TOK_TIME: /* map __TIME__ to string */
tok_time(t);
tok_strcat(t); /* look for more strings */
break;
case TOK_DATE: /* map __DATE__ to string */
tok_date(t);
tok_strcat(t); /* look for more strings */
break;
#if defined(MAP_VOID_STAR) || defined(MAP_VOID)
case TOK_VOID: /* optionally map void types */
tok_void(t);
break;
#endif
default: /* other keyword */
t->tokno = s->type;
break;
}
}
break;
case '"': /* string, look for more */
tok_strcat(t);
break;
}
}
return (t);
}
/* tok_list - collect ()-delimited, comma-separated list of tokens */
static struct token *tok_list(t)
struct token *t;
{
register struct token *list = tok_alloc();
char *filename;
int lineno;
/* Save context of '(' for diagnostics. */
filename = t->path;
lineno = t->line;
list->tokno = TOK_LIST;
list->head = list->tail = t;
list->path = t->path;
list->line = t->line;
#ifdef DEBUG
strcpy(list->vstr->str, "LIST");
#endif
/*
* Read until the matching ')' is found, accounting for structured stuff
* (enclosed by '{' and '}' tokens). Break the list up at each ',' token,
* and try to preserve as much whitespace as possible. Newlines are
* discarded so that they will not mess up the layout when we rewrite
* argument lists. The output routines will regenerate discarded
* newlines.
*/
while (t = tok_class()) { /* skip blanks */
switch (t->tokno) {
case ')': /* end of list */
tok_list_append(list, t);
return (list);
case '{': /* struct/union type */
tok_list_struct(list->tail, t);
break;
case TOK_WSPACE: /* preserve trailing blanks */
tok_space_append(list->tail->tail, t); /* except after list */
break;
case '\n': /* fix newlines later */
tok_free(t);
break;
case ',': /* list separator */
tok_list_append(list, t);
break;
default: /* other */
tok_list_append(list->tail, t);
break;
}
}
error_where(filename, lineno, "unmatched '('");
return (list); /* do not waste any data */
}
/* tok_list_struct - collect structured type info within list */
static void tok_list_struct(list, t)
register struct token *list;
register struct token *t;
{
char *filename;
int lineno;
/*
* Save context of '{' for diagnostics. This routine is called by the one
* that collects list members. If the '}' is not found, the list
* collector will not see the closing ')' either.
*/
filename = t->path;
lineno = t->line;
tok_list_append(list, t);
/*
* Collect tokens until the matching '}' is found. Try to preserve as
* much whitespace as possible. Newlines are discarded so that they do
* not interfere when rewriting argument lists. The output routines will
* regenerate discarded newlines.
*/
while (t = tok_class()) {
switch (t->tokno) {
case TOK_WSPACE: /* preserve trailing blanks */
tok_space_append(list->tail, t); /* except after list */
break;
case '\n': /* fix newlines later */
tok_free(t);
break;
case '{': /* recurse */
tok_list_struct(list, t);
break;
case '}': /* done */
tok_list_append(list, t);
return;
default: /* other */
tok_list_append(list, t);
break;
}
}
error_where(filename, lineno, "unmatched '{'");
}
/* tok_strcat - concatenate multiple string constants */
static void tok_strcat(t1)
register struct token *t1;
{
register struct token *t2;
register struct token *lookahead = 0;
/*
* Read ahead past whitespace, comments and newlines. If we find a string
* token, concatenate it with the previous one and push back the
* intervening tokens (thus preserving as much information as possible).
* If we find something else, push back all lookahead tokens.
*/
#define PUSHBACK_AND_RETURN { if (lookahead) tok_unget(lookahead); return; }
while (t2 = tok_class()) {
switch (t2->tokno) {
case TOK_WSPACE: /* read past comments/blanks */
case '\n': /* read past newlines */
TOK_PREPEND(lookahead, t2);
break;
case '"': /* concatenate string tokens */
if (vs_strcpy(t1->vstr,
t1->vstr->str + strlen(t1->vstr->str) - 1,
t2->vstr->str + 1) == 0)
fatal("out of memory");
tok_free(t2);
PUSHBACK_AND_RETURN;
default: /* something else, push back */
tok_unget(t2);
PUSHBACK_AND_RETURN;
}
}
PUSHBACK_AND_RETURN; /* hit EOF */
}
#if defined(MAP_VOID_STAR) || defined(MAP_VOID)
/* tok_void - support for compilers that have problems with "void" */
static void tok_void(t)
register struct token *t;
{
register struct token *t2;
register struct token *lookahead = 0;
/*
* Look ahead beyond whitespace, comments and newlines until we see a '*'
* token. If one is found, replace "void" by "char". If we find something
* else, and if "void" should always be mapped, replace "void" by "int".
* Always push back the lookahead tokens.
*
* XXX The code also replaces the (void) argument list; this must be
* accounted for later on. The alternative would be to add (in unproto.c)
* TOK_VOID cases all over the place and that would be too error-prone.
*/
#define PUSHBACK_AND_RETURN { if (lookahead) tok_unget(lookahead); return; }
while (t2 = tok_class()) {
switch (TOK_PREPEND(lookahead, t2)->tokno) {
case TOK_WSPACE: /* read past comments/blanks */
case '\n': /* read past newline */
break;
case '*': /* "void *" -> "char *" */
if (vs_strcpy(t->vstr, t->vstr->str, "char") == 0)
fatal("out of memory");
PUSHBACK_AND_RETURN;
default:
#ifdef MAP_VOID /* plain "void" -> "int" */
if (vs_strcpy(t->vstr, t->vstr->str, "int") == 0)
fatal("out of memory");
#endif
PUSHBACK_AND_RETURN;
}
}
PUSHBACK_AND_RETURN; /* hit EOF */
}
#endif
/* tok_time - rewrite __TIME__ to "hh:mm:ss" string constant */
static void tok_time(t)
struct token *t;
{
long now;
char *cp;
char buf[BUFSIZ];
/*
* Using sprintf() to select parts of a string is gross, but this should
* be fast enough.
*/
(void) time(&now);
cp = ctime(&now);
sprintf(buf, "\"%.8s\"", cp + 11);
if (vs_strcpy(t->vstr, t->vstr->str, buf) == 0)
fatal("out of memory");
t->tokno = buf[0];
}
/* tok_date - rewrite __DATE__ to "Mmm dd yyyy" string constant */
static void tok_date(t)
struct token *t;
{
long now;
char *cp;
char buf[BUFSIZ];
/*
* Using sprintf() to select parts of a string is gross, but this should
* be fast enough.
*/
(void) time(&now);
cp = ctime(&now);
sprintf(buf, "\"%.3s %.2s %.4s\"", cp + 4, cp + 8, cp + 20);
if (vs_strcpy(t->vstr, t->vstr->str, buf) == 0)
fatal("out of memory");
t->tokno = buf[0];
}
/* tok_unget - push back one or more possibly composite tokens */
void tok_unget(t)
register struct token *t;
{
register struct token *next;
do {
next = t->next;
TOK_PREPEND(tok_buf, t);
} while (t = next);
}
/* tok_list_append - append data to list */
static void tok_list_append(h, t)
struct token *h;
struct token *t;
{
if (h->head == 0) {
h->head = h->tail = t;
} else {
h->tail->next = t;
h->tail = t;
}
}

612
build/unproto/tok_io.c Normal file
View File

@ -0,0 +1,612 @@
/*++
/* NAME
/* tok_io 3
/* SUMMARY
/* token I/O
/* PACKAGE
/* unproto
/* SYNOPSIS
/* #include "token.h"
/*
/* struct token *tok_get()
/*
/* void tok_flush(t)
/* struct token *t;
/*
/* void tok_show(t)
/* struct token *t;
/*
/* void tok_show_ch(t)
/* struct token *t;
/*
/* void put_str(s)
/* char *s;
/*
/* void put_ch(c)
/* int c;
/*
/* void put_nl()
/*
/* char *in_path;
/* int in_line;
/* DESCRIPTION
/* These functions read from stdin and write to stdout. The
/* tokenizer keeps track of where the token appeared in the input
/* stream; on output, this information is used to preserve correct
/* line number information (even after lots of token lookahead or
/* after function-header rewriting) so that diagnostics from the
/* next compiler stage make sense.
/*
/* tok_get() reads the next token from standard input. It returns
/* a null pointer when the end of input is reached.
/*
/* tok_show() displays the contents of a (possibly composite) token
/* on the standard output.
/*
/* tok_show_ch() displays the contents of a single-character token
/* on the standard output. The character should not be a newline.
/*
/* tok_flush() displays the contents of a (possibly composite) token
/* on the standard output and makes it available for re-use.
/*
/* put_str() writes a null-terminated string to standard output.
/* There should be no newline characters in the string argument.
/*
/* put_ch() writes one character to standard output. The character
/* should not be a newline.
/*
/* put_nl() outputs a newline character and adjusts the program's idea of
/* the current output line.
/*
/* The in_path and in_line variables contain the file name and
/* line number of the most recently read token.
/* BUGS
/* The tokenizer is just good enough for the unproto filter.
/* As a benefit, it is quite fast.
/* AUTHOR(S)
/* Wietse Venema
/* Eindhoven University of Technology
/* Department of Mathematics and Computer Science
/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
/* LAST MODIFICATION
/* 92/01/15 21:52:59
/* VERSION/RELEASE
/* 1.3
/*--*/
static char io_sccsid[] = "@(#) tok_io.c 1.3 92/01/15 21:52:59";
/* C library */
#include <stdio.h>
#include <ctype.h>
extern char *strchr();
extern char *malloc();
extern char *realloc();
extern char *strcpy();
/* Application-specific stuff */
#include "token.h"
#include "vstring.h"
#include "error.h"
extern char *strsave(); /* XXX need include file */
/* Stuff to keep track of original source file name and position */
static char def_path[] = ""; /* default path name */
char *in_path = def_path; /* current input file name */
int in_line = 1; /* current input line number */
static char *out_path = def_path; /* last name in output line control */
static int out_line = 1; /* current output line number */
int last_ch; /* type of last output */
/* Forward declarations */
static int read_quoted();
static void read_comment();
static int backslash_newline();
static char *read_hex();
static char *read_octal();
static void fix_line_control();
/*
* Character input with one level of pushback. The INPUT() macro recursively
* strips backslash-newline pairs from the input stream. The UNPUT() macro
* should be used only for characters obtained through the INPUT() macro.
*
* After skipping a backslash-newline pair, the input line counter is not
* updated, and we continue with the same logical source line. We just
* update a counter with the number of backslash-newline sequences that must
* be accounted for (backslash_newline() updates the counter). At the end of
* the logical source line, an appropriate number of newline characters is
* pushed back (in tok_get()). I do not know how GCC handles this, but it
* seems to produce te same output.
*
* Because backslash_newline() recursively calls itself (through the INPUT()
* macro), we will run out of stack space, given a sufficiently long
* sequence of backslash-newline pairs.
*/
static char in_char = 0; /* push-back storage */
static int in_flag = 0; /* pushback available */
static int nl_compensate = 0; /* line continuation kluge */
#define INPUT(c) (in_flag ? (in_flag = 0, c = in_char) : \
(c = getchar()) != '\\' ? c : \
(c = getchar()) != '\n' ? (ungetc(c, stdin), c = '\\') : \
(c = backslash_newline()))
#define UNPUT(c) (in_flag = 1, in_char = c)
/* Directives that should be ignored. */
#ifdef IGNORE_DIRECTIVES
static char *ignore_directives[] = {
IGNORE_DIRECTIVES,
0,
};
#endif
/* Modified string and ctype stuff. */
#define STREQUAL(x,y) (*(x) == *(y) && strcmp((x),(y)) == 0)
#define ISALNUM(c) (isalnum(c) || (c) == '_')
#define ISALPHA(c) (isalpha(c) || (c) == '_')
#define ISSPACE(c) (isspace(c) && c != '\n')
#define ISDOT(c) (c == '.')
#define ISHEX(c) (isdigit(c) || strchr("abcdefABCDEF", c) != 0)
#define ISOCTAL(c) (isdigit(c) && (c) != '8' && (c) != '9')
/* Collect all characters that satisfy one condition */
#define COLLECT(v,c,cond) { \
register struct vstring *vs = v; \
register char *cp = vs->str; \
*cp++ = c; \
while (INPUT(c) != EOF) { \
if (cond) { \
if (VS_ADDCH(vs, cp, c) == 0) \
fatal("out of memory"); \
} else { \
UNPUT(c); \
break; \
} \
} \
*cp = 0; \
}
/* Ensure that output line information is correct */
#define CHECK_LINE_CONTROL(p,l) { if (out_path != (p) || out_line != (l)) \
fix_line_control((p),(l)); }
/* do_control - parse control line */
static int do_control()
{
struct token *t;
int line;
char *path;
/* Make sure that the directive shows up in the right place. */
CHECK_LINE_CONTROL(in_path, in_line);
while (t = tok_get()) {
switch (t->tokno) {
case TOK_WSPACE:
/* Ignore blanks after "#" token. */
tok_free(t);
break;
case TOK_NUMBER:
/*
* Line control is of the form: number pathname junk. Since we
* have no idea what junk the preprocessor may generate, we copy
* all line control tokens to stdout.
*/
put_str("# ");
line = atoi(t->vstr->str); /* extract line number */
tok_flush(t);
while ((t = tok_get()) && t->tokno == TOK_WSPACE)
tok_flush(t); /* copy white space */
if (t) { /* extract path name */
path = (t->tokno == '"') ? strsave(t->vstr->str) : in_path;
do {
tok_flush(t); /* copy until newline */
} while (t->tokno != '\n' && (t = tok_get()));
}
out_line = in_line = line; /* synchronize */
out_path = in_path = path; /* synchronize */
return;
#ifdef IGNORE_DIRECTIVES
case TOK_WORD:
/*
* Optionally ignore other #directives. This is only a partial
* solution, because the preprocessor will still see them.
*/
{
char **cpp;
char *cp = t->vstr->str;
for (cpp = ignore_directives; *cpp; cpp++) {
if (STREQUAL(cp, *cpp)) {
do {
tok_free(t);
} while (t->tokno != '\n' && (t = tok_get()));
return;
}
}
}
/* FALLTHROUGH */
#endif
default:
/* Pass through. */
put_ch('#');
do {
tok_flush(t);
} while (t->tokno != '\n' && (t = tok_get()));
return;
case 0:
/* Hit EOF, punt. */
put_ch('#');
return;
}
}
}
/* backslash_newline - fix up things after reading a backslash-newline pair */
static int backslash_newline()
{
register int c;
nl_compensate++;
return (INPUT(c));
}
/* tok_get - get next token */
static int last_tokno = '\n';
struct token *tok_get()
{
register struct token *t;
register int c;
int d;
/*
* Get one from the pool and fill it in. The loop is here in case we hit
* a preprocessor control line, which happens in a minority of all cases.
* We update the token input path and line info *after* backslash-newline
* processing or the newline compensation would go wrong.
*/
t = tok_alloc();
for (;;) {
if ((INPUT(c)) == EOF) {
tok_free(t);
return (0);
} else if ((t->line = in_line, t->path = in_path), !isascii(c)) {
t->vstr->str[0] = c;
t->vstr->str[1] = 0;
t->tokno = TOK_OTHER;
break;
} else if (ISSPACE(c)) {
COLLECT(t->vstr, c, ISSPACE(c));
t->tokno = TOK_WSPACE;
break;
} else if (ISALPHA(c)) {
COLLECT(t->vstr, c, ISALNUM(c));
t->tokno = TOK_WORD;
break;
} else if (isdigit(c)) {
COLLECT(t->vstr, c, isdigit(c));
t->tokno = TOK_NUMBER;
break;
} else if (c == '"' || c == '\'') {
t->tokno = read_quoted(t->vstr, c); /* detect missing end quote */
break;
} else if (ISDOT(c)) {
COLLECT(t->vstr, c, ISDOT(c));
t->tokno = TOK_OTHER;
break;
} else if (c == '#' && last_tokno == '\n') {
do_control();
continue;
} else {
t->vstr->str[0] = c;
if (c == '\n') {
in_line++;
if (nl_compensate > 0) { /* compensation for bs-nl */
UNPUT('\n');
nl_compensate--;
}
} else if (c == '/') {
if ((INPUT(d)) == '*') {
t->vstr->str[1] = d; /* comment */
read_comment(t->vstr);
t->tokno = TOK_WSPACE;
break;
} else {
if (d != EOF)
UNPUT(d);
}
} else if (c == '\\') {
t->vstr->str[1] = (INPUT(c) == EOF ? 0 : c);
t->vstr->str[2] = 0;
t->tokno = TOK_OTHER;
break;
}
t->vstr->str[1] = 0;
t->tokno = c;
break;
}
}
last_tokno = t->tokno;
t->end_line = in_line;
return (t);
}
/* read_quoted - read string or character literal, canonicalize escapes */
static int read_quoted(vs, ch)
register struct vstring *vs;
int ch;
{
register char *cp = vs->str;
register int c;
int ret = TOK_OTHER;
*cp++ = ch;
/*
* Clobber the token type in case of a premature newline or EOF. This
* prevents us from attempting to concatenate string constants with
* broken ones that have no closing quote.
*/
while (INPUT(c) != EOF) {
if (c == '\n') { /* newline in string */
UNPUT(c);
break;
}
if (VS_ADDCH(vs, cp, c) == 0) /* store character */
fatal("out of memory");
if (c == ch) { /* closing quote */
ret = c;
break;
}
if (c == '\\') { /* parse escape sequence */
if ((INPUT(c)) == EOF) { /* EOF, punt */
break;
} else if (c == 'a') { /* \a -> audible bell */
if ((cp = vs_strcpy(vs, cp, BELL)) == 0)
fatal("out of memory");
} else if (c == 'x') { /* \xhh -> \nnn */
cp = read_hex(vs, cp);
} else if (ISOCTAL(c) && ch != '\'') {
cp = read_octal(vs, cp, c); /* canonicalize \octal */
} else {
if (VS_ADDCH(vs, cp, c) == 0) /* \other: leave alone */
fatal("out of memory");
}
}
}
*cp = 0;
return (ret);
}
/* read_comment - stuff a whole comment into one huge token */
static void read_comment(vs)
register struct vstring *vs;
{
register char *cp = vs->str + 2; /* skip slash star */
register int c;
register int d;
while (INPUT(c) != EOF) {
if (VS_ADDCH(vs, cp, c) == 0)
fatal("out of memory");
if (c == '*') {
if ((INPUT(d)) == '/') {
if (VS_ADDCH(vs, cp, d) == 0)
fatal("out of memory");
break;
} else {
if (d != EOF)
UNPUT(d);
}
} else if (c == '\n') {
in_line++;
} else if (c == '\\') {
if ((INPUT(d)) != EOF && VS_ADDCH(vs, cp, d) == 0)
fatal("out of memory");
}
}
*cp = 0;
}
/* read_hex - rewrite hex escape to three-digit octal escape */
static char *read_hex(vs, cp)
struct vstring *vs;
register char *cp;
{
register int c;
register int i;
char buf[BUFSIZ];
int len;
unsigned val;
/*
* Eat up all subsequent hex digits. Complain later when there are too
* many.
*/
for (i = 0; i < sizeof(buf) && (INPUT(c) != EOF) && ISHEX(c); i++)
buf[i] = c;
buf[i] = 0;
if (i < sizeof(buf) && c)
UNPUT(c);
/*
* Convert hex form to three-digit octal form. The three-digit form is
* used so that strings can be concatenated without problems. Complain
* about malformed input; truncate the result to at most three octal
* digits.
*/
if (i == 0) {
error("\\x escape sequence without hexadecimal digits");
if (VS_ADDCH(vs, cp, 'x') == 0)
fatal("out of memory");
} else {
(void) sscanf(buf, "%x", &val);
sprintf(buf, "%03o", val);
if ((len = strlen(buf)) > 3)
error("\\x escape sequence yields non-character value");
if ((cp = vs_strcpy(vs, cp, buf + len - 3)) == 0)
fatal("out of memory");
}
return (cp);
}
/* read_octal - convert octal escape to three-digit format */
static char obuf[] = "00123";
static char *read_octal(vs, cp, c)
register struct vstring *vs;
register char *cp;
register int c;
{
register int i;
#define buf_input (obuf + 2)
/* Eat up at most three octal digits. */
buf_input[0] = c;
for (i = 1; i < 3 && (INPUT(c) != EOF) && ISOCTAL(c); i++)
buf_input[i] = c;
buf_input[i] = 0;
if (i < 3 && c)
UNPUT(c);
/*
* Leave three-digit octal escapes alone. Convert one-digit and two-digit
* octal escapes to three-digit form by prefixing them with a suitable
* number of '0' characters. This is done so that strings can be
* concatenated without problems.
*/
if ((cp = vs_strcpy(vs, cp, buf_input + i - 3)) == 0)
fatal("out of memory");
return (cp);
}
/* put_nl - emit newline and adjust output line count */
void put_nl()
{
put_ch('\n');
out_line++;
}
/* fix_line_control - to adjust path and/or line count info in output */
static void fix_line_control(path, line)
register char *path;
register int line;
{
/*
* This function is called sporadically, so it should not be a problem
* that we repeat some of the tests that preceded this function call.
*
* Emit a newline if we are not at the start of a line.
*
* If we switch files, or if we jump backwards, emit line control. If we
* jump forward, emit the proper number of newlines to compensate.
*/
if (last_ch != '\n') /* terminate open line */
put_nl();
if (path != out_path || line < out_line) { /* file switch or back jump */
printf("# %d %s\n", out_line = line, out_path = path);
last_ch = '\n';
} else { /* forward jump */
while (line > out_line)
put_nl();
}
}
/* tok_show_ch - output single-character token (not newline) */
void tok_show_ch(t)
register struct token *t;
{
CHECK_LINE_CONTROL(t->path, t->line);
put_ch(t->tokno); /* show token contents */
}
/* tok_show - output (possibly composite) token */
void tok_show(t)
register struct token *t;
{
register struct token *p;
if (t->tokno == TOK_LIST) {
register struct token *s;
/*
* This branch is completely in terms of tok_xxx() primitives, so
* there is no need to check the line control information.
*/
for (s = t->head; s; s = s->next) {
tok_show_ch(s); /* '(' or ',' or ')' */
for (p = s->head; p; p = p->next)
tok_show(p); /* show list element */
}
} else {
register char *cp = t->vstr->str;
/*
* Measurements show that it pays off to give special treatment to
* single-character tokens. Note that both types of token may cause a
* change of output line number.
*/
CHECK_LINE_CONTROL(t->path, t->line);
if (cp[1] == 0) {
put_ch(*cp); /* single-character token */
} else {
put_str(cp); /* multi_character token */
}
out_line = t->end_line; /* may span multiple lines */
for (p = t->head; p; p = p->next)
tok_show(p); /* trailing blanks */
}
}

103
build/unproto/tok_pool.c Normal file
View File

@ -0,0 +1,103 @@
/*++
/* NAME
/* tok_pool 3
/* SUMMARY
/* maintain pool of unused token structures
/* PACKAGE
/* unproto
/* SYNOPSIS
/* #include "token.h"
/*
/* struct token *tok_alloc()
/*
/* void tok_free(t)
/* struct token *t;
/* DESCRIPTION
/* tok_alloc() and tok_free() maintain a pool of unused token
/* structures.
/*
/* tok_alloc() takes the first free token structure from the pool
/* or allocates a new one if the pool is empty.
/*
/* tok_free() adds a (possibly composite) token structure to the pool.
/* BUGS
/* The pool never shrinks.
/* AUTHOR(S)
/* Wietse Venema
/* Eindhoven University of Technology
/* Department of Mathematics and Computer Science
/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
/* LAST MODIFICATION
/* 92/01/15 21:53:04
/* VERSION/RELEASE
/* 1.2
/*--*/
static char pool_sccsid[] = "@(#) tok_pool.c 1.2 92/01/15 21:53:04";
/* C library */
extern char *malloc();
/* Application-specific stuff */
#include "token.h"
#include "vstring.h"
#include "error.h"
#define TOKLEN 5 /* initial string buffer length */
struct token *tok_pool = 0; /* free token pool */
/* tok_alloc - allocate token structure from pool or heap */
struct token *tok_alloc()
{
register struct token *t;
if (tok_pool) { /* re-use an old one */
t = tok_pool;
tok_pool = t->next;
} else { /* create a new one */
if ((t = (struct token *) malloc(sizeof(struct token))) == 0
|| (t->vstr = vs_alloc(TOKLEN)) == 0)
fatal("out of memory");
}
t->next = t->head = t->tail = 0;
#ifdef DEBUG
strcpy(t->vstr->str, "BUSY");
#endif
return (t);
}
/* tok_free - return (possibly composite) token to pool of free tokens */
void tok_free(t)
register struct token *t;
{
#ifdef DEBUG
/* Check if we are freeing free token */
register struct token *p;
for (p = tok_pool; p; p = p->next)
if (p == t)
fatal("freeing free token");
#endif
/* Free neighbours and subordinates first */
if (t->next)
tok_free(t->next);
if (t->head)
tok_free(t->head);
/* Free self */
t->next = tok_pool;
t->head = t->tail = 0;
tok_pool = t;
#ifdef DEBUG
strcpy(t->vstr->str, "FREE");
#endif
}

55
build/unproto/token.h Normal file
View File

@ -0,0 +1,55 @@
/* @(#) token.h 1.4 92/01/15 21:53:17 */
struct token {
int tokno; /* token value, see below */
char *path; /* file name */
int line; /* line number at token start */
int end_line; /* line number at token end */
struct vstring *vstr; /* token contents */
struct token *next;
struct token *head;
struct token *tail;
};
/* Special token values */
#define TOK_LIST 256 /* () delimited list */
#define TOK_WORD 257 /* keyword or identifier */
#define TOK_NUMBER 258 /* one or more digits */
#define TOK_WSPACE 259 /* comment, white space, not newline */
#define TOK_OTHER 260 /* other token */
#define TOK_CONTROL 261 /* flow control keyword */
#define TOK_COMPOSITE 262 /* struct or union keyword */
#define TOK_DATE 263 /* date: Mmm dd yyyy */
#define TOK_TIME 264 /* time: hh:mm:ss */
#define TOK_VOID 265 /* void keyword */
/* Input/output functions and macros */
extern struct token *tok_get(); /* read next single token */
extern void tok_show(); /* display (composite) token */
extern struct token *tok_class(); /* classify tokens */
extern void tok_unget(); /* stuff token back into input */
extern void put_nl(); /* print newline character */
extern void tok_show_ch(); /* emit single-character token */
#define tok_flush(t) (tok_show(t), tok_free(t))
#ifdef DEBUG
#define put_ch(c) (putchar(last_ch = c),fflush(stdout))
#define put_str(s) (fputs(s,stdout),last_ch = 0,fflush(stdout))
#else
#define put_ch(c) putchar(last_ch = c)
#define put_str(s) (fputs(s,stdout),last_ch = 0)
#endif
/* Memory management */
struct token *tok_alloc(); /* allocate token storage */
extern void tok_free(); /* re-cycle storage */
/* Context */
extern char *in_path; /* current input path name */
extern int in_line; /* current input line number */
extern int last_ch; /* type of last output */

152
build/unproto/unproto.1 Normal file
View File

@ -0,0 +1,152 @@
.TH UNPROTO 1
.ad
.fi
.SH NAME
unproto
\-
compile ANSI C with traditional UNIX C compiler
.SH PACKAGE
.na
.nf
unproto
.SH SYNOPSIS
.na
.nf
/somewhere/cpp ...
cc cflags -E file.c | unproto >file.i; cc cflags -c file.i
.SH DESCRIPTION
.ad
.fi
This document describes a filter that sits in between the UNIX
C preprocessor and the next UNIX C compiler stage, on the fly rewriting
ANSI-style syntax to old-style syntax. Typically, the program is
invoked by the native UNIX C compiler as an alternate preprocessor.
The unprototyper in turn invokes the native C preprocessor and
massages its output. Similar tricks can be used with the lint(1)
command.
Language constructs that are always rewritten:
.TP
function headings, prototypes, pointer types
ANSI-C style function headings, function prototypes, function
pointer types and type casts are rewritten to old style.
<stdarg.h> support is provided for functions with variable-length
argument lists.
.TP
character and string constants
The \\a and \\x escape sequences are rewritten to their (three-digit)
octal equivalents.
Multiple string tokens are concatenated; an arbitrary number of
whitespace or comment tokens may appear between successive
string tokens.
Within string constants, octal escape sequences are rewritten to the
three-digit \\ddd form, so that string concatenation produces correct
results.
.TP
date and time
The __DATE__ and __TIME__ tokens are replaced by string constants
of the form "Mmm dd yyyy" and "hh:mm:ss", respectively. The result
is subjected to string concatenation, just like any other string
constant.
.PP
Language constructs that are rewritten only if the program has been
configured to do so:
.TP
void types
The unprototyper can be configured to rewrite "void *" to "char *",
and even to rewrite plain "void" to "int".
These features are configurable because many traditional UNIX C
compilers do not need them.
Note: (void) argument lists are always replaced by empty ones.
.PP
ANSI C constructs that are not rewritten because the traditional
UNIX C preprocessor provides suitable workarounds:
.TP
const and volatile
Use the "-Dconst=" and/or "-Dvolatile=" preprocessor directives to
get rid of unimplemented keywords.
.TP
token pasting and stringizing
The traditional UNIX C preprocessor provides excellent alternatives.
For example:
.nf
.ne 2
#define string(bar) "bar" /* instead of: # x */
#define paste(x,y) x/**\/y /* instead of: x##y */
.fi
There is a good reason why the # and ## operators are not implemented
in the unprototyper.
After program text has gone through a non-ANSI C preprocessor, all
information about the grouping of the operands of # and ## is lost.
Thus, if the unprototyper were to perform these operations, it would
produce correct results only in the most trivial cases. Operands
with embedded blanks, operands that expand to null tokens, and nested
use of # and/or ## would cause all kinds of obscure problems.
.PP
Unsupported ANSI features:
.TP
trigraphs and #pragmas
Trigraphs are useful only for systems with broken character sets.
If the local compiler chokes on #pragma, insert a blank before the
"#" character, and enclose the offending directive between #ifdef
and #endif.
.SH SEE ALSO
.na
.nf
.ad
.fi
cc(1), how to specify a non-default C preprocessor.
Some versions of the lint(1) command are implemented as a shell
script. It should require only minor modification for integration
with the unprototyper. Other versions of the lint(1) command accept
the same command syntax as the C compiler for the specification of a
non-default preprocessor. Some research may be needed.
.SH FILES
.na
.nf
/wherever/stdarg.h, provided with the unproto filter.
.SH DIAGNOSTICS
.ad
.fi
Problems are reported on the standard error stream.
A non-zero exit status means that there was a problem.
.SH BUGS
.ad
.fi
The unprototyper should be run on preprocessed source only:
unexpanded macros may confuse the program.
Declarations of (object) are misunderstood and will result in
syntax errors: the objects between parentheses disappear.
Sometimes does not preserve whitespace after parentheses and commas.
This is a purely aesthetical matter, and the compiler should not care.
Whitespace within string constants is, of course, left intact.
Does not generate explicit type casts for function-argument
expressions. The lack of explicit conversions between integral
and/or pointer argument types should not be a problem in environments
where sizeof(int) == sizeof(long) == sizeof(pointer). A more serious
problem is the lack of automatic type conversions between integral and
floating-point argument types. Let lint(1) be your friend.
.SH AUTHOR(S)
.na
.nf
Wietse Venema (wietse@wzv.win.tue.nl)
Eindhoven University of Technology
Department of Mathematics and Computer Science
Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
.SH LAST MODIFICATION
.na
.nf
93/06/18 22:29:37
.SH VERSION/RELEASE
.na
.nf
1.6

999
build/unproto/unproto.c Normal file
View File

@ -0,0 +1,999 @@
/*++
/* NAME
/* unproto 1
/* SUMMARY
/* compile ANSI C with traditional UNIX C compiler
/* PACKAGE
/* unproto
/* SYNOPSIS
/* /somewhere/cpp ...
/*
/* cc cflags -E file.c | unproto >file.i; cc cflags -c file.i
/* DESCRIPTION
/* This document describes a filter that sits in between the UNIX
/* C preprocessor and the next UNIX C compiler stage, on the fly rewriting
/* ANSI-style syntax to old-style syntax. Typically, the program is
/* invoked by the native UNIX C compiler as an alternate preprocessor.
/* The unprototyper in turn invokes the native C preprocessor and
/* massages its output. Similar tricks can be used with the lint(1)
/* command.
/*
/* Language constructs that are always rewritten:
/* .TP
/* function headings, prototypes, pointer types
/* ANSI-C style function headings, function prototypes, function
/* pointer types and type casts are rewritten to old style.
/* <stdarg.h> support is provided for functions with variable-length
/* argument lists.
/* .TP
/* character and string constants
/* The \\a and \\x escape sequences are rewritten to their (three-digit)
/* octal equivalents.
/*
/* Multiple string tokens are concatenated; an arbitrary number of
/* whitespace or comment tokens may appear between successive
/* string tokens.
/*
/* Within string constants, octal escape sequences are rewritten to the
/* three-digit \\ddd form, so that string concatenation produces correct
/* results.
/* .TP
/* date and time
/* The __DATE__ and __TIME__ tokens are replaced by string constants
/* of the form "Mmm dd yyyy" and "hh:mm:ss", respectively. The result
/* is subjected to string concatenation, just like any other string
/* constant.
/* .PP
/* Language constructs that are rewritten only if the program has been
/* configured to do so:
/* .TP
/* void types
/* The unprototyper can be configured to rewrite "void *" to "char *",
/* and even to rewrite plain "void" to "int".
/* These features are configurable because many traditional UNIX C
/* compilers do not need them.
/*
/* Note: (void) argument lists are always replaced by empty ones.
/* .PP
/* ANSI C constructs that are not rewritten because the traditional
/* UNIX C preprocessor provides suitable workarounds:
/* .TP
/* const and volatile
/* Use the "-Dconst=" and/or "-Dvolatile=" preprocessor directives to
/* get rid of unimplemented keywords.
/* .TP
/* token pasting and stringizing
/* The traditional UNIX C preprocessor provides excellent alternatives.
/* For example:
/*
/* .nf
/* .ne 2
/* #define string(bar) "bar" /* instead of: # x */
/* #define paste(x,y) x/**\/y /* instead of: x##y */
/* .fi
/*
/* There is a good reason why the # and ## operators are not implemented
/* in the unprototyper.
/* After program text has gone through a non-ANSI C preprocessor, all
/* information about the grouping of the operands of # and ## is lost.
/* Thus, if the unprototyper were to perform these operations, it would
/* produce correct results only in the most trivial cases. Operands
/* with embedded blanks, operands that expand to null tokens, and nested
/* use of # and/or ## would cause all kinds of obscure problems.
/* .PP
/* Unsupported ANSI features:
/* .TP
/* trigraphs and #pragmas
/* Trigraphs are useful only for systems with broken character sets.
/* If the local compiler chokes on #pragma, insert a blank before the
/* "#" character, and enclose the offending directive between #ifdef
/* and #endif.
/* SEE ALSO
/* .ad
/* .fi
/* cc(1), how to specify a non-default C preprocessor.
/* Some versions of the lint(1) command are implemented as a shell
/* script. It should require only minor modification for integration
/* with the unprototyper. Other versions of the lint(1) command accept
/* the same command syntax as the C compiler for the specification of a
/* non-default preprocessor. Some research may be needed.
/* FILES
/* /wherever/stdarg.h, provided with the unproto filter.
/* DIAGNOSTICS
/* Problems are reported on the standard error stream.
/* A non-zero exit status means that there was a problem.
/* BUGS
/* The unprototyper should be run on preprocessed source only:
/* unexpanded macros may confuse the program.
/*
/* Declarations of (object) are misunderstood and will result in
/* syntax errors: the objects between parentheses disappear.
/*
/* Sometimes does not preserve whitespace after parentheses and commas.
/* This is a purely aesthetical matter, and the compiler should not care.
/* Whitespace within string constants is, of course, left intact.
/*
/* Does not generate explicit type casts for function-argument
/* expressions. The lack of explicit conversions between integral
/* and/or pointer argument types should not be a problem in environments
/* where sizeof(int) == sizeof(long) == sizeof(pointer). A more serious
/* problem is the lack of automatic type conversions between integral and
/* floating-point argument types. Let lint(1) be your friend.
/* AUTHOR(S)
/* Wietse Venema (wietse@wzv.win.tue.nl)
/* Eindhoven University of Technology
/* Department of Mathematics and Computer Science
/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
/* LAST MODIFICATION
/* 93/06/18 22:29:37
/* VERSION/RELEASE
/* 1.6
/*--*/
static char unproto_sccsid[] = "@(#) unproto.c 1.6 93/06/18 22:29:37";
/* C library */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
extern void exit();
extern int optind;
extern char *optarg;
extern int getopt();
/* Application-specific stuff */
#include "vstring.h"
#include "stdarg.h"
#include "token.h"
#include "error.h"
#include "symbol.h"
/* Forward declarations. */
static struct token *dcl_flush();
static void block_flush();
static void block_dcls();
static struct token *show_func_ptr_type();
static struct token *show_struct_type();
static void show_arg_name();
static void show_type();
static void pair_flush();
static void check_cast();
static void show_empty_list();
#define check_cast_flush(t) (check_cast(t), tok_free(t))
#ifdef PIPE_THROUGH_CPP
static int pipe_stdin_through_cpp();
#endif
/* Disable debugging printfs while preserving side effects. */
#ifdef DEBUG
#define DPRINTF printf
#else
#define DPRINTF (void)
#endif
/* An attempt to make some complicated expressions a bit more readable. */
#define STREQ(x,y) (*(x) == *(y) && !strcmp((x),(y)))
#define LAST_ARG_AND_EQUAL(s,c) ((s)->next && (s)->next->next == 0 \
&& (s)->head && ((s)->head == (s)->tail) \
&& (STREQ((s)->head->vstr->str, (c))))
#define LIST_BEGINS_WITH_STAR(s) (s->head->head && s->head->head->tokno == '*')
#define IS_FUNC_PTR_TYPE(s) (s->tokno == TOK_LIST && s->next \
&& s->next->tokno == TOK_LIST \
&& LIST_BEGINS_WITH_STAR(s))
/* What to look for to detect a (void) argument list. */
#ifdef MAP_VOID
#define VOID_ARG "int" /* bare "void" is mapped to "int" */
#else
#define VOID_ARG "void" /* bare "void" is left alone */
#endif
/* main - driver */
int main(argc, argv)
int argc;
char **argv;
{
register struct token *t;
#ifdef PIPE_THROUGH_CPP /* pipe through /lib/cpp */
int cpp_status;
int wait_pid;
int cpp_pid;
cpp_pid = pipe_stdin_through_cpp(argv);
#endif
sym_init(); /* prime the symbol table */
while (t = tok_class()) {
if (t = dcl_flush(t)) { /* try declaration */
if (t->tokno == '{') { /* examine rejected token */
block_flush(t); /* body */
} else {
tok_flush(t); /* other, recover */
}
}
}
#ifdef PIPE_THROUGH_CPP /* pipe through /lib/cpp */
while ((wait_pid = wait(&cpp_status)) != -1 && wait_pid != cpp_pid)
/* void */ ;
return (errcount != 0 || wait_pid != cpp_pid || cpp_status != 0);
#else
return (errcount != 0);
#endif
}
#ifdef PIPE_THROUGH_CPP /* pipe through /lib/cpp */
/* pipe_stdin_through_cpp - avoid shell script overhead */
static int pipe_stdin_through_cpp(argv)
char **argv;
{
int pipefds[2];
int pid;
char **cpptr = argv;
int i;
struct stat st;
/*
* The code that sets up the pipe requires that file descriptors 0,1,2
* are already open. All kinds of mysterious things will happen if that
* is not the case. The following loops makes sure that descriptors 0,1,2
* are set up properly.
*/
for (i = 0; i < 3; i++) {
if (fstat(i, &st) == -1 && open("/dev/null", 2) != i) {
perror("open /dev/null");
exit(1);
}
}
/*
* With most UNIX implementations, the second non-option argument to
* /lib/cpp specifies the output file. If an output file other than
* stdout is specified, we must force /lib/cpp to write to stdout, and we
* must redirect our own standard output to the specified output file.
*/
#define IS_OPTION(cp) ((cp)[0] == '-' && (cp)[1] != 0)
/* Skip to first non-option argument, if any. */
while (*++cpptr && IS_OPTION(*cpptr))
/* void */ ;
/*
* Assume that the first non-option argument is the input file name. The
* next argument could be the output destination or an option (System V
* Release 2 /lib/cpp gets the options *after* the file arguments).
*/
if (*cpptr && *++cpptr && **cpptr != '-') {
/*
* The first non-option argument is followed by another argument that
* is not an option ("-stuff") or a hyphen ("-"). Redirect our own
* standard output before we clobber the file name.
*/
if (freopen(*cpptr, "w", stdout) == 0) {
perror(*cpptr);
exit(1);
}
/* Clobber the file name argument so that /lib/cpp writes to stdout */
*cpptr = "-";
}
/* Set up the pipe that connects /lib/cpp to our standard input. */
if (pipe(pipefds)) {
perror("pipe");
exit(1);
}
switch (pid = fork()) {
case -1: /* error */
perror("fork");
exit(1);
/* NOTREACHED */
case 0: /* child */
(void) close(pipefds[0]); /* close reading end */
(void) close(1); /* connect stdout to pipe */
if (dup(pipefds[1]) != 1)
fatal("dup() problem");
(void) close(pipefds[1]); /* close redundant fd */
(void) execv(PIPE_THROUGH_CPP, argv);
perror(PIPE_THROUGH_CPP);
exit(1);
/* NOTREACHED */
default: /* parent */
(void) close(pipefds[1]); /* close writing end */
(void) close(0); /* connect stdin to pipe */
if (dup(pipefds[0]) != 0)
fatal("dup() problem");
close(pipefds[0]); /* close redundant fd */
return (pid);
}
}
#endif
/* show_arg_names - display function argument names */
static void show_arg_names(t)
register struct token *t;
{
register struct token *s;
/* Do argument names, but suppress void and rewrite trailing ... */
if (LAST_ARG_AND_EQUAL(t->head, VOID_ARG)) {
show_empty_list(t); /* no arguments */
} else {
for (s = t->head; s; s = s->next) { /* foreach argument... */
if (LAST_ARG_AND_EQUAL(s, "...")) {
#ifdef _VA_ALIST_ /* see ./stdarg.h */
tok_show_ch(s); /* ',' */
put_str(_VA_ALIST_); /* varargs magic */
#endif
} else {
tok_show_ch(s); /* '(' or ',' or ')' */
show_arg_name(s); /* extract argument name */
}
}
}
}
/* show_arg_types - display function argument types */
static void show_arg_types(t)
register struct token *t;
{
register struct token *s;
/* Do argument types, but suppress void and trailing ... */
if (!LAST_ARG_AND_EQUAL(t->head, VOID_ARG)) {
for (s = t->head; s; s = s->next) { /* foreach argument... */
if (LAST_ARG_AND_EQUAL(s, "...")) {
#ifdef _VA_DCL_ /* see ./stdarg.h */
put_str(_VA_DCL_); /* varargs magic */
put_nl(); /* make output look nicer */
#endif
} else {
if (s->head != s->tail) { /* really new-style argument? */
show_type(s); /* rewrite type info */
put_ch(';');
put_nl(); /* make output look nicer */
}
}
}
}
}
/* header_flush - rewrite new-style function heading to old style */
static void header_flush(t)
register struct token *t;
{
show_arg_names(t); /* show argument names */
put_nl(); /* make output look nicer */
show_arg_types(t); /* show argument types */
tok_free(t); /* discard token */
}
/* fpf_header_names - define func returning ptr to func, no argument types */
static void fpf_header_names(list)
struct token *list;
{
register struct token *s;
register struct token *p;
/*
* Recurse until we find the argument list. Account for the rare case
* that list is a comma-separated list (which should be a syntax error).
* Display old-style fuction argument names.
*/
for (s = list->head; s; s = s->next) {
tok_show_ch(s); /* '(' or ',' or ')' */
for (p = s->head; p; p = p->next) {
if (p->tokno == TOK_LIST) {
if (IS_FUNC_PTR_TYPE(p)) { /* recurse */
fpf_header_names(p);
show_empty_list(p = p->next);
} else { /* display argument names */
show_arg_names(p);
}
} else { /* pass through other stuff */
tok_show(p);
}
}
}
}
/* fpf_header_types - define func returning ptr to func, argument types only */
static void fpf_header_types(list)
struct token *list;
{
register struct token *s;
register struct token *p;
/*
* Recurse until we find the argument list. Account for the rare case
* that list is a comma-separated list (which should be a syntax error).
* Display old-style function argument types.
*/
for (s = list->head; s; s = s->next) {
for (p = s->head; p; p = p->next) {
if (p->tokno == TOK_LIST) {
if (IS_FUNC_PTR_TYPE(p)) { /* recurse */
fpf_header_types(p);
p = p->next;
} else { /* display argument types */
show_arg_types(p);
}
}
}
}
}
/* fpf_header - define function returning pointer to function */
static void fpf_header(l1, l2)
struct token *l1;
struct token *l2;
{
fpf_header_names(l1); /* strip argument types */
show_empty_list(l2); /* strip prototype */
put_nl(); /* nicer output */
fpf_header_types(l1); /* show argument types */
}
/* skip_enclosed - skip over enclosed tokens */
static struct token *skip_enclosed(p, stop)
register struct token *p;
register int stop;
{
register int start = p->tokno;
/* Always return a pointer to the last processed token, never NULL. */
while (p->next) {
p = p->next;
if (p->tokno == start) {
p = skip_enclosed(p, stop); /* recurse */
} else if (p->tokno == stop) {
break; /* done */
}
}
return (p);
}
/* show_arg_name - extract argument name from argument type info */
static void show_arg_name(s)
register struct token *s;
{
if (s->head) {
register struct token *p;
register struct token *t = 0;
/* Find the last interesting item. */
for (p = s->head; p; p = p->next) {
if (p->tokno == TOK_WORD) {
t = p; /* remember last word */
} else if (p->tokno == '{') {
p = skip_enclosed(p, '}'); /* skip structured stuff */
} else if (p->tokno == '[') {
break; /* dimension may be a macro */
} else if (IS_FUNC_PTR_TYPE(p)) {
t = p; /* or function pointer */
p = p->next;
}
}
/* Extract argument name from last interesting item. */
if (t) {
if (t->tokno == TOK_LIST)
show_arg_name(t->head); /* function pointer, recurse */
else
tok_show(t); /* print last word */
}
}
}
/* show_type - rewrite type to old-style syntax */
static void show_type(s)
register struct token *s;
{
register struct token *p;
/*
* Rewrite (*stuff)(args) to (*stuff)(). Rewrite word(args) to word(),
* but only if the word was preceded by a word, '*' or '}'. Leave
* anything else alone.
*/
for (p = s->head; p; p = p->next) {
if (IS_FUNC_PTR_TYPE(p)) {
p = show_func_ptr_type(p, p->next); /* function pointer type */
} else {
register struct token *q;
register struct token *r;
tok_show(p); /* other */
if ((p->tokno == TOK_WORD || p->tokno == '*' || p->tokno == '}')
&& (q = p->next) && q->tokno == TOK_WORD
&& (r = q->next) && r->tokno == TOK_LIST) {
tok_show(q); /* show name */
show_empty_list(p = r); /* strip args */
}
}
}
}
/* show_func_ptr_type - display function_pointer type using old-style syntax */
static struct token *show_func_ptr_type(t1, t2)
struct token *t1;
struct token *t2;
{
register struct token *s;
/*
* Rewrite (list1) (list2) to (list1) (). Account for the rare case that
* (list1) is a comma-separated list. That should be an error, but we do
* not want to waste any information.
*/
for (s = t1->head; s; s = s->next) {
tok_show_ch(s); /* '(' or ',' or ')' */
show_type(s); /* recurse */
}
show_empty_list(t2);
return (t2);
}
/* show_empty_list - display opening and closing parentheses (if available) */
static void show_empty_list(t)
register struct token *t;
{
tok_show_ch(t->head); /* opening paren */
if (t->tail->tokno == ')')
tok_show_ch(t->tail); /* closing paren */
}
/* show_struct_type - display structured type, rewrite function-pointer types */
static struct token *show_struct_type(p)
register struct token *p;
{
tok_show(p); /* opening brace */
while (p->next) { /* XXX cannot return 0 */
p = p->next;
if (IS_FUNC_PTR_TYPE(p)) {
p = show_func_ptr_type(p, p->next); /* function-pointer member */
} else if (p->tokno == '{') {
p = show_struct_type(p); /* recurse */
} else {
tok_show(p); /* other */
if (p->tokno == '}') {
return (p); /* done */
}
}
}
DPRINTF("/* missing '}' */");
return (p);
}
/* is_func_ptr_cast - recognize function-pointer type cast */
static int is_func_ptr_cast(t)
register struct token *t;
{
register struct token *p;
/*
* Examine superficial structure. Require (list1) (list2). Require that
* list1 begins with a star.
*/
if (!IS_FUNC_PTR_TYPE(t))
return (0);
/*
* Make sure that there is no name in (list1). Do not worry about
* unexpected tokens, because the compiler will complain anyway.
*/
for (p = t->head->head; p; p = p->next) {
switch (p->tokno) {
case TOK_LIST: /* recurse */
return (is_func_ptr_cast(p));
case TOK_WORD: /* name in list */
return (0);
case '[':
return (1); /* dimension may be a macro */
}
}
return (1); /* no name found */
}
/* check_cast - display ()-delimited, comma-separated list */
static void check_cast(t)
struct token *t;
{
register struct token *s;
register struct token *p;
/*
* Rewrite function-pointer types and function-pointer casts. Do not
* blindly rewrite (*list1)(list2) to (*list1)(). Function argument lists
* are about the only thing we can discard without provoking diagnostics
* from the compiler.
*/
for (s = t->head; s; s = s->next) {
tok_show_ch(s); /* '(' or ',' or ')' */
for (p = s->head; p; p = p->next) {
switch (p->tokno) {
case TOK_LIST:
if (is_func_ptr_cast(p)) { /* not: IS_FUNC_PTR_TYPE(p) */
p = show_func_ptr_type(p, p->next);
} else {
check_cast(p); /* recurse */
}
break;
case '{':
p = show_struct_type(p); /* rewrite func. ptr. types */
break;
default:
tok_show(p);
break;
}
}
}
}
/* block_dcls - on the fly rewrite decls/initializers at start of block */
static void block_dcls()
{
register struct token *t;
/*
* Away from the top level, a declaration should be preceded by type or
* storage-class information. That is why inside blocks, structs and
* unions we insist on reading one word before passing the _next_ token
* to the dcl_flush() function.
*
* Struct and union declarations look the same everywhere: we make an
* exception for these more regular constructs and pass the "struct" and
* "union" tokens to the type_dcl() function.
*/
while (t = tok_class()) {
switch (t->tokno) {
case TOK_WSPACE: /* preserve white space */
case '\n': /* preserve line count */
tok_flush(t);
break;
case TOK_WORD: /* type declarations? */
tok_flush(t); /* advance to next token */
t = tok_class(); /* null return is ok */
/* FALLTRHOUGH */
case TOK_COMPOSITE: /* struct or union */
if ((t = dcl_flush(t)) == 0)
break;
/* FALLTRHOUGH */
default: /* end of declarations */
DPRINTF("/* end dcls */");
/* FALLTRHOUGH */
case '}': /* end of block */
tok_unget(t);
return;
}
}
}
/* block_flush - rewrite struct, union or statement block on the fly */
static void block_flush(t)
register struct token *t;
{
static int count = 0;
tok_flush(t);
DPRINTF("/*%d*/", ++count);
/*
* Rewrite function pointer types in declarations and function pointer
* casts in initializers at start of block.
*/
block_dcls();
/* Remainder of block: only rewrite function pointer casts. */
while (t = tok_class()) {
if (t->tokno == TOK_LIST) {
check_cast_flush(t);
} else if (t->tokno == '{') {
block_flush(t);
} else {
tok_flush(t);
if (t->tokno == '}') {
DPRINTF("/*%d*/", count--);
return;
}
}
}
DPRINTF("/* missing '}' */");
}
/* pair_flush - on the fly rewrite casts in grouped stuff */
static void pair_flush(t, start, stop)
register struct token *t;
register int start;
register int stop;
{
tok_flush(t);
while (t = tok_class()) {
if (t->tokno == start) { /* recurse */
pair_flush(t, start, stop);
} else if (t->tokno == TOK_LIST) { /* expression or cast */
check_cast_flush(t);
} else { /* other, copy */
tok_flush(t);
if (t->tokno == stop) { /* done */
return;
}
}
}
DPRINTF("/* missing '%c' */", stop);
}
/* initializer - on the fly rewrite casts in initializer */
static void initializer()
{
register struct token *t;
while (t = tok_class()) {
switch (t->tokno) {
case ',': /* list separator */
case ';': /* list terminator */
tok_unget(t);
return;
case TOK_LIST: /* expression or cast */
check_cast_flush(t);
break;
case '[': /* array subscript, may nest */
pair_flush(t, '[', ']');
break;
case '{': /* structured data, may nest */
pair_flush(t, '{', '}');
break;
default: /* other, just copy */
tok_flush(t);
break;
}
}
}
/* func_ptr_dcl_flush - rewrite function pointer stuff */
static struct token *func_ptr_dcl_flush(list)
register struct token *list;
{
register struct token *t;
register struct token *t2;
/*
* Ignore blanks and newlines because we are too lazy to maintain more
* than one token worth of lookahead. The output routines will regenerate
* discarded newline tokens.
*/
while (t = tok_class()) {
switch (t->tokno) {
case TOK_WSPACE:
case '\n':
tok_free(t);
break;
case TOK_LIST:
/* Function pointer or function returning pointer to function. */
while ((t2 = tok_class()) /* skip blanks etc. */
&&(t2->tokno == TOK_WSPACE || t2->tokno == '\n'))
tok_free(t2);
switch (t2 ? t2->tokno : 0) {
case '{': /* function heading (new) */
fpf_header(list, t);
break;
case TOK_WORD: /* function heading (old) */
tok_show(list);
tok_show(t);
break;
default: /* func pointer type */
(void) show_func_ptr_type(list, t);
break;
}
tok_free(list);
tok_free(t);
if (t2)
tok_unget(t2);
return (0);
default: /* not a declaration */
tok_unget(t);
return (list);
}
}
/* Hit EOF; must be mistake, but do not waste any information. */
return (list);
}
/* function_dcl_flush - rewrite function { heading, type declaration } */
static struct token *function_dcl_flush(list)
register struct token *list;
{
register struct token *t;
/*
* Ignore blanks and newlines because we are too lazy to maintain more
* than one token worth of lookahead. The output routines will regenerate
* ignored newline tokens.
*/
while (t = tok_class()) {
switch (t->tokno) {
case TOK_WSPACE:
case '\n':
tok_free(t);
break;
case '{':
/* Function heading: word (list) { -> old style heading */
header_flush(list);
tok_unget(t);
return (0);
case TOK_WORD:
/* Old-style function heading: word (list) word... */
tok_flush(list);
tok_unget(t);
return (0);
case TOK_LIST:
/* Function pointer: word (list1) (list2) -> word (list1) () */
tok_flush(list);
show_empty_list(t);
tok_free(t);
return (0);
case ',':
case ';':
/* Function type declaration: word (list) -> word () */
show_empty_list(list);
tok_free(list);
tok_unget(t);
return (0);
default:
/* Something else, reject the list. */
tok_unget(t);
return (list);
}
}
/* Hit EOF; must be mistake, but do not waste any information. */
return (list);
}
/* dcl_flush - parse declaration on the fly, return rejected token */
static struct token *dcl_flush(t)
register struct token *t;
{
register int got_word;
/*
* Away from the top level, type or storage-class information is required
* for an (extern or forward) function type declaration or a variable
* declaration.
*
* With our naive word-counting approach, this means that the caller should
* read one word before passing the next token to us. This is how we
* distinguish, for example, function declarations from function calls.
*
* An exception are structs and unions, because they look the same at any
* level. The caller should give is the "struct" or "union" token.
*/
for (got_word = 0; t; t = tok_class()) {
switch (t->tokno) {
case TOK_WSPACE: /* advance past blanks */
case '\n': /* advance past newline */
case '*': /* indirection: keep trying */
tok_flush(t);
break;
case TOK_WORD: /* word: keep trying */
case TOK_COMPOSITE: /* struct or union */
got_word = 1;
tok_flush(t);
break;
default:
/*
* Function pointer types can be preceded by zero or more words
* (at least one when not at the top level). Other stuff can be
* accepted only after we have seen at least one word (two words
* when not at the top level). See also the above comment on
* structs and unions.
*/
if (t->tokno == TOK_LIST && LIST_BEGINS_WITH_STAR(t)) {
if (t = func_ptr_dcl_flush(t)) {
return (t); /* reject token */
} else {
got_word = 1; /* for = and [ and , and ; */
}
} else if (got_word == 0) {
return (t); /* reject token */
} else {
switch (t->tokno) {
case TOK_LIST: /* function type */
if (t = function_dcl_flush(t))
return (t); /* reject token */
break;
case '[': /* dimension, does not nest */
pair_flush(t, '[', ']');
break;
case '=': /* initializer follows */
tok_flush(t);
initializer(); /* rewrite casts */
break;
case '{': /* struct, union, may nest */
block_flush(t); /* use code for stmt blocks */
break;
case ',': /* separator: keep trying */
got_word = 0;
tok_flush(t);
break;
case ';': /* terminator: succeed */
tok_flush(t);
return (0);
default: /* reject token */
return (t);
}
}
}
}
return (0); /* hit EOF */
}

32
build/unproto/varargs.c Normal file
View File

@ -0,0 +1,32 @@
/*
* @(#) varargs.c 1.1 91/09/01 23:08:45
*
* This program can be used to verify that the stdarg.h file is set up
* correctly for your system. If it works, it should print one line with the
* text "stdarg.h works".
*/
#include <stdio.h>
#include "stdarg.h"
main(int argc, char *argv[])
{
varargs_test("%s %s\n", "stdarg.h", "works");
}
varargs_test(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
while (*fmt) {
if (strncmp("%s", fmt, 2) == 0) {
fputs(va_arg(ap, char *), stdout);
fmt += 2;
} else {
putchar(*fmt);
fmt++;
}
}
va_end(ap);
}

122
build/unproto/vstring.c Normal file
View File

@ -0,0 +1,122 @@
/*++
/* NAME
/* vs_alloc(), VS_ADDCH()
/* SUMMARY
/* auto-resizing string library
/* PACKAGE
/* vstring
/* SYNOPSIS
/* #include "vstring.h"
/*
/* struct vstring *vs_alloc(len)
/* int len;
/*
/* int VS_ADDCH(vs, wp, ch)
/* struct vstring *vs;
/* char *wp;
/* int ch;
/*
/* char *vs_strcpy(vp, dst, src)
/* struct vstring *vp;
/* char *dst;
/* char *src;
/* DESCRIPTION
/* These functions and macros implement a small library for
/* arbitrary-length strings that grow automatically when
/* they fill up. The allocation strategy is such that there
/* will always be place for the terminating null character.
/*
/* vs_alloc() allocates storage for a variable-length string
/* of at least "len" bytes.
/*
/* VS_ADDCH() adds a character to a variable-length string
/* and automagically extends the string if fills up.
/* \fIvs\fP is a pointer to a vstring structure; \fIwp\fP
/* the current write position in the corresponding character
/* array; \fIch\fP the character value to be written.
/* Note that VS_ADDCH() is a macro that evaluates some
/* arguments more than once.
/*
/* vs_strcpy() appends a null-terminated string to a variable-length
/* string. \fIsrc\fP provides the data to be copied; \fIvp\fP is the
/* target, and \fIdst\fP the current write position within the target.
/* The result is null-terminated. The return value is the new write
/* position.
/* DIAGNOSTICS
/* VS_ADDCH() returns zero if it was unable to dynamically
/* resize a string.
/*
/* vs_alloc() returns a null pointer in case of problems.
/*
/* vs_strcpy() returns a null pointer if the request failed.
/* BUGS
/* Auto-resizing may change the address of the string data in
/* a vstring structure. Beware of dangling pointers.
/* AUTHOR(S)
/* Wietse Venema
/* Eindhoven University of Technology
/* Department of Mathematics and Computer Science
/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
/* LAST MODIFICATION
/* 92/01/15 21:53:06
/* VERSION/RELEASE
/* 1.3
/*--*/
static char vstring_sccsid[] = "@(#) vstring.c 1.3 92/01/15 21:53:06";
/* C library */
extern char *malloc();
extern char *realloc();
/* Application-specific stuff */
#include "vstring.h"
/* vs_alloc - initial string allocation */
struct vstring *vs_alloc(len)
int len;
{
register struct vstring *vp;
if (len < 1
|| (vp = (struct vstring *) malloc(sizeof(struct vstring))) == 0
|| (vp->str = malloc(len)) == 0)
return (0);
vp->last = vp->str + len - 1;
return (vp);
}
/* vs_realloc - extend string, update write pointer */
char *vs_realloc(vp, cp)
register struct vstring *vp;
char *cp;
{
int where = cp - vp->str;
int len = vp->last - vp->str + 1;
if ((vp->str = realloc(vp->str, len *= 2)) == 0)
return (0);
vp->last = vp->str + len - 1;
return (vp->str + where);
}
/* vs_strcpy - copy string */
char *vs_strcpy(vp, dst, src)
register struct vstring *vp;
register char *dst;
register char *src;
{
while (*src) {
if (VS_ADDCH(vp, dst, *src) == 0)
return (0);
src++;
}
*dst = '\0';
return (dst);
}

15
build/unproto/vstring.h Normal file
View File

@ -0,0 +1,15 @@
/* @(#) vstring.h 1.2 92/01/15 21:53:19 */
struct vstring {
char *str; /* string value */
char *last; /* last position */
};
extern struct vstring *vs_alloc(); /* initial allocation */
extern char *vs_realloc(); /* string extension */
extern char *vs_strcpy(); /* copy string */
/* macro to add one character to auto-resized string */
#define VS_ADDCH(vs,wp,c) \
((wp < (vs)->last || (wp = vs_realloc(vs,wp))) ? (*wp++ = c) : 0)

1
build/version Normal file
View File

@ -0,0 +1 @@
3.3

84
clients/Make-template Normal file
View File

@ -0,0 +1,84 @@
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# LDAP clients Makefile
#
#-----------------------------------------------------------------------------
############################################################################
# #
# You should not have to edit anything below this point #
# #
############################################################################
all: FORCE
@echo "making all in `$(PWD)`"
@for i in *; do \
if [ -d $$i -a $$i != "RCS" ]; then \
echo; echo " cd $$i; $(MAKE) $(MFLAGS) all"; \
( cd $$i; $(MAKE) $(MFLAGS) all ); \
fi; \
done
#
# rules to install the software
#
install: FORCE
@echo "making install in `$(PWD)`"
@for i in *; do \
if [ -d $$i -a $$i != "RCS" ]; then \
echo; echo " cd $$i; $(MAKE) $(MFLAGS) install"; \
( cd $$i; $(MAKE) $(MFLAGS) install ); \
fi; \
done
#
# rules to make clean
#
clean: FORCE
@echo "making clean in `$(PWD)`"
@for i in *; do \
if [ -d $$i -a $$i != "RCS" ]; then \
echo; echo " cd $$i; $(MAKE) $(MFLAGS) clean"; \
( cd $$i; $(MAKE) $(MFLAGS) clean ); \
fi; \
done
veryclean: clean
#
# rules to make depend
#
#
depend: FORCE
@echo "making depend in `$(PWD)`"
@for i in *; do \
if [ -d $$i -a $$i != "RCS" ]; then \
echo; echo " cd $$i; $(MAKE) $(MFLAGS) depend"; \
( cd $$i; $(MAKE) $(MFLAGS) depend ); \
fi; \
done
links:
@echo "making links in `$(PWD)`"; \
for i in .src/*; do \
if [ -d $$i -a $$i != ".src/RCS" ]; then \
d=`basename $$i`; \
( $(MKDIR) $$d; cd $$d; $(LN) ../.src/$$d .src; \
$(LN) ../.src/$$d/Make-template . ; \
$(MAKE) $(MFLAGS) MKDIR="$(MKDIR)" LN="$(LN)" \
-f Make-template links ) ; \
fi; \
done

View File

@ -0,0 +1,87 @@
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# X.500 ldap fax mailer makefile
#
#-----------------------------------------------------------------------------
LDAPSRC = ../..
HDIR = $(LDAPSRC)/include
LDIR = $(LDAPSRC)/libraries
VERSIONFILE = $(LDAPSRC)/build/version
SRCS = rp500.c main.c faxtotpc.c
OBJS = rp500.o main.o faxtotpc.o
INCLUDES= -I$(HDIR)
DEFINES = $(DEFS)
CFLAGS = $(INCLUDES) $(DEFINES) $(ACFLAGS)
LIBS = -lldap -llber $(KRBLIBFLAG) $(KRBLIBS) $(ALIBS)
all: rp500 fax500
rp500: rpversion.o
$(CC) $(ALDFLAGS) -o $@ faxtotpc.o rp500.o rpversion.o \
-L$(LDIR) $(LIBS)
fax500: fax5version.o
$(CC) $(ALDFLAGS) -o $@ main.o fax5version.o faxtotpc.o \
-L$(LDIR) $(LIBS)
rpversion.c: faxtotpc.o rp500.o $(LDIR)/libldap.a
$(RM) $@
(u=$${USER-root} v=`$(CAT) $(VERSIONFILE)` d=`$(PWD)` h=`$(HOSTNAME)` \
t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
-e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
-e "s|%VERSION%|$${v}|" \
< Versionrp.c > $@)
fax5version.c: main.o faxtotpc.o $(LDIR)/libldap.a
$(RM) $@
(u=$${USER-root} v=`$(CAT) $(VERSIONFILE)` d=`$(PWD)` h=`$(HOSTNAME)` \
t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
-e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
-e "s|%VERSION%|$${v}|" \
< Version.c > $@ )
install: rp500 xrpcomp fax500 FORCE
-$(MKDIR) -p $(ETCDIR) $(BINDIR)
$(INSTALL) $(INSTALLFLAGS) -m 755 rp500 $(ETCDIR)
$(SED) -e 's%ETCDIR%$(ETCDIR)%' xrpcomp > /tmp/xrpcomp.tmp
$(INSTALL) $(INSTALLFLAGS) -m 755 /tmp/xrpcomp.tmp $(BINDIR)/xrpcomp
$(RM) /tmp/xrpcomp.tmp
$(INSTALL) $(INSTALLFLAGS) -m 755 fax500 $(ETCDIR)
lint: FORCE
$(LINT) $(INCLUDES) $(DEFINES) $(SRCS)
5lint: FORCE
$(5LINT) $(INCLUDES) $(DEFINES) $(SRCS)
clean: FORCE
$(RM) *.o core a.out rpversion.c fax5version.c rp500 fax500
depend: FORCE
$(MKDEP) $(INCLUDES) $(DEFINES) $(SRCS)
links:
@$(LN) .src/README .src/xrpcomp .src/*.[ch] .
# DO NOT DELETE THIS LINE -- mkdep uses it.
# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
rp500.o: rp500.c ../../include/ldapconfig.h ../../include/lber.h
rp500.o: ../../include/ldap.h
main.o: main.c ../../include/ldapconfig.h ../../include/portable.h
main.o: ../../include/lber.h ../../include/ldap.h
faxtotpc.o: faxtotpc.c
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY

104
clients/fax500/README Normal file
View File

@ -0,0 +1,104 @@
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

13
clients/fax500/Version.c Normal file
View File

@ -0,0 +1,13 @@
/*
* 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.
*/
char Version[] = " fax500 v%VERSION% (%WHEN%)\n\t%WHOANDWHERE%\n";

View File

@ -0,0 +1,13 @@
/*
* 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.
*/
char Version[] = " rp500 v%VERSION% (%WHEN%)\n\t%WHOANDWHERE%\n";

248
clients/fax500/faxtotpc.c Normal file
View File

@ -0,0 +1,248 @@
/*
* 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(str)
* char *str;
*
* faxtotpc() returns a pointer to a string allocated with malloc(3).
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#ifdef ultrix
extern char *strdup();
#endif
#define TPCDOMAIN "tpc.int"
/*
* Remove everything from 'str' which is not a digit
*/
void strip_nonnum(str)
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(ibuf, obuf)
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(ibuf, obuf)
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(phone, userinfo)
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);
}

1499
clients/fax500/main.c Normal file

File diff suppressed because it is too large Load Diff

283
clients/fax500/rp500.c Normal file
View File

@ -0,0 +1,283 @@
/*
* 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 <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <syslog.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <signal.h>
#include <ldapconfig.h>
#include "lber.h"
#include "ldap.h"
#define DEFAULT_PORT 79
#define DEFAULT_SIZELIMIT 50
int debug;
char *ldaphost = LDAPHOST;
char *base = DEFAULT_BASE;
int deref;
int sizelimit;
LDAPFiltDesc *filtd;
static print_entry();
static
usage( name )
char *name;
{
fprintf( stderr, "usage: %s [-d debuglevel] [-x ldaphost] [-b searchbase] [-a] [-z sizelimit] [-f filterfile] searchstring\r\n", name );
exit( -1 );
}
main (argc, argv)
int argc;
char **argv;
{
int i, rc, matches;
char *filterfile = FILTERFILE;
struct timeval timeout;
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 };
extern char *optarg;
extern int optind;
deref = LDAP_DEREF_ALWAYS;
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 );
}
if ( (ld = ldap_open( ldaphost, LDAP_PORT )) == NULL ) {
perror( "ldap_open" );
exit( -1 );
}
ld->ld_sizelimit = sizelimit ? sizelimit : DEFAULT_SIZELIMIT;
ld->ld_deref = deref;
if ( ldap_simple_bind_s( ld, RP_BINDDN, NULL ) != LDAP_SUCCESS ) {
fprintf( stderr, "X.500 is temporarily unavailable.\n" );
ldap_perror( ld, "ldap_simple_bind_s" );
exit( -1 );
}
result = NULL;
if ( strchr( key, ',' ) != NULL ) {
ld->ld_deref = LDAP_DEREF_FINDING;
if ( (rc = ldap_ufn_search_s( ld, key, attrs, 0, &result ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED &&
rc != LDAP_TIMELIMIT_EXCEEDED )
{
ldap_perror( ld, "ldap_ufn_search_s" );
exit( -1 );
}
matches = ldap_count_entries( ld, result );
} else {
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;
char *s;
int i, last;
cn = ldap_get_values( ld, e, "cn" );
for ( i = 0; cn[i] != NULL; i++ ) {
last = strlen( cn[i] ) - 1;
if ( isdigit( 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( 1 );
}
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( 1 );
}
print_entry( ld, e );
} else if ( matches == 0 ) {
fprintf( stderr, "No matches found for \"%s\"\n", key );
exit( 1 );
} else {
fprintf( stderr, "Error return from ldap_count_entries\n" );
exit( -1 );
}
ldap_unbind( ld );
return( 0 );
}
static
print_entry( ld, e )
LDAP *ld;
LDAPMessage *e;
{
int i;
char *dn, *rdn;
char **ufn;
char **title, **dept, **addr, **phone, **fax, **mail;
char *faxmail, *org, *faxtotpc();
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( 1 );
}
faxmail = faxtotpc( fax[0] );
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] : "" );
}

85
clients/fax500/xrpcomp Normal file
View File

@ -0,0 +1,85 @@
: run this script through /bin/sh
RP500=ETCDIR/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

View File

@ -0,0 +1,70 @@
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# X.500 ldap finger daemon makefile
#
#-----------------------------------------------------------------------------
LDAPSRC = ../..
HDIR = $(LDAPSRC)/include
LDIR = $(LDAPSRC)/libraries
VERSIONFILE = $(LDAPSRC)/build/version
SRCS = main.c
OBJS = main.o
INCLUDES=-I$(HDIR)
DEFINES = $(DEFS)
CFLAGS = $(INCLUDES) $(DEFINES) $(ACFLAGS)
LIBS = -lldap -llber $(KRBLIBFLAG) $(KRBLIBS) $(ALIBS)
all: in.xfingerd
in.xfingerd: version.o
$(CC) $(ALDFLAGS) -o $@ $(OBJS) version.o \
-L$(LDIR) $(LIBS)
version.c: $(OBJS) $(LDIR)/libldap.a
$(RM) $@
(u=$${USER-root} v=`$(CAT) $(VERSIONFILE)` d=`$(PWD)` h=`$(HOSTNAME)` \
t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
-e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
-e "s|%VERSION%|$${v}|" \
< Version.c > $@)
install: in.xfingerd FORCE
-$(MKDIR) -p $(ETCDIR)
$(INSTALL) $(INSTALLFLAGS) -m 755 in.xfingerd $(ETCDIR)
lint: FORCE
$(LINT) $(INCLUDES) $(DEFINES) $(SRCS)
5lint: FORCE
$(5LINT) $(INCLUDES) $(DEFINES) $(SRCS)
clean: FORCE
$(RM) *.o core a.out version.c in.xfingerd
depend: FORCE
$(MKDEP) $(INCLUDES) $(DEFINES) $(SRCS)
links:
@$(LN) .src/README .src/*.[ch] .
# DO NOT DELETE THIS LINE -- mkdep uses it.
# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
main.o: main.c ../../include/lber.h ../../include/ldap.h
main.o: ../../include/disptmpl.h ../../include/portable.h
main.o: ../../include/ldapconfig.h
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY

13
clients/finger/Version.c Normal file
View File

@ -0,0 +1,13 @@
/*
* Copyright (c) 1991 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.
*/
char Version[] = " in.xfingerd v%VERSION% (%WHEN%)\n\t%WHOANDWHERE%\n";

429
clients/finger/main.c Normal file
View File

@ -0,0 +1,429 @@
/*
* Copyright (c) 1990,1994 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 "lber.h"
#include "ldap.h"
#include "disptmpl.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <syslog.h>
#include <sys/resource.h>
#include <sys/wait.h>
#ifdef aix
#include <sys/select.h>
#endif /* aix */
#include <signal.h>
#include "portable.h"
#include "ldapconfig.h"
#ifdef USE_SYSCONF
#include <unistd.h>
#endif /* USE_SYSCONF */
int dosyslog = 1;
char *ldaphost = LDAPHOST;
int ldapport = LDAP_PORT;
char *base = FINGER_BASE;
int deref;
char *filterfile = FILTERFILE;
char *templatefile = TEMPLATEFILE;
int rdncount = FINGER_RDNCOUNT;
static do_query();
static do_search();
static do_read();
static print_attr();
static usage( name )
char *name;
{
fprintf( stderr, "usage: %s [-l] [-x ldaphost] [-p ldapport] [-f filterfile] [-t templatefile] [-c rdncount]\r\n", name );
exit( 1 );
}
main (argc, argv)
int argc;
char **argv;
{
int i;
char *myname;
unsigned long mypeer = -1;
struct hostent *hp;
struct sockaddr_in peername;
int peernamelen;
int interactive = 0;
extern char *optarg;
deref = FINGER_DEREF;
while ( (i = getopt( argc, argv, "f:ilp:t:x:p:c:" )) != EOF ) {
switch( i ) {
case 'f': /* ldap filter file */
filterfile = strdup( optarg );
break;
case 'i': /* interactive */
interactive = 1;
break;
case 'l': /* don't do syslogging */
dosyslog = 0;
break;
case 't': /* ldap template file */
templatefile = strdup( optarg );
break;
case 'x': /* specify ldap host */
ldaphost = strdup( optarg );
break;
case 'p': /* specify ldap port */
ldapport = atoi( optarg );
break;
case 'c': /* specify number of DN components to show */
rdncount = atoi( optarg );
break;
default:
usage( argv[0] );
}
}
if ( !interactive ) {
peernamelen = sizeof(peername);
if ( getpeername( 0, (struct sockaddr *)&peername,
&peernamelen ) != 0 ) {
perror( "getpeername" );
exit( 1 );
}
mypeer = (unsigned long) peername.sin_addr.s_addr;
}
#ifdef FINGER_BANNER
if ( FINGER_BANNER != NULL && strcmp( FINGER_BANNER, "" ) != 0 ) {
printf( FINGER_BANNER );
fflush( stdout );
}
#endif
if ( (myname = strrchr( argv[0], '/' )) == NULL )
myname = strdup( argv[0] );
else
myname = strdup( myname + 1 );
if ( dosyslog ) {
#ifdef LOG_LOCAL4
openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
#else
openlog( myname, OPENLOG_OPTIONS );
#endif
}
if ( dosyslog && mypeer != -1 ) {
struct in_addr addr;
hp = gethostbyaddr( (char *) &mypeer, sizeof(mypeer), AF_INET );
addr.s_addr = mypeer;
syslog( LOG_INFO, "connection from %s (%s)", (hp == NULL) ?
"unknown" : hp->h_name, inet_ntoa( addr ) );
}
do_query();
return( 0 );
}
static do_query()
{
char buf[256];
int len, rc, tblsize;
struct timeval timeout;
fd_set readfds;
LDAP *ld;
if ( (ld = ldap_open( ldaphost, ldapport )) == NULL ) {
fprintf( stderr, FINGER_UNAVAILABLE );
perror( "ldap_open" );
exit( 1 );
}
ld->ld_sizelimit = FINGER_SIZELIMIT;
ld->ld_deref = deref;
if ( ldap_simple_bind_s( ld, FINGER_BINDDN, NULL ) != LDAP_SUCCESS ) {
fprintf( stderr, FINGER_UNAVAILABLE );
ldap_perror( ld, "ldap_simple_bind_s" );
exit( 1 );
}
#ifdef USE_SYSCONF
tblsize = sysconf( _SC_OPEN_MAX );
#else /* USE_SYSCONF */
tblsize = getdtablesize();
#endif /* USE_SYSCONF */
timeout.tv_sec = FINGER_TIMEOUT;
timeout.tv_usec = 0;
FD_ZERO( &readfds );
FD_SET( fileno( stdin ), &readfds );
if ( (rc = select( tblsize, &readfds, 0, 0, &timeout )) <= 0 ) {
if ( rc < 0 )
perror( "select" );
else
fprintf( stderr, "connection timed out on input\r\n" );
exit( 1 );
}
if ( fgets( buf, sizeof(buf), stdin ) == NULL )
exit( 1 );
len = strlen( buf );
/* strip off \r \n */
if ( buf[len - 1] == '\n' ) {
buf[len - 1] = '\0';
len--;
}
if ( buf[len - 1] == '\r' ) {
buf[len - 1] = '\0';
len--;
}
if ( len == 0 ) {
printf( "No campus-wide login information available. Info for this machine only:\r\n" );
fflush( stdout );
execl( FINGER_CMD, FINGER_CMD, NULL );
} else {
char *p;
/* skip and ignore stinking /w */
if ( strncmp( buf, "/W ", 2 ) == 0 ) {
p = buf + 2;
} else {
p = buf;
}
for ( ; *p && isspace( *p ); p++ )
; /* NULL */
do_search( ld, p );
}
}
static void
spaces2dots( s )
char *s;
{
for ( ; *s; s++ ) {
if ( *s == ' ' ) {
*s = '.';
}
}
}
static do_search( ld, buf )
LDAP *ld;
char *buf;
{
char *dn, *rdn;
char **title;
int rc, matches, i, ufn;
struct timeval tv;
LDAPFiltInfo *fi;
LDAPMessage *result, *e;
static char *attrs[] = { "cn", "title", "objectClass", "joinable",
#ifdef FINGER_SORT_ATTR
FINGER_SORT_ATTR,
#endif
0 };
extern int strcasecmp();
ufn = 0;
#ifdef FINGER_UFN
if ( strchr( buf, ',' ) != NULL ) {
ldap_ufn_setprefix( ld, base );
tv.tv_sec = FINGER_TIMEOUT;
tv.tv_usec = 0;
ldap_ufn_timeout( (void *) &tv );
if ( (rc = ldap_ufn_search_s( ld, buf, attrs, 0, &result ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
fprintf( stderr, FINGER_UNAVAILABLE );
ldap_perror( ld, "ldap_search_st" );
exit( 1 );
}
matches = ldap_count_entries( ld, result );
ufn = 1;
} else {
#endif
if ( (ld->ld_filtd = ldap_init_getfilter( filterfile ))
== NULL ) {
fprintf( stderr, "Cannot open filter file (%s)\n",
filterfile );
exit( 1 );
}
for ( fi = ldap_getfirstfilter( ld->ld_filtd, "finger", buf );
fi != NULL;
fi = ldap_getnextfilter( ld->ld_filtd ) )
{
tv.tv_sec = FINGER_TIMEOUT;
tv.tv_usec = 0;
if ( (rc = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE,
fi->lfi_filter, attrs, 0, &tv, &result ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
&& rc != LDAP_TIMELIMIT_EXCEEDED )
{
fprintf( stderr, FINGER_UNAVAILABLE );
ldap_perror( ld, "ldap_search_st" );
exit( 1 );
}
if ( (matches = ldap_count_entries( ld, result )) != 0 )
break;
ldap_msgfree( result );
result = NULL;
}
#ifdef FINGER_UFN
}
#endif
if ( rc == LDAP_SIZELIMIT_EXCEEDED ) {
printf( "(Partial results - a size limit was exceeded)\r\n" );
} else if ( rc == LDAP_TIMELIMIT_EXCEEDED ) {
printf( "(Partial results - a time limit was exceeded)\r\n" );
}
if ( matches == 0 ) {
printf( FINGER_NOMATCH );
fflush( stdout );
} else if ( matches < 0 ) {
fprintf( stderr, "error return from ldap_count_entries\r\n" );
exit( 1 );
} else if ( matches <= FINGER_LISTLIMIT ) {
printf( "%d %s match%s found for \"%s\":\r\n", matches,
ufn ? "UFN" : fi->lfi_desc, matches > 1 ? "es" : "", buf );
fflush( stdout );
for ( e = ldap_first_entry( ld, result ); e != NULL; ) {
do_read( ld, e );
e = ldap_next_entry( ld, e );
if ( e != NULL ) {
printf( "--------------------\r\n" );
}
}
} else {
printf( "%d %s matches for \"%s\":\r\n", matches,
ufn ? "UFN" : fi->lfi_desc, buf );
fflush( stdout );
#ifdef FINGER_SORT_ATTR
ldap_sort_entries( ld, &result, FINGER_SORT_ATTR, strcasecmp );
#endif
for ( e = ldap_first_entry( ld, result ); e != NULL;
e = ldap_next_entry( ld, e ) ) {
char *p;
dn = ldap_get_dn( ld, e );
rdn = dn;
if ( (p = strchr( dn, ',' )) != NULL )
*p = '\0';
while ( *rdn && *rdn != '=' )
rdn++;
if ( *rdn )
rdn++;
/* hack attack */
for ( i = 0; buf[i] != '\0'; i++ ) {
if ( buf[i] == '.' || buf[i] == '_' )
buf[i] = ' ';
}
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( cn[i][last] ) ) {
rdn = strdup( cn[i] );
break;
}
}
}
title = ldap_get_values( ld, e, "title" );
spaces2dots( rdn );
printf( " %-20s %s\r\n", rdn,
title ? title[0] : "" );
if ( title != NULL ) {
for ( i = 1; title[i] != NULL; i++ )
printf( " %-20s %s\r\n", "",
title[i] );
}
fflush( stdout );
if ( title != NULL )
ldap_value_free( title );
free( dn );
}
}
if ( result != NULL ) {
ldap_msgfree( result );
}
ldap_unbind( ld );
}
static int
entry2textwrite( void *fp, char *buf, int len )
{
return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
}
static do_read( ld, e )
LDAP *ld;
LDAPMessage *e;
{
static struct ldap_disptmpl *tmpllist;
static char *defattrs[] = { "mail", NULL };
static char *mailvals[] = FINGER_NOEMAIL;
static char **defvals[] = { mailvals, NULL };
ldap_init_templates( templatefile, &tmpllist );
if ( ldap_entry2text_search( ld, NULL, base, e, tmpllist, defattrs,
defvals, entry2textwrite, (void *)stdout, "\r\n", rdncount,
LDAP_DISP_OPT_DOSEARCHACTIONS ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_entry2text_search" );
exit( 1 );
}
if ( tmpllist != NULL ) {
ldap_free_templates( tmpllist );
}
}

View File

@ -0,0 +1,91 @@
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# gopher to x.500 gateway makefile
#
#-----------------------------------------------------------------------------
LDAPSRC = ../..
HDIR = $(LDAPSRC)/include
LDIR = $(LDAPSRC)/libraries
VERSIONFILE = $(LDAPSRC)/build/version
SRCS = go500.c go500gw.c detach.c setproctitle.c
OBJS = go500.o go500gw.o detach.o setproctitle.o
GOOBJS = go500.o detach.o goversion.o setproctitle.o
GWOBJS = go500gw.o detach.o gwversion.o setproctitle.o
INCLUDES= -I$(HDIR)
DEFINES = $(DEFS)
CFLAGS = $(INCLUDES) $(DEFS) $(ACFLAGS)
LIBS = -lldap -llber $(KRBLIBFLAG) $(KRBLIBS) $(ALIBS)
DLIBS = $(LDIR)/libldap.a $(LDIR)/liblber.a
all: go500gw go500
go500gw: gwversion.o
$(CC) $(ALDFLAGS) -o $@ $(GWOBJS) -L$(LDIR) $(LIBS)
go500: goversion.o
$(CC) $(ALDFLAGS) -o $@ $(GOOBJS) -L$(LDIR) $(LIBS)
goversion.c: go500.o detach.o setproctitle.o $(DLIBS)
$(RM) $@
(u=$${USER-root} v=`$(CAT) $(VERSIONFILE)` d=`$(PWD)` h=`$(HOSTNAME)` \
t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
-e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
-e "s|%VERSION%|$${v}|" \
< Version.c > $@)
gwversion.c: go500gw.o detach.o setproctitle.o $(DLIBS)
$(RM) $@
(u=$${USER-root} v=`$(CAT) $(VERSIONFILE)` d=`$(PWD)` h=`$(HOSTNAME)` \
t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
-e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
-e "s|%VERSION%|$${v}|" \
< Versiongw.c > $@)
install: go500 go500gw go500gw.help FORCE
-$(MKDIR) -p $(ETCDIR)
$(INSTALL) $(INSTALLFLAGS) -m 755 go500 $(ETCDIR)
$(INSTALL) $(INSTALLFLAGS) -m 755 go500gw $(ETCDIR)
-$(MV) $(ETCDIR)/go500gw.help $(ETCDIR)/go500gw.help-
$(INSTALL) $(INSTALLFLAGS) -m 644 go500gw.help $(ETCDIR)
lint: FORCE
$(LINT) $(INCLUDES) $(DEFINES) $(SRCS)
5lint: FORCE
$(5LINT) $(INCLUDES) $(DEFINES) $(SRCS)
clean: FORCE
$(RM) *.o core a.out gwversion.c goversion.c go500gw go500
depend: FORCE
$(MKDEP) $(INCLUDES) $(DEFINES) $(SRCS)
links:
@$(LN) .src/README .src/*.help .src/*.[ch] .
# DO NOT DELETE THIS LINE -- mkdep uses it.
# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
go500.o: go500.c ../../include/portable.h ../../include/ldapconfig.h
go500.o: ../../include/lber.h ../../include/ldap.h ../../include/disptmpl.h
go500gw.o: go500gw.c ../../include/lber.h ../../include/ldap.h
go500gw.o: ../../include/disptmpl.h ../../include/portable.h
go500gw.o: ../../include/ldapconfig.h
detach.o: detach.c ../../include/portable.h
setproctitle.o: setproctitle.c
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY

188
clients/gopher/README Normal file
View File

@ -0,0 +1,188 @@
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. If you did not
get this software with the U-M LDAP software distribution, you will
need to have the LDAP libraries on hand to be able to make this software.
The LDAP distribution is available for anonymous ftp from the host
terminator.rs.itd.umich.edu in the x500/ directory.
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.

13
clients/gopher/Version.c Normal file
View File

@ -0,0 +1,13 @@
/*
* Copyright (c) 1991 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.
*/
char Version[] = " go500 v%VERSION% (%WHEN%)\n\t%WHOANDWHERE%\n";

View File

@ -0,0 +1,13 @@
/*
* Copyright (c) 1991 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.
*/
char Version[] = " go500gw 1.0 (%WHEN%)\n\t%WHOANDWHERE%\n";

80
clients/gopher/detach.c Normal file
View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 1990, 1994 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 <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <signal.h>
#include "portable.h"
#ifdef USE_SYSCONF
#include <unistd.h>
#endif /* USE_SYSCONF */
detach( debug )
int debug;
{
int i, sd, nbits;
#ifdef USE_SYSCONF
nbits = sysconf( _SC_OPEN_MAX );
#else /* USE_SYSCONF */
nbits = getdtablesize();
#endif /* USE_SYSCONF */
if ( debug == 0 || !(isatty( 1 )) ) {
for ( i = 0; i < 5; i++ ) {
switch ( fork() ) {
case -1:
sleep( 5 );
continue;
case 0:
break;
default:
_exit( 0 );
}
break;
}
for ( i = 3; i < nbits; i++ )
close( i );
(void) chdir( "/" );
if ( (sd = open( "/dev/null", O_RDWR )) == -1 ) {
if ( debug ) perror( "/dev/null" );
exit( 1 );
}
if ( isatty( 0 ) )
(void) dup2( sd, 0 );
if ( isatty( 1 ) )
(void) dup2( sd, 1 );
if ( isatty(2) )
(void) dup2( sd, 2 );
close( sd );
#ifdef USE_SETSID
(void) setsid();
#else /* USE_SETSID */
if ( (sd = open( "/dev/tty", O_RDWR )) != -1 ) {
(void) ioctl( sd, TIOCNOTTY, NULL );
(void) close( sd );
}
#endif /* USE_SETSID */
}
(void) signal( SIGPIPE, SIG_IGN );
}

568
clients/gopher/go500.c Normal file
View File

@ -0,0 +1,568 @@
/*
* 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 <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <syslog.h>
#include <sys/resource.h>
#include <sys/wait.h>
#ifdef aix
#include <sys/select.h>
#endif /* aix */
#include <signal.h>
#include "portable.h"
#include "ldapconfig.h"
#include "lber.h"
#include "ldap.h"
#include "disptmpl.h"
#ifdef USE_SYSCONF
#include <unistd.h>
#endif /* USE_SYSCONF */
int debug;
int dosyslog;
int inetd;
int dtblsize;
char *ldaphost = LDAPHOST;
char *base = GO500_BASE;
int rdncount = GO500_RDNCOUNT;
char *filterfile = FILTERFILE;
char *templatefile = TEMPLATEFILE;
char myhost[MAXHOSTNAMELEN];
int myport;
static set_socket();
static SIG_FN wait4child();
static do_queries();
static do_error();
static do_search();
static do_read();
extern int strcasecmp();
static usage( name )
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( 1 );
}
main (argc, argv)
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;
int fromlen;
SIG_FN wait4child();
extern char *optarg;
extern char **Argv;
extern int Argc;
/* for setproctitle */
Argv = argv;
Argc = argc;
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 ) {
perror( "gethostname" );
exit( 1 );
}
#endif
#ifdef USE_SYSCONF
dtblsize = sysconf( _SC_OPEN_MAX );
#else /* USE_SYSCONF */
dtblsize = getdtablesize();
#endif /* USE_SYSCONF */
/* detach if stderr is redirected or no debugging */
if ( inetd == 0 )
(void) detach( debug );
if ( (myname = strrchr( argv[0], '/' )) == NULL )
myname = strdup( argv[0] );
else
myname = strdup( myname + 1 );
if ( dosyslog ) {
#ifdef LOG_LOCAL3
openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL3 );
#else
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, (void *) wait4child );
} else {
myport = GO500_PORT;
fromlen = sizeof(from);
if ( getpeername( 0, (struct sockaddr *) &from, &fromlen )
== 0 ) {
hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
sizeof(from.sin_addr.s_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 ) );
}
setproctitle( hp == NULL ? inet_ntoa( from.sin_addr ) :
hp->h_name );
}
do_queries( 0 );
exit( 0 );
}
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( 1 );
}
hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
sizeof(from.sin_addr.s_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 */
close( s );
do_queries( ns );
break;
case -1: /* failed */
perror( "fork" );
break;
default: /* parent */
close( ns );
if ( debug )
fprintf( stderr, "forked child %d\n", pid );
break;
}
}
/* NOT REACHED */
}
static
set_socket( port )
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( 1 );
}
/* 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( 1 );
}
/* bind to a name */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons( port );
if ( bind( s, (struct sockaddr *) &addr, sizeof(addr) ) ) {
perror( "bind" );
exit( 1 );
}
/* listen for connections */
if ( listen( s, 5 ) == -1 ) {
perror( "listen" );
exit( 1 );
}
if ( debug ) printf("tcp socket allocated, bound, and listening\n");
return( s );
}
static SIG_FN
wait4child()
{
WAITSTATUSTYPE status;
if ( debug ) printf( "parent: catching child status\n" );
#ifdef USE_WAITPID
while (waitpid ((pid_t) -1, 0, WAIT_FLAGS) > 0)
#else /* USE_WAITPID */
while ( wait3( &status, WAIT_FLAGS, 0 ) > 0 )
#endif /* USE_WAITPID */
; /* NULL */
(void) signal( SIGCHLD, (void *) wait4child );
}
static
do_queries( s )
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( 1 );
}
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( 1 );
if ( fgets( buf, sizeof(buf), fp ) == NULL )
exit( 1 );
len = strlen( buf );
if ( debug ) {
fprintf( stderr, "got %d bytes\n", len );
#ifdef LDAP_DEBUG
lber_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( *query )) {
++query;
--len;
}
rewind(fp);
if ( *query != '~' && *query != '@' ) {
if ( (ld = ldap_open( ldaphost, LDAP_PORT )) == 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( 1 );
}
ld->ld_deref = GO500_DEREF;
if ( (rc = ldap_simple_bind_s( ld, GO500_BINDDN, NULL ))
!= 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( 1 );
}
}
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);
ldap_unbind( ld );
exit( 1 );
/* NOT REACHED */
}
static
do_error( fp, s )
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
do_search( ld, fp, buf )
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 };
#ifdef GO500_UFN
if ( strchr( buf, ',' ) != NULL ) {
ldap_ufn_setprefix( ld, base );
tv.tv_sec = GO500_TIMEOUT;
tv.tv_usec = 0;
ldap_ufn_timeout( (void *) &tv );
if ( (rc = ldap_ufn_search_s( ld, buf, attrs, 0, &res ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
fprintf(fp,
"0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
rc, myhost, myport );
return;
}
matches = ldap_count_entries( ld, res );
} else {
#endif
if ( (filtd = ldap_init_getfilter( filterfile )) == NULL ) {
fprintf( stderr, "Cannot open filter file (%s)\n",
filterfile );
exit( 1 );
}
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 );
#ifdef GO500_UFN
}
#endif
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, int len )
{
return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
}
static
do_read( ld, fp, dn )
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( 1 );
}
if ( tmpllist != NULL ) {
ldap_free_templates( tmpllist );
}
}

891
clients/gopher/go500gw.c Normal file
View File

@ -0,0 +1,891 @@
/*
* 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 "lber.h"
#include "ldap.h"
#include "disptmpl.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <syslog.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <signal.h>
#ifdef aix
#include <sys/select.h>
#endif /* aix */
#include "portable.h"
#include "ldapconfig.h"
#ifdef USE_SYSCONF
#include <unistd.h>
#endif /* USE_SYSCONF */
int debug;
int dosyslog;
int inetd;
int dtblsize;
char *ldaphost = LDAPHOST;
int ldapport = LDAP_PORT;
int searchaliases = 1;
char *helpfile = GO500GW_HELPFILE;
char *filterfile = FILTERFILE;
char *templatefile = TEMPLATEFILE;
char *friendlyfile = FRIENDLYFILE;
int rdncount = GO500GW_RDNCOUNT;
static set_socket();
static SIG_FN wait4child();
static do_queries();
static do_menu();
static do_list();
static do_search();
static do_read();
static do_help();
static do_sizelimit();
static do_error();
extern int strcasecmp();
char myhost[MAXHOSTNAMELEN];
int myport = GO500GW_PORT;
static usage( name )
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( 1 );
}
main (argc, argv)
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;
int fromlen;
SIG_FN wait4child();
extern char *optarg;
extern char **Argv;
extern int Argc;
/* for setproctitle */
Argv = argv;
Argc = argc;
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 );
#ifdef LDAP_DEBUG
ldap_debug = debug;
#else
fprintf( stderr, "warning: ldap debugging requires LDAP_DEBUG\n" );
#endif
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 USE_SYSCONF
dtblsize = sysconf( _SC_OPEN_MAX );
#else /* USE_SYSCONF */
dtblsize = getdtablesize();
#endif /* USE_SYSCONF */
#ifdef GO500GW_HOSTNAME
strcpy( myhost, GO500GW_HOSTNAME );
#else
if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost) )
== -1 ) {
perror( "gethostname" );
exit( 1 );
}
#endif
/* detach if stderr is redirected or no debugging */
if ( inetd == 0 )
(void) detach( debug );
if ( (myname = strrchr( argv[0], '/' )) == NULL )
myname = strdup( argv[0] );
else
myname = strdup( myname + 1 );
if ( dosyslog ) {
#ifdef LOG_LOCAL3
openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL3 );
#else
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, (void *) wait4child );
}
if ( inetd ) {
fromlen = sizeof(from);
if ( getpeername( 0, (struct sockaddr *) &from, &fromlen )
== 0 ) {
hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
sizeof(from.sin_addr.s_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 ) );
}
setproctitle( hp == NULL ? inet_ntoa( from.sin_addr ) :
hp->h_name );
}
do_queries( 0 );
close( 0 );
exit( 0 );
}
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( 1 );
}
hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
sizeof(from.sin_addr.s_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 */
close( s );
do_queries( ns );
break;
case -1: /* failed */
perror( "fork" );
break;
default: /* parent */
close( ns );
if ( debug )
fprintf( stderr, "forked child %d\n", pid );
break;
}
}
/* NOT REACHED */
}
static set_socket( port )
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( 1 );
}
/* 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( 1 );
}
/* bind to a name */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons( port );
if ( bind( s, (struct sockaddr *) &addr, sizeof(addr) ) ) {
perror( "bind" );
exit( 1 );
}
/* listen for connections */
if ( listen( s, 5 ) == -1 ) {
perror( "listen" );
exit( 1 );
}
if ( debug )
printf( "go500gw listening on port %d\n", port );
return( s );
}
static SIG_FN
wait4child()
{
WAITSTATUSTYPE status;
if ( debug ) printf( "parent: catching child status\n" );
#ifdef USE_WAITPID
while (waitpid ((pid_t) -1, 0, WAIT_FLAGS) > 0)
#else /* USE_WAITPID */
while ( wait3( &status, WAIT_FLAGS, 0 ) > 0 )
#endif /* USE_WAITPID */
; /* NULL */
(void) signal( SIGCHLD, (void *) wait4child );
}
static do_queries( s )
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 ) {
perror( "fdopen" );
exit( 1 );
}
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( 1 );
if ( fgets( buf, sizeof(buf), fp ) == NULL )
exit( 1 );
len = strlen( buf );
if ( debug ) {
fprintf( stderr, "got %d bytes\n", len );
#ifdef LDAP_DEBUG
lber_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( *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( 0 );
/* NOT REACHED */
}
if ( (ld = ldap_open( ldaphost, ldapport )) == NULL ) {
if ( debug ) perror( "ldap_open" );
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( 1 );
}
ld->ld_deref = LDAP_DEREF_ALWAYS;
if ( !searchaliases )
ld->ld_deref = LDAP_DEREF_FINDING;
if ( (rc = ldap_simple_bind_s( ld, GO500GW_BINDDN, 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( 1 );
}
switch ( *query++ ) {
case 'R': /* read an entry */
do_read( ld, fp, query );
break;
case 'S': /* search */
do_search( ld, fp, query, 1 );
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( 0 );
/* NOT REACHED */
}
static char *pick_oc( oclist )
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 isnonleaf( ld, oclist, dn )
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 };
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
ld->ld_sizelimit = 1;
if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_ONELEVEL,
"(objectClass=*)", attrs, 0, &timeout, &res ))
== LDAP_SUCCESS || rc == LDAP_SIZELIMIT_EXCEEDED ) {
ld->ld_sizelimit = LDAP_NO_LIMIT;
numentries = ldap_count_entries( ld, res );
if ( res != NULL )
ldap_msgfree( res );
return( numentries == 1 ? 1 : 0 );
}
}
return( 0 );
#endif
}
static do_menu( ld, fp, dn )
LDAP *ld;
FILE *fp;
char *dn;
{
char **s;
char *rdn = NULL;
FriendlyMap *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 do_list( ld, fp, dn )
LDAP *ld;
FILE *fp;
char *dn;
{
int rc;
LDAPMessage *e, *res;
struct timeval timeout;
FriendlyMap *fm = NULL;
static char *attrs[] = { "objectClass", 0 };
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
ld->ld_deref = LDAP_DEREF_FINDING;
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;
}
ld->ld_deref = LDAP_DEREF_ALWAYS;
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 isoc( ocl, oc )
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( ld, dn )
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, "objectClass=*",
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 do_search( ld, fp, query )
LDAP *ld;
FILE *fp;
char *query;
{
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( 1 );
}
*filter++ = '\0';
base = query;
#ifdef GO500GW_UFN
if ( strchr( filter, ',' ) != NULL ) {
ldap_ufn_setprefix( ld, base );
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
ldap_ufn_timeout( (void *) &timeout );
ld->ld_deref = LDAP_DEREF_FINDING;
if ( (rc = ldap_ufn_search_s( ld, filter, attrs, 0, &res ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
fprintf(fp,
"0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
rc, myhost, myport );
return;
}
count = ldap_count_entries( ld, res );
} else {
#endif
if ( (scope = make_scope( ld, base )) == -1 ) {
fprintf( fp, "3Bad scope\r\n" );
exit( 1 );
}
filtertype = (scope == LDAP_SCOPE_ONELEVEL ?
"go500gw onelevel" : "go500gw subtree");
ld->ld_deref = (scope == LDAP_SCOPE_ONELEVEL ?
LDAP_DEREF_FINDING : LDAP_DEREF_ALWAYS);
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( 1 );
}
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( 1 );
}
if ( (count = ldap_count_entries( ld, res )) != 0 )
break;
}
ld->ld_deref = LDAP_DEREF_ALWAYS;
ldap_getfilter_free( filtd );
#ifdef GO500GW_UFN
}
#endif
if ( count == 0 ) {
return( 0 );
}
if ( count == 1 ) {
char *dn, **s, **oc;
int rc;
e = ldap_first_entry( ld, res );
oc = ldap_get_values( ld, e, "objectClass" );
if ( isnonleaf( ld, oc, dn ) ) {
dn = ldap_get_dn( ld, e );
rc = do_menu( ld, fp, dn );
free( dn );
return( rc );
}
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, int len )
{
return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
}
static do_read( ld, fp, dn )
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 ) {
fprintf(fp,
"0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
ld->ld_errno, myhost, myport );
}
if ( tmpllist != NULL ) {
ldap_free_templates( tmpllist );
}
}
static do_help( op )
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 do_sizelimit( fp, type )
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 do_error( fp, s )
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" );
}

View File

@ -0,0 +1,17 @@
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.
If you have comments, suggestions or questions about this service,
please send mail to x500@umich.edu. -- Tim Howes 8/25/93

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 1990,1991 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.
*/
char **Argv; /* pointer to original (main's) argv */
int Argc; /* original argc */
/*
* takes a printf-style format string (fmt) and up to three parameters (a,b,c)
* this clobbers the original argv...
*/
/* VARARGS */
setproctitle( fmt, a, b, c )
char *fmt;
{
static char *endargv = (char *)0;
char *s;
int i;
char buf[ 1024 ];
if ( endargv == (char *)0 ) {
/* set pointer to end of original argv */
endargv = Argv[ Argc-1 ] + strlen( Argv[ Argc-1 ] );
}
sprintf( buf, fmt, a, b, c );
/* make ps print "([prog name])" */
s = Argv[0];
*s++ = '-';
i = strlen( buf );
if ( i > endargv - s - 2 ) {
i = endargv - s - 2;
buf[ i ] = '\0';
}
strcpy( s, buf );
s += i;
while ( s < endargv ) *s++ = ' ';
}

View File

@ -0,0 +1,68 @@
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# X.500 ldap mailer makefile
#
#-----------------------------------------------------------------------------
LDAPSRC = ../..
HDIR = $(LDAPSRC)/include
LDIR = $(LDAPSRC)/libraries
VERSIONFILE = $(LDAPSRC)/build/version
SRCS = main.c
OBJS = main.o
INCLUDES= -I$(HDIR)
DEFINES = $(DEFS)
CFLAGS = $(INCLUDES) $(DEFINES) $(ACFLAGS)
LDFLAGS = -L$(LDIR)
LIBS = -lldap -llber $(KRBLIBFLAG) $(KRBLIBS) $(ALIBS)
all: mail500
mail500: version.o
$(CC) $(ALDFLAGS) -o $@ $(OBJS) version.o $(LDFLAGS) $(LIBS)
version.c: $(OBJS) $(LDIR)/libldap/libldap.a
$(RM) $@
(u=$${USER-root} v=`$(CAT) $(VERSIONFILE)` d=`$(PWD)` h=`$(HOSTNAME)` \
t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
-e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
-e "s|%VERSION%|$${v}|" \
< Version.c > $@)
install: mail500 FORCE
-$(MKDIR) -p $(ETCDIR)
$(INSTALL) $(INSTALLFLAGS) -m 755 mail500 $(ETCDIR)
lint: FORCE
$(LINT) $(INCLUDES) $(DEFINES) $(SRCS)
5lint: FORCE
$(5LINT) $(INCLUDES) $(DEFINES) $(SRCS)
clean: FORCE
$(RM) *.o core a.out version.c mail500
depend: FORCE
$(MKDEP) $(INCLUDES) $(DEFINES) $(SRCS)
links:
@$(LN) .src/README .src/sendmail.cf .src/*.[ch] .
# DO NOT DELETE THIS LINE -- mkdep uses it.
# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
main.o: main.c ../../include/portable.h ../../include/lber.h
main.o: ../../include/ldap.h ../../include/ldapconfig.h
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY

186
clients/mail500/README Normal file
View File

@ -0,0 +1,186 @@
This is the README file for mail500, a mailer that does X.500 lookups
via LDAP.
If you are planning to run mail500 at your site, there are several
things you will have to tailor in main.c:
LDAPHOST - The host running an LDAP server
base[] - The array telling mail500 where/how to search for
things. See the explanation below.
*** WHAT mail500 DOES: ***
mail500 is designed to be invoked as a mailer (e.g., from sendmail),
similar to the way /bin/mail works. It takes a few required arguments
and then a list of addresses to deliver to. It expects to find the
message to deliver on its standard input. It looks up the addresses in
X.500 to figure out where to route the mail, and then execs sendmail to
do the actual delivery. It supports simple aliases, groups, and
mailing lists, the details of which are given below.
*** HOW IT WORKS (from the sendmail side): ***
The idea is that you might have a rule like this in your sendmail.cf
file somewhere in rule set 0:
R$*<@umich.edu>$* $#mail500$@umich.edu$:<$1>
This rule says that any address that ends in @umich.edu will cause
the mail500 mailer to be called to deliver the mail. You probably
also want to do something to prevent addresses like terminator!tim@umich.edu
or tim%terminator.rs.itd.umich.edu@umich.edu from being passed to mail500.
At U-M, we do this by adding rules like this to rule set 9 where we
strip off our local names:
R<@umich.edu>$*:$* $>10<@>$1:$2
R$+%$+<@umich.edu> $>10$1%$2<@>
R$+!$+<@umich.edu> $>10$1!$2<@>
See the sample sendmail.cf in this directory for more details.
The mail500 mailer should be defined similar to this in the
sendmail.cf file:
Mmail500, P=/usr/local/etc/mail500, F=DFMSmnXuh, A=mail500 -f $f -h $h -m $n@$w $u
This defines how mail500 will be treated by sendmail and what
arguments it will have when it's called. The various flags specified
by the F=... parameter are explained in your local sendmail book (with
any luck). The arguments to mail500 are as follows:
-f Who the mail is from. This will be used as the address
to which any errors should be sent (unless the address
specifies a mailing list - see below). Normally, sendmail
defines the $f macro to be the sender.
-h The domain for which the mail is destined. This is passed
in to mail500 via the $h macro, which is set by the
$@ metasymbol in the rule added to rule set 0 above.
It's normally used when searching for groups.
-m The mailer-daemon address. If errors have to be sent,
this is the address they will come from. $n is normally
set to mailer-daemon and $w is normally the local host
name.
The final argument $u is used to stand for the addresses to which to
deliver the mail.
*** HOW IT WORKS (from the mail500 side): ***
When mail500 gets invoked with one or more names to which to
deliver mail, it searches for each name in X.500. Where it searches,
and what kind(s) of search(es) it does are compile-time configurable
by changing the base array in main.c. For example, the configuration
we use at U-M is like this:
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
};
which means that in delivering mail to "name" mail500 would do the
the following searches, stopping if it found anything at any step:
Search (18) [2]: c=US@o=University of Michigan@ou=People
Search subtree (uid=name)
Search (18) [3]: c=US@o=University of Michigan@ou=People
Search subtree (cn=name)
Search (18) [4]: c=US@o=University of Michigan@ou=Groups@ou=System Groups
Search subtree & ((cn=name)(associatedDomain=umich.edu))
Search (18) [5]: c=US@o=University of Michigan@ou=Groups@ou=User Groups
Search subtree & ((cn=name)(associatedDomain=umich.edu))
Notice that when specifying a filter %s is replaced by the name,
or user portion of the address while %h is replaced by whatever is
passed in to mail500 via the -h option (typically the host portion
of the address).
You can also specify whether you want search results that matched
because the entry's RDN matched the search to be given preference
or not. At U-M, we only give such preference in the mail group
portion of the searches. Beware with this option: the algorithm
used to decide whether an entry's RDN matched the search is very
simple-minded, and may not always be correct.
There is currently no limit on the number of areas searched (the base
array can be as large as you want), and an arbitrary limit of 2 filters
for each base. If you want more than that, simply changing the 3 in
the typedef for Base should do the trick.
*** HOW IT WORKS (from the X.500 side): ***
In X.500, there are several new attribute types and one new object
class defined that mail500 makes use of. At its most basic, for normal
entries mail500 will deliver to the value(s) listed in the
rfc822Mailbox attribute of the entry. For example, at U-M my entry has
the attribute
mail= tim@terminator.rs.itd.umich.edu
So mail sent to tim@umich.edu will be delivered via mail500 to that
address. If there were multiple values for the mail attribute, multiple
copies of the mail would be sent.
A new object class, rfc822MailGroup, and several new attributes have
been defined to handle email groups/mailing lists. To use this, you
will need to add this to your local oidtable.oc:
# object class for representing rfc 822 mailgroups
rfc822MailGroup: umichObjectClass.2 : \
top : \
cn : \
rfc822Mailbox, member, memberOfGroup, owner, \
errorsTo, rfc822ErrorsTo, requestsTo, rfc822RequestsTo,
joinable, associatedDomain, \
description, multiLineDescription, \
userPassword, krbName, \
telecommunicationAttributeSet, postalAttributeSet
And you will need to add these to your local oidtable.at:
# attrs for rfc822mailgroups
multiLineDescription: umichAttributeType.2 : CaseIgnoreList
rfc822ErrorsTo: umichAttributeType.26 : CaseIgnoreIA5String
rfc822RequestsTo: umichAttributeType.27 : CaseIgnoreIA5String
joinable: umichAttributeType.28 : Boolean
memberOfGroup: umichAttributeType.29 : DN
errorsTo: umichAttributeType.30 : DN
requestsTo: umichAttributeType.31 : DN
The idea was to define a kind of hybrid mail group that could handle
people who were in X.500 or not. So, for example, members of a group
can be specified via the member attribute (for X.500 members) or the
rfc822MailBox attribute (for non-X.500 members). Similarly for the
errorsTo and rfc822ErrorsTo, and the requestsTo and rfc822RequestsTo
attributes.
To create a real mailing list, with a list maintainer, all you have to
do is create an rfc822MailGroup and fill in the errorsTo or
rfc822ErrorsTo attributes (or both). That will cause any errors
encountered when delivering mail to the group to go to the addresses
listed (or X.500 entry via it's mail attribute).
If you fill in the requestsTo or rfc822RequestsTo (or both) attributes,
mail sent to groupname-request will be sent to the addresses listed
there. mail500 does this automatically, so you don't have to explicitly
add the groupname-request alias to your group.
To allow users to join a group, there is the joinable flag. If TRUE,
mail500 will search for entries that have a memberOfGroup attribute
equal to the DN of the group, using the same algorithm it used to find
the group in the first place (i.e. the DNs and filters listed in the
base array). This allows people to join (or subscribe to) a group
without having to modify the group entry directly. If joinable is
FALSE, the search is not done.
Finally, keep in mind that this is somewhat experimental at the moment.
We are using it in production at U-M, but your mileage may vary...

13
clients/mail500/Version.c Normal file
View File

@ -0,0 +1,13 @@
/*
* Copyright (c) 1991 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.
*/
char Version[] = " mail500 v%VERSION% (%WHEN%)\n\t%WHOANDWHERE%\n";

1691
clients/mail500/main.c Normal file

File diff suppressed because it is too large Load Diff

203
clients/mail500/sendmail.cf Normal file
View File

@ -0,0 +1,203 @@
# Mostly rfc1123 compliant sendmail.cf
#
# Mail sendmail-admins-request@itd.umich.edu to join
# sendmail-admins@itd.umich.edu. sendmail-admins carries information
# regarding this sendmail.cf, including announcements of changes
# and discussions of interest to admins.
#
DWtotalrecall
Dw$W.rs.itd.umich.edu
DBcunyvm.cuny.edu
DUdestroyer.rs.itd.umich.edu
DV2.2
De$j sendmail ($v/$V) ready at $b
Dj$w
DlFrom $g $d
Dnmailer-daemon
Do.:%@!^=/[]
Dq$?x\"$x\" <$g>$|$g$.
OA/etc/aliases
OQ/var/spool/mqueue
OH/usr/lib/sendmail.hf
OS/usr/lib/sendmail.st
OP
OD
OX10
Ox5
Ou1
Og1
Odb
OF0600
OL9
Oo
Or15m
Os
OT3d
H?P?Return-Path: <$g>
HReceived: $?sfrom $s $.by $j ($v/$V)
$?rwith $r $.id $i; $b
H?D?Resent-Date: $a
H?F?Resent-From: $q
H?M?Resent-Message-Id: <$t.$i@$j>
H?M?Message-Id: <$t.$i@$j>
H?D?Date: $a
H?x?Full-Name: $x
H?F?From: $q
Troot uucp daemon
Pspecial-delivery=100
Pfirst-class=0
Pjunk=-100
# Organization:
#
# ruleset 3 and friends
# focus addresses, don't screw with them
# ruleset 0 and friends
# beat the hell out of addresses, convert them to
# their deliverable form
# mailers and associated rulesets
# * focused addresses are body addresses, and should be
# left as they are
# * unfocused addresses are envelope addresses, and should
# be converted to the mailers format
# ruleset 4
# remove focus on all addresses
# All addresses are passed through this rule. It functions by finding
# the host to delivery to, and marking it with <>
S3
R$*<$+>$* $2 remove comments
R$+:$*; $@ $1:$2; done if list
R$*@$+ $: $>5$1@$2 focus rfc822 addresses
R$+!$+ $: $>6$1!$2 focus uucp
R$*<@$+>$* $: $1<@$[$2$]>$3 canonicalize
R$*<$+>$* $@ $1<$2>$3 done if focused
R$+%$+ $: $1@$2 a%b -> a@b
R$+@$+%$+ $1%$2@$3 a@b%c -> a%b@c
R$+@$+ $: $>3$1@$2 try again...
# Find the "next hop" in normal rfc822 syntax. These rules
# all return upon marking the next hop with <>
S5
R@$+,@$+:$+ $@ <@$1>,@$2:$3 @a,@b:@c -> <@a>,@b:c
R@$+:$+ $@ <@$1>:$2 @a:b -> <@a>:b
R$+@$+ $@ $1<@$2> a@b -> a<@b>
# Focus bang style addresses. Won't change already focused addresses.
# Strips .uucp in bang paths, and converts domain syntax to rfc822 adresses.
S6
R$*<$+>$* $@ $1<$2>$3 already focused
R$+!$+ $: <$1!>$2 a!b -> <a!>b
R<$+.uucp!>$+ <$1!>$2 <a.uucp!>b -> <a!>b
# Find a mailer. This involves finding the "real" host to deliver to,
# by removing our local name, and/or doing a "domain forward"
S0
R$+ $: $>7$1 deliverable format
R$*<$+>$* $: $>11$1<$2>$3 domain forward
R<$+!>$+ $: $>12<$1!>$2 route uucp
R$*<@$+.bitnet>$* $#inet$@$B$:$1<@$2.bitnet>$3
R$*<@umich.edu>$* $#mail500$@umich.edu$:<$1>
R$*<@itd.umich.edu>$* $#mail500$@itd.umich.edu$:<$1>
#R<$+!>$+ $#uux$@$U$:<$1!>$2
R<$+!>$+ $#unet$@$U$:<$1!>$2
R$*<@$+>$* $#inet$@$2$:$1<@$2>$3
R$+ $#local$:$1
# Find the delivery address. Convert to standard-internal form,
# remove local name.
S7
R<$-.$+!>$+ $3<@$1.$2> <a.b!>c -> c<@a.b>
R$*<@$-.uucp>$* $>8$1@$2.uucp$3 *.uucp to !
R$*<$+>$* $: $>9$1<$2>$3 strip local name
# Convert rfc822 syntax to a uucp "bang path". This works well
# on normal a@b address and route-addrs. It will also do something
# to list syntax address, but it's not clear how correct it is.
S8
R@$+,@$+:$+ @$1!$2:$3 @a,@b:c -> @a!b:c
R@$+:$+@$+ $1!$3!$2 @a:b@c -> a!c!b
R@$+:$+!$+ $1!$2!$3 @a:b!c -> a!b!c
R$+@$+ $2!$1 a@b -> b!c
R$+ $: $>3$1 refocus
# Remove local names. You won't see things like a.b!u or u@b.uucp.
# Add new rules here to accept more than just the default locally.
S9
R$*<@$w>$* $>10$1<@>$2 remove local name
R<$W!>$+ $>10<!>$1
R<@umich.edu>$*:$* $>10<@>$1:$2
R$+%$+<@umich.edu> $>10$1%$2<@>
R$+!$+<@umich.edu> $>10$1!$2<@>
# Called only from above. Refocus and loop.
S10
R<@>,$+ $>3$1
R<@>:$+ $>3$1
R$+<@> $>3$1
R<!>$+ $>3$1
R$*<$+>$* $: $>7$1<$2>$3
# Convert domain names to uucp names, and refocus
S11
#R$*<@inquiry.org>$* $: $>8$1@inquiry$2
# Route uucp addresses, if we're not connected to them. We rely on the
# domain-path operator to down case addresses.
S12
R<$+!>$+ $: <${$1$}!>$2 pathalias route
R<$+!$+!>$+ <$1!>$2!$3 <a!b!>c -> <a!>b!c
Muux, P=/usr/bin/uux, F=DFMhu, S=13, R=14,
A=uux - -gC -b -r -a$f $h!rmail ($u)
Munet, P=[IPC], F=mDFMhuX, S=13, R=14, A=IPC $h, E=\r\n
Minet, P=[IPC], F=mDFMuX, S=15, R=15, A=IPC $h, E=\r\n
Mlocal, P=/bin/mail, F=rlsDFMmn, S=16, R=16, A=mail -d $u
Mprog, P=/bin/sh, F=lsDFMe, S=16, R=16, A=sh -c $u
Mmail500, P=/usr/local/etc/mail500, F=DFMSmnXuh,
A=mail500 -f $f -h $h -m $n@$w $u
# UUCP mailers require that the sender be in ! format.
# XXX Do we add our name to other people's paths?
S13
R$*<@$+>$* $: $>8$1@$2$3
#R<$w!>$+ $@ <$W!>$1
R<$+!>$+ $@ <$1!>$2
R$+:$*; $@ $1:$2;
R<> $@
#R$+ $@ <$W!>$1
R$+ $@ <$w!>$1
# Only add our name to local mail. Anything that's focused, leave alone.
S14
R$*<$+>$* $@ $1<$2>$3
R$+:$*; $@ $1:$2;
#R$+ $@ <$W!>$1
R$+ $@ <$w!>$1
# SMTP mailers require that addresses be in rfc822 format. If there's no
# @ in the address, add one.
S15
R<$W!>$+ $1<@$w>
R<$-.$+!>$+ $3<@$1.$2>
R$*<@$+>$* $@ $1<@$2>$3
R<$+!>$+ $@ $1!$2<@$w>
R$+:$*; $@ $1:$2;
R<> $@
R$+ $@ $1<@$w>
# Local and prog mailer
S16
R$+ $@ $1
#
# Called on all outgoing addresses. Used to remove the <> focus
#
S4
R$*<$+>$* $@ $1$2$3 defocus

View File

@ -0,0 +1,71 @@
#-----------------------------------------------------------------------------
# Copyright (c) 1994 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.
#
# X.500 ldap rcpt500 mail query responder makefile
#
#-----------------------------------------------------------------------------
LDAPSRC = ../..
HDIR = $(LDAPSRC)/include
LDIR = $(LDAPSRC)/libraries
VERSIONFILE = $(LDAPSRC)/build/version
SRCS= main.c cmds.c help.c query.c
OBJS= main.o cmds.o help.o query.o
INCLUDES= -I$(HDIR)
DEFINES = $(DEFS)
CFLAGS = $(INCLUDES) $(DEFINES) $(ACFLAGS)
LIBS = -lldap -llber $(KRBLIBFLAG) $(KRBLIBS) $(ALIBS)
all: rcpt500
rcpt500: version.o
$(CC) $(ALDFLAGS) -o $@ $(OBJS) version.o -L$(LDIR) $(LIBS)
version.c: $(OBJS) $(LDIR)/libldap.a
$(RM) $@
(u=$${USER-root} v=`$(CAT) $(VERSIONFILE)` d=`$(PWD)` h=`$(HOSTNAME)` \
t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
-e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
-e "s|%VERSION%|$${v}|" \
< Version.c > $@)
install: rcpt500 rcpt500.help FORCE
-$(MKDIR) -p $(ETCDIR)
$(INSTALL) $(INSTALLFLAGS) -m 755 rcpt500 $(ETCDIR)
$(INSTALL) $(INSTALLFLAGS) -m 644 rcpt500.help $(ETCDIR)
lint: FORCE
$(LINT) $(INCLUDES) $(DEFINES) $(SRCS)
5lint: FORCE
$(5LINT) $(INCLUDES) $(DEFINES) $(SRCS)
clean: FORCE
$(RM) *.o core a.out version.c rcpt500
depend: FORCE
$(MKDEP) $(INCLUDES) $(DEFINES) $(SRCS)
links:
@$(LN) .src/README .src/*.[ch] .src/*.help .
# DO NOT DELETE THIS LINE -- mkdep uses it.
# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
main.o: main.c ../../include/portable.h ../../include/ldapconfig.h rcpt500.h
cmds.o: cmds.c rcpt500.h
help.o: help.c ../../include/portable.h ../../include/ldapconfig.h rcpt500.h
query.o: query.c ../../include/lber.h ../../include/ldap.h
query.o: ../../include/portable.h ../../include/ldapconfig.h
query.o: ../../include/disptmpl.h rcpt500.h
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY

115
clients/rcpt500/README Normal file
View File

@ -0,0 +1,115 @@
LDAP rcpt500 mail query server README
OVERVIEW
This is a mail-query server that answers X.500 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 X.500 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 x500-query@umich.edu
Subject: find tim howes
.
Reply from rcpt500:
Received: from totalrecall.rs.itd.umich.edu by terminator.cc.umich.edu
id AA26151; Wed, 16 Sep 92 11:26:18 -0400
Received: by umich.edu (5.65/2.2)
id AA12041; Wed, 16 Sep 92 11:26:17 -0400
Message-Id: <9209161526.AA12041@umich.edu>
Date: Wed, 16 Sep 92 11:26:17 -0400
From: "X.500 Query Program" <X500-Query@umich.edu>
Subject: Re: find tim howes
In-Reply-To: Your message of "Wed, 16 Sep 92 11:26:12 -0400"
<9209161526.AA26144@terminator.cc.umich.edu>
To: "Mark Smith" <mcs@terminator.cc.umich.edu>
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 x500-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:
x500-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 X.500 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 X.500 as when searching
The search and display behavior is defined in the ldapfilter.conf and
ldaptemplates.conf files.
SUPPORT
The software is provided as is without any express or implied
warranty, but there is a bug reporting mail address which is
responded to on a best-effort basis:
ldap-support@terminator.cc.umich.edu
BUG REPORTING
Bug reports should be sent to bug-ldap@terminator.cc.umich.edu.
README Last updated 10 November 1994 Mark Smith

13
clients/rcpt500/Version.c Normal file
View File

@ -0,0 +1,13 @@
/*
* Copyright (c) 1992 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.
*/
char Version[] = " rcpt500 v%VERSION% (%WHEN%)\n\t%WHOANDWHERE%\n";

28
clients/rcpt500/cmds.c Normal file
View File

@ -0,0 +1,28 @@
/*
* 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 <stdio.h>
#include "rcpt500.h"
struct command 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 */
};

49
clients/rcpt500/help.c Normal file
View File

@ -0,0 +1,49 @@
/*
* 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 <stdio.h>
#include <syslog.h>
#include <string.h>
#include <fcntl.h>
#include "portable.h"
#include "ldapconfig.h"
#include "rcpt500.h"
extern int dosyslog;
int
help_cmd( msgp, reply )
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 );
}

384
clients/rcpt500/main.c Normal file
View File

@ -0,0 +1,384 @@
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <string.h>
#include <ctype.h>
#include "portable.h"
#include "ldapconfig.h"
#include "rcpt500.h"
#ifdef ultrix
extern char *strdup();
#endif
int dosyslog = 0;
#ifdef CLDAP
int do_cldap = 0;
#endif /* CLDAP */
int derefaliases = 1;
int sizelimit = RCPT500_SIZELIMIT;
int rdncount = RCPT500_RDNCOUNT;
int ldapport = 0;
char *ldaphost = LDAPHOST;
char *searchbase = RCPT500_BASE;
char *dapuser = RCPT500_BINDDN;
char *filterfile = FILTERFILE;
char *templatefile = TEMPLATEFILE;
char reply[ MAXSIZE * RCPT500_LISTLIMIT ];
/*
* functions
*/
int read_msg();
char *read_hdr();
int send_reply();
/*
* main is invoked by sendmail via the alias file
* the entire incoming message gets piped to our standard input
*/
main( argc, argv )
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;
char *replytext;
extern int optind;
extern char *optarg;
*reply = '\0';
if (( prog = strrchr( argv[ 0 ], '/' )) == NULL ) {
prog = strdup( argv[ 0 ] );
} else {
prog = strdup( prog + 1 );
}
errflg = 0;
while (( c = getopt( argc, argv, "alUh:b:s:z:f:t:p:c:" )) != EOF ) {
switch( c ) {
case 'a':
derefaliases = 0;
break;
case 'l':
dosyslog = 1;
break;
case 'U':
#ifdef CLDAP
do_cldap = 1;
#else /* CLDAP */
fprintf( stderr, "Compile with -DCLDAP for -U support\n" );
#endif /* CLDAP */
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( 1 );
}
if ( dosyslog ) {
/*
* if syslogging requested, initialize
*/
#ifdef LOG_DAEMON
openlog( prog, OPENLOG_OPTIONS, LOG_DAEMON );
#else
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" :
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",
cmds[ msg.msg_command ].cmd_text, msg.msg_arg );
*/
(*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 );
}
int
read_msg( fp, msgp )
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 );
}
char *
read_hdr( fp, offset, buf, MAXSIZEe, linep )
FILE *fp;
int offset;
char *buf;
int MAXSIZEe;
char **linep;
{
char *hdr;
for ( hdr = buf + offset; isspace( *hdr ); ++hdr ) {
;
}
if (( hdr = strdup( hdr )) == NULL ) {
if ( dosyslog ) {
syslog( LOG_ERR, "strdup: %m" );
}
exit( 1 );
}
while ( 1 ) {
*linep = fgets( buf, MAXSIZE, fp );
buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
if ( *linep == NULL || !isspace( **linep )) {
break;
}
if (( hdr = realloc( hdr, strlen( hdr ) +
strlen( *linep ) + 3 )) == NULL) {
if ( dosyslog ) {
syslog( LOG_ERR, "realloc: %m" );
}
exit( 1 );
}
strcat( hdr, "\n" );
strcat( hdr, *linep );
}
return( hdr );
}
int
send_reply( msgp, body )
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 );
}
int
find_command( text, argp )
char *text;
char **argp;
{
int i;
char *s, *p;
static char argbuf[ MAXSIZE ];
p = text;
for ( s = argbuf; *p != '\0'; ++p ) {
*s++ = tolower( *p );
}
*s = '\0';
for ( i = 0; cmds[ i ].cmd_text != NULL; ++i ) {
if (( s = strstr( argbuf, cmds[ i ].cmd_text )) != NULL
&& isspace( *(s + strlen( cmds[ i ].cmd_text )))) {
strcpy( argbuf, text + (s - argbuf) + strlen( cmds[ i ].cmd_text ));
*argp = argbuf;
while ( isspace( **argp )) {
++(*argp);
}
return( i );
}
}
return( -1 );
}

348
clients/rcpt500/query.c Normal file
View File

@ -0,0 +1,348 @@
/*
* 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 <stdio.h>
#include <syslog.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#include "lber.h"
#include "ldap.h"
#include "portable.h"
#include "ldapconfig.h"
#include "disptmpl.h"
#include "rcpt500.h"
extern int dosyslog;
extern int do_cldap;
extern int rdncount;
extern int derefaliases;
extern int sizelimit;
extern int ldapport;
extern char *ldaphost;
extern char *searchbase;
extern char *dapuser;
extern char *filterfile;
extern char *templatefile;
static char buf[ MAXSIZE ];
static char *errpreface = "Your query failed: ";
extern int strcasecmp();
void close_ldap();
int
query_cmd( msgp, reply )
struct msginfo *msgp;
char *reply;
{
LDAP *ldp;
LDAPMessage *ldmsgp, *entry;
char *s, *dn;
int matches, rc, ufn;
LDAPFiltDesc *lfdp;
LDAPFiltInfo *lfi;
struct ldap_disptmpl *tmpllist = NULL;
static char *attrs[] = { "cn", "title",
#ifdef RCPT500_SORT_ATTR
RCPT500_SORT_ATTR,
#endif
NULL };
ufn = 0;
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
*/
#ifdef CLDAP
if ( do_cldap )
ldp = cldap_open( ldaphost, ldapport );
else
#endif /* CLDAP */
ldp = ldap_open( ldaphost, ldapport );
if ( ldp == NULL ) {
strcat( reply, errpreface );
strcat( reply, "X.500 service unavailable. Try again later." );
ldap_getfilter_free( lfdp );
return( 0 );
}
#ifdef CLDAP
if ( !do_cldap )
#endif /* CLDAP */
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
*/
ldp->ld_deref = derefaliases;
ldp->ld_sizelimit = sizelimit;
matches = 0;
#ifdef RCPT500_UFN
#ifdef CLDAP
if ( !do_cldap && strchr( msgp->msg_arg, ',' ) != NULL ) {
#else /* CLDAP */
if ( strchr( msgp->msg_arg, ',' ) != NULL ) {
#endif /* CLDAP */
struct timeval tv;
ldap_ufn_setprefix( ldp, searchbase );
if (( rc = ldap_ufn_search_s( ldp, msgp->msg_arg, attrs, 0, &ldmsgp ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
&& rc != LDAP_TIMELIMIT_EXCEEDED ) {
report_ldap_err( ldp, reply );
close_ldap( ldp );
ldap_getfilter_free( lfdp );
return( 0 );
}
matches = ldap_count_entries( ldp, ldmsgp );
ufn = 1;
} else {
#endif /* RCPT500_UFN */
for ( lfi = ldap_getfirstfilter( lfdp, "rcpt500", msgp->msg_arg );
lfi != NULL; lfi = ldap_getnextfilter( lfdp )) {
#ifdef CLDAP
if ( do_cldap )
rc = cldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
lfi->lfi_filter, attrs, 0, &ldmsgp, dapuser );
else
#endif /* CLDAP */
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 );
}
}
#ifdef RCPT500_UFN
}
#endif /* RCPT500_UFN */
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 );
}
if ( ldp->ld_errno == LDAP_TIMELIMIT_EXCEEDED
|| ldp->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,
ufn ? "UFN" : 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, ufn ? "UFN" : 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 );
}
void
close_ldap( LDAP *ld )
{
#ifdef CLDAP
if ( do_cldap )
cldap_close( ld );
else
#endif /* CLDAP */
ldap_unbind( ld );
}
append_entry_list( reply, query, ldp, ldmsgp )
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( *( 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 );
}
}
}
int
append_text( reply, text, len )
char *reply;
char *text;
int len;
{
strcat( reply, text );
return( len );
}
int
do_read( ldp, dn, reply, tmpll )
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, NULLMSG, tmpll,
defattrs, defvals, (void *)append_text, (void *)reply, "\n",
rdncount, LDAP_DISP_OPT_DOSEARCHACTIONS );
return( rc );
}
report_ldap_err( ldp, reply )
LDAP *ldp;
char *reply;
{
strcat( reply, errpreface );
strcat( reply, ldap_err2string( ldp->ld_errno ));
strcat( reply, "\n" );
}
remove_trailing_space( s )
char *s;
{
char *p = s + strlen( s ) - 1;
while ( isspace( *p ) && p > s ) {
--p;
}
*(++p) = '\0';
}

Some files were not shown because too many files have changed in this diff Show More