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 int length = sizeof(sa);
57 static char options[] = "[-b searchbase] [-d debug ] \
58 [-h ldaphost ] [-i] [-l] [-s sizelimit] [-t timelimit] [-T tailorfile ] \
60 static char *attributes[] =
61 { "businessCategory", "info", NULL };
63 if ( (program = strrchr( argv[0], '/' )) == NULL )
64 program = strdup( argv[0] );
66 program = strdup( program + 1 );
68 #if defined(LOG_DAEMON)
69 openlog(program, LOG_PID, FACILITY );
71 openlog(program, LOG_PID );
76 sprintf( tailor, "%s/%stailor", ETCDIR, program );
77 if ( (tailorFile = fopen( tailor, "r" )) != NULL ) {
78 readConfiguration( tailorFile );
82 while ( (i = getopt( argc, argv, "b:d:h:ils:t:T:u:v?" )) != EOF ) {
84 case 'b': /* search base */
85 base = strdup( optarg );
89 debug = atoi( optarg );
92 case 'h': /* ldap host */
93 ldaphost = strdup( optarg );
96 case 'i': /* print info attribute */
100 case 'l': /* enable logging via syslog */
104 case 's': /* size limit */
105 if ( ( maxHits = atoi( optarg ) ) < 1 ) {
106 fprintf( stderr, "%s: Invalid maxhits value\n",
108 syslog( LOG_ERR, "Invalid maxhits value" );
111 maximumSize = maxHits;
114 case 't': /* time limit */
115 timelimit = atoi( optarg );
118 case 'T': /* tailor file */
119 if ( (tailorFile = fopen( optarg, "r" )) != NULL ) {
120 readConfiguration( tailorFile );
121 fclose( tailorFile );
128 case 'u': /* user to bind as */
129 user = strdup( optarg );
132 case 'v': /* version */
133 fprintf( stderr, "%s: %s %d.%s\n",
134 program, RELEASE, REVISION, version() );
137 default: /* usage message, don't "fail" if ? */
138 fprintf( stderr, "usage: %s %s\n", program, options );
143 language = defaultLanguage;
146 * We can cope without knowing most things but we do need to know
147 * where to start looking!
149 if ( base == NULL ) {
150 syslog( LOG_ERR, "No base specified" );
151 fprintf( stderr, "%s: No base specified.\n", program );
156 if ( getpeername(0, &sa, &length) < 0) {
157 perror( "getpeername" );
161 if ( ( hp = gethostbyaddr((char *) &sin->sin_addr,
162 sizeof(sin->sin_addr), AF_INET) ) != 0 ) {
163 hostname = strdup( hp->h_name );
164 if ( ( hp = gethostbyname( hostname ) ) == 0 ) {
166 hostname = strdup( inet_ntoa(sin->sin_addr) );
169 hostname = strdup( inet_ntoa(sin->sin_addr) );
171 remote = rfc931_name( sin );
175 syslog( LOG_INFO, "Connection from %s%s%s [%s]",
176 (remote)?remote:"", (remote)?"@":"",
177 hostname, inet_ntoa(sin->sin_addr) );
181 if ( (ld = ldap_open( ldaphost, LDAP_PORT )) == NULL ) {
182 printFormatted( lineLength, TRUE, stdout,
183 "Connection to LDAP port on %s has failed", ldaphost );
184 syslog( LOG_ERR, "Connection to LDAP port on %s has failed",
188 ld->ld_timelimit = timelimit;
189 ld->ld_sizelimit = maxHits;
190 ld->ld_deref = LDAP_DEREF_FINDING;
192 ldap_simple_bind_s( ld, user, password );
193 switch ( ld->ld_errno ) {
197 case LDAP_UNAVAILABLE:
198 printFormatted( lineLength, TRUE, stdout,
199 "Sorry, the X.500 service is temporarily unavailable. \
200 Please try again later." );
201 syslog( LOG_NOTICE, "X.500 service temporarily unavailable" );
205 printFormatted( lineLength, TRUE, stdout,
206 "Bind to Directory failed, %s",
207 ldap_err2string( ld->ld_errno ) );
208 syslog( LOG_ERR, "Bind to Directory failed, %s",
209 ldap_err2string( ld->ld_errno ) );
214 ldap_search_s( ld, base, LDAP_SCOPE_BASE, "objectclass=*",
215 attributes, 0, &result );
216 if ( ld->ld_errno != LDAP_SUCCESS ) {
217 printFormatted( lineLength, TRUE, stdout,
218 "Read of entry \"%s\" failed, %s",
219 base, ldap_err2string( ld->ld_errno ) );
222 entry = ldap_first_entry( ld, result );
223 organisation = strdup( ldap_dn2ufn( ldap_get_dn( ld, entry ) ) );
224 category = ldap_get_values( ld, entry, "businessCategory" );
226 printFormatted( lineLength, FALSE, stdout,
227 "Whois++ Service at %s.", ldap_dn2ufn( base ) );
228 printFormatted( lineLength, FALSE, stdout,
229 "For more information about this service send the \"help\" command." );
231 if ( printInfo && ( info = ldap_get_values( ld, entry, "info" ) ) != NULL ) {
232 for ( i = 0; info[i] != NULL; i++ ) {
233 printFormatted( lineLength, FALSE, stdout, "" );
234 printFormatted( lineLength, TRUE, stdout,
237 ldap_value_free( info );
239 if ( banner != NULL && ( bannerFile = fopen( banner, "r" ) ) != NULL ) {
240 printFormatted( lineLength, FALSE, stdout, "" );
241 while ( fgets( buffer, BUFSIZ, bannerFile ) != NULL ) {
242 i = strlen( buffer );
243 while ( i-- > 0 && ( buffer[i] == '\n' || buffer[i] == '\r' ) )
245 printFormatted( lineLength, TRUE, stdout, "%s", buffer );
247 fclose( bannerFile );
249 printFormatted( lineLength, FALSE, stdout, "" );
253 holdConnection = FALSE;
254 switch ( parseCommand( query ) ) {
256 /* No need to search, just read the entry given! */
257 ldap_search_s( ld, query, LDAP_SCOPE_BASE,
258 "objectclass=*", NULL, 0, &result );
259 switch( ld->ld_errno ) {
263 case LDAP_NO_SUCH_OBJECT:
264 /**/ /* PROBABLY WANT SPECIAL PROCESSING HERE */
267 printFormatted( lineLength, TRUE, stdout,
269 ldap_err2string( ld->ld_errno ) );
273 displayResult( ld, result, outputFormat );
278 fprintf( stderr, "LDAP Query %s\n", query );
280 syslog( LOG_INFO, "LDAP Query %s", query );
282 ld->ld_sizelimit = maxHits;
283 ldap_search_s( ld, base, LDAP_SCOPE_SUBTREE, query,
285 switch ( ld->ld_errno ) {
289 case LDAP_SIZELIMIT_EXCEEDED:
290 printFormatted( lineLength, TRUE, stdout,
291 "Partial results only - a size limit \
292 was exceeded, only %d entries returned", ldap_count_entries( ld, result ) );
295 case LDAP_TIMELIMIT_EXCEEDED:
296 printFormatted( lineLength, TRUE, stdout,
297 "Partial results only - a time limit \
302 printFormatted( lineLength, TRUE, stdout,
304 ldap_err2string( ld->ld_errno ) );
308 displayResult( ld, result, outputFormat );
312 needHelp( lowerCase( query ) );
316 displayDescribe( ld, base );
320 printFormatted( lineLength, TRUE, stdout,
321 "Whois++ Protocol version %s", PROTOCOL );
322 printFormatted( lineLength, TRUE, stdout,
323 "Program version %s %d.%s",
324 RELEASE, REVISION, version() );
325 printFormatted( lineLength, TRUE, stdout,
326 "Default language is %s", defaultLanguage );
327 printFormatted( lineLength, TRUE, stdout,
328 "Built by %s", BUILD );
332 listTemplates( lowerCase( query ) );
336 showTemplate( lowerCase( query ) );
340 printFormatted( lineLength, TRUE, stdout,
341 "This implementation supports the following constraints." );
342 printFormatted( lineLength, TRUE, stdout,
343 "Local constraints are" );
344 printFormatted( lineLength, TRUE, stdout,
345 " match=(exact|fuzzy)" );
346 printFormatted( lineLength, TRUE, stdout,
347 "Global constraints are" );
348 printFormatted( lineLength, TRUE, stdout,
349 " format=(full|abridged|handle|summary)" );
350 printFormatted( lineLength, TRUE, stdout,
352 printFormatted( lineLength, TRUE, stdout,
353 " language=<string>" );
354 printFormatted( lineLength, TRUE, stdout,
355 " linelength=<number>" );
356 printFormatted( lineLength, TRUE, stdout,
357 " maxhits=<number>" );
361 printFormatted( lineLength, TRUE, stdout,
362 "Commands supported by this implementation are" );
363 printFormatted( lineLength, TRUE, stdout,
365 printFormatted( lineLength, TRUE, stdout,
367 printFormatted( lineLength, TRUE, stdout,
369 printFormatted( lineLength, TRUE, stdout,
371 printFormatted( lineLength, TRUE, stdout,
373 printFormatted( lineLength, TRUE, stdout,
375 printFormatted( lineLength, TRUE, stdout,
383 } while ( holdConnection );
394 maxHits = DEFAULT_SIZELIMIT;
395 maximumSize = maxHits;
397 lineLength = DEFAULT_LINE_LENGTH;
398 ldaphost = DEFAULT_LDAPHOST;
399 defaultLanguage = DEFAULT_LANGUAGE;
403 if ( gethostname( buffer, BUFSIZ ) == 0 )
404 hostname = strdup( buffer );
409 helpDir = HELP_DIRECTORY;
410 configDir = CONFIG_DIRECTORY;
414 numberOfTemplates = 0;
415 tableSize = TABLE_INCREMENT;
416 templateTranslationTable = NULL;