mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-03-19 14:30:57 +08:00
Initial revision
This commit is contained in:
commit
42e0d83cb3
90
ANNOUNCEMENT
Normal file
90
ANNOUNCEMENT
Normal 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
545
CHANGES
Normal 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
9
COPYRIGHT
Normal 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
136
INSTALL
Normal 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
200
Make-common
Normal 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
200
Make-common.um
Normal 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
392
Makefile
Normal 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
59
README
Normal 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
78
build/Make-append
Normal 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
38
build/Make-template
Normal 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
98
build/PORTS
Normal 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
3
build/README-unproto
Normal 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
158
build/db.1.85.patch
Normal 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
45
build/install.sh
Executable 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
133
build/mkdep
Executable 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
|
68
build/platforms/Make-setup
Normal file
68
build/platforms/Make-setup
Normal 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
46
build/platforms/Makefile
Normal 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:
|
||||
|
18
build/platforms/aix-cc/Make-platform
Normal file
18
build/platforms/aix-cc/Make-platform
Normal 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
|
19
build/platforms/aix-gcc/Make-platform
Normal file
19
build/platforms/aix-gcc/Make-platform
Normal 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
|
16
build/platforms/freebsd-gcc/Make-platform
Normal file
16
build/platforms/freebsd-gcc/Make-platform
Normal 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
|
27
build/platforms/hpux-c89/Make-platform
Normal file
27
build/platforms/hpux-c89/Make-platform
Normal 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
|
33
build/platforms/hpux-cc/Make-platform
Normal file
33
build/platforms/hpux-cc/Make-platform
Normal 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
|
28
build/platforms/hpux-gcc/Make-platform
Normal file
28
build/platforms/hpux-gcc/Make-platform
Normal 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
|
29
build/platforms/irix-cc/Make-platform
Normal file
29
build/platforms/irix-cc/Make-platform
Normal 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=
|
29
build/platforms/irix-gcc/Make-platform
Normal file
29
build/platforms/irix-gcc/Make-platform
Normal 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=
|
17
build/platforms/linux-gcc/Make-platform
Normal file
17
build/platforms/linux-gcc/Make-platform
Normal 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
|
34
build/platforms/ncr-mp-ras-2-cc/Make-platform
Normal file
34
build/platforms/ncr-mp-ras-2-cc/Make-platform
Normal 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
|
17
build/platforms/netbsd-cc/Make-platform
Normal file
17
build/platforms/netbsd-cc/Make-platform
Normal 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
|
16
build/platforms/netbsd-gcc/Make-platform
Normal file
16
build/platforms/netbsd-gcc/Make-platform
Normal 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
|
15
build/platforms/nextstep-cc/Make-platform
Normal file
15
build/platforms/nextstep-cc/Make-platform
Normal 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
|
24
build/platforms/osf1-cc/Make-platform
Normal file
24
build/platforms/osf1-cc/Make-platform
Normal 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
|
23
build/platforms/sco-cc/Make-platform
Normal file
23
build/platforms/sco-cc/Make-platform
Normal 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
|
22
build/platforms/sco-gcc/Make-platform
Normal file
22
build/platforms/sco-gcc/Make-platform
Normal 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
|
25
build/platforms/sunos4-cc/Make-platform
Normal file
25
build/platforms/sunos4-cc/Make-platform
Normal 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
|
19
build/platforms/sunos4-gcc/Make-platform
Normal file
19
build/platforms/sunos4-gcc/Make-platform
Normal 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
|
29
build/platforms/sunos5-cc/Make-platform
Normal file
29
build/platforms/sunos5-cc/Make-platform
Normal 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
|
28
build/platforms/sunos5-gcc/Make-platform
Normal file
28
build/platforms/sunos5-gcc/Make-platform
Normal 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
|
16
build/platforms/ultrix-cc/Make-platform
Normal file
16
build/platforms/ultrix-cc/Make-platform
Normal 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
|
16
build/platforms/ultrix-gcc/Make-platform
Normal file
16
build/platforms/ultrix-gcc/Make-platform
Normal 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
|
31
build/platforms/vms/Makefile
Normal file
31
build/platforms/vms/Makefile
Normal 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:
|
95
build/platforms/vms/make.com
Normal file
95
build/platforms/vms/make.com
Normal 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
109
build/uname.sh
Normal 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
123
build/unproto/Makefile
Normal 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
160
build/unproto/README
Normal 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
35
build/unproto/acc.sh
Executable 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
35
build/unproto/cpp.sh
Executable 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
97
build/unproto/error.c
Normal 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
6
build/unproto/error.h
Normal 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
222
build/unproto/example.c
Normal 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
271
build/unproto/example.out
Normal 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
54
build/unproto/hash.c
Normal 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
90
build/unproto/stdarg.h
Normal 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
23
build/unproto/stddef.h
Normal 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
53
build/unproto/stdlib.h
Normal 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
71
build/unproto/strsave.c
Normal 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
144
build/unproto/symbol.c
Normal 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
11
build/unproto/symbol.h
Normal 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
432
build/unproto/tok_class.c
Normal 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
612
build/unproto/tok_io.c
Normal 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
103
build/unproto/tok_pool.c
Normal 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
55
build/unproto/token.h
Normal 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
152
build/unproto/unproto.1
Normal 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
999
build/unproto/unproto.c
Normal 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
32
build/unproto/varargs.c
Normal 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
122
build/unproto/vstring.c
Normal 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
15
build/unproto/vstring.h
Normal 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
1
build/version
Normal file
@ -0,0 +1 @@
|
||||
3.3
|
84
clients/Make-template
Normal file
84
clients/Make-template
Normal 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
|
87
clients/fax500/Make-template
Normal file
87
clients/fax500/Make-template
Normal 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
104
clients/fax500/README
Normal 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
13
clients/fax500/Version.c
Normal 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";
|
13
clients/fax500/Versionrp.c
Normal file
13
clients/fax500/Versionrp.c
Normal 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
248
clients/fax500/faxtotpc.c
Normal 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
1499
clients/fax500/main.c
Normal file
File diff suppressed because it is too large
Load Diff
283
clients/fax500/rp500.c
Normal file
283
clients/fax500/rp500.c
Normal 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
85
clients/fax500/xrpcomp
Normal 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
|
70
clients/finger/Make-template
Normal file
70
clients/finger/Make-template
Normal 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
13
clients/finger/Version.c
Normal 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
429
clients/finger/main.c
Normal 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 );
|
||||
}
|
||||
}
|
91
clients/gopher/Make-template
Normal file
91
clients/gopher/Make-template
Normal 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
188
clients/gopher/README
Normal 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
13
clients/gopher/Version.c
Normal 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";
|
13
clients/gopher/Versiongw.c
Normal file
13
clients/gopher/Versiongw.c
Normal 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
80
clients/gopher/detach.c
Normal 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
568
clients/gopher/go500.c
Normal 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
891
clients/gopher/go500gw.c
Normal 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" );
|
||||
}
|
17
clients/gopher/go500gw.help
Normal file
17
clients/gopher/go500gw.help
Normal 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
|
46
clients/gopher/setproctitle.c
Normal file
46
clients/gopher/setproctitle.c
Normal 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++ = ' ';
|
||||
}
|
68
clients/mail500/Make-template
Normal file
68
clients/mail500/Make-template
Normal 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
186
clients/mail500/README
Normal 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
13
clients/mail500/Version.c
Normal 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
1691
clients/mail500/main.c
Normal file
File diff suppressed because it is too large
Load Diff
203
clients/mail500/sendmail.cf
Normal file
203
clients/mail500/sendmail.cf
Normal 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
|
71
clients/rcpt500/Make-template
Normal file
71
clients/rcpt500/Make-template
Normal 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
115
clients/rcpt500/README
Normal 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
13
clients/rcpt500/Version.c
Normal 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
28
clients/rcpt500/cmds.c
Normal 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
49
clients/rcpt500/help.c
Normal 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
384
clients/rcpt500/main.c
Normal 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
348
clients/rcpt500/query.c
Normal 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
Loading…
x
Reference in New Issue
Block a user