From 8a721589ac0839fdc4bb086df020291515dfec60 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Fri, 3 Jun 2016 09:17:51 -0700 Subject: [PATCH] import nph-1.2.3 --- .cvsignore | 3 + COPYRIGHT | 35 + ChangeLog | 560 +++ INSTALL | 183 + Makefile.in | 62 + README | 147 + TODO | 36 + autoconf/ac_path_generic.m4 | 136 + autoconf/aclocal.m4 | 199 + autoconf/encap.m4 | 133 + autoconf/install-sh | 251 ++ buffer/ChangeLog | 1 + buffer/TODO | 3 + buffer/buffer.c.in | 114 + buffer/buffer.h.in | 37 + buffer/module.ac | 18 + compat/ChangeLog | 34 + compat/README | 12 + compat/TODO | 4 + compat/basename.c | 74 + compat/compat.h | 260 ++ compat/dirname.c | 77 + compat/fnmatch.c | 237 ++ compat/gethostbyname_r.c | 41 + compat/gethostname.c | 36 + compat/getservbyname_r.c | 41 + compat/glob.c | 873 +++++ compat/inet_aton.c | 27 + compat/module.ac | 608 +++ compat/snprintf.c | 788 ++++ compat/strdup.c | 62 + compat/strlcat.c | 72 + compat/strlcpy.c | 68 + compat/strmode.c | 152 + compat/strrstr.c | 40 + compat/strsep.c | 87 + config.h.in | 158 + configure | 7103 +++++++++++++++++++++++++++++++++++ configure.ac | 98 + doc/Makefile.in | 120 + doc/nph.1 | 375 ++ doc/ph_change.3 | 51 + doc/ph_email_resolve.3 | 56 + doc/ph_encode_selector.3 | 43 + doc/ph_get_fieldinfo.3 | 79 + doc/ph_get_option.3 | 72 + doc/ph_get_siteinfo.3 | 68 + doc/ph_id.3 | 37 + doc/ph_login.3 | 85 + doc/ph_open.3 | 66 + doc/ph_query.3 | 49 + doc/ph_rfd.3 | 33 + doc/ph_serverlist_add.3 | 67 + doc/ph_set_sendhook.3 | 33 + doc/ph_www_resolve.3 | 43 + doc/rfc2378.txt | 1235 ++++++ lib/Makefile.in | 93 + lib/auth.c | 485 +++ lib/change.c | 236 ++ lib/fields.c | 397 ++ lib/handle.c | 347 ++ lib/internal.h | 104 + lib/misc.c | 120 + lib/options.c | 245 ++ lib/phclient.h | 606 +++ lib/protocol.c | 499 +++ lib/query.c | 206 + lib/redirection.c | 521 +++ lib/serverlist.c | 248 ++ lib/siteinfo.c | 204 + mmgr/ChangeLog | 4 + mmgr/TODO | 3 + mmgr/mmgr.c.in | 268 ++ mmgr/mmgr.h.in | 69 + mmgr/module.ac | 17 + nph/Makefile.in | 90 + nph/commands.c | 403 ++ nph/conf.c | 461 +++ nph/content.c | 723 ++++ nph/edit.c | 237 ++ nph/init.c | 293 ++ nph/interactive.c | 439 +++ nph/login.c | 212 ++ nph/nph.c | 152 + nph/nph.h | 223 ++ nph/output.c | 346 ++ nph/serverinfo.c | 250 ++ nph/sighandler.c | 146 + nphrc | 9 + postinstall.in | 42 + 90 files changed, 24080 insertions(+) create mode 100644 .cvsignore create mode 100644 COPYRIGHT create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.in create mode 100644 README create mode 100644 TODO create mode 100644 autoconf/ac_path_generic.m4 create mode 100644 autoconf/aclocal.m4 create mode 100644 autoconf/encap.m4 create mode 100755 autoconf/install-sh create mode 100644 buffer/ChangeLog create mode 100644 buffer/TODO create mode 100644 buffer/buffer.c.in create mode 100644 buffer/buffer.h.in create mode 100644 buffer/module.ac create mode 100644 compat/ChangeLog create mode 100644 compat/README create mode 100644 compat/TODO create mode 100644 compat/basename.c create mode 100644 compat/compat.h create mode 100644 compat/dirname.c create mode 100644 compat/fnmatch.c create mode 100644 compat/gethostbyname_r.c create mode 100644 compat/gethostname.c create mode 100644 compat/getservbyname_r.c create mode 100644 compat/glob.c create mode 100644 compat/inet_aton.c create mode 100644 compat/module.ac create mode 100644 compat/snprintf.c create mode 100644 compat/strdup.c create mode 100644 compat/strlcat.c create mode 100644 compat/strlcpy.c create mode 100644 compat/strmode.c create mode 100644 compat/strrstr.c create mode 100644 compat/strsep.c create mode 100644 config.h.in create mode 100755 configure create mode 100644 configure.ac create mode 100644 doc/Makefile.in create mode 100644 doc/nph.1 create mode 100644 doc/ph_change.3 create mode 100644 doc/ph_email_resolve.3 create mode 100644 doc/ph_encode_selector.3 create mode 100644 doc/ph_get_fieldinfo.3 create mode 100644 doc/ph_get_option.3 create mode 100644 doc/ph_get_siteinfo.3 create mode 100644 doc/ph_id.3 create mode 100644 doc/ph_login.3 create mode 100644 doc/ph_open.3 create mode 100644 doc/ph_query.3 create mode 100644 doc/ph_rfd.3 create mode 100644 doc/ph_serverlist_add.3 create mode 100644 doc/ph_set_sendhook.3 create mode 100644 doc/ph_www_resolve.3 create mode 100644 doc/rfc2378.txt create mode 100644 lib/Makefile.in create mode 100644 lib/auth.c create mode 100644 lib/change.c create mode 100644 lib/fields.c create mode 100644 lib/handle.c create mode 100644 lib/internal.h create mode 100644 lib/misc.c create mode 100644 lib/options.c create mode 100644 lib/phclient.h create mode 100644 lib/protocol.c create mode 100644 lib/query.c create mode 100644 lib/redirection.c create mode 100644 lib/serverlist.c create mode 100644 lib/siteinfo.c create mode 100644 mmgr/ChangeLog create mode 100644 mmgr/TODO create mode 100644 mmgr/mmgr.c.in create mode 100644 mmgr/mmgr.h.in create mode 100644 mmgr/module.ac create mode 100644 nph/Makefile.in create mode 100644 nph/commands.c create mode 100644 nph/conf.c create mode 100644 nph/content.c create mode 100644 nph/edit.c create mode 100644 nph/init.c create mode 100644 nph/interactive.c create mode 100644 nph/login.c create mode 100644 nph/nph.c create mode 100644 nph/nph.h create mode 100644 nph/output.c create mode 100644 nph/serverinfo.c create mode 100644 nph/sighandler.c create mode 100644 nphrc create mode 100755 postinstall.in diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..383d757 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,3 @@ +autom4te.cache +configure +config.h.in diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..db21d34 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,35 @@ +Copyright (c) 2000-2004 University of Illinois Board of Trustees +Copyright (c) 2000-2004 Mark D. Roth +All rights reserved. + +Developed by: Campus Information Technologies and Educational Services, + University of Illinois at Urbana-Champaign + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal with the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimers. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + +* Neither the names of Campus Information Technologies and Educational + Services, University of Illinois at Urbana-Champaign, nor the names + of its contributors may be used to endorse or promote products derived + from this Software without specific prior written permission. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..ad46b82 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,560 @@ +nph 1.2.3 - 6/17/04 +--------- + +- updated ph_open(3) man page +- updated ph_email_resolve(3) man page +- added PH_ERR_READONLY constant +- modified ph_change(), ph_add(), and ph_delete() to return + PH_ERR_READONLY when server is in read-only mode + (note that this also affects ph_passwd(), since it uses ph_change()) +- modified nph "change", "add", "delete", and "edit" commands to + check for PH_ERR_READONLY return value from libphclient +- fixed ph_email_resolve() to avoid segfault if user name is all + punctuation or all spaces + (thanks to Neil Rickert for the bug report) +- added "keyfields=" option to nph "resolve_email" command + +---------------------------------------------------------------------------- + +nph 1.2.2 - 7/2/03 +--------- + +- fixed ph_open() to check that result parameter of gethostbyname_r() + and getservbyname_r() is non-NULL + (was causing segfault under Linux for unknown hostnames; thanks to + Damian Menscher for the bug report) +- fixed segfault in nph "make" command + +---------------------------------------------------------------------------- + +nph 1.2.1 - 5/9/03 +--------- + +- minor portability fixes +- better handling of postinstall script in top-level Makefile +- fixed bug in ph_email_resolve() that caused a segfault when querying + based on the "name" field + (thanks to Neil Rickert and + Doug Brenner for the bug reports) +- renamed MASK macro in lib/auth.c to avoid conflict with OS X header files + (thanks to Andrew Laurence for the bug report) +- added autoconf test for _SC_GETPW_R_SIZE_MAX + (thanks to Jon Roma and Andrew Laurence + for the bug reports) + +---------------------------------------------------------------------------- + +nph 1.2.0 - 11/24/02 +--------- + +- updated README file +- added libphclient_is_thread_safe variable to libphclient API +- updated compat code +- minor portability fixes + +---------------------------------------------------------------------------- + +nph 1.2.dev1 - 11/11/02 +------------ + +- use poll() or select() to avoid SIGPIPE in ph_send_command() +- replaced ph_fd() function with ph_rfd() and ph_wfd() + +---------------------------------------------------------------------------- + +nph 1.2.dev0 - 10/19/02 +------------ + +- libphclient API changes: + - use clearer names for constant macros in + - add prefixes to field names in all structures + - pass application-supplied pointer to send/recv hooks + - moved PH structure definition out of + - libphclient code is now thread-safe +- code cleanup: + - reformatted code for readability + - moved network line buffer code into its own module + - moved memory management code into its own module +- packaging changes: + - updated COPYRIGHT info + - updated autoconf macros + - added --with-mailmatches configure option + +---------------------------------------------------------------------------- + +nph 1.1.8 - 6/14/02 +--------- + +- fixed postinstall script to find nslookup in either /usr/bin or + /usr/sbin +- updated to autoconf-2.53 +- added ".PHONY" target in top-level Makefile.in to fix portability issue + (thanks to Alex J. Lovell-Troy for the bug report) +- removed silly extern wrapper from nph/nph.h +- avoid segfault when requesting a hidden field +- calculate query output field name width dynamically +- free fieldinfo cache in ph_login(), ph_logout(), and ph_suser() to + accomodate hidden fields that are only visible to heros +- restructured autoconf macros + +---------------------------------------------------------------------------- + +nph 1.1.7 - 1/30/02 +--------- + +- fixed postinstall script to properly find domain even if hostname is + not set to the FQDN + (thanks to Charley LeCrone for the suggestion) +- use $HOME if set instead of getpwuid(getuid()) +- do not use pager in non-interactive mode +- match option, siteinfo, and field names in a case-insensitive manner +- minor code cleanups +- updated to autoconf-2.52 +- improved Makefile portability +- avoid segfault when "return" is the first word of a query + (thanks to Charley LeCrone for the bug report) +- fixed ph_email_resolve() to properly return PH_DATAERR when the matching + entry does not have an "email" field + (based on patch from Doug Brenner ) + +---------------------------------------------------------------------------- + +nph 1.1.6 - 5/29/01 +--------- + +- updated to use readline-4.2 API + +---------------------------------------------------------------------------- + +nph 1.1.5 - 5/29/01 +--------- + +- match field names in a case-insensitive manner +- updated autoconf macros and compat code +- if server doesn't support "fields" command, avoid infinite loop and + assume default field name length of 16 + +---------------------------------------------------------------------------- + +nph 1.1.4 - 1/18/01 +--------- + +- changed ph_serverlist_merge(), ph_email_resolve(), + ph_advertised_email(), ph_www_resolve(), and ph_advertised_www() + to handle PH_DATAERR when returned from ph_query() + +---------------------------------------------------------------------------- + +nph 1.1.3 - 1/17/01 +--------- + +- changed ph_query() to return PH_DATAERR for invalid queries +- changed ph_login() to set errno properly +- updated autoconf macros +- automatically add postinstall script when creating Encap package +- install nphrc and ph_server files from postinstall script instead of + from make install target +- minor code cleanups + +---------------------------------------------------------------------------- + +nph 1.1.2 - 12/13/00 +--------- + +- fixed "set" command to properly display an error when setting a + non-existant option +- fixed autoconf snprintf() test to make sure it NUL-terminates +- added $(DESTDIR) to Makefiles (patch from Dave Terrell ) +- replaced $(etcdir) with $(sysconfdir) in nph/Makefile.in +- Makefile changes to support WSG_PKG and WSG_ENCAP autoconf macros + +---------------------------------------------------------------------------- + +nph 1.1.1 - 10/29/00 +--------- + +- fixed bug in ph_open() related to non-default port numbers +- removed reference to ph_free_query() from ph_query() manpage +- fixed memory leak in nph by calling ph_free_selectors() instead of free() +- updated README file +- minor directory structure changes because of CVS setup +- various portability fixes + +---------------------------------------------------------------------------- + +nph 1.1 - 9/14/00 +------- + +- changed argument list for ph_open() +- trailing newline is no longer sent to sendhook function +- nph query output looks more like the original ph client + +---------------------------------------------------------------------------- + +nph 1.0.3 - 9/12/00 +--------- + +- fixed a bug in ph_get_fieldinfo() which caused a segfault when + called with an unknown field name +- fixed ph_open() not to send the ident string if the connection fails +- fixed segfault in nph when server returned no status info +- fixed segfault in nph when user typed "query" or "ph" with no further + arguments +- changed various redundant for() loops to while() loops for strsep() +- minor manpage corrections + +---------------------------------------------------------------------------- + +nph 1.0.2 - 7/20/00 +--------- + +- added note to README about requiring readline-4.1 or newer +- changed ph_get_response() to set errno to ECONNRESET and return -1 + when read() returns 0 +- declare internal auxiliury functions as static in lib/redirection.c +- changed ph_open() to fall back to a hardcoded port if the "csnet-ns" + service isn't found +- changed ph_email_resolve() to ignore the fields argument if it points + to an empty string + (thanks to Jon Roma ) +- improved ph_email_resolve(3) manpage + (thanks to Jon Roma ) +- added aclocal.m4 to clean up configure.in +- removed "inline" declarations +- portability fixes related to snprintf() + +---------------------------------------------------------------------------- + +nph 1.0.1 - 5/27/00 +--------- + +- changed PH_DEFAULT_MAILMATCHES to "alias:callsign" +- changed ph_email_resolve() to terminate the returned address at the first + whitespace or comma +- fixed error in lib/options.c which failed to return 0 on successful + return from ph_retrieve_options() +- fixed error in lib/options.c which failed to set errno to EINVAL in + ph_set_option() +- removed declarations for various unused variables +- fixed nph/Makefile.in to strip installed nph binary + +---------------------------------------------------------------------------- + +nph 1.0 - 5/9/00 +------- + +- First public release + +---------------------------------------------------------------------------- + +nph 0.10.7 - 4/21/00 +---------- + +- fixed NULL pointer problem with defaultfield and returnfields options + +---------------------------------------------------------------------------- + +nph 0.10.6 - 4/7/00 +---------- + +- portability fix: use autoconf to detect + (thanks to Dave Terrell for the patch) +- fixed segfault caused by logging in and then quitting + (thanks to Geoff Raye for the bug report) +- added $(CFLAGS) to link link in nph/Makefile.in + +---------------------------------------------------------------------------- + +nph 0.10.5 - 4/2/00 +---------- + +- fixed lib/stack.c to avoid calling free() on a NULL pointer + (needed to prevent segfault in sendmail timeout code) + +---------------------------------------------------------------------------- + +nph 0.10.4 - 4/1/00 +---------- + +- fixed bugs in field alias code +- fixed C preprocessor typo in lib/query.c +- simplified readline detection +- removed a patch from 0.10.2 which declared variables as extern and then + later without extern to prevent vendor compiler horkage +- changed nph/Makefile.in to install a default ph_server file + +---------------------------------------------------------------------------- + +nph 0.10.3 - 3/29/00 +---------- + +- added "defaultfield" option to set field for selectors which do not + specify a field name +- set rl_readline_name in nph/interactive.c +- fixed option parsing (broken from 0.10.2) +- added support for field aliases via the "fieldaliases" server option + +---------------------------------------------------------------------------- + +nph 0.10.2 - 3/29/00 +---------- + +- changed syntax for "option" command to allow whitespace surrounding '=' +- nph calls ph_id() automatically to log its version on the server +- ph_open() automatically calls ph_id() to log the libphclient version + on the server unless the PH_DONTID flag is set +- if "canonicaladdrs" option is set, nph will always display cannonical + email and www fields, even if those fields were directly requested + in the return clause +- added libphclient_version variable to libphclient +- minor config cleanup + +---------------------------------------------------------------------------- + +nph 0.10.1 - 3/24/00 +---------- + +- fixed a typo in nph/interactive.c affecting systems without poll() +- changed nph/content.c to look for "canonicaladdrs" option instead of + "showredirects" (was actually renamed in 0.10) + +---------------------------------------------------------------------------- + +nph 0.10 - 3/21/00 +-------- + +- libphclient changes: + - added general-purpose return value macros to and modified + all library functions to use them as appropriate + - changed ph_retrieve_*() functions to use stack and only set fields of + ph handle when they complete successfully + - changed ph_retrieve_*() functions to return 0 immediately if data is + already cached locally + - added ph_is_*_cached() macros to determine if PH handle fields are valid + - moved ph_free_*() functions for fieldlist, options, and siteinfo to the + public interface + - fixed ph_resolve_www() and ph_advertised_www() to return PH_DATAERR + if the matching entry does not have a "www" field + - fixed ph_advertised_www() to call ph_resolve_www() if the server + doesn't support the "wwwredirects" siteinfo field + - fixed ph_change() to return PH_DATAERR if it reads a -LR_VALUE + response code + - added ph_fd() call + - changed NSSERVICE to PH_SERVICE + - changed BUF_SIZE to PH_BUF_SIZE + +- nph changes: + - default server is now determined from commandline, ${PH_SERVER}, or + ${prefix}/etc/ph_server (in that order) + - check for .nphrc.${PH_SERVER}, then .nphrc, then ${prefix}/etc/nphrc + (this allows for per-server dotfiles) + - nphrc files are now parsed as nph commands, rather than simply option + settings, so any arbitrary command can be run automatically + - added "serveradd" command to replace ph_servers file + - added "connect" command to connect to a new server + - added "source" command to read commands from a file + - added "ph" as a synonym for "query" command + - changed "servers" to "listservers" + - misc updates to reflect libphclient changes above + - make sure to call rl_callback_handler_remove() before all exit() calls + +- portability fixes: + - added check for vfork() to configure script + - fixed syntax error in nph/interactive.c for systems without poll() + - added a digusting hack in nph/interactive.c to force use of select() + over poll() under IRIX + +---------------------------------------------------------------------------- + +nph 0.9.4 - 3/7/00 +--------- + +- replaced ph_serverlist() call with new calls ph_serverlist_add(), + ph_serverlist_iterate(), and ph_serverlist_merge() +- nph now reads ${prefix}/etc/ph_servers for the default server/site + list, and adds to this list from servers which have additional data + +---------------------------------------------------------------------------- + +nph 0.9.3 - 3/5/00 +--------- + +- changed ph_close() to not wait for a response code if PH_FASTCLOSE is set +- added lib/serverlist.c module to libphclient and corresponding + "servers" command to nph +- added optional "@domain" argument to nph query command which will perform + the query on a known PH server for "domain" +- replaced global ph_server variable in nph with "server" option + (setting this will change which server you are connected to) +- added "usereservedport" option to nph +- removed "-p" commandline option to nph (ports are now represented as + part of the server name, such as "ns.uiuc.edu:105") +- nph will now read ${prefix}/etc/nphrc before the user's .nphrc file +- improved handling of SIGINT in nph readline code + +---------------------------------------------------------------------------- + +nph 0.9.2 - 2/24/00 +--------- + +- misc portability fixes +- added error checking for memory allocation in library code +- added conditional directives to lib/phclient.h to prevent including it twice +- changed ph_resolve_email() to accept ':' or ' ' as a delimiter in field list +- added "confirm_alias" argument to ph_advertised_email() + and ph_advertised_www() +- various documentation fixes and updates +- improved space-padding of field names in query output + (thanks to Geoff Raye for the suggestion) +- optimized nph query code to add "alias" to list of requested fields rather + than requesting all fields and only printing some +- added "-C" option to tell nph not to read ~/.nphrc +- changed nph to bail out if "-f rcfile" was used but rcfile doesn't exist +- nph readline completion code now handles the "return", "make", and + "force" keywords + +---------------------------------------------------------------------------- + +nph 0.9.1 - 2/23/00 +--------- + +- fixed a bug in nph/commands.c which free()'d staticly-allocated memory +- fixed a bug in nph/conf.c which caused nph to segfault if "-f nphrc" + option was used +- changed ph_query() to return -2 if it encountered an LR_TOOMANY response +- portability fix: if EPROTO isn't defined, use EINVAL + +---------------------------------------------------------------------------- + +nph 0.9 - 2/22/00 +------- + +- changed ph_open() to allocate memory for the PH handle and set a pointer, + rather than filling in a caller-supplied buffer +- changed ph_close() to check the response code to the "quit" command +- cleaned up API for field list, server options, and siteinfo list +- cleaned up value-parsing code and moved it from nph into libphclient + (see new ph_encode_selector() call) +- fixed nph to set debugging hooks and validate "returnfields" option + after connecting to the PH server +- changed readline code to redisplay input line after debugging output + (e.g., for completion of field names or server options) +- added "-V" option to display nph version + +---------------------------------------------------------------------------- + +nph 0.8 - 2/20/00 +------- + +- added manpages for libphclient API and nph client +- replaced ph_field structure with ph_fieldselector (for queries) and + ph_fieldval (which includes the response code for returned entries) +- added a generalized stack mechanism in PH handle to prevent memory leaks +- replaced php and current_alias in PH handle with new struct ph_auth +- added nph "confirmedits" option (and corresponding commandline option "-c") +- added nph "returnfields" option to set default return fields +- readline completion code now completes client options and server options + where appropriate +- changed "edit" command to support "edit field alias" + +---------------------------------------------------------------------------- + +nph 0.7 - 2/18/00 +------- + +- changed some variable names, function names, and paramter lists to + improve readability +- added send and receive hook functions so applications can see everything + sent between the client and server +- added library calls to determine resolved and advertised URLs for + PH-redirected www fields (actually added in 0.6, forgot to list below) +- added "resolve_www" and "public_www" commands to nph +- replaced "auth_method" command with generic "option" command which + can change any nph setting +- nph commands can be redirected to a file or piped to a program with + ">", ">>", or "|" +- "query", "me", and "status" commands are piped through the pager + by default +- if compiled with readline support, nph commandline is redisplayed + after being suspended and foregrounded again +- if compiled with readline support, command can be interrupted with SIGINT +- added "make" command +- expanded nph "whoami" command to display server and port + +---------------------------------------------------------------------------- + +nph 0.6 - 2/14/00 +------- + +- changed several filenames to better reflect their content +- moved current_alias field from nph code to PH structure in libphclient + and added ph_whoami() call to lib/auth.c +- changed auth method plugins in lib/auth.c to use a static buffer from + the caller rather than dynamicly allocating memory +- added ph_quote_value() in lib/protocol.c to convert a field value from + literal representation to a server-parsable quoted string +- fixed nph client to use literal representation of field values internally +- added "edit" and "me" commands +- nph will now send a query from its commandline arguments, just like + the classic ph client +- added/changed several commandline options to nph + +---------------------------------------------------------------------------- + +nph 0.5 - 2/12/00 +------- + +- added whoami command +- fixed parsing problem with trailing spaces +- added bye, stop, and exit as synonyms for quit +- added motd as a synonym for status +- updated help information +- added ph_passwd() library call and corresponding functionality in nph +- added --enable-nph-setuid configure option +- nph drops root privs after connecting to the PH server if installed setuid +- changed ph_resolve_email() to ignore all but the first address listed + in the matching email field + +---------------------------------------------------------------------------- + +nph 0.4 - 2/11/00 +------- + +- added readline and polling support to nph +- added command and field completion +- tweaked Makefiles to support CPPFLAGS +- fixed to correctly parse quoted strings for field values + +---------------------------------------------------------------------------- + +nph 0.3 - 2/10/00 +------- + +- modularized nph client code +- added basic help facility to nph +- added rudimentary ~/.nphrc support +- decided not to encode key modification information in server mailmatches + field and modified ph_resolve_email() to just use builtin defaults +- added argument to ph_resolve_email() to avoid memory leaks in applications + which use timeouts +- changed ph_resolve_email() to properly handle a lookup which returns + only a single error field (e.g., when email field is not present) + +---------------------------------------------------------------------------- + +nph 0.2 - 2/9/00 +------- + +- removed extraneous strsep() prototypes from library code +- added phent argument to ph_email_address() in emailaddr.c to + avoid memory leak in applications which use timeouts +- changed arguments of ph_resolve_email() so that server can indicate + how keys should be modified before a given field lookup + +---------------------------------------------------------------------------- + +nph 0.1 - 2/7/00 +------- + +- Initial alpha release. + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..50dbe43 --- /dev/null +++ b/INSTALL @@ -0,0 +1,183 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..cb33672 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,62 @@ +# @configure_input@ + +### Path settings +prefix = @prefix@ +top_srcdir = @top_srcdir@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +mandir = @mandir@ +libdir = @libdir@ +includedir = @includedir@ + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ + +@ENCAP_DEFS@ + +### Installation programs and flags +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +@SET_MAKE@ + + +### Makefile rules - no user-servicable parts below + +SUBDIRS = lib nph doc + +all: + for n in ${SUBDIRS}; do \ + ( cd $$n && ${MAKE} $@ ${MAKE_FLAGS} ) || exit 1; \ + done + +.PHONY: install install-recurse postinstall-encap postinstall-no-encap clean distclean + +install: install-recurse @ENCAP_INSTALL_TARGET@ + +install-recurse: + for n in ${SUBDIRS}; do \ + ( cd $$n && ${MAKE} install ${MAKE_FLAGS} ) || exit 1; \ + done + +postinstall-encap: + ${INSTALL_DATA} ${top_srcdir}/nphrc ${ENCAP_SOURCE}/${ENCAP_PKGSPEC} + ${INSTALL_PROGRAM} postinstall ${ENCAP_SOURCE}/${ENCAP_PKGSPEC} + @ENCAP_INSTALL_RULES@ + +postinstall-no-encap: + prefix="${prefix}" ENCAP_SOURCE="${top_srcdir}" ENCAP_PKGNAME="" sh postinstall + +clean: + for n in ${SUBDIRS}; do \ + ( cd $$n && ${MAKE} $@ ${MAKE_FLAGS} ) || exit 1; \ + done + +distclean: + for n in ${SUBDIRS}; do \ + ( cd $$n && ${MAKE} $@ ${MAKE_FLAGS} ) || exit 1; \ + done + rm -f config.cache config.log config.status config.h Makefile + rm -f postinstall + diff --git a/README b/README new file mode 100644 index 0000000..3bf5e90 --- /dev/null +++ b/README @@ -0,0 +1,147 @@ +nph - PH Client and Library +=== + +nph is a modern client and API library for accessing PH servers. + + +Installation +------------ + +To build nph, you should be able to simply run these commands: + + ./configure + make + make install + + +Encap Package Support +--------------------- + +To build this software as an Encap package, you can pass the +--enable-encap option to configure. This will be automatically +enabled if the epkg or mkencap programs are detected on the system, +but can be overridden by the --disable-encap option. + +When building an Encap package, the configure script will automatically +adjust the installation prefix to use an appropriate Encap package +directory. It does this using a heuristic algorithm which examines the +values of the ${ENCAP_SOURCE} and ${ENCAP_TARGET} environment variables +and the argument to configure's --prefix option. + +If mkencap was detected on the system, it will be automatically run during +"make install". By default, epkg will also be run, but this can be +inhibited with the --disable-epkg-install configure option. + +For information on the Encap package management system, see the WSG +Encap Archive: + + http://www.encap.org/ + + +Readline Support +---------------- + +The configure script will attempt to find the readline library on +your system. The readline package is available from: + + ftp://ftp.gnu.org/gnu/readline/ + +If you do not have readline-4.2 or newer, you will need to specify the +--disable-readline option to configure. + + +Installing nph Setuid +--------------------- + +If you wish to use PH's email authentication mechanism, you must install +nph to be setuid-root using the --enable-setuid-nph option to configure. + +SECURITY WARNING: + Installing nph as a setuid-root binary may constitute a serious + security hole! While I do not know of any security holes in nph, + I make no guaruntees about your system security. I strongly + recommend against using --enable-setuid-nph unless it is + absolutely unavoidable. + + +Default "mailmatch" Fields +-------------------------- + +For PH servers that don't have a "mailmatches" entry in their siteinfo +list, libphclient will use a built-in default for the list of fields to +check when resolving email addresses. This default list can be set by +specifying the --with-mailmatches=LIST option to configure. (Replace +"LIST" with a ':'-delimited list of field names.) + +If this option is not specified, the default list is "alias:callsign". + + +More Information +---------------- + +After you install nph, you will need to tell it what server to connect to. +This can be set in the global ${sysconfdir}/ph_server file or by setting +the environment variable ${PH_SERVER}. Alternately, you can invoke nph +with "-s servername" to specify the server name on the commandline. + +For documentation on nph or on the libphclient API, see the enclosed +manpages. For more information on the nph package, see: + + http://www.feep.net/nph/ + +Both source code and Encap binary distributions of the latest version +of nph are available there. + + +Supported Platforms +------------------- + +I develop and test nph on the following platforms: + + AIX 4.3.3 + AIX 5.1 + HP-UX 11.00 + IRIX 6.5 + RedHat Linux 7.2 + Solaris 8 + Solaris 9 + +The nph code should build properly on the following platforms, but I +do not actively support them: + + AIX 3.2.5 + AIX 4.2.1 + FreeBSD + HP-UX 10.20 + Linux/libc5 + RedHat Linux 8.0 + Mac OS X + OpenBSD + Solaris 2.5 + Solaris 2.6 + Solaris 7 + +If you successfully build nph on another platform, please email me a +patch and/or configuration information. + + +Compatibility Code +------------------ + +nph depends on some library calls which are not available or not +usable on some platforms. To accomodate these systems, I've included +a version of these calls in the lib/compat subdirectory. + +I've slightly modified these functions for integration into this source +tree, but the functionality has not been modified from the original +source. Please note that while this code should work for you, I didn't +write it, so please don't send me bug reports on it. + + +Author +------ + +Feedback and bug reports are welcome. + +Mark D. Roth + diff --git a/TODO b/TODO new file mode 100644 index 0000000..56cc303 --- /dev/null +++ b/TODO @@ -0,0 +1,36 @@ +libphclient +----------- +* establish better conventions for returning error codes: + * goal is to not have to create a new PH_ERR_* macro for each new situation + * one possibility: if response code is other than LR_OK, return negative + value of the response code + (i.e., anything less than 0 is an error) + * can provide a ph_strerror() function to front-end any negative + return value + (i.e., use strerror() if -1, otherwise use internal sys_errlist[] table) +* code cleanup: + * add ph_dequote_value() to public API ??? + * check return values from strl*() functions +* API cleanup: + * hide structures behind additional functions where possible + (e.g., ph_next_entry(), ph_next_field(), etc) +* add phclient-config script for apps using -lphclient? + (maybe include a flag to tell if it's thread-safe) +* add intelligent data caching mechanism +* provide perl module interface to libphclient + +nph +--- +* fix error message when ph_server file is empty: + nph: fgets(): Error 0 +* add ability to set default query selectors +* curses interface? X interface? +* use editor to modify entire entry ??? +* add auto-login capability ??? +* enhance history (~/.ph_history, "!foo", etc) ??? +* add close and open commands ??? +* allow "change [selectors] add field=val" (to add "val" to whatever's + already listed in field) ??? +* allow command to be executed conditionally based on whether we were + invoked in interactive mode + diff --git a/autoconf/ac_path_generic.m4 b/autoconf/ac_path_generic.m4 new file mode 100644 index 0000000..3b9b77d --- /dev/null +++ b/autoconf/ac_path_generic.m4 @@ -0,0 +1,136 @@ +dnl @synopsis AC_PATH_GENERIC(LIBRARY [, MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl +dnl Runs a LIBRARY-config script and defines LIBRARY_CFLAGS and LIBRARY_LIBS +dnl +dnl The script must support `--cflags' and `--libs' args. +dnl If MINIMUM-VERSION is specified, the script must also support the +dnl `--version' arg. +dnl If the `--with-library-[exec-]prefix' arguments to ./configure are given, +dnl it must also support `--prefix' and `--exec-prefix'. +dnl (In other words, it must be like gtk-config.) +dnl +dnl For example: +dnl +dnl AC_PATH_GENERIC(Foo, 1.0.0) +dnl +dnl would run `foo-config --version' and check that it is at least 1.0.0 +dnl +dnl If so, the following would then be defined: +dnl +dnl FOO_CFLAGS to `foo-config --cflags` +dnl FOO_LIBS to `foo-config --libs` +dnl +dnl At present there is no support for additional "MODULES" (see AM_PATH_GTK) +dnl (shamelessly stolen from gtk.m4 and then hacked around a fair amount) +dnl +dnl @author Angus Lees +dnl @version $Id: ac_path_generic.m4,v 1.1 2002/08/01 01:45:09 roth Exp $ + +AC_DEFUN([AC_PATH_GENERIC], +[dnl +dnl we're going to need uppercase, lowercase and user-friendly versions of the +dnl string `LIBRARY' +pushdef([UP], translit([$1], [a-z], [A-Z]))dnl +pushdef([DOWN], translit([$1], [A-Z], [a-z]))dnl + +dnl +dnl Get the cflags and libraries from the LIBRARY-config script +dnl +AC_ARG_WITH(DOWN-prefix,[ --with-]DOWN[-prefix=PFX Prefix where $1 is installed (optional)], + DOWN[]_config_prefix="$withval", DOWN[]_config_prefix="") +AC_ARG_WITH(DOWN-exec-prefix,[ --with-]DOWN[-exec-prefix=PFX Exec prefix where $1 is installed (optional)], + DOWN[]_config_exec_prefix="$withval", DOWN[]_config_exec_prefix="") + + if test x$DOWN[]_config_exec_prefix != x ; then + DOWN[]_config_args="$DOWN[]_config_args --exec-prefix=$DOWN[]_config_exec_prefix" + if test x${UP[]_CONFIG+set} != xset ; then + UP[]_CONFIG=$DOWN[]_config_exec_prefix/bin/DOWN-config + fi + fi + if test x$DOWN[]_config_prefix != x ; then + DOWN[]_config_args="$DOWN[]_config_args --prefix=$DOWN[]_config_prefix" + if test x${UP[]_CONFIG+set} != xset ; then + UP[]_CONFIG=$DOWN[]_config_prefix/bin/DOWN-config + fi + fi + + AC_PATH_PROG(UP[]_CONFIG, DOWN-config, no) + ifelse([$2], , + AC_MSG_CHECKING(for $1), + AC_MSG_CHECKING(for $1 - version >= $2) + ) + no_[]DOWN="" + if test "$UP[]_CONFIG" = "no" ; then + no_[]DOWN=yes + else + UP[]_CFLAGS="`$UP[]_CONFIG $DOWN[]_config_args --cflags`" + UP[]_LIBS="`$UP[]_CONFIG $DOWN[]_config_args --libs`" + ifelse([$2], , ,[ + DOWN[]_config_major_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + DOWN[]_config_minor_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + DOWN[]_config_micro_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + DOWN[]_wanted_major_version="regexp($2, [\<\([0-9]*\)], [\1])" + DOWN[]_wanted_minor_version="regexp($2, [\<\([0-9]*\)\.\([0-9]*\)], [\2])" + DOWN[]_wanted_micro_version="regexp($2, [\<\([0-9]*\).\([0-9]*\).\([0-9]*\)], [\3])" + + # Compare wanted version to what config script returned. + # If I knew what library was being run, i'd probably also compile + # a test program at this point (which also extracted and tested + # the version in some library-specific way) + if test "$DOWN[]_config_major_version" -lt \ + "$DOWN[]_wanted_major_version" \ + -o \( "$DOWN[]_config_major_version" -eq \ + "$DOWN[]_wanted_major_version" \ + -a "$DOWN[]_config_minor_version" -lt \ + "$DOWN[]_wanted_minor_version" \) \ + -o \( "$DOWN[]_config_major_version" -eq \ + "$DOWN[]_wanted_major_version" \ + -a "$DOWN[]_config_minor_version" -eq \ + "$DOWN[]_wanted_minor_version" \ + -a "$DOWN[]_config_micro_version" -lt \ + "$DOWN[]_wanted_micro_version" \) ; then + # older version found + no_[]DOWN=yes + echo -n "*** An old version of $1 " + echo -n "($DOWN[]_config_major_version" + echo -n ".$DOWN[]_config_minor_version" + echo ".$DOWN[]_config_micro_version) was found." + echo -n "*** You need a version of $1 newer than " + echo -n "$DOWN[]_wanted_major_version" + echo -n ".$DOWN[]_wanted_minor_version" + echo ".$DOWN[]_wanted_micro_version." + echo "***" + echo "*** If you have already installed a sufficiently new version, this error" + echo "*** probably means that the wrong copy of the DOWN-config shell script is" + echo "*** being found. The easiest way to fix this is to remove the old version" + echo "*** of $1, but you can also set the UP[]_CONFIG environment to point to the" + echo "*** correct copy of DOWN-config. (In this case, you will have to" + echo "*** modify your LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf" + echo "*** so that the correct libraries are found at run-time)" + fi + ]) + fi + if test "x$no_[]DOWN" = x ; then + AC_MSG_RESULT(yes) + ifelse([$3], , :, [$3]) + else + AC_MSG_RESULT(no) + if test "$UP[]_CONFIG" = "no" ; then + echo "*** The DOWN-config script installed by $1 could not be found" + echo "*** If $1 was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the UP[]_CONFIG environment variable to the" + echo "*** full path to DOWN-config." + fi + UP[]_CFLAGS="" + UP[]_LIBS="" + ifelse([$4], , :, [$4]) + fi + AC_SUBST(UP[]_CFLAGS) + AC_SUBST(UP[]_LIBS) + + popdef([UP]) + popdef([DOWN]) +]) diff --git a/autoconf/aclocal.m4 b/autoconf/aclocal.m4 new file mode 100644 index 0000000..ee34c8e --- /dev/null +++ b/autoconf/aclocal.m4 @@ -0,0 +1,199 @@ +m4_include([encap.m4]) +m4_include([ac_path_generic.m4]) + + +# PSG_LIB_READLINE +# ---------------- +# Check for GNU readline library. +AC_DEFUN([PSG_LIB_READLINE], [ + AC_CHECK_HEADERS([readline/readline.h]) + AC_CHECK_HEADERS([readline/history.h]) + if test "$ac_cv_header_readline_readline_h" = "yes"; then + AC_SEARCH_LIBS([tputs], [termcap curses]) + AC_CHECK_LIB([readline], [rl_callback_handler_install]) + fi +]) + + +# PSG_LIB_TAR +# ----------- +# Check for usable version of libtar library. +AC_DEFUN([PSG_LIB_TAR], [ + psg_old_libs="$LIBS" + LIBS="$LIBS -ltar" + AC_CACHE_CHECK([for usable version of libtar], + [psg_cv_lib_tar_usable], + [AC_TRY_RUN([ +#include +#include +#include + +int main(int argc, char *argv[]) { + return (strcmp(libtar_version, "1.2") >= 0 ? 0 : 1); +} +], + [psg_cv_lib_tar_usable=yes], + [psg_cv_lib_tar_usable=no], + [psg_cv_lib_tar_usable=no] + )] + ) + if test "$psg_cv_lib_tar_usable" = "yes"; then + AC_DEFINE([HAVE_LIBTAR], 1, + [Define if your system has a current version of libtar]) + else + LIBS="$psg_old_libs" + fi +]) + + +# PSG_LIB_FGET +# ------------ +# Check for usable version of libfget library. +AC_DEFUN([PSG_LIB_FGET], [ + psg_old_libs="$LIBS" + AC_CHECK_LIB([socket], [socket]) + AC_CHECK_LIB([nsl], [gethostbyname]) + LIBS="$LIBS -lfget" + AC_CACHE_CHECK([for usable version of libfget], + [psg_cv_lib_fget_usable], + [AC_TRY_COMPILE([ + #include + ], [ + FTP *ftp; + char buf[10240]; + struct ftp_url fu; + + ftp_url_parse("ftp://host.com/dir/file.txt", &fu); + + ftp_connect(&ftp, fu.fu_hostname, buf, sizeof(buf), 0, 0, + -1, -1, NULL, NULL); + ], + [psg_cv_lib_fget_usable=yes], + [psg_cv_lib_fget_usable=no] + )] + ) + if test "$psg_cv_lib_fget_usable" = "yes"; then + AC_DEFINE([HAVE_LIBFGET], 1, + [Define if your system has a current version of libfget]) + else + LIBS="$psg_old_libs"; + fi +]) + + +# PSG_LIB_WRAP +# ------------ +# Check for TCP Wrapper library. +AC_DEFUN([PSG_LIB_WRAP], [ + AC_CHECK_HEADERS([tcpd.h]) + if test "$ac_cv_header_tcpd_h" = "yes"; then + psg_old_libs="$LIBS" + LIBS="$LIBS -lwrap" + AC_CACHE_CHECK([for libwrap library], + [psg_cv_lib_wrap_hosts_ctl], + AC_TRY_LINK([ + #include + #include + int allow_severity; + int deny_severity; + ], [ + hosts_ctl("test", STRING_UNKNOWN, "10.0.0.1", STRING_UNKNOWN); + ], + [psg_cv_lib_wrap_hosts_ctl=yes], + [psg_cv_lib_wrap_hosts_ctl=no] + ) + ) + if test "$psg_cv_lib_wrap_hosts_ctl" = "yes"; then + AC_DEFINE([HAVE_LIBWRAP], 1, [Define if you have libwrap]) + else + LIBS="$psg_old_libs" + fi + fi +]) + + +# PSG_REPLACE_TYPE(type_t, default, [includes]) +# --------------------------------------------- +# Check for arbitrary type in arbitrary header file(s). +AC_DEFUN([PSG_REPLACE_TYPE], + [AC_CHECK_TYPES([$1], + , + [AC_DEFINE($1, $2, + [Define to `$2' if not defined in system header files.] + )], + $3 + )] +) + + +# PSG_SHLIB(includes, code) +# ------------------------- +# Check how to build shared libraries containing the specified code +# (very rudimentary). +AC_DEFUN([PSG_SHLIB], [ + AC_MSG_CHECKING([how to build shared libraries]) + cflag_options="-fpic"; + ldflag_options="-G -shared"; + if test "$CC" != "gcc"; then + case "`uname`" in + HP-UX) + cflag_options="+Z $cflag_options"; + ldflag_options="-Wl,-b $ldflag_options"; + ;; + SunOS) + cflag_options="-Kpic $cflag_options"; + ;; + esac + fi + for SHLIB_CFLAGS in $cflag_options ""; do + for SHLIB_LDFLAGS in $ldflag_options ""; do + psg_old_cflags="$CFLAGS"; + CFLAGS="$CFLAGS $SHLIB_CFLAGS"; + psg_old_ldflags="$LDFLAGS"; + LDFLAGS="$LDFLAGS $SHLIB_LDFLAGS"; + AC_LINK_IFELSE([AC_LANG_SOURCE([[ +$1 + +int +dummy(void) +{ + $2 + return 0; +} +]])], + [psg_cv_flags_shlib="CFLAGS=$SHLIB_CFLAGS LDFLAGS=$SHLIB_LDFLAGS"], + [psg_cv_flags_shlib=no] + ) + CFLAGS="$psg_old_cflags"; + LDFLAGS="$psg_old_ldflags"; + if test "$psg_cv_flags_shlib" != "no"; then + break; + fi + done + if test "$psg_cv_flags_shlib" != "no"; then + break; + fi + done + if test "$psg_cv_flags_shlib" = "no"; then + SHLIB_CFLAGS=""; + SHLIB_LDFLAGS=""; + fi + AC_SUBST([SHLIB_CFLAGS]) + AC_SUBST([SHLIB_LDFLAGS]) + AC_MSG_RESULT([$psg_cv_flags_shlib]) +]) + + +# PSG_MODULE(subdir, [args, ...]) +# ------------------------------- +# Process the module.ac file in subdir. If the module.ac file defines a +# macro called subdir[]_INIT, call it with the arguments passed to +# PSG_MODULE(). +AC_DEFUN([PSG_MODULE], [ + m4_define([subdir], [$1])dnl + m4_include([$1/module.ac])dnl + m4_ifdef([$1][_INIT], [$1][_INIT($@)])dnl + m4_undefine([subdir])dnl +]) + + diff --git a/autoconf/encap.m4 b/autoconf/encap.m4 new file mode 100644 index 0000000..67f4998 --- /dev/null +++ b/autoconf/encap.m4 @@ -0,0 +1,133 @@ +# ENCAP_PKG([mkencap-options], [install target if enabled], +# [install target if disabled]) +# --------------------------------------------------------- +# Check for Encap tools. +AC_DEFUN([ENCAP_PKG], [ + MKENCAP_OPTS=$1; + + # allow user to disable Encap support + AC_ARG_ENABLE([encap], + [ --disable-encap Do not configure as an Encap package], + [], + [enable_encap=default]) + + if test "$enable_encap" != "no"; then + # look for epkg and mkencap + AC_PATH_PROG([EPKG], [epkg]) + AC_PATH_PROG([MKENCAP], [mkencap]) + + # enable by default if epkg or mkencap are found + if test "${EPKG:+set}" = "set" || test "${MKENCAP:+set}" = "set" && test "$enable_encap" = "default"; then + enable_encap=yes; + fi + fi + + if test "$enable_encap" = "yes"; then + # generate fallback values for ${ENCAP_SOURCE} and ${ENCAP_TARGET} + # from the environment or the default prefix + if test -z "${ENCAP_SOURCE}" && test -z "${ENCAP_TARGET}"; then + ENCAP_SOURCE="${ac_default_prefix}/encap"; + ENCAP_TARGET="${ac_default_prefix}"; + elif test -z "${ENCAP_TARGET}"; then + ENCAP_TARGET="`dirname ${ENCAP_SOURCE}`"; + elif test -z "${ENCAP_SOURCE}"; then + ENCAP_SOURCE="${ENCAP_TARGET}/encap"; + fi + + # if --prefix is specified: + # 1) if its next-to-last component is "encap", assume that it + # points to the package directory + # 2) otherwise, assume it points to the target directory + if test "${prefix}" != "NONE"; then + prefixdir="`dirname ${prefix}`"; + prefixbase="`basename ${prefix}`"; + if test "`basename ${prefixdir}`" = "encap"; then + ENCAP_SOURCE="${prefixdir}"; + ENCAP_TARGET="`dirname ${ENCAP_SOURCE}`"; + elif test "${prefixdir}" != "${ENCAP_SOURCE}"; then + ENCAP_SOURCE="${prefix}/encap"; + ENCAP_TARGET="${prefix}"; + fi + if ( test "`basename ${prefixdir}`" = "encap" || \ + test "${prefixdir}" = "${ENCAP_SOURCE}" ) && \ + test "${prefixbase}" != "${PACKAGE_NAME}-${PACKAGE_VERSION}"; then + ENCAP_PKGSPEC="${prefixbase}"; + fi + fi + + # display results + AC_MSG_CHECKING([for Encap source directory]) + AC_MSG_RESULT([${ENCAP_SOURCE}]) + AC_MSG_CHECKING([for Encap target directory]) + AC_MSG_RESULT([${ENCAP_TARGET}]) + AC_MSG_CHECKING([for Encap package directory]) + if test "${ENCAP_PKGSPEC:-unset}" = "unset"; then + ENCAP_PKGSPEC='${PACKAGE_NAME}-${PACKAGE_VERSION}'; + AC_MSG_RESULT([${ENCAP_SOURCE}/${PACKAGE_NAME}-${PACKAGE_VERSION}]) + else + AC_MSG_RESULT([${ENCAP_SOURCE}/${ENCAP_PKGSPEC}]) + fi + prefix='${ENCAP_SOURCE}/${ENCAP_PKGSPEC}'; + + # override default sysconfdir and localstatedir + if test "$sysconfdir" = '${prefix}/etc'; then + sysconfdir='${ENCAP_TARGET}/etc'; + fi + if test "$localstatedir" = '${prefix}/var'; then + localstatedir='/var/lib/${PACKAGE_NAME}'; + fi + + # check for --disable-epkg-install + AC_ARG_ENABLE([epkg-install], + [ --disable-epkg-install Do not run epkg during make install], + [], + [enable_epkg_install=yes]) + if test "$enable_epkg_install" = "no"; then + EPKG=":"; + fi + + # generate Makefile variables +dnl AC_SUBST([ENCAP_SOURCE]) +dnl AC_SUBST([ENCAP_TARGET]) +dnl AC_SUBST([ENCAP_PKGSPEC]) +dnl AC_SUBST([EPKG]) +dnl AC_SUBST([MKENCAP]) +dnl AC_SUBST([MKENCAP_OPTS]) +dnl +dnl m4_ifdef([EM_MAKEFILE_END], [ +dnl # generate rules for make install target +dnl EM_MAKEFILE_END([[ +dnl target modify : +dnl command \\\${MKENCAP} \\\`test -f \\\${srcdir}/COPYRIGHT && echo -I \\\${srcdir}/COPYRIGHT\\\` \\\${MKENCAP_OPTS} -s \\\${DESTDIR}\\\${ENCAP_SOURCE} -e \\\${ENCAP_PKGSPEC} +dnl command if test -z \\\\\"\\\${DESTDIR}\\\\\"; then \ +dnl \\\${EPKG} -s \\\${ENCAP_SOURCE} -t \\\${ENCAP_TARGET} \\\${ENCAP_PKGSPEC}; \ +dnl fi +dnl ]])]) + + ENCAP_DEFS="ENCAP_SOURCE = ${ENCAP_SOURCE}\\ +ENCAP_TARGET = ${ENCAP_TARGET}\\ +ENCAP_PKGSPEC = ${ENCAP_PKGSPEC}\\ +EPKG = ${EPKG:-:}\\ +MKENCAP = ${MKENCAP:-:}\\ +MKENCAP_OPTS = ${MKENCAP_OPTS}"; + AC_SUBST([ENCAP_DEFS]) + + dnl ### generate rules for make install target + ENCAP_INSTALL_RULES='if test -f ${top_srcdir}/COPYRIGHT; then \\\ + ${INSTALL_DATA} ${top_srcdir}/COPYRIGHT ${ENCAP_SOURCE}/${ENCAP_PKGSPEC}; \\\ + fi\ + ${MKENCAP} ${MKENCAP_OPTS} -s ${DESTDIR}${ENCAP_SOURCE} -e ${ENCAP_PKGSPEC};\ + if test -z \"${DESTDIR}\"; then \\\ + ${EPKG} -s ${ENCAP_SOURCE} -t ${ENCAP_TARGET} ${ENCAP_PKGSPEC}; \\\ + fi'; + AC_SUBST([ENCAP_INSTALL_RULES]) + + ENCAP_INSTALL_TARGET=$2 + else + ENCAP_INSTALL_TARGET=$3 + fi + + AC_SUBST([ENCAP_INSTALL_TARGET]) +]) + + diff --git a/autoconf/install-sh b/autoconf/install-sh new file mode 100755 index 0000000..e9de238 --- /dev/null +++ b/autoconf/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/buffer/ChangeLog b/buffer/ChangeLog new file mode 100644 index 0000000..678789e --- /dev/null +++ b/buffer/ChangeLog @@ -0,0 +1 @@ +2002-10-16 initial version diff --git a/buffer/TODO b/buffer/TODO new file mode 100644 index 0000000..f28a81d --- /dev/null +++ b/buffer/TODO @@ -0,0 +1,3 @@ +* add timeout functionality with poll()/select() +* add *_buffer_write() function? + (similar to ph_send_command() or ftp_send_command()) diff --git a/buffer/buffer.c.in b/buffer/buffer.c.in new file mode 100644 index 0000000..5ceb484 --- /dev/null +++ b/buffer/buffer.c.in @@ -0,0 +1,114 @@ +/* @configure_input@ */ + +/* +** Copyright 1998-2004 University of Illinois Board of Trustees +** Copyright 1998-2004 Mark D. Roth +** All rights reserved. +** +** @BUFFER_PREFIX@_buffer.c - network line buffer code +** +** Mark D. Roth +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include +#include + +#include <@BUFFER_PREFIX@_buffer.h> + +#include +#include + +#ifdef STDC_HEADERS +# include +#endif + + +struct @BUFFER_PREFIX@_buffer +{ + char *b_buf; + size_t b_bufsize; + char *b_readp; + char *b_writep; + @BUFFER_PREFIX@_read_func_t b_readfunc; + void *b_app_data; +}; + + +int +@BUFFER_PREFIX@_buffer_new(@BUFFER_PREFIX@_buffer_t *bufp, + size_t bufsize, + @BUFFER_PREFIX@_read_func_t readfunc, + void *app_data) +{ + *bufp = (@BUFFER_PREFIX@_buffer_t)calloc(1, sizeof(struct @BUFFER_PREFIX@_buffer)); + if (*bufp == NULL) + return -1; + + (*bufp)->b_buf = (char *)calloc(1, bufsize); + if ((*bufp)->b_buf == NULL) + return -1; + + (*bufp)->b_readp = (*bufp)->b_writep = (*bufp)->b_buf; + (*bufp)->b_bufsize = bufsize; + (*bufp)->b_readfunc = readfunc; + (*bufp)->b_app_data = app_data; + + return 0; +} + + +#define BUF_FREE_LEN(buf) \ + (((buf)->b_bufsize - 1) - ((buf)->b_writep - (buf)->b_buf)) + + +ssize_t +@BUFFER_PREFIX@_buffer_read_line(@BUFFER_PREFIX@_buffer_t buf, + char *callbuf, size_t callbuflen) +{ + char *linep; + ssize_t sz; + size_t retlen; + + /* keep reading until we have a line in the buffer */ + while (strchr(buf->b_readp, '\n') == NULL) + { + sz = (*(buf->b_readfunc))(buf->b_app_data, buf->b_writep, + BUF_FREE_LEN(buf)); + if (sz == 0) + { + errno = ECONNRESET; + return -1; + } + if (sz == (ssize_t)-1) + return -1; + buf->b_writep += sz; + *(buf->b_writep) = '\0'; + } + + /* chop off the first line and move read pointer */ + linep = strsep(&(buf->b_readp), "\n"); + + /* copy line to caller-suppied buffer */ + retlen = strlcpy(callbuf, linep, callbuflen); + + /* move remaining data to beginning of buffer and update pointers */ + sz = buf->b_writep - buf->b_readp; + memmove(buf->b_buf, buf->b_readp, sz + 1); + buf->b_writep = buf->b_buf + sz; + buf->b_readp = buf->b_buf; + + return retlen; +} + + +void +@BUFFER_PREFIX@_free(@BUFFER_PREFIX@_buffer_t buf) +{ + if (buf->b_buf != NULL) + free(buf->b_buf); + free(buf); +} + + diff --git a/buffer/buffer.h.in b/buffer/buffer.h.in new file mode 100644 index 0000000..3737a4e --- /dev/null +++ b/buffer/buffer.h.in @@ -0,0 +1,37 @@ +/* @configure_input@ */ + +/* +** Copyright 1998-2004 University of Illinois Board of Trustees +** Copyright 1998-2004 Mark D. Roth +** All rights reserved. +** +** @BUFFER_PREFIX@_buffer.h - header file for buffer module +** +** Mark D. Roth +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#ifndef @BUFFER_PREFIX@_BUFFER_H +#define @BUFFER_PREFIX@_BUFFER_H + +#include + + +typedef struct @BUFFER_PREFIX@_buffer *@BUFFER_PREFIX@_buffer_t; + +typedef ssize_t (*@BUFFER_PREFIX@_read_func_t)(void *, char *, size_t); + + +int @BUFFER_PREFIX@_buffer_new(@BUFFER_PREFIX@_buffer_t *, + size_t, + @BUFFER_PREFIX@_read_func_t, + void *); + +ssize_t @BUFFER_PREFIX@_buffer_read_line(@BUFFER_PREFIX@_buffer_t, + char *, size_t); + +void @BUFFER_PREFIX@_free(@BUFFER_PREFIX@_buffer_t); + +#endif /* ! @BUFFER_PREFIX@_BUFFER_H */ + diff --git a/buffer/module.ac b/buffer/module.ac new file mode 100644 index 0000000..9a8d9b2 --- /dev/null +++ b/buffer/module.ac @@ -0,0 +1,18 @@ +AC_DEFUN(subdir[_INIT], [ + AC_REQUIRE([COMPAT_FUNC_STRLCPY]) + AC_REQUIRE([COMPAT_FUNC_STRSEP]) + + if test -z "$2"; then + BUFFER_PREFIX="${PACKAGE_NAME}"; + else + BUFFER_PREFIX="$2"; + fi + AC_SUBST([BUFFER_PREFIX]) + + BUFFER_DIR="$1"; + AC_SUBST([BUFFER_DIR]) + + AC_CONFIG_FILES([$1/${BUFFER_PREFIX}_buffer.h:$1/buffer.h.in]) + AC_CONFIG_FILES([$1/${BUFFER_PREFIX}_buffer.c:$1/buffer.c.in]) +]) + diff --git a/compat/ChangeLog b/compat/ChangeLog new file mode 100644 index 0000000..04d6c92 --- /dev/null +++ b/compat/ChangeLog @@ -0,0 +1,34 @@ +2003-05-09 fixed COMPAT_FUNC_GETPWUID_R macro to test for + _SC_GETPW_R_SIZE_MAX + +2003-01-08 added COMPAT_FUNC_MAKEDEV macro + +2002-12-20 added COMPAT_VAR___PROGNAME macro + +2002-12-19 include necessary header files from gethostbyname_r.c + and getservbyname_r.c + + check for size_t in COMPAT_FUNC_GETHOSTBYNAME_R and + COMPAT_FUNC_GETSERVBYNAME_R macros + +2002-12-18 define _LINUX_SOURCE_COMPAT in compat.h if strsep() + is needed on AIX + + avoid prototype syntax problem with IBM C compiler in + fnmatch.c + +2002-11-24 added COMPAT_PROTO_MACRO macro + +2002-11-22 updated gethostbyname_r() and getservbyname_r() code and + macros to detect and use weird AIX implementation + + added warnings if thread-safe functions are not found + +2002-10-18 new macros and corresponding compat code: + * COMPAT_FUNC_GETHOSTBYNAME_R + * COMPAT_FUNC_GETSERVBYNAME_R + +2002-10-15 added COMPAT_FUNC_GETPWUID_R macro + +2002-07-17 added inet_aton.c + diff --git a/compat/README b/compat/README new file mode 100644 index 0000000..fd23ced --- /dev/null +++ b/compat/README @@ -0,0 +1,12 @@ +Compatibility Suite +------------------- + +This directory contains a compatibility suite that provides alternate +implementations of various library functions which are not available or +not usable on some platforms. + +The original copyright information for each function is included in +the source files. I've modified the files slightly for integration +into this suite, but the functionality has not been modified from +the original source. + diff --git a/compat/TODO b/compat/TODO new file mode 100644 index 0000000..1b44a33 --- /dev/null +++ b/compat/TODO @@ -0,0 +1,4 @@ +- fix COMPAT_FUNC_INET_ATON to check for existing function in -lresolv +- fix COMPAT_FUNC_MAKEDEV to avoid problems with IBM C compiler + (calling cpp macro with more args that necessary doesn't fail, but + calling it with too few macros does fail) diff --git a/compat/basename.c b/compat/basename.c new file mode 100644 index 0000000..2ac1e13 --- /dev/null +++ b/compat/basename.c @@ -0,0 +1,74 @@ +/* $OpenBSD: basename.c,v 1.4 1999/05/30 17:10:30 espie Exp $ */ + +/* + * Copyright (c) 1997 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author 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 ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$OpenBSD: basename.c,v 1.4 1999/05/30 17:10:30 espie Exp $"; +#endif /* not lint */ + +#include +#include +#include + +char * +openbsd_basename(path) + const char *path; +{ + static char bname[MAXPATHLEN]; + register const char *endp, *startp; + + /* Empty or NULL string gets treated as "." */ + if (path == NULL || *path == '\0') { + (void)strcpy(bname, "."); + return(bname); + } + + /* Strip trailing slashes */ + endp = path + strlen(path) - 1; + while (endp > path && *endp == '/') + endp--; + + /* All slashes becomes "/" */ + if (endp == path && *endp == '/') { + (void)strcpy(bname, "/"); + return(bname); + } + + /* Find the start of the base */ + startp = endp; + while (startp > path && *(startp - 1) != '/') + startp--; + + if (endp - startp + 1 > sizeof(bname)) { + errno = ENAMETOOLONG; + return(NULL); + } + (void)strncpy(bname, startp, endp - startp + 1); + bname[endp - startp + 1] = '\0'; + return(bname); +} diff --git a/compat/compat.h b/compat/compat.h new file mode 100644 index 0000000..366667c --- /dev/null +++ b/compat/compat.h @@ -0,0 +1,260 @@ +/* prototypes for borrowed "compatibility" code */ + +#include + +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#else +# include +#endif + +#ifdef HAVE_LIBGEN_H +# include +#endif + + +#if defined(NEED_BASENAME) && !defined(HAVE_BASENAME) + +# ifdef basename +# undef basename /* fix glibc brokenness */ +# endif + +char *openbsd_basename(const char *); +# define basename openbsd_basename + +#endif /* NEED_BASENAME && ! HAVE_BASENAME */ + + +#if defined(NEED_DIRNAME) && !defined(HAVE_DIRNAME) + +char *openbsd_dirname(const char *); +# define dirname openbsd_dirname + +#endif /* NEED_DIRNAME && ! HAVE_DIRNAME */ + + +#ifdef NEED_FNMATCH +# ifndef HAVE_FNMATCH + +# define FNM_NOMATCH 1 /* Match failed. */ + +# define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ +# define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ +# define FNM_PERIOD 0x04 /* Period must be matched by period. */ + +# define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ +# define FNM_CASEFOLD 0x10 /* Case insensitive search. */ +# define FNM_IGNORECASE FNM_CASEFOLD +# define FNM_FILE_NAME FNM_PATHNAME + +int openbsd_fnmatch(const char *, const char *, int); +# define fnmatch openbsd_fnmatch + +# else /* HAVE_FNMATCH */ + +# ifdef HAVE_FNMATCH_H +# include +# endif + +# endif /* ! HAVE_FNMATCH */ +#endif /* NEED_FNMATCH */ + + +#ifdef NEED_GETHOSTBYNAME_R + +# include + +# if GETHOSTBYNAME_R_NUM_ARGS != 6 + +int compat_gethostbyname_r(const char *, struct hostent *, + char *, size_t, struct hostent **, int *); + +# define gethostbyname_r compat_gethostbyname_r + +# endif /* GETHOSTBYNAME_R_NUM_ARGS != 6 */ + +#endif /* NEED_GETHOSTBYNAME_R */ + + +#if defined(NEED_GETHOSTNAME) && !defined(HAVE_GETHOSTNAME) + +int gethostname(char *, size_t); + +#endif /* NEED_GETHOSTNAME && ! HAVE_GETHOSTNAME */ + + +#ifdef NEED_GETSERVBYNAME_R + +# include + +# if GETSERVBYNAME_R_NUM_ARGS != 6 + +int compat_getservbyname_r(const char *, const char *, struct servent *, + char *, size_t, struct servent **); + +# define getservbyname_r compat_getservbyname_r + +# endif /* GETSERVBYNAME_R_NUM_ARGS != 6 */ + +#endif /* NEED_GETSERVBYNAME_R */ + + + +#ifdef NEED_GLOB +# ifndef HAVE_GLOB + +typedef struct { + int gl_pathc; /* Count of total paths so far. */ + int gl_matchc; /* Count of paths matching pattern. */ + int gl_offs; /* Reserved at beginning of gl_pathv. */ + int gl_flags; /* Copy of flags parameter to glob. */ + char **gl_pathv; /* List of paths matching pattern. */ + /* Copy of errfunc parameter to glob. */ + int (*gl_errfunc)(const char *, int); + + /* + * Alternate filesystem access methods for glob; replacement + * versions of closedir(3), readdir(3), opendir(3), stat(2) + * and lstat(2). + */ + void (*gl_closedir)(void *); + struct dirent *(*gl_readdir)(void *); + void *(*gl_opendir)(const char *); + int (*gl_lstat)(const char *, struct stat *); + int (*gl_stat)(const char *, struct stat *); +} glob_t; + +/* Flags */ +# define GLOB_APPEND 0x0001 /* Append to output from previous call. */ +# define GLOB_DOOFFS 0x0002 /* Use gl_offs. */ +# define GLOB_ERR 0x0004 /* Return on error. */ +# define GLOB_MARK 0x0008 /* Append / to matching directories. */ +# define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */ +# define GLOB_NOSORT 0x0020 /* Don't sort. */ + +# define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ +# define GLOB_BRACE 0x0080 /* Expand braces ala csh. */ +# define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */ +# define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */ +# define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ +# define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ +# define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */ + +/* Error values returned by glob(3) */ +# define GLOB_NOSPACE (-1) /* Malloc call failed. */ +# define GLOB_ABORTED (-2) /* Unignored error. */ +# define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */ +# define GLOB_NOSYS (-4) /* Function not supported. */ +# define GLOB_ABEND GLOB_ABORTED + +int openbsd_glob(const char *, int, int (*)(const char *, int), glob_t *); +void openbsd_globfree(glob_t *); +# define glob openbsd_glob +# define globfree openbsd_globfree + +# else /* HAVE_GLOB */ + +# ifdef HAVE_GLOB_H +# include +# endif + +# endif /* ! HAVE_GLOB */ +#endif /* NEED_GLOB */ + + +#if defined(NEED_INET_ATON) && !defined(HAVE_INET_ATON) + +int inet_aton(const char *, struct in_addr *); + +#endif /* NEED_INET_ATON && ! HAVE_INET_ATON */ + + +#ifdef NEED_MAKEDEV + +# ifdef MAJOR_IN_MKDEV +# include +# else +# ifdef MAJOR_IN_SYSMACROS +# include +# endif +# endif + +/* +** On most systems makedev() has two args. +** Some weird systems, like QNX6, have makedev() functions that expect +** an extra first argument for "node", which can be 0 for a local +** machine. +*/ + +# ifdef MAKEDEV_THREE_ARGS +# define compat_makedev(maj, min) makedev(0, maj, min) +# else +# define compat_makedev makedev +# endif + +#endif /* NEED_MAKEDEV */ + + +#if defined(NEED_SNPRINTF) && !defined(HAVE_SNPRINTF) + +int mutt_snprintf(char *, size_t, const char *, ...); +int mutt_vsnprintf(char *, size_t, const char *, va_list); +#define snprintf mutt_snprintf +#define vsnprintf mutt_vsnprintf + +#endif /* NEED_SNPRINTF && ! HAVE_SNPRINTF */ + + +#if defined(NEED_STRLCAT) && !defined(HAVE_STRLCAT) + +size_t strlcat(char *, const char *, size_t); + +#endif /* NEED_STRLCAT && ! HAVE_STRLCAT */ + + +#if defined(NEED_STRLCPY) && !defined(HAVE_STRLCPY) + +size_t strlcpy(char *, const char *, size_t); + +#endif /* NEED_STRLCPY && ! HAVE_STRLCPY */ + + +#if defined(NEED_STRDUP) && !defined(HAVE_STRDUP) + +char *openbsd_strdup(const char *); +# define strdup openbsd_strdup + +#endif /* NEED_STRDUP && ! HAVE_STRDUP */ + + +#if defined(NEED_STRMODE) && !defined(HAVE_STRMODE) + +void strmode(register mode_t, register char *); + +#endif /* NEED_STRMODE && ! HAVE_STRMODE */ + + +#if defined(NEED_STRRSTR) && !defined(HAVE_STRRSTR) + +char *strrstr(char *, char *); + +#endif /* NEED_STRRSTR && ! HAVE_STRRSTR */ + + +#ifdef NEED_STRSEP + +# ifdef HAVE_STRSEP +# define _LINUX_SOURCE_COMPAT /* needed on AIX 4.3.3 */ +# else + +char *strsep(register char **, register const char *); + +# endif + +#endif /* NEED_STRSEP */ + + diff --git a/compat/dirname.c b/compat/dirname.c new file mode 100644 index 0000000..986db4a --- /dev/null +++ b/compat/dirname.c @@ -0,0 +1,77 @@ +/* $OpenBSD: dirname.c,v 1.4 1999/05/30 17:10:30 espie Exp $ */ + +/* + * Copyright (c) 1997 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author 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 ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$OpenBSD: dirname.c,v 1.4 1999/05/30 17:10:30 espie Exp $"; +#endif /* not lint */ + +#include +#include +#include + +char * +openbsd_dirname(path) + const char *path; +{ + static char bname[MAXPATHLEN]; + register const char *endp; + + /* Empty or NULL string gets treated as "." */ + if (path == NULL || *path == '\0') { + (void)strcpy(bname, "."); + return(bname); + } + + /* Strip trailing slashes */ + endp = path + strlen(path) - 1; + while (endp > path && *endp == '/') + endp--; + + /* Find the start of the dir */ + while (endp > path && *endp != '/') + endp--; + + /* Either the dir is "/" or there are no slashes */ + if (endp == path) { + (void)strcpy(bname, *endp == '/' ? "/" : "."); + return(bname); + } else { + do { + endp--; + } while (endp > path && *endp == '/'); + } + + if (endp - path + 1 > sizeof(bname)) { + errno = ENAMETOOLONG; + return(NULL); + } + (void)strncpy(bname, path, endp - path + 1); + bname[endp - path + 1] = '\0'; + return(bname); +} diff --git a/compat/fnmatch.c b/compat/fnmatch.c new file mode 100644 index 0000000..fe75f0e --- /dev/null +++ b/compat/fnmatch.c @@ -0,0 +1,237 @@ +/* $OpenBSD: fnmatch.c,v 1.6 1998/03/19 00:29:59 millert Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94"; +#else +static char rcsid[] = "$OpenBSD: fnmatch.c,v 1.6 1998/03/19 00:29:59 millert Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +/* + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. + * Compares a filename or pathname to a pattern. + */ + +#include + +#include + +#ifdef STDC_HEADERS +# include +#endif + +#ifdef HAVE_CTYPE_H +# include +#endif + +#include + + +#define EOS '\0' + +#define RANGE_MATCH 1 +#define RANGE_NOMATCH 0 +#define RANGE_ERROR (-1) + +#ifdef NO_IBM_COMPILER_HORKAGE +static int rangematch (const char *, char, int, char **); +#else +static int rangematch (); +#endif + +int +fnmatch(pattern, string, flags) + const char *pattern, *string; + int flags; +{ + const char *stringstart; + char *newp; + char c, test; + + for (stringstart = string;;) + switch (c = *pattern++) { + case EOS: + if ((flags & FNM_LEADING_DIR) && *string == '/') + return (0); + return (*string == EOS ? 0 : FNM_NOMATCH); + case '?': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && (flags & FNM_PATHNAME)) + return (FNM_NOMATCH); + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + ++string; + break; + case '*': + c = *pattern; + /* Collapse multiple stars. */ + while (c == '*') + c = *++pattern; + + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + + /* Optimize for pattern with * at end or before /. */ + if (c == EOS) { + if (flags & FNM_PATHNAME) + return ((flags & FNM_LEADING_DIR) || + strchr(string, '/') == NULL ? + 0 : FNM_NOMATCH); + else + return (0); + } else if (c == '/' && (flags & FNM_PATHNAME)) { + if ((string = strchr(string, '/')) == NULL) + return (FNM_NOMATCH); + break; + } + + /* General case, use recursion. */ + while ((test = *string) != EOS) { + if (!fnmatch(pattern, string, flags & ~FNM_PERIOD)) + return (0); + if (test == '/' && (flags & FNM_PATHNAME)) + break; + ++string; + } + return (FNM_NOMATCH); + case '[': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && (flags & FNM_PATHNAME)) + return (FNM_NOMATCH); + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + + switch (rangematch(pattern, *string, flags, &newp)) { + case RANGE_ERROR: + /* not a good range, treat as normal text */ + goto normal; + case RANGE_MATCH: + pattern = newp; + break; + case RANGE_NOMATCH: + return (FNM_NOMATCH); + } + ++string; + break; + case '\\': + if (!(flags & FNM_NOESCAPE)) { + if ((c = *pattern++) == EOS) { + c = '\\'; + --pattern; + } + } + /* FALLTHROUGH */ + default: + normal: + if (c != *string && !((flags & FNM_CASEFOLD) && + (tolower((unsigned char)c) == + tolower((unsigned char)*string)))) + return (FNM_NOMATCH); + ++string; + break; + } + /* NOTREACHED */ +} + +static int +rangematch(pattern, test, flags, newp) + const char *pattern; + char test; + int flags; + char **newp; +{ + int negate, ok; + char c, c2; + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin (conklin@ngai.kaleida.com) + */ + if ((negate = (*pattern == '!' || *pattern == '^'))) + ++pattern; + + if (flags & FNM_CASEFOLD) + test = tolower((unsigned char)test); + + /* + * A right bracket shall lose its special meaning and represent + * itself in a bracket expression if it occurs first in the list. + * -- POSIX.2 2.8.3.2 + */ + ok = 0; + c = *pattern++; + do { + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = *pattern++; + if (c == EOS) + return (RANGE_ERROR); + if (c == '/' && (flags & FNM_PATHNAME)) + return (RANGE_NOMATCH); + if ((flags & FNM_CASEFOLD)) + c = tolower((unsigned char)c); + if (*pattern == '-' + && (c2 = *(pattern+1)) != EOS && c2 != ']') { + pattern += 2; + if (c2 == '\\' && !(flags & FNM_NOESCAPE)) + c2 = *pattern++; + if (c2 == EOS) + return (RANGE_ERROR); + if (flags & FNM_CASEFOLD) + c2 = tolower((unsigned char)c2); + if (c <= test && test <= c2) + ok = 1; + } else if (c == test) + ok = 1; + } while ((c = *pattern++) != ']'); + + *newp = (char *)pattern; + return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH); +} diff --git a/compat/gethostbyname_r.c b/compat/gethostbyname_r.c new file mode 100644 index 0000000..5264b84 --- /dev/null +++ b/compat/gethostbyname_r.c @@ -0,0 +1,41 @@ +/* +** Copyright 2002 University of Illinois Board of Trustees +** Copyright 2002 Mark D. Roth +** All rights reserved. +** +** gethostbyname_r.c - gethostbyname_r() function for compatibility library +** +** Mark D. Roth +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include + +#include +#include +#include + + +int +compat_gethostbyname_r(const char *name, struct hostent *hp, + char *buf, size_t buflen, + struct hostent **hpp, int *herr) +{ +#if GETHOSTBYNAME_R_NUM_ARGS == 5 + *hpp = gethostbyname_r(name, hp, buf, buflen, herr); + + if (*hpp == NULL) + return -1; + return 0; +#elif GETHOSTBYNAME_R_NUM_ARGS == 3 + struct hostent_data hdata; + + if (gethostbyname_r(name, hp, &hdata) == -1) + return -1; + *hpp = hp; + return 0; +#endif /* GETHOSTBYNAME_R_NUM_ARGS == 5 */ +} + + diff --git a/compat/gethostname.c b/compat/gethostname.c new file mode 100644 index 0000000..1abaae1 --- /dev/null +++ b/compat/gethostname.c @@ -0,0 +1,36 @@ +/* gethostname.c: minimal substitute for missing gethostname() function + * created 2000-Mar-02 jmk + * requires SVR4 uname() and -lc + * + * by Jim Knoble + * Copyright ? 2000 Jim Knoble + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This software is provided "as is", without warranty of any kind, + * express or implied, including but not limited to the warranties of + * merchantability, fitness for a particular purpose and + * noninfringement. In no event shall the author(s) be liable for any + * claim, damages or other liability, whether in an action of contract, + * tort or otherwise, arising from, out of or in connection with the + * software or the use or other dealings in the software. + */ + +#include +#include + +int gethostname(char *name, size_t len) +{ + struct utsname u; + int status = uname(&u); + if (-1 != status) { + strncpy(name, u.nodename, len); + name[len - 1] = '\0'; + } + return(status); +} + diff --git a/compat/getservbyname_r.c b/compat/getservbyname_r.c new file mode 100644 index 0000000..e386bc9 --- /dev/null +++ b/compat/getservbyname_r.c @@ -0,0 +1,41 @@ +/* +** Copyright 2002 University of Illinois Board of Trustees +** Copyright 2002 Mark D. Roth +** All rights reserved. +** +** getservbyname_r.c - getservbyname_r() function for compatibility library +** +** Mark D. Roth +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include + +#include +#include +#include + + +int +compat_getservbyname_r(const char *name, const char *proto, + struct servent *sp, char *buf, size_t buflen, + struct servent **spp) +{ +#if GETSERVBYNAME_R_NUM_ARGS == 5 + *spp = getservbyname_r(name, proto, sp, buf, buflen); + + if (*spp == NULL) + return -1; + return 0; +#elif GETSERVBYNAME_R_NUM_ARGS == 4 + struct servent_data sdata; + + if (getservbyname_r(name, proto, sp, &sdata) == -1) + return -1; + *spp = sp; + return 0; +#endif /* GETSERVBYNAME_R_NUM_ARGS == 5 */ +} + + diff --git a/compat/glob.c b/compat/glob.c new file mode 100644 index 0000000..9ee235a --- /dev/null +++ b/compat/glob.c @@ -0,0 +1,873 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; +#else +static char rcsid[] = "$OpenBSD: glob.c,v 1.8 1998/08/14 21:39:30 deraadt Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +/* + * glob(3) -- a superset of the one defined in POSIX 1003.2. + * + * The [!...] convention to negate a range is supported (SysV, Posix, ksh). + * + * Optional extra services, controlled by flags not defined by POSIX: + * + * GLOB_QUOTE: + * Escaping convention: \ inhibits any special meaning the following + * character might have (except \ at end of string is retained). + * GLOB_MAGCHAR: + * Set in gl_flags if pattern contained a globbing character. + * GLOB_NOMAGIC: + * Same as GLOB_NOCHECK, but it will only append pattern if it did + * not contain any magic characters. [Used in csh style globbing] + * GLOB_ALTDIRFUNC: + * Use alternately specified directory access functions. + * GLOB_TILDE: + * expand ~user/foo to the /home/dir/of/user/foo + * GLOB_BRACE: + * expand {1,2}{a,b} to 1a 1b 2a 2b + * gl_matchc: + * Number of matches in the current invocation of glob. + */ + +#include + +#include +#include + +#include +#include +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include + + +#define DOLLAR '$' +#define DOT '.' +#define EOS '\0' +#define LBRACKET '[' +#define NOT '!' +#define QUESTION '?' +#define QUOTE '\\' +#define RANGE '-' +#define RBRACKET ']' +#define SEP '/' +#define STAR '*' +#define TILDE '~' +#define UNDERSCORE '_' +#define LBRACE '{' +#define RBRACE '}' +#define SLASH '/' +#define COMMA ',' + +#ifndef DEBUG + +#define M_QUOTE 0x8000 +#define M_PROTECT 0x4000 +#define M_MASK 0xffff +#define M_ASCII 0x00ff + +typedef u_short Char; + +#else + +#define M_QUOTE 0x80 +#define M_PROTECT 0x40 +#define M_MASK 0xff +#define M_ASCII 0x7f + +typedef char Char; + +#endif + + +#define CHAR(c) ((Char)((c)&M_ASCII)) +#define META(c) ((Char)((c)|M_QUOTE)) +#define M_ALL META('*') +#define M_END META(']') +#define M_NOT META('!') +#define M_ONE META('?') +#define M_RNG META('-') +#define M_SET META('[') +#define ismeta(c) (((c)&M_QUOTE) != 0) + + +static int compare (const void *, const void *); +static void g_Ctoc (const Char *, char *); +static int g_lstat (Char *, struct stat *, glob_t *); +static DIR *g_opendir (Char *, glob_t *); +static Char *g_strchr (Char *, int); +#ifdef notdef +static Char *g_strcat (Char *, const Char *); +#endif +static int g_stat (Char *, struct stat *, glob_t *); +static int glob0 (const Char *, glob_t *); +static int glob1 (Char *, glob_t *); +static int glob2 (Char *, Char *, Char *, glob_t *); +static int glob3 (Char *, Char *, Char *, Char *, glob_t *); +static int globextend (const Char *, glob_t *); +static const Char * globtilde (const Char *, Char *, size_t, glob_t *); +static int globexp1 (const Char *, glob_t *); +static int globexp2 (const Char *, const Char *, glob_t *, int *); +static int match (Char *, Char *, Char *); +#ifdef DEBUG +static void qprintf (const char *, Char *); +#endif + +int +openbsd_glob(pattern, flags, errfunc, pglob) + const char *pattern; + int flags, (*errfunc) __P((const char *, int)); + glob_t *pglob; +{ + const u_char *patnext; + int c; + Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; + + patnext = (u_char *) pattern; + if (!(flags & GLOB_APPEND)) { + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + if (!(flags & GLOB_DOOFFS)) + pglob->gl_offs = 0; + } + pglob->gl_flags = flags & ~GLOB_MAGCHAR; + pglob->gl_errfunc = errfunc; + pglob->gl_matchc = 0; + + bufnext = patbuf; + bufend = bufnext + MAXPATHLEN; + if (flags & GLOB_NOESCAPE) + while (bufnext < bufend && (c = *patnext++) != EOS) + *bufnext++ = c; + else { + /* Protect the quoted characters. */ + while (bufnext < bufend && (c = *patnext++) != EOS) + if (c == QUOTE) { + if ((c = *patnext++) == EOS) { + c = QUOTE; + --patnext; + } + *bufnext++ = c | M_PROTECT; + } + else + *bufnext++ = c; + } + *bufnext = EOS; + + if (flags & GLOB_BRACE) + return globexp1(patbuf, pglob); + else + return glob0(patbuf, pglob); +} + +/* + * Expand recursively a glob {} pattern. When there is no more expansion + * invoke the standard globbing routine to glob the rest of the magic + * characters + */ +static int globexp1(pattern, pglob) + const Char *pattern; + glob_t *pglob; +{ + const Char* ptr = pattern; + int rv; + + /* Protect a single {}, for find(1), like csh */ + if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) + return glob0(pattern, pglob); + + while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) + if (!globexp2(ptr, pattern, pglob, &rv)) + return rv; + + return glob0(pattern, pglob); +} + + +/* + * Recursive brace globbing helper. Tries to expand a single brace. + * If it succeeds then it invokes globexp1 with the new pattern. + * If it fails then it tries to glob the rest of the pattern and returns. + */ +static int globexp2(ptr, pattern, pglob, rv) + const Char *ptr, *pattern; + glob_t *pglob; + int *rv; +{ + int i; + Char *lm, *ls; + const Char *pe, *pm, *pl; + Char patbuf[MAXPATHLEN + 1]; + + /* copy part up to the brace */ + for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) + continue; + ls = lm; + + /* Find the balanced brace */ + for (i = 0, pe = ++ptr; *pe; pe++) + if (*pe == LBRACKET) { + /* Ignore everything between [] */ + for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) + continue; + if (*pe == EOS) { + /* + * We could not find a matching RBRACKET. + * Ignore and just look for RBRACE + */ + pe = pm; + } + } + else if (*pe == LBRACE) + i++; + else if (*pe == RBRACE) { + if (i == 0) + break; + i--; + } + + /* Non matching braces; just glob the pattern */ + if (i != 0 || *pe == EOS) { + *rv = glob0(patbuf, pglob); + return 0; + } + + for (i = 0, pl = pm = ptr; pm <= pe; pm++) + switch (*pm) { + case LBRACKET: + /* Ignore everything between [] */ + for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) + continue; + if (*pm == EOS) { + /* + * We could not find a matching RBRACKET. + * Ignore and just look for RBRACE + */ + pm = pl; + } + break; + + case LBRACE: + i++; + break; + + case RBRACE: + if (i) { + i--; + break; + } + /* FALLTHROUGH */ + case COMMA: + if (i && *pm == COMMA) + break; + else { + /* Append the current string */ + for (lm = ls; (pl < pm); *lm++ = *pl++) + continue; + /* + * Append the rest of the pattern after the + * closing brace + */ + for (pl = pe + 1; (*lm++ = *pl++) != EOS;) + continue; + + /* Expand the current pattern */ +#ifdef DEBUG + qprintf("globexp2:", patbuf); +#endif + *rv = globexp1(patbuf, pglob); + + /* move after the comma, to the next string */ + pl = pm + 1; + } + break; + + default: + break; + } + *rv = 0; + return 0; +} + + + +/* + * expand tilde from the passwd file. + */ +static const Char * +globtilde(pattern, patbuf, patbuf_len, pglob) + const Char *pattern; + Char *patbuf; + size_t patbuf_len; + glob_t *pglob; +{ + struct passwd *pwd; + char *h; + const Char *p; + Char *b, *eb; + + if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) + return pattern; + + /* Copy up to the end of the string or / */ + eb = &patbuf[patbuf_len - 1]; + for (p = pattern + 1, h = (char *) patbuf; + h < (char *)eb && *p && *p != SLASH; *h++ = *p++) + continue; + + *h = EOS; + + if (((char *) patbuf)[0] == EOS) { + /* + * handle a plain ~ or ~/ by expanding $HOME + * first and then trying the password file + */ +#ifdef HAVE_ISSETUGID + if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { +#endif + if ((pwd = getpwuid(getuid())) == NULL) + return pattern; + else + h = pwd->pw_dir; +#ifdef HAVE_ISSETUGID + } +#endif + } + else { + /* + * Expand a ~user + */ + if ((pwd = getpwnam((char*) patbuf)) == NULL) + return pattern; + else + h = pwd->pw_dir; + } + + /* Copy the home directory */ + for (b = patbuf; b < eb && *h; *b++ = *h++) + continue; + + /* Append the rest of the pattern */ + while (b < eb && (*b++ = *p++) != EOS) + continue; + *b = EOS; + + return patbuf; +} + + +/* + * The main glob() routine: compiles the pattern (optionally processing + * quotes), calls glob1() to do the real pattern matching, and finally + * sorts the list (unless unsorted operation is requested). Returns 0 + * if things went well, nonzero if errors occurred. It is not an error + * to find no matches. + */ +static int +glob0(pattern, pglob) + const Char *pattern; + glob_t *pglob; +{ + const Char *qpatnext; + int c, err, oldpathc; + Char *bufnext, patbuf[MAXPATHLEN+1]; + + qpatnext = globtilde(pattern, patbuf, sizeof(patbuf) / sizeof(Char), + pglob); + oldpathc = pglob->gl_pathc; + bufnext = patbuf; + + /* We don't need to check for buffer overflow any more. */ + while ((c = *qpatnext++) != EOS) { + switch (c) { + case LBRACKET: + c = *qpatnext; + if (c == NOT) + ++qpatnext; + if (*qpatnext == EOS || + g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { + *bufnext++ = LBRACKET; + if (c == NOT) + --qpatnext; + break; + } + *bufnext++ = M_SET; + if (c == NOT) + *bufnext++ = M_NOT; + c = *qpatnext++; + do { + *bufnext++ = CHAR(c); + if (*qpatnext == RANGE && + (c = qpatnext[1]) != RBRACKET) { + *bufnext++ = M_RNG; + *bufnext++ = CHAR(c); + qpatnext += 2; + } + } while ((c = *qpatnext++) != RBRACKET); + pglob->gl_flags |= GLOB_MAGCHAR; + *bufnext++ = M_END; + break; + case QUESTION: + pglob->gl_flags |= GLOB_MAGCHAR; + *bufnext++ = M_ONE; + break; + case STAR: + pglob->gl_flags |= GLOB_MAGCHAR; + /* collapse adjacent stars to one, + * to avoid exponential behavior + */ + if (bufnext == patbuf || bufnext[-1] != M_ALL) + *bufnext++ = M_ALL; + break; + default: + *bufnext++ = CHAR(c); + break; + } + } + *bufnext = EOS; +#ifdef DEBUG + qprintf("glob0:", patbuf); +#endif + + if ((err = glob1(patbuf, pglob)) != 0) + return(err); + + /* + * If there was no match we are going to append the pattern + * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified + * and the pattern did not contain any magic characters + * GLOB_NOMAGIC is there just for compatibility with csh. + */ + if (pglob->gl_pathc == oldpathc) { + if ((pglob->gl_flags & GLOB_NOCHECK) || + ((pglob->gl_flags & GLOB_NOMAGIC) && + !(pglob->gl_flags & GLOB_MAGCHAR))) + return(globextend(pattern, pglob)); + else + return(GLOB_NOMATCH); + } + if (!(pglob->gl_flags & GLOB_NOSORT)) + qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, + pglob->gl_pathc - oldpathc, sizeof(char *), compare); + return(0); +} + +static int +compare(p, q) + const void *p, *q; +{ + return(strcmp(*(char **)p, *(char **)q)); +} + +static int +glob1(pattern, pglob) + Char *pattern; + glob_t *pglob; +{ + Char pathbuf[MAXPATHLEN+1]; + + /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ + if (*pattern == EOS) + return(0); + return(glob2(pathbuf, pathbuf, pattern, pglob)); +} + +/* + * The functions glob2 and glob3 are mutually recursive; there is one level + * of recursion for each segment in the pattern that contains one or more + * meta characters. + */ +static int +glob2(pathbuf, pathend, pattern, pglob) + Char *pathbuf, *pathend, *pattern; + glob_t *pglob; +{ + struct stat sb; + Char *p, *q; + int anymeta; + + /* + * Loop over pattern segments until end of pattern or until + * segment with meta character found. + */ + for (anymeta = 0;;) { + if (*pattern == EOS) { /* End of pattern? */ + *pathend = EOS; + if (g_lstat(pathbuf, &sb, pglob)) + return(0); + + if (((pglob->gl_flags & GLOB_MARK) && + pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) + || (S_ISLNK(sb.st_mode) && + (g_stat(pathbuf, &sb, pglob) == 0) && + S_ISDIR(sb.st_mode)))) { + *pathend++ = SEP; + *pathend = EOS; + } + ++pglob->gl_matchc; + return(globextend(pathbuf, pglob)); + } + + /* Find end of next segment, copy tentatively to pathend. */ + q = pathend; + p = pattern; + while (*p != EOS && *p != SEP) { + if (ismeta(*p)) + anymeta = 1; + *q++ = *p++; + } + + if (!anymeta) { /* No expansion, do next segment. */ + pathend = q; + pattern = p; + while (*pattern == SEP) + *pathend++ = *pattern++; + } else /* Need expansion, recurse. */ + return(glob3(pathbuf, pathend, pattern, p, pglob)); + } + /* NOTREACHED */ +} + +static int +glob3(pathbuf, pathend, pattern, restpattern, pglob) + Char *pathbuf, *pathend, *pattern, *restpattern; + glob_t *pglob; +{ + register struct dirent *dp; + DIR *dirp; + int err; + char buf[MAXPATHLEN]; + + /* + * The readdirfunc declaration can't be prototyped, because it is + * assigned, below, to two functions which are prototyped in glob.h + * and dirent.h as taking pointers to differently typed opaque + * structures. + */ + struct dirent *(*readdirfunc)(); + + *pathend = EOS; + errno = 0; + + if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { + /* TODO: don't call for ENOENT or ENOTDIR? */ + if (pglob->gl_errfunc) { + g_Ctoc(pathbuf, buf); + if (pglob->gl_errfunc(buf, errno) || + pglob->gl_flags & GLOB_ERR) + return (GLOB_ABORTED); + } + return(0); + } + + err = 0; + + /* Search directory for matching names. */ + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + readdirfunc = pglob->gl_readdir; + else + readdirfunc = readdir; + while ((dp = (*readdirfunc)(dirp))) { + register u_char *sc; + register Char *dc; + + /* Initial DOT must be matched literally. */ + if (dp->d_name[0] == DOT && *pattern != DOT) + continue; + for (sc = (u_char *) dp->d_name, dc = pathend; + (*dc++ = *sc++) != EOS;) + continue; + if (!match(pathend, pattern, restpattern)) { + *pathend = EOS; + continue; + } + err = glob2(pathbuf, --dc, restpattern, pglob); + if (err) + break; + } + + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir)(dirp); + else + closedir(dirp); + return(err); +} + + +/* + * Extend the gl_pathv member of a glob_t structure to accomodate a new item, + * add the new item, and update gl_pathc. + * + * This assumes the BSD realloc, which only copies the block when its size + * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic + * behavior. + * + * Return 0 if new item added, error code if memory couldn't be allocated. + * + * Invariant of the glob_t structure: + * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and + * gl_pathv points to (gl_offs + gl_pathc + 1) items. + */ +static int +globextend(path, pglob) + const Char *path; + glob_t *pglob; +{ + register char **pathv; + register int i; + u_int newsize; + char *copy; + const Char *p; + + newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); + pathv = pglob->gl_pathv ? + realloc((char *)pglob->gl_pathv, newsize) : + malloc(newsize); + if (pathv == NULL) { + if (pglob->gl_pathv) + free(pglob->gl_pathv); + return(GLOB_NOSPACE); + } + + if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { + /* first time around -- clear initial gl_offs items */ + pathv += pglob->gl_offs; + for (i = pglob->gl_offs; --i >= 0; ) + *--pathv = NULL; + } + pglob->gl_pathv = pathv; + + for (p = path; *p++;) + continue; + if ((copy = malloc(p - path)) != NULL) { + g_Ctoc(path, copy); + pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; + } + pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + return(copy == NULL ? GLOB_NOSPACE : 0); +} + + +/* + * pattern matching function for filenames. Each occurrence of the * + * pattern causes a recursion level. + */ +static int +match(name, pat, patend) + register Char *name, *pat, *patend; +{ + int ok, negate_range; + Char c, k; + + while (pat < patend) { + c = *pat++; + switch (c & M_MASK) { + case M_ALL: + if (pat == patend) + return(1); + do + if (match(name, pat, patend)) + return(1); + while (*name++ != EOS); + return(0); + case M_ONE: + if (*name++ == EOS) + return(0); + break; + case M_SET: + ok = 0; + if ((k = *name++) == EOS) + return(0); + if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) + ++pat; + while (((c = *pat++) & M_MASK) != M_END) + if ((*pat & M_MASK) == M_RNG) { + if (c <= k && k <= pat[1]) + ok = 1; + pat += 2; + } else if (c == k) + ok = 1; + if (ok == negate_range) + return(0); + break; + default: + if (*name++ != c) + return(0); + break; + } + } + return(*name == EOS); +} + +/* Free allocated data belonging to a glob_t structure. */ +void +openbsd_globfree(pglob) + glob_t *pglob; +{ + register int i; + register char **pp; + + if (pglob->gl_pathv != NULL) { + pp = pglob->gl_pathv + pglob->gl_offs; + for (i = pglob->gl_pathc; i--; ++pp) + if (*pp) + free(*pp); + free(pglob->gl_pathv); + } +} + +static DIR * +g_opendir(str, pglob) + register Char *str; + glob_t *pglob; +{ + char buf[MAXPATHLEN]; + + if (!*str) + strcpy(buf, "."); + else + g_Ctoc(str, buf); + + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_opendir)(buf)); + + return(opendir(buf)); +} + +static int +g_lstat(fn, sb, pglob) + register Char *fn; + struct stat *sb; + glob_t *pglob; +{ + char buf[MAXPATHLEN]; + + g_Ctoc(fn, buf); + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_lstat)(buf, sb)); + return(lstat(buf, sb)); +} + +static int +g_stat(fn, sb, pglob) + register Char *fn; + struct stat *sb; + glob_t *pglob; +{ + char buf[MAXPATHLEN]; + + g_Ctoc(fn, buf); + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_stat)(buf, sb)); + return(stat(buf, sb)); +} + +static Char * +g_strchr(str, ch) + Char *str; + int ch; +{ + do { + if (*str == ch) + return (str); + } while (*str++); + return (NULL); +} + +#ifdef notdef +static Char * +g_strcat(dst, src) + Char *dst; + const Char* src; +{ + Char *sdst = dst; + + while (*dst++) + continue; + --dst; + while((*dst++ = *src++) != EOS) + continue; + + return (sdst); +} +#endif + +static void +g_Ctoc(str, buf) + register const Char *str; + char *buf; +{ + register char *dc; + + for (dc = buf; (*dc++ = *str++) != EOS;) + continue; +} + +#ifdef DEBUG +static void +qprintf(str, s) + const char *str; + register Char *s; +{ + register Char *p; + + (void)printf("%s:\n", str); + for (p = s; *p; p++) + (void)printf("%c", CHAR(*p)); + (void)printf("\n"); + for (p = s; *p; p++) + (void)printf("%c", *p & M_PROTECT ? '"' : ' '); + (void)printf("\n"); + for (p = s; *p; p++) + (void)printf("%c", ismeta(*p) ? '_' : ' '); + (void)printf("\n"); +} +#endif diff --git a/compat/inet_aton.c b/compat/inet_aton.c new file mode 100644 index 0000000..a935d5a --- /dev/null +++ b/compat/inet_aton.c @@ -0,0 +1,27 @@ +/* +** Copyright 2002 University of Illinois Board of Trustees +** Copyright 2002 Mark D. Roth +** All rights reserved. +** +** inet_aton.c - inet_aton() function for compatibility library +** +** Mark D. Roth +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include +#include +#include + + +int +inet_aton(const char *cp, struct in_addr *inp) +{ + inp->s_addr = inet_addr(cp); + if (inp->s_addr == -1) + return 0; + return 1; +} + + diff --git a/compat/module.ac b/compat/module.ac new file mode 100644 index 0000000..a08e6b3 --- /dev/null +++ b/compat/module.ac @@ -0,0 +1,608 @@ +# COMPAT_VAR___PROGNAME +# --------------------- +# Check if libc defines the __progname variable. +AC_DEFUN([COMPAT_VAR___PROGNAME], [ + AC_CACHE_CHECK([if libc defines __progname], + [ac_cv_libc_defines___progname], + [AC_TRY_LINK([], + [ + extern char *__progname; + printf("%s", __progname); + ], + [ac_cv_libc_defines___progname=yes], + [ac_cv_libc_defines___progname=no] + )] + ) + if test "$ac_cv_libc_defines___progname" = "yes"; then + AC_DEFINE([HAVE___PROGNAME], 1, + [Define if libc defines the __progname variable]) + fi +]) + + +# COMPAT_FUNC_BASENAME +# -------------------- +# Check for working basename() function. +AC_DEFUN([COMPAT_FUNC_BASENAME], [ + AC_DEFINE([NEED_BASENAME], 1, + [Define if you want to use the basename function]) + AC_CHECK_HEADERS([libgen.h]) + AC_CACHE_CHECK([for working basename], + [compat_cv_func_basename_works], + [AC_TRY_RUN([ +#include +#ifdef HAVE_LIBGEN_H +# include +#endif + +typedef struct { + char *test; + char *result; +} test_t; + +const test_t tests[] = { + { "/usr/local/foo", "foo" }, + { "/usr/local/foo/", "foo" }, + { NULL, NULL } +}; + +int main() { + char test1[1024]; + int i; + + for (i = 0; tests[i].test; i++) { + strcpy(test1, tests[i].test); + if (strcmp(basename(test1), tests[i].result) || + strcmp(test1, tests[i].test)) + exit(1); + } + + exit(0); +} +], + [compat_cv_func_basename_works=yes], + [compat_cv_func_basename_works=no], + [compat_cv_func_basename_works=no] + )] + ) + if test "$compat_cv_func_basename_works" = "yes"; then + AC_DEFINE([HAVE_BASENAME], 1, + [Define if your system has a working basename]) + else + AC_LIBOBJ([basename]) + fi +]) + + +# COMPAT_FUNC_DIRNAME +# ------------------- +# Check for working dirname() function. +AC_DEFUN([COMPAT_FUNC_DIRNAME], [ + AC_DEFINE([NEED_DIRNAME], 1, + [Define if you want to use the dirname function]) + AC_CHECK_HEADERS([libgen.h]) + AC_CACHE_CHECK([for working dirname], + [compat_cv_func_dirname_works], + [AC_TRY_RUN([ +#include +#ifdef HAVE_LIBGEN_H +# include +#endif + +typedef struct { + char *test; + char *result; +} test_t; + +const test_t tests[] = { + { "foobar", "." }, + { "/usr/local/foo", "/usr/local" }, + { "/usr/local/foo/", "/usr/local" }, + { "/", "/" }, + { "", "." }, + { NULL, NULL } +}; + +int main() { + char test1[1024]; + int i; + + for (i = 0; tests[i].test; i++) { + strcpy(test1, tests[i].test); + if (strcmp(dirname(test1), tests[i].result) || + strcmp(test1, tests[i].test)) + exit(1); + } + + exit(0); +} +], + [compat_cv_func_dirname_works=yes], + [compat_cv_func_dirname_works=no], + [compat_cv_func_dirname_works=no] + )] + ) + if test "$compat_cv_func_dirname_works" = "yes"; then + AC_DEFINE([HAVE_DIRNAME], 1, + [Define if your system has a working dirname]) + else + AC_LIBOBJ([dirname]) + fi +]) + + +# COMPAT_FUNC_FNMATCH +# ------------------- +# Check for working fnmatch() function. +AC_DEFUN([COMPAT_FUNC_FNMATCH], [ + AC_DEFINE([NEED_FNMATCH], 1, [Define if you want to use the fnmatch function]) + AC_CHECK_HEADERS([fnmatch.h]) + if test "$ac_cv_header_fnmatch_h" = "yes"; then + AC_FUNC_FNMATCH + fi + if test "$ac_cv_func_fnmatch_works" != "yes"; then + AC_CHECK_HEADERS([ctype.h]) + AC_LIBOBJ([fnmatch]) + fi +]) + + +# COMPAT_FUNC_GLOB +# ---------------- +# Check for working glob() function. +AC_DEFUN([COMPAT_FUNC_GLOB], [ + AC_DEFINE([NEED_GLOB], 1, [Define if you want to use the glob function]) + AC_CHECK_HEADERS([glob.h]) + AC_CACHE_CHECK([for working glob], + [compat_cv_func_glob_works], + [AC_TRY_RUN([ +#include +#ifdef HAVE_GLOB_H +# include +#endif + +#ifndef GLOB_ABORTED +# define GLOB_ABORTED GLOB_ABEND +#endif + +int main() { + glob_t g; + int status; + + status = glob("conf*", 0, NULL, &g); + switch (status) { + case 0: + case GLOB_NOSPACE: + case GLOB_ABORTED: + case GLOB_NOMATCH: + exit(0); + break; + default: + exit(1); + break; + } +} +], + [compat_cv_func_glob_works=yes], + [compat_cv_func_glob_works=no], + [compat_cv_func_glob_works=no] + )] + ) + if test "$compat_cv_func_glob_works" = "yes"; then + AC_DEFINE([HAVE_GLOB], 1, [Define if your system has a working glob]) + else + AC_LIBOBJ([glob]) + AC_CHECK_FUNCS([issetugid]) + fi +]) + + +# COMPAT_FUNC_MAKEDEV +# ------------------- +# Check for number of arguments expected by makedev(). +AC_DEFUN([COMPAT_FUNC_MAKEDEV], [ + AC_REQUIRE([AC_HEADER_MAJOR]) + AC_DEFINE([NEED_MAKEDEV], 1, + [Define if you want to use the makedev function]) + AC_CACHE_CHECK([whether makedev expects three arguments], + [compat_cv_func_makedev_three_args], + [AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ +#include +#ifdef MAJOR_IN_MKDEV +# include +#else +# ifdef MAJOR_IN_SYSMACROS +# include +# endif +#endif +]], [[ +dev_t dev; +major_t maj = 5; +minor_t min = 7; + +dev = makedev(0, maj, min); +if (major(dev) != maj + || minor(dev) != min) + exit(1); +exit(0); +]])], + [compat_cv_func_makedev_three_args=yes], + [compat_cv_func_makedev_three_args=no] + )] + ) + if test "$compat_cv_func_makedev_three_args" = "yes"; then + AC_DEFINE([MAKEDEV_THREE_ARGS], 1, + [Define as 1 if makedev expects three arguments]) + fi +]) + + +# COMPAT_FUNC_SNPRINTF +# -------------------- +# Check for working snprintf() function. +AC_DEFUN([COMPAT_FUNC_SNPRINTF], [ + AC_DEFINE([NEED_SNPRINTF], 1, + [Define if you want to use the snprintf function]) + AC_CACHE_CHECK([for working snprintf], + [compat_cv_func_snprintf_works], + [AC_TRY_RUN([ +#include + +typedef struct { + int length; + char *test; + int retval; + char *result; +} test_t; + +const test_t tests[] = { + { 10, "12345678901234567890", 20, "123456789" }, +#if 0 + { 0, "12345678901234567890", 20, NULL }, + { -1, "12345678901234567890", -1, NULL }, +#endif + { 0, NULL, 0, NULL } +}; + +int main() { + char test1[1024]; + int i; + + for (i = 0; tests[i].test; i++) { + memset(test1, 'X', sizeof(test1)); + if ((snprintf(test1, tests[i].length, "%s", tests[i].test) + != tests[i].retval) || + (tests[i].result && strcmp(tests[i].result, test1))) + exit(1); + } + + exit(0); +} +], + [compat_cv_func_snprintf_works=yes], + [compat_cv_func_snprintf_works=no], + [compat_cv_func_snprintf_works=no] + )] + ) + if test "$compat_cv_func_snprintf_works" = "yes"; then + AC_DEFINE([HAVE_SNPRINTF], 1, + [Define if your system has a working snprintf]) + else + AC_LIBOBJ([snprintf]) + fi +]) + + +# COMPAT_PROTO_MACRO(FUNCTION, HEADER, MACRO-LIST, [BODY]) +# -------------------------------------------------------- +# Determine which C preprocessor macro is needed to expose prototype of +# FUNCTION in HEADER. First, we try with nothing special defined; then we +# try with each macro from MACRO-LIST. We stop as soon as it's found +# and adjust $CFLAGS appropriately. +AC_DEFUN([COMPAT_PROTO_MACRO], + [AC_CACHE_CHECK([what to define for $1 prototype], + [compat_cv_proto_]$1[_macro], + [AC_TRY_COMPILE( + [ + #include <$2> + ], + [ + void *funcptr; + $4 + funcptr = $1; + ], + [compat_cv_proto_]$1[_macro="none"], + [for macro in $3; do + AC_TRY_COMPILE( + [ + #define $macro + #include <$2> + ], + [ + void *funcptr; + $4 + funcptr = $1; + ], + [ + compat_cv_proto_]$1[_macro="$macro" + break + ], + [compat_cv_proto_]$1[_macro="not found"] + ) + done] + )] + )] + if test -n "$compat_cv_proto_$1_macro" -a "$compat_cv_proto_$1_macro" != "not found" -a "$compat_cv_proto_$1_macro" != "none"; then + CFLAGS="${CFLAGS} -D$compat_cv_proto_$1_macro"; + fi +) + + +# COMPAT_FUNC_STRTOK_R +# -------------------- +# Check for working strtok_r(). +AC_DEFUN([COMPAT_FUNC_STRTOK_R], [ + AC_DEFINE([NEED_STRTOK_R], 1, + [Define if you want to use the strtok_r function]) + AC_REPLACE_FUNCS([strtok_r]) + COMPAT_PROTO_MACRO([strtok_r], [string.h], [_REENTRANT _THREAD_SAFE]) +]) + + +# COMPAT_FUNC_GETPWUID_R +# ---------------------- +# Check for POSIX-compliant getpwuid_r(). +AC_DEFUN([COMPAT_FUNC_GETPWUID_R], [ + AC_REQUIRE([AC_TYPE_SIZE_T]) + AC_CACHE_CHECK([for _SC_GETPW_R_SIZE_MAX], + [compat_cv__SC_GETPW_R_SIZE_MAX], + [AC_TRY_COMPILE( + [ + #include + ], + [ + size_t sz; + sz = (size_t)sysconf(_SC_GETPW_R_SIZE_MAX); + ], + [compat_cv__SC_GETPW_R_SIZE_MAX=yes], + [compat_cv__SC_GETPW_R_SIZE_MAX=no] + )] + ) + if test "$compat_cv__SC_GETPW_R_SIZE_MAX" = "yes"; then + COMPAT_PROTO_MACRO([getpwuid_r], [pwd.h], + [_POSIX_PTHREAD_SEMANTICS _REENTRANT], + [ + struct passwd pwd, *pwdp; + char buf[10240]; + getpwuid_r(0, &pwd, buf, sizeof(buf), &pwdp); + ] + ) + if test "$compat_cv_proto_getpwuid_r_macro" != "not found"; then + AC_DEFINE([HAVE_GETPWUID_R], 1, + [Define if your system has a POSIX-compliant getpwuid_r]) + else + AC_MSG_WARN([cannot find usable getpwuid_r - resulting libraries will not be thread-safe]) + fi + fi +]) + + +# COMPAT_FUNC_GETHOSTBYNAME_R +# --------------------------- +# Check for gethostbyname_r(). +AC_DEFUN([COMPAT_FUNC_GETHOSTBYNAME_R], [ + AC_REQUIRE([AC_TYPE_SIZE_T]) + AC_DEFINE([NEED_GETHOSTBYNAME_R], 1, + [Define if you want to use the gethostbyname_r function]) + AC_SEARCH_LIBS([gethostbyname_r], [nsl]) + if test "$ac_cv_search_gethostbyname_r" != "no"; then + COMPAT_PROTO_MACRO([gethostbyname_r], [netdb.h], [_REENTRANT]) + AC_CACHE_CHECK( + [for number of arguments to gethostbyname_r], + [compat_cv_gethostbyname_r_args], + [AC_TRY_COMPILE( + [ + #include + ], + [ + struct hostent hent; + char buf[10240]; + int herr; + + gethostbyname_r("localhost", &hent, buf, sizeof(buf), &herr); + ], + [compat_cv_gethostbyname_r_args=5], + [AC_TRY_COMPILE( + [ + #include + ], + [ + struct hostent hent, *hp; + char buf[10240]; + int herr; + + gethostbyname_r("localhost", &hent, buf, sizeof(buf), &hp, &herr); + ], + [compat_cv_gethostbyname_r_args=6], + [AC_TRY_COMPILE( + [ + #include + ], + [ + struct hostent hent; + struct hostent_data hdata; + + gethostbyname_r("localhost", &hent, &hdata); + ], + [compat_cv_gethostbyname_r_args=3], + [compat_cv_gethostbyname_r_args=no] + )] + )] + )] + ) + if test "$compat_cv_gethostbyname_r_args" != "no"; then + AC_DEFINE([HAVE_GETHOSTBYNAME_R], 1, + [Define if you have the gethostbyname_r function]) + AC_DEFINE_UNQUOTED([GETHOSTBYNAME_R_NUM_ARGS], + [$compat_cv_gethostbyname_r_args], + [Define to number of arguments for gethostbyname_r]) + if test "$compat_cv_gethostbyname_r_args" != "6"; then + AC_LIBOBJ([gethostbyname_r]) + fi + else + AC_MSG_WARN([unknown form of gethostbyname_r - resulting libraries will not be thread-safe]) + fi + else + AC_MSG_WARN([cannot find gethostbyname_r - resulting libraries will not be thread-safe]) + fi +]) + + +# COMPAT_FUNC_GETSERVBYNAME_R +# --------------------------- +# Check for getservbyname_r(). +AC_DEFUN([COMPAT_FUNC_GETSERVBYNAME_R], [ + AC_REQUIRE([AC_TYPE_SIZE_T]) + AC_DEFINE([NEED_GETSERVBYNAME_R], 1, + [Define if you want to use the getservbyname_r function]) + AC_SEARCH_LIBS([getservbyname_r], [socket nsl]) + if test "$ac_cv_search_getservbyname_r" != "no"; then + COMPAT_PROTO_MACRO([getservbyname_r], [netdb.h], [_REENTRANT]) + AC_CACHE_CHECK( + [for number of arguments to getservbyname_r], + [compat_cv_getservbyname_r_args], + [AC_TRY_COMPILE( + [ + #include + ], + [ + struct servent sent; + char buf[10240]; + + getservbyname_r("telnet", "tcp", &sent, buf, sizeof(buf)); + ], + [compat_cv_getservbyname_r_args=5], + [AC_TRY_COMPILE( + [ + #include + ], + [ + struct servent sent, *sp; + char buf[10240]; + + getservbyname_r("telnet", "tcp", &sent, buf, sizeof(buf), &sp); + ], + [compat_cv_getservbyname_r_args=6], + [AC_TRY_COMPILE( + [ + #include + ], + [ + struct servent sent; + struct servent_data sdata; + + getservbyname_r("telnet", "tcp", &sent, &sdata); + ], + [compat_cv_getservbyname_r_args=4], + [compat_cv_getservbyname_r_args=no] + )] + )] + )] + ) + if test "$compat_cv_getservbyname_r_args" != "no"; then + AC_DEFINE([HAVE_GETSERVBYNAME_R], 1, + [Define if you have the getservbyname_r function]) + AC_DEFINE_UNQUOTED([GETSERVBYNAME_R_NUM_ARGS], + [$compat_cv_getservbyname_r_args], + [Define to number of arguments for getservbyname_r]) + if test "$compat_cv_getservbyname_r_args" != "6"; then + AC_LIBOBJ([getservbyname_r]) + fi + else + AC_MSG_WARN([unknown form of getservbyname_r - resulting libraries will not be thread-safe]) + fi + else + AC_MSG_WARN([cannot find getservbyname_r - resulting libraries will not be thread-safe]) + fi +]) + + +# COMPAT_REPLACE_FUNC(function) +# ----------------------------- +# Replacement for AC_REPLACE_FUNCS. +AC_DEFUN([COMPAT_REPLACE_FUNC], [ + AC_DEFINE([NEED_]translit($1,[a-z],[A-Z]), 1, + [Define if you want to use the ]$1[ function]) + AC_CHECK_FUNC($1, + [AC_DEFINE([HAVE_]translit($1,[a-z],[A-Z]), 1, + [Define if you have the ]$1[ function])], + [AC_LIBOBJ(]$1[)] + ) +]) + + +# COMPAT_FUNC_GETHOSTNAME +# ----------------------- +# Check for gethostname(). +AC_DEFUN([COMPAT_FUNC_GETHOSTNAME], [ + COMPAT_REPLACE_FUNC([gethostname]) +]) + + +# COMPAT_FUNC_INET_ATON +# --------------------- +# Check for inet_aton(). +AC_DEFUN([COMPAT_FUNC_INET_ATON], [ + COMPAT_REPLACE_FUNC([inet_aton]) +]) + + +# COMPAT_FUNC_STRDUP +# ------------------ +# Check for strdup(). +AC_DEFUN([COMPAT_FUNC_STRDUP], [ + COMPAT_REPLACE_FUNC([strdup]) +]) + + +# COMPAT_FUNC_STRLCAT +# ------------------- +# Check for strlcat(). +AC_DEFUN([COMPAT_FUNC_STRLCAT], [ + COMPAT_REPLACE_FUNC([strlcat]) +]) + + +# COMPAT_FUNC_STRLCPY +# ------------------- +# Check for strlcpy(). +AC_DEFUN([COMPAT_FUNC_STRLCPY], [ + COMPAT_REPLACE_FUNC([strlcpy]) +]) + + +# COMPAT_FUNC_STRMODE +# ------------------- +# Check for strmode(). +AC_DEFUN([COMPAT_FUNC_STRMODE], [ + COMPAT_REPLACE_FUNC([strmode]) +]) + + +# COMPAT_FUNC_STRRSTR +# ------------------- +# Check for strrstr(). +AC_DEFUN([COMPAT_FUNC_STRRSTR], [ + COMPAT_REPLACE_FUNC([strrstr]) +]) + + +# COMPAT_FUNC_STRSEP +# ------------------ +# Check for strsep(). +AC_DEFUN([COMPAT_FUNC_STRSEP], [ + COMPAT_REPLACE_FUNC([strsep]) +]) + + diff --git a/compat/snprintf.c b/compat/snprintf.c new file mode 100644 index 0000000..56a68b4 --- /dev/null +++ b/compat/snprintf.c @@ -0,0 +1,788 @@ +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + * + * More Recently: + * Brandon Long 9/15/96 for mutt 0.43 + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything + * from the normal C string format, at least as far as I can tell from + * the Solaris 2.5 printf(3S) man page. + * + * Brandon Long 10/22/97 for mutt 0.87.1 + * Ok, added some minimal floating point support, which means this + * probably requires libm on most operating systems. Don't yet + * support the exponent (e,E) and sigfig (g,G). Also, fmtint() + * was pretty badly broken, it just wasn't being exercised in ways + * which showed it, so that's been fixed. Also, formated the code + * to mutt conventions, and removed dead code left over from the + * original. Also, there is now a builtin-test, just compile with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm + * and run snprintf for results. + * + * Thomas Roessler 01/27/98 for mutt 0.89i + * The PGP code was using unsigned hexadecimal formats. + * Unfortunately, unsigned formats simply didn't work. + * + * Michael Elkins 03/05/98 for mutt 0.90.8 + * The original code assumed that both snprintf() and vsnprintf() were + * missing. Some systems only have snprintf() but not vsnprintf(), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + **************************************************************/ + +#include + +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) + +#include +# include +#include + +/* Define this as a fall through, HAVE_STDARG_H is probably already set */ + +#define HAVE_VARARGS_H + +/* varargs declarations: */ + +#if defined(HAVE_STDARG_H) +# include +# define HAVE_STDARGS /* let's hope that works everywhere (mj) */ +# define VA_LOCAL_DECL va_list ap +# define VA_START(f) va_start(ap, f) +# define VA_SHIFT(v,t) ; /* no-op for ANSI */ +# define VA_END va_end(ap) +#else +# if defined(HAVE_VARARGS_H) +# include +# undef HAVE_STDARGS +# define VA_LOCAL_DECL va_list ap +# define VA_START(f) va_start(ap) /* f is ignored! */ +# define VA_SHIFT(v,t) v = va_arg(ap,t) +# define VA_END va_end(ap) +# else +/*XX ** NO VARARGS ** XX*/ +# endif +#endif + +/*int snprintf (char *str, size_t count, const char *fmt, ...);*/ +/*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/ + +static void dopr (char *buffer, size_t maxlen, const char *format, + va_list args); +static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max); +static void fmtint (char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags); +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + long double fvalue, int min, int max, int flags); +static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); + +/* + * dopr(): poor man's version of doprintf + */ + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* Conversion Flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 + +#define char_to_int(p) (p - '0') +#define MAX(p,q) ((p >= q) ? p : q) + +static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) +{ + char ch; + long value; + long double fvalue; + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + + state = DP_S_DEFAULT; + currlen = flags = cflags = min = 0; + max = -1; + ch = *format++; + + while (state != DP_S_DONE) + { + if ((ch == '\0') || (currlen >= maxlen)) + state = DP_S_DONE; + + switch(state) + { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + dopr_outch (buffer, &currlen, maxlen, ch); + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) + { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) + { + min = 10*min + char_to_int (ch); + ch = *format++; + } + else if (ch == '*') + { + min = va_arg (args, int); + ch = *format++; + state = DP_S_DOT; + } + else + state = DP_S_DOT; + break; + case DP_S_DOT: + if (ch == '.') + { + state = DP_S_MAX; + ch = *format++; + } + else + state = DP_S_MOD; + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) + { + if (max < 0) + max = 0; + max = 10*max + char_to_int (ch); + ch = *format++; + } + else if (ch == '*') + { + max = va_arg (args, int); + ch = *format++; + state = DP_S_MOD; + } + else + state = DP_S_MOD; + break; + case DP_S_MOD: + /* Currently, we don't support Long Long, bummer */ + switch (ch) + { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + cflags = DP_C_LONG; + ch = *format++; + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) + { + case 'd': + case 'i': + if (cflags == DP_C_SHORT) + value = va_arg (args, short int); + else if (cflags == DP_C_LONG) + value = va_arg (args, long int); + else + value = va_arg (args, int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'o': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned short int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else + value = va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); + break; + case 'u': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned short int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else + value = va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'X': + flags |= DP_F_UP; + case 'x': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned short int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else + value = va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, long double); + else + fvalue = va_arg (args, double); + /* um, floating point? */ + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'E': + flags |= DP_F_UP; + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, long double); + else + fvalue = va_arg (args, double); + break; + case 'G': + flags |= DP_F_UP; + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, long double); + else + fvalue = va_arg (args, double); + break; + case 'c': + dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); + break; + case 's': + strvalue = va_arg (args, char *); + if (max < 0) + max = maxlen; /* ie, no max */ + fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); + break; + case 'p': + strvalue = va_arg (args, void *); + fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); + break; + case 'n': + if (cflags == DP_C_SHORT) + { + short int *num; + num = va_arg (args, short int *); + *num = currlen; + } + else if (cflags == DP_C_LONG) + { + long int *num; + num = va_arg (args, long int *); + *num = currlen; + } + else + { + int *num; + num = va_arg (args, int *); + *num = currlen; + } + break; + case '%': + dopr_outch (buffer, &currlen, maxlen, ch); + break; + case 'w': + /* not supported yet, treat as next char */ + ch = *format++; + break; + default: + /* Unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + /* hmm? */ + break; /* some picky compilers need this */ + } + } + if (currlen < maxlen - 1) + buffer[currlen] = '\0'; + else + buffer[maxlen - 1] = '\0'; +} + +static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max) +{ + int padlen, strln; /* amount to pad */ + int cnt = 0; + + if (value == 0) + { + value = ""; + } + + for (strln = 0; value[strln]; ++strln); /* strlen */ + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justify */ + + while ((padlen > 0) && (cnt < max)) + { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + ++cnt; + } + while (*value && (cnt < max)) + { + dopr_outch (buffer, currlen, maxlen, *value++); + ++cnt; + } + while ((padlen < 0) && (cnt < max)) + { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + ++cnt; + } +} + +/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ + +static void fmtint (char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags) +{ + int signvalue = 0; + unsigned long uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; /* amount to space pad */ + int zpadlen = 0; /* amount to zero pad */ + int caps = 0; + + if (max < 0) + max = 0; + + uvalue = value; + + if(!(flags & DP_F_UNSIGNED)) + { + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } + else + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else + if (flags & DP_F_SPACE) + signvalue = ' '; + } + + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ + + do { + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + } while(uvalue && (place < 20)); + if (place == 20) place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) zpadlen = 0; + if (spadlen < 0) spadlen = 0; + if (flags & DP_F_ZERO) + { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; /* Left Justifty */ + +#ifdef DEBUG_SNPRINTF + dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", + zpadlen, spadlen, min, max, place)); +#endif + + /* Spaces */ + while (spadlen > 0) + { + dopr_outch (buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* Sign */ + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + /* Zeros */ + if (zpadlen > 0) + { + while (zpadlen > 0) + { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + + /* Digits */ + while (place > 0) + dopr_outch (buffer, currlen, maxlen, convert[--place]); + + /* Left Justified spaces */ + while (spadlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++spadlen; + } +} + +static long double abs_val (long double value) +{ + long double result = value; + + if (value < 0) + result = -value; + + return result; +} + +static long double pow10 (int exp) +{ + long double result = 1; + + while (exp) + { + result *= 10; + exp--; + } + + return result; +} + +static long round (long double value) +{ + long intpart; + + intpart = value; + value = value - intpart; + if (value >= 0.5) + intpart++; + + return intpart; +} + +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + long double fvalue, int min, int max, int flags) +{ + int signvalue = 0; + long double ufvalue; + char iconvert[20]; + char fconvert[20]; + int iplace = 0; + int fplace = 0; + int padlen = 0; /* amount to pad */ + int zpadlen = 0; + int caps = 0; + long intpart; + long fracpart; + + /* + * AIX manpage says the default is 0, but Solaris says the default + * is 6, and sprintf on AIX defaults to 6 + */ + if (max < 0) + max = 6; + + ufvalue = abs_val (fvalue); + + if (fvalue < 0) + signvalue = '-'; + else + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else + if (flags & DP_F_SPACE) + signvalue = ' '; + +#if 0 + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ +#endif + + intpart = ufvalue; + + /* + * Sorry, we only support 9 digits past the decimal because of our + * conversion method + */ + if (max > 9) + max = 9; + + /* We "cheat" by converting the fractional part to integer by + * multiplying by a factor of 10 + */ + fracpart = round ((pow10 (max)) * (ufvalue - intpart)); + + if (fracpart >= pow10 (max)) + { + intpart++; + fracpart -= pow10 (max); + } + +#ifdef DEBUG_SNPRINTF + dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart)); +#endif + + /* Convert integer part */ + do { + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; + intpart = (intpart / 10); + } while(intpart && (iplace < 20)); + if (iplace == 20) iplace--; + iconvert[iplace] = 0; + + /* Convert fractional part */ + do { + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; + fracpart = (fracpart / 10); + } while(fracpart && (fplace < 20)); + if (fplace == 20) fplace--; + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) + zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justifty */ + + if ((flags & DP_F_ZERO) && (padlen > 0)) + { + if (signvalue) + { + dopr_outch (buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) + { + dopr_outch (buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) + { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + dopr_outch (buffer, currlen, maxlen, '.'); + + while (fplace > 0) + dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); + + while (zpadlen > 0) + { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (padlen < 0) + { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) +{ + if (*currlen < maxlen) + buffer[(*currlen)++] = c; +} +#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ + +#ifndef HAVE_VSNPRINTF +int mutt_vsnprintf (char *str, size_t count, const char *fmt, va_list args) +{ + str[0] = 0; + dopr(str, count, fmt, args); + return(strlen(str)); +} +#endif /* !HAVE_VSNPRINTF */ + +#ifndef HAVE_SNPRINTF +/* VARARGS3 */ +#ifdef HAVE_STDARGS +int mutt_snprintf (char *str,size_t count,const char *fmt,...) +#else +int mutt_snprintf (va_alist) va_dcl +#endif +{ +#ifndef HAVE_STDARGS + char *str; + size_t count; + char *fmt; +#endif + VA_LOCAL_DECL; + + VA_START (fmt); + VA_SHIFT (str, char *); + VA_SHIFT (count, size_t ); + VA_SHIFT (fmt, char *); + (void) mutt_vsnprintf(str, count, fmt, ap); + VA_END; + return(strlen(str)); +} + +#ifdef TEST_SNPRINTF +#ifndef LONG_STRING +#define LONG_STRING 1024 +#endif +int main (void) +{ + char buf1[LONG_STRING]; + char buf2[LONG_STRING]; + char *fp_fmt[] = { + "%-1.5f", + "%1.5f", + "%123.9f", + "%10.5f", + "% 10.5f", + "%+22.9f", + "%+4.9f", + "%01.3f", + "%4f", + "%3.1f", + "%3.2f", + NULL + }; + double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, + 0.9996, 1.996, 4.136, 0}; + char *int_fmt[] = { + "%-1.5d", + "%1.5d", + "%123.9d", + "%5.5d", + "%10.5d", + "% 10.5d", + "%+22.33d", + "%01.3d", + "%4d", + NULL + }; + long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; + int x, y; + int fail = 0; + int num = 0; + + printf ("Testing snprintf format codes against system sprintf...\n"); + + for (x = 0; fp_fmt[x] != NULL ; x++) + for (y = 0; fp_nums[y] != 0 ; y++) + { + mutt_snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]); + sprintf (buf2, fp_fmt[x], fp_nums[y]); + if (strcmp (buf1, buf2)) + { + printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", + fp_fmt[x], buf1, buf2); + fail++; + } + num++; + } + + for (x = 0; int_fmt[x] != NULL ; x++) + for (y = 0; int_nums[y] != 0 ; y++) + { + mutt_snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]); + sprintf (buf2, int_fmt[x], int_nums[y]); + if (strcmp (buf1, buf2)) + { + printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", + int_fmt[x], buf1, buf2); + fail++; + } + num++; + } + printf ("%d tests failed out of %d.\n", fail, num); +} +#endif /* SNPRINTF_TEST */ + +#endif /* !HAVE_SNPRINTF */ diff --git a/compat/strdup.c b/compat/strdup.c new file mode 100644 index 0000000..75e9af5 --- /dev/null +++ b/compat/strdup.c @@ -0,0 +1,62 @@ +/* $OpenBSD: strdup.c,v 1.3 1997/08/20 04:18:52 millert Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93"; +#else +static char *rcsid = "$OpenBSD: strdup.c,v 1.3 1997/08/20 04:18:52 millert Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include + +char * +openbsd_strdup(str) + const char *str; +{ + size_t siz; + char *copy; + + siz = strlen(str) + 1; + if ((copy = malloc(siz)) == NULL) + return(NULL); + (void)memcpy(copy, str, siz); + return(copy); +} diff --git a/compat/strlcat.c b/compat/strlcat.c new file mode 100644 index 0000000..3912539 --- /dev/null +++ b/compat/strlcat.c @@ -0,0 +1,72 @@ +/* $OpenBSD: strlcat.c,v 1.5 2001/01/13 16:17:24 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author 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 ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: strlcat.c,v 1.5 2001/01/13 16:17:24 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(initial dst) + strlen(src); if retval >= siz, + * truncation occurred. + */ +size_t strlcat(dst, src, siz) + char *dst; + const char *src; + size_t siz; +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} diff --git a/compat/strlcpy.c b/compat/strlcpy.c new file mode 100644 index 0000000..300a28b --- /dev/null +++ b/compat/strlcpy.c @@ -0,0 +1,68 @@ +/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author 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 ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t strlcpy(dst, src, siz) + char *dst; + const char *src; + size_t siz; +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} diff --git a/compat/strmode.c b/compat/strmode.c new file mode 100644 index 0000000..5e7f15e --- /dev/null +++ b/compat/strmode.c @@ -0,0 +1,152 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: strmode.c,v 1.3 1997/06/13 13:57:20 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +void +strmode(mode, p) + register mode_t mode; + register char *p; +{ + /* print type */ + switch (mode & S_IFMT) { + case S_IFDIR: /* directory */ + *p++ = 'd'; + break; + case S_IFCHR: /* character special */ + *p++ = 'c'; + break; + case S_IFBLK: /* block special */ + *p++ = 'b'; + break; + case S_IFREG: /* regular */ + *p++ = '-'; + break; + case S_IFLNK: /* symbolic link */ + *p++ = 'l'; + break; + case S_IFSOCK: /* socket */ + *p++ = 's'; + break; +#ifdef S_IFIFO + case S_IFIFO: /* fifo */ + *p++ = 'p'; + break; +#endif +#ifdef S_IFWHT + case S_IFWHT: /* whiteout */ + *p++ = 'w'; + break; +#endif + default: /* unknown */ + *p++ = '?'; + break; + } + /* usr */ + if (mode & S_IRUSR) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWUSR) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXUSR | S_ISUID)) { + case 0: + *p++ = '-'; + break; + case S_IXUSR: + *p++ = 'x'; + break; + case S_ISUID: + *p++ = 'S'; + break; + case S_IXUSR | S_ISUID: + *p++ = 's'; + break; + } + /* group */ + if (mode & S_IRGRP) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWGRP) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXGRP | S_ISGID)) { + case 0: + *p++ = '-'; + break; + case S_IXGRP: + *p++ = 'x'; + break; + case S_ISGID: + *p++ = 'S'; + break; + case S_IXGRP | S_ISGID: + *p++ = 's'; + break; + } + /* other */ + if (mode & S_IROTH) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWOTH) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXOTH | S_ISVTX)) { + case 0: + *p++ = '-'; + break; + case S_IXOTH: + *p++ = 'x'; + break; + case S_ISVTX: + *p++ = 'T'; + break; + case S_IXOTH | S_ISVTX: + *p++ = 't'; + break; + } + *p++ = ' '; /* will be a '+' if ACL's implemented */ + *p = '\0'; +} diff --git a/compat/strrstr.c b/compat/strrstr.c new file mode 100644 index 0000000..097ef91 --- /dev/null +++ b/compat/strrstr.c @@ -0,0 +1,40 @@ +/* +** Copyright 1998-2002 University of Illinois Board of Trustees +** Copyright 1998-2002 Mark D. Roth +** All rights reserved. +** +** strrstr.c - strrstr() function for compatibility library +** +** Mark D. Roth +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include +#include + +#include + + +/* +** find the last occurrance of find in string +*/ +char * +strrstr(char *string, char *find) +{ + size_t stringlen, findlen; + char *cp; + + findlen = strlen(find); + stringlen = strlen(string); + if (findlen > stringlen) + return NULL; + + for (cp = string + stringlen - findlen; cp >= string; cp--) + if (strncmp(cp, find, findlen) == 0) + return cp; + + return NULL; +} + + diff --git a/compat/strsep.c b/compat/strsep.c new file mode 100644 index 0000000..3132962 --- /dev/null +++ b/compat/strsep.c @@ -0,0 +1,87 @@ +/* $OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93"; +#else +static char *rcsid = "$OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +#ifndef HAVE_STRSEP +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strsep returns NULL. + */ +char * +strsep(stringp, delim) + register char **stringp; + register const char *delim; +{ + register char *s; + register const char *spanp; + register int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} +#endif /* ! HAVE_STRSEP */ diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..76a1b4d --- /dev/null +++ b/config.h.in @@ -0,0 +1,158 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to number of arguments for gethostbyname_r */ +#undef GETHOSTBYNAME_R_NUM_ARGS + +/* Define to number of arguments for getservbyname_r */ +#undef GETSERVBYNAME_R_NUM_ARGS + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_AIXRCMDS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_CRYPT_H + +/* Define if you have the gethostbyname_r function */ +#undef HAVE_GETHOSTBYNAME_R + +/* Define if your system has a POSIX-compliant getpwuid_r */ +#undef HAVE_GETPWUID_R + +/* Define if you have the getservbyname_r function */ +#undef HAVE_GETSERVBYNAME_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `crypt' library (-lcrypt). */ +#undef HAVE_LIBCRYPT + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define to 1 if you have the `readline' library (-lreadline). */ +#undef HAVE_LIBREADLINE + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PATHS_H + +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + +/* Define to 1 if you have the header file. */ +#undef HAVE_READLINE_HISTORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_READLINE_READLINE_H + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define if your system has a working snprintf */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the strdup function */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the strlcat function */ +#undef HAVE_STRLCAT + +/* Define if you have the strlcpy function */ +#undef HAVE_STRLCPY + +/* Define if you have the strsep function */ +#undef HAVE_STRSEP + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_POLL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Path to more. */ +#undef MORE + +/* Define if you want to use the gethostbyname_r function */ +#undef NEED_GETHOSTBYNAME_R + +/* Define if you want to use the getservbyname_r function */ +#undef NEED_GETSERVBYNAME_R + +/* Define if you want to use the snprintf function */ +#undef NEED_SNPRINTF + +/* Define if you want to use the strdup function */ +#undef NEED_STRDUP + +/* Define if you want to use the strlcat function */ +#undef NEED_STRLCAT + +/* Define if you want to use the strlcpy function */ +#undef NEED_STRLCPY + +/* Define if you want to use the strsep function */ +#undef NEED_STRSEP + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Default mailmatch fields */ +#undef PH_DEFAULT_MAILMATCHES + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Path to vi. */ +#undef VI + +/* Define to 1 if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `unsigned' if does not define. */ +#undef size_t diff --git a/configure b/configure new file mode 100755 index 0000000..4c6b959 --- /dev/null +++ b/configure @@ -0,0 +1,7103 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.57 for nph 1.2.3. +# +# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +# +# +# Copyright (c) 2000-2004 University of Illinois Board of Trustees +# Copyright (c) 2000-2004 Mark D. Roth +# All rights reserved. +# +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='nph' +PACKAGE_TARNAME='nph' +PACKAGE_VERSION='1.2.3' +PACKAGE_STRING='nph 1.2.3' +PACKAGE_BUGREPORT='' + +ac_unique_file="lib/phclient.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS EPKG MKENCAP ENCAP_DEFS ENCAP_INSTALL_RULES ENCAP_INSTALL_TARGET MKDIR CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT RANLIB ac_ct_RANLIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE MORE VI CPP EGREP LIBOBJS NPH_MODE BUFFER_PREFIX BUFFER_DIR MMGR_PREFIX MMGR_DIR LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures nph 1.2.3 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of nph 1.2.3:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-encap Do not configure as an Encap package + --disable-epkg-install Do not run epkg during make install + --disable-readline Do not use the readline library in the nph client + --enable-setuid-nph Install nph setuid-root (for email authentication) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-mailmatches=LIST Set default mailmatch fields + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +nph configure 1.2.3 +generated by GNU Autoconf 2.57 + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. + + +Copyright (c) 2000-2004 University of Illinois Board of Trustees +Copyright (c) 2000-2004 Mark D. Roth +All rights reserved. + +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by nph $as_me 1.2.3, which was +generated by GNU Autoconf 2.57. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core core.* *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ac_aux_dir= +for ac_dir in autoconf $srcdir/autoconf; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in autoconf $srcdir/autoconf" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in autoconf $srcdir/autoconf" >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + + ac_config_headers="$ac_config_headers config.h" + + + + + MKENCAP_OPTS=; + + # allow user to disable Encap support + # Check whether --enable-encap or --disable-encap was given. +if test "${enable_encap+set}" = set; then + enableval="$enable_encap" + +else + enable_encap=default +fi; + + if test "$enable_encap" != "no"; then + # look for epkg and mkencap + # Extract the first word of "epkg", so it can be a program name with args. +set dummy epkg; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_EPKG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $EPKG in + [\\/]* | ?:[\\/]*) + ac_cv_path_EPKG="$EPKG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_EPKG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +EPKG=$ac_cv_path_EPKG + +if test -n "$EPKG"; then + echo "$as_me:$LINENO: result: $EPKG" >&5 +echo "${ECHO_T}$EPKG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + # Extract the first word of "mkencap", so it can be a program name with args. +set dummy mkencap; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_MKENCAP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MKENCAP in + [\\/]* | ?:[\\/]*) + ac_cv_path_MKENCAP="$MKENCAP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MKENCAP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +MKENCAP=$ac_cv_path_MKENCAP + +if test -n "$MKENCAP"; then + echo "$as_me:$LINENO: result: $MKENCAP" >&5 +echo "${ECHO_T}$MKENCAP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + + # enable by default if epkg or mkencap are found + if test "${EPKG:+set}" = "set" || test "${MKENCAP:+set}" = "set" && test "$enable_encap" = "default"; then + enable_encap=yes; + fi + fi + + if test "$enable_encap" = "yes"; then + # generate fallback values for ${ENCAP_SOURCE} and ${ENCAP_TARGET} + # from the environment or the default prefix + if test -z "${ENCAP_SOURCE}" && test -z "${ENCAP_TARGET}"; then + ENCAP_SOURCE="${ac_default_prefix}/encap"; + ENCAP_TARGET="${ac_default_prefix}"; + elif test -z "${ENCAP_TARGET}"; then + ENCAP_TARGET="`dirname ${ENCAP_SOURCE}`"; + elif test -z "${ENCAP_SOURCE}"; then + ENCAP_SOURCE="${ENCAP_TARGET}/encap"; + fi + + # if --prefix is specified: + # 1) if its next-to-last component is "encap", assume that it + # points to the package directory + # 2) otherwise, assume it points to the target directory + if test "${prefix}" != "NONE"; then + prefixdir="`dirname ${prefix}`"; + prefixbase="`basename ${prefix}`"; + if test "`basename ${prefixdir}`" = "encap"; then + ENCAP_SOURCE="${prefixdir}"; + ENCAP_TARGET="`dirname ${ENCAP_SOURCE}`"; + elif test "${prefixdir}" != "${ENCAP_SOURCE}"; then + ENCAP_SOURCE="${prefix}/encap"; + ENCAP_TARGET="${prefix}"; + fi + if ( test "`basename ${prefixdir}`" = "encap" || \ + test "${prefixdir}" = "${ENCAP_SOURCE}" ) && \ + test "${prefixbase}" != "${PACKAGE_NAME}-${PACKAGE_VERSION}"; then + ENCAP_PKGSPEC="${prefixbase}"; + fi + fi + + # display results + echo "$as_me:$LINENO: checking for Encap source directory" >&5 +echo $ECHO_N "checking for Encap source directory... $ECHO_C" >&6 + echo "$as_me:$LINENO: result: ${ENCAP_SOURCE}" >&5 +echo "${ECHO_T}${ENCAP_SOURCE}" >&6 + echo "$as_me:$LINENO: checking for Encap target directory" >&5 +echo $ECHO_N "checking for Encap target directory... $ECHO_C" >&6 + echo "$as_me:$LINENO: result: ${ENCAP_TARGET}" >&5 +echo "${ECHO_T}${ENCAP_TARGET}" >&6 + echo "$as_me:$LINENO: checking for Encap package directory" >&5 +echo $ECHO_N "checking for Encap package directory... $ECHO_C" >&6 + if test "${ENCAP_PKGSPEC:-unset}" = "unset"; then + ENCAP_PKGSPEC='${PACKAGE_NAME}-${PACKAGE_VERSION}'; + echo "$as_me:$LINENO: result: ${ENCAP_SOURCE}/${PACKAGE_NAME}-${PACKAGE_VERSION}" >&5 +echo "${ECHO_T}${ENCAP_SOURCE}/${PACKAGE_NAME}-${PACKAGE_VERSION}" >&6 + else + echo "$as_me:$LINENO: result: ${ENCAP_SOURCE}/${ENCAP_PKGSPEC}" >&5 +echo "${ECHO_T}${ENCAP_SOURCE}/${ENCAP_PKGSPEC}" >&6 + fi + prefix='${ENCAP_SOURCE}/${ENCAP_PKGSPEC}'; + + # override default sysconfdir and localstatedir + if test "$sysconfdir" = '${prefix}/etc'; then + sysconfdir='${ENCAP_TARGET}/etc'; + fi + if test "$localstatedir" = '${prefix}/var'; then + localstatedir='/var/lib/${PACKAGE_NAME}'; + fi + + # check for --disable-epkg-install + # Check whether --enable-epkg-install or --disable-epkg-install was given. +if test "${enable_epkg_install+set}" = set; then + enableval="$enable_epkg_install" + +else + enable_epkg_install=yes +fi; + if test "$enable_epkg_install" = "no"; then + EPKG=":"; + fi + + # generate Makefile variables + + ENCAP_DEFS="ENCAP_SOURCE = ${ENCAP_SOURCE}\\ +ENCAP_TARGET = ${ENCAP_TARGET}\\ +ENCAP_PKGSPEC = ${ENCAP_PKGSPEC}\\ +EPKG = ${EPKG:-:}\\ +MKENCAP = ${MKENCAP:-:}\\ +MKENCAP_OPTS = ${MKENCAP_OPTS}"; + + + ENCAP_INSTALL_RULES='if test -f ${top_srcdir}/COPYRIGHT; then \\\ + ${INSTALL_DATA} ${top_srcdir}/COPYRIGHT ${ENCAP_SOURCE}/${ENCAP_PKGSPEC}; \\\ + fi\ + ${MKENCAP} ${MKENCAP_OPTS} -s ${DESTDIR}${ENCAP_SOURCE} -e ${ENCAP_PKGSPEC};\ + if test -z \"${DESTDIR}\"; then \\\ + ${EPKG} -s ${ENCAP_SOURCE} -t ${ENCAP_TARGET} ${ENCAP_PKGSPEC}; \\\ + fi'; + + + ENCAP_INSTALL_TARGET=postinstall-encap + else + ENCAP_INSTALL_TARGET=postinstall-no-encap + fi + + + + + +if test -z "$CFLAGS"; then + CFLAGS="-O" +fi +MKDIR="mkdir -p -m 755" + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output" >&5 +echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + ''\ + '#include ' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6 +fi + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Extract the first word of "more", so it can be a program name with args. +set dummy more; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_MORE+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MORE in + [\\/]* | ?:[\\/]*) + ac_cv_path_MORE="$MORE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MORE="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +MORE=$ac_cv_path_MORE + +if test -n "$MORE"; then + echo "$as_me:$LINENO: result: $MORE" >&5 +echo "${ECHO_T}$MORE" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + +cat >>confdefs.h <<_ACEOF +#define MORE "${ac_cv_path_MORE}" +_ACEOF + +# Extract the first word of "vi", so it can be a program name with args. +set dummy vi; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_VI+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $VI in + [\\/]* | ?:[\\/]*) + ac_cv_path_VI="$VI" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_VI="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +VI=$ac_cv_path_VI + +if test -n "$VI"; then + echo "$as_me:$LINENO: result: $VI" >&5 +echo "${ECHO_T}$VI" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + +cat >>confdefs.h <<_ACEOF +#define VI "${ac_cv_path_VI}" +_ACEOF + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + + +echo "$as_me:$LINENO: checking for AIX" >&5 +echo $ECHO_N "checking for AIX... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef _AIX + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +cat >>confdefs.h <<\_ACEOF +#define _ALL_SOURCE 1 +_ACEOF + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +rm -f conftest* + + +echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + } +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_const=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6 +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + +for ac_header in arpa/aixrcmds.h crypt.h paths.h unistd.h sys/poll.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +if test "$ac_cv_header_sys_poll_h" != "yes"; then + +for ac_header in sys/select.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +fi + + + + # COMPAT_VAR___PROGNAME +# --------------------- +# Check if libc defines the __progname variable. + + + +# COMPAT_FUNC_BASENAME +# -------------------- +# Check for working basename() function. + + + +# COMPAT_FUNC_DIRNAME +# ------------------- +# Check for working dirname() function. + + + +# COMPAT_FUNC_FNMATCH +# ------------------- +# Check for working fnmatch() function. + + + +# COMPAT_FUNC_GLOB +# ---------------- +# Check for working glob() function. + + + +# COMPAT_FUNC_MAKEDEV +# ------------------- +# Check for number of arguments expected by makedev(). + + + +# COMPAT_FUNC_SNPRINTF +# -------------------- +# Check for working snprintf() function. + + + +# COMPAT_PROTO_MACRO(FUNCTION, HEADER, MACRO-LIST, [BODY]) +# -------------------------------------------------------- +# Determine which C preprocessor macro is needed to expose prototype of +# FUNCTION in HEADER. First, we try with nothing special defined; then we +# try with each macro from MACRO-LIST. We stop as soon as it's found +# and adjust $CFLAGS appropriately. + + + +# COMPAT_FUNC_STRTOK_R +# -------------------- +# Check for working strtok_r(). + + + +# COMPAT_FUNC_GETPWUID_R +# ---------------------- +# Check for POSIX-compliant getpwuid_r(). + + + +# COMPAT_FUNC_GETHOSTBYNAME_R +# --------------------------- +# Check for gethostbyname_r(). + + + +# COMPAT_FUNC_GETSERVBYNAME_R +# --------------------------- +# Check for getservbyname_r(). + + + +# COMPAT_REPLACE_FUNC(function) +# ----------------------------- +# Replacement for AC_REPLACE_FUNCS. + + + +# COMPAT_FUNC_GETHOSTNAME +# ----------------------- +# Check for gethostname(). + + + +# COMPAT_FUNC_INET_ATON +# --------------------- +# Check for inet_aton(). + + + +# COMPAT_FUNC_STRDUP +# ------------------ +# Check for strdup(). + + + +# COMPAT_FUNC_STRLCAT +# ------------------- +# Check for strlcat(). + + + +# COMPAT_FUNC_STRLCPY +# ------------------- +# Check for strlcpy(). + + + +# COMPAT_FUNC_STRMODE +# ------------------- +# Check for strmode(). + + + +# COMPAT_FUNC_STRRSTR +# ------------------- +# Check for strrstr(). + + + +# COMPAT_FUNC_STRSEP +# ------------------ +# Check for strsep(). + + + + +echo "$as_me:$LINENO: checking for size_t" >&5 +echo $ECHO_N "checking for size_t... $ECHO_C" >&6 +if test "${ac_cv_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((size_t *) 0) + return 0; +if (sizeof (size_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_size_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_size_t=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_type_size_t" >&6 +if test $ac_cv_type_size_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned +_ACEOF + +fi + + + + +cat >>confdefs.h <<\_ACEOF +#define NEED_GETHOSTBYNAME_R 1 +_ACEOF + + echo "$as_me:$LINENO: checking for library containing gethostbyname_r" >&5 +echo $ECHO_N "checking for library containing gethostbyname_r... $ECHO_C" >&6 +if test "${ac_cv_search_gethostbyname_r+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_gethostbyname_r=no +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname_r (); +int +main () +{ +gethostbyname_r (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_gethostbyname_r="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_gethostbyname_r" = no; then + for ac_lib in nsl; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname_r (); +int +main () +{ +gethostbyname_r (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_gethostbyname_r="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_gethostbyname_r" >&5 +echo "${ECHO_T}$ac_cv_search_gethostbyname_r" >&6 +if test "$ac_cv_search_gethostbyname_r" != no; then + test "$ac_cv_search_gethostbyname_r" = "none required" || LIBS="$ac_cv_search_gethostbyname_r $LIBS" + +fi + + if test "$ac_cv_search_gethostbyname_r" != "no"; then + echo "$as_me:$LINENO: checking what to define for gethostbyname_r prototype" >&5 +echo $ECHO_N "checking what to define for gethostbyname_r prototype... $ECHO_C" >&6 +if test "${compat_cv_proto_gethostbyname_r_macro+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + +int +main () +{ + + void *funcptr; + + funcptr = gethostbyname_r; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + compat_cv_proto_gethostbyname_r_macro="none" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +for macro in _REENTRANT; do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #define $macro + #include + +int +main () +{ + + void *funcptr; + + funcptr = gethostbyname_r; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + compat_cv_proto_gethostbyname_r_macro="$macro" + break + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +compat_cv_proto_gethostbyname_r_macro="not found" + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + done + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $compat_cv_proto_gethostbyname_r_macro" >&5 +echo "${ECHO_T}$compat_cv_proto_gethostbyname_r_macro" >&6 + if test -n "$compat_cv_proto_gethostbyname_r_macro" -a "$compat_cv_proto_gethostbyname_r_macro" != "not found" -a "$compat_cv_proto_gethostbyname_r_macro" != "none"; then + CFLAGS="${CFLAGS} -D$compat_cv_proto_gethostbyname_r_macro"; + fi + + echo "$as_me:$LINENO: checking for number of arguments to gethostbyname_r" >&5 +echo $ECHO_N "checking for number of arguments to gethostbyname_r... $ECHO_C" >&6 +if test "${compat_cv_gethostbyname_r_args+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + +int +main () +{ + + struct hostent hent; + char buf[10240]; + int herr; + + gethostbyname_r("localhost", &hent, buf, sizeof(buf), &herr); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + compat_cv_gethostbyname_r_args=5 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + +int +main () +{ + + struct hostent hent, *hp; + char buf[10240]; + int herr; + + gethostbyname_r("localhost", &hent, buf, sizeof(buf), &hp, &herr); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + compat_cv_gethostbyname_r_args=6 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + +int +main () +{ + + struct hostent hent; + struct hostent_data hdata; + + gethostbyname_r("localhost", &hent, &hdata); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + compat_cv_gethostbyname_r_args=3 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +compat_cv_gethostbyname_r_args=no + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $compat_cv_gethostbyname_r_args" >&5 +echo "${ECHO_T}$compat_cv_gethostbyname_r_args" >&6 + if test "$compat_cv_gethostbyname_r_args" != "no"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GETHOSTBYNAME_R 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define GETHOSTBYNAME_R_NUM_ARGS $compat_cv_gethostbyname_r_args +_ACEOF + + if test "$compat_cv_gethostbyname_r_args" != "6"; then + LIBOBJS="$LIBOBJS gethostbyname_r.$ac_objext" + fi + else + { echo "$as_me:$LINENO: WARNING: unknown form of gethostbyname_r - resulting libraries will not be thread-safe" >&5 +echo "$as_me: WARNING: unknown form of gethostbyname_r - resulting libraries will not be thread-safe" >&2;} + fi + else + { echo "$as_me:$LINENO: WARNING: cannot find gethostbyname_r - resulting libraries will not be thread-safe" >&5 +echo "$as_me: WARNING: cannot find gethostbyname_r - resulting libraries will not be thread-safe" >&2;} + fi + + + + echo "$as_me:$LINENO: checking for _SC_GETPW_R_SIZE_MAX" >&5 +echo $ECHO_N "checking for _SC_GETPW_R_SIZE_MAX... $ECHO_C" >&6 +if test "${compat_cv__SC_GETPW_R_SIZE_MAX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + +int +main () +{ + + size_t sz; + sz = (size_t)sysconf(_SC_GETPW_R_SIZE_MAX); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + compat_cv__SC_GETPW_R_SIZE_MAX=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +compat_cv__SC_GETPW_R_SIZE_MAX=no + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $compat_cv__SC_GETPW_R_SIZE_MAX" >&5 +echo "${ECHO_T}$compat_cv__SC_GETPW_R_SIZE_MAX" >&6 + if test "$compat_cv__SC_GETPW_R_SIZE_MAX" = "yes"; then + echo "$as_me:$LINENO: checking what to define for getpwuid_r prototype" >&5 +echo $ECHO_N "checking what to define for getpwuid_r prototype... $ECHO_C" >&6 +if test "${compat_cv_proto_getpwuid_r_macro+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + +int +main () +{ + + void *funcptr; + + struct passwd pwd, *pwdp; + char buf[10240]; + getpwuid_r(0, &pwd, buf, sizeof(buf), &pwdp); + + + funcptr = getpwuid_r; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + compat_cv_proto_getpwuid_r_macro="none" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +for macro in _POSIX_PTHREAD_SEMANTICS _REENTRANT; do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #define $macro + #include + +int +main () +{ + + void *funcptr; + + struct passwd pwd, *pwdp; + char buf[10240]; + getpwuid_r(0, &pwd, buf, sizeof(buf), &pwdp); + + + funcptr = getpwuid_r; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + compat_cv_proto_getpwuid_r_macro="$macro" + break + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +compat_cv_proto_getpwuid_r_macro="not found" + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + done + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $compat_cv_proto_getpwuid_r_macro" >&5 +echo "${ECHO_T}$compat_cv_proto_getpwuid_r_macro" >&6 + if test -n "$compat_cv_proto_getpwuid_r_macro" -a "$compat_cv_proto_getpwuid_r_macro" != "not found" -a "$compat_cv_proto_getpwuid_r_macro" != "none"; then + CFLAGS="${CFLAGS} -D$compat_cv_proto_getpwuid_r_macro"; + fi + + if test "$compat_cv_proto_getpwuid_r_macro" != "not found"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GETPWUID_R 1 +_ACEOF + + else + { echo "$as_me:$LINENO: WARNING: cannot find usable getpwuid_r - resulting libraries will not be thread-safe" >&5 +echo "$as_me: WARNING: cannot find usable getpwuid_r - resulting libraries will not be thread-safe" >&2;} + fi + fi + + + + +cat >>confdefs.h <<\_ACEOF +#define NEED_GETSERVBYNAME_R 1 +_ACEOF + + echo "$as_me:$LINENO: checking for library containing getservbyname_r" >&5 +echo $ECHO_N "checking for library containing getservbyname_r... $ECHO_C" >&6 +if test "${ac_cv_search_getservbyname_r+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_getservbyname_r=no +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getservbyname_r (); +int +main () +{ +getservbyname_r (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_getservbyname_r="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_getservbyname_r" = no; then + for ac_lib in socket nsl; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getservbyname_r (); +int +main () +{ +getservbyname_r (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_getservbyname_r="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_getservbyname_r" >&5 +echo "${ECHO_T}$ac_cv_search_getservbyname_r" >&6 +if test "$ac_cv_search_getservbyname_r" != no; then + test "$ac_cv_search_getservbyname_r" = "none required" || LIBS="$ac_cv_search_getservbyname_r $LIBS" + +fi + + if test "$ac_cv_search_getservbyname_r" != "no"; then + echo "$as_me:$LINENO: checking what to define for getservbyname_r prototype" >&5 +echo $ECHO_N "checking what to define for getservbyname_r prototype... $ECHO_C" >&6 +if test "${compat_cv_proto_getservbyname_r_macro+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + +int +main () +{ + + void *funcptr; + + funcptr = getservbyname_r; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + compat_cv_proto_getservbyname_r_macro="none" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +for macro in _REENTRANT; do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #define $macro + #include + +int +main () +{ + + void *funcptr; + + funcptr = getservbyname_r; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + compat_cv_proto_getservbyname_r_macro="$macro" + break + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +compat_cv_proto_getservbyname_r_macro="not found" + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + done + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $compat_cv_proto_getservbyname_r_macro" >&5 +echo "${ECHO_T}$compat_cv_proto_getservbyname_r_macro" >&6 + if test -n "$compat_cv_proto_getservbyname_r_macro" -a "$compat_cv_proto_getservbyname_r_macro" != "not found" -a "$compat_cv_proto_getservbyname_r_macro" != "none"; then + CFLAGS="${CFLAGS} -D$compat_cv_proto_getservbyname_r_macro"; + fi + + echo "$as_me:$LINENO: checking for number of arguments to getservbyname_r" >&5 +echo $ECHO_N "checking for number of arguments to getservbyname_r... $ECHO_C" >&6 +if test "${compat_cv_getservbyname_r_args+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + +int +main () +{ + + struct servent sent; + char buf[10240]; + + getservbyname_r("telnet", "tcp", &sent, buf, sizeof(buf)); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + compat_cv_getservbyname_r_args=5 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + +int +main () +{ + + struct servent sent, *sp; + char buf[10240]; + + getservbyname_r("telnet", "tcp", &sent, buf, sizeof(buf), &sp); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + compat_cv_getservbyname_r_args=6 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + +int +main () +{ + + struct servent sent; + struct servent_data sdata; + + getservbyname_r("telnet", "tcp", &sent, &sdata); + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + compat_cv_getservbyname_r_args=4 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +compat_cv_getservbyname_r_args=no + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $compat_cv_getservbyname_r_args" >&5 +echo "${ECHO_T}$compat_cv_getservbyname_r_args" >&6 + if test "$compat_cv_getservbyname_r_args" != "no"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GETSERVBYNAME_R 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define GETSERVBYNAME_R_NUM_ARGS $compat_cv_getservbyname_r_args +_ACEOF + + if test "$compat_cv_getservbyname_r_args" != "6"; then + LIBOBJS="$LIBOBJS getservbyname_r.$ac_objext" + fi + else + { echo "$as_me:$LINENO: WARNING: unknown form of getservbyname_r - resulting libraries will not be thread-safe" >&5 +echo "$as_me: WARNING: unknown form of getservbyname_r - resulting libraries will not be thread-safe" >&2;} + fi + else + { echo "$as_me:$LINENO: WARNING: cannot find getservbyname_r - resulting libraries will not be thread-safe" >&5 +echo "$as_me: WARNING: cannot find getservbyname_r - resulting libraries will not be thread-safe" >&2;} + fi + + + +for ac_func in poll sigaction +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ +#ifdef __STDC__ +# include +#else +# include +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +cat >>confdefs.h <<\_ACEOF +#define NEED_SNPRINTF 1 +_ACEOF + + echo "$as_me:$LINENO: checking for working snprintf" >&5 +echo $ECHO_N "checking for working snprintf... $ECHO_C" >&6 +if test "${compat_cv_func_snprintf_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + compat_cv_func_snprintf_works=no + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include + +typedef struct { + int length; + char *test; + int retval; + char *result; +} test_t; + +const test_t tests[] = { + { 10, "12345678901234567890", 20, "123456789" }, +#if 0 + { 0, "12345678901234567890", 20, NULL }, + { -1, "12345678901234567890", -1, NULL }, +#endif + { 0, NULL, 0, NULL } +}; + +int main() { + char test1[1024]; + int i; + + for (i = 0; tests[i].test; i++) { + memset(test1, 'X', sizeof(test1)); + if ((snprintf(test1, tests[i].length, "%s", tests[i].test) + != tests[i].retval) || + (tests[i].result && strcmp(tests[i].result, test1))) + exit(1); + } + + exit(0); +} + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + compat_cv_func_snprintf_works=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +compat_cv_func_snprintf_works=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $compat_cv_func_snprintf_works" >&5 +echo "${ECHO_T}$compat_cv_func_snprintf_works" >&6 + if test "$compat_cv_func_snprintf_works" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SNPRINTF 1 +_ACEOF + + else + LIBOBJS="$LIBOBJS snprintf.$ac_objext" + fi + + + + +cat >>confdefs.h <<\_ACEOF +#define NEED_STRDUP 1 +_ACEOF + + echo "$as_me:$LINENO: checking for strdup" >&5 +echo $ECHO_N "checking for strdup... $ECHO_C" >&6 +if test "${ac_cv_func_strdup+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strdup (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ +#ifdef __STDC__ +# include +#else +# include +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strdup (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strdup) || defined (__stub___strdup) +choke me +#else +char (*f) () = strdup; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != strdup; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_strdup=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_strdup=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_strdup" >&5 +echo "${ECHO_T}$ac_cv_func_strdup" >&6 +if test $ac_cv_func_strdup = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STRDUP 1 +_ACEOF + +else + LIBOBJS="$LIBOBJS strdup.$ac_objext" + +fi + + + + + + +cat >>confdefs.h <<\_ACEOF +#define NEED_STRLCAT 1 +_ACEOF + + echo "$as_me:$LINENO: checking for strlcat" >&5 +echo $ECHO_N "checking for strlcat... $ECHO_C" >&6 +if test "${ac_cv_func_strlcat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strlcat (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ +#ifdef __STDC__ +# include +#else +# include +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strlcat (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strlcat) || defined (__stub___strlcat) +choke me +#else +char (*f) () = strlcat; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != strlcat; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_strlcat=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_strlcat=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_strlcat" >&5 +echo "${ECHO_T}$ac_cv_func_strlcat" >&6 +if test $ac_cv_func_strlcat = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STRLCAT 1 +_ACEOF + +else + LIBOBJS="$LIBOBJS strlcat.$ac_objext" + +fi + + + + + + +cat >>confdefs.h <<\_ACEOF +#define NEED_STRLCPY 1 +_ACEOF + + echo "$as_me:$LINENO: checking for strlcpy" >&5 +echo $ECHO_N "checking for strlcpy... $ECHO_C" >&6 +if test "${ac_cv_func_strlcpy+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strlcpy (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ +#ifdef __STDC__ +# include +#else +# include +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strlcpy (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strlcpy) || defined (__stub___strlcpy) +choke me +#else +char (*f) () = strlcpy; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != strlcpy; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_strlcpy=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_strlcpy=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_strlcpy" >&5 +echo "${ECHO_T}$ac_cv_func_strlcpy" >&6 +if test $ac_cv_func_strlcpy = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STRLCPY 1 +_ACEOF + +else + LIBOBJS="$LIBOBJS strlcpy.$ac_objext" + +fi + + + + + + +cat >>confdefs.h <<\_ACEOF +#define NEED_STRSEP 1 +_ACEOF + + echo "$as_me:$LINENO: checking for strsep" >&5 +echo $ECHO_N "checking for strsep... $ECHO_C" >&6 +if test "${ac_cv_func_strsep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strsep (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ +#ifdef __STDC__ +# include +#else +# include +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strsep (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strsep) || defined (__stub___strsep) +choke me +#else +char (*f) () = strsep; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != strsep; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_strsep=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_strsep=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_strsep" >&5 +echo "${ECHO_T}$ac_cv_func_strsep" >&6 +if test $ac_cv_func_strsep = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STRSEP 1 +_ACEOF + +else + LIBOBJS="$LIBOBJS strsep.$ac_objext" + +fi + + + + + + +echo "$as_me:$LINENO: checking for socket in -lsocket" >&5 +echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6 +if test "${ac_cv_lib_socket_socket+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char socket (); +int +main () +{ +socket (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_socket_socket=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_socket_socket=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6 +if test $ac_cv_lib_socket_socket = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSOCKET 1 +_ACEOF + + LIBS="-lsocket $LIBS" + +fi + + +echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 +echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6 +if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_nsl_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_nsl_gethostbyname=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6 +if test $ac_cv_lib_nsl_gethostbyname = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNSL 1 +_ACEOF + + LIBS="-lnsl $LIBS" + +fi + + +echo "$as_me:$LINENO: checking for crypt in -lcrypt" >&5 +echo $ECHO_N "checking for crypt in -lcrypt... $ECHO_C" >&6 +if test "${ac_cv_lib_crypt_crypt+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypt $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char crypt (); +int +main () +{ +crypt (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_crypt_crypt=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_crypt_crypt=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_crypt" >&5 +echo "${ECHO_T}$ac_cv_lib_crypt_crypt" >&6 +if test $ac_cv_lib_crypt_crypt = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCRYPT 1 +_ACEOF + + LIBS="-lcrypt $LIBS" + +fi + + + +# Check whether --enable-readline or --disable-readline was given. +if test "${enable_readline+set}" = set; then + enableval="$enable_readline" + +fi; +if test "$enable_readline" != "no"; then + + +for ac_header in readline/readline.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in readline/history.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + if test "$ac_cv_header_readline_readline_h" = "yes"; then + echo "$as_me:$LINENO: checking for library containing tputs" >&5 +echo $ECHO_N "checking for library containing tputs... $ECHO_C" >&6 +if test "${ac_cv_search_tputs+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_tputs=no +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tputs (); +int +main () +{ +tputs (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_tputs="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_tputs" = no; then + for ac_lib in termcap curses; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tputs (); +int +main () +{ +tputs (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_tputs="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_tputs" >&5 +echo "${ECHO_T}$ac_cv_search_tputs" >&6 +if test "$ac_cv_search_tputs" != no; then + test "$ac_cv_search_tputs" = "none required" || LIBS="$ac_cv_search_tputs $LIBS" + +fi + + +echo "$as_me:$LINENO: checking for rl_callback_handler_install in -lreadline" >&5 +echo $ECHO_N "checking for rl_callback_handler_install in -lreadline... $ECHO_C" >&6 +if test "${ac_cv_lib_readline_rl_callback_handler_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lreadline $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char rl_callback_handler_install (); +int +main () +{ +rl_callback_handler_install (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_readline_rl_callback_handler_install=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_readline_rl_callback_handler_install=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_readline_rl_callback_handler_install" >&5 +echo "${ECHO_T}$ac_cv_lib_readline_rl_callback_handler_install" >&6 +if test $ac_cv_lib_readline_rl_callback_handler_install = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBREADLINE 1 +_ACEOF + + LIBS="-lreadline $LIBS" + +fi + + fi + +fi + +# Check whether --enable-setuid-nph or --disable-setuid-nph was given. +if test "${enable_setuid_nph+set}" = set; then + enableval="$enable_setuid_nph" + +fi; +if test "$enable_setuid_nph" = "yes"; then + NPH_MODE=4555 +else + NPH_MODE=755 +fi + + + +# Check whether --with-mailmatches or --without-mailmatches was given. +if test "${with_mailmatches+set}" = set; then + withval="$with_mailmatches" + +else + with_mailmatches="alias:callsign" + +fi; + +cat >>confdefs.h <<_ACEOF +#define PH_DEFAULT_MAILMATCHES "${with_mailmatches}" +_ACEOF + + + + + + + + + + + if test -z "ph"; then + BUFFER_PREFIX="${PACKAGE_NAME}"; + else + BUFFER_PREFIX="ph"; + fi + + + BUFFER_DIR="buffer"; + + + ac_config_files="$ac_config_files buffer/${BUFFER_PREFIX}_buffer.h:buffer/buffer.h.in" + + ac_config_files="$ac_config_files buffer/${BUFFER_PREFIX}_buffer.c:buffer/buffer.c.in" + + + + + + + + + if test -z "ph"; then + MMGR_PREFIX="${PACKAGE_NAME}"; + else + MMGR_PREFIX="ph"; + fi + + + MMGR_DIR="mmgr"; + + + ac_config_files="$ac_config_files mmgr/${MMGR_PREFIX}_mmgr.h:mmgr/mmgr.h.in" + + ac_config_files="$ac_config_files mmgr/${MMGR_PREFIX}_mmgr.c:mmgr/mmgr.c.in" + + + ac_config_files="$ac_config_files Makefile lib/Makefile nph/Makefile doc/Makefile" + + ac_config_files="$ac_config_files postinstall" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by nph $as_me 1.2.3, which was +generated by GNU Autoconf 2.57. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +nph config.status 1.2.3 +configured by $0, generated by GNU Autoconf 2.57, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "buffer/${BUFFER_PREFIX}_buffer.h" ) CONFIG_FILES="$CONFIG_FILES buffer/${BUFFER_PREFIX}_buffer.h:buffer/buffer.h.in" ;; + "buffer/${BUFFER_PREFIX}_buffer.c" ) CONFIG_FILES="$CONFIG_FILES buffer/${BUFFER_PREFIX}_buffer.c:buffer/buffer.c.in" ;; + "mmgr/${MMGR_PREFIX}_mmgr.h" ) CONFIG_FILES="$CONFIG_FILES mmgr/${MMGR_PREFIX}_mmgr.h:mmgr/mmgr.h.in" ;; + "mmgr/${MMGR_PREFIX}_mmgr.c" ) CONFIG_FILES="$CONFIG_FILES mmgr/${MMGR_PREFIX}_mmgr.c:mmgr/mmgr.c.in" ;; + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; + "nph/Makefile" ) CONFIG_FILES="$CONFIG_FILES nph/Makefile" ;; + "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "postinstall" ) CONFIG_FILES="$CONFIG_FILES postinstall" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@EPKG@,$EPKG,;t t +s,@MKENCAP@,$MKENCAP,;t t +s,@ENCAP_DEFS@,$ENCAP_DEFS,;t t +s,@ENCAP_INSTALL_RULES@,$ENCAP_INSTALL_RULES,;t t +s,@ENCAP_INSTALL_TARGET@,$ENCAP_INSTALL_TARGET,;t t +s,@MKDIR@,$MKDIR,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@LN_S@,$LN_S,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@MORE@,$MORE,;t t +s,@VI@,$VI,;t t +s,@CPP@,$CPP,;t t +s,@EGREP@,$EGREP,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@NPH_MODE@,$NPH_MODE,;t t +s,@BUFFER_PREFIX@,$BUFFER_PREFIX,;t t +s,@BUFFER_DIR@,$BUFFER_DIR,;t t +s,@MMGR_PREFIX@,$MMGR_PREFIX,;t t +s,@MMGR_DIR@,$MMGR_DIR,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + + # Run the commands associated with the file. + case $ac_file in + postinstall ) chmod +x postinstall ;; + esac +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..4d1309a --- /dev/null +++ b/configure.ac @@ -0,0 +1,98 @@ +dnl ### Normal initialization. ###################################### +AC_INIT([nph], [1.2.3]) +AC_PREREQ([2.57]) +AC_CONFIG_AUX_DIR([autoconf]) +AC_CONFIG_HEADERS([config.h]) +AC_COPYRIGHT([[ +Copyright (c) 2000-2004 University of Illinois Board of Trustees +Copyright (c) 2000-2004 Mark D. Roth +All rights reserved. +]]) +AC_CONFIG_SRCDIR([lib/phclient.h]) +ENCAP_PKG([], [postinstall-encap], [postinstall-no-encap]) + + +dnl ### Set some option defaults. ################################### +if test -z "$CFLAGS"; then + CFLAGS="-O" +fi +MKDIR="mkdir -p -m 755" +AC_SUBST([MKDIR]) + + +dnl ### Check for compiler et al. ################################### +AC_PROG_CC +AC_PROG_RANLIB +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PATH_PROG([MORE], [more]) +AC_DEFINE_UNQUOTED([MORE], ["${ac_cv_path_MORE}"], [Path to more.]) +AC_PATH_PROG([VI], [vi]) +AC_DEFINE_UNQUOTED([VI], ["${ac_cv_path_VI}"], [Path to vi.]) + + +dnl ### Compiler characteristics. ################################## +AC_AIX +AC_C_CONST + + +dnl ### Checks for header files. ################################### +AC_HEADER_STDC +AC_CHECK_HEADERS([arpa/aixrcmds.h crypt.h paths.h unistd.h sys/poll.h]) +if test "$ac_cv_header_sys_poll_h" != "yes"; then + AC_CHECK_HEADERS([sys/select.h]) +fi + + +dnl ### Checks for needed functions. ############################### +PSG_MODULE([compat]) +COMPAT_FUNC_GETHOSTBYNAME_R +COMPAT_FUNC_GETPWUID_R +COMPAT_FUNC_GETSERVBYNAME_R +AC_CHECK_FUNCS([poll sigaction]) +COMPAT_FUNC_SNPRINTF +COMPAT_FUNC_STRDUP +COMPAT_FUNC_STRLCAT +COMPAT_FUNC_STRLCPY +COMPAT_FUNC_STRSEP + + +dnl ### Check for libraries. ####################################### +AC_CHECK_LIB([socket], [socket]) +AC_CHECK_LIB([nsl], [gethostbyname]) +AC_CHECK_LIB([crypt], [crypt]) + + +dnl ### Optional features. ######################################### +AC_ARG_ENABLE([readline], + [ --disable-readline Do not use the readline library in the nph client]) +if test "$enable_readline" != "no"; then + PSG_LIB_READLINE +fi + +AC_ARG_ENABLE([setuid-nph], + [ --enable-setuid-nph Install nph setuid-root (for email authentication)]) +if test "$enable_setuid_nph" = "yes"; then + NPH_MODE=4555 +else + NPH_MODE=755 +fi +AC_SUBST([NPH_MODE]) + +AC_ARG_WITH([mailmatches], + [ --with-mailmatches=LIST Set default mailmatch fields], + [], + [with_mailmatches="alias:callsign"] +) +AC_DEFINE_UNQUOTED([PH_DEFAULT_MAILMATCHES], ["${with_mailmatches}"], + [Default mailmatch fields]) + + +dnl ### Create output files. ####################################### +PSG_MODULE([buffer], [ph]) +PSG_MODULE([mmgr], [ph]) +AC_CONFIG_FILES([Makefile lib/Makefile nph/Makefile doc/Makefile]) +AC_CONFIG_FILES([postinstall], [chmod +x postinstall]) +AC_OUTPUT + diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..6307254 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,120 @@ +# @configure_input@ + +### Path settings +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +mandir = @mandir@ + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ + +@ENCAP_DEFS@ + +### Installation programs and flags +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +LN_S = @LN_S@ +MKDIR = @MKDIR@ +@SET_MAKE@ + + +### Makefile rules - no user-servicable parts below + +PH_OPEN_SO = ph_close +PH_LOGIN_SO = ph_logout \ + ph_suser \ + ph_passwd \ + ph_whoami +PH_CHANGE_SO = ph_add \ + ph_delete +PH_GET_FIELDINFO_SO = ph_retrieve_fieldinfo \ + ph_decode_field_attributes \ + ph_fieldinfo_iterate +PH_ID_SO = ph_status ph_external +PH_GET_OPTION_SO = ph_retrieve_options \ + ph_set_option ph_option_iterate +PH_GET_SITEINFO_SO = ph_retrieve_siteinfo \ + ph_siteinfo_iterate +PH_QUERY_SO = ph_free_entries +PH_RFD_SO = ph_wfd +PH_EMAIL_RESOLVE_SO = ph_advertised_email +PH_WWW_RESOLVE_SO = ph_advertised_www +PH_SET_SENDHOOK_SO = ph_set_recvhook \ + ph_set_hookdata +PH_ENCODE_SELECTOR_SO = ph_free_selectors +PH_SERVERLIST_ADD_SO = ph_serverlist_iterate \ + ph_serverlist_merge \ + ph_free_serverlist + +all: + +.PHONY: clean distclean install + +clean: + +distclean: clean + rm -f Makefile + +install: + ${MKDIR} ${DESTDIR}${mandir}/man1 + ${INSTALL_DATA} ${srcdir}/nph.1 ${DESTDIR}${mandir}/man1 + ${MKDIR} ${DESTDIR}${mandir}/man3 + ${INSTALL_DATA} ${srcdir}/ph_open.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_OPEN_SO}; do \ + echo ".so man3/ph_open.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_login.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_LOGIN_SO}; do \ + echo ".so man3/ph_login.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_change.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_CHANGE_SO}; do \ + echo ".so man3/ph_change.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_get_fieldinfo.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_GET_FIELDINFO_SO}; do \ + echo ".so man3/ph_get_fieldinfo.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_id.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_ID_SO}; do \ + echo ".so man3/ph_id.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_get_option.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_GET_OPTION_SO}; do \ + echo ".so man3/ph_get_option.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_get_siteinfo.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_GET_SITEINFO_SO}; do \ + echo ".so man3/ph_get_siteinfo.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_query.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_QUERY_SO}; do \ + echo ".so man3/ph_query.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_rfd.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_RFD_SO}; do \ + echo ".so man3/ph_rfd.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_email_resolve.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_EMAIL_RESOLVE_SO}; do \ + echo ".so man3/ph_email_resolve.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_www_resolve.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_WWW_RESOLVE_SO}; do \ + echo ".so man3/ph_www_resolve.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_set_sendhook.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_SET_SENDHOOK_SO}; do \ + echo ".so man3/ph_set_sendhook.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_encode_selector.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_ENCODE_SELECTOR_SO}; do \ + echo ".so man3/ph_encode_selector.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + ${INSTALL_DATA} ${srcdir}/ph_serverlist_add.3 ${DESTDIR}${mandir}/man3 + for i in ${PH_SERVERLIST_ADD_SO}; do \ + echo ".so man3/ph_serverlist_add.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ + done + diff --git a/doc/nph.1 b/doc/nph.1 new file mode 100644 index 0000000..a4d817d --- /dev/null +++ b/doc/nph.1 @@ -0,0 +1,375 @@ +.TH nph 1 "Oct 2002" "University of Illinois" "Directory Services" +.SH NAME +nph \- new PH client +.SH SYNOPSIS +\fBnph [options] [selectors [return field1 ...] [@domain]]\fP +.br +\fBnph [options]\fP +.SH VERSION +This man page documents version 1.2 of \fBnph\fP. +.SH DESCRIPTION +\fBnph\fP is a new PH client. It uses the \fIlibphclient\fP API and +contains a number of new features and usability improvements over the +old PH client. +.SH STARTUP +If \fBnph\fP is invoked with non-option arguments, they are interpreted +as a query command. \fBnph\fP will perform the query and exit immediately. +Otherwise, \fBnph\fP will start up in interactive mode and accept commands +from \fIstdin\fP. + +To determine what PH server to connect to, \fBnph\fP looks in three places. +If the \fI-s\fP commandline option (described below) is given, the +specified server is used. Otherwise, if the \fIPH_SERVER\fP environment +variable is set, its value is used. Finally, if neither of the previous +sources specify a server, the file \fI/etc/ph_server\fP is +read if it exists. If no server is found, \fBnph\fP will not start. + +Once a server is selected, \fBnph\fP then searches for a startup +file containing a list of commands to be automatically executed. +If the \fI-f\fP commandline option (described below) is given, it +specifies the name of the startup file to use. Otherwise, it looks +for the file \fI${HOME}/.nphrc.server\fP, where \fIserver\fP is the +name of the selected server. If that file does not exist, it looks for +\fI${HOME}/.nphrc\fP. Lastly, if neither of the previous files exist, +it reads \fI/etc/nphrc\fP. +.SH COMMANDLINE OPTIONS +.TP +.B -c +Enable "confirmedits" option (see below). +.TP +.B -C +Do not read the system-wide \fInphrc\fP or the user's \fI${HOME}/.nphrc\fB +file. +.TP +.B -d +Enable "debug" option (see below). +.TP +.B -f rcfile +Tells \fBnph\fP to use \fIrcfile\fP as the startup file. +.TP +.B -F "field1 field2 ..." +Set the "returnfields" option to "field1 field2 ..." (see below). +.TP +.B -m +Disable the "usepager" option (see below). +.TP +.B -r +Disable the "canonicaladdrs" option (see below). +.TP +.B -R +Use a reserved port on the local end of the connection. (This will only +succeed if \fBnph\fP is running as \fBroot\fP.) +.TP +.B -s server[:port] +Specify which PH server (and optionally, what port) to connect to. If +the port is not given, the port corresponding to the \fIcsnet-ns\fP service +is used (usually port 105). +.SH INTERACTIVE MODE +The following commands are supported in interactive mode: +.TP +.B id text +Identify yourself for the PH server's logs. Users do not normally need +to use this command. +.TP +.B external +Mark the session as external, or non-local. This prevents the user from +accessing fields marked with the \fILocalPub\fP attribute. +.TP +.B suser alias +Assume the privileges of \fIalias\fP. Only heros may execute this command. +.TP +.B login alias +Log in to the server as user \fIalias\fP. The \fIlogin\fP command uses +the authentication mechanism indicated by the \fIauthtype\fP option. +.TP +.B logout +Log out of the PH server. +.TP +.B passwd +Change the password of the currently logged-in user. +.TP +.B password +Synonym for \fIpasswd\fP. +.TP +.B option [option=value] +With no arguments, displays the current value of all client-side options. +If arguments are given, the \fIoption\fP command sets the given option to +the given value. See below for more information on options. +.TP +.B switch +Synonym for \fIoption\fP. +.TP +.B source file +Read and executes commands from \fIfile\fP. +.TP +.B . +Synonym for \fIsource\fP. +.TP +.B < +Synonym for \fIsource\fP. +.TP +.B help [command] +Displays a one-line help message for \fIcommand\fP. If no arguments are given, +the \fIhelp\fP command displays information for all valid commands. +.TP +.B ? +Synonym for \fIhelp\fP. +.TP +.B quit +Disconnect from the PH server and exit \fInph\fP. +.TP +.B bye +Synonym for \fIquit\fP. +.TP +.B exit +Synonym for \fIquit\fP. +.TP +.B stop +Synonym for \fIquit\fP. +.TP +.B whoami +Displays the currently logged-in username, plus the name of the server. +.TP +.B status +Prints the PH server's status information. +.TP +.B motd +Synonym for \fIstatus\fP. +.TP +.B set [option[=value]] +Without arguments, displays the current value of all server-side options. +With arguments, it sets the value of the given option. If the value is +not specified, the default value is "on". +.TP +.B siteinfo +Displays the site-specific configuration list from the PH server. +.TP +.B connect host[:port] +Connects to the specified server and disconnects from the currently-connected +server. +.TP +.B serveradd server [site] +Adds a server and corresponding site name to the list of known PH servers. +.TP +.B listservers [domain] +Displays the list of known PH servers. If \fIdomain\fP is listed, +only servers in that domain will be displayed. \fIdomain\fP must be +composed of at least two '.'-delimited portions of the server name +to search for (e.g., "uiuc.edu" instead of "edu"). +.TP +.B fields [field] +Displays information about the fields supported by the server. Without +arguments, it displays all supported fields. With arguments, it displays +only the listed fields. +.TP +.B edit field [alias] +Edit the named field using the external editor specified by the +\fIeditor\fP client option. The user must be logged in before using +this command. + +If \fIalias\fP is given, edit the field from the entry for \fIalias\fP; +otherwise, edit the field from the logged-in user's entry. To edit +a field from some entry other than that of the logged-in user, the +logged-in user must either have hero privileges or must be allowed to +edit the specified entry by proxy. +.TP +.B query selectors... [return fields...] [@domain] +Retrieve entries from the PH server. The \fIselectors\fP specify the +entries to retrieve (as described in \fISELECTING ENTRIES\fP below). + +The optional \fIreturn\fP clause specifies which fields of the matching +entries should be returned. If no \fIreturn\fP clause is given and the +\fIreturnfields\fP option is unset, only fields marked with the +\fIDefault\fP attribute will be returned by the server. + +If the \fI@domain\fP argument is given, \fBnph\fP will attempt to find +the PH server for the specified domain. If found, the query will be +sent to that server, rather than the current server. Once the query is +complete, the connection to the original server will be resumed without +interruption. +.TP +.B change selectors... make|force assignments... +Change entries on the server. The user must be logged in before using +this command and must have permission to change the selected entry or +entries. The \fIselectors\fP specify the entries to which the changes +should be applied. The \fIassignments\fP specify the changes to apply +to all matching entries. + +The \fIforce\fP keyword allows the user to make a non-encrypted change +to fields marked with the \fIEncrypt\fP keyword. Otherwise, all +changes will normally use the \fImake\fP keyword instead. +.TP +.B make assignments... +This is a short form of the \fIchange\fP command which operates on the +entry of the logged-in user. +.TP +.B delete selectors... +Delete entries. The user must be logged in and have hero privileges in +order to perform this operation. +.TP +.B add assignments... +Adds an entry with the data given in \fIassignments\fP. The user must be +logged in and have hero privileges in order to perform this operation. +.TP +.B me +A short form of the \fIquery\fP command which displays all fields of the +currently logged-in user's entry. +.TP +.B resolve_email user +Returns the PH-resolved email address for \fIuser\fP. +.TP +.B public_email alias +Returns the advertised email address for \fIalias\fP. +.TP +.B resolve_www user +Returns the PH-resolved URL for \fIuser\fP. +.TP +.B public_www alias +Returns the advertised URL for \fIalias\fP. +.SH SELECTING ENTRIES +The \fIquery\fP, \fIchange\fP, and \fIdelete\fP commands select the entries +which they operate on based on \fIselectors\fP. The selectors are +a list of one or more criteria which are used by the server to select +entries. When multiple selectors are listed, only entries which +match all of the selectors will be selected. + +Each selector is composed of a value, preceded by an optional field +and operator. If the field and operator are given, the selector matches +entries whose data for the given field matches the given value. If no +field and operator are given, the default fields are checked, which are +usually "name" and "nickname". The only universally understood operator +is '=', but some servers support '~', '<', and '>'. + +Certain special symbols, called "wildcard" characters, can be used in +the value if the exact spelling is unknown. The '*' character is used in +place of zero or more characters, the '+' character in place of one or more +unknown characters, and the '?' character can be used when exactly one +character is unknown. In addition, if the unknown character can be one +of a limited set this can be specified by surrounding the set with +brackets, e.g., [ei] means that in that place an 'e' or an 'i' would match. + +Here are a few examples of selectors: +.TP +.B alias=smith +Select entries whose \fIalias\fP field is set to \fIsmith\fP. +.TP +.B john smith +Select entries whose \fIname\fP or \fInickname\fP fields match \fIjohn\fP +and \fIsmith\fP. +.TP +.B alias=smi* name=john +Select entries whose \fIalias\fP field starts with \fIsmi\fP and whose +\fIname\fP or \fInickname\fP fields contain \fIjohn\fP. +.PP +Many servers apply limits on computation time and or on the number of +entries returned, to prevent mailing list generation and/or to minimize +performance problems. Therefore, it is often advisable to be as specific +as possible in identifying an entry. +.SH ASSIGNING VALUES +The \fIchange\fP, \fImake\fP, and \fIadd\fP commands set specific fields +to specific values on the server based on a list of one or more +\fIassignments\fP. All of the listed assignments are performed on +all of the selected entries. + +Each assignment is composed of a field name, the '=' character, and a +value. This syntax is similar to the \fIselector\fP syntax, but it is +somewhat more rigid. Assignments cannot omit the field name, cannot +use operators other then '=', and cannot use wildcard characters. + +Here are a few examples of assignments: +.TP +.B email=j-smith@students.uiuc.edu +Sets the \fIemail\fP field to \fIj-smith@students.uiuc.edu\fP. +.TP +.B www=http://www.students.uiuc.edu/~j-smith/ +Sets the \fIwww\fP field to \fIhttp://www.students.uiuc.edu/~j-smith/\fP. +.SH CLIENT OPTIONS +Client options are settable using the \fIoption\fP command described +above. The following client options are supported. The default value +is listed in parenthesis next to each option. +.TP +.B authtype (password) +Defines the authentication mechanism used to login to the PH server. +Supported mechanisms are \fIpassword\fP, \fIemail\fP, and \fIclear\fP. +(The \fIclear\fP method is not recommended because it is inherently +insecure.) +.TP +.B confirmedits (off) +This is a boolean option. If on, \fBnph\fP will ask for confirmation +before applying the change during an \fIedit\fP command. +.TP +.B debug (off) +This is a boolean option. If on, all communication between the client +and server will be displayed. +.TP +.B defaultfield (not set by default) +Defines the default field for field selectors which do not specify a field. +If unset, the default field configured on the server is used (usually +\fIname\fP and \fInickname\fP). +.TP +.B editor ($EDITOR) +Defines the editor to use for \fIedit\fP commands. If the first character +is a '$', the value is obtained from the named environment variable. +.TP +.B pager ($PAGER) +Defines an external pager program (such as \fImore\fP or \fIless\fP) to +use for \fIquery\fP, \fIme\fP, \fIfields\fP, and \fIstatus\fP commands. +If the first character is a '$', the value is obtained from the named +environment variable. +.TP +.B returnfields (not set by default) +Set the list of fields which are returned for queries which do not +have a \fIreturn\fP clause. For multiple fields, specify a quoted +string of space-delimited field names. If this option is not set and no +\fIreturn\fP clause is given, only fields marked with the \fIDefault\fP +attribute are returned by the server. +.TP +.B server (none) +Defines which PH server (and optionally, which port) to connect to. +Changing this setting will imediately disconnect from the current server and +connect to the newly-specified server. +.TP +.B canonicaladdrs (off) +This is a boolean option. If on, advertised addresses are printed for the +\fIemail\fP and \fIwww\fP fields instead of the actual values. +.TP +.B usepager (on) +This is a boolean option. If on, the pager specified by the \fIpager\fP +option will be used for the \fIquery\fP, \fIme\fP, \fIfields\fP, and +\fIstatus\fP commands. Otherwise, the output of these commands will be +sent to \fIstdout\fP. +.TP +.B usereservedport (off) +Connect to the PH server from a port below 1024. This is necessary in +order to use the \fIemail\fP authentication method (described above). +However, \fBnph\fP must be running as \fIroot\fP in order to do this, +which is not recommended. +.SH STARTUP FILES +On startup, \fBnph\fP will first read the \fI/etc/nphrc\fP file, +and then the invoking user's \fI${HOME}/.nphrc\fP file. These files can +be used to set defaults for \fBnph\fP options. The file must consist of +assignments of the form \fIoption=value\fP, one per line. Blank lines +are ignored, as is any text on the same line following a '#' character. + +\fBnph\fP will also read the \fI/etc/ph_server\fP file at +startup for a default list of known PH servers at different sites. +.SH REDIRECTING OUTPUT +The standard shell expressions ">", ">>", and "|" can be used at the end of +any \fBnph\fP command to redirect the output to a file or program. If the +output of a \fIquery\fP, \fIme\fP, \fIfields\fP, or \fIstatus\fP command +is redirected, it is not piped to the pager regardless of the setting of the +\fIusepager\fP option. +.SH FILES +\fI/etc/nphrc\fP +.br +\fI/etc/ph_server\fP +.br +\fI${HOME}/.nphrc\fP +.br +\fI${HOME}/.nphrc.*\fP +.SH SEE ALSO +\fBph_open\fP(3) +.br +The \fBnph\fP Homepage (\fIhttp://www.feep.net/nph/\fP) +.SH AUTHOR +Mark D. Roth diff --git a/doc/ph_change.3 b/doc/ph_change.3 new file mode 100644 index 0000000..44a24cd --- /dev/null +++ b/doc/ph_change.3 @@ -0,0 +1,51 @@ +.TH ph_change 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_change, ph_add, ph_delete \- modify data on PH server +.SH SYNOPSIS +.B #include +.P +.BI "int ph_change(PH *" ph ", struct ph_fieldselector " query "[]," +.BI "struct ph_fieldselector " change "[], int " flags ");" +.br +.BI "int ph_add(PH *" ph ", struct ph_fieldselector " fields "[]);" +.br +.BI "int ph_delete(PH *" ph ", struct ph_fieldselector " query "[]);" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +The \fBph_change\fP() function changes data on the PH server associated +with the \fBPH\fP handle \fIph\fP. The \fIquery\fP argument selects which +entries will be changed in the same manner as for the \fBph_query\fP() +function. The \fIchange\fP argument is an array of changes to make +on the server. Each element of the array is a structure with three +fields: \fIfield\fP (the name of the field to modify encoded as a +string), \fIoperation\fP (a character value which must be set to '='), +and \fIvalue\fP (a string value to set the field to). The last element +in the array must be set to all zeros. If the \fIflags\fP argument is +set to \fBPH_CHANGE_FORCE\fP, the "force" clause is used instead of the +"make" clause when sending the change command to the server. + +The \fBph_add\fP() function adds a new PH entry whose contents are specified +in \fIfields\fP. This data is encoded just as the \fIchange\fP argument +to \fBph_change\fP() above. + +The \fBph_delete\fP() function deletes entries from the PH server. The +\fIquery\fP argument selects which entries will be deleted in the same +manner as for the \fBph_query\fP() function. +.SH RETURN VALUE +On success, the \fBph_change\fP() and \fBph_delete\fP() functions return +the number of entries changed or deleted, or \fIPH_ERR_DATAERR\fP if the +supplied field data is invalid. + +All of the functions described here return \fIPH_ERR_NOTLOG\fP if no user +is logged in, and \fIPH_ERR_READONLY\fP if the server is in read-only +mode. On error, they return -1 and set \fIerrno\fP. +.SH ERRORS +The functions describe here will fail with \fBEINVAL\fP if they receive +an unexpected response code from the server. In addition, they may fail +with any error from the functions \fIread\fP() or \fIwrite\fP(). +.SH SEE ALSO +.BR read (2), +.BR write (2), +.BR ph_query (3), +.BR ph_open (3) diff --git a/doc/ph_email_resolve.3 b/doc/ph_email_resolve.3 new file mode 100644 index 0000000..1bda858 --- /dev/null +++ b/doc/ph_email_resolve.3 @@ -0,0 +1,56 @@ +.TH ph_email_resolve 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_email_resolve, ph_advertised_email \- determine PH-redirected email addresses +.SH SYNOPSIS +.B #include +.P +.BI "int ph_email_resolve(PH *" ph ", char *" user "," +.BI "char *" fields ", char **" real_email ");" +.br +.BI "int ph_advertised_email(PH *" ph ", char *" alias "," +.BI "int " confirm_alias ", char **" advertised_email ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +The \fBph_email_resolve\fP() function resolves the email address whose +user portion is \fIuser\fP. The \fIreal_email\fP argument is set to +point to a dynamically-allocated string containing the resolved email +address. This memory must be later freed by the calling application. + +The \fIfields\fP argument is a string containing a space- or +colon-delimited list of field names to match entries on. If \fIfields\fP +is \fBNULL\fP or points to an empty string, \fBph_email_resolve\fP() uses +the field list specified by the server's \fImailmatches\fP \fBsiteinfo\fP +field. If the server doesn't support the \fImailmatches\fP field, +\fBph_email_resolve\fP() falls back to the default list, which is +"alias:callsign". + +The \fBph_email_resolve\fP() function returns the email address found in +the field specified by the server's \fImailbox\fP \fBsiteinfo\fP field. +This is typically set to \fIemail\fP, which means that the email address +will be found in the user's \fIemail\fP field. + +The \fBph_advertised_email\fP() function determines the advertised +email address for the user whose alias is \fIalias\fP. If \fIconfirm_alias\fP +is set, the entry for \fIalias\fP is looked up to make sure it exists. The +\fIadvertised_email\fP argument is set to point to a dynamically-allocated +string containing the advertised email address. This memory must later +be freed by the calling application. +.SH RETURN VALUE +These functions return 0 on success, \fIPH_ERR_NOMATCH\fP if a single matching +entry cannot be found, and \fIPH_ERR_DATAERR\fP if the query is invalid. +On error, they return -1 and set \fIerrno\fP. + +In addition, \fBph_email_resolve\fP() returns \fIPH_ERR_DATAERR\fP if a single +matching entry is found but contains no \fIemail\fP field. +.SH ERRORS +These functions will fail with \fBEINVAL\fP if the server does +not support the \fImailbox\fP or \fImailfield\fP siteinfo entries, +or if they receive an unexpected response code from the server. +In addition, they may fail with any error from the functions \fIread\fP() +or \fIwrite\fP(). +.SH SEE ALSO +.BR read (2), +.BR write (2), +.BR ph_open (3), +.BR ph_siteinfo (3) diff --git a/doc/ph_encode_selector.3 b/doc/ph_encode_selector.3 new file mode 100644 index 0000000..ba47d1d --- /dev/null +++ b/doc/ph_encode_selector.3 @@ -0,0 +1,43 @@ +.TH ph_encode_selector 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_encode_selector, ph_free_selectors \- retrieve data from a PH server +.SH SYNOPSIS +.B #include +.P +.BI "int ph_encode_selector(char *" string ", int " requirefield "," +.BI "int *" lastindex ", struct ph_fieldselector **" selectors ");" +.br +.BI "void ph_free_selectors(struct ph_fieldselector *" selectors ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +The \fBph_encode_selector\fP() function is a utility function for +text-based applications which need to convert field specifiers from +a string format into an array of \fIph_fieldselector\fP structures. + +The \fIstring\fP argument is a text string consisting of an optional +field name and operator, as well as a mandantory value. The +\fIrequirefield\fP argument indicates whether the field portion +of \fIstring\fP is required. + +The \fIselectors\fP argument is a pointer to a dynamically-allocated +array of \fIph_fieldselector\fP structures. The \fIlastindex\fP +argument is a pointer to an integer which keeps track of the size +of the \fIselectors\fP array. + +Successive calls to \fBph_encode_selector\fP() add the selector encoded in +\fIstring\fP to the array pointed to by \fIselectors\fP. Before calling +\fBph_encode_selector\fP() for the first time on a given array, the caller +should initialize \fIselectors\fP to \fBNULL\fP and \fIlastindex\fP to 0. + +The \fBph_free_selectors\fP() function is used to free memory allocated +by \fBph_encode_selector\fP() for the \fIselectors\fP array. +.SH RETURN VALUE +On success, the \fBph_encode_selector\fP() function returns 0. On error, it +returns -1 and sets \fIerrno\fP. +.SH ERRORS +If the \fIrequirefield\fP argument is non-zero and \fIstring\fP does +not include the field name and operator, \fBph_encode_selector\fP() +returns -1 and sets \fIerrno\fP to \fBEINVAL\fP. +.SH SEE ALSO +.BR ph_query (3) diff --git a/doc/ph_get_fieldinfo.3 b/doc/ph_get_fieldinfo.3 new file mode 100644 index 0000000..5998a30 --- /dev/null +++ b/doc/ph_get_fieldinfo.3 @@ -0,0 +1,79 @@ +.TH ph_get_fieldinfo 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_get_fieldinfo, ph_retrieve_fieldinfo, ph_fieldinfo_iterate, ph_decode_field_attributes \- access field information from PH server +.SH SYNOPSIS +.B #include +.P +.BI "int ph_get_fieldinfo(PH *" ph ", char *" fieldname "," +.BI "struct ph_fieldinfo **" fieldinfo ");" +.br +.BI "int ph_retrieve_fields(PH *" ph ");" +.br +.BI "void ph_decode_field_attributes(unsigned long " bitmask "," +.BI "char *" buf ", int " bufsize ");" +.br +.BI "int ph_fieldinfo_iterate(PH *" ph ", struct ph_fieldinfo **" fieldinfo ");" +.br +.BI "void ph_free_fieldinfo(PH *" ph ");" +.br +.BI "int ph_is_fieldinfo_cached(PH *" ph ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +These functions allow the caller to access the field list from the PH +server associated with the \fBPH\fP handle \fIph\fP. The information +for a given field is encoded as a \fIstruct ph_fieldinfo\fP, which includes +the fields \fIname\fP (the field's name), \fIid\fP (the field's numeric ID), +\fImax_size\fP (the maximum size of the field), \fIdescription\fP (a text +string describing the field), and \fIattrib\fP (a bitmask of attributes +associated with the field). + +The \fBph_retrieve_fieldinfo\fP() function retrieves the field list from +the server associated with \fIph\fP and caches it locally. If the field +list is already cached before the call to \fBph_retrieve_fieldinfo\fP(), +it returns successfully without doing anything. + +The \fBph_free_fieldinfo\fP() function frees the memory associated with +the locally-cached field list. A subsequent call to +\fBph_retrieve_fieldinfo\fP() will reload the cache from the server. + +The \fBph_is_fieldinfo_cached\fP() macro determines whether or not the +field list is cached locally. + +The \fBph_get_fieldinfo\fP() function sets \fIfieldinfo\fP to point to +the \fIph_fieldinfo\fP structure describing \fIfieldname\fP. If the +field list has not been retrieved from the server, +\fBph_retrieve_fieldinfo\fP() is called. + +The \fBph_fieldinfo_iterate\fP() function allows the calling application +to iterate through the entire field list by setting \fIfieldinfo\fP to +the next entry at each call. To begin at the beginning of the list, +the caller must initialize \fIfieldinfo\fP to \fBNULL\fP. + +The \fBph_decode_field_attributes\fP() function generates a text representation +of the attributes set in \fIbitmask\fP. It writes the text string to the +buffer of size \fIbufsize\fP pointed to by \fIbuf\fP. +.SH RETURN VALUE +The \fBph_retrieve_fieldinfo\fP() function returns 0 on success, or -1 on error +and sets \fIerrno\fP. + +The \fBph_is_fieldinfo_cached\fP() macro returns 1 if the field list is +cached locally, or 0 otherwise. + +The \fBph_fieldinfo_iterate\fP() function returns 1 when field information +is returned, or 0 when there are no more fields. On error, it returns +-1 and sets \fIerrno\fP. + +The \fBph_get_fieldinfo\fP() function returns 0 on success, \fIPH_ERR_DATAERR\fP if +\fIfieldname\fP is not found. On error, it returns -1 and sets errno. +.SH ERRORS +The \fBph_retrieve_fieldinfo\fP() and \fBph_get_fieldinfo\fP() functions +will fail with \fBEINVAL\fP if they receive an unexpected response code +from the server. + +The \fBph_retrieve_fieldinfo\fP() function may fail with any error from the +functions \fIread\fP() or \fIwrite\fP(). +.SH SEE ALSO +.BR read (2), +.BR write (2), +.BR ph_open (3) diff --git a/doc/ph_get_option.3 b/doc/ph_get_option.3 new file mode 100644 index 0000000..6231e62 --- /dev/null +++ b/doc/ph_get_option.3 @@ -0,0 +1,72 @@ +.TH ph_get_option 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_get_option, ph_retrieve_options, ph_set_option, ph_option_iterate \- show and set PH server options +.SH SYNOPSIS +.B #include +.P +.BI "int ph_get_option(PH *" ph ", char *" option "," +.BI "char **" setting ");" +.br +.BI "int ph_retrieve_options(PH *" ph ");" +.br +.BI "int ph_set_option(PH *" ph ", char *" option "," +.BI "char *" setting ");" +.br +.BI "int ph_option_iterate(PH *" ph ", struct ph_option **" svropt ");" +.br +.BI "void ph_free_options(PH *" ph ");" +.br +.BI "int ph_is_optionlist_cached(PH *" ph ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +These functions allow the caller to access the list of options supported +by the PH server associated with the \fBPH\fP handle \fIph\fP. Each +option is represented as a \fIstruct ph_option\fP, which contains the +fields \fIoption\fP and \fIsetting\fP. + +The \fBph_retrieve_options\fP() function retrieves the option list from +the PH server to be cached locally. If the option list is already cached +locally, the call will return successfully without doing anything. + +The \fBph_is_optionlist_cached\fP() macro determines if the option list +is currently cached locally. + +The \fBph_free_options\fP() function clears the local option list cache. +A subsequent call to \fBph_retrieve_options\fP() will reload the option +list from the server. + +The \fBph_get_option\fP() function sets the \fIsetting\fP argument to point to +the current value of the option named \fIoption\fP. It automatically calls +\fBph_retrieve_options\fP() if the option list is not cached locally. + +The \fBph_set_option\fP() function sets the value of \fIoption\fP to +\fIsetting\fP. + +The \fBph_option_iterate\fP() function allows the caller to iterate +through all server options by setting \fIsvropt\fP to point to the next +option at each successive call. To begin at the beginning of the list, +the caller initializes \fIsvropt\fP to \fBNULL\fP. +.SH RETURN VALUE +The \fBph_retrieve_options\fP() function returns 0 on success, or -1 on error +and sets \fIerrno\fP. + +The \fBph_is_optionlist_cached\fP() macro returns 1 if the option list is +cached locally, or 0 otherwise. + +The \fBph_get_option\fP() and \fBph_set_option\fP() functions return 0 on +success, or -1 on error, or \fIPH_ERR_DATAERR\fP if \fIoption\fP is not found. + +The \fBph_option_iterate\fP() function returns 1 when an option is returned, +or 0 when the end of the list has been reached. On error, it returns -1 +and sets \fIerrno\fP. +.SH ERRORS +The \fBph_get_options\fP() function will fail with \fBEINVAL\fP if it +receives an unexpected response code from the server. + +The \fBph_get_options\fP() function may fail with any error from the functions +\fIread\fP() or \fIwrite\fP(). +.SH SEE ALSO +.BR read (2), +.BR write (2), +.BR ph_open (3) diff --git a/doc/ph_get_siteinfo.3 b/doc/ph_get_siteinfo.3 new file mode 100644 index 0000000..1f042fd --- /dev/null +++ b/doc/ph_get_siteinfo.3 @@ -0,0 +1,68 @@ +.TH ph_get_siteinfo 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_retrieve_siteinfo, ph_get_siteinfo, ph_siteinfo_iterate \- access site-specific information from PH server +.SH SYNOPSIS +.B #include +.P +.BI "int ph_get_siteinfo(PH *" ph ", char *" info "," +.BI "char **" data ");" +.br +.BI "int ph_retrieve_siteinfo(PH *" ph ");" +.br +.BI "int ph_siteinfo_iterate(PH *" ph ", struct ph_siteinfo **" siteinfo ");" +.br +.BI "void ph_free_siteinfo(PH *" ph ");" +.br +.BI "int ph_is_siteinfo_cached(PH *" ph ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +These functions allow the caller to access the list of site-specific +settings from the PH server associated with the \fBPH\fP handle \fIph\fP. +Site-specific settings are represented as \fIph_siteinfo\fP structures, +which contain the following fields: \fIinfo\fP (the name of the field, +encoded as a string) and \fIdata\fP (the string encoding of the data +contained in the field). + +The \fBph_retrieve_siteinfo\fP() function retrieves the siteinfo list +from the PH server to be cached locally. If the siteinfo data is already +cached locally, the function returns successfully without doing anything. + +The \fBph_free_siteinfo\fP() function clears the local siteinfo cache. +A subsequent call to \fBph_retrieve_siteinfo\fP() will reload the siteinfo +data from the server. + +The \fBph_is_siteinfo_cached\fP() macro determines whether or not the +siteinfo data is cached locally. + +The \fBph_get_siteinfo\fP() function sets \fIdata\fP to point to the value +of the siteinfo field named by \fIinfo\fP. It automatically calls +\fBph_retrieve_siteinfo\fP() if the siteinfo data is not cached locally. + +The \fBph_siteinfo_iterate\fP() function allows the caller to cycle +through the list of siteinfo entries by setting \fIsiteinfo\fP to +point to the next entry on each successive call. To start at the beginning +of the list, the caller initializes \fIsiteinfo\fP to \fBNULL\fP. +.SH RETURN VALUE +The \fBph_retrieve_siteinfo\fP() function returns 0 on success, or -1 on error +and sets \fIerrno\fP. + +The \fBph_is_siteinfo_cached\fP() macro returns 1 if the siteinfo data is +cached locally, or 0 otherwise. + +The \fBph_get_siteinfo\fP() function returns 0 on success, -1 on error, +or \fIPH_ERR_DATAERR\fP if there is no entry for \fIinfo\fP. + +The \fBph_siteinfo_iterate\fP() function returns 1 when the next siteinfo +entry is returned, 0 at the end of the list, or -1 on error (and sets +\fIerrno\fP). +.SH ERRORS +The \fBph_retrieve_siteinfo\fP() function will fail with \fBEINVAL\fP if it +receives an unexpected response code from the server. + +The \fBph_retrieve_siteinfo\fP() function may fail with any error from the +functions \fIread\fP() or \fIwrite\fP(). +.SH SEE ALSO +.BR read (2), +.BR write (2), +.BR ph_open (3) diff --git a/doc/ph_id.3 b/doc/ph_id.3 new file mode 100644 index 0000000..27c17f5 --- /dev/null +++ b/doc/ph_id.3 @@ -0,0 +1,37 @@ +.TH ph_id 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_id, ph_external, ph_status \- miscellaneous functions for PH server connections +.SH SYNOPSIS +.B #include +.P +.BI "int ph_id(PH *" ph ", char *" id ");" +.br +.BI "int ph_status(PH *" ph ", char ** " motd ");" +.br +.BI "int ph_external(PH *" ph ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +The \fBph_id\fP() function adds an entry to the PH server's logs +containing the text found in \fIid\fP. This is intended to be used +for tracking PH usage. + +The \fBph_status\fP() function retrieves the server's message of the +day. The \fImotd\fP argument is set to point to a dynamicly-allocated +string containing the text returned by the server. It is then the +calling application's responsibility to free this memory when it is +no longer needed. + +The \fBph_external\fP() function tells the server to consider the +session non-local, even if it originated from a host which would +normally be treated as local. +.SH RETURN VALUE +These functions return 0 on success. On error, they return -1 and set +\fIerrno\fP. +.SH ERRORS +These functions may fail with any error from the functions +\fIread\fP() or \fIwrite\fP(). +.SH SEE ALSO +.BR read (2), +.BR write (2), +.BR ph_open (3) diff --git a/doc/ph_login.3 b/doc/ph_login.3 new file mode 100644 index 0000000..41801d7 --- /dev/null +++ b/doc/ph_login.3 @@ -0,0 +1,85 @@ +.TH ph_login 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_login, ph_logout, ph_suser \- PH server authentication routines +.SH SYNOPSIS +.B #include +.P +.BI "int ph_login(PH *" ph ", char *" alias "," +.BI "int " authtype ", void *" auth ");" +.br +.BI "int ph_logout(PH *" ph ");" +.br +.BI "int ph_suser(PH *" ph ", char *" alias ");" +.br +.BI "int ph_passwd(PH *" ph ", char *" newpass ");" +.br +.BI "char *ph_whoami(PH *" ph ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +The \fBph_login\fP() function authenticates the user \fIalias\fP to the +PH server associated with the \fBPH\fP handle \fIph\fP. The \fIauthtype\fP +argument must be set to one of the following values: +.IP \fBPH_AUTH_EMAIL\fP +Email authentication. If the connection was established using the +\fBPH_OPEN_PRIVPORT\fP flag to \fBph_open\fP(), the user will be authenticated +if the local username and hostname match the value of the user's \fIemail\fP +field on the PH server. The \fIauth\fP argument is ignored. +.IP \fBPH_AUTH_PASSWORD\fP +Encrypted password authentication. The \fIauth\fP argument is the user's +password. +.IP \fBPH_AUTH_CLEAR\fP +Cleartext password authentication. Use of this authentication method is +not recommended, since it is inherently insecure. The \fIauth\fP argument +is the user's password. +.PP +The \fBph_logout\fP() function logs the currently logged-in user out of the +PH server. The session goes back to being an unpriveledged, anonymous +session. + +The \fBph_suser\fP() function allows a PH hero to assume the identity of +any arbitrary user without hero priveledges. The \fIalias\fP argument +indicates the user whose priveledges should be assumed. + +The \fBph_passwd\fP() function changes the password of the currently +logged-in user. The \fInewpass\fP argument is the new password. + +The \fBph_whoami\fP() function returns the name of the currently +logged-in user, or NULL if no user is logged in. +.SH RETURN VALUE +On successful completion, \fBph_login\fP() returns 0. If authentication +is denied by the server, it returns \fIPH_ERR_NOTLOG\fP. On failure, it +returns -1 and sets \fIerrno\fP to an appropriate value. + +On successful completion, \fBph_logout\fP() returns 0. If no user is +logged in, it returns \fIPH_ERR_NOTLOG\fP. On other errors, it returns -1 +and sets \fIerrno\fP to an appropriate value. + +The \fBph_suser\fP() function returns 0 on success, \fIPH_ERR_NOTHERO\fP +if the calling user is not a PH hero, or \fIPH_ERR_NOTLOG\fP if no user +is logged in. On failure, it returns -1 and sets \fIerrno\fP to an +appropriate value. + +The \fBph_passwd\fP() function returns 0 on success, or \fIPH_ERR_NOTLOG\fP +if no user is logged in. It can also fail with the same values returned +by \fBph_change\fP(3). On failure, it returns -1 and sets \fIerrno\fP. +.SH ERRORS +The functions described here may fail with any error from the functions +\fIread\fP() or \fIwrite\fP(). + +The \fBph_login\fP() function will return the following errors: +.IP \fBEINVAL\fP +The \fIauthtype\fP is invalid. +.IP \fBEINVAL\fP +Invalid data is read from the server. +.IP \fBEAGAIN\fP +The server responds with a temporary failure. +.PP +In addition, \fBph_login\fP() may fail with any error from the functions +\fIgetpwuid\fP() or \fImalloc\fP(). +.SH SEE ALSO +.BR read (2), +.BR write (2), +.BR getpwuid (3), +.BR ph_open (3), +.BR ph_change (3) diff --git a/doc/ph_open.3 b/doc/ph_open.3 new file mode 100644 index 0000000..94cc816 --- /dev/null +++ b/doc/ph_open.3 @@ -0,0 +1,66 @@ +.TH ph_open 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_open, ph_close \- manage PH server connections +.SH SYNOPSIS +.B #include +.P +.B "typedef void (*ph_debug_func_t)(void *, char *);" +.br +.BI "int ph_open(PH **" ph ", char *" server "," +.BI "int " flags ", ph_debug_func_t " sendhook "," +.BI "ph_debug_func_t " recvhook ", void *" hook_data ");" +.br +.BI "int ph_close(PH *" ph ", int " flags ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +The \fBph_open\fP() function connects to the PH server specified by +\fIserver\fP. It allocates memory for a \fBPH\fP handle and +sets the \fIph\fP argument to point to the allocated handle. The handle +can then be passed to other \fIlibphclient\fP calls to communicate with +the server. + +The \fIflags\fP argument is a bitwise-or of zero or more of the following +values: +.IP \fBPH_OPEN_PRIVPORT\fP +Use a reserved port for the local part of the connection. +.IP \fBPH_OPEN_ROUNDROBIN\fP +If \fIserver\fP is a round-robin DNS entry, try all IP addresses +before giving up. +.IP \fBPH_OPEN_LOCAL\fP +Connect to a local process via a pipe, rather than to a remote network +port. If this flag is given, the \fBPH_OPEN_PRIVPORT\fP and +\fBPH_OPEN_ROUNDROBIN\fP flags are ignored, the \fIserver\fP argument +specifies a path to the PH server program on the local system. + +If \fBPH_OPEN_LOCAL\fP is not set, the \fIserver\fP argument specifies the +hostname of the remote PH server. It may optionally be suffixed with +a ":" character followed by a numeric port number. +.IP \fBPH_OPEN_DONTID\fP +Do not send the library version string to the server upon connection. +.PP +The \fIsendhook\fP() and \fIrecvhook\fP() arguments are optional pointers +to functions which allow the calling application to monitor the communication +between \fBlibphclient\fP and the PH server. See \fBph_set_sendhook\fP(3) +for more information. + +The \fBph_close\fP() function closes the PH server connection and frees +memory associated with \fIph\fP. If \fIflags\fP is set to +\fBPH_CLOSE_FAST\fP, the connection is closed without sending the +PH "quit" command. +.SH RETURN VALUE +On successful completion, \fBph_open\fP() and \fBph_close\fP() will return +0. On failure, they will return -1 and set \fIerrno\fP to an +appropriate value. +.SH ERRORS +The \fBph_open\fP() function may fail with any error from the functions +\fIpipe\fP(), \fIclose\fP(), \fIdup2\fP(), \fIvfork()\fP, \fIexecl\fP(), +\fIexeclp\fP(), \fIgethostbyname\fP(), \fIrresvport\fP(), \fIsocket\fP(), +\fIconnect\fP(), or \fIcalloc\fP(). + +The \fBph_close\fP() function may fail with any error from the functions +\fIclose\fP() or \fIwrite\fP(). +.SH SEE ALSO +.BR socket (2), +.BR connect (2), +.BR close (2) diff --git a/doc/ph_query.3 b/doc/ph_query.3 new file mode 100644 index 0000000..5401a77 --- /dev/null +++ b/doc/ph_query.3 @@ -0,0 +1,49 @@ +.TH ph_query 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_query, ph_free_entries, ph_free_query \- retrieve data from a PH server +.SH SYNOPSIS +.B #include +.P +.BI "int ph_query(PH *" ph ", struct ph_fieldselector " query "[]," +.BI "char *" retfields "[], ph_entry **" entries ");" +.br +.BI "int ph_free_entries(ph_entry *" entries ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +The \fBph_query\fP() function retrieves entries from the PH server +associated with the \fBPH\fP handle \fIph\fP. The \fIquery\fP argument +selects which entries to return. The \fIretfields\fP argument +indicates which fields from the selected entries should be returned. +The resulting entries are stored in dynamicly-allocated memory, and the +\fIentries\fP argument is set to point to them. + +The \fIquery\fP argument is an array of structures which contain the +following fields: \fIfield\fP (a string representation of the field name), +\fIvalue\fP (a string representation of the value to check for), and +\fIoperation\fP (a character value indicating how the field and value +should be compared). If \fIfield\fP is NULL, the \fIoperation\fP field +is ignored and the value is matched against the default fields on the +server. The only universally-supported value for \fIoperation\fP is '=', +but other possibilities include '~', '<', and '>'. + +The \fIretfields\fP argument is a NULL-terminated array of strings which +lists the fields to return. If \fIretfields\fP is NULL, the default +set of fields is returned from the server. + +The \fBph_free_entries\fP() function is used to free memory allocated +by \fBph_query\fP() for the \fIentries\fP argument. +.SH RETURN VALUE +On success, the \fBph_query\fP() function returns the number of entries +which matched \fIquery\fP. If the query matched too many entries for the +server to return them, it returns \fIPH_ERR_TOOMANY\fP. If no entries matched, +it returns \fIPH_ERR_NOMATCH\fP. If the query was invalid, it returns +\fIPH_ERR_DATAERR\fP. On error, it returns -1 and sets \fIerrno\fP. +.SH ERRORS +The \fBph_query\fP() function will fail with \fBEINVAL\fP if it receives +an unexpected response code from the server. In addition, it may fail +with any error from the functions \fIread\fP() or \fIwrite\fP(). +.SH SEE ALSO +.BR read (2), +.BR write (2), +.BR ph_open (3) diff --git a/doc/ph_rfd.3 b/doc/ph_rfd.3 new file mode 100644 index 0000000..f005373 --- /dev/null +++ b/doc/ph_rfd.3 @@ -0,0 +1,33 @@ +.TH ph_rfd 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_rfd, ph_wfd \- return file descriptors associated with a PH handle +.SH SYNOPSIS +.B #include +.P +.BI "int ph_rfd(PH *" ph ");" +.br +.BI "int ph_wfd(PH *" ph ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +The \fBph_rfd\fP() and \fBph_wfd\fP() functions allow the application +to access the underlying file descriptors used by the PH handle \fIph\fP +to communicate with the PH server. The application can use this +information to detect communications problems with the server using +\fBpoll\fP() or \fBselect\fP(). +.SH RETURN VALUES +The \fBph_rfd\fP() function returns the file descriptor used for reading +from the server. + +The \fBph_wfd\fP() function returns the file descriptor used for writing +to the server. +.SH NOTES +The file descriptors used for reading and writing may be (and usually are) +the same. + +The application must not write to or read from the file descriptors +returned by the \fBph_rfd\fP() and \fBph_wfd\fP() functions. If it does, +the PH handle may be left in an inconsistent state, and all subsequent +behavior is undefined. +.SH SEE ALSO +.BR ph_open (3) diff --git a/doc/ph_serverlist_add.3 b/doc/ph_serverlist_add.3 new file mode 100644 index 0000000..79b0da8 --- /dev/null +++ b/doc/ph_serverlist_add.3 @@ -0,0 +1,67 @@ +.TH ph_serverlist_add 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_serverlist_add, ph_serverlist_merge, ph_serverlist_iterate, ph_free_serverlist \- access list of known PH servers at other sites +.SH SYNOPSIS +.B #include +.P +.BI "int ph_serverlist_add(struct ph_serverlist *" serverlist "," +.BI "char *" server ", char *" site ");" +.br +.BI "int ph_serverlist_merge(PH *" ph ", struct ph_serverlist *" serverlist ");" +.br +.BI "int ph_serverlist_iterate(struct ph_serverlist *" serverlist "," +.BI "char *" server ", char *" site "," +.BI "struct ph_serversite **" serversite ");" +.br +.BI "void ph_free_serverlist(struct ph_serverlist *" serverlist ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +The \fBph_serverlist_add\fP() function will add an entry for the PH +server \fIserver\fP at site \fIsite\fP to the list of servers in +\fIserverlist\fP. + +The \fBph_serverlist_merge\fP() function will read the list of known PH +servers from the server associated with \fIph\fP and add any previously- +unknown entries to the list of servers in \fIserverlist\fP. + +The \fBph_serverlist_iterate\fP() function allows the caller to cycle +through the list of known PH servers by setting \fIserversite\fP to +point to the next matching entry in \fIserverlist\fP on each successive +call. To start at the beginning of the list, the caller initializes +\fIserversite\fP to \fINULL\fP. + +If \fIserver\fP is not \fINULL\fP, only entries whose last two or more +domain name componants of the \fIserver\fP field match the \fIserver\fP +argument will be returned. If \fIsite\fP is not \fINULL\fP, only +entries whose \fIsite\fP field contain the argument \fIsite\fP as a +substring will be returned. If both \fIserver\fP and \fIsite\fP are +non-\fINULL\fP, only entries matching both criteria will be returned. +If both \fIserver\fP and \fIsite\fP are \fINULL\fP, all entries are +returned. + +The \fBph_free_serverlist\fP() function frees memory associated with +the PH server list \fIserverlist\fP. +.SH RETURN VALUE +The \fBph_serverlist_add\fP() function returns 0 on success, or -1 on +error (and set \fIerrno\fP). + +The \fBph_serverlist_merge\fP() function returns 0 on success, +\fIPH_ERR_DATAERR\fP if the server does not understand the query, or -1 on +error (and set \fIerrno\fP). + +The \fBph_serverlist_iterate\fP() function returns 1 when a matching +entry is returned, 0 when no more matching entries have been found, +or -1 on error (and sets \fIerrno\fP). +.SH ERRORS +The \fBph_serverlist_merge\fP() function will fail with \fBEINVAL\fP if it +receives an unexpected response code from the server. + +The \fBph_serverlist_iterate\fP() function will fail with \fBEINVAL\fP if +the \fIserver\fP argument is non-\fINULL\fP but specifies an illegal +domain name. +.SH SEE ALSO +.BR read (2), +.BR write (2), +.BR ph_open (3), +.BR ph_query (3) diff --git a/doc/ph_set_sendhook.3 b/doc/ph_set_sendhook.3 new file mode 100644 index 0000000..fc7f111 --- /dev/null +++ b/doc/ph_set_sendhook.3 @@ -0,0 +1,33 @@ +.TH ph_set_sendhook 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_set_sendhook, ph_set_recvhook \- set libphclient debugging hooks +.SH SYNOPSIS +.B #include +.P +.B "typedef void (*ph_debug_func_t)(void *, char *);" +.br +.BI "void ph_set_sendhook(PH *" ph ", ph_debug_func_t " sendfunc ");" +.br +.BI "void ph_set_recvhook(PH *" ph ", ph_debug_func_t " recvfunc ");" +.br +.BI "void ph_set_hookdata(PH *" ph ", void *" hook_data ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +The \fBph_set_sendhook\fP() and \fBph_set_recvhook\fP() functions set the +\fIlibphclient\fP sending and receiving hooks to point to the application- +supplied functions \fIsendfunc\fP and \fIrecvfunc\fP, respectively. + +Once these hooks are set, when each line of data is sent to or received +from the PH server, the \fIsendfunc\fP and \fIrecvfunc\fP functions are +called with two arguments. The first is a pointer to application-specific +data (set by the \fBph_set_hookdata\fP() function). The second is +a pointer to the line that was sent to or received from the server. +This is typically used by the application to monitor and debug the +communication between the library and the PH server. + +To unset the send and receive hooks, applications can call +\fBph_set_sendhook\fP() and \fBph_set_recvhook\fP() with a second +argument of \fBNULL\fP. +.SH SEE ALSO +.BR ph_open (3) diff --git a/doc/ph_www_resolve.3 b/doc/ph_www_resolve.3 new file mode 100644 index 0000000..0e5ae22 --- /dev/null +++ b/doc/ph_www_resolve.3 @@ -0,0 +1,43 @@ +.TH ph_www_resolve 3 "Oct 2002" "University of Illinois" "C Library Calls" +.SH NAME +ph_www_resolve, ph_advertised_www \- determine PH-redirected www addresses +.SH SYNOPSIS +.B #include +.P +.BI "int ph_www_resolve(PH *" ph ", char *" user "," +.BI "char **" real_url ");" +.br +.BI "int ph_advertised_www(PH *" ph ", char *" alias "," +.BI "int " confirm_alias ", char **" advertised_url ");" +.SH VERSION +This man page documents version 1.2 of \fBlibphclient\fP. +.SH DESCRIPTION +The \fBph_www_resolve\fP() function resolves the URL for the +user \fIuser\fP. The \fIreal_www\fP argument is set to point to a +dynamically-allocated string containing the resolved URL. This memory +must be later freed by the calling application. + +The \fBph_advertised_www\fP() function determines the advertised URL for +the user whose alias is \fIalias\fP. If \fIconfirm_alias\fP is set, +the entry for \fIalias\fP is looked up to make sure it exists. The +\fIadvertised_www\fP argument is set to point to a dynamically-allocated +string containing the advertised URL. This memory must later be freed +by the calling application. + +If the server does not support the \fIwwwredirect\fP siteinfo field, the +\fBph_advertised_www\fP() function will return the same URL as the +\fBph_www_resolve\fP() function. +.SH RETURN VALUE +These functions return 0 on success, \fIPH_ERR_NOMATCH\fP if a single matching +entry cannot be found, and \fIPH_ERR_DATAERR\fP if the query is invalid or if +a single matching entry is found but does not contain a \fIwww\fP field. +On error, they return -1 and set \fIerrno\fP. +.SH ERRORS +These functions will fail with \fBEINVAL\fP if they receive an unexpected +response code from the server. In addition, they may fail with any +error from the functions \fIread\fP() or \fIwrite\fP(). +.SH SEE ALSO +.BR read (2), +.BR write (2), +.BR ph_open (3), +.BR ph_siteinfo (3) diff --git a/doc/rfc2378.txt b/doc/rfc2378.txt new file mode 100644 index 0000000..8673b2b --- /dev/null +++ b/doc/rfc2378.txt @@ -0,0 +1,1235 @@ + + + + + + +Network Working Group R. Hedberg +Request for Comments: 2378 Umea University +Category: Informational P. Pomes + QUALCOMM, Inc. + September 1998 + + + The CCSO Nameserver (Ph) Architecture + +Status of this Memo + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (1998). All Rights Reserved. + +Abstract + + The Ph Nameserver from the Computing and Communications Services + Office (CCSO), University of Illinois at Urbana-Champaign has for + some time now been used by several organizations as their choice of + publicly available database for information about people as well as + other things. This document provides a formal definition of the + client-server protocol. The Ph service as specified in this document + is built around an information model, a client command language and + the server responses. + +1. Overview + +1.1. Basic Information Model + + At its simplest the Ph database can be thought of as a computer- + resident "phone book". However, it can be used to collect arbitrary + information about people, and in response to a query about an object + named in the database, return information about that entity. It is + in short a nameserver for people and objects. It was designed to + keep a relatively small amount of arbitrary information about a + relatively large number of people or things, and provide access to + that information over the Internet. In order to structure the + information the manager of the database has to decide which views to + present of the real-world objects that are to be represented in the + database. Each view is then composed of a number of fields and their + values. To support this concept Ph has the notion of named + information, i.e., categorizing information into what are called + fields and assigning descriptive names to those fields. + + + +Hedberg & Pomes Informational [Page 1] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + + Even if the database resides and is reachable from the Internet it is + local in the meaning that no server is supposed to be able to refer a + client to another server which might hold the wanted information. + However a server may contain a list of other Nameservers which can be + used by clients to query other Nameservers for information. + +1.1.1. Fields + + A field descriptor is associated with each field and is used to + describe the type and behavior of the field. A field descriptor + includes the fieldname, the maximum length of information the field + can store before truncation, keywords describing the properties of + the field as well as free text describing what kind of information + the field is supposed to hold. + + The keywords can be any of the following: + + Always: Forces the field's contents to be always printed in + addition to whatever fields specified by the query. + + Any: This field is always searched by queries. To be most + use ful, a field marked as Any should also have the Indexed + and Lookup keywords as well. + + Change: Can be changed by the owner of the entry. + + Default: Printed if no return clause is given in the query. + + Encrypt: Must be encrypted before transmission. + + ForcePub: Viewable/searchable regardless of the content of the + suppress field + + Indexed: Fields that are kept track of in the database's index for + efficient lookups. At least one indexed field must be + present in each query. + + LocalPub: May be viewed by anyone in the "local" domain or address + space. Fields with this keyword are completely invisible + outside of the "local" domain. They will not be shown with + the fields command (section 3.3), and are disallowed in + query commands or return clauses (section 3.8). + + Lookup: May be used in the selection part of a query. A Field + without this keyword may not be used to select entries. + + NoMeta: Wildcard searches are disallowed. + + + + +Hedberg & Pomes Informational [Page 2] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + + NoPeople: No entry of type "person" may include this field. + + Private: Field may be viewed by Heros (section 1.4) only. + + Public: May be viewed by anyone. Fields not marked with this + keyword may only be viewed by the entry's owner or a Hero. + + Sacred: Changes to the field are prohibited except via non-network + invocations of the server, i.e., from a tty, file, or pipe. + + Turn: Users may turn off visibility of a field to everyone except + themselves and Heros by prefixing the field text with '*'. + + Unique: Any change to the field will be rejected if the change + causes the modified field to match the same field in any + other entry. + +1.1.2. Character Sets + + Historically Ph has been restricted to only handle printable + characters, that is characters with hexadecimal values between 0x20 + and 0x7f. Lately with the spreading of 8-bit clean Operating Systems + there is no reason to keep this limitation. + + This document therefore proposes that ISO-8859-1 shall be regarded as + an alternative character set for Ph, the default still being US- + ASCII. + + Clients that utilize ISO-8859-1 should request that the server return + ISO-8859-1 by using the "set"-command. + + In the instance that values are stored using ISO-8859-1 and are to be + shown to a client expecting US-ASCII, the characters with character + codes outside of the US-ASCII range should be displayed in the + "Quoted-Printable" content-transfer-encoding form defined in RFC-2045 + [MIME]. + + 1.2. Standardization issues + + Each Nameserver manager is in essence free to name new fields to suit + the special needs of his/her organization. But in order to make the + directory service useful outside of the organization it is + recommended that a core set of standard fields always should be + present. + + Therefore this document defines a couple of standard collections of + fields (Appendix A). + + + + +Hedberg & Pomes Informational [Page 3] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + + Also note that the architecture makes no assumption about the search + and retrieval mechanisms used within individual servers. Operators + are thereby free to use any kind of dedicated databases, fast + indexing software or even gateways to other directory services to + store and retrieve the information, if desired. + + Ph simply functions as a known front-end, offering a simple data + model in addition to a well known port and simple query language. + +1.3. Conventions Used in this Document + + In examples, "C:" and "S:" indicate lines sent by the client and + server respectively. + +1.4. Heros + + For Ph a Hero is equivalent to a superuser or operator. Being in + Hero mode means that some or all artificial limits are removed; full + Heros may change any field in any entry in the database, as well as + view as many entries as they wish. Heros can also be limited to one + field of one other entry. Hero mode is used mostly for + administrative purposes, delegation of group authority over selected + fields, and is controlled by the acl field. + +2. Basic Operation + + Initially, the server host starts the Ph service by listening on TCP + port 105. When a client host wishes to make use of the service, it + establishes a TCP connection to the server host. The client and the + Ph server then exchange commands and responses (respectively) until + the connection is closed or aborted. + +2.1. Command syntax + + Commands in Ph consist of a keyword optionally followed by zero or + more keywords or values, separated by spaces, tabs or newlines, and + followed by a carriage return-linefeed (CRLF) pair. A more thorough + description using BNF is given in Appendix C. + + Values containing spaces, tabs or newlines must be enclosed in double + quotes ('"'). In addition the sequences "\n", "\t","\"" and "\\" may + be used to mean newline, tab, double quote and backslash, + respectively. + + Keywords must be given in lower case; case in the values of fields is + preserved, although queries are not case-sensitive. + + + + + +Hedberg & Pomes Informational [Page 4] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + +2.2. Response syntax + + Responses consist of a result code followed by additional information + possibly separated by entry index and/or field name and are + terminated by a CRLF pair. + + result code:[entry index:][field name:]text + + Responses to some commands might be multi-lined. In these cases each + line in the response, except the last, has the appropriate result + code negated (prefaced with "-"). The last line then starts with the + appropriate result code without negation. Each line must be + terminated by a CRLF pair. + + If a particular command can apply to more than one entry, then the + multilined response must be so organized that all information + pertaining to each entry is returned on consecutive lines, and that + each of those lines must have one and the same entry index directly + following the resultcode. The first entry index should be 1 and + incremented each time a new entry is referred to. + + C: query hedberg return email name title + S: 102:There were 3 matches to your request. + S: -200:1: email: canheg95@student.umu.se + S: -200:1: name: Carl Johan Hedberg + S: -200:1: title: Student + S: -200:2: email: parheg95@student.umu.se + S: -200:2: name: Par Hedberg + S: -200:2: title: Student + S: -200:3: email: Roland.Hedberg@umdac.umu.se + S: -200:3: name: Roland Hedberg + S: -200:3: title: Boss of the Network group + S: 200:Ok + + Commands that can apply to more than one field must have the name of + the field to which the response applies directly following the entry + index. + + The text of the response will be either an error message in human + readable format, or data from the Nameserver. Whitespace (spaces or + tabs) may appear anywhere in the response, but the field name and + text columns if present must each begin with a whitespace character. + + Since more than one specific piece of information may be manipulated + by a particular command, it is possible for parts of a command to + succeed, while other parts of the same command fail. This situation + is handled as a single multi-line response with the result code + changing as appropriate. + + + +Hedberg & Pomes Informational [Page 5] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + + As for FTP, the result codes are in the range 100-699 (or from -699 + to -100 for multiline responses), where the leading digit has the + following significance: + + 1: In progress + 2: Success + 3: More information needed + 4: Temporary failure; it may be worthwhile to try again. + 5: Permanent failure + 6: Phquery specific codes + + Many commands generate more than one line of response; every client + should be prepared to deal with such continued responses. Note that + a command is finished when and only when the result code on a + response line (treated as a signed integer) is greater than or equal + to 200. + + Clients should assume that any numeric response, within the above + mentioned ranges, are valid. Also note that the server is allowed to + send one or more lines with result codes between -199 - -100 (the + leading "-" indicates a continuation line) and 100 - 199, as status + information, before the actual results are transmitted. + +2.3. Format of a search string + + Matching is not sensitive to upper or lower case letters and is + normally done on a word-by-word basis. That is, both the query + expression and the entry information is broken up into words, and + individual words are compared using exact matching. If the order of + the words is important in a query, then the query string can be + surrounded by '"' (double quotes), whereby the complete search string + is matched against the information in the Nameserver database. + + Word delimiters are the following characters: , , , ",", ";" and ":" . These characters are not indexed and + should not be part of the search string. + + However, special symbols, called "wildcard" characters, can be used + if the exact spelling is unknown. The '*' (asterisk, 0x2A) is used + in place of zero or more characters, '+' (plus, 0x2B) in place of one + or more unknown characters, and '?' (question mark, 0x3F) can be used + when exactly one character is unknown. If the unknown character can + be one of a limited set this can be specified by surrounding the set + with brackets, e.g., [ei] means that in that place an 'e' or an 'i' + would match. + + + + + + +Hedberg & Pomes Informational [Page 6] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + +3. Commands + +3.1. status + + status + + Prints the message of the day and the current status of the + nameserver. + + C: status + S: 100:Qi server $Revision: 1.6 $ + S: 100:Ph passwords may be obtained at CCSO Accounting, + S: 100:1420 Digital Computer Lab, between 8:30 and 5 Monday-Friday. + S: 100:Be sure to bring your U of I ID card. + S: 200:Database ready + +3.2. siteinfo + + siteinfo + + Returns information about the servers site. Possible fields are + + Version Version information for the server. + Maildomain The mail domain to use for phquery-type mail. + Mailfield The field containing the specific email address. + Mailbox Mandatory entry that names the field to use as + maildrop. + Administrator Guru in charge of service. + Passwords Person in charge of ordinary password/change requests. + Authenticate Authentication methods supported by the server, + ordered in the site-preferred way. Presently the + following options are defined: + + 1 attempt auto login + 2 allowed to be interactive if needed + 4 use ANSI X9.9 challenge/response + 8 use v4 Kerberos login + 16 use v5 Kerberos [KRB5] login + 32 use GSS-API [GSS-API] login + 64 use email login + 128 password encrypted response to challenge + 256 use clear-text password + 512 use HMAC [HMAC] with SHA-1 of challenge string + + + + + + + + +Hedberg & Pomes Informational [Page 7] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + + Example + + C: siteinfo + S: -200:1:version:3.1 + S: -200:2:maildomain:umu.se + S: -200:3:mailfield:alias + S: -200:4:mailbox:email + S: -200:5:administrator:roland.hedberg@umdac.umu.se + S: -200:6:passwords:roland.hedberg@umdac.umu.se + S: -200:7:authenticate:64:32:128 + S: 200: Ok. + + The mail fields in the siteinfo command direct how address + information stored in the Nameserver is to be used for delivering + mail. + + The specific (username, host) pair to where a user's mail should be + sent for final delivery is stored in the field named by {mailbox}. + Phquery and like utilities will use this field. + + To construct a useable email address from Nameserver information, the + algorithm below is followed: + + if ({maildomain} is not null) then + address = (contents of {mailfield})@{maildomain} + else + address = (contents of {mailfield}) + + Some existing client software will not format email addresses + correctly if the value of {mailbox} is set to anything other than + "email" when {maildomain} is non-empty. + + If {mailbox} is set to anything other than {email}, {maildomain} must + be reported empty by the siteinfo command. Also reformatting of each + record's {mailfield} must be done by the server before reporting it + to the client. + +3.3. fields + + fields [field ...] + + Without an argument, a list of all available field descriptors should + be delivered. Any space-separated argument(s) restricts the list to + the named fields. Fields marked with the "LocalPub" keyword (section + 1.1.1) should not be delivered outside of the local domain. + + + + + + +Hedberg & Pomes Informational [Page 8] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + + The output of the command consists of two lines describing each + field. The first line defines the field in technical terms (max + length and field attributes), while the second line is a brief + description of what the field is intended to hold. The second + number of each response is the field id number. + + C: fields + S: -200:6:alias:max 32 Indexed Lookup Public Default + S: -200:6:alias:Unique name for user. + S: -200:3:name:max 64 Indexed Lookup Public Default + S: -200:3:name:Fullname + S: -200:2:email:max 128 Lookup Public Default + S: -200:2:email:Account to receive electronic mail. + S: -200:16:other:max 256 Lookup Public Default Change + S: -200:16:other:Other info the user finds important. + S: -200:33:home_phone:max 60 Lookup Public Change Turn + S: -200:33:home_phone:Home telephone number. + S: 200:Ok. + +3.4. id + + id information + + Enters the given information in the Nameserver's log. This command + is used by the Ph client to enter the user id of the person running + it. + +3.5. set + + set [option[=value] ...] + + Sets the named option for this nameserver session to a value. The + default string "on" is used if no value is supplied. Used without + arguments it return the settable options and their current value. + Some common options are + + echo If on, echo the client's commands back to the client. + limit Changes that affect more than the specified number of + entries results in an error. + charset Return responses to the client in the character set + specified. + verbose If on, report interim progress messages to the client. + addonly If on, change commands can only create fields in entries, + not modify them. + nolog If on, disable logging. + external If on, make Fields marked as "LocalPub" invisible. + + + + + +Hedberg & Pomes Informational [Page 9] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + + Example + + C: set verbose=off + S: 200:Done. + + C: set + S: -200:echo:off + S: -200:limit:2 + S: -200:charset:iso-8859-1 + S: -200:verbose:off + S: -200:addonly:off + S: -200:nolog:off + S: -200:external:on + S: 200:Done. + +3.6. login, logout, answer, clear, email, and xlogin + +3.6.1. login + + login [alias] + + The "login" command allows client users to identify themselves to the + Nameserver. More specifically it identifies a client user with a + particular entry in the Nameserver and allows them to change fields + in that entry and possibly other entries. It is also necessary to be + logged in to the Nameserver to view certain sensitive fields in the + user's own entry. + + In order to use the "login" command the client must prompt the user + for their ph alias and password. The client is then responsible for + (optionally) encrypting the password and sending it to the server. + This will be covered in sections 3.6.3 (answer) and 3.6.4 (clear). + + C: login foo + S: 301:,:P"_Y$ONU%"SDUQ6&^`ZZ'?*#Y`A_.Z/A>?@SH>*- + +3.6.2. logout + + logout + + The "logout" command allows a user who is logged in to the Nameserver + to logout. + + C: logout S: 200:Ok. + + + + + + + +Hedberg & Pomes Informational [Page 10] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + +3.6.3. answer + + answer encrypted-response + + In response to the login command, the Nameserver responds with a + random challenge string. The Nameserver client encrypts the + challenge with the password supplied by the user, uuencodes the + result into US-ASCII, and returns the printable result in the + "answer" command: + + C: login ppomes + S: 301:.%$&.D^67$*1?<.2S@DR:Z@M*)AV-<:4QM>#R>M*HT + C: answer M5K'F:NI(a?M?O2+-a9`48RA#ZF=L9)G)/XRS7Q^0>0@-R7X$WGb`50B] + S: 200:ppomes:Hi how are you? + + The encryption algorithm is based on a three rotor Enigma engine. + There are known attacks on the security of this approach. + + The answer command is also used to return method-specific responses + to the xlogin command (section 3.6.6). + +3.6.4. clear + + clear cleartext-password + + The "clear" command can be used instead of the "answer" command to + complete a login sequence. It's argument is the user's cleartext + password. This command is supplied only to support those clients + that have not implemented one of the encryption engines used by the + "answer" command. It's use is strongly discouraged. + + C: login ppomes + S: 301:E=@Y&VW^_9YVI;D5.[EB0:B)9Z#_&X$:2)/eL$VJC87 + C: clear MySecret + S: 200:ppomes:Hi how are you? + +3.6.5. email + + email local-userid + + The "email" command can also be used instead of the "answer" command + to complete a login sequence. The value of local-userid is the + user's login name on the local machine. If all of the following + conditions are true, then the email command will be accepted by the + server: + + + + + + +Hedberg & Pomes Informational [Page 11] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + + 1) The connection to the server originates on port 1023 or less on + the client. Note: This is a system port. Port 1023 is not + allocated to this use. + + 2) The canonical name of the client's host matches the right-hand + side of the email address of the requested alias specified in the + "login" command. + + 3) The "local-userid" matches the left-hand side of the email + address belonging to the requested alias. + + This is a weak but convenient form of authentication. Depending on + the information users are allowed to change about themselves and the + threat environment the server operates in, this method may be + appropriate. Servers should take care to avoid DNS spoofing. + +3.6.6. xlogin + + xlogin option alias + + Extended login command for GSS, Kerberos v4 and v5, ANSI X9.9 token + devices (e.g., SNK/4), etc. The option is one of the values returned + in the Authenticate field of the "siteinfo" command (section 3.2). + Alias is the user's alias. + + C: xlogin 16 ppomes + S: 301:DoKrbLogin started; send Kerberos mutual authenticator. + C: answer MJa8QO1cJHYz2IdWyg7uhAnixVqgCZQBWr64ciXYku1ktdu.... + S: 200:ppomes:Hi how are you? + + C: xlogin 4 ppomes + S: 302:SNK Challenge "024142": + C: answer 82344338 + S: 200:ppomes:Hi how are you? + + The answer command returns the requested quantity, Kerberos + authenticator, X9.9 device response, etc. Binary quantities are + first uuencoded into US-ASCII. + +3.7. add + + add field=value... + + This command is used to add new entries to the database. You must be + logged in and have full Hero privileges (section 1.4) to use "add". + + C: add name="doe john" id="123456789" alias="j-doe" + S: 200:Ok. + + + +Hedberg & Pomes Informational [Page 12] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + +3.8. query + + query [field=]value [field=value] . . . [return field1 [field2]] + + If no field is specified together with a value then the field is + assumed to be "name" and/or "nickname". When more than one field- + value specification are given in a query, entries matching all + specifications are returned (implicit AND). + + It is possible to define which fields should be returned by adding a + "return" clause. If no return clause is defined the Ph server will + return a default list of fields. Typical default fields are "alias", + "name", "title", "email", "phone", "address", "department", "www", + and "other". A return clause consists of the word "return" followed + by a list of fields or the word "all". If the word "all" is used + then all viewable fields will be returned. + + C: query name=doe name=john + S: 102:There was 1 match to your request. + S: -200:1: alias: j-doe + S: -200:1: name: doe john + S: 200:Ok. + +3.9. delete + + delete [field=]value... + + This command is used to delete entire entries from the database. You + must be logged in and have full Hero (section 1.4) privileges to use + "delete". + + The arguments to the "delete" command are the same as the selection + part of a "query" command. "Delete" finds all the entries that match + the argument(s) and deletes them. + + The "delete" command obeys the Nameserver "limit" option, which can + be used to prevent deletion of more entries than intended. + + C: delete name="doe john" id="123456789" alias="j-doe" + S: 200:1 entries deleted. + +3.10. change + + change [field=]value [make|force] field="value"... + + This command is used to change one or more fields in one or more + entries to the values specified. The "change" command consists of + two clauses, the "change" clause and the "make" or "force" clause. + + + +Hedberg & Pomes Informational [Page 13] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + + The "change" clause determines which entries will be affected by the + command. It uses the same arguments as the selection clause of a + "query" command. The "make" or "force" clause specifies which + field(s) will be changed and the new value(s) of the specified + field(s). The "force" clause is only used to make non-encrypted + changes to fields marked "Encrypt". + + You must be logged in to use "change". + + The "change" command obeys the Nameserver "limit" option, which can + be used to prevent changing the field contents of more entries than + intended. + + C: change alias=j-doe force password=NewSecret + S: 200:1 entry changed. + + C: set limit=500 + S: 200:Done. + C: change fax="(619) 555-1212" make fax="(760) 555-1212" + S: 200: 113 entries changed. + +3.11. help + + help [{native|client} [topic ...]] + + Prints help on the Nameserver or on specific clients. If client is + specified, it should be a valid Nameserver client identifier, such as + "ph". The client-specific help will first be searched for topic, and + then the native help will be searched. If topic is omitted, a list + of all available help texts will be returned. If "native" or client + are also omitted, a list of clients will be returned. + +C: help native 101 +-200:1:101: +-200:1: The Nameserver echo option is set. The text of this response is +-200:1: the command you just gave, which has not (yet) been executed. +200:Ok. + +3.12. quit/exit/stop + + quit + + Terminates the session with the Nameserver and causes the client to + exit. + + C: quit + S: 200:Bye! + + + + +Hedberg & Pomes Informational [Page 14] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + +4. Security + +4.1. Transport Layer + + In the absence of encryption between client and server, all + Nameserver traffic is unsecure. Kerberos v4, v5, and the GSS-API all + provide encryption mechanisms, however the Nameserver protocol does + not support the means to negotiate encryption between client and + server. This implies that all traffic can be seen by other machines + having access to the network linking the client and server. + Furthermore clear-text traffic is subject to modification in transit + between client and server. Possible ways of augmenting this would be + to use something like TLS [TLS] or IPSec [IPSEC]. + +4.2. Server Authentication + + Unless one of the mutual authentication mechanisms is used, e.g., + Kerberos 4/5 or GSS-API, there is no way to prove the identity of a + server. Further, there is no mechanism to prove a given server is + authoritative for a set of information. + +4.3. Secure User Authentication + + The Ph protocol allows the negotiation of several authentication + protocols between client and server, some weak and some strong. It + does not prohibit the use of cleartext passwords, something which + should be depreciated, but is useful when dealing with some clients. + +4.4. Privacy and Access Lists + + Directory services like the CCSO white pages server that contain + information on persons have to consider privacy issues. This paper + describes one way of partitioning specific attributes from unwanted + access by designating them visible only to the "local" community, + visible only to the person connected with the information, or visible + only to the database administrator. + + + + + + + + + + + + + + + +Hedberg & Pomes Informational [Page 15] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + +4.5. References + + [GSS-API] Linn, J., "Generic Security Service Application Program + Interface, Version 2", RFC 2078, January 1997. + + [HMAC] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed- + Hashing for Message Authentication", RFC 2104, February + 1997. + + [IPSEC] Atkinson, R., "Security Architecture for the Internet + Protocol", RFC 1825, August 1995. + + [KRB5] Kohl, J., and C. Neuman, "The Kerberos Network + Authentication Service (V5)", RFC 1510, September 1993. + + [TLS] Dierks, T., and C. Allen, "The TLS Protocol, + Version 1.0", Work in Progress. + + [MIME] Freed, N., and N. Borenstein, "Multipurpose Internet Mail + Extensions, (MIME) Part One: Format of Internet Message + Bodies", RFC 2045, November 1996. + +5. Miscellaneous + +5.1. Authors' Addresses + + Roland Hedberg + Umdac + Umea University + 901 87 Umea + Sweden + + EMail: Roland.Hedberg@umdac.umu.se + + + Paul Pomes + Qualcomm Inc + 6455 Lusk Blvd + San Diego, CA + USA + + EMail: ppomes@qualcomm.com + + + + + + + + + +Hedberg & Pomes Informational [Page 16] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + +Appendix A + + Default fields and suggested lengths connected to different object + types. + + All entries: Information common to all entries + type 64 + name 256 + address 128 + proxy 32 + password 32 + + type=phone: Information found in a phonebook + phone 64 + fax 64 + + type=person: Information about a human being + alias 32 + forename 64 + surname 64 + group 32 + email 128 + public_key 4096 + nickname 128 + www 256 + acl 128 + + type=staff: Information about an employee + empno 16 + department 64 + supervisor 64 + secretary 64 + office_location 128 + office_address 128 + office_phone 64 + title 64 + pager 64 + hours 128 + + type=unit: Information about an organizational unit + email 128 + www 256 + public_key 4096 + + + + + + + + +Hedberg & Pomes Informational [Page 17] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + +Appendix B + + Result codes + + 100 In progress (general). + 101 Echo of current command. + 102 Count of number of matches to query. + 103 No hostname found for IP address. + 200 Success (general). + 201 Database ready, but read-only. + 300 More information (general). + 301 Encrypt this string. + 302 Print this prompt. + 400 Temporary error (general). + 401 Internal database error. + 402 Lock not obtained within timeout period. + 403 Login would have been OK, but database read-only + 475 Database unavailable; try later. + 500 Permanent error (general). + 501 No matches to query. + 502 Too many matches to query. + 503 Not authorized for requested information. + 504 Not authorized for requested search criteria. + 505 Not authorized to change requested field. + 506 Request refused; must be logged in to execute. + 507 Field does not exist. + 508 Field is not present in requested entry. + 509 Alias already in use. + 510 Not authorized to change this entry. + 511 Not authorized to add entries. + 512 Illegal value. + 513 Unknown option. + 514 Unknown command. + 515 No indexed field in query. + 516 No authorization for request. + 517 Operation failed because database is read-only. + 518 To many entries selected by change command. + 520 CPU usage limit exceeded. + 521 Change command would have overridden existing field, + and the "addonly" option is on. + 522 Attempt to view "Encrypted" field. + 523 Expecting "answer" or "clear". + 524 Names of help topics may not contain "/". + 525 Email authentication failed + 526 Host name address not found in DNS + 527 Reverse DNS lookup does not match forward DNS lookup + 528 General Kerberos database error. + 529 Selected authentication method not available + + + +Hedberg & Pomes Informational [Page 18] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + + 590 Remote queries not allowed. + 598 Command unknown. + 599 Syntax error. + 600 Ambiguous or multiple match + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Hedberg & Pomes Informational [Page 19] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + +Appendix C + + Description of the client command language using the augmented + Backus-Naur Form (RFC822). + + response = code [index] [field] text CRLF + + code = [-] LDIG 2DIGIT ":" + index = number ":" + field = 1*SPACE attribute ":" 1*SPACE + text = 1*( CHAR / LWSP-char ) + + + command = ph-command CRLF + + ph-command = "status" / a-command / oa-command + ph-command =/ av-command / answer-command / query-command + ph-command =/ delete-command / change-command / "help" / quit-command + + a-command = ("siteinfo"/"fields"/"id"/"login"/"help"/"email"/ + "clear") [attribute] + oa-command = ("xlogin") number attribute + av-command = ("set"/"add"/"make") 1*attribute-value + answer-command = ("answer") 1*printable + query-command = ("query"/"ph") 1*selection ["return" 1*attribute] + quit-command = "quit" / "exit" / "stop" + change-command = "change" 1*selection make 1*attribute-value + delete-command = "delete" selection + + selection = value / attribute-value + + attribute-value = attribute "=" value + + value = 1*(cstring / quoted-string / set) + + cstring = 1*( ALPHA / DIGIT / S_SPEC / set / quoted-pair ) + attribute = 1*( ALPHA / DIGIT / "_" / "-" ) + number = 1*(DIGIT) + + quoted-string = <"> 1*(qtext/quoted-pair) <"> + + quoted-pair = "\" CHAR + qtext = 1*( CHAR / CR / SPEC1 / DELIMIT1 / DELIMIT2 / LWS ) + set = '[' 1*(ALPHA/DIGIT) ']' + + LWSP-char = SPACE / HTAB + LWS = 1*([CRLF] (LWSP-char)) + CRLF = CR LF + + + +Hedberg & Pomes Informational [Page 20] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + + S_SPEC = '*'/'+'/'?' + SPEC1 = "=" / "*" / "?" / "+" / "[" / "]" + SPEC2 = "\" / """ + DELIMIT1 = SPACE / HTAB / LF + DELIMIT2 = "," / ";" / ":" + PRINTABLE = %d32..%d126 + CTL = %d0..%d31 / %d127..%d160 + ALPHA = %d65..%d90 / %d97..%d122 + DIGIT = %d48..%d57 + LDIG = %d49..%d54 + SPACE = %d32 + SEP = (CR LF) / LF + CR = %d13 + LF = %d10 + HTAB = %d9 + CHAR = %d33..%d126 / %d160..%d255 + OTHER = "(" / ")" / "-" / "." / "/" + "@" / "$" / "_" / "!" / "~" / + "'" / "#" / "&" / "<" / ">" / + "^" / "`" / "{" / "|" / "}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Hedberg & Pomes Informational [Page 21] + +RFC 2378 The CCSO Nameserver (Ph) Architecture September 1998 + + +Full Copyright Statement + + Copyright (C) The Internet Society (1998). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + + + + + + + + + + + + + + + + + + + + + + + +Hedberg & Pomes Informational [Page 22] + diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 0000000..402b9d4 --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,93 @@ +# @configure_input@ + +### Path settings +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +mandir = @mandir@ +libdir = @libdir@ +includedir = @includedir@ + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ + +@ENCAP_DEFS@ + +### Installation programs and flags +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s +INSTALL_DATA = @INSTALL_DATA@ +LN_S = @LN_S@ +MKDIR = @MKDIR@ + +### Compiler and link options +CC = @CC@ +CPPFLAGS = -I.. \ + -I${srcdir} \ + -I${top_srcdir}/compat \ + -I../buffer \ + -I../mmgr \ + @CPPFLAGS@ +CFLAGS = @CFLAGS@ +RANLIB = @RANLIB@ +LIBOBJS = @LIBOBJS@ +@SET_MAKE@ +VPATH = @srcdir@:@top_srcdir@/compat:../buffer:../mmgr + + +### Makefile rules - no user-servicable parts below + +LIBPHCLIENT_OBJS = auth.o \ + change.o \ + fields.o \ + handle.o \ + misc.o \ + options.o \ + ph_buffer.o \ + ph_mmgr.o \ + protocol.o \ + query.o \ + redirection.o \ + serverlist.o \ + siteinfo.o +LIBPHCLIENT_HDRS = ../config.h \ + ${srcdir}/phclient.h \ + ${srcdir}/internal.h \ + ${top_srcdir}/compat/compat.h \ + ../buffer/ph_buffer.h \ + ../mmgr/ph_mmgr.h +ALL = libphclient.a + +DISTCLEANFILES = ../buffer/ph_buffer.c \ + ../buffer/ph_buffer.h \ + ../mmgr/ph_mmgr.c \ + ../mmgr/ph_mmgr.h + + +all: ${ALL} + +.PHONY: clean distclean install + +libphclient.a: ${LIBPHCLIENT_OBJS} ${LIBOBJS} + ${AR} rc libphclient.a ${LIBPHCLIENT_OBJS} ${LIBOBJS} + ${RANLIB} libphclient.a + +${LIBPHCLIENT_OBJS}: ${LIBPHCLIENT_HDRS} + +.c.o: + ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $< + +clean: + rm -f *~ *.o ${ALL} core + +distclean: clean + rm -f Makefile ${DISTCLEANFILES} + +install: all + ${MKDIR} ${DESTDIR}${libdir} + ${INSTALL_DATA} libphclient.a ${DESTDIR}${libdir} + ${MKDIR} ${DESTDIR}${includedir} + ${INSTALL_DATA} ${srcdir}/phclient.h ${DESTDIR}${includedir} + diff --git a/lib/auth.c b/lib/auth.c new file mode 100644 index 0000000..e52bbe3 --- /dev/null +++ b/lib/auth.c @@ -0,0 +1,485 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** auth.c - authentication code for libphclient +** +** Mark D. Roth +*/ + +#include + +#include +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_CRYPT_H +# include +#endif + + +/* function prototypes */ +typedef int (*ph_authfunc_t)(PH *, struct ph_auth *, char *, char *, + char *, size_t); + +static int ph_passwd_auth(PH *, struct ph_auth *, char *, char *, + char *, size_t); +static int ph_email_auth(PH *, struct ph_auth *, char *, char *, + char *, size_t); + + +/* details of each auth type */ +struct authtype +{ + int at_type; /* auth type */ + char *at_logincmd; /* server login command for this auth method */ + char *at_passcmd; /* password or challenge response command */ + ph_authfunc_t at_authfunc; /* function to modify auth token + (optional) */ + int at_denycode; /* reply code sent from server to deny + authentication */ +}; +typedef struct authtype authtype_t; + + +static authtype_t authtypes[] = { + { PH_AUTH_EMAIL, "login", "email", ph_email_auth, LR_NOEMAIL }, + { PH_AUTH_PASSWORD, "login", "answer", ph_passwd_auth, LR_ERROR }, + { PH_AUTH_CLEAR, "login", "clear", NULL, LR_ERROR }, + { 0, NULL, NULL, NULL, 0 } +}; + + +void +ph_free_auth(struct ph_auth *auth) +{ + if (auth->pa_alias != NULL) + free(auth->pa_alias); + if (auth->pa_authkey != NULL) + free(auth->pa_authkey); + free(auth); +} + + +/* +** ph_login() - login to the PH server. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOTLOG authentication denied +*/ +int +ph_login(PH *ph, char *alias, int authtype, void *auth) +{ + int i, code, authslot; + char response[PH_BUF_SIZE]; + char challenge[PH_BUF_SIZE]; + struct ph_auth *authdata; + ph_memblock_t *blockp; + +#ifdef DEBUG + printf("ph_login(): alias=\"%s\", authtype=%d, auth=\"%s\")\n", + alias, authtype, auth); +#endif + + /* find authtype entry */ + for (authslot = 0; authtypes[authslot].at_type != 0; authslot++) + if (authtypes[authslot].at_type == authtype) + break; + if (authtypes[authslot].at_type == 0) + { + errno = EINVAL; + return -1; + } + + /* old alias no longer valid */ + if (ph->ph_auth != NULL) + ph_free_auth(ph->ph_auth); + ph->ph_auth = NULL; + + /* + ** free cached field info, since hidden fields are visible to + ** different users + */ + ph_free_fieldinfo(ph); + + if (ph_mmgr_malloc(ph->ph_mmgr, 0, 1, sizeof(struct ph_auth), + (ph_free_func_t)ph_free_auth, &blockp) == -1) + return -1; + authdata = (struct ph_auth *)ph_mmgr_ptr(blockp); + authdata->pa_alias = strdup(alias); + if (authdata->pa_alias == NULL) + return -1; + authdata->pa_authtype = authtype; + + /* send login command */ + if (ph_send_command(ph, "%s %s", authtypes[authslot].at_logincmd, + alias) == -1) + return -1; + + /* read challenge */ + do + { + if (ph_get_response(ph, &code, challenge, + sizeof(challenge)) == -1) + return -1; + } + while (code < LR_OK); + if (code != LR_LOGIN) + { + errno = EINVAL; + return -1; + } + + /* determine response based on auth method */ + if (authtypes[authslot].at_authfunc != NULL) + { + if ((*(authtypes[authslot].at_authfunc))(ph, authdata, auth, + challenge, response, + sizeof(response)) == -1) + return -1; + } + else + strlcpy(response, auth, sizeof(response)); + + /* send response */ + i = ph_send_command(ph, "%s %s", authtypes[authslot].at_passcmd, + response); + if (i == -1) + return -1; + do + { + if (ph_get_response(ph, &code, NULL, 0) == -1) + return -1; + } + while (code < LR_OK); + + /* successful login or login failed */ + if (code == LR_OK) + { + ph->ph_auth = authdata; + ph_mmgr_free(blockp, 0); + return 0; + } + + if (code == authtypes[authslot].at_denycode) + return PH_ERR_NOTLOG; + + if (code == LR_TEMP) + errno = EAGAIN; + else + errno = EINVAL; + return -1; +} + + +/* plugin function for email authentication */ +static int +ph_email_auth(PH *ph, struct ph_auth *auth, char *password, char *challenge, + char *response, size_t responselen) +{ + struct passwd *pw; +#ifdef HAVE_GETPWUID_R + struct passwd pent; + size_t bufsize; + ph_memblock_t *blockp; + + bufsize = (size_t)sysconf(_SC_GETPW_R_SIZE_MAX); + + if (ph_mmgr_malloc(ph->ph_mmgr, 0, 1, bufsize, free, &blockp) == -1) + return -1; + + getpwuid_r(getuid(), &pent, ph_mmgr_ptr(blockp), bufsize, &pw); +#else /* ! HAVE_GETPWUID_R */ + pw = getpwuid(getuid()); +#endif /* HAVE_GETPWUID_R */ + if (pw == NULL) + { +#ifdef HAVE_GETPWUID_R + ph_mmgr_free(blockp, 1); +#endif /* HAVE_GETPWUID_R */ + return -1; + } + + strlcpy(response, pw->pw_name, responselen); + +#ifdef HAVE_GETPWUID_R + ph_mmgr_free(blockp, 1); +#endif /* HAVE_GETPWUID_R */ + + return 0; +} + + +/* structure and definitions used for encrypted password authentication */ +#define _PH_PWD_ROTORSZ 256 +#define _PH_PWD_MASK 0377 +struct ph_pwcrypt +{ + int n1, n2; + char t1[_PH_PWD_ROTORSZ], t2[_PH_PWD_ROTORSZ], t3[_PH_PWD_ROTORSZ]; +}; + + +/* plugin function for encrypted password authentication */ +static int +ph_passwd_auth(PH *ph, struct ph_auth *auth, char *password, char *challenge, + char *response, size_t responselen) +{ + int i, k, ic, seed, temp; + unsigned random; + char buf[13], scratch[PH_BUF_SIZE]; + char *p, *q; + struct ph_pwcrypt *php; + +#ifdef DEBUG + printf("ph_passwd_crypt(): challenge=\"%s\", password=\"%s\"\n", + challenge, (password ? password : "NULL")); +#endif + + if (auth->pa_authkey == NULL) + { + auth->pa_authkey = (void *)malloc(sizeof(struct ph_pwcrypt)); + if (auth->pa_authkey == NULL) + return -1; + } + + php = (struct ph_pwcrypt *)auth->pa_authkey; + + if (password != NULL) + { + /* initialize arrays */ + memset(auth->pa_authkey, 0, sizeof(struct ph_pwcrypt)); + strncpy(buf, crypt(password, password), 13); + seed = 123; + for (i = 0; i < 13; i++) + seed = seed * buf[i] + i; + for (i = 0; i < _PH_PWD_ROTORSZ; i++) + php->t1[i] = i; + for (i = 0; i < _PH_PWD_ROTORSZ; i++) + { + seed = 5 * seed + buf[i % 13]; + random = seed % 65521; + k = _PH_PWD_ROTORSZ - 1 - i; + ic = (random & _PH_PWD_MASK) % (k + 1); + random >>= 8; + temp = php->t1[k]; + php->t1[k] = php->t1[ic]; + php->t1[ic] = temp; + if (php->t3[k] != 0) + continue; + ic = (random & _PH_PWD_MASK) % k; + while (php->t3[ic] != 0) + ic = (ic + 1) % k; + php->t3[k] = ic; + php->t3[ic] = k; + } + for (i = 0; i < _PH_PWD_ROTORSZ; i++) + php->t2[php->t1[i] & _PH_PWD_MASK] = i; + } + + /* decode challenge into scratch */ + for (p = challenge, q = scratch; + (q - scratch < sizeof(scratch)) && *p; + p++) + { + *q++ = php->t2[(php->t3[(php->t1[(*p + php->n1) & _PH_PWD_MASK] + php->n2) & _PH_PWD_MASK] - php->n2) & _PH_PWD_MASK] - php->n1; + php->n1++; + if (php->n1 == _PH_PWD_ROTORSZ) + { + php->n1 = 0; + php->n2++; + if (php->n2 == _PH_PWD_ROTORSZ) + php->n2 = 0; + } + } + + /* encode as ASCII into response buffer */ + k = q - scratch; + p = response; + q = scratch; + *p++ = (k & 077) + '#'; + for (; (p - response < responselen) && (q - scratch < k); q += 3) + { + *p++ = ((*q >> 2) & 077) + '#'; + *p++ = ((((*q << 4) & 060) | ((q[1] >> 4) & 017)) & 077) + '#'; + *p++ = ((((q[1] << 2) & 074) | ((q[2] >> 6) & 03)) & 077) + '#'; + *p++ = ((q[2] & 077) & 077) + '#'; + } + *p = '\0'; + + return 0; +} + + +/* +** ph_logout() - logout of the PH server. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOTLOG not logged in +*/ +int +ph_logout(PH *ph) +{ + int code; + + if (ph->ph_auth == NULL) + return PH_ERR_NOTLOG; + + /* old alias now invalid */ + ph_free_auth(ph->ph_auth); + ph->ph_auth = NULL; + + /* + ** free cached field info, since hidden fields are visible to + ** different users + */ + ph_free_fieldinfo(ph); + + if (ph_send_command(ph, "logout") == -1) + return -1; + + do + { + if (ph_get_response(ph, &code, NULL, 0) == -1) + return -1; + } + while (code < LR_OK); + + if (code == LR_ERROR) + return PH_ERR_NOTLOG; + if (code == LR_OK) + return 0; + + errno = EINVAL; + return -1; +} + + +/* +** ph_suser() - assume another user's identity (heros only). +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOTHERO not a hero +** PH_ERR_NOTLOG not logged in +*/ +int +ph_suser(PH *ph, char *alias) +{ + int code; + + if (ph->ph_auth == NULL) + return PH_ERR_NOTLOG; + + if (ph_send_command(ph, "suser %s", alias) == -1) + return -1; + + do + { + if (ph_get_response(ph, &code, NULL, 0) == -1) + return -1; + } + while (code < LR_OK); + + if (code == LR_AUTH) + return PH_ERR_NOTHERO; + if (code == LR_OK) + { + /* + ** free cached field info, since hidden fields are visible to + ** different users + */ + ph_free_fieldinfo(ph); + + if (ph->ph_auth->pa_alias != NULL) + free(ph->ph_auth->pa_alias); + ph->ph_auth->pa_alias = strdup(alias); + if (ph->ph_auth->pa_alias != NULL) + return -1; + return 0; + } + + errno = EINVAL; + return -1; +} + + +/* +** ph_passwd() - change the current user's PH password. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOTLOG not logged in +** (any value returned by ph_change()) +*/ +int +ph_passwd(PH *ph, char *newpass) +{ + struct ph_fieldselector selector[2]; + struct ph_fieldselector changes[2]; + char encrypted_passwd[PH_BUF_SIZE]; + int i; + +#ifdef DEBUG + printf("==> ph_passwd(newpass=\"%s\")\n", newpass); +#endif + + /* must be logged in to change password */ + if (ph->ph_auth == NULL) + return PH_ERR_NOTLOG; + + selector[0].pfs_field = "alias"; + selector[0].pfs_operation = '='; + selector[0].pfs_value = ph->ph_auth->pa_alias; + memset(&(selector[1]), 0, sizeof(struct ph_fieldselector)); + + /* generate the encrypted password */ + ph_passwd_auth(ph, ph->ph_auth, NULL, newpass, + encrypted_passwd, sizeof(encrypted_passwd)); +#ifdef DEBUG + printf("encrypted_passwd = \"%s\"\n", encrypted_passwd); +#endif + changes[0].pfs_field = "password"; + changes[0].pfs_operation = '='; + changes[0].pfs_value = encrypted_passwd; + memset(&(changes[1]), 0, sizeof(struct ph_fieldselector)); + +#ifdef DEBUG + puts("calling ph_change()..."); +#endif + + i = ph_change(ph, selector, changes, 0); + if (i == 1) + return 0; + + return i; +} + + +/* +** ph_whoami() - determine the currently logged-in alias +** returns: +** pointer to the current alias success +** NULL not logged in +*/ +char * +ph_whoami(PH *ph) +{ + return (ph->ph_auth != NULL + ? ph->ph_auth->pa_alias + : NULL); +} + + diff --git a/lib/change.c b/lib/change.c new file mode 100644 index 0000000..0780eda --- /dev/null +++ b/lib/change.c @@ -0,0 +1,236 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** change.c - libphclient code to modify server data +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + + +/* +** ph_change() - change a PH entry. +** returns: +** number of entries changed success +** -1 error (sets errno) +** PH_ERR_NOTLOG not logged in +** PH_ERR_DATAERR invalid field data +*/ +int +ph_change(PH *ph, struct ph_fieldselector query[], + struct ph_fieldselector change[], int flags) +{ + char buf[PH_BUF_SIZE]; + size_t buflen = 0; + int code; + +#ifdef DEBUG + puts("==> ph_change()"); +#endif + + /* make sure we're logged in */ + if (ph->ph_auth == NULL) + return PH_ERR_NOTLOG; + + /* encode command */ + buflen = strlcpy(buf, "change", sizeof(buf)); + buflen += ph_decode_selectors(query, buf + buflen, + sizeof(buf) - buflen); + buflen += snprintf(buf + buflen, sizeof(buf) - buflen, " %s", + (BIT_ISSET(flags, PH_CHANGE_FORCE) + ? "force" : "make")); + buflen += ph_decode_selectors(change, buf + buflen, + sizeof(buf) - buflen); + + /* send command */ +#ifdef DEBUG + printf("ph_change(): sending command: \"%s\"\n", buf); +#endif + if (ph_send_command(ph, "%s", buf) == -1) + return -1; + + /* check response code */ + do + { + if (ph_get_response(ph, &code, buf, sizeof(buf)) == -1) + return -1; + } + while (code < LR_OK); + + switch (code) + { + case LR_OK: + /* return number of entries changed */ + return atoi(buf); + + case LR_NOMATCH: + /* + ** no match means 0 entries matched + ** we could also return PH_ERR_NOMATCH here... + */ + return 0; + + case LR_VALUE: + return PH_ERR_DATAERR; + + case LR_NOTLOG: + /* + ** can't happen, since we check for login above + ** but we'll handle it, just in case + */ + return PH_ERR_NOTLOG; + + case LR_READONLY: + return PH_ERR_READONLY; + + default: + break; + } + + /* unknown response code from server, fail with EINVAL */ + errno = EINVAL; + return -1; +} + + +/* +** ph_add() - add a PH entry. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOTLOG not logged in +** PH_ERR_DATAERR invalid field data +*/ +int +ph_add(PH *ph, struct ph_fieldselector fields[]) +{ + int code; + size_t buflen = 0; + char buf[PH_BUF_SIZE]; + + /* make sure we're logged in */ + if (ph->ph_auth == NULL) + return PH_ERR_NOTLOG; + + /* encode command */ + buflen = strlcpy(buf, "add", sizeof(buf)); + buflen += ph_decode_selectors(fields, buf + buflen, + sizeof(buf) - buflen); + + /* send to server */ + if (ph_send_command(ph, "%s", buf) == -1) + return -1; + + /* check response */ + do + { + if (ph_get_response(ph, &code, buf, sizeof(buf)) == -1) + return -1; + } + while (code < LR_OK); + + switch (code) + { + case LR_OK: + return 0; + + case LR_SYNTAX: + return PH_ERR_DATAERR; + + case LR_NOTLOG: + /* + ** can't happen, since we check for login above + ** but we'll handle it, just in case + */ + return PH_ERR_NOTLOG; + + case LR_READONLY: + return PH_ERR_READONLY; + + default: + break; + } + + /* unknown response code from server, fail with EINVAL */ + errno = EINVAL; + return -1; +} + + +/* +** ph_delete() - delete a PH entry. +** returns: +** number of entries deleted success +** -1 error (sets errno) +** PH_ERR_NOTLOG not logged in +*/ +int +ph_delete(PH *ph, struct ph_fieldselector query[]) +{ + char buf[PH_BUF_SIZE]; + int code; + size_t buflen = 0; + + /* make sure we're logged in */ + if (ph->ph_auth == NULL) + return PH_ERR_NOTLOG; + + /* encode command */ + buflen = strlcpy(buf, "delete", sizeof(buf)); + buflen += ph_decode_selectors(query, buf + buflen, + sizeof(buf) - buflen); + + /* send to server */ + if (ph_send_command(ph, "%s", buf) == -1) + return -1; + + /* check response */ + do + { + if (ph_get_response(ph, &code, buf, sizeof(buf)) == -1) + return -1; + } + while (code < LR_OK); + + switch (code) + { + case LR_OK: + return atoi(buf); + + case LR_NOMATCH: + /* + ** no match means 0 entries matched + ** we could also return PH_ERR_NOMATCH here... + */ + return 0; + + case LR_NOTLOG: + /* + ** can't happen, since we check for login above + ** but we'll handle it, just in case + */ + return PH_ERR_NOTLOG; + + case LR_READONLY: + return PH_ERR_READONLY; + + default: + break; + } + + /* unknown response code from server, fail with EINVAL */ + errno = EINVAL; + return -1; +} + + diff --git a/lib/fields.c b/lib/fields.c new file mode 100644 index 0000000..6cf7925 --- /dev/null +++ b/lib/fields.c @@ -0,0 +1,397 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** fields.c - libphclient code to parse server field data +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include + + +struct attriblist +{ + char *name; + unsigned long value; +}; +typedef struct attriblist attriblist_t; + +static attriblist_t attributes[] = { + { "Always", PH_ATTRIB_ALWAYS }, + { "Any", PH_ATTRIB_ANY }, + { "Change", PH_ATTRIB_CHANGE }, + { "Default", PH_ATTRIB_DEFAULT }, + { "Encrypt", PH_ATTRIB_ENCRYPT }, + { "ForcePub", PH_ATTRIB_FORCEPUB }, + { "Indexed", PH_ATTRIB_INDEXED }, + { "LocalPub", PH_ATTRIB_LOCALPUB }, + { "Lookup", PH_ATTRIB_LOOKUP }, + { "NoMeta", PH_ATTRIB_NOMETA }, + { "NoPeople", PH_ATTRIB_NOPEOPLE }, + { "Private", PH_ATTRIB_PRIVATE }, + { "Public", PH_ATTRIB_PUBLIC }, + { "Sacred", PH_ATTRIB_SACRED }, + { "Turn", PH_ATTRIB_TURN }, + { "Unique", PH_ATTRIB_UNIQUE }, + { "PrivLookup", PH_ATTRIB_PRIVLOOKUP }, + { "SacredPerson", PH_ATTRIB_SACREDPERSON }, + { NULL, 0 } +}; + + +int +ph_is_fieldinfo_cached(PH *ph) +{ + return (ph->ph_fieldlist != NULL ? 1 : 0); +} + + +/* ph_free_fieldlist() - free a field list generated by ph_field_list(). */ +static void +ph_free_fieldlist(struct ph_fieldinfo *fi) +{ + int i, j; + +#ifdef DEBUG + printf("==> ph_free_fieldlist(fi=0x%lx)\n", fi); +#endif + + for (i = 0; fi[i].pf_fnames != NULL; i++) + { + for (j = 0; fi[i].pf_fnames[j] != NULL; j++) + free(fi[i].pf_fnames[j]); + free(fi[i].pf_fnames); + if (fi[i].pf_description != NULL) + free(fi[i].pf_description); + } + + free(fi); +} + + +/* maps an attribute string to the corresponding value */ +static unsigned long +ph_field_attrib_value(char *buf) +{ + int i; + + for (i = 0; attributes[i].value != 0; i++) + if (strcasecmp(buf, attributes[i].name) == 0) + break; + + return attributes[i].value; +} + + +/* +** returns bitmask representation for a space-delimited string of +** multiple attributes +*/ +static unsigned long +ph_encode_field_attributes(char *buf) +{ + char *attribp, *nextp; + unsigned long bitmask = 0; + + for (nextp = buf; (attribp = strsep(&nextp, " ")) != NULL;) + { + if (*attribp == '\0') + continue; + BIT_SET(bitmask, ph_field_attrib_value(attribp)); + } + + return bitmask; +} + + +#if 0 +/* maps an attribute value to the corresponding string */ +static char * +ph_field_attrib_string(unsigned long attrib) +{ + int i; + + for (i = 0; attributes[i].value != 0; i++) + if (attributes[i].value == attrib) + break; + + return attributes[i].name; +} +#endif + + +/* +** writes a string of space-delimited attribute names corresponding to +** the numeric bitmask +*/ +void +ph_decode_field_attributes(unsigned long bitmask, char *buf, size_t bufsize) +{ + int i; + size_t buflen = 0; + + buf[0] = '\0'; + + for (i = 0; attributes[i].value != 0; i++) + if (BIT_ISSET(bitmask, attributes[i].value)) + buflen += snprintf(buf + buflen, bufsize - buflen, + "%s ", attributes[i].name); +} + + + +/* +** ph_retrieve_fieldinfo() - obtain a list of fields supported by the PH server. +** returns: +** 0 success +** -1 error (sets errno) +*/ +int +ph_retrieve_fieldinfo(PH *ph) +{ + int numfields = 0, numaliases = 0; + int i, code, id, save_errno; + char *fieldnames, *value, *name; + char buf[PH_BUF_SIZE]; + void *ptr; + ph_memblock_t *blockp; + struct ph_fieldinfo *phfi; + +#ifdef DEBUG + puts("==> ph_retrieve_fieldinfo()"); +#endif + + /* don't load if already cached */ + if (ph_is_fieldinfo_cached(ph)) + return 0; + + /* tell the server to list field aliases, if supported */ + ph_set_option(ph, "fieldaliases", NULL); + + if (ph_mmgr_malloc(ph->ph_mmgr, ph_MMGR_ARRAY, + 0, sizeof(struct ph_fieldinfo), + (ph_free_func_t)ph_free_fieldlist, + &blockp) == -1) + return -1; + phfi = (struct ph_fieldinfo *)ph_mmgr_ptr(blockp); + + if (ph_send_command(ph, "fields") == -1) + return -1; + + while ((i = ph_get_response(ph, &code, buf, sizeof(buf))) == 0) + { +#ifdef DEBUG + printf("ph_retrieve_fieldinfo(): code=%d buf=\"%s\"\n", code, + buf); +#endif + + /* check the response code */ + if (code < LR_OK && code > 0) + continue; + if (code == LR_OK) + { + ph->ph_fieldlist = phfi; + ph_mmgr_free(blockp, 0); + return 0; + } + if (code != -(LR_OK)) + { + ph_mmgr_free(blockp, 1); + errno = EINVAL; + return -1; + } + + /* parse line from server */ + if (ph_parse_response(buf, &id, &fieldnames, &value) == -1) + { + ph_mmgr_free(blockp, 1); + errno = EINVAL; + return -1; + } +#ifdef DEBUG + printf("id=%d fieldnames=\"%s\" value=\"%s\"\n", id, + fieldnames, value); +#endif + + /* allocate memory if it's a new entry */ + if (numfields == 0 + || id != phfi[numfields - 1].pf_id) + { +#ifdef DEBUG + printf("allocating memory - numfields = %d\n", + numfields); +#endif + + if (ph_mmgr_array_add(blockp, numfields + 2) == -1) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; + } + phfi = (struct ph_fieldinfo *)ph_mmgr_ptr(blockp); + + /* set field id */ + phfi[numfields].pf_id = id; + + /* set field names */ + numaliases = 0; + while ((name = strsep(&fieldnames, " ,")) != NULL) + { + ptr = realloc(phfi[numfields].pf_fnames, + (numaliases + 2) * sizeof(char *)); + if (ptr == NULL) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; + } + phfi[numfields].pf_fnames = (char **)ptr; + + phfi[numfields].pf_fnames[numaliases] = strdup(name); + phfi[numfields].pf_fnames[++numaliases] = NULL; + } + + if (phfi[numfields].pf_fnames[0] == NULL) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; + } + + /* set max_size */ + i = sscanf(value, "max %d", + &(phfi[numfields].pf_max_size)); + if (i != 1) + { + ph_mmgr_free(blockp, 1); + errno = EINVAL; + return -1; + } +#ifdef DEBUG + printf("max_size = %d\n", phfi[numfields].pf_max_size); +#endif + + /* extract the field attributes */ +#ifdef DEBUG + printf("attributes = \"%s\"\n", value + 4); +#endif + phfi[numfields].pf_attrib = ph_encode_field_attributes(strchr(value + 4, ' ')); + + numfields++; + + } + else /* second line for this field */ + { + + /* otherwise, extract the description */ +#ifdef DEBUG + printf("description = \"%s\"\n", value); +#endif + phfi[numfields - 1].pf_description = strdup(value); + if (phfi[numfields - 1].pf_description == NULL) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; + } + } + + /* end of loop - call ph_get_response() again */ + } + + /* in case ph_get_response() returned an error */ + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; +} + + +/* +** ph_get_fieldinfo() - return the description for a given field. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_DATAERR unknown field +*/ +int +ph_get_fieldinfo(PH *ph, char *fieldname, struct ph_fieldinfo **fieldinfo) +{ + int i, j; + + if (!ph_is_fieldinfo_cached(ph) + && ph_retrieve_fieldinfo(ph) == -1) + return -1; + + for (i = 0; ph->ph_fieldlist[i].pf_fnames != NULL; i++) + for (j = 0; ph->ph_fieldlist[i].pf_fnames[j] != NULL; j++) + if (strcasecmp(ph->ph_fieldlist[i].pf_fnames[j], + fieldname) == 0) + { + *fieldinfo = &(ph->ph_fieldlist[i]); + return 0; + } + + return PH_ERR_DATAERR; +} + + +/* +** ph_fieldinfo_iterate() - return the next field info structure. +** returns: +** 1 data returned +** 0 no more data +** -1 error (sets errno) +*/ +int +ph_fieldinfo_iterate(PH *ph, struct ph_fieldinfo **fieldinfo) +{ + if (!ph_is_fieldinfo_cached(ph) + && ph_retrieve_fieldinfo(ph) == -1) + return -1; + + /* first entry */ + if (*fieldinfo == NULL) + { + *fieldinfo = &(ph->ph_fieldlist[0]); + return 1; + } + + /* next element */ + (*fieldinfo)++; + if ((*fieldinfo)->pf_fnames != NULL) + return 1; + + /* end of list */ + *fieldinfo = NULL; + return 0; +} + + +/* +** ph_free_fieldinfo() - free fieldlist associated with ph. +*/ +void +ph_free_fieldinfo(PH *ph) +{ + if (ph->ph_fieldlist != NULL) + ph_free_fieldlist(ph->ph_fieldlist); + ph->ph_fieldlist = NULL; +} + + diff --git a/lib/handle.c b/lib/handle.c new file mode 100644 index 0000000..61c654c --- /dev/null +++ b/lib/handle.c @@ -0,0 +1,347 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** handle.c - libphclient code to initialize a PH handle +** +** Mark D. Roth +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_ARPA_AIXRCMDS_H +# include +#endif + + +const char libphclient_version[] = PACKAGE_VERSION; + +const int libphclient_is_thread_safe = +#if defined(HAVE_GETHOSTBYNAME_R) && defined(HAVE_GETSERVBYNAME_R) && defined(HAVE_GETPWUID_R) + 1; +#else + 0; +#endif + + +/* +** ph_open_local() - opens a pipe to a local qi process. +** returns: 0 on success, -1 on error (and sets errno) +*/ +static int +ph_open_local(PH *ph, char *qi_path) +{ + pid_t pid; + + if (pipe(ph->ph_rfd) == -1) + return -1; + if (pipe(ph->ph_wfd) == -1) + { + close(ph->ph_rfd[0]); + ph->ph_rfd[0] = -1; + close(ph->ph_rfd[1]); + ph->ph_rfd[1] = -1; + return -1; + } + + if ((pid = fork()) == -1) + { + close(ph->ph_rfd[0]); + ph->ph_rfd[0] = -1; + close(ph->ph_rfd[1]); + ph->ph_rfd[1] = -1; + close(ph->ph_wfd[0]); + ph->ph_wfd[0] = -1; + close(ph->ph_wfd[1]); + ph->ph_wfd[1] = -1; + return -1; + } + + /* child sets its I/O to the pipe and exec's qi */ + if (pid == 0) + { + if (dup2(ph->ph_wfd[0], 0) == -1 + || dup2(ph->ph_rfd[1], 1) == -1 + || dup2(ph->ph_rfd[1], 2) == -1 + || close(ph->ph_rfd[1]) == -1 + || close(ph->ph_rfd[0]) == -1 + || close(ph->ph_wfd[1]) == -1 + || close(ph->ph_wfd[0]) == -1) + _exit(1); + + if (strchr(qi_path, '/') != NULL) + execl(qi_path, "qi", "-q", NULL); + else + execlp(qi_path, "qi", "-q", NULL); + + /* NOTREACHED */ + _exit(1); + } + + /* parent closes the extra file descriptors and returns */ + close(ph->ph_wfd[0]); + ph->ph_wfd[0] = -1; + close(ph->ph_rfd[1]); + ph->ph_rfd[1] = -1; + + return 0; +} + + +#if MAXPATHLEN > MAXHOSTNAMELEN +# define PH_SERVER_LEN MAXPATHLEN +#else +# define PH_SERVER_LEN MAXHOSTNAMELEN +#endif + + +/* +** ph_rresvport() - thread-safe alternative to rresvport() +*/ +static int +ph_rresvport(int sock) +{ + struct sockaddr_in local_addr; + + memset(&local_addr, 0, sizeof(local_addr)); + local_addr.sin_family = AF_INET; + local_addr.sin_addr.s_addr = INADDR_ANY; + + for (local_addr.sin_port = IPPORT_RESERVED - 1; + local_addr.sin_port > 0; + local_addr.sin_port--) + { + if (bind(sock, (struct sockaddr *)&local_addr, + sizeof(local_addr)) == 0) + return 0; + } + + errno = EADDRINUSE; + return -1; +} + + +/* +** ph_open_remote() - opens a socket to a remote PH server. +** returns: 0 on success, -1 on error (and sets errno) +*/ +static int +ph_open_remote(PH *ph, char *server, int flags) +{ + struct sockaddr_in addr; + int i; + char serverbuf[PH_SERVER_LEN]; + char *cp; + struct hostent *hp; +#ifdef HAVE_GETHOSTBYNAME_R + struct hostent hent; + int h_errno_r; +#endif + struct servent *sp; +#ifdef HAVE_GETSERVBYNAME_R + struct servent sent; +#endif +#if defined(HAVE_GETHOSTBYNAME_R) || defined(HAVE_GETSERVBYNAME_R) + char buf[10240]; +#endif + + addr.sin_family = AF_INET; + strlcpy(serverbuf, server, sizeof(serverbuf)); + + /* set the server's port */ + if ((cp = strchr(server, ':')) != NULL) + { + if ((cp - server) < sizeof(serverbuf)) + serverbuf[cp - server] = '\0'; + addr.sin_port = htons(atoi(++cp)); + } +#ifdef HAVE_GETSERVBYNAME_R + else if (getservbyname_r(PH_SERVICE, "tcp", &sent, + buf, sizeof(buf), &sp) == 0 + || sp == NULL) +#else /* ! HAVE_GETSERVBYNAME_R */ + else if ((sp = getservbyname(PH_SERVICE, "tcp")) != NULL) +#endif /* HAVE_GETSERVBYNAME_R */ + addr.sin_port = sp->s_port; + else + addr.sin_port = htons(PH_PORT); + + /* lookup the server's address */ +#ifdef HAVE_GETHOSTBYNAME_R + if (gethostbyname_r(serverbuf, &hent, buf, sizeof(buf), + &hp, &h_errno_r) != 0 + || hp == NULL) +#else /* ! HAVE_GETHOSTBYNAME_R */ + hp = gethostbyname(serverbuf); + if (hp == NULL) +#endif /* HAVE_GETHOSTBYNAME_R */ + { + errno = EINVAL; + return -1; + } + for (i = 0; hp->h_addr_list[i] != NULL; i++) + { + memmove(&(addr.sin_addr.s_addr), hp->h_addr_list[i], + hp->h_length); + + if ((ph->ph_rfd[0] = socket(PF_INET, SOCK_STREAM, 0)) == -1) + return -1; + + /* bind to a reserved port if appropriate */ + if (BIT_ISSET(flags, PH_OPEN_PRIVPORT) + && ph_rresvport(ph->ph_rfd[0]) == -1) + return -1; + + /* connect to server */ + if (connect(ph->ph_rfd[0], (struct sockaddr *)&addr, + sizeof(addr)) == -1) + { + close(ph->ph_rfd[0]); + ph->ph_rfd[0] = -1; + if (BIT_ISSET(flags, PH_OPEN_ROUNDROBIN)) + continue; + return -1; + } + + return 0; + } + + return -1; +} + + +/* +** ph_open() - opens a connection to the PH server. +** returns: 0 on success, -1 on error (and sets errno) +*/ +int +ph_open(PH **ph, char *server, int flags, + ph_debug_func_t send_hook, ph_debug_func_t recv_hook, + void *hook_data) +{ + int i; + char buf[PH_BUF_SIZE]; + + /* initialize PH data structure */ + *ph = (PH *)calloc(1, sizeof(PH)); + if (*ph == NULL) + return -1; + (*ph)->ph_rfd[0] = -1; + (*ph)->ph_rfd[1] = -1; + (*ph)->ph_wfd[0] = -1; + (*ph)->ph_wfd[1] = -1; + (*ph)->ph_sendhook = send_hook; + (*ph)->ph_recvhook = recv_hook; + (*ph)->ph_hook_data = hook_data; + + /* create network buffer */ + if (ph_buffer_new(&((*ph)->ph_buf), PH_BUF_SIZE, + ph_buffer_read, *ph) == -1) + return -1; + + /* create mmgr handle */ + if (ph_mmgr_init(&((*ph)->ph_mmgr)) == -1) + return -1; + + /* connect to the server */ + if (BIT_ISSET(flags, PH_OPEN_LOCAL)) + i = ph_open_local(*ph, server); + else + i = ph_open_remote(*ph, server, flags); + + if (i == 0 + && !BIT_ISSET(flags, PH_OPEN_DONTID)) + { + snprintf(buf, sizeof(buf), "libphclient-%s", + libphclient_version); + if (ph_id(*ph, buf) == -1) + return -1; + } + + return i; +} + + +/* +** ph_close() - closes a connection to the PH server. +** returns: 0 on success, -1 on error (and sets errno) +*/ +int +ph_close(PH *ph, int flags) +{ + int i, code; + + if (!BIT_ISSET(flags, PH_CLOSE_FAST)) + { + if (ph_send_command(ph, "quit") == -1) + return -1; + while (ph_get_response(ph, &code, NULL, 0) != -1 + && code != LR_OK); + } + + if (ph->ph_wfd[1] >= 0) + { + if (close(ph->ph_wfd[1]) == -1) + return -1; + ph->ph_wfd[1] = -1; + } + if (close(ph->ph_rfd[0]) == -1) + return -1; + ph->ph_rfd[0] = -1; + + if (ph_is_fieldinfo_cached(ph)) + ph_free_fieldinfo(ph); + if (ph_is_optionlist_cached(ph)) + ph_free_options(ph); + if (ph_is_siteinfo_cached(ph)) + ph_free_siteinfo(ph); + if (ph->ph_auth != NULL) + ph_free_auth(ph->ph_auth); + if (ph->ph_mmgr != NULL) + ph_mmgr_cleanup(ph->ph_mmgr); + free(ph); + + return 0; +} + + +/* +** ph_rfd() - return the read file descriptor associated with the PH handle. +*/ +int +ph_rfd(PH *ph) +{ + return ph->ph_rfd[0]; +} + + +/* +** ph_wfd() - return the write file descriptor associated with the PH handle. +*/ +int +ph_wfd(PH *ph) +{ + return (ph->ph_wfd[1] >= 0 + ? ph->ph_wfd[1] + : ph->ph_rfd[0]); +} + + diff --git a/lib/internal.h b/lib/internal.h new file mode 100644 index 0000000..f915fc9 --- /dev/null +++ b/lib/internal.h @@ -0,0 +1,104 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** internal.h - internal header file for libphclient +** +** Mark D. Roth +*/ + +#include + +#include + +#include + +#include +#include + + +#define PH_BUF_SIZE 8192 /* useful constant */ + +#define PH_SERVICE "csnet-ns" /* service name from /etc/services */ +#define PH_PORT 105 /* fallback port number */ + + +/* useful macros */ +#define BIT_ISSET(bitfield, opt) ((bitfield) & (opt)) +#define BIT_SET(bitfield, opt) ((bitfield) |= (opt)) +#define BIT_CLEAR(bitfield, opt) ((bitfield) &= ~(opt)) +#define BIT_TOGGLE(bitfield, opt) { \ + if (BIT_ISSET(bitfield, opt)) \ + BIT_CLEAR(bitfield, opt); \ + else \ + BIT_SET(bitfield, opt); \ + } + + +/* PH server handle */ +struct ph_handle +{ + int ph_rfd[2]; /* file descriptor to read from server */ + int ph_wfd[2]; /* file descriptor to write to server */ + ph_debug_func_t ph_sendhook; /* debug hook for sending */ + ph_debug_func_t ph_recvhook; /* debug hook for receiving */ + void *ph_hook_data; /* app-supplied ptr to pass to hooks */ + ph_buffer_t ph_buf; /* receive buffer */ + struct ph_siteinfo *ph_siteinfo; /* siteinfo list */ + struct ph_fieldinfo *ph_fieldlist; /* field information */ + struct ph_option *ph_options; /* server options */ + struct ph_auth *ph_auth; /* currently logged-in user */ + ph_mmgr_t ph_mmgr; /* memory management handle */ +}; + + +/***** auth.c **********************************************************/ + +/* auth data for current user */ +struct ph_auth +{ + char *pa_alias; + int pa_authtype; + void *pa_authkey; +}; + +/* free ph_auth memory */ +void ph_free_auth(struct ph_auth *); + + +/***** protocol.c ******************************************************/ + +/* buffer plugin to read from server */ +ssize_t ph_buffer_read(void *, char *, size_t); + +/* ph_get_response() - read and parse a response from the server. */ +int ph_get_response(PH *, int *, char *, size_t); + +/* +** ph_parse_response() - utility function to split up ':'-delimited +** sections of the text returned by ph_get_response() +*/ +int ph_parse_response(char *, int *, char **, char **); + +/* ph_send_command() - send a command to the server */ +ssize_t +#ifdef STDC_HEADERS +ph_send_command(PH *, char *, ...); +#else +ph_send_command(PH *, char *, int); +#endif + +/* +** ph_dequote_value() - convert a server-parsable quoted value to a literal +** field value. returns number of characters written. +*/ +size_t ph_dequote_value(char *, char *, size_t); + +/* +** ph_decode_selectors() - decode a ph_fieldselector array into a string +** to send to the server. returns number of characters written. +*/ +size_t ph_decode_selectors(struct ph_fieldselector[], char *, size_t); + + diff --git a/lib/misc.c b/lib/misc.c new file mode 100644 index 0000000..71955be --- /dev/null +++ b/lib/misc.c @@ -0,0 +1,120 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** misc.c - miscellaneous PH access code for libphclient +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +#endif + + +/* +** ph_id() - send id command to server. +** returns: +** 0 success +** -1 error (sets errno) +*/ +int +ph_id(PH *ph, char *id) +{ + int code; + + if (ph_send_command(ph, "id %s", id) == -1) + return -1; + + do + { + if (ph_get_response(ph, &code, NULL, 0) == -1) + return -1; + } + while (code < LR_OK); + + if (code == LR_OK) + return 0; + + errno = EINVAL; + return -1; +} + + +/* +** ph_status() - get status info. +** 0 success +** -1 error (sets errno) +*/ +int +ph_status(PH *ph, char **motd) +{ + int code; + size_t buflen = 0; + char buf[PH_BUF_SIZE]; + void *ptr; + + *motd = NULL; + + if (ph_send_command(ph, "status") == -1) + return -1; + + while (ph_get_response(ph, &code, buf, sizeof(buf)) == 0) + { + if (code != LR_PROGRESS && code < LR_OK && code > 0) + continue; + if (code == LR_OK) + return 0; + if (code != LR_PROGRESS) + { + errno = EINVAL; + return -1; + } + + *motd = (char *)((ptr = realloc(*motd, + buflen + strlen(buf) + 2)) + ? ptr + : *motd); + if (ptr == NULL) + return -1; + buflen += sprintf(*motd + buflen, "%s\n", buf); + } + + return -1; +} + + +/* +** ph_external() - send "external" command. +** 0 success +** -1 error (sets errno) +*/ +int +ph_external(PH *ph) +{ + int code; + + if (ph_send_command(ph, "external") == -1) + return -1; + do + { + if (ph_get_response(ph, &code, NULL, 0) == -1) + return -1; + } + while (code < LR_OK); + + if (code != LR_OK) + { + errno = EINVAL; + return -1; + } + + return 0; +} + + diff --git a/lib/options.c b/lib/options.c new file mode 100644 index 0000000..9b66b17 --- /dev/null +++ b/lib/options.c @@ -0,0 +1,245 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** options.c - libphclient code to handle server options +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include + + +int +ph_is_optionlist_cached(PH *ph) +{ + return (ph->ph_options != NULL ? 1 : 0); +} + + +/* ph_free_optionlist() - free option list. */ +static void +ph_free_optionlist(struct ph_option *opt) +{ + int i; + + for (i = 0; opt[i].po_option != NULL; i++) + { + free(opt[i].po_option); + free(opt[i].po_setting); + } + + free(opt); +} + + +/* +** ph_retrieve_options() - obtain options from server. +** 0 success +** -1 error (sets errno) +*/ +int +ph_retrieve_options(PH *ph) +{ + int code, numopts = 0, save_errno; + char *option, *setting; + char buf[PH_BUF_SIZE]; + void *ptr; + struct ph_option *opt; + ph_memblock_t *blockp; + + /* don't load if already cached */ + if (ph_is_optionlist_cached(ph)) + return 0; + + if (ph_send_command(ph, "set") == -1) + return -1; + + if (ph_mmgr_malloc(ph->ph_mmgr, ph_MMGR_ARRAY, + 0, sizeof(struct ph_option), + (ph_free_func_t)ph_free_optionlist, + &blockp) == -1) + return -1; + opt = (struct ph_option *)ph_mmgr_ptr(blockp); + + while (ph_get_response(ph, &code, buf, sizeof(buf)) == 0) + { + if (code < LR_OK && code > 0) + continue; + if (code == LR_OK) + { + ph->ph_options = opt; + ph_mmgr_free(blockp, 0); + return 0; + } + if (code != -(LR_OK)) + { + ph_mmgr_free(blockp, 1); + errno = EINVAL; + return -1; + } + + if (ph_parse_response(buf, NULL, &option, &setting) == -1) + { + ph_mmgr_free(blockp, 1); + errno = EINVAL; + return -1; + } + + if (ph_mmgr_array_add(blockp, numopts + 2) == -1) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; + } + opt = (struct ph_option *)ph_mmgr_ptr(blockp); + + opt[numopts].po_option = strdup(option); + opt[numopts].po_setting = strdup(setting); + if (opt[numopts].po_option == NULL + || opt[numopts].po_setting == NULL) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; + } + + numopts++; + } + + return 0; +} + + +/* +** ph_set_option() - set an option on the server. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_DATAERR no such option +*/ +int +ph_set_option(PH *ph, char *option, char *setting) +{ + int code, i; + + if (ph_send_command(ph, "set %s%s%s", option, (setting ? "=" : ""), + (setting ? setting : "")) == -1) + return -1; + + do + { + if (ph_get_response(ph, &code, NULL, 0) == -1) + return -1; + } + while (code < LR_OK); + + if (code == LR_OPTION) + return PH_ERR_DATAERR; + if (code != LR_OK) + { + errno = EINVAL; + return -1; + } + + /* if the option list is stored in the local PH handle, update it */ + if (ph_is_optionlist_cached(ph)) + for (i = 0; ph->ph_options[i].po_option != NULL; i++) + if (strcasecmp(ph->ph_options[i].po_option, + option) == 0) + { + free(ph->ph_options[i].po_setting); + ph->ph_options[i].po_setting = strdup(setting + ? setting + : "on"); + if (ph->ph_options[i].po_setting == NULL) + return -1; + break; + } + + return 0; +} + + +/* +** ph_get_option() - obtain the current setting of a given option. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_DATAERR no such option +*/ +int +ph_get_option(PH *ph, char *option, char **setting) +{ + int i; + + if (!ph_is_optionlist_cached(ph) + && ph_retrieve_options(ph) == -1) + return -1; + + for (i = 0; ph->ph_options[i].po_option != NULL; i++) + if (strcasecmp(ph->ph_options[i].po_option, option) == 0) + { + *setting = ph->ph_options[i].po_setting; + return 0; + } + + return PH_ERR_DATAERR; +} + + +/* +** ph_option_iterate() - iterate through server option list. +** returns: +** 1 data returned +** 0 no more data +** -1 error (sets errno) +*/ +int +ph_option_iterate(PH *ph, struct ph_option **svropt) +{ + if (!ph_is_optionlist_cached(ph) + && ph_retrieve_options(ph) == -1) + return -1; + + if (*svropt == NULL) + { + *svropt = &(ph->ph_options[0]); + return 1; + } + + /* get next element */ + (*svropt)++; + if ((*svropt)->po_option != NULL) + return 1; + + /* end of list */ + *svropt = NULL; + return 0; +} + + +/* +** ph_free_options() - free option list associated with PH handle ph. +*/ +void +ph_free_options(PH *ph) +{ + if (ph->ph_options != NULL) + ph_free_optionlist(ph->ph_options); + ph->ph_options = NULL; +} + + diff --git a/lib/phclient.h b/lib/phclient.h new file mode 100644 index 0000000..85a6689 --- /dev/null +++ b/lib/phclient.h @@ -0,0 +1,606 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** phclient.h - main header file for libphclient +** +** Mark D. Roth +*/ + +#ifndef PHCLIENT_H +#define PHCLIENT_H + + +/* general return values */ +#define PH_ERR_NOTLOG -2 /* not logged in */ +#define PH_ERR_NOTHERO -3 /* not hero */ +#define PH_ERR_DATAERR -4 /* invalid field data */ +#define PH_ERR_NOMATCH -5 /* no matching entries found */ +#define PH_ERR_TOOMANY -6 /* too many entries matched */ +#define PH_ERR_READONLY -7 /* database is read-only */ + + +/* PH server handle */ +typedef struct ph_handle PH; + + +/***** auth.c **********************************************************/ + +/* macros for ph_login()'s authtype argument */ + +#ifdef PHLIB_XLOGIN /* not currently supported */ +# define PH_AUTH_FWTK 4 /* TIS authsrv */ +# define PH_AUTH_KRB4 8 /* Kerberos 4 */ +# define PH_AUTH_KRB5 16 /* Kerberos 5 */ +# define PH_AUTH_GSS 32 /* GSS-API */ +#endif + +#define PH_AUTH_EMAIL 64 /* email field */ +#define PH_AUTH_PASSWORD 128 /* encrypted password */ +#define PH_AUTH_CLEAR 256 /* cleartext password */ + + +/* +** ph_login() - login to the PH server. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOTLOG authentication denied +*/ +int ph_login(PH *, char *, int, void *); + +/* +** ph_logout() - logout of the PH server. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOTLOG not logged in +*/ +int ph_logout(PH *); + +/* +** ph_suser() - assume another user's identity (heros only). +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOTHERO not a hero +** PH_ERR_NOTLOG not logged in +*/ +int ph_suser(PH *, char *); + +/* +** ph_passwd() - change the current user's PH password. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOTLOG not logged in +*/ +int ph_passwd(PH *, char *); + +/* +** ph_whoami() - determine the currently logged-in alias +** returns: +** pointer to the current alias success +** NULL not logged in +*/ +char *ph_whoami(PH *); + + +/***** change.c ********************************************************/ + +/* representation of a field selector */ +struct ph_fieldselector +{ + char *pfs_field; + char pfs_operation; /* must be '=', '~', '>', or '<' */ + char *pfs_value; +}; + +/* flags for ph_change() */ +#define PH_CHANGE_FORCE 1 /* use "force" instead of "make" */ + +/* +** ph_change() - change a PH entry. +** returns: +** number of entries changed success +** -1 error (sets errno) +** PH_ERR_NOTLOG not logged in +** PH_ERR_DATAERR invalid field data +*/ +int ph_change(PH *, struct ph_fieldselector[], struct ph_fieldselector[], int); + +/* +** ph_add() - add a PH entry. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOTLOG not logged in +** PH_ERR_DATAERR invalid field data +*/ +int ph_add(PH *, struct ph_fieldselector[]); + +/* +** ph_delete() - delete a PH entry. +** returns: +** number of entries deleted success +** -1 error (sets errno) +** PH_ERR_NOTLOG not logged in +*/ +int ph_delete(PH *, struct ph_fieldselector[]); + + +/***** fields.c ********************************************************/ + +/* values for attribute bitmask */ +#define PH_ATTRIB_ALWAYS 1 +#define PH_ATTRIB_ANY 2 +#define PH_ATTRIB_CHANGE 4 +#define PH_ATTRIB_DEFAULT 8 +#define PH_ATTRIB_ENCRYPT 16 +#define PH_ATTRIB_FORCEPUB 32 +#define PH_ATTRIB_INDEXED 64 +#define PH_ATTRIB_LOCALPUB 128 +#define PH_ATTRIB_LOOKUP 256 +#define PH_ATTRIB_NOMETA 512 +#define PH_ATTRIB_NOPEOPLE 1024 +#define PH_ATTRIB_PRIVATE 2048 +#define PH_ATTRIB_PUBLIC 4096 +#define PH_ATTRIB_SACRED 8192 +#define PH_ATTRIB_TURN 16384 +#define PH_ATTRIB_UNIQUE 32768 +#define PH_ATTRIB_PRIVLOOKUP 65536 +#define PH_ATTRIB_SACREDPERSON 131072 + +/* fields supported by the server */ +struct ph_fieldinfo +{ + int pf_id; + char **pf_fnames; + int pf_max_size; + char *pf_description; + unsigned long pf_attrib; +}; + +/* +** ph_retrieve_fieldinfo() - obtain a list of fields supported by the PH server. +** returns: +** 0 success +** -1 error (sets errno) +*/ +int ph_retrieve_fieldinfo(PH *); + +/* +** writes a string of space-delimited attribute names corresponding to +** the numeric bitmask +*/ +void ph_decode_field_attributes(unsigned long, char *, size_t); + +/* +** ph_get_fieldinfo() - return the description for a given field. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_DATAERR unknown field +*/ +int ph_get_fieldinfo(PH *, char *, struct ph_fieldinfo **); + +/* +** ph_fieldinfo_iterate() - return the next field info structure. +** returns: +** 1 data returned +** 0 no more data +** -1 error (sets errno) +*/ +int ph_fieldinfo_iterate(PH *, struct ph_fieldinfo **); + +/* +** ph_free_fieldinfo() - free fieldlist associated with ph. +*/ +void ph_free_fieldinfo(PH *); + +/* +** ph_is_fieldlist_cached() - check if field list is cached. +** returns: +** 0 not cached +** 1 cached +*/ +int ph_is_fieldlist_cached(PH *); + + +/***** handle.c *******************************************************/ + +extern const char libphclient_version[]; + +extern const int libphclient_is_thread_safe; + +/* typedef for debug hooks */ +typedef void (*ph_debug_func_t)(void *, char *); + + +/* flags for ph_open() */ +#define PH_OPEN_PRIVPORT 1 /* connect from a priveledged port */ +#define PH_OPEN_ROUNDROBIN 2 /* try all addresses of a DNS + round-robin before failing */ +#define PH_OPEN_LOCAL 4 /* open pipe to local PH server + process */ +#define PH_OPEN_DONTID 8 /* don't identify library version + to server */ + +/* flags for ph_close() */ +#define PH_CLOSE_FAST 1 /* drop connection without sending + "quit" */ + + +/* +** ph_open() - opens a connection to the PH server. +** returns: +** 0 success +** -1 error (sets errno) +*/ +int ph_open(PH **, char *, int, ph_debug_func_t, ph_debug_func_t, void *); + +/* +** ph_close() - closes a connection to the PH server. +** 0 success +** -1 error (sets errno) +*/ +int ph_close(PH *, int); + +/* +** ph_rfd() - return the read file descriptor associated with the PH handle. +*/ +int ph_rfd(PH *); + +/* +** ph_wfd() - return the write file descriptor associated with the PH handle. +*/ +int ph_wfd(PH *); + + +/***** misc.c **********************************************************/ + +/* +** ph_id() - send id command to server. +** returns: +** 0 success +** -1 error (sets errno) +*/ +int ph_id(PH *, char *); + +/* +** ph_status() - get status info. +** 0 success +** -1 error (sets errno) +*/ +int ph_status(PH *, char **); + +/* +** ph_external() - send "external" command. +** 0 success +** -1 error (sets errno) +*/ +int ph_external(PH *); + + +/***** options.c *******************************************************/ + +/* options supported by the server */ +struct ph_option +{ + char *po_option; + char *po_setting; +}; + +/* +** ph_retrieve_options() - obtain options from server. +** 0 success +** -1 error (sets errno) +*/ +int ph_retrieve_options(PH *); + +/* +** ph_set_option() - set an option on the server. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_DATAERR no such option +*/ +int ph_set_option(PH *, char *, char *); + +/* +** ph_get_option() - obtain the current setting of a given option. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_DATAERR no such option +*/ +int ph_get_option(PH *, char *, char **); + +/* +** ph_option_iterate() - iterate through server option list. +** returns: +** 1 data returned +** 0 no more data +** -1 error (sets errno) +*/ +int ph_option_iterate(PH *, struct ph_option **); + +/* +** ph_free_options() - free option list associated with PH handle ph. +*/ +void ph_free_options(PH *); + +/* +** ph_is_optionlist_cached() - check if option list is cached. +** returns: +** 0 not cached +** 1 cached +*/ +int ph_is_optionlist_cached(PH *); + + +/***** protocol.c ******************************************************/ + +/* +** server reply codes (from qi distribution): +** 1XX - status +** 2XX - information +** 3XX - additional information or action needed +** 4XX - temporary errors +** 5XX - permanent errors +*/ + +#define LR_PROGRESS 100 /* in progress */ +#define LR_ECHO 101 /* echoing cmd */ +#define LR_NUMRET 102 /* how many entries are being returned */ +#define LR_NONAME 103 /* no hostname found for IP address */ + +#define LR_OK 200 /* success */ +#define LR_RONLY 201 /* database ready in read only mode */ + +#define LR_MORE 300 /* need more info */ +#define LR_LOGIN 301 /* encrypt this string */ +#define LR_XLOGIN 302 /* print this prompt */ + +#define LR_TEMP 400 /* temporary error */ +#define LR_INTERNAL 401 /* database error, possibly temporary */ +#define LR_LOCK 402 /* lock not obtained within timeout period */ +#define LR_COULDA_BEEN 403 /* login would have been ok but db read only */ +#define LR_DOWN 475 /* database unavailable; try again later */ + +#define LR_ERROR 500 /* hard error; general */ +#define LR_NOMATCH 501 /* no matches to query */ +#define LR_TOOMANY 502 /* too many matches to query */ +#define LR_AINFO 503 /* may not see that field */ +#define LR_ASEARCH 504 /* may not search on that field */ +#define LR_ACHANGE 505 /* may not change field */ +#define LR_NOTLOG 506 /* must be logged in */ +#define LR_FIELD 507 /* field unknown */ +#define LR_ABSENT 508 /* field not present in entry */ +#define LR_ALIAS 509 /* requested alias is already in use */ +#define LR_AENTRY 510 /* may not change entry */ +#define LR_ADD 511 /* may not add entries */ +#define LR_VALUE 512 /* illegal value */ +#define LR_OPTION 513 /* unknown option */ +#define LR_UNKNOWN 514 /* unknown command */ +#define LR_NOKEY 515 /* no indexed field found in query */ +#define LR_AUTH 516 /* no authorization for query */ +#define LR_READONLY 517 /* operation failed; database is read-only */ +#define LR_LIMIT 518 /* too many entries selected for change */ +#define LR_HISTORY 519 /* history substitution failed (obsolete) */ +#define LR_XCPU 520 /* too much cpu used */ +#define LR_ADDONLY 521 /* addonly option set and change command + applied to a field with data */ +#define LR_ISCRYPT 522 /* attempt to view encrypted field */ +#define LR_NOANSWER 523 /* "answer" was expected but not gotten */ +#define LR_BADHELP 524 /* help topics cannot contain slashes */ +#define LR_NOEMAIL 525 /* email authentication failed */ +#define LR_NOADDR 526 /* host name address not found in DNS */ +#define LR_MISMATCH 527 /* host = gethostbyaddr(foo); foo != gethostbyname(host) */ +#define LR_KDB5 528 /* general kerberos database error */ +#define LR_NOAUTH 529 /* selected authentication method not avail */ +#define LR_NOCMD 598 /* no such command */ +#define LR_SYNTAX 599 /* syntax error */ + +/* +** ph_set_sendhook() - set the send hook function. +*/ +void ph_set_sendhook(PH *, ph_debug_func_t); + +/* +** ph_set_recvhook() - set the receive hook function. +*/ +void ph_set_recvhook(PH *, ph_debug_func_t); + +/* +** ph_set_hookdata() - set the hook data to be passed to the debug hooks +*/ +void ph_set_hookdata(PH *, void *); + +/* +** ph_encode_selector() - parse the selector string and add an entry to +** the selectors array. +** returns: +** 0 success +** -1 parse error +*/ +int ph_encode_selector(char *, int, int *, struct ph_fieldselector **); + +/* +** ph_free_selectors() - free memory associated with an array of selectors +*/ +void ph_free_selectors(struct ph_fieldselector *); + + +/***** query.c *********************************************************/ + +struct ph_fieldvalue +{ + int pfv_code; + char *pfv_field; + char *pfv_value; +}; + +typedef struct ph_fieldvalue *ph_entry; + +/* +** ph_query() - send a query to the PH server and return matching entries. +** returns: +** number of entries returned success +** -1 error (sets errno) +** PH_ERR_TOOMANY too many entries matched +** PH_ERR_NOMATCH no matching entries +** PH_ERR_DATAERR invalid query +*/ +int ph_query(PH *, struct ph_fieldselector[], char *[], + ph_entry **); + +/* +** ph_free_entries() - free memory returned by ph_query(). +*/ +void ph_free_entries(ph_entry *); + + +/***** redirection.c **************************************************/ + +/* +** ph_advertised_email() - returns alias-based email address for alias +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOMATCH alias does not exist +** PH_ERR_DATAERR no email field +*/ +int ph_advertised_email(PH *, char *, int, char **); + +/* +** ph_email_resolve() - returns the expanded email address for user +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOMATCH no single match found +** PH_ERR_DATAERR no email field +*/ +int ph_email_resolve(PH *, char *, char *, char **); + +/* +** ph_advertised_www() - returns alias-based URL for alias +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOMATCH alias does not exist +** PH_ERR_DATAERR no www field +*/ +int ph_advertised_www(PH *, char *, int, char **); + +/* +** ph_www_resolve() - returns the expanded URL for user +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOMATCH no single entry matched +** PH_ERR_DATAERR no www field +*/ +int ph_www_resolve(PH *, char *, char **); + + +/***** serverlist.c ****************************************************/ + +/* structure to describe other PH servers */ +struct ph_serversite +{ + char *ss_server; + char *ss_site; +}; + +struct ph_serverlist +{ + struct ph_serversite *sl_list; + unsigned int sl_numservers; +}; + + +/* +** ph_serverlist_add() - add an entry to a list of known PH servers. +** returns: +** 0 success +** -1 error (sets errno) +*/ +int ph_serverlist_add(struct ph_serverlist *, char *, char *); + +/* +** ph_serverlist_iterate() - iterate through all matching PH server entries. +** returns: +** 1 data returned +** 0 no more data +** -1 error (sets errno) +*/ +int ph_serverlist_iterate(struct ph_serverlist *, char *, char *, + struct ph_serversite **); + +/* +** ph_serverlist_merge() - read list of known PH servers from the server +** associated with ph and merge them into serverlist. +** returns: +** 0 success +** -1 error (sets errno) +*/ +int ph_serverlist_merge(PH *, struct ph_serverlist *); + +/* +** ph_free_serverlist() - free memory associated with serverlist. +*/ +void ph_free_serverlist(struct ph_serverlist *); + + +/***** siteinfo.c ******************************************************/ + +/* siteinfo provided by the server */ +struct ph_siteinfo +{ + char *ps_info; + char *ps_data; +}; + +/* +** ph_retrieve_siteinfo() - read siteinfo from server. +** returns: +** 0 success +** -1 error (sets errno) +*/ +int ph_retrieve_siteinfo(PH *); + +/* +** ph_get_siteinfo() - return the value of a specific info field. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_DATAERR unknown siteinfo field +*/ +int ph_get_siteinfo(PH *, char *, char **); + +/* +** ph_siteinfo_iterate() - iterate through siteinfo list. +** returns: +** 1 data returned +** 0 no more data +** -1 error (sets errno) +*/ +int ph_siteinfo_iterate(PH *, struct ph_siteinfo **); + +/* +** ph_free_siteinfo() - free the siteinfo list associated with ph. +*/ +void ph_free_siteinfo(PH *); + +/* +** ph_is_siteinfo_cached() - check if siteinfo data is cached. +** returns: +** 0 not cached +** 1 cached +*/ +int ph_is_siteinfo_cached(PH *); + + +#endif /* PHCLIENT_H */ diff --git a/lib/protocol.c b/lib/protocol.c new file mode 100644 index 0000000..6c88122 --- /dev/null +++ b/lib/protocol.c @@ -0,0 +1,499 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** protocol.c - libphclient protocol code +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +# include +# include +#else +# ifdef HAVE_VARARGS_H +# include +# endif +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_SYS_POLL_H +# include +#else +# ifdef HAVE_SYS_SELECT_H +# include +# endif +#endif + + +/* +** ph_set_sendhook() - set the send hook function. +*/ +void +ph_set_sendhook(PH *ph, ph_debug_func_t sendfunc) +{ + ph->ph_sendhook = sendfunc; +} + +/* +** ph_set_recvhook() - set the receive hook function. +*/ +void +ph_set_recvhook(PH *ph, ph_debug_func_t recvfunc) +{ + ph->ph_recvhook = recvfunc; +} + +/* +** ph_set_hookdata() - set the hook data to be passed to the debug hooks +*/ +void +ph_set_hookdata(PH *ph, void *hook_data) +{ + ph->ph_hook_data = hook_data; +} + + +/* buffer plugin to read from server */ +ssize_t +ph_buffer_read(void *app_data, char *buf, size_t buflen) +{ + PH *ph = (PH *)app_data; + + return read(ph->ph_rfd[0], buf, buflen); +} + + +/* ph_get_response() - read and parse a response from the server. */ +int +ph_get_response(PH *ph, int *code, char *buf, size_t bufsize) +{ + char linebuf[PH_BUF_SIZE]; + char *linep, *fieldp; + ssize_t sz; + + if (ph_buffer_read_line(ph->ph_buf, linebuf, sizeof(linebuf)) == -1) + return -1; + + /* call receive hook, if set */ + if (ph->ph_recvhook != NULL) + (*(ph->ph_recvhook))(ph->ph_hook_data, linebuf); + + /* blank line */ + if (linebuf[0] == '\0') + { + errno = EINVAL; + return -1; + } + + /* extract response code */ + linep = linebuf; + fieldp = strsep(&linep, ":"); + if (sscanf(fieldp, "%d", code) != 1) + { + errno = EINVAL; + return -1; + } + + /* response code with no text */ + if (linep == NULL) + { + if (buf != NULL) + buf[0] = '\0'; + errno = EINVAL; + return -1; + } + + /* valid line, copy it to caller-supplied buffer */ + if (buf != NULL) + strlcpy(buf, linep, bufsize); + + return 0; +} + + +/* +** ph_parse_response() - utility function to split up ':'-delimited +** sections of the text returned by ph_get_response() +*/ +int +ph_parse_response(char *buf, int *subcode, char **field1, char **field2) +{ + /* extract entry number */ + if (subcode != NULL) + { + if (sscanf(buf, "%d:", subcode) != 1) + { + errno = EINVAL; + return -1; + } + strsep(&buf, ":"); + } + + /* extract fields */ + if (field1 != NULL) + { + *field1 = strsep(&buf, ":"); + if (*field1 == NULL) + { + errno = EINVAL; + return -1; + } + } + if (field2 != NULL) + { + *field2 = buf; + if (*field2 == NULL) + { + errno = EINVAL; + return -1; + } + } + + return 0; +} + + +/* ph_send_command() - send a command to the server */ +ssize_t +#ifdef STDC_HEADERS +ph_send_command(PH *ph, char *fmt, ...) +#else +ph_send_command(PH *ph, char *fmt, int va_alist) +#endif +{ + va_list args; + char buf[PH_BUF_SIZE]; + int fd; +#ifdef HAVE_POLL + struct pollfd pfd[1]; +#else /* ! HAVE_POLL */ + fd_set wfds, efds; + int max; + struct timeval tm; +#endif /* HAVE_POLL */ + + fd = ph_wfd(ph); + +#ifdef HAVE_POLL + memset(pfd, 0, sizeof(pfd)); + pfd[0].events = POLLOUT; + pfd[0].fd = fd; + if (poll(pfd, 1, 0) == -1) + return -1; + if (! BIT_ISSET(pfd[0].revents, POLLOUT)) + { + errno = EPIPE; + return -1; + } +#else /* ! HAVE_POLL */ + FD_ZERO(&wfds); + FD_ZERO(&efds); + FD_SET(fd, &wfds); + FD_SET(fd, &efds); + memset(&tm, 0, sizeof(tm)); + if (select(fd + 1, NULL, &wfds, &efds, &tm) == -1) + return -1; + if (! FD_ISSET(fd, &wfds) || FD_ISSET(fd, &efds)) + { + errno = EPIPE; + return -1; + } +#endif /* HAVE_POLL */ + +#ifdef STDC_HEADERS + va_start(args, fmt); +#else + va_start(args); +#endif + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + +#ifdef DEBUG + printf("ph_send_command(): sending \"%s\"\n", buf); +#endif + + /* execute the send hook, if set */ + if (ph->ph_sendhook != NULL) + (*(ph->ph_sendhook))(ph->ph_hook_data, buf); + + strlcat(buf, "\n", sizeof(buf)); + return write(fd, buf, strlen(buf) + 1); +} + + +/* +** ph_quote_value() - convert a literal field value to a server-parsable +** quoted string. returns number of characters written. +*/ +static size_t +ph_quote_value(char *value, char *buf, size_t bufsize) +{ + char tmpbuf[PH_BUF_SIZE]; + char *sp, *p, *q; + char c; + + /* + ** FIXME: need to check return value from strlcpy() and strlcat() + */ + + strlcpy(tmpbuf, value, sizeof(tmpbuf)); + strlcat(buf, "\"", bufsize); + + for (sp = tmpbuf, p = strpbrk(sp, "\n\t\"\\"); + p != NULL; + sp = p + 1, p = strpbrk(sp, "\n\t\"\\")) + { + c = *p; + *p = '\0'; + strlcat(buf, sp, bufsize); + + switch (c) + { + case '\n': + q = "\\n"; + break; + case '\t': + q = "\\t"; + break; + case '\\': + q = "\\\\"; + break; + case '"': + if (p == value || *(p - 1) != '\\') + q = "\\\""; + else + q = "\""; + break; + default: + q = ""; + break; + } + if (strlen(q) != 0) + strlcat(buf, q, bufsize); + } + strlcat(buf, sp, bufsize); + + return strlcat(buf, "\"", bufsize); +} + + +/* +** ph_dequote_value() - convert a server-parsable quoted value to a literal +** field value. returns number of characters written. +*/ +size_t +ph_dequote_value(char *value, char *buf, size_t bufsize) +{ + size_t sz; + char *sp, *p; + +#ifdef DEBUG + printf("==> ph_dequote_value(\"%s\")\n", value); +#endif + + sz = strlcpy(buf, value, bufsize); + + /* first, eliminate the non-escaped quotes */ + for (sp = buf; (p = strchr(sp, '"')) != NULL; sp = p) + if (p == buf || *(p - 1) != '\\') + { + memmove(p, p + 1, strlen(p + 1) + 1); + sz--; + } + else + p++; + + /* change ``\\"'' to "\\\"" and ``\"'' to "\"" */ + for (sp = buf; (p = strstr(sp, "\\\"")) != NULL; sp = p) + { + if (p == buf || *(p - 1) == '\\') + memmove(p - 1, p, strlen(p) + 1); + else + { + *p = '"'; + memmove(p + 1, p + 2, strlen(p + 2) + 1); + } + sz--; + } + + /* change ``\\n'' to "\\n" and ``\n'' to "\n" */ + for (sp = buf; (p = strstr(sp, "\\n")) != NULL; sp = p) + { + if (p == buf || *(p - 1) == '\\') + memmove(p - 1, p, strlen(p) + 1); + else + { + *p = '\n'; + memmove(p + 1, p + 2, strlen(p + 2) + 1); + } + sz--; + } + + /* change ``\\t'' to "\\t" and ``\t'' to "\t" */ + for (sp = buf; (p = strstr(sp, "\\t")) != NULL; sp = p) + { + if (p == buf || *(p - 1) == '\\') + memmove(p - 1, p, strlen(p) + 1); + else + { + *p = '\t'; + memmove(p + 1, p + 2, strlen(p + 2) + 1); + } + sz--; + } + + /* change ``\\'' to "\\" and ``\'' to "" */ + for (sp = buf; (p = strstr(sp, "\\\\")) != NULL; sp = p) + { + if (p == buf || *(p - 1) == '\\') + memmove(p - 1, p, strlen(p) + 1); + else + { + *p = '"'; + memmove(p + 1, p + 2, strlen(p + 2) + 1); + } + sz--; + } + + return sz; +} + + +/* +** ph_decode_selectors() - decode a ph_fieldselector array into a string +** to send to the server. returns number of characters written. +*/ +size_t +ph_decode_selectors(struct ph_fieldselector selectors[], + char *buf, size_t bufsize) +{ + int i; + size_t buflen = 0; + + for (i = 0; selectors[i].pfs_value != NULL; i++) + { + buflen = strlcat(buf, " ", bufsize); + if (selectors[i].pfs_field != NULL + && selectors[i].pfs_field[0] != '\0') + buflen += snprintf(buf + buflen, bufsize - buflen, + "%s%c", + selectors[i].pfs_field, + selectors[i].pfs_operation); + buflen += ph_quote_value(selectors[i].pfs_value, buf + buflen, + bufsize - buflen); + } + + return buflen; +} + + +/* +** ph_encode_selector() - parse the selector string and add an entry to +** the selectors array. +** returns: +** 0 success +** -1 parse error +*/ +int +ph_encode_selector(char *string, int requirefield, int *lastindex, + struct ph_fieldselector **selectors) +{ + char *p; + char buf[PH_BUF_SIZE], valbuf[PH_BUF_SIZE]; + char op; + void *ptr; + +#ifdef DEBUG + printf("==> ph_encode_selector(\"%s\")\n", string); +#endif + + strlcpy(buf, string, sizeof(buf)); + + /* check for an operator */ + p = strpbrk(buf, "=><~"); + if (p == NULL + && requirefield) + { + errno = EINVAL; + return -1; + } + + /* allocate memory */ + ptr = realloc(*selectors, + (*lastindex + 2) * sizeof(struct ph_fieldselector)); + if (ptr == NULL) + return -1; + *selectors = (struct ph_fieldselector *)ptr; + memset(&((*selectors)[*lastindex]), 0, + 2 * sizeof(struct ph_fieldselector)); + + if (p != NULL) + { + /* encode field and operator */ + op = *p; + *p++ = '\0'; + (*selectors)[*lastindex].pfs_field = strdup(buf); + if ((*selectors)[*lastindex].pfs_field == NULL) + return -1; + (*selectors)[*lastindex].pfs_operation = op; + } + else + /* set p to point to value */ + p = buf; + + /* encode value */ + ph_dequote_value(p, valbuf, sizeof(valbuf)); + (*selectors)[*lastindex].pfs_value = strdup(valbuf); + if ((*selectors)[*lastindex].pfs_value == NULL) + return -1; + +#ifdef DEBUG + printf("field=\"%s\", value=\"%s\"\n", + (*selectors)[*lastindex].pfs_field + ? (*selectors)[*lastindex].pfs_field + : "NULL", + (*selectors)[*lastindex].pfs_value + ? (*selectors)[*lastindex].pfs_value + : "NULL"); +#endif + + /* increment last index */ + (*lastindex)++; + + return 0; +} + + +/* +** ph_free_selectors() - free memory associated with an array of selectors +*/ +void +ph_free_selectors(struct ph_fieldselector *selectors) +{ + int i; + + if (selectors == NULL) + return; + + for (i = 0; selectors[i].pfs_value != NULL; i++) + { + if (selectors[i].pfs_field != NULL) + free(selectors[i].pfs_field); + if (selectors[i].pfs_value != NULL) + free(selectors[i].pfs_value); + } + + free(selectors); +} + + diff --git a/lib/query.c b/lib/query.c new file mode 100644 index 0000000..c1937d1 --- /dev/null +++ b/lib/query.c @@ -0,0 +1,206 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** query.c - libphclient query code +** +** Mark D. Roth +*/ + +#include + +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + + +/* +** ph_query() - send a query to the PH server and return matching entries. +** returns: +** number of entries returned success +** -1 error (sets errno) +** PH_ERR_TOOMANY too many entries matched +** PH_ERR_NOMATCH no matching entries +** PH_ERR_DATAERR invalid query +*/ +int +ph_query(PH *ph, struct ph_fieldselector query[], char *retfields[], + ph_entry **entries) +{ + int i; + size_t sz, buflen = 0; + char buf[PH_BUF_SIZE]; + int code, entrynum; + int numresponses = 0, numfields = 0; + char *field, *value; + void *ptr; + ph_entry entry; + +#ifdef DEBUG + puts("==> ph_query()"); + for (i = 0; query[i].pfs_field; i++) + printf(" query[%d]: %s%c%s\n", + i, query[i].pfs_field, query[i].pfs_operation, + query[i].pfs_value); +#endif + + /* important initialization */ + *entries = NULL; + + /* construct the query command */ + buflen = sprintf(buf, "query"); + buflen += ph_decode_selectors(query, buf + buflen, + sizeof(buf) - buflen); + if (retfields != NULL) + { + buflen = strlcat(buf, " return", sizeof(buf)); + for (i = 0; retfields[i] != NULL; i++) + buflen += snprintf(buf + buflen, sizeof(buf) - buflen, + " %s", retfields[i]); + } + + /* send the query command */ +#ifdef DEBUG + printf("ph_query(): sending query: \"%s\"\n", buf); +#endif + if (ph_send_command(ph, "%s", buf) == -1) + return -1; + + /* read the server response */ + while (ph_get_response(ph, &code, buf, sizeof(buf)) == 0) + { +#ifdef DEBUG + printf("top of ph_get_response() loop: code=%d, buf=\"%s\"\n", + code, buf); +#endif + + /* check response code */ + if ((code < LR_OK && code > 99) + || (code < 0 && !isdigit((int)buf[0]))) + continue; + if (code == LR_OK || code == LR_NOMATCH) + return (numresponses > 0 + ? numresponses + : PH_ERR_NOMATCH); + if (code == LR_TOOMANY) + return PH_ERR_TOOMANY; + if (code > 0) + return PH_ERR_DATAERR; + + /* parse the response text */ + if (ph_parse_response(buf, &entrynum, &field, &value) == -1) + return -1; + + sz = strspn(field, " "); + + /* first field of a new entry */ + if (entrynum > numresponses) + { + /* + ** field name can't be all spaces on first line + ** of a new entry + */ + if (sz == strlen(field)) + { + errno = EINVAL; + return -1; + } + + ptr = realloc(*entries, + (entrynum + 1) * sizeof(ph_entry)); + if (ptr == NULL) + return -1; + *entries = (ph_entry *)ptr; + memset(&((*entries)[entrynum - 1]), 0, + (entrynum - numresponses + 1) * sizeof(ph_entry)); + numresponses = entrynum; + numfields = 0; + } + + value += strspn(value, " "); + + /* + ** if field name is all spaces, value should be appended + ** to last field + */ + if (sz == strlen(field)) + { +#ifdef DEBUG + printf("old value: (length = %d) \"%s\"\n", + strlen(entry[numfields - 1].pfv_value), + entry[numfields - 1].pfv_value); + printf("new value: (length = %d) \"%s\"\n", + strlen(value), value); +#endif + sz = strlen(entry[numfields - 1].pfv_value) + strlen(value) + 2; + ptr = realloc(entry[numfields - 1].pfv_value, sz); + if (ptr == NULL) + return -1; + entry[numfields - 1].pfv_value = (char *)ptr; + strlcat(entry[numfields - 1].pfv_value, "\n", sz); + if (value[0] != '\0') + strlcat(entry[numfields - 1].pfv_value, + value, sz); +#ifdef DEBUG + printf("combined value: (length = %d) \"%s\"\n", + strlen(entry[numfields - 1].pfv_value), + entry[numfields - 1].pfv_value); +#endif + } + else + { + /* new field */ + ptr = realloc((*entries)[entrynum - 1], + (numfields + 2) * sizeof(struct ph_fieldvalue)); + if (ptr == NULL) + return -1; + (*entries)[entrynum - 1] = (struct ph_fieldvalue *)ptr; + entry = (*entries)[entrynum - 1]; + memset(entry + numfields, 0, + 2 * sizeof(struct ph_fieldvalue)); + entry[numfields].pfv_field = strdup(field + sz); + entry[numfields].pfv_value = strdup(value); + if (entry[numfields].pfv_field == NULL + || entry[numfields].pfv_value == NULL) + return -1; + entry[numfields].pfv_code = code; + numfields++; + } + } + +#ifdef DEBUG + puts("ph_query(): reached end of ph_get_response() loop!"); +#endif + return -1; +} + + +/* +** ph_free_entries() - free memory returned by ph_query(). +*/ +void +ph_free_entries(ph_entry *entries) +{ + int i, j; + + if (entries == NULL) + return; + + for (i = 0; entries[i] != NULL; i++) + { + for (j = 0; entries[i][j].pfv_field != NULL; j++) + { + free(entries[i][j].pfv_field); + free(entries[i][j].pfv_value); + } + free(entries[i]); + } + free(entries); +} + + diff --git a/lib/redirection.c b/lib/redirection.c new file mode 100644 index 0000000..ec1a1e2 --- /dev/null +++ b/lib/redirection.c @@ -0,0 +1,521 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** redirection.c - libphclient code to select entries from the server +** +** Mark D. Roth +*/ + +#include + +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include + + +/* +** FIXME: can I generalize this further to help simplify ph_email_resolve() ? +*/ +static int +_ph_get_alias_field(PH *ph, char *alias, char *field, char **valuep) +{ + int i, save_errno; + char *getfields[2]; + struct ph_fieldselector query[2]; + ph_memblock_t *blockp; + ph_entry *entries; + + /* construct query */ + query[0].pfs_field = "alias"; + query[0].pfs_operation = '='; + query[0].pfs_value = alias; + memset(&(query[1]), 0, sizeof(struct ph_fieldselector)); + getfields[0] = field; + getfields[1] = NULL; + + if (ph_mmgr_malloc(ph->ph_mmgr, 0, 0, 0, + (ph_free_func_t)ph_free_entries, + &blockp) == -1) + return -1; + + i = ph_query(ph, query, getfields, + (ph_entry **)&(ph_mmgr_ptr(blockp))); + + if (i <= 0) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return i; + } + + entries = (ph_entry *)ph_mmgr_ptr(blockp); + + if (strcasecmp(entries[0][0].pfv_field, field) != 0) + { + ph_mmgr_free(blockp, 1); + errno = EINVAL; + return -1; + } + + if (entries[0][0].pfv_code != -(LR_OK) + || entries[0][0].pfv_value[0] == '\0') + { + ph_mmgr_free(blockp, 1); + return PH_ERR_DATAERR; + } + + if (valuep != NULL) + { + *valuep = strdup(entries[0][0].pfv_value); + if (*valuep == NULL) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; + } + } + + ph_mmgr_free(blockp, 1); + return 0; +} + + +/* +** ph_advertised_email() - returns alias-based email address for alias +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOMATCH alias does not exist +** PH_ERR_DATAERR no email field +*/ +int +ph_advertised_email(PH *ph, char *alias, int confirm_alias, + char **advertised_email) +{ + int i, save_errno; + char *maildomain, *mailfield; + void *ptr; + + /* check siteinfo for the field name */ + i = ph_get_siteinfo(ph, "mailfield", &mailfield); + if (i == -1) + return -1; + if (i == PH_ERR_DATAERR) + { + errno = EINVAL; + return -1; + } + + /* shortcut */ + if (strcasecmp(mailfield, "alias") == 0 && !confirm_alias) + *advertised_email = strdup(alias); + else + { + i = _ph_get_alias_field(ph, alias, mailfield, + advertised_email); + if (i != 0) + return i; + } + + /* check siteinfo for the maildomain and append it if found */ + i = ph_get_siteinfo(ph, "maildomain", &maildomain); + if (i == -1) + return -1; + if (i == 0) + { + ptr = realloc(*advertised_email, + strlen(*advertised_email) + strlen(maildomain) + 2); + if (ptr == NULL) + { + save_errno = errno; + free(*advertised_email); + *advertised_email = NULL; + errno = save_errno; + return -1; + } + + *advertised_email = (char *)ptr; + sprintf(*advertised_email + strlen(*advertised_email), "@%s", + maildomain); + } + + return 0; +} + + +/* create a multiple-word name query */ +static int +rewrite_name(char *field, char *user, struct ph_fieldselector **phf) +{ + char buf[PH_BUF_SIZE]; + int i, numfields; + char *fieldp, *nextp; + void *ptr; + + strlcpy(buf, user, sizeof(buf)); + for (i = 0; buf[i] != '\0'; i++) + if (ispunct((int)buf[i]) && buf[i] != '*') + buf[i] = ' '; + + /* if the name is all spaces, bail out */ + if (strspn(buf, " ") == strlen(buf)) + return PH_ERR_DATAERR; + + numfields = 0; + nextp = buf; + *phf = NULL; + while ((fieldp = strsep(&nextp, " ")) != NULL) + { + if (*fieldp == '\0') + continue; + + ptr = realloc(*phf, (numfields + 2) * sizeof(struct ph_fieldselector)); + if (ptr == NULL) + return -1; + *phf = (struct ph_fieldselector *)ptr; + memset(&((*phf)[numfields]), 0, + 2 * sizeof(struct ph_fieldselector)); + (*phf)[numfields].pfs_field = NULL; + (*phf)[numfields].pfs_operation = '='; + (*phf)[numfields].pfs_value = strdup(fieldp); + if ((*phf)[numfields].pfs_value == NULL) + return -1; + numfields++; + } + + return 0; +} + + +/* replace all punctuation characters in alias query with dashes */ +static int +rewrite_alias(char *field, char *user, struct ph_fieldselector **phf) +{ + char buf[PH_BUF_SIZE]; + int i; + + strlcpy(buf, user, sizeof(buf)); + for (i = 0; buf[i] != '\0'; i++) + if (ispunct((int)buf[i])) + buf[i] = '-'; + + *phf = (struct ph_fieldselector *)calloc(2, sizeof(struct ph_fieldselector)); + if (*phf == NULL) + return -1; + + (*phf)[0].pfs_operation = '='; + (*phf)[0].pfs_field = strdup(field); + (*phf)[0].pfs_value = strdup(buf); + if ((*phf)[0].pfs_field == NULL || (*phf)[0].pfs_value == NULL) + return -1; + + return 0; +} + + +/* default action - look up user without rewriting */ +static int +no_rewrite(char *field, char *user, struct ph_fieldselector **phf) +{ + *phf = (struct ph_fieldselector *)calloc(2, sizeof(struct ph_fieldselector)); + if (*phf == NULL) + return -1; + + (*phf)[0].pfs_operation = '='; + (*phf)[0].pfs_field = strdup(field); + (*phf)[0].pfs_value = strdup(user); + if ((*phf)[0].pfs_field == NULL || (*phf)[0].pfs_value == NULL) + return -1; + + return 0; +} + + +typedef int (*rewritefunc_t)(char *, char *, struct ph_fieldselector **); + +struct field_rewrite_map +{ + char *field; + rewritefunc_t rewrite_funcs[3]; +}; +typedef struct field_rewrite_map field_rewrite_map_t; + +static const field_rewrite_map_t rewrite_map[] = { + { "alias", { rewrite_alias, NULL } }, + { "name", { no_rewrite, rewrite_name, NULL } }, + { NULL, { no_rewrite, NULL } } +}; + + +/* +** ph_email_resolve() - returns the expanded email address for user +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOMATCH no single match found +** PH_ERR_DATAERR no email field +*/ +int +ph_email_resolve(PH *ph, char *user, char *fields, char **real_email) +{ + int i, save_errno; + char *getfields[2]; + char *mailbox, *mailmatches; + char buf[PH_BUF_SIZE]; + char *fieldp, *nextp; + ph_memblock_t *qblockp, *eblockp; + const field_rewrite_map_t *rewritep; + const rewritefunc_t *rwfunc; + struct ph_fieldselector *query; + ph_entry *entries; + + /* check siteinfo for the mailbox field (usually "email") */ + i = ph_get_siteinfo(ph, "mailbox", &mailbox); + if (i == -1) + return -1; + if (i == PH_ERR_DATAERR) + { + errno = EINVAL; + return -1; + } + getfields[0] = mailbox; + getfields[1] = NULL; +#ifdef DEBUG + printf("ph_email_resolve(): mailbox=\"%s\"\n", mailbox); +#endif + + /* set list of fields to match */ + if (fields != NULL + && *fields != '\0') + mailmatches = fields; + else + { + i = ph_get_siteinfo(ph, "mailmatches", &mailmatches); + if (i == -1) + return -1; + if (i == PH_ERR_DATAERR) + mailmatches = PH_DEFAULT_MAILMATCHES; + } +#ifdef DEBUG + printf("ph_email_resolve(): mailmatches=\"%s\"\n", mailmatches); +#endif + + /* copy mailmatches to a temp buffer so we don't modify the original */ + strlcpy(buf, mailmatches, sizeof(buf)); + nextp = buf; + + /* iterate through the field list to find a match */ + while ((fieldp = strsep(&nextp, " :")) != NULL) + { + if (*fieldp == '\0') + continue; + +#ifdef DEBUG + printf("ph_email_resolve(): trying field %s\n", fieldp); +#endif + + /* find the appropriate rewrite function(s) for the field */ + for (rewritep = rewrite_map; + rewritep->field != NULL; + rewritep++) + { +#ifdef DEBUG + printf("comparing \"%s\" and \"%s\"\n", + fieldp, rewritep->field); +#endif + if (strcasecmp(fieldp, rewritep->field) == 0) + break; + } + + /* perform a query with each specified rewrite function */ + for (rwfunc = rewritep->rewrite_funcs; + *rwfunc != NULL; + rwfunc++) + { + if (ph_mmgr_malloc(ph->ph_mmgr, ph_MMGR_ARRAY, 0, 0, + (ph_free_func_t)ph_free_selectors, + &qblockp) == -1) + return -1; + + /* do rewrite and perform query */ +#ifdef DEBUG + printf("calling rewrite function at 0x%lx (%s)\n", + *rwfunc, + (*rwfunc == rewrite_alias ? "rewrite_alias" : + (*rwfunc == rewrite_name ? "rewrite_name" : + "no_rewrite"))); +#endif + i = (**rwfunc)(fieldp, user, + (struct ph_fieldselector **)&(ph_mmgr_ptr(qblockp))); + switch (i) + { + case 0: + break; + + case -1: + save_errno = errno; + ph_mmgr_free(qblockp, 1); + errno = save_errno; + return -1; + + default: + /* + ** special case: + ** PH_ERR_DATAERR can be returned by + ** rewrite_name() when user name is + ** all punctuation chars or spaces + */ + ph_mmgr_free(qblockp, 1); + return i; + } + +#ifdef DEBUG + printf("rewrote \"%s\" to \"%s\"\n", + user, + ((struct ph_fieldselector *)(ph_mmgr_ptr(qblockp)))[0].pfs_value); +#endif + + query = (struct ph_fieldselector *)ph_mmgr_ptr(qblockp); + + if (ph_mmgr_malloc(ph->ph_mmgr, ph_MMGR_ARRAY, 0, 0, + (ph_free_func_t)ph_free_entries, + &eblockp) == -1) + return -1; + +#ifdef DEBUG + puts("calling ph_query()"); +#endif + i = ph_query(ph, query, getfields, + (ph_entry **)&(ph_mmgr_ptr(eblockp))); + + /* free query */ +#ifdef DEBUG + puts("free()'ing query memory"); +#endif + ph_mmgr_free(qblockp, 1); + + /* if ph_query() returned an error above */ +#ifdef DEBUG + printf("ph_query() returned %d\n", i); +#endif + if (i == -1 || i == PH_ERR_DATAERR) + { + save_errno = errno; + ph_mmgr_free(eblockp, 1); + errno = save_errno; + return i; + } + + entries = (ph_entry *)ph_mmgr_ptr(eblockp); + + /* one match found - return it */ + if (i == 1) + { + /* if the one match is an error... */ + if (entries[0][0].pfv_code != -(LR_OK)) + { + ph_mmgr_free(eblockp, 1); + return PH_ERR_DATAERR; + } + + /* + ** terminate string at first whitespace or + ** comma (in case more than one email + ** address is listed) + */ + nextp = entries[0][0].pfv_value; + while (*nextp != '\0' + && !isspace((int)*nextp) + && (*nextp != ',')) + nextp++; + *nextp = '\0'; + +#ifdef DEBUG + puts("returning match"); +#endif + *real_email = strdup(entries[0][0].pfv_value); + if (*real_email == NULL) + { + save_errno = errno; + ph_mmgr_free(eblockp, 1); + errno = save_errno; + return -1; + } + + ph_mmgr_free(eblockp, 1); + return 0; + } + + /* more than one match found - clean up */ + ph_mmgr_free(eblockp, 1); + } + } + + /* no matches found */ + return PH_ERR_NOMATCH; +} + + +/* +** ph_advertised_www() - returns alias-based URL for alias +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOMATCH alias does not exist +** PH_ERR_DATAERR no www field +*/ +int +ph_advertised_www(PH *ph, char *alias, int confirm_alias, + char **advertised_url) +{ + char *wwwredirect; + int i, code = 0, save_errno = 0; + + /* check siteinfo for the wwwredirect field */ + i = ph_get_siteinfo(ph, "wwwredirect", &wwwredirect); + if (i == -1) + return -1; + if (i == PH_ERR_DATAERR) + return ph_www_resolve(ph, alias, advertised_url); + + /* do a query to make sure that the alias exists */ + if (confirm_alias) + { + i = _ph_get_alias_field(ph, alias, "www", NULL); + if (i != 0) + return i; + } + + *advertised_url = (char *)malloc(strlen(wwwredirect) + strlen(alias) + 1); + if (*advertised_url == NULL) + return -1; + sprintf(*advertised_url, "%s%s", wwwredirect, alias); + return 0; +} + + +/* +** ph_www_resolve() - returns the expanded URL for user +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_NOMATCH no single entry matched +** PH_ERR_DATAERR no www field +*/ +int +ph_www_resolve(PH *ph, char *user, char **real_url) +{ + return _ph_get_alias_field(ph, user, "www", real_url); +} + + diff --git a/lib/serverlist.c b/lib/serverlist.c new file mode 100644 index 0000000..3490450 --- /dev/null +++ b/lib/serverlist.c @@ -0,0 +1,248 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** serverlist.c - code to handle references to other PH servers +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include + + +/* +** ph_serverlist_add() - add an entry to a list of known PH servers. +** returns: +** 0 success +** -1 error (sets errno) +*/ +int +ph_serverlist_add(struct ph_serverlist *serverlist, char *server, char *site) +{ + void *ptr; + +#ifdef DEBUG + printf("in ph_serverlist_add([serverlist], \"%s\", \"%s\")\n", server, + site); +#endif + + ptr = realloc(serverlist->sl_list, + (serverlist->sl_numservers + 2) * sizeof(struct ph_serversite)); + if (ptr == NULL) + return -1; + serverlist->sl_list = (struct ph_serversite *)ptr; + + memset(&(serverlist->sl_list[serverlist->sl_numservers + 1]), + 0, sizeof(struct ph_serversite)); + serverlist->sl_list[serverlist->sl_numservers].ss_server = strdup(server); + serverlist->sl_list[serverlist->sl_numservers].ss_site = strdup(site); + serverlist->sl_numservers++; + + return 0; +} + + +/* +** ph_serverlist_iterate() - iterate through all matching PH server entries. +** returns: +** 1 data returned +** 0 no more data +** -1 error (sets errno) +*/ +int +ph_serverlist_iterate(struct ph_serverlist *serverlist, + char *server, char *site, + struct ph_serversite **serversite) +{ + char *p; + +#ifdef DEBUG + printf("in ph_serverlist_iterate([serverlist], \"%s\", \"%s\", " + "0x%lx)\n", + (server ? server : "NULL"), + (site ? site : "NULL"), + *serversite); +#endif + + if (server != NULL) + { + /* make sure it's at least two levels */ + p = strchr(server, '.'); + if (p == NULL || p == server || *(p + 1) == '\0') + { + errno = EINVAL; + return -1; + } + + /* strip trailing '.' */ + if (server[strlen(server) - 1] == '.') + server[strlen(server) - 1] = '\0'; + } + + if (*serversite == NULL) + *serversite = serverlist->sl_list; + else + (*serversite)++; + + for (; (*serversite)->ss_site != NULL; (*serversite)++) + { +#ifdef DEBUG + printf("ph_serverlist_iterate(): checking server=\"%s\" " + "site=\"%s\"\n", + (*serversite)->ss_server, (*serversite)->ss_site); +#endif + + /* match server name only on final set of domain components */ + if (server != NULL) + { + p = (*serversite)->ss_server + strlen((*serversite)->ss_server) - strlen(server); + if (p < (*serversite)->ss_server + || strcasecmp(p, server) != 0 + || (p != (*serversite)->ss_server + && *(p - 1) != '.')) + continue; + } + + /* match site on substring match */ + if (site != NULL + && strstr((*serversite)->ss_site, site) == NULL) + continue; + + /* found a match */ + return 1; + } + + return 0; +} + + +/* +** ph_serverlist_merge() - read list of known PH servers from the server +** associated with ph and merge them into serverlist. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_DATAERR invalid query +*/ +int +ph_serverlist_merge(PH *ph, struct ph_serverlist *serverlist) +{ + char *site; + char *linep, *nextp, *typep; + int i, save_errno, numentries; + ph_memblock_t *blockp; + struct ph_fieldselector query[] = { + { "name", '=', "ns-servers" }, + { "type", '=', "serverlist" }, + { NULL, '\0', NULL } + }; + char *getfields[] = { "text", NULL }; + ph_entry *entries; + + /* get list of known servers */ + if (ph_mmgr_malloc(ph->ph_mmgr, 0, 0, 0, + (ph_free_func_t)ph_free_entries, + &blockp) == -1) + return -1; + numentries = ph_query(ph, query, getfields, + (ph_entry **)&(ph_mmgr_ptr(blockp))); + if (numentries == PH_ERR_NOMATCH) + { + ph_mmgr_free(blockp, 1); + return 0; + } + if (numentries <= 0) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return numentries; + } + + entries = (ph_entry *)ph_mmgr_ptr(blockp); + + /* read the responses */ + for (i = 0; i < numentries; i++) + { + site = NULL; + + /* skip entries which don't contain valid data */ + if (entries[i][0].pfv_code != -(LR_OK)) + continue; + + /* parse each line */ + nextp = entries[i][0].pfv_value; + while ((linep = strsep(&nextp, "\n")) != NULL) + { + /* format is "(site|server):data" */ + typep = strsep(&linep, ":"); + if (typep == NULL || *typep == '\0') + continue; + + /* + ** "site" line comes first, + ** so save pointer and read next line + */ + if (strcasecmp(typep, "site") == 0) + { + site = linep; + continue; + } + + /* for "server" line, create a new element */ + if (strcasecmp(typep, "server") == 0) + { + /* + ** if we get a "server" line without a + ** "site" line, skip it + */ + if (site == NULL) + continue; + + if (ph_serverlist_add(serverlist, linep, + site) == -1) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; + } + } + } + } + + ph_mmgr_free(blockp, 1); + return 0; +} + + +/* +** ph_free_serverlist() - free memory associated with serverlist. +*/ +void +ph_free_serverlist(struct ph_serverlist *serverlist) +{ + int i; + + for (i = 0; serverlist->sl_list[i].ss_server != NULL; i++) + { + free(serverlist->sl_list[i].ss_server); + free(serverlist->sl_list[i].ss_site); + } + + free(serverlist->sl_list); + serverlist->sl_list = NULL; + serverlist->sl_numservers = 0; +} + + diff --git a/lib/siteinfo.c b/lib/siteinfo.c new file mode 100644 index 0000000..ae6bcfa --- /dev/null +++ b/lib/siteinfo.c @@ -0,0 +1,204 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** siteinfo.c - libphclient code to parse siteinfo data +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include + + +int +ph_is_siteinfo_cached(PH *ph) +{ + return (ph->ph_siteinfo != NULL ? 1 : 0); +} + + +/* ph_free_siteinfo_list() - free a siteinfo list. */ +static void +ph_free_siteinfo_list(struct ph_siteinfo *si) +{ + int i; + + for (i = 0; si[i].ps_info != NULL; i++) + { +#ifdef DEBUG + printf("freeing siteinfo[%d]: \"%s\" = \"%s\"\n", i, + (si[i].ps_info ? si[i].ps_info : ""), + (si[i].ps_data ? si[i].ps_data : "")); +#endif + free(si[i].ps_info); + free(si[i].ps_data); + } + + free(si); +} + + +/* +** ph_retrieve_siteinfo() - read siteinfo from server. +** returns: +** 0 success +** -1 error (sets errno) +*/ +int +ph_retrieve_siteinfo(PH *ph) +{ + char *info, *setting; + char buf[PH_BUF_SIZE]; + int code = -1, infonum = 0, i, save_errno; + ph_memblock_t *blockp; + struct ph_siteinfo *phsi; + + /* don't load if already cached */ + if (ph_is_siteinfo_cached(ph)) + return 0; + + if (ph_mmgr_malloc(ph->ph_mmgr, ph_MMGR_ARRAY, + 0, sizeof(struct ph_siteinfo), + (ph_free_func_t)ph_free_siteinfo_list, + &blockp) == -1) + return -1; + phsi = (struct ph_siteinfo *)ph_mmgr_ptr(blockp); + + /* send command */ + if (ph_send_command(ph, "siteinfo") == -1) + return -1; + + /* read responses */ + while (ph_get_response(ph, &code, buf, sizeof(buf)) == 0) + { + if (code < LR_OK && code > 0) + continue; + if (code == LR_OK) + { + ph->ph_siteinfo = phsi; + ph_mmgr_free(blockp, 0); + return 0; + } + + if (ph_parse_response(buf, &i, &info, &setting) == -1) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; + } + +#ifdef DEBUG + printf("code=%d, i=%d, info=\"%s\", setting=\"%s\", " + "infonum=%d\n", code, i, info, setting, infonum); +#endif + + if (ph_mmgr_array_add(blockp, infonum + 2) == -1) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; + } + phsi = (struct ph_siteinfo *)ph_mmgr_ptr(blockp); + + phsi[infonum].ps_info = strdup(info); + phsi[infonum].ps_data = strdup(setting); + if (phsi[infonum].ps_info == NULL + || phsi[infonum].ps_data == NULL) + { + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; + } + + infonum++; + } + + save_errno = errno; + ph_mmgr_free(blockp, 1); + errno = save_errno; + return -1; +} + + +/* +** ph_get_siteinfo() - return the value of a specific info field. +** returns: +** 0 success +** -1 error (sets errno) +** PH_ERR_DATAERR unknown siteinfo field +*/ +int +ph_get_siteinfo(PH *ph, char *info, char **data) +{ + int i; + + if (!ph_is_siteinfo_cached(ph) && ph_retrieve_siteinfo(ph) == -1) + return -1; + + for (i = 0; ph->ph_siteinfo[i].ps_info != NULL; i++) + if (strcasecmp(ph->ph_siteinfo[i].ps_info, info) == 0) + { + *data = ph->ph_siteinfo[i].ps_data; + return 0; + } + + return PH_ERR_DATAERR; +} + + +/* +** ph_siteinfo_iterate() - iterate through siteinfo list. +** returns: +** 1 data returned +** 0 no more data +** -1 error (sets errno) +*/ +int +ph_siteinfo_iterate(PH *ph, struct ph_siteinfo **siteinfo) +{ + if (!ph_is_siteinfo_cached(ph) && ph_retrieve_siteinfo(ph) == -1) + return -1; + + /* first entry */ + if (*siteinfo == NULL) + { + *siteinfo = &(ph->ph_siteinfo[0]); + return 1; + } + + /* next entry */ + (*siteinfo)++; + if ((*siteinfo)->ps_info != NULL) + return 1; + + /* last entry */ + *siteinfo = NULL; + return 0; +} + + +/* +** ph_free_siteinfo() - free the siteinfo list associated with ph. +*/ +void +ph_free_siteinfo(PH *ph) +{ + if (ph->ph_siteinfo != NULL) + ph_free_siteinfo_list(ph->ph_siteinfo); + ph->ph_siteinfo = NULL; +} + + diff --git a/mmgr/ChangeLog b/mmgr/ChangeLog new file mode 100644 index 0000000..2944b60 --- /dev/null +++ b/mmgr/ChangeLog @@ -0,0 +1,4 @@ +2002-11-24 syntax change to work around pointer arithmetic + problem with IRIX compiler + +2002-10-16 initial version diff --git a/mmgr/TODO b/mmgr/TODO new file mode 100644 index 0000000..9b188f7 --- /dev/null +++ b/mmgr/TODO @@ -0,0 +1,3 @@ +- redesign memmgr structure as a dynamically-allocated hash +- make allocation calls as atomic as possible (e.g., block signals, use + mutexes, etc) diff --git a/mmgr/mmgr.c.in b/mmgr/mmgr.c.in new file mode 100644 index 0000000..7bbdac4 --- /dev/null +++ b/mmgr/mmgr.c.in @@ -0,0 +1,268 @@ +/* @configure_input@ */ + +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** @MMGR_PREFIX@_mmgr.c - memory management code +** +** Mark D. Roth +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include +#include + +#include <@MMGR_PREFIX@_mmgr.h> + +#include + +#ifdef STDC_HEADERS +# include +#endif + + +/* useful macros */ +#define BIT_ISSET(bitfield, opt) ((bitfield) & (opt)) +#define BIT_SET(bitfield, opt) ((bitfield) |= (opt)) +#define BIT_CLEAR(bitfield, opt) ((bitfield) &= ~(opt)) +#define BIT_TOGGLE(bitfield, opt) { \ + if (BIT_ISSET(bitfield, opt)) \ + BIT_CLEAR(bitfield, opt); \ + else \ + BIT_SET(bitfield, opt); \ + } + + +/* flags for internal use */ +#define MMGR_VALID 1 /* memblock is valid */ +#define MMGR_FOREIGN 2 /* used by _mmgr_register() */ + +#define MMGR_INTERNAL_MASK 255 /* mask for internal flags */ + + + +struct @MMGR_PREFIX@_mmgr +{ + @MMGR_PREFIX@_memblock_t *mm_memblocks; + unsigned long mm_numblocks; + unsigned long mm_freeblock; +}; + + +int +@MMGR_PREFIX@_mmgr_init(@MMGR_PREFIX@_mmgr_t *mmgrp) +{ + *mmgrp = (@MMGR_PREFIX@_mmgr_t)calloc(1, sizeof(struct @MMGR_PREFIX@_mmgr)); + if (*mmgrp == NULL) + return -1; + + return 0; +} + + +void +@MMGR_PREFIX@_mmgr_cleanup(@MMGR_PREFIX@_mmgr_t mmgr) +{ + int index; + + for (index = 0; index < mmgr->mm_freeblock; index++) + @MMGR_PREFIX@_mmgr_free(mmgr->mm_memblocks + index, 1); + + free(mmgr); +} + + +static int +_find_free_memblock(@MMGR_PREFIX@_mmgr_t mmgr) +{ + void *ptr; + int index; + +#ifdef MMGR_DEBUG + puts("==> _find_free_memblock()"); +#endif + + /* check if we can re-use previously-allocated memblocks */ + for (index = 0; index < mmgr->mm_freeblock; index++) + if (! BIT_ISSET(mmgr->mm_memblocks[index].mb_flags, MMGR_VALID)) + { +#ifdef MMGR_DEBUG + printf("<== _find_free_memblock(): returning %d\n", + index); +#endif + return index; + } + + /* allocate new memblocks if needed */ + if (mmgr->mm_freeblock >= mmgr->mm_numblocks) + { + ptr = realloc(mmgr->mm_memblocks, + (mmgr->mm_numblocks + 10) * sizeof(@MMGR_PREFIX@_memblock_t)); + if (ptr == NULL) + { +#ifdef MMGR_DEBUG + printf("<== _find_free_memblock(): returning -1\n"); +#endif + return -1; + } + mmgr->mm_memblocks = (@MMGR_PREFIX@_memblock_t *)ptr; + memset(mmgr->mm_memblocks + mmgr->mm_numblocks, 0, + sizeof(@MMGR_PREFIX@_memblock_t) * 10); + mmgr->mm_numblocks += 10; + } + +#ifdef MMGR_DEBUG + printf("<== _find_free_memblock(): returning %d\n", mmgr->mm_freeblock); +#endif + return mmgr->mm_freeblock++; +} + + +int +@MMGR_PREFIX@_mmgr_malloc(@MMGR_PREFIX@_mmgr_t mmgr, + unsigned long flags, + size_t nelem, + size_t elsize, + @MMGR_PREFIX@_free_func_t freefunc, + @MMGR_PREFIX@_memblock_t **blockpp) +{ + int index; + + index = _find_free_memblock(mmgr); + if (index == -1) + return -1; + + *blockpp = mmgr->mm_memblocks + index; + + /* don't let caller set internal flags */ + BIT_CLEAR(flags, MMGR_INTERNAL_MASK); + + /* nelem is always set to 1 for non-arrays */ + if (! BIT_ISSET(flags, @MMGR_PREFIX@_MMGR_ARRAY)) + nelem = 1; + + (*blockpp)->mb_flags = flags; + (*blockpp)->mb_elsize = elsize; + (*blockpp)->mb_nelem = nelem; + (*blockpp)->mb_freefunc = freefunc; + if ((nelem * elsize) == 0) + (*blockpp)->mb_ptr = NULL; + else + { + (*blockpp)->mb_ptr = calloc(nelem, elsize); + if ((*blockpp)->mb_ptr == NULL) + return -1; + } + + /* now we can set the valid bit */ + BIT_SET((*blockpp)->mb_flags, MMGR_VALID); + + return 0; +} + + +int +@MMGR_PREFIX@_mmgr_register(@MMGR_PREFIX@_mmgr_t mmgr, + void *ptr, + @MMGR_PREFIX@_free_func_t freefunc, + @MMGR_PREFIX@_memblock_t **blockpp) +{ + int index; + + index = _find_free_memblock(mmgr); + if (index == -1) + return -1; + + *blockpp = mmgr->mm_memblocks + index; + + memset(*blockpp, 0, sizeof(@MMGR_PREFIX@_memblock_t)); + (*blockpp)->mb_ptr = ptr; + (*blockpp)->mb_freefunc = freefunc; + (*blockpp)->mb_flags = (MMGR_VALID | MMGR_FOREIGN); + + return 0; +} + + +int +@MMGR_PREFIX@_mmgr_array_add(@MMGR_PREFIX@_memblock_t *blockp, size_t nelem) +{ + void *ptr; + size_t oldsize, newsize; + +#ifdef MMGR_DEBUG + printf("==> @MMGR_PREFIX@_mmgr_array_add(blockp=0x%lx, nelem=%lu)\n", + blockp, (unsigned long)nelem); +#endif + + oldsize = blockp->mb_elsize * blockp->mb_nelem; + newsize = blockp->mb_elsize * nelem; + +#ifdef MMGR_DEBUG + printf(" @MMGR_PREFIX@_mmgr_array_add(): oldsize=%lu newsize=%lu\n", + (unsigned long)oldsize, (unsigned long)newsize); +#endif + + ptr = realloc(blockp->mb_ptr, newsize); + if (ptr == NULL) + return -1; + + blockp->mb_ptr = ptr; + blockp->mb_nelem = nelem; + + if (newsize > oldsize) + { + ptr = (unsigned char *)ptr + oldsize; + memset(ptr, 0, newsize - oldsize); + } + + return 0; +} + + +int +@MMGR_PREFIX@_mmgr_realloc(@MMGR_PREFIX@_memblock_t *blockp, + size_t newsize) +{ + void *ptr; + + ptr = realloc(blockp->mb_ptr, newsize); + if (ptr == NULL) + return -1; + + blockp->mb_ptr = ptr; + + if (newsize > blockp->mb_elsize) + { + ptr = (unsigned char *)ptr + blockp->mb_elsize; + memset(ptr, 0, newsize - blockp->mb_elsize); + } + blockp->mb_elsize = newsize; + + return 0; +} + + +int +@MMGR_PREFIX@_mmgr_free(@MMGR_PREFIX@_memblock_t *blockp, int freeflag) +{ +#ifdef MMGR_DEBUG + printf("==> @MMGR_PREFIX@_mmgr_free(blockp=0x%lx, freeflag=%d)\n", + blockp, freeflag); +#endif + + if (!BIT_ISSET(blockp->mb_flags, MMGR_VALID)) + return 0; + + if (freeflag && blockp->mb_ptr != NULL) + (*(blockp->mb_freefunc))(blockp->mb_ptr); + + BIT_CLEAR(blockp->mb_flags, MMGR_VALID); + + return 0; +} + + diff --git a/mmgr/mmgr.h.in b/mmgr/mmgr.h.in new file mode 100644 index 0000000..29fcdf4 --- /dev/null +++ b/mmgr/mmgr.h.in @@ -0,0 +1,69 @@ +/* @configure_input@ */ + +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** @MMGR_PREFIX@_buffer.h - header file for buffer module +** +** Mark D. Roth +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#ifndef @MMGR_PREFIX@_MMGR_H +#define @MMGR_PREFIX@_MMGR_H + +#include + + +/* bits for mb_flags field */ +#define @MMGR_PREFIX@_MMGR_ARRAY 256 /* array (elsize * nelem) */ + +typedef void (*@MMGR_PREFIX@_free_func_t)(void *); + +struct @MMGR_PREFIX@_memblock +{ + unsigned long mb_flags; + void *mb_ptr; + size_t mb_elsize; + size_t mb_nelem; + @MMGR_PREFIX@_free_func_t mb_freefunc; +}; +typedef struct @MMGR_PREFIX@_memblock @MMGR_PREFIX@_memblock_t; + +#define @MMGR_PREFIX@_mmgr_ptr(bp) ((bp)->mb_ptr) +#define @MMGR_PREFIX@_mmgr_size(bp) ((bp)->mb_nelem * (bp)->mb_elsize) + + +typedef struct @MMGR_PREFIX@_mmgr *@MMGR_PREFIX@_mmgr_t; + + +int @MMGR_PREFIX@_mmgr_init(@MMGR_PREFIX@_mmgr_t *); + +void @MMGR_PREFIX@_mmgr_cleanup(@MMGR_PREFIX@_mmgr_t); + +int @MMGR_PREFIX@_mmgr_malloc(@MMGR_PREFIX@_mmgr_t, + unsigned long, + size_t, + size_t, + @MMGR_PREFIX@_free_func_t, + @MMGR_PREFIX@_memblock_t **); + +int @MMGR_PREFIX@_mmgr_register(@MMGR_PREFIX@_mmgr_t, + void *, + @MMGR_PREFIX@_free_func_t, + @MMGR_PREFIX@_memblock_t **); + +int @MMGR_PREFIX@_mmgr_array_add(@MMGR_PREFIX@_memblock_t *, + size_t); + +int @MMGR_PREFIX@_mmgr_realloc(@MMGR_PREFIX@_memblock_t *, + size_t); + +int @MMGR_PREFIX@_mmgr_free(@MMGR_PREFIX@_memblock_t *, + int); + +#endif /* ! @MMGR_PREFIX@_MMGR_H */ + diff --git a/mmgr/module.ac b/mmgr/module.ac new file mode 100644 index 0000000..7fedc5c --- /dev/null +++ b/mmgr/module.ac @@ -0,0 +1,17 @@ +AC_DEFUN(subdir[_INIT], [ + AC_REQUIRE([AC_HEADER_STDC]) + + if test -z "$2"; then + MMGR_PREFIX="${PACKAGE_NAME}"; + else + MMGR_PREFIX="$2"; + fi + AC_SUBST([MMGR_PREFIX]) + + MMGR_DIR="$1"; + AC_SUBST([MMGR_DIR]) + + AC_CONFIG_FILES([$1/${MMGR_PREFIX}_mmgr.h:$1/mmgr.h.in]) + AC_CONFIG_FILES([$1/${MMGR_PREFIX}_mmgr.c:$1/mmgr.c.in]) +]) + diff --git a/nph/Makefile.in b/nph/Makefile.in new file mode 100644 index 0000000..013b85e --- /dev/null +++ b/nph/Makefile.in @@ -0,0 +1,90 @@ +# @configure_input@ + +### Path settings +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +mandir = @mandir@ +sysconfdir = @sysconfdir@ + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ + +@ENCAP_DEFS@ + +### Installation programs and flags +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s +NPH_MODE = @NPH_MODE@ +INSTALL_DATA = @INSTALL_DATA@ +LN_S = @LN_S@ +MKDIR = @MKDIR@ +MORE = @MORE@ +VI = @VI@ + +### Compiler and link options +CC = @CC@ +CPPFLAGS = -I.. \ + -I${srcdir} \ + -I${top_srcdir}/lib \ + -I${top_srcdir}/compat \ + @CPPFLAGS@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +RANLIB = @RANLIB@ +@SET_MAKE@ +VPATH = @srcdir@ + + +### Makefile rules - no user-servicable parts below + +NPH_OBJS = commands.o \ + conf.o \ + content.o \ + edit.o \ + init.o \ + interactive.o \ + login.o \ + nph.o \ + output.o \ + serverinfo.o \ + sighandler.o +NPH_HDRS = ../config.h \ + ${srcdir}/nph.h \ + ${top_srcdir}/lib/phclient.h \ + ${top_srcdir}/compat/compat.h +NPH_LIBS = ../lib/libphclient.a +ALL = nph + +INIT_DEFS = -DSYSTEM_NPHRC=\"${sysconfdir}/nphrc\" \ + -DSERVER_FILE=\"${sysconfdir}/ph_server\" + + +all: ${ALL} + +.PHONY: clean distclean install + +nph: ${NPH_OBJS} ${NPH_LIBS} + ${CC} ${CFLAGS} ${LDFLAGS} -o nph ${NPH_OBJS} ${NPH_LIBS} ${LIBS} + +${NPH_OBJS}: ${NPH_HDRS} + +.c.o: + ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $< + +init.o: ${srcdir}/init.c ${NPH_HDRS} + ${CC} ${CFLAGS} ${CPPFLAGS} ${INIT_DEFS} -c -o $@ $< + +clean: + rm -f *~ *.o ${ALL} core + +distclean: clean + rm -f Makefile + +install: all + ${MKDIR} ${DESTDIR}${bindir} + ${INSTALL_PROGRAM} -m ${NPH_MODE} nph ${DESTDIR}${bindir} + diff --git a/nph/commands.c b/nph/commands.c new file mode 100644 index 0000000..4ea8627 --- /dev/null +++ b/nph/commands.c @@ -0,0 +1,403 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** commands.c - nph command vector code +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include + +#ifdef HAVE_READLINE_READLINE_H +# include +#endif + + +typedef int (*cmd_func_t)(int, char **); + +struct command +{ + char *command; + int pager; + cmd_func_t function; + char *helptext; +}; + +const struct command cmds[] = { + { "connect", 0, nph_connect, + "connect host[:port]\tConnect to a new PH server" }, + { "source", 0, nph_source, + "source file\t\tRead commands from a file" }, + {".", 0, nph_source, + ". file\t\t\t(same as source command)" }, + { "<", 0, nph_source, + "< file\t\t\t(same as source command)" }, + { "id", 0, nph_id, + "id text\t\t\tIdentify yourself for the server's logs" }, + { "external", 0, nph_external, + "external\t\tSet session to be non-local" }, + { "suser", 0, nph_suser, + "suser alias\t\tBecome user alias (heros only)" }, + { "login", 0, nph_login, + "login alias\t\tLog in to the server" }, + { "logout", 0, nph_logout, + "logout\t\t\tLog out of the server" }, + { "passwd", 0, nph_passwd, + "passwd\t\t\tChange your PH password" }, + { "password", 0, nph_passwd, + "password\t\t(same as passwd command)" }, + { "option", 0, nph_option, + "option [opt[=val]]\tShow or set nph client options" }, + { "switch", 0, nph_option, + "switch [opt[=val]]\t(same as option command)" }, + { "help", 0, nph_help, + "help [command]\t\tShow help for nph commands" }, + { "?", 0, nph_help, + "?\t\t\t(same as help command)" }, + { "quit", 0, nph_quit, + "quit\t\t\tEnd PH session" }, + { "bye", 0, nph_quit, + "bye\t\t\t(same as quit command)" }, + { "exit", 0, nph_quit, + "exit\t\t\t(same as quit command)" }, + { "stop", 0, nph_quit, + "stop\t\t\t(same as quit command)" }, + { "whoami", 0, nph_whoami, + "whoami\t\t\tDisplays the currently logged-in username" }, + { "status", 1, nph_status, + "status\t\t\tView the server's message of the day" }, + { "motd", 1, nph_status, + "motd\t\t\t(same as status command)" }, + { "serveradd", 0, nph_serveradd, + "serveradd server [sitename]\n\t\t\t" + "Add a server to the list of known servers" }, + { "listservers", 1, nph_listservers, + "listservers [domain]\tView list of other known PH servers" }, + { "set", 0, nph_set, + "set [option[=setting]]\tShow or set server options" }, + { "siteinfo", 0, nph_siteinfo, + "siteinfo\t\tRetrieve site-specific settings from server" }, + { "fields", 1, nph_fields, + "fields [field]\t\tView the fields supported by the server" }, + { "edit", 0, nph_edit, + "edit field [alias]\tEdit a given field (once logged in)" }, + { "change", 0, nph_change, + "change selectors... make|force changes...\n\t\t\t" + "Change data on server" }, + { "make", 0, nph_change, + "make changes...\t\t" + "Change data of currently logged-in user on server" }, + { "delete", 0, nph_delete, + "delete selectors...\tDelete entries on server (heros only)" }, + { "add", 0, nph_add, + "add fields...\t\tAdd an entry on the server (heros only)" }, + { "me", 1, nph_me, + "me\t\t\tView your PH entry (once logged in)" }, + { "query", 1, nph_query, + "query selectors [return fields...] [@domain]\n\t\t\t" + "Retrieve data from the server" }, + { "ph", 1, nph_query, + "ph selectors [return fields...] [@domain]\n\t\t\t" + "(same as query command)" }, +#if 0 + { "select", 0, nph_select, + "select [selectors]\t\t\t" + "Select entries for further processing" }, +#endif + { "resolve_email", 0, nph_resolvemail, + "resolve_email [keyfields=field1:field2:...] user\n\t\t\t" + "Resolve email address for user" }, + { "public_email", 0, nph_publicemail, + "public_email alias\t" + "Determine the advertised email address for alias" }, + { "resolve_www", 0, nph_resolvewww, + "resolve_www user\tResolve URL for user" }, + { "public_www", 0, nph_publicwww, + "public_www alias\tDetermine the advertised URL for alias" }, + { NULL, 0, NULL, + NULL } +}; + + +/* parse a command vector and call the appropriate function */ +int +nph_command(char *command) +{ + char *p, *q; + char *wordp, *nextp; + char **cmdv = NULL; + int i, j, cmdc = 0; + int redirected = 0; + +#ifdef DEBUG + printf("==> nph_command(\"%s\")\n", command); +#endif + + /* now parse actual command */ + nextp = command; + do + { + /* skip leading spaces */ + wordp = nextp + strspn(nextp, " "); + if (*nextp == '\0') + break; + + /* if wordp starts with '>', output to a file */ + if (wordp[0] == '>') + { + q = wordp + 1; + + /* append if ">>" */ + if (wordp[1] == '>') + { + i = 1; + q++; + } + else + i = 0; + + /* open the file */ + q += strspn(q, " "); + if (output_file(q, i) == -1) + return -1; + + /* done parsing command */ + redirected = 1; + break; + } + + /* if wordp starts with '|', pipe to program */ + if (wordp[0] == '|') + { + q = wordp + 1; + q += strspn(q, " "); + + if (output_pipe(q) == -1) + return -1; + + /* done parsing command */ + redirected = 1; + break; + } + + /* find a non-escaped quote */ + p = strchr(wordp, '"'); + if (p != NULL + && p != wordp + && *(p - 1) == '\\') + p = NULL; + + /* find a non-escaped space */ + q = strchr(wordp, ' '); + if (q != NULL + && *(q - 1) == '\\') + q = NULL; + + /* + ** quoted string - word ends at first non-escaped space + ** after next non-escaped quote + */ + if (p != NULL + && (p - q) < 0) + { + for (q = strchr(p + 1, '"'); + q != NULL; + q = strchr(q + 1, '"')) + if (*(q - 1) != '\\') + break; + if (q == NULL) + { + nph_printf(1, "parse error - unmatched '\"'\n"); + return -1; + } + for (q = strchr(q + 1, ' '); + q != NULL; + q = strchr(q + 1, ' ')) + if (*(q - 1) != '\\') + break; + } + + /* set the word delimiter */ + if (q != NULL) + *q++ = '\0'; + nextp = q; + + cmdv = (char **)realloc(cmdv, (cmdc + 2) * sizeof(char *)); + cmdv[cmdc] = wordp; + cmdv[++cmdc] = NULL; + } + while (nextp != NULL); + +#ifdef DEBUG + for (i = 0; i < cmdc; i++) + printf("cmdv[%d] = \"%s\"\n", i, cmdv[i]); +#endif + + /* find command function */ + for (i = 0; cmds[i].command != NULL; i++) + if (strcasecmp(cmds[i].command, cmdv[0]) == 0) + break; + + /* + ** if the command wasn't redirected and is set for paging, + ** use the pager + */ + get_option("usepager", &j); + if (j && !redirected && cmds[i].pager) + { + get_option("pager", &q); + + if (output_pipe(q) == -1) + return -1; + } + + /* call command */ + if (cmds[i].function != NULL) + { + if (!sigsetjmp(command_env, 1)) + { + sighandler_state = HANDLER_COMMAND; + i = (*(cmds[i].function))(cmdc, cmdv); + } + } + else + { + nph_printf(1, "unknown command \"%s\"\n", cmdv[0]); + i = -1; + } + + /* reset output */ + reset_output(0); + free(cmdv); + return i; +} + + +/* prints the help text for command */ +int +nph_help(int cmdc, char **cmdv) +{ + int i; + + /* if no argument, print all help */ + if (cmdv[1] == NULL) + { + for (i = 0; cmds[i].helptext != NULL; i++) + nph_printf(0, "%s\n", cmds[i].helptext); + return 0; + } + + /* print help for the specified command only */ + if (cmdv[2] != NULL) + { + nph_printf(1, "help: too many arguments\n"); + print_help("help"); + } + else + print_help(cmdv[1]); + + return 0; +} + + +/* prints the help text for command */ +void +print_help(char *command) +{ + int i; + + for (i = 0; cmds[i].command != NULL; i++) + if (strcasecmp(cmds[i].command, command) == 0) + break; + + if (cmds[i].helptext != NULL) + nph_printf(0, "%s\n", cmds[i].helptext); + else + nph_printf(1, "unknown command \"%s\"\n", command); +} + + +#ifdef HAVE_LIBREADLINE + +/* command completion function */ +char * +rl_complete_command(char *text, int state) +{ + static int i; + static int textlen; + + if (!state) + { + i = 0; + textlen = strlen(text); + } + else + i++; + + for (; cmds[i].command != NULL; i++) + if (strncasecmp(cmds[i].command, text, textlen) == 0) + return strdup(cmds[i].command); + + return NULL; +} + +#endif /* HAVE_LIBREADLINE */ + + +/* quit */ +int +nph_quit(int cmdc, char **cmdv) +{ + if (cmdv[1] != NULL) + { + print_help(cmdv[0]); + return -1; + } + +#ifdef HAVE_LIBREADLINE + rl_callback_handler_remove(); +#endif + + sighandler_state = HANDLER_DEFAULT; + + if (ph_close(ph, 0) == -1) + { + nph_printf(1, "ph_close(): %s\n", strerror(errno)); + exit(1); + } + exit(0); +} + + +/* whoami */ +int +nph_whoami(int cmdc, char **cmdv) +{ + char *user; + + if (cmdv[1] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + user = ph_whoami(ph); + if (user == NULL) + user = "(anonymous)"; + + nph_printf(0, "user %s on server %s\n", user, ph_server); + return 0; +} + + diff --git a/nph/conf.c b/nph/conf.c new file mode 100644 index 0000000..e2dcaff --- /dev/null +++ b/nph/conf.c @@ -0,0 +1,461 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** conf.c - nph client option code +** +** Mark D. Roth +*/ + +#include + +#include +#include +#include +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include + +#ifdef HAVE_PATHS_H +# include +#endif + +#ifndef _PATH_VI +# define _PATH_VI VI +#endif + +#ifndef _PATH_MORE +# define _PATH_MORE MORE +#endif + + +/* plugin prototypes */ + +#if 0 +static int set_numeric(int, char *); +static int get_numeric(int, void *); +#endif + +static int set_boolean(int, char *); +static int get_boolean(int, void *); + +static int set_string(int, char *); +static int get_string(int, void *); + +static int set_authmethod(int, char *); +static int get_authmethod(int, void *); + +static int get_prog(int, void *); + +static int set_debug(int, char *); + +static int set_fields(int, char *); + + +typedef int (*nph_set_opt_func_t)(int, char *); +typedef int (*nph_get_opt_func_t)(int, void *); + +struct nph_option +{ + char *option; + int freeflag; + char *str; + nph_set_opt_func_t setval; + nph_get_opt_func_t getval; +}; + +static struct nph_option nphopts[] = { + { "authtype", 0, "password", + set_authmethod, get_authmethod }, + { "canonicaladdrs", 0, "off", + set_boolean, get_boolean }, + { "confirmedits", 0, "off", + set_boolean, get_boolean }, + { "debug", 0, "off", + set_debug, get_boolean }, + { "defaultfield", 0, "", + set_fields, get_string }, + { "editor", 0, "$EDITOR", + set_string, get_prog }, + { "pager", 0, "$PAGER", + set_string, get_prog }, + { "returnfields", 0, "", + set_fields, get_string }, + { "usepager", 0, "on", + set_boolean, get_boolean }, + { "usereservedport", 0, "off", + set_boolean, get_boolean }, + { NULL, 0, NULL, + NULL, NULL } +}; + + +#ifdef HAVE_LIBREADLINE + +/* option completion function */ +char * +rl_complete_conf(char *text, int state) +{ + static int i; + static int textlen; + + if (!state) + { + i = 0; + textlen = strlen(text); + } + else + i++; + + for (; nphopts[i].option != NULL; i++) + if (strncasecmp(nphopts[i].option, text, textlen) == 0) + return strdup(nphopts[i].option); + + return NULL; +} + +#endif /* HAVE_LIBREADLINE */ + + +/* internal function - find a given option index */ +static int +find_option(char *name) +{ + int i; + + for (i = 0; nphopts[i].option != NULL; i++) + if (strcasecmp(nphopts[i].option, name) == 0) + break; + + return i; +} + + +/* set/get the setting for an option */ + +int +get_option(char *name, void *value) +{ + int i; + + i = find_option(name); + if (nphopts[i].option == NULL) + return -1; + + return (*(nphopts[i].getval))(i, value); +} + +int +set_option(char *name, char *value) +{ + int i; + + i = find_option(name); + if (nphopts[i].option == NULL) + return -1; + + return (*(nphopts[i].setval))(i, value); +} + + +/* string functions */ + +static int +get_string(int i, void *ptr) +{ + char **string = (char **)ptr; + + *string = nphopts[i].str; + return 0; +} + + +static int +set_string(int i, char *string) +{ + if (nphopts[i].freeflag) + free(nphopts[i].str); + nphopts[i].str = strdup(string); + nphopts[i].freeflag = 1; + return 0; +} + + +#if 0 + +/* numeric functions */ + +static int +set_numeric(int i, char *number) +{ + char *cp; + + for (cp = number; *cp != '\0'; cp++) + if (!isdigit((int)*cp)) + { + nph_printf(1, "invalid value for numeric option " + "\"%s\"\n", nphopts[i].option); + return -1; + } + + return set_string(i, number); +} + + +static int +get_numeric(int i, void *ptr) +{ + int *number = (int *)ptr; + + *number = atoi(nphopts[i].str); + return 0; +} + +#endif + + +/* boolean functions */ + +static int +set_boolean(int i, char *val) +{ + if (strcasecmp(val, "on") != 0 + && strcasecmp(val, "off") != 0) + { + nph_printf(1, "invalid value for boolean option \"%s\"\n", + nphopts[i].option); + return -1; + } + + return set_string(i, val); +} + +static int +get_boolean(int i, void *ptr) +{ + int *val = (int *)ptr; + + if (strcasecmp(nphopts[i].str, "on") == 0) + *val = 1; + else if (strcasecmp(nphopts[i].str, "off") == 0) + *val = 0; + else + return -1; + + return 0; +} + + +static int +set_fields(int i, char *string) +{ + if (ph != NULL + && string != NULL + && *string != '\0') + { + if (strcasecmp(nphopts[i].option, "returnfields") == 0) + { + if (check_fields(ph, string) == -1) + return -1; + } + else if (check_field(ph, string) == -1) + return -1; + } + + return set_string(i, string); +} + + +static int +get_prog(int i, void *ptr) +{ + char **string = (char **)ptr; + + /* if the value is set, use it */ + if (nphopts[i].str != NULL) + { + /* if value starts with '$', get environment variable */ + if (nphopts[i].str[0] == '$') + { + *string = getenv(nphopts[i].str + 1); + if (*string != NULL) + return 0; + /* otherwise, fall through to defaults */ + } + else + { + *string = nphopts[i].str; + return 0; + } + + } + + /* otherwise, use default */ + if (strcasecmp(nphopts[i].option, "editor") == 0) + *string = _PATH_VI; + else if (strcasecmp(nphopts[i].option, "pager") == 0) + *string = _PATH_MORE; + + return 0; +} + + +static int +set_debug(int i, char *val) +{ + int j; + + j = set_boolean(i, val); + + if (ph != NULL + && j != -1) + { + if (strcasecmp(val, "on") == 0) + { + ph_set_sendhook(ph, send_debug); + ph_set_recvhook(ph, recv_debug); + } + else + { + ph_set_sendhook(ph, NULL); + ph_set_recvhook(ph, NULL); + } + } + + return j; +} + + +static int +set_authmethod(int i, char *method) +{ + int j; + const char *methods[] = { + "email", "password", "passwd", "clear", NULL + }; + + for (j = 0; methods[j] != NULL; j++) + if (strcasecmp(methods[j], method) == 0) + { + if (strcasecmp(method, "clear") == 0) + nph_printf(0, "WARNING: the \"clear\" " + "authentication method is insecure " + "and should not be used!\n"); + + nphopts[i].str = strdup(method); + nphopts[i].freeflag = 1; + return 0; + } + + nph_printf(1, "unknown authtype \"%s\"\n", method); + return -1; +} + + +static int +get_authmethod(int i, void *ptr) +{ + int *method = (int *)ptr; + + if (strcasecmp(nphopts[i].str, "email") == 0) + *method = PH_AUTH_EMAIL; + else if (strcasecmp(nphopts[i].str, "password") == 0 + || strcasecmp(nphopts[i].str, "passwd") == 0) + *method = PH_AUTH_PASSWORD; + else if (strcasecmp(nphopts[i].str, "clear") == 0) + *method = PH_AUTH_CLEAR; + else + return -1; + + return 0; +} + + +/* command for option configuration */ +int +nph_option(int cmdc, char **cmdv) +{ + int i = 0; + char *setting = NULL; + char buf[NPH_BUF_SIZE]; + + switch (cmdc) + { + case 4: + if (strcmp(cmdv[2], "=") == 0) + setting = cmdv[3]; + else + i = 1; + break; + + case 3: + if (cmdv[1][strlen(cmdv[1]) - 1] == '=') + { + setting = cmdv[2]; + cmdv[1][strlen(cmdv[1]) - 1] = '\0'; + } + else if (cmdv[2][0] == '=') + setting = cmdv[2] + 1; + else + + default: + i = 1; + /* FALLTHROUGH */ + + case 1: + break; + + case 2: + setting = strchr(cmdv[1], '='); + if (setting != NULL) + *setting++ = '\0'; + break; + } + + if (i != 0) + { + nph_printf(1, "%s: invalid argument\n", cmdv[0]); + print_help(cmdv[0]); + return -1; + } + + /* no setting listed - print current setting(s) */ + if (cmdv[1] == NULL) + { + nph_printf(0, "nph options:\n\n"); + for (i = 0; nphopts[i].option != NULL; i++) + nph_printf(0, "%20.20s = %s\n", nphopts[i].option, + nphopts[i].str); + return 0; + } + + /* argument listed - find corresponding option */ + if (setting != NULL) + /* FIXME: not part of libphclient public API! */ + ph_dequote_value(setting, buf, sizeof(buf)); + i = find_option(cmdv[1]); + if (nphopts[i].option == NULL) + { + nph_printf(1, "unknown option \"%s\"\n", cmdv[1]); + return -1; + } + + /* set the option if a value was specified */ + if (setting != NULL) + return (*(nphopts[i].setval))(i, buf); + + /* otherwise print the value of the option */ + nph_printf(0, "nph options:\n\n"); + nph_printf(0, "%20.20s = %s\n", nphopts[i].option, nphopts[i].str); + + return 0; +} + + diff --git a/nph/content.c b/nph/content.c new file mode 100644 index 0000000..1c521b3 --- /dev/null +++ b/nph/content.c @@ -0,0 +1,723 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** content.c - nph code to access server data +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include + + +/* find www field for a given alias */ +int +nph_resolvewww(int cmdc, char **cmdv) +{ + int i; + char *p; + + if (cmdv[1] == NULL + || cmdv[2] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + i = ph_www_resolve(ph, cmdv[1], &p); + if (i == -1) + nph_printf(1, "ph_www_resolve(): %s\n", strerror(errno)); + else if (i == PH_ERR_NOMATCH) + nph_printf(1, "user unknown\n"); + else if (i == PH_ERR_DATAERR) + nph_printf(1, "invalid query or no \"www\" field\n"); + else + { + nph_printf(0, "resolved URL for user %s is \"%s\"\n", + cmdv[1], p); + free(p); + } + + return i; +} + + +/* determine advertised URL for a given alias */ +int +nph_publicwww(int cmdc, char **cmdv) +{ + int i; + char *p; + + if (cmdv[1] == NULL + || cmdv[2] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + i = ph_advertised_www(ph, cmdv[1], 1, &p); + if (i == -1) + nph_printf(1, "ph_advertised_www(): %s\n", strerror(errno)); + else if (i == PH_ERR_NOMATCH) + nph_printf(1, "alias not found\n"); + else if (i == PH_ERR_DATAERR) + nph_printf(1, "invalid query or no \"www\" field\n"); + else + { + nph_printf(0, "advertised URL for alias %s is \"%s\"\n", + cmdv[1], p); + free(p); + } + + return i; +} + + +/* resolve user portion of email address */ +int +nph_resolvemail(int cmdc, char **cmdv) +{ + int i; + char *cp, *keyfields = NULL, *alias; + + switch (cmdc) + { + case 2: + alias = cmdv[1]; + break; + + case 3: + if (strncmp(cmdv[1], "keyfields=", 10) == 0) + { + keyfields = cmdv[1] + 10; + alias = cmdv[2]; + break; + } + /* FALLTHROUGH */ + + default: + print_help(cmdv[0]); + return -1; + } + + i = ph_email_resolve(ph, alias, keyfields, &cp); + if (i == -1) + nph_printf(1, "ph_email_resolve(): %s\n", strerror(errno)); + else if (i == PH_ERR_NOMATCH) + nph_printf(1, "user unknown\n"); + else if (i == PH_ERR_DATAERR) + nph_printf(1, "invalid query or no \"email\" field\n"); + else + { + nph_printf(0, "resolved email address for user %s is \"%s\"\n", + alias, cp); + free(cp); + } + + return i; +} + + +/* determine advertised email address for a given alias */ +int +nph_publicemail(int cmdc, char **cmdv) +{ + int i; + char *p; + + if (cmdv[1] == NULL + || cmdv[2] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + i = ph_advertised_email(ph, cmdv[1], 1, &p); + if (i == -1) + nph_printf(1, "ph_advertised_email(): %s\n", strerror(errno)); + else if (i == PH_ERR_NOMATCH) + nph_printf(1, "alias not found\n"); + else if (i == PH_ERR_DATAERR) + nph_printf(1, "invalid query or no \"email\" field\n"); + else + { + nph_printf(0, "advertised email address for alias " + "%s is \"%s\"\n", cmdv[1], p); + free(p); + } + + return i; +} + + +/* +** parse field selectors. +** if fieldflag is set, requires "field=" portion to be present. +** starts from cmdv[*cmdi] and increments *cmdi as it goes. +** returns: +** -1 parse error +** -2 all input consumed +** 0 or greater index into stop[] which matched the current token +*/ +static int +nph_parse_selectors(char **cmdv, int *cmdi, + const char *stop[], int requirefield, + struct ph_fieldselector **selectors) +{ + int i, numfields = 0; + char *default_field, *selector; + char buf[NPH_BUF_SIZE]; + +#ifdef DEBUG + puts("==> nph_parse_selectors()"); +#endif + + get_option("defaultfield", &default_field); + + for (; cmdv[*cmdi] != NULL; (*cmdi)++) + { +#ifdef DEBUG + printf("nph_parse_selectors(): cmdv[%d] = \"%s\"\n", *cmdi, + cmdv[*cmdi]); +#endif + + /* + ** if stop is set, check each token to see if + ** we should stop here + */ + if (stop != NULL && (*selectors) != NULL) + for (i = 0; stop[i] != NULL; i++) + if (strcasecmp(cmdv[*cmdi], stop[i]) == 0) + return i; + + if (strchr(cmdv[*cmdi], '=') == NULL + && default_field != NULL + && *default_field != '\0') + { + snprintf(buf, sizeof(buf), "%s=%s", default_field, + cmdv[*cmdi]); + selector = buf; + } + else + selector = cmdv[*cmdi]; + + if (ph_encode_selector(selector, requirefield, + &numfields, selectors) == -1) + { + nph_printf(1, "parse error in field selectors\n"); + return -1; + } + +#ifdef DEBUG + printf("field=\"%s\", value=\"%s\"\n", + (*selectors)[numfields - 1].pfs_field + ? (*selectors)[numfields - 1].pfs_field + : "NULL", + (*selectors)[numfields - 1].pfs_value + ? (*selectors)[numfields - 1].pfs_value + : "NULL"); +#endif + } + + return -2; +} + + +#if 0 +/* select entries for further processing */ +int +nph_select(int cmdc, char **cmdv) +{ + int i, cmdi = 1; + struct ph_fieldselector *selector; + char *retfields = { "alias", NULL }; + ph_entry *entries; + + if (cmdv[1] == NULL) + { + print_help(cmdv[0]); + return -1; + } + + i = nph_parse_selectors(cmdv, &cmdi, NULL, 0, &selector); + if (i != -2) + { + nph_printf(1, "parse error\n"); + return -1; + } + + i = ph_query(ph, selector, retfields, &entries); + ph_free_entries(entries); + + if (i > 0) + { + ph_free_selectors(default_selectors); + default_selectors = selectors; + nph_printf(0, "%d entries selected\n", i); + return 0; + } + + ph_free_selectors(selector); + nph_printf(1, "ph_query(): %s\n", strerror(errno)); + return -1; +} +#endif + + +/* change an entry */ +int +nph_change(int cmdc, char **cmdv) +{ + int i, cmdi = 1, changeflag = 0; + const char *stoptokens[] = { "make", "force", NULL }; + struct ph_fieldselector *selectors = NULL, *changes = NULL; + char *user; + + if (strcasecmp(cmdv[0], "make") == 0) + { + user = ph_whoami(ph); + if (user == NULL) + { + nph_printf(1, "not logged in\n"); + print_help(cmdv[0]); + return -1; + } + + selectors = (struct ph_fieldselector *)calloc(2, sizeof(struct ph_fieldselector)); + selectors[0].pfs_field = strdup("alias"); + selectors[0].pfs_value = strdup(user); + selectors[0].pfs_operation = '='; + } + else + { + /* parse field selectors */ + i = nph_parse_selectors(cmdv, &cmdi, stoptokens, 0, + &selectors); + if (i == -2) + { + nph_printf(1, "%s: no %s specified\n", cmdv[0], + (cmdi == 1 ? "selectors" : "changes")); + print_help(cmdv[0]); + if (selectors != NULL) + ph_free_selectors(selectors); + return -1; + } + + /* set force flag if it's a "force" command */ + if (i == 1) + changeflag |= PH_CHANGE_FORCE; + cmdi++; + + } + + /* parse changes */ + i = nph_parse_selectors(cmdv, &cmdi, NULL, 1, &changes); + if (i != -2) + { + nph_printf(1, "%s: invalid change: \"%s\"\n", cmdv[0], + cmdv[cmdi]); + print_help(cmdv[0]); + ph_free_selectors(selectors); + if (changes != NULL) + ph_free_selectors(changes); + return -1; + } + + /* send change command */ + i = ph_change(ph, selectors, changes, changeflag); + switch (i) + { + case -1: + nph_printf(1, "ph_change(): %s\n", strerror(errno)); + break; + + case PH_ERR_NOTLOG: + nph_printf(1, "not logged in\n"); + break; + + case PH_ERR_READONLY: + nph_printf(1, "server is in read-only mode\n"); + break; + + case PH_ERR_DATAERR: + nph_printf(1, "illegal value specified\n"); + break; + + default: + nph_printf(0, "%d entries changed\n", i); + } + + /* clean up */ + ph_free_selectors(selectors); + ph_free_selectors(changes); + return i; +} + + +/* delete entries */ +int +nph_delete(int cmdc, char **cmdv) +{ + int i, cmdi = 1; + struct ph_fieldselector *selectors = NULL; + + /* parse field selectors */ + if (nph_parse_selectors(cmdv, &cmdi, NULL, 0, &selectors) != -2) + { + nph_printf(1, "%s: invalid argument: \"%s\"\n", cmdv[0], + cmdv[cmdi]); + print_help(cmdv[0]); + if (selectors != NULL) + ph_free_selectors(selectors); + return -1; + } + + /* send delete command */ + i = ph_delete(ph, selectors); + switch (i) + { + case -1: + nph_printf(1, "ph_delete(): %s\n", strerror(errno)); + break; + + case PH_ERR_NOTLOG: + nph_printf(1, "not logged in\n"); + break; + + case PH_ERR_READONLY: + nph_printf(1, "server is in read-only mode\n"); + break; + + default: + nph_printf(0, "deleted %d entries\n", i); + } + + /* clean up */ + ph_free_selectors(selectors); + return i; +} + + +/* add an entry */ +int +nph_add(int cmdc, char **cmdv) +{ + int i, cmdi = 1; + struct ph_fieldselector *fields = NULL; + + /* parse field data */ + if (nph_parse_selectors(cmdv, &cmdi, NULL, 1, &fields) != -2) + { + nph_printf(1, "%s: invalid argument: \"%s\"\n", cmdv[0], + cmdv[cmdi]); + print_help(cmdv[0]); + if (fields != NULL) + ph_free_selectors(fields); + return -1; + } + + /* send add command */ + i = ph_add(ph, fields); + switch (i) + { + case -1: + nph_printf(1, "ph_add(): %s\n", strerror(errno)); + break; + + case PH_ERR_NOTLOG: + nph_printf(1, "not logged in\n"); + break; + + case PH_ERR_READONLY: + nph_printf(1, "server is in read-only mode\n"); + break; + + case PH_ERR_DATAERR: + nph_printf(1, "invalid field data\n"); + break; + + default: + nph_printf(0, "add successful\n"); + } + + /* clean up */ + ph_free_selectors(fields); + return i; +} + + +/* retrieve data from server */ +int +nph_query(int cmdc, char **cmdv) +{ + char *altdomain = NULL, *altserver = NULL; + struct ph_serversite *serversite = NULL; + PH *altph = NULL; + int usealtph = 0; + int i, j = 0, cmdi = 1; + struct ph_fieldselector *selectors = NULL; + ph_entry *entries; + const char *stoppers[] = { "return", NULL }; + char **retfields = NULL, **realretfields = NULL, *default_fields; + int redirect_flag = 0; + char buf[NPH_BUF_SIZE]; + char *wordp, *nextp; + +#ifdef DEBUG + printf("==> nph_query(cmdc=%d, cmdv[]={\"%s\"", cmdc, cmdv[0]); + for (i = 1; i < cmdc; i++) + printf(",\"%s\"", cmdv[i]); + printf("})\n"); +#endif + + if (cmdc < 2) + { + nph_printf(1, "%s: required argument missing\n", cmdv[0]); + print_help(cmdv[0]); + return -1; + } + + /* + ** if "@domain" is specified, remove it from the argument list + ** and save + */ + if (cmdv[cmdc - 1][0] == '@') + { + altdomain = cmdv[cmdc - 1] + 1; + cmdv[cmdc - 1] = NULL; + } + + /* parse field data */ + i = nph_parse_selectors(cmdv, &cmdi, stoppers, 0, &selectors); + if (i == -1) + { + nph_printf(1, "parse error in query command\n"); + return -1; + } + + /* if the return fields have been specified, parse them */ + if (i == 0) + for (j = 0, cmdi++; cmdv[cmdi]; cmdi++, j++) + { + retfields = (char **)realloc(retfields, + (j + 2) * sizeof(char *)); + retfields[j] = cmdv[cmdi]; + retfields[j + 1] = NULL; + } + else + { + get_option("returnfields", &default_fields); + if (default_fields != NULL) + { + snprintf(buf, sizeof(buf), "%s", default_fields); + nextp = buf; + j = 0; + while ((wordp = strsep(&nextp, " ")) != NULL) + { + if (*wordp == '\0') + continue; + + retfields = (char **)realloc(retfields, + (j + 2) * sizeof(char *)); + retfields[j] = wordp; + retfields[++j] = NULL; + } + } + } + get_option("canonicaladdrs", &redirect_flag); + if (redirect_flag + && !field_match("alias", retfields)) + { + realretfields = (char **)malloc((j + 2) * sizeof(char *)); + memcpy(realretfields, retfields, j * sizeof(char *)); + realretfields[j] = "alias"; + realretfields[j + 1] = NULL; + } + else + realretfields = retfields; + +#ifdef DEBUG + if (retfields != NULL) + for (i = 0; retfields[i] != NULL; i++) + printf("retfields[%d] = \"%s\"\n", i, retfields[i]); + if (realretfields != NULL) + for (i = 0; realretfields[i] != NULL; i++) + printf("realretfields[%d] = \"%s\"\n", i, + realretfields[i]); +#endif + + /* + ** if "@domain" was specified, + ** try to find the PH server for that domain + */ + if (altdomain != NULL) + { + if (!got_servers + && ph_serverlist_merge(ph, &serverlist) == -1) + { + nph_printf(1, "%s: ph_serverlist_merge(): %s\n", + cmdv[0], strerror(errno)); + return -1; + } + got_servers = 1; + + i = ph_serverlist_iterate(&serverlist, altdomain, NULL, + &serversite); + if (i == 0) + { + nph_printf(1, + "%s: no known PH server for domain \"%s\"\n", + cmdv[0], altdomain); + return -1; + } + if (i == -1) + { + nph_printf(1, "%s: ph_serverlist_iterate(): %s\n", + cmdv[0], strerror(errno)); + return -1; + } + + /* + ** make sure the match isn't just a pointer to the + ** current server + */ + get_option("server", &wordp); + if (strcasecmp(wordp, serversite->ss_server) != 0) + { + /* found a match */ + altserver = strdup(serversite->ss_server); + + /* connect to the alternate server */ + if (server_init(&altph, altserver)) + return -1; + + usealtph = 1; + } + } + if (altph == NULL) + altph = ph; + + /* send query */ + i = ph_query(altph, selectors, + (realretfields ? realretfields : retfields), &entries); + + if (usealtph) + { + if (ph_close(altph, 0) == -1) + nph_printf(1, "%s: ph_close(\"%s\"): %s\n", + cmdv[0], altserver, strerror(errno)); + free(altserver); + } + + if (i == PH_ERR_TOOMANY) + { + nph_printf(1, "too many matches\n"); + return -2; + } + if (i == PH_ERR_NOMATCH) + { + nph_printf(1, "no matches to query\n"); + return -2; + } + if (i == PH_ERR_DATAERR) + { + nph_printf(1, "invalid query\n"); + return -2; + } + if (i == -1) + { + nph_printf(1, "ph_query(): %s\n", strerror(errno)); + return -1; + } + + /* print out returned entries */ + nph_printf(1, "matched %d entr%s\n", i, (i == 1 ? "y" : "ies")); + if (i != 0) + { + for (i = 0; entries[i] != NULL; i++) + { + nph_printf(0, "----------------------------------------" + "\n"); + nph_printf(0, "ENTRY #%d:\n", i + 1); + print_entry(entries[i], retfields, redirect_flag); + } + nph_printf(0, "----------------------------------------\n"); + ph_free_entries(entries); + } + + /* clean up */ + ph_free_selectors(selectors); + if (retfields != NULL) + free(retfields); + if (realretfields != retfields) + free(realretfields); + + if (usealtph) + nph_printf(1, "resuming primary PH connection\n"); + + return 0; +} + + +/* me command */ +int +nph_me(int cmdc, char **cmdv) +{ + ph_entry *entry; + struct ph_fieldselector selector[2]; + char *retfield[2]; + int i; + + if (cmdv[1] != NULL) + { + print_help(cmdv[0]); + return -1; + } + if (ph_whoami(ph) == NULL) + { + nph_printf(1, "not logged in\n"); + return -1; + } + + /* construct query */ + selector[0].pfs_field = "alias"; + selector[0].pfs_operation = '='; + selector[0].pfs_value = ph_whoami(ph); + memset(&(selector[1]), 0, sizeof(struct ph_fieldselector)); + retfield[0] = "all"; + retfield[1] = NULL; + + /* send query */ + i = ph_query(ph, selector, retfield, &entry); + if (i == -1) + { + perror("ph_query()"); + return -1; + } + if (i != 1) + { + nph_printf(1, "internal error: can't get entry for alias=%s\n", + ph_whoami(ph)); + return -1; + } + + /* print entry */ + print_entry(entry[0], NULL, 0); + + /* clean up and return */ + ph_free_entries(entry); + return 0; +} + + diff --git a/nph/edit.c b/nph/edit.c new file mode 100644 index 0000000..7ebd160 --- /dev/null +++ b/nph/edit.c @@ -0,0 +1,237 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** edit.c - nph code to edit server data +** +** Mark D. Roth +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + + +/* use an external editor to edit the given text */ +static int +edit_value(char *oldval, char *buf, size_t bufsize) +{ + int i, fd; + char *editor, *cp; + char path[MAXPATHLEN]; + char cmd[NPH_BUF_SIZE]; + char c; + + /* create temp file */ + cp = getenv("TMPDIR"); + if (cp == NULL) + cp = "/tmp"; + snprintf(path, sizeof(path), "%s/nph-XXXXXX", cp); + fd = mkstemp(path); + if (fd == -1) + { + fprintf(stderr, "nph: edit_value(): mkstemp(): %s\n", + strerror(errno)); + return -1; + } + + /* write the current value out to the temp file */ + if (write(fd, oldval, strlen(oldval)) == -1) + { + perror("write()"); + close(fd); + unlink(path); + return -1; + } + if (close(fd) == -1) + { + perror("close()"); + unlink(path); + return -1; + } + + /* determine which editor to invoke */ + get_option("editor", &editor); + + while (1) + { + /* invoke the editor */ + snprintf(cmd, sizeof(cmd), "%s %s", editor, path); + if (system(cmd)) + { + perror("system()"); + unlink(path); + return -1; + } + + /* continue with the change if confirmedits isn't on */ + get_option("confirmedits", &i); + if (i == 0) + break; + + do + { + nph_printf(1, + "confirm change ([Y]es, [N]o, [E]dit): "); + fgets(cmd, sizeof(cmd), stdin); + c = tolower(cmd[0]); + } + while (c != 'y' && c != 'n' && c != 'e'); + + /* procede with change */ + if (c == 'y') + break; + + /* edit again */ + if (c == 'e') + continue; + + /* user typed 'n' */ + unlink(path); + return -1; + } + + /* re-read the tmpfile */ + fd = open(path, O_RDONLY); + if (fd == -1) + { + perror("open()"); + unlink(path); + return -1; + } + if ((i = read(fd, buf, bufsize)) == -1) + { + perror("read()"); + unlink(path); + return -1; + } + buf[i] = '\0'; + if (close(fd) == -1) + { + perror("close()"); + unlink(path); + return -1; + } + if (unlink(path) == -1) + { + perror("unlink()"); + return -1; + } + + return 0; +} + + +/* edit command */ +int +nph_edit(int cmdc, char **cmdv) +{ + int i; + char buf[NPH_BUF_SIZE]; + ph_entry *entry; + struct ph_fieldselector selector[2]; + struct ph_fieldselector change[2]; + char *retfields[2]; + char *user; + + if (cmdv[1] == NULL) + { + fprintf(stderr, "edit: field parameter missing\n"); + return -1; + } + + user = ph_whoami(ph); + if (user == NULL) + { + fprintf(stderr, "not logged in\n"); + return 1; + } + + /* create the query */ + selector[0].pfs_field = "alias"; + selector[0].pfs_operation = '='; + selector[0].pfs_value = (cmdv[2] ? cmdv[2] : user); + memset(&(selector[1]), 0, sizeof(struct ph_fieldselector)); + retfields[0] = cmdv[1]; + retfields[1] = NULL; + + /* send the query */ + i = ph_query(ph, selector, retfields, &entry); + if (i == -1) + { + perror("ph_query()"); + return -1; + } + if (i != 1) + { + fprintf(stderr, + "internal error: can't get alias=%s field %s\n", + ph_whoami(ph), cmdv[1]); + ph_free_entries(entry); + return -1; + } + + /* let the user edit the value */ + if (edit_value(entry[0][0].pfv_value, buf, sizeof(buf))) + { + ph_free_entries(entry); + return -1; + } + + /* create the change */ + change[0].pfs_field = cmdv[1]; + change[0].pfs_operation = '='; + change[0].pfs_value = buf; + memset(&(change[1]), 0, sizeof(struct ph_fieldselector)); + + /* send change command */ + i = ph_change(ph, selector, change, 0); + switch (i) + { + case -1: + nph_printf(1, "ph_change(): %s\n", strerror(errno)); + break; + + case PH_ERR_NOTLOG: + /* + ** can't happen, because we check for this above, + ** but we'll handle it, just in case + */ + nph_printf(1, "not logged in\n"); + break; + + case PH_ERR_READONLY: + nph_printf(1, "server is in read-only mode\n"); + break; + + case PH_ERR_DATAERR: + nph_printf(1, "illegal value specified\n"); + break; + + default: + break; + } + + /* clean up and return */ + ph_free_entries(entry); + return 0; +} + + diff --git a/nph/init.c b/nph/init.c new file mode 100644 index 0000000..744779c --- /dev/null +++ b/nph/init.c @@ -0,0 +1,293 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** init.c - nph code to initialize a new server connection +** +** Mark D. Roth +*/ + +#include + +#include +#include +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + + +/* verify that a field exists on the server */ +int +check_field(PH *newph, char *field) +{ + struct ph_fieldinfo *fieldinfo = NULL; + + if (ph_get_fieldinfo(newph, field, &fieldinfo) == PH_ERR_DATAERR) + { + nph_printf(1, "unknown field \"%s\"\n", field); + return -1; + } + return 0; +} + + +/* verify that a list of fields exists on the server */ +int +check_fields(PH *newph, char *string) +{ + char buf[NPH_BUF_SIZE]; + char *wordp, *nextp; + + strlcpy(buf, string, sizeof(buf)); + nextp = buf; + while ((wordp = strsep(&nextp, " ")) != NULL) + { + if (*wordp == '\0') + continue; + + if (check_field(newph, wordp) == -1) + return -1; + } + + return 0; +} + + +/* connect to PH server and initialize options */ +int +server_init(PH **newph, char *server) +{ + int i, debug, ph_open_flags = PH_OPEN_DONTID; + char *fields = NULL; + char buf[NPH_BUF_SIZE]; + + /* set flags */ + if (strchr(server, '/') != NULL) + ph_open_flags |= PH_OPEN_LOCAL; + else if (geteuid() == 0) + { + get_option("usereservedport", &i); + if (i) + ph_open_flags |= PH_OPEN_PRIVPORT; + } + get_option("debug", &debug); + + /* open connection */ + if (ph_open(newph, server, ph_open_flags, + (debug ? send_debug : NULL), + (debug ? recv_debug : NULL), + NULL) == -1) + { + nph_printf(1, "ph_open(): %s\n", strerror(errno)); + return -1; + } + nph_printf(1, "connected to PH server %s\n", server); + + /* send id */ + snprintf(buf, sizeof(buf), "nph-%s", PACKAGE_VERSION); + if (ph_id(*newph, buf) == -1) + { + nph_printf(1, "ph_id(): %s\n", strerror(errno)); + return -1; + } + + /* validate field list */ + get_option("returnfields", &fields); + if (fields != NULL + && check_fields(*newph, fields)) + { + nph_printf(1, "unsetting invalid \"returnfields\" option\n"); + set_option("returnfields", ""); + } + + return 0; +} + + +/* read the system-wide ph_server file */ +char * +read_server_file(void) +{ + FILE *f; + char buf[MAXHOSTNAMELEN + 5]; + + f = fopen(SERVER_FILE, "r"); + if (f == NULL) + { + nph_printf(1, "cannot open server file %s: %s\n", + SERVER_FILE, strerror(errno)); + exit(1); + } + + if (fgets(buf, sizeof(buf), f) == NULL) + { + nph_printf(1, "fgets(): %s\n", strerror(errno)); + fclose(f); + exit(1); + } + + fclose(f); + + /* strip newline */ + if (buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = '\0'; + + return strdup(buf); +} + + +/* change servers */ +int +nph_connect(int cmdc, char **cmdv) +{ + PH *newph; + + if (cmdv[1] == NULL + || cmdv[2] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + if (server_init(&newph, cmdv[1]) != 0) + return -1; + + /* close old connection */ + if (ph != NULL) + { + nph_printf(1, "disconnecting from server %s\n", ph_server); + if (ph_close(ph, 0) == -1) + nph_printf(1, "warning: ph_close(): %s\n", + strerror(errno)); + } + + /* save new handle */ + ph = newph; + ph_server = strdup(cmdv[1]); + got_servers = 0; + + return 0; +} + + +/* read an nphrc file */ +int +read_nphrc(char *filename) +{ + struct passwd *pw; + char nphrc[MAXPATHLEN]; + char *cp; + int i; + + if (filename != NULL) + return read_command_file(filename); + + cp = getenv("HOME"); + if (cp == NULL) + { + pw = getpwuid(getuid()); + if (pw == NULL) + { + perror("nph: cannot determine user's home directory: " + "getpwuid()"); + return -1; + } + cp = pw->pw_dir; + } + + snprintf(nphrc, sizeof(nphrc), "%s/.nphrc.%s", cp, ph_server); + i = read_command_file(nphrc); + + if (i == 1) + { + snprintf(nphrc, MAXPATHLEN, "%s/.nphrc", cp); + i = read_command_file(nphrc); + } + + if (i == 1) + { + snprintf(nphrc, MAXPATHLEN, "%s", SYSTEM_NPHRC); + i = read_command_file(nphrc); + } + + return i; +} + + +/* read commands from a file and execute them */ +int +read_command_file(char *filename) +{ + char buf[NPH_BUF_SIZE]; + FILE *f; + int line = 0; + char *p; + + /* open file */ + f = fopen(filename, "r"); + if (f == NULL) + { + if (errno == ENOENT) + return 1; + nph_printf(1, "cannot open %s: %s\n", filename, + strerror(errno)); + return -1; + } + nph_printf(1, "reading file %s...\n", filename); + + /* parse each line of the config file */ + while (fgets(buf, sizeof(buf), f) != NULL) + { + line++; + + /* strip off newlines */ + if (buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = '\0'; + + /* strip off comments */ + if ((p = strchr(buf, '#')) != NULL) + *p = '\0'; + + /* handle blank lines */ + if (buf[0] == '\0') + continue; + + /* run command */ + nph_command(buf); + } + + fclose(f); + return 0; +} + + +/* read commands from a file */ +int +nph_source(int cmdc, char **cmdv) +{ + int i; + + if (cmdv[1] == NULL + || cmdv[2] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + i = read_command_file(cmdv[1]); + if (i == 1) + nph_printf(1, "cannot open %s: no such file or directory\n", + cmdv[1]); + return i; +} + + diff --git a/nph/interactive.c b/nph/interactive.c new file mode 100644 index 0000000..6fe0ca1 --- /dev/null +++ b/nph/interactive.c @@ -0,0 +1,439 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** interactive.c - command line interface for nph +** +** Mark D. Roth +*/ + +#include + +#include +#include + +/* FIXME: IRIX's poll() is broken... */ +#ifdef sgi +# undef HAVE_POLL +#endif + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_SYS_POLL_H +# include +#else +# ifdef HAVE_SYS_SELECT_H +# include +# endif +#endif + +#ifdef HAVE_READLINE_READLINE_H +# include +#endif +#ifdef HAVE_READLINE_HISTORY_H +# include +#endif + + +/* local convenience variable */ +const char *prompt = "nph> "; + + +#ifdef HAVE_LIBREADLINE + +/* readline hook to process the entered command */ +static void +rl_docmd(char *line) +{ + char buf[NPH_BUF_SIZE]; /* space for an input line */ + + /* EOF */ + if (line == NULL) + { + rl_callback_handler_remove(); + sighandler_state = HANDLER_DEFAULT; + ph_close(ph, 0); + exit(0); + } + + /* blank line */ + if (*line == '\0') + { + free(line); + return; + } + + add_history(line); + strlcpy(buf, line, sizeof(buf)); + free(line); + + /* do command */ + nph_command(buf); + putchar('\n'); +} + + +/* server option completion function */ +static char * +rl_complete_set(char *text, int state) +{ + static struct ph_option *phopt; + static int textlen; + int debug; + + if (!state) + { + phopt = NULL; + textlen = strlen(text); + if (!ph_is_optionlist_cached(ph)) + { + get_option("debug", &debug); + if (debug) + { + putchar('\n'); + rl_on_new_line(); + } + if (ph_retrieve_options(ph) == -1) + { + perror("ph_retrieve_options()"); + return NULL; + } + if (debug) + rl_redisplay(); + } + } + + while (ph_option_iterate(ph, &phopt) == 1) + if (strncasecmp(phopt->po_option, text, textlen) == 0) + return strdup(phopt->po_option); + + return NULL; +} + + +/* field completion function */ +static char * +rl_complete_field(char *text, int state) +{ + static struct ph_fieldinfo *phfield; + static int namecounter; + static int textlen; + int debug; + + if (!state) + { + phfield = NULL; + textlen = strlen(text); + if (!ph_is_fieldinfo_cached(ph)) + { + get_option("debug", &debug); + if (debug) + { + putchar('\n'); + rl_on_new_line(); + } + if (ph_retrieve_fieldinfo(ph) == -1) + { + perror("ph_retrieve_fieldinfo()"); + return NULL; + } + if (debug) + rl_redisplay(); +#ifdef DEBUG + printf("==> rl_complete_field(\"%s\")\n", text); +#endif + } + } + else + namecounter++; + + while (1) + { + if (phfield != NULL) + for (; + phfield->pf_fnames[namecounter] != NULL; + namecounter++) + { +#ifdef DEBUG + printf("rl_complete_field(): " + "phfield->pf_fnames[%d] = \"%s\"\n", + namecounter, + phfield->pf_fnames[namecounter]); +#endif + if (strncasecmp(phfield->pf_fnames[namecounter], + text, textlen) == 0) + return strdup(phfield->pf_fnames[namecounter]); + } + + if (ph_fieldinfo_iterate(ph, &phfield) != 1) + break; + + namecounter = 0; + } + + return NULL; +} + + +/* command completion function (in commands.c) */ +char *rl_complete_command(char *text, int state); + +/* config option completion function (in conf.c) */ +char *rl_complete_conf(char *text, int state); + + +/* completion hook */ +static char ** +rl_completion_hook(char *text, int start, int end) +{ + int leading_spaces; + char **cpp; + + /* handle completion interrupts */ + if (sigsetjmp(complete_env, 1) != 0) + return NULL; + sighandler_state = HANDLER_COMPLETION; + + /* + ** inhibit normal filename completion. + ** (must be in the completion hook.) + */ + rl_attempted_completion_over = 1; + + leading_spaces = strspn(rl_line_buffer, " "); + + /* command completion at beginning of line or as argument to "help" */ + if (start == leading_spaces + || strncasecmp(rl_line_buffer + leading_spaces, "help ", 5) == 0) + { + rl_completion_append_character = ' '; + return rl_completion_matches(text, + (rl_compentry_func_t *)rl_complete_command); + } + + /* client option completion */ + if (strncasecmp(rl_line_buffer + leading_spaces, "option ", 7) == 0 + || strncasecmp(rl_line_buffer + leading_spaces, "switch ", 7) == 0) + { + rl_completion_append_character = '='; + return rl_completion_matches(text, + (rl_compentry_func_t *)rl_complete_conf); + } + + /* server option completion */ + if (strncasecmp(rl_line_buffer + leading_spaces, "set ", 4) == 0) + { + rl_completion_append_character = '='; + return rl_completion_matches(text, + (rl_compentry_func_t *)rl_complete_set); + } + + /* file name completion */ + if (strncasecmp(rl_line_buffer + leading_spaces, "source ", 7) == 0) + { + rl_completion_append_character = ' '; + return rl_completion_matches(text, + (rl_compentry_func_t *)rl_filename_completion_function); + } + + /* field completion */ + if (strncasecmp(rl_line_buffer + leading_spaces, "fields ", 7) == 0 + || strncasecmp(rl_line_buffer + leading_spaces, "edit ", 5) == 0 + || (strncasecmp(rl_line_buffer + leading_spaces, "query ", 6) == 0 + && strstr(rl_line_buffer, " return ") != NULL)) + rl_completion_append_character = ' '; + else + rl_completion_append_character = '='; + cpp = rl_completion_matches(text, + (rl_compentry_func_t *)rl_complete_field); + if (cpp != NULL) + return cpp; + + /* keyword completion */ + rl_completion_append_character = ' '; + + if (strncasecmp(rl_line_buffer + leading_spaces, "query ", 6) == 0 + && strspn(rl_line_buffer + leading_spaces + 5, " ") < (size_t)(start - (leading_spaces + 5)) + && strstr(rl_line_buffer, " return ") == NULL) + { + if (strncasecmp(text, "return", strlen(text)) == 0) + { + cpp = (char **)calloc(2, sizeof(char *)); + if (cpp != NULL) + cpp[0] = strdup("return"); + } + return cpp; + } + + if (strncasecmp(rl_line_buffer + leading_spaces, "change ", 7) == 0 + && strspn(rl_line_buffer + leading_spaces + 6, " ") < (size_t)(start - (leading_spaces + 6)) + && strstr(rl_line_buffer, " make ") == NULL + && strstr(rl_line_buffer, " force ") == NULL) + { + if (strncasecmp(text, "make", strlen(text)) == 0) + { + cpp = (char **)calloc(2, sizeof(char *)); + if (cpp != NULL) + cpp[0] = strdup("make"); + return cpp; + } + if (strncasecmp(text, "force", strlen(text)) == 0) + { + cpp = (char **)calloc(2, sizeof(char *)); + if (cpp != NULL) + cpp[0] = strdup("force"); + return cpp; + } + } + + return NULL; +} + +#endif /* HAVE_LIBREADLINE */ + + +void +interactive(void) +{ + char cmdbuf[NPH_BUF_SIZE]; +#ifdef HAVE_POLL + struct pollfd pfd[2]; +#else + fd_set rfds, efds; +#endif + +#ifdef HAVE_LIBREADLINE + /* initialize readline */ + if (isatty(fileno(stdin))) + { + /* set readline callback handler for polling */ + rl_callback_handler_install(prompt, rl_docmd); + + /* set completion hook */ + rl_attempted_completion_function = (CPPFunction *)rl_completion_hook; + rl_ignore_completion_duplicates = 1; + + /* set application name for readline init file */ + rl_readline_name = "nph"; + } +#endif /* HAVE_LIBREADLINE */ + + while (1) + { + /* set state for signal handler */ + sighandler_state = HANDLER_INPUT; + + /* initialize file descriptor multiplexing */ +#ifdef HAVE_POLL + pfd[0].fd = fileno(stdin); + pfd[0].events = POLLIN | POLLPRI; + pfd[0].revents = 0; + pfd[1].fd = ph_rfd(ph); + pfd[1].events = POLLIN | POLLPRI | POLLERR; + pfd[1].revents = 0; +#else /* ! HAVE_POLL */ + FD_ZERO(&rfds); + FD_ZERO(&efds); + FD_SET(fileno(stdin), &rfds); + FD_SET(ph_rfd(ph), &rfds); + FD_SET(ph_rfd(ph), &efds); +#endif /* HAVE_POLL */ + +#ifndef HAVE_LIBREADLINE + if (isatty(fileno(stdin))) + { + printf("%s", prompt); + fflush(stdout); /* prompt */ + } +#endif /* ! HAVE_LIBREADLINE */ + +#ifdef HAVE_POLL + if (poll(pfd, 2, -1) == -1) + { + if (errno == EINTR) + continue; + perror("poll()"); + exit(1); + } + if (pfd[1].revents) +#else /* ! HAVE_POLL */ + if (select((fileno(stdin) > ph_rfd(ph) + ? fileno(stdin) + : ph_rfd(ph)) + 1, + &rfds, NULL, &efds, NULL) == -1) + { + if (errno == EINTR) + continue; + perror("select()"); + exit(1); + } + if (FD_ISSET(ph_rfd(ph), &rfds) + || FD_ISSET(ph_rfd(ph), &efds)) +#endif /* HAVE_POLL */ + { + puts("\nnph: server closed connection, exiting"); +#ifdef HAVE_LIBREADLINE + rl_callback_handler_remove(); +#endif /* HAVE_LIBREADLINE */ + ph_close(ph, PH_CLOSE_FAST); + exit(1); + } + + /* command input available */ +#ifdef HAVE_POLL + if (pfd[0].revents) +#else /* ! HAVE_POLL */ + if (FD_ISSET(fileno(stdin), &rfds)) +#endif /* HAVE_POLL */ + { +#ifdef HAVE_LIBREADLINE + if (isatty(fileno(stdin))) + { + rl_callback_read_char(); + continue; + } +#endif /* HAVE_LIBREADLINE */ + + if (fgets(cmdbuf, sizeof(cmdbuf), stdin) == NULL) + { + if (ferror(stdin)) + { + perror("fgets()"); + exit(1); + } + + /* got EOF - exit normally */ + ph_close(ph, 0); + exit(0); + } + + /* strip trailing newline */ + if (cmdbuf[strlen(cmdbuf) - 1] == '\n') + cmdbuf[strlen(cmdbuf) - 1] = '\0'; + + /* skip empty lines */ + if (cmdbuf[0] == '\0') + continue; + + nph_command(cmdbuf); + putchar('\n'); + } + } + + /* can't happen */ + fprintf(stderr, + "nph: internal error: reached the end of interactive()\n"); + exit(1); +} + + diff --git a/nph/login.c b/nph/login.c new file mode 100644 index 0000000..75d5112 --- /dev/null +++ b/nph/login.c @@ -0,0 +1,212 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** login.c - authentication code for nph +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + + +/* id */ +int +nph_id(int cmdc, char **cmdv) +{ + char buf[NPH_BUF_SIZE]; + int i, buflen = 0; + + if (cmdv[1] == NULL) + { + print_help(cmdv[0]); + return -1; + } + + for (i = 1; cmdv[i] != NULL; i++) + buflen += snprintf(buf + buflen, sizeof(buf) - buflen, " %s", + cmdv[i]); + if (ph_id(ph, buf + 1) == -1) + { + nph_printf(1, "ph_id(): %s\n", strerror(errno)); + return -1; + } + + nph_printf(0, "sent id \"%s\"\n", buf + 1); + return 0; +} + + +/* external */ +int +nph_external(int cmdc, char **cmdv) +{ + if (cmdv[1] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + if (ph_external(ph) == -1) + { + nph_printf(1, "ph_external(): %s\n", strerror(errno)); + return -1; + } + + nph_printf(0, "session is now external\n"); + return 0; +} + + +/* suser command */ +int +nph_suser(int cmdc, char **cmdv) +{ + int i; + + if (cmdv[1] == NULL + || cmdv[2] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + i = ph_suser(ph, cmdv[1]); + if (i == -1) + nph_printf(1, "ph_suser(): %s\n", strerror(errno)); + else if (i == PH_ERR_NOTHERO || i == PH_ERR_NOTLOG) + nph_printf(1, "permission denied\n"); + else + nph_printf(0, "suser succeeded\n"); + + return i; +} + + +/* login to server */ +int +nph_login(int cmdc, char **cmdv) +{ + int i, auth_method; + char *p; + + if (cmdv[1] == NULL + || cmdv[2] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + /* check auth_method configuration option */ + get_option("authtype", &auth_method); + + /* read password from user if needed */ + if (auth_method == PH_AUTH_EMAIL) + p = NULL; + else + p = getpass("Password: "); + + /* login to server */ + i = ph_login(ph, cmdv[1], auth_method, p); + if (i == -1) + nph_printf(1, "ph_login(): %s\n", strerror(errno)); + else if (i == PH_ERR_NOTLOG) + nph_printf(1, "login incorrect\n"); + else + nph_printf(0, "login successful\n"); + + return i; +} + + +/* logout of server */ +int +nph_logout(int cmdc, char **cmdv) +{ + int i; + + if (cmdv[1] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + i = ph_logout(ph); + if (i == -1) + nph_printf(1, "ph_logout(): %s\n", strerror(errno)); + else if (i == PH_ERR_NOTLOG) + nph_printf(1, "not logged in\n"); + else + nph_printf(0, "logged out\n"); + + return i; +} + + +/* change password */ +int +nph_passwd(int cmdc, char **cmdv) +{ + char *pass, *p; + int i; + + if (ph_whoami(ph) == NULL) + { + nph_printf(1, "not logged in\n"); + return -1; + } + if (cmdv[1] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + /* read new password twice */ + p = getpass("New password: "); + if (p == NULL + || *p == '\0') + { + nph_printf(1, "invalid password\n"); + return -1; + } + pass = strdup(p); + p = getpass("Confirm password: "); + if (p == NULL + || *p == '\0') + { + nph_printf(1, "invalid password\n"); + return -1; + } + if (strcmp(pass, p) != 0) + { + nph_printf(1, "passwords do not match\n"); + return -1; + } + + /* issue change command */ + i = ph_passwd(ph, pass); + if (i == -1) + nph_printf(1, "ph_passwd()i: %s\n", strerror(errno)); + else if (i == PH_ERR_NOTLOG) + nph_printf(1, "not logged in\n"); + else + nph_printf(1, "password updated\n"); + + /* clean up and return */ + free(pass); + return i; +} + + diff --git a/nph/nph.c b/nph/nph.c new file mode 100644 index 0000000..f73f571 --- /dev/null +++ b/nph/nph.c @@ -0,0 +1,152 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** nph.c - main driver program for nph +** +** Mark D. Roth +*/ + +#include + +#include +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + + +/* global variables */ +PH *ph = NULL; +char *ph_server = NULL; +struct ph_serverlist serverlist; +short got_servers; + + +static void +usage(void) +{ + printf("Usage: nph [options] [selectors [return field1 ...]]\n"); + printf("Options: [-s server[:port]] [-f rcfile] [-F fields] [-cCdmrR]\n"); + exit(1); +} + + +int +main(int argc, char *argv[]) +{ + int i, readconfig = 1; + char *nphrc = NULL; + + /* initialize */ + reset_output(1); + set_signals(); + + /* parse commandline options */ + while ((i = getopt(argc, argv, "cCdf:F:hmrRs:V")) != -1) + { + switch (i) + { + case 'c': + set_option("confirmedits", "on"); + break; + case 'C': + readconfig = 0; + break; + case 'f': + nphrc = strdup(optarg); + break; + case 'd': + set_option("debug", "on"); + break; + case 'F': + set_option("returnfields", optarg); + break; + case 'm': + set_option("usepager", "off"); + break; + case 'r': + set_option("canonicaladdrs", "off"); + break; + case 'R': + set_option("usereservedport", "on"); + break; + case 's': + if (ph_server != NULL) + free(ph_server); + ph_server = strdup(optarg); + break; + case 'V': + printf("nph %s by Mark D. Roth \n", + PACKAGE_VERSION); + break; + case 'h': + default: + usage(); + } + } + + /* determine server */ + if (ph_server == NULL) + ph_server = getenv("PH_SERVER"); + if (ph_server == NULL) + ph_server = read_server_file(); + + /* connect to server */ + if (server_init(&ph, ph_server) != 0) + exit(1); + + /* drop privs */ + if (geteuid() == 0 + && setuid(getuid()) != 0) + { + perror("setuid()"); + ph_close(ph, 0); + exit(1); + } + + /* query listed on commandline - disable pager */ + if (optind < argc) + set_option("usepager", "off"); + + /* read the user's rc file */ + if (readconfig) + read_nphrc(nphrc); + if (nphrc != NULL) + free(nphrc); + + /* + ** query listed on commandline. + ** just do the query and exit, don't be interactive + */ + if (optind < argc) + { +#ifdef DEBUG + for (i = optind; i < argc; i++) + printf("argv[%d] = \"%s\"\n", i, argv[i]); +#endif + + /* do query and exit */ + i = nph_query(argc - optind + 1, &(argv[optind - 1])); + ph_close(ph, 0); + exit(i); + } + + /* otherwise, go into interactive mode */ + putchar('\n'); + interactive(); + + /* can't happen */ + fprintf(stderr, "nph: internal error: reached end of main()\n"); + exit(1); +} + + diff --git a/nph/nph.h b/nph/nph.h new file mode 100644 index 0000000..af86cd1 --- /dev/null +++ b/nph/nph.h @@ -0,0 +1,223 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** nph.h - main header file for nph +** +** Mark D. Roth +*/ + +#include + +#include +#include +#include + +#include + + + +#define NPH_BUF_SIZE 8192 + + +/***** commands.c ******************************************************/ + +/* parse a command vector and call the appropriate function */ +int nph_command(char *); + +/* prints the help text for command */ +void print_help(char *); + +/* client help (not server help command) */ +int nph_help(int, char **); + +/* quit command */ +int nph_quit(int, char **); + +/* whoami command */ +int nph_whoami(int, char **); + + +/***** conf.c **********************************************************/ + +/* change the authentication method used to login to the server */ +int nph_option(int, char **); + +/* get the value for an option */ +int get_option(char *, void *); + +/* set the value for an option */ +int set_option(char *, char *); + +/* connect to PH server and initialize options */ +int server_init(PH **, char *); + + +/***** content.c *******************************************************/ + +/* select entries for further processing */ +int nph_select(int, char **); + +/* change entries on the server */ +int nph_change(int, char **); + +/* delete entries */ +int nph_delete(int, char **); + +/* add an entry */ +int nph_add(int, char **); + +/* retrieve entries from the server */ +int nph_query(int, char **); + +/* me command */ +int nph_me(int, char **); + +/* resolve an email address */ +int nph_resolvemail(int, char **); + +/* determine the advertised email address */ +int nph_publicemail(int, char **); + +/* find www field for a given alias */ +int nph_resolvewww(int, char **); + +/* determine advertised URL for a given alias */ +int nph_publicwww(int, char **); + + +/***** edit.c **********************************************************/ + +/* edit command */ +int nph_edit(int, char **); + + +/***** interactive.c ***************************************************/ + +/* interactive mode */ +void interactive(void); + + +/***** init.c **********************************************************/ + +/* verify that a field exists on the server */ +int check_field(PH *, char *); + +/* verify that a list of fields exist on the server */ +int check_fields(PH *, char *); + +/* read the system-wide ph_server file */ +char *read_server_file(void); + +/* change servers */ +int nph_connect(int, char **); + +/* read the user's ~/.nphrc file */ +int read_nphrc(char *); + +/* read commands from a file */ +int nph_source(int, char **); + +/* read commands from a file and execute them */ +int read_command_file(char *); + + +/***** login.c *********************************************************/ + +/* send an id for the server's logs */ +int nph_id(int, char **); + +/* make the session non-local */ +int nph_external(int, char **); + +/* become another user (heros only) */ +int nph_suser(int, char **); + +/* login to the server */ +int nph_login(int, char **); + +/* logout from the server */ +int nph_logout(int, char **); + +/* change password */ +int nph_passwd(int, char **); + + +/***** nph.c ***********************************************************/ + +extern PH *ph; +extern char *ph_server; +extern struct ph_serverlist serverlist; +extern short got_servers; /* flag to indicate we've merged the + server list from ph into serverlist */ + + +/***** output.c ********************************************************/ + +/* output to a pipe */ +int output_pipe(char *); + +/* send output to a file (optionally appending) */ +int output_file(char *, int); + +/* reset output file */ +void reset_output(int); + +/* print a message */ +#ifdef STDC_HEADERS +int nph_printf(int, char *, ...); +#else +int nph_printf(int, char *, int); +#endif + +/* +** returns 1 if one of the aliases of result_name is listed in showfields, +** 0 if not listed, or -1 on error from ph_get_fieldinfo() +*/ +int field_match(char *, char *[]); + +/* print an entry */ +void print_entry(ph_entry, char *[], int); + +/* debugging hooks */ +void send_debug(void *, char *); +void recv_debug(void *, char *); + + +/***** serverinfo.c ****************************************************/ + +/* view list of known PH servers */ +int nph_listservers(int, char **); + +/* add entry to list of known PH servers */ +int nph_serveradd(int, char **); + +/* view server's message of the day */ +int nph_status(int, char **); + +/* show or set server options */ +int nph_set(int, char **); + +/* view siteinfo data */ +int nph_siteinfo(int, char **); + +/* view fields supported by server */ +int nph_fields(int, char **); + + +/***** sighandler.c ****************************************************/ + +extern sigjmp_buf complete_env, command_env; +extern int sighandler_state; + +/* values for sighandler_state */ +#define HANDLER_DEFAULT 0 /* default dispositions */ +#define HANDLER_INPUT 1 /* normal input */ +#define HANDLER_COMPLETION 2 /* commandline completion */ +#define HANDLER_COMMAND 3 /* performing operation */ + +/* set up signal handlers */ +void set_signals(void); + + diff --git a/nph/output.c b/nph/output.c new file mode 100644 index 0000000..3d442b6 --- /dev/null +++ b/nph/output.c @@ -0,0 +1,346 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** output.c - nph code to display server data +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +# include +# include +#else +# ifdef HAVE_VARARGS_H +# include +# endif +#endif + +#include + + +/* values for outtype */ +#define OUT_DEFAULT 0 /* stdout */ +#define OUT_FILE 1 /* file redirection */ +#define OUT_PIPE 2 /* pipe redirection */ + +/* local variables */ +static FILE *outf = NULL; +static int outtype = -1; + + +/* output to a pipe */ +int +output_pipe(char *prog) +{ + FILE *f; + + f = popen(prog, "w"); + if (f == NULL) + { + perror("popen()"); + return -1; + } + + outtype = OUT_PIPE; + outf = f; + return 0; +} + + +/* send output to a file (optionally appending) */ +int +output_file(char *filename, int append) +{ + FILE *f; + + f = fopen(filename, (append ? "a" : "w")); + if (f == NULL) + { + perror("fopen()"); + return -1; + } + + outtype = OUT_FILE; + outf = f; + return 0; +} + + +/* reset output file */ +void +reset_output(int initialize) +{ + if (!initialize) + { + if (outtype == OUT_FILE) + fclose(outf); + else if (outtype == OUT_PIPE) + pclose(outf); + } + + outtype = OUT_DEFAULT; + outf = stdout; +} + + +/* print a message */ +int +#ifdef STDC_HEADERS +nph_printf(int err, char *fmt, ...) +#else +nph_printf(int err, char *fmt, int va_alist) +#endif +{ + size_t i = 0; + va_list args; + + if (err) + fprintf(outf, "nph: "); + +#ifdef STDC_HEADERS + va_start(args, fmt); +#else + va_start(args); +#endif + i += vfprintf(outf, fmt, args); + va_end(args); + + return i; +} + + +/* print a field */ +static void +print_field(struct ph_fieldvalue *field, int width) +{ + int newline_flag = 0; + char *wordp, *nextp; + char buf[NPH_BUF_SIZE]; + + /* special cases */ + if (field->pfv_code != -(LR_OK)) + { + if (field->pfv_code == -(LR_AINFO)) + wordp = "field suppressed"; + else if (field->pfv_code == -(LR_ABSENT)) + wordp = "field not present"; + else if (field->pfv_code == -(LR_ISCRYPT)) + wordp = "encrypted"; + else + wordp = "unknown response code"; + + snprintf(buf, sizeof(buf), "[ %s", field->pfv_field); + nph_printf(0, "%*s : %s ]\n", width + 2, buf, wordp); + return; + } + + nph_printf(0, " %*s : ", width, field->pfv_field); + nextp = field->pfv_value; + while ((wordp = strsep(&nextp, "\n")) != NULL) + { + if (newline_flag) + nph_printf(0, " %*s : ", width, ""); + nph_printf(0, "%s\n", wordp); + newline_flag = 1; + } +} + + +/* +** returns 1 if one of the aliases of result_name is listed in showfields, +** 0 if not listed, or -1 on error from ph_get_fieldinfo() +*/ +int +field_match(char *result_name, char *showfields[]) +{ + struct ph_fieldinfo *phinfo = NULL; + int i, j; + + /* check for no specified return fields or for "all" */ + if (showfields == NULL) + return 1; + for (i = 0; showfields[i] != NULL; i++) + if (strcasecmp(showfields[i], "all") == 0) + return 1; + + /* get info for current field */ + if (ph_get_fieldinfo(ph, result_name, &phinfo) == -1) + { + nph_printf(1, "ph_get_fieldinfo(): %s\n", strerror(errno)); + return -1; + } + + /* check against all aliases */ + for (i = 0; showfields[i] != NULL; i++) + { + /* + ** if ph_get_fieldinfo() returned PH_ERR_DATAERR, phinfo will + ** be NULL. this happens for hidden fields, since they don't + ** show up in the "fields" output, so we just compare to the + ** name specified by the user. + */ + if (phinfo == NULL) + { + if (strcasecmp(showfields[i], result_name) == 0) + return 1; + continue; + } + + for (j = 0; phinfo->pf_fnames[j] != NULL; j++) + if (strcasecmp(showfields[i], + phinfo->pf_fnames[j]) == 0) + return 1; + } + + /* no match */ + return 0; +} + + +/* print an entry */ +void +print_entry(ph_entry entry, char *showfields[], int show_redirection) +{ + int i, j; + int alias = -1, width = 16; + char *advertised_email, *advertised_www; + + /* determine the maximum field width */ + for (j = 0; entry[j].pfv_field != NULL; j++) + { + /* + ** FIXME: we should really call ph_get_fieldinfo() and check + ** the length of all field aliases... + */ + i = strlen(entry[j].pfv_field); + if (i > width) + width = i; + } + + /* loop through the fields in the entry */ + for (j = 0; entry[j].pfv_field != NULL; j++) + { + /* save index of "alias" field */ + if (show_redirection + && strcasecmp(entry[j].pfv_field, "alias") == 0) + alias = j; + + /* check if we should print this entry */ + i = field_match(entry[j].pfv_field, showfields); + if (i == -1) + return; + if (i == 0) + continue; + + /* + ** if it's the email or www field and show_redirection is set, + ** show the PH-redirected value + */ + if (show_redirection) + { + if (strcasecmp(entry[j].pfv_field, "email") == 0) + { + /* make sure we know the alias */ + if (alias == -1) + { + for (alias = j + 1; + entry[alias].pfv_field; + alias++) + if (strcasecmp(entry[alias].pfv_field, + "alias") == 0) + break; + + /* + ** can't find alias field, + ** print normally + */ + if (entry[alias].pfv_field == NULL) + { + alias = -1; + print_field(&entry[j], width); + continue; + } + } + + if (ph_advertised_email(ph, + entry[alias].pfv_value, + 0, &advertised_email) == -1) + { + nph_printf(1, "ph_advertised_email(): " + "%s\n", strerror(errno)); + return; + } + nph_printf(0, " %*s : %s\n", width, "email", + advertised_email); + free(advertised_email); + continue; + } + + if (strcasecmp(entry[j].pfv_field, "www") == 0) + { + /* make sure we know the alias */ + if (alias == -1) + { + for (alias = j + 1; + entry[alias].pfv_field; + alias++) + if (strcasecmp(entry[alias].pfv_field, + "alias") == 0) + break; + + /* + ** can't find alias field, + ** print normally + */ + if (entry[alias].pfv_field == NULL) + { + alias = -1; + print_field(&entry[j], width); + continue; + } + } + + if (ph_advertised_www(ph, + entry[alias].pfv_value, + 0, &advertised_www) != -1) + { + nph_printf(0, " %*s : %s\n", width, + "www", advertised_www); + free(advertised_www); + continue; + } + + /* + ** if ph_advertised_www() returns an error, + ** fall through + */ + } + } + + /* otherwise (show_redirection not set), print normally */ + print_field(&entry[j], width); + } +} + + +void +send_debug(void *dummy, char *text) +{ + nph_printf(0, ">>> %s\n", text); +} + + +void +recv_debug(void *dummy, char *text) +{ + nph_printf(0, "<<< %s\n", text); +} + + diff --git a/nph/serverinfo.c b/nph/serverinfo.c new file mode 100644 index 0000000..728c27d --- /dev/null +++ b/nph/serverinfo.c @@ -0,0 +1,250 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** serverinfo.c - nph code to handle references to other PH servers +** +** Mark D. Roth +*/ + +#include + +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + + +/* add entry to list of known PH servers */ +int +nph_serveradd(int cmdc, char **cmdv) +{ + char buf[NPH_BUF_SIZE]; + + if (cmdc < 2 || cmdc > 3) + { + print_help(cmdv[0]); + return -1; + } + + if (cmdv[2] != NULL) + /* FIXME: not part of libphclient public API! */ + ph_dequote_value(cmdv[2], buf, sizeof(buf)); + else + buf[0] = '\0'; + + return ph_serverlist_add(&serverlist, cmdv[1], buf); +} + + +/* view list of known PH servers */ +int +nph_listservers(int cmdc, char **cmdv) +{ + int i; + struct ph_serversite *serversite = NULL; + + if (cmdc > 3) + { + print_help(cmdv[0]); + return -1; + } + + if (!got_servers && ph_serverlist_merge(ph, &serverlist) == -1) + { + nph_printf(1, "%s: ph_serverlist_merge(): %s\n", cmdv[0], + strerror(errno)); + return -1; + } + got_servers = 1; + + nph_printf(0, "\n%-20s %s\n", "SERVER", "SITE"); + while ((i = ph_serverlist_iterate(&serverlist, cmdv[1], + NULL, &serversite)) != 0) + { + if (i == -1) + { + nph_printf(1, "%s: ph_serverlist_iterate(): %s\n", + cmdv[0], strerror(errno)); + return -1; + } + nph_printf(0, "%-20s %s\n", serversite->ss_server, + serversite->ss_site); + } + + return 0; +} + + +/* status */ +int +nph_status(int cmdc, char **cmdv) +{ + char *p; + + if (cmdv[1] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + if (ph_status(ph, &p) == -1) + { + nph_printf(1, "ph_status(): %s\n", strerror(errno)); + return -1; + } + + if (p != NULL) + { + nph_printf(0, "\nSTATUS INFORMATION:\n\n%s", p); + free(p); + } + else + nph_printf(1, "%s: no status information available\n", + cmdv[0]); + + return 0; +} + + +/* show or set server options */ +int +nph_set(int cmdc, char **cmdv) +{ + char *p; + int i, cmdi; + struct ph_option *phop = NULL; + + /* if options were given, set them */ + if (cmdv[1] != NULL) + { + for (cmdi = 1; cmdv[cmdi] != NULL; cmdi++) + { + if ((p = strchr(cmdv[cmdi], '=')) != NULL) + *p++ = '\0'; + i = ph_set_option(ph, cmdv[cmdi], p); + if (i == -1) + { + nph_printf(1, "ph_set_option(): %s\n", + strerror(errno)); + return -1; + } + else if (i == PH_ERR_DATAERR) + { + nph_printf(1, "unknown option \"%s\"\n", + cmdv[cmdi]); + return 1; + } + nph_printf(0, "set %s=%s\n", cmdv[cmdi], + (p != NULL ? p : "on")); + } + + return 0; + } + + /* no options given - display current settings */ + nph_printf(0, "\n%-20.20s\t%s\n", "OPTION", "SETTING"); + while ((i = ph_option_iterate(ph, &phop)) == 1) + nph_printf(0, "%-20.20s\t%s\n", + phop->po_option, phop->po_setting); + if (i == -1) + nph_printf(1, "ph_option_iterate(): %s\n", strerror(errno)); + + return i; +} + + +/* print out siteinfo data */ +int +nph_siteinfo(int cmdc, char **cmdv) +{ + int i; + struct ph_siteinfo *siteinfo = NULL; + + if (cmdv[1] != NULL) + { + print_help(cmdv[0]); + return -1; + } + + nph_printf(0, "\n%-20.20s\t%s\n", "INFO", "SETTING"); + while ((i = ph_siteinfo_iterate(ph, &siteinfo)) == 1) + nph_printf(0, "%-20.20s\t%s\n", siteinfo->ps_info, + siteinfo->ps_data); + if (i == -1) + nph_printf(1, "ph_siteinfo_iterate(): %s\n", strerror(errno)); + + return i; +} + + +/* display server field information */ +int +nph_fields(int cmdc, char **cmdv) +{ + char buf[NPH_BUF_SIZE]; + int i, cmdi; + struct ph_fieldinfo *fieldinfo = NULL; + + /* display field information */ + nph_printf(0, "\n%-20.20s\t%2s\t%4s\t%s\n\t\t\t%s\n\t\t\t%s\n", + "FIELD", "ID", "MAX", "ATTRIBUTES", "DESCRIPTION", + "ALIASES"); + + /* if arguments were specified, show those fields only */ + if (cmdv[1] != NULL) + { + for (cmdi = 1; cmdv[cmdi] != NULL; cmdi++) + { + if ((i = ph_get_fieldinfo(ph, cmdv[cmdi], + &fieldinfo)) == -1) + { + nph_printf(1, "ph_get_fieldinfo(): %s\n", + strerror(errno)); + return -1; + } + if (i == 1) + nph_printf(0, "%-20.20s\t*** no such field\n", + cmdv[cmdi]); + else + { + ph_decode_field_attributes(fieldinfo->pf_attrib, + buf, sizeof(buf)); + nph_printf(0, "%-20.20s\t%2d\t%4d\t%s\n" + "\t\t\t%s\n\t\t\t", + fieldinfo->pf_fnames[0], + fieldinfo->pf_id, + fieldinfo->pf_max_size, + buf, fieldinfo->pf_description); + for (i = 1; + fieldinfo->pf_fnames[i] != NULL; + i++) + nph_printf(0, "%s ", + fieldinfo->pf_fnames[i]); + nph_printf(0, "\n"); + } + } + return 0; + } + + /* otherwise, show all fields */ + while (ph_fieldinfo_iterate(ph, &fieldinfo) == 1) + { + ph_decode_field_attributes(fieldinfo->pf_attrib, buf, + sizeof(buf)); + nph_printf(0, "%-20.20s\t%2d\t%4d\t%s\n\t\t\t%s\n\t\t\t", + fieldinfo->pf_fnames[0], fieldinfo->pf_id, + fieldinfo->pf_max_size, buf, + fieldinfo->pf_description); + for (i = 1; fieldinfo->pf_fnames[i]; i++) + nph_printf(0, "%s ", fieldinfo->pf_fnames[i]); + nph_printf(0, "\n"); + } + + return 0; +} + + diff --git a/nph/sighandler.c b/nph/sighandler.c new file mode 100644 index 0000000..34a4f77 --- /dev/null +++ b/nph/sighandler.c @@ -0,0 +1,146 @@ +/* +** Copyright 2000-2004 University of Illinois Board of Trustees +** Copyright 2000-2004 Mark D. Roth +** All rights reserved. +** +** sighandler.c - nph signal handling code +** +** Mark D. Roth +*/ + +#include + +#include +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_READLINE_READLINE_H +# include +#endif + + +/* global variables */ +sigjmp_buf complete_env, command_env; +int sighandler_state = HANDLER_DEFAULT; + + +/* signal handler for SIGCONT */ +static void +resume(int sig) +{ +#ifdef HAVE_LIBREADLINE + if (sighandler_state != HANDLER_COMMAND) + rl_forced_update_display(); +#endif /* HAVE_LIBREADLINE */ +} + + +/* signal handler for SIGINT */ +static void +interrupt(int sig) +{ + if (sighandler_state == HANDLER_DEFAULT) + { + fprintf(stderr, "\nnph: terminating on signal %d\n", sig); + exit(1); + } + + if (sighandler_state == HANDLER_INPUT) + /* + ** interrupting a normal input line + ** restart input on next line + */ + putchar('\n'); + + else if (sighandler_state == HANDLER_COMMAND) + /* + ** interrupting a command + ** print a message before the next input line + */ + nph_printf(0, "\nnph: command interrupted\n"); + +#ifdef HAVE_LIBREADLINE + /* reset tty state in all cases */ + rl_reset_after_signal(); + + if (sighandler_state == HANDLER_COMPLETION) + { + /* interrupt completion - jump back to rl_completion_hook() */ + siglongjmp(complete_env, 1); + + /* can't happen */ + fprintf(stderr, + "interrupt(): internal error: " + "returned from siglongjmp()\n"); + exit(1); + } + + /* + ** clear input buffer and issue a new prompt + ** (this is needed for both HANDLER_INPUT and HANDLER_COMMAND) + */ + rl_delete_text(0, rl_end); + rl_point = rl_end = rl_done = 0; + + if (sighandler_state == HANDLER_INPUT) + rl_forced_update_display(); +#endif /* HAVE_LIBREADLINE */ + + if (sighandler_state == HANDLER_COMMAND) + { + /* jump back to command loop */ + siglongjmp(command_env, 1); + + /* can't happen */ + fprintf(stderr, + "interrupt(): internal error: " + "returned from siglongjmp()\n"); + exit(1); + } +} + + +void +set_signals(void) +{ + sighandler_state = HANDLER_DEFAULT; + + if (isatty(fileno(stdin))) + { +#ifdef HAVE_SIGACTION + struct sigaction sa; + + memset(&sa, 0, sizeof(struct sigaction)); + sa.sa_handler = interrupt; + sa.sa_flags = SA_RESTART; + if (sigaction(SIGINT, &sa, NULL) == -1) + { + perror("sigaction()"); + exit(1); + } + sa.sa_handler = resume; + if (sigaction(SIGCONT, &sa, NULL) == -1) + { + perror("sigaction()"); + exit(1); + } +#else /* ! HAVE_SIGACTION */ + if (signal(SIGINT, interrupt) == SIG_ERR) + { + perror("signal()"); + exit(1); + } + if (signal(SIGCONT, resume) == SIG_ERR) + { + perror("signal()"); + exit(1); + } +#endif /* HAVE_SIGACTION */ + } +} + + diff --git a/nphrc b/nphrc new file mode 100644 index 0000000..666cf69 --- /dev/null +++ b/nphrc @@ -0,0 +1,9 @@ +# +# nphrc - system-wide startup file for nph +# + +# Examples: +# option pager=/usr/local/bin/less +# addserver ns.uiuc.edu "University of Illinois at Urbana-Champaign" + +status diff --git a/postinstall.in b/postinstall.in new file mode 100755 index 0000000..fe1f2e5 --- /dev/null +++ b/postinstall.in @@ -0,0 +1,42 @@ +#!/bin/sh + +grep csnet-ns /etc/services > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "adding csnet-ns to /etc/services..." + cp /etc/services /etc/services.pre.${ENCAP_PKGNAME} + echo "csnet-ns 105/tcp ns # PH" >> /etc/services +fi + +if [ ! -d "@sysconfdir@" ]; then + echo "creating directory @sysconfdir@..."; + mkdir -p "@sysconfdir@"; +fi + +if [ ! -f "@sysconfdir@/ph_server" ]; then + PH_SERVER=`hostname | awk -F. '(NF > 1) { printf "ns.%s.%s\n", $(NF - 1), $NF; }'`; + + if [ -z "${PH_SERVER}" ]; then + if [ -x /usr/sbin/nslookup ]; then + NSLOOKUP=/usr/sbin/nslookup; + elif [ -x /usr/bin/nslookup ]; then + NSLOOKUP=/usr/bin/nslookup; + fi + + if [ -n "${NSLOOKUP}" ]; then + PH_SERVER=`hostname | xargs ${NSLOOKUP} | awk '/^Name:/ { print $2; exit; }' | awk -F. '{ printf("ns.%s.%s\n", $(NF - 1), $NF); }'`; + fi + fi + + if [ -n "${PH_SERVER}" ]; then + echo "creating default @sysconfdir@/ph_server file..."; + echo "${PH_SERVER}" > @sysconfdir@/ph_server; + else + echo "WARNING: cannot determine PH server name - you must create @sysconfdir@/ph_server manually"; + fi +fi + +if [ ! -f "@sysconfdir@/nphrc" ]; then + echo "installing default @sysconfdir@/nphrc file..."; + cp ${ENCAP_SOURCE}/${ENCAP_PKGNAME}/nphrc @sysconfdir@/nphrc; +fi +