2 static char copyright[] = "Copyright 1992 The University of Adelaide";
8 * Author: Mark R. Prior
9 * Communications and Systems Branch
10 * Information Technology Division
11 * The University of Adelaide
12 * E-mail: mrp@itd.adelaide.edu.au
16 * This is an experimental implementation of the proposed IETF
17 * WNILS WG update to the whois/nicname protocol (whois++).
19 * Redistribution and use in source and binary forms are permitted
20 * provided that the above copyright notice and this paragraph are
21 * duplicated in all such forms and that any documentation,
22 * advertising materials, and other materials related to such
23 * distribution and use acknowledge that the software was developed
24 * by the University of Adelaide. The name of the University may not
25 * be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
28 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
29 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
33 #include <sys/socket.h>
34 #include <netinet/in.h>
43 FILE *tailorFile, *bannerFile;
44 char tailor[MAXPATHLEN];
45 char query[BUFSIZ], buffer[BUFSIZ];
46 char *s, *hostname, *remote;
48 int i, printInfo = FALSE;
51 LDAPMessage *result, *entry;
52 int timelimit = DEFAULT_TIMELIMIT;
54 static struct sockaddr sa;
55 struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
56 /* #### length should be socklen_t when we include portable.h #### */
57 int length = sizeof(sa);
58 static char options[] = "[-b searchbase] [-d debug ] \
59 [-h ldaphost ] [-i] [-l] [-s sizelimit] [-t timelimit] [-T tailorfile ] \
61 static char *attributes[] =
62 { "businessCategory", "info", NULL };
64 if ( (program = strrchr( argv[0], '/' )) == NULL )
65 program = strdup( argv[0] );
67 program = strdup( program + 1 );
69 #if defined(LOG_DAEMON)
70 openlog(program, LOG_PID, FACILITY );
72 openlog(program, LOG_PID );
77 sprintf( tailor, "%s/%stailor", ETCDIR, program );
78 if ( (tailorFile = fopen( tailor, "r" )) != NULL ) {
79 readConfiguration( tailorFile );
83 while ( (i = getopt( argc, argv, "b:d:h:ils:t:T:u:v?" )) != EOF ) {
85 case 'b': /* search base */
86 base = strdup( optarg );
90 debug = atoi( optarg );
93 case 'h': /* ldap host */
94 ldaphost = strdup( optarg );
97 case 'i': /* print info attribute */
101 case 'l': /* enable logging via syslog */
105 case 's': /* size limit */
106 if ( ( maxHits = atoi( optarg ) ) < 1 ) {
107 fprintf( stderr, "%s: Invalid maxhits value\n",
109 syslog( LOG_ERR, "Invalid maxhits value" );
112 maximumSize = maxHits;
115 case 't': /* time limit */
116 timelimit = atoi( optarg );
119 case 'T': /* tailor file */
120 if ( (tailorFile = fopen( optarg, "r" )) != NULL ) {
121 readConfiguration( tailorFile );
122 fclose( tailorFile );
129 case 'u': /* user to bind as */
130 user = strdup( optarg );
133 case 'v': /* version */
134 fprintf( stderr, "%s: %s %d.%s\n",
135 program, RELEASE, REVISION, version() );
138 default: /* usage message, don't "fail" if ? */
139 fprintf( stderr, "usage: %s %s\n", program, options );
144 language = defaultLanguage;
147 * We can cope without knowing most things but we do need to know
148 * where to start looking!
150 if ( base == NULL ) {
151 syslog( LOG_ERR, "No base specified" );
152 fprintf( stderr, "%s: No base specified.\n", program );
157 if ( getpeername(0, &sa, &length) < 0) {
158 perror( "getpeername" );
162 if ( ( hp = gethostbyaddr((char *) &sin->sin_addr,
163 sizeof(sin->sin_addr), AF_INET) ) != 0 ) {
164 hostname = strdup( hp->h_name );
165 if ( ( hp = gethostbyname( hostname ) ) == 0 ) {
167 hostname = strdup( inet_ntoa(sin->sin_addr) );
170 hostname = strdup( inet_ntoa(sin->sin_addr) );
172 remote = rfc931_name( sin );
176 syslog( LOG_INFO, "Connection from %s%s%s [%s]",
177 (remote)?remote:"", (remote)?"@":"",
178 hostname, inet_ntoa(sin->sin_addr) );
182 if ( (ld = ldap_init( ldaphost, LDAP_PORT )) == NULL ) {
183 printFormatted( lineLength, TRUE, stdout,
184 "Connection to LDAP port on %s has failed", ldaphost );
185 syslog( LOG_ERR, "Initialization of LDAP session (%s)",
189 ld->ld_timelimit = timelimit;
190 ld->ld_sizelimit = maxHits;
191 ld->ld_deref = LDAP_DEREF_FINDING;
193 ldap_simple_bind_s( ld, user, password );
194 switch ( ld->ld_errno ) {
198 case LDAP_UNAVAILABLE:
199 printFormatted( lineLength, TRUE, stdout,
200 "Sorry, the X.500 service is temporarily unavailable. \
201 Please try again later." );
202 syslog( LOG_NOTICE, "X.500 service temporarily unavailable" );
206 printFormatted( lineLength, TRUE, stdout,
207 "Bind to Directory failed, %s",
208 ldap_err2string( ld->ld_errno ) );
209 syslog( LOG_ERR, "Bind to Directory failed, %s",
210 ldap_err2string( ld->ld_errno ) );
215 ldap_search_s( ld, base, LDAP_SCOPE_BASE, "objectclass=*",
216 attributes, 0, &result );
217 if ( ld->ld_errno != LDAP_SUCCESS ) {
218 printFormatted( lineLength, TRUE, stdout,
219 "Read of entry \"%s\" failed, %s",
220 base, ldap_err2string( ld->ld_errno ) );
223 entry = ldap_first_entry( ld, result );
224 organisation = ldap_dn2ufn( ldap_get_dn( ld, entry ) );
225 category = ldap_get_values( ld, entry, "businessCategory" );
227 printFormatted( lineLength, FALSE, stdout,
228 "Whois++ Service at %s.", ldap_dn2ufn( base ) );
229 printFormatted( lineLength, FALSE, stdout,
230 "For more information about this service send the \"help\" command." );
232 if ( printInfo && ( info = ldap_get_values( ld, entry, "info" ) ) != NULL ) {
233 for ( i = 0; info[i] != NULL; i++ ) {
234 printFormatted( lineLength, FALSE, stdout, "" );
235 printFormatted( lineLength, TRUE, stdout,
238 ldap_value_free( info );
240 if ( banner != NULL && ( bannerFile = fopen( banner, "r" ) ) != NULL ) {
241 printFormatted( lineLength, FALSE, stdout, "" );
242 while ( fgets( buffer, BUFSIZ, bannerFile ) != NULL ) {
243 i = strlen( buffer );
244 while ( i-- > 0 && ( buffer[i] == '\n' || buffer[i] == '\r' ) )
246 printFormatted( lineLength, TRUE, stdout, "%s", buffer );
248 fclose( bannerFile );
250 printFormatted( lineLength, FALSE, stdout, "" );
254 holdConnection = FALSE;
255 switch ( parseCommand( query ) ) {
257 /* No need to search, just read the entry given! */
258 ldap_search_s( ld, query, LDAP_SCOPE_BASE,
259 "objectclass=*", NULL, 0, &result );
260 switch( ld->ld_errno ) {
264 case LDAP_NO_SUCH_OBJECT:
265 /**/ /* PROBABLY WANT SPECIAL PROCESSING HERE */
268 printFormatted( lineLength, TRUE, stdout,
270 ldap_err2string( ld->ld_errno ) );
274 displayResult( ld, result, outputFormat );
279 fprintf( stderr, "LDAP Query %s\n", query );
281 syslog( LOG_INFO, "LDAP Query %s", query );
283 ld->ld_sizelimit = maxHits;
284 ldap_search_s( ld, base, LDAP_SCOPE_SUBTREE, query,
286 switch ( ld->ld_errno ) {
290 case LDAP_SIZELIMIT_EXCEEDED:
291 printFormatted( lineLength, TRUE, stdout,
292 "Partial results only - a size limit \
293 was exceeded, only %d entries returned", ldap_count_entries( ld, result ) );
296 case LDAP_TIMELIMIT_EXCEEDED:
297 printFormatted( lineLength, TRUE, stdout,
298 "Partial results only - a time limit \
303 printFormatted( lineLength, TRUE, stdout,
305 ldap_err2string( ld->ld_errno ) );
309 displayResult( ld, result, outputFormat );
313 needHelp( lowerCase( query ) );
317 displayDescribe( ld, base );
321 printFormatted( lineLength, TRUE, stdout,
322 "Whois++ Protocol version %s", PROTOCOL );
323 printFormatted( lineLength, TRUE, stdout,
324 "Program version %s %d.%s",
325 RELEASE, REVISION, version() );
326 printFormatted( lineLength, TRUE, stdout,
327 "Default language is %s", defaultLanguage );
328 printFormatted( lineLength, TRUE, stdout,
329 "Built by %s", BUILD );
333 listTemplates( lowerCase( query ) );
337 showTemplate( lowerCase( query ) );
341 printFormatted( lineLength, TRUE, stdout,
342 "This implementation supports the following constraints." );
343 printFormatted( lineLength, TRUE, stdout,
344 "Local constraints are" );
345 printFormatted( lineLength, TRUE, stdout,
346 " match=(exact|fuzzy)" );
347 printFormatted( lineLength, TRUE, stdout,
348 "Global constraints are" );
349 printFormatted( lineLength, TRUE, stdout,
350 " format=(full|abridged|handle|summary)" );
351 printFormatted( lineLength, TRUE, stdout,
353 printFormatted( lineLength, TRUE, stdout,
354 " language=<string>" );
355 printFormatted( lineLength, TRUE, stdout,
356 " linelength=<number>" );
357 printFormatted( lineLength, TRUE, stdout,
358 " maxhits=<number>" );
362 printFormatted( lineLength, TRUE, stdout,
363 "Commands supported by this implementation are" );
364 printFormatted( lineLength, TRUE, stdout,
366 printFormatted( lineLength, TRUE, stdout,
368 printFormatted( lineLength, TRUE, stdout,
370 printFormatted( lineLength, TRUE, stdout,
372 printFormatted( lineLength, TRUE, stdout,
374 printFormatted( lineLength, TRUE, stdout,
376 printFormatted( lineLength, TRUE, stdout,
384 } while ( holdConnection );
395 maxHits = DEFAULT_SIZELIMIT;
396 maximumSize = maxHits;
398 lineLength = DEFAULT_LINE_LENGTH;
399 ldaphost = DEFAULT_LDAPHOST;
400 defaultLanguage = DEFAULT_LANGUAGE;
404 if ( gethostname( buffer, BUFSIZ ) == 0 )
405 hostname = strdup( buffer );
410 helpDir = HELP_DIRECTORY;
411 configDir = CONFIG_DIRECTORY;
415 numberOfTemplates = 0;
416 tableSize = TABLE_INCREMENT;
417 templateTranslationTable = NULL;