]> git.sur5r.net Git - openldap/blob - contrib/whois++/whois++.c
Add comment that socklen_t should be used
[openldap] / contrib / whois++ / whois++.c
1 #if !defined(lint)
2 static char copyright[] = "Copyright 1992 The University of Adelaide";
3 #endif
4
5 /*
6  *                      W H O I S + +
7  *
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
13  * Date:        October 1992
14  * Version:     1.7
15  * Description:
16  *      This is an experimental implementation of the proposed IETF
17  *      WNILS WG update to the whois/nicname protocol (whois++).
18  *
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.
30  */
31
32 #include "whois++.h"
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <netdb.h>
36
37 static initialise();
38
39 main( argc, argv )
40 int     argc;
41 char    **argv;
42 {
43         FILE                    *tailorFile, *bannerFile;
44         char                    tailor[MAXPATHLEN];
45         char                    query[BUFSIZ], buffer[BUFSIZ];
46         char                    *s, *hostname, *remote;
47         char                    **info;
48         int                     i, printInfo = FALSE;
49         extern char             *optarg;
50         LDAP                    *ld;
51         LDAPMessage             *result, *entry;
52         int                     timelimit = DEFAULT_TIMELIMIT;
53         struct hostent          *hp;
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 ] \
60 [-u user] [-v]";
61         static char             *attributes[] =
62                                         { "businessCategory", "info", NULL };
63
64         if ( (program = strrchr( argv[0], '/' )) == NULL )
65                 program = strdup( argv[0] );
66         else
67                 program = strdup( program + 1 );
68
69 #if defined(LOG_DAEMON)
70         openlog(program, LOG_PID, FACILITY );
71 #else
72         openlog(program, LOG_PID );
73 #endif
74
75         initialise();
76
77         sprintf( tailor, "%s/%stailor", ETCDIR, program );
78         if ( (tailorFile = fopen( tailor, "r" )) != NULL ) {
79                 readConfiguration( tailorFile );
80                 fclose( tailorFile );
81         }
82
83         while ( (i = getopt( argc, argv, "b:d:h:ils:t:T:u:v?" )) != EOF ) {
84                 switch ( i ) {
85                 case 'b':       /* search base */
86                         base = strdup( optarg );
87                         break;
88
89                 case 'd':       /* debug */
90                         debug = atoi( optarg );
91                         break;
92
93                 case 'h':       /* ldap host */
94                         ldaphost = strdup( optarg );
95                         break;
96
97                 case 'i':       /* print info attribute */
98                         printInfo = TRUE;
99                         break;
100
101                 case 'l':       /* enable logging via syslog */
102                         log = TRUE;
103                         break;
104
105                 case 's':       /* size limit */
106                         if ( ( maxHits = atoi( optarg ) ) < 1 ) {
107                                 fprintf( stderr, "%s: Invalid maxhits value\n",
108                                         program );
109                                 syslog( LOG_ERR, "Invalid maxhits value" );
110                                 exit( 1 );
111                         }
112                         maximumSize = maxHits;
113                         break;
114
115                 case 't':       /* time limit */
116                         timelimit = atoi( optarg );
117                         break;
118
119                 case 'T':       /* tailor file */
120                         if ( (tailorFile = fopen( optarg, "r" )) != NULL ) {
121                                 readConfiguration( tailorFile );
122                                 fclose( tailorFile );
123                         } else {
124                                 perror( program );
125                                 exit( 1 );
126                         }
127                         break;
128
129                 case 'u':       /* user to bind as */
130                         user = strdup( optarg );
131                         break;
132
133                 case 'v':       /* version */
134                         fprintf( stderr, "%s: %s %d.%s\n",
135                                 program, RELEASE, REVISION, version() );
136                         exit( 0 );
137
138                 default:        /* usage message, don't "fail" if ? */
139                         fprintf( stderr, "usage: %s %s\n", program, options );
140                         exit( i != '?' );
141                 }
142         }
143
144         language = defaultLanguage;
145
146         /*
147          * We can cope without knowing most things but we do need to know
148          * where to start looking!
149          */
150         if ( base == NULL ) {
151                 syslog( LOG_ERR, "No base specified" );
152                 fprintf( stderr, "%s: No base specified.\n", program );
153                 exit( 1 );
154         }
155
156         if ( ! debug ) {
157                 if ( getpeername(0, &sa, &length) < 0) {
158                         perror( "getpeername" );
159                         exit( 1 );
160                 }
161                 if ( log ) {
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 ) {
166                                         free( hostname );
167                                         hostname = strdup( inet_ntoa(sin->sin_addr) );
168                                 }
169                         } else
170                                 hostname = strdup( inet_ntoa(sin->sin_addr) );
171 #if defined(RFC931)
172                         remote = rfc931_name( sin );
173 #else
174                         remote = NULL;
175 #endif
176                         syslog( LOG_INFO, "Connection from %s%s%s [%s]",
177                                 (remote)?remote:"", (remote)?"@":"",
178                                 hostname, inet_ntoa(sin->sin_addr) );
179                 }
180         }
181
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)",
186                         ldaphost );
187                 exit( 1 );
188         }
189         ld->ld_timelimit = timelimit;
190         ld->ld_sizelimit = maxHits;
191         ld->ld_deref = LDAP_DEREF_FINDING;
192
193         ldap_simple_bind_s( ld, user, password );
194         switch ( ld->ld_errno ) {
195         case LDAP_SUCCESS:
196                 break;
197
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" );
203                 exit( 1 );
204
205         default:
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 ) );
211                 exit( 1 );
212
213         }
214
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 ) );
221                 exit( 1 );
222         }
223         entry = ldap_first_entry( ld, result );
224         organisation = ldap_dn2ufn( ldap_get_dn( ld, entry ) );
225         category = ldap_get_values( ld, entry, "businessCategory" );
226
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." );
231
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,
236                                 "%s", info[i] );
237                 }
238                 ldap_value_free( info );
239         }
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' ) )
245                                 buffer[i] = '\0';
246                         printFormatted( lineLength, TRUE, stdout, "%s", buffer );
247                 }
248                 fclose( bannerFile );
249         }
250         printFormatted( lineLength, FALSE, stdout, "" );
251
252         do {
253                 *query = '\0';
254                 holdConnection = FALSE;
255                 switch ( parseCommand( query ) ) {
256                 case READ:
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 ) {
261                         case LDAP_SUCCESS:
262                                 break;
263                 
264                         case LDAP_NO_SUCH_OBJECT:
265 /**/                            /* PROBABLY WANT SPECIAL PROCESSING HERE */
266
267                         default:
268                                 printFormatted( lineLength, TRUE, stdout,
269                                         "Read failed, %s",
270                                         ldap_err2string( ld->ld_errno ) );
271                                 return 1;
272
273                         }
274                         displayResult( ld, result, outputFormat );
275                         break;
276
277                 case SEARCH:
278                         if ( debug > 2 )
279                                 fprintf( stderr, "LDAP Query %s\n", query );
280                         if ( log )
281                                 syslog( LOG_INFO, "LDAP Query %s", query );
282
283                         ld->ld_sizelimit = maxHits;
284                         ldap_search_s( ld, base, LDAP_SCOPE_SUBTREE, query,
285                                 NULL, 0, &result );
286                         switch ( ld->ld_errno ) {
287                         case LDAP_SUCCESS:
288                                 break;
289
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 ) );
294                                 break;
295
296                         case LDAP_TIMELIMIT_EXCEEDED:
297                                 printFormatted( lineLength, TRUE, stdout,
298                                         "Partial results only - a time limit \
299 was exceeded." );
300                                 break;
301
302                         default:
303                                 printFormatted( lineLength, TRUE, stdout,
304                                         "Search failed, %s",
305                                         ldap_err2string( ld->ld_errno ) );
306                                 exit( 1 );
307
308                         }
309                         displayResult( ld, result, outputFormat );
310                         break;
311
312                 case HELP:
313                         needHelp( lowerCase( query ) );
314                         break;
315
316                 case DESCRIBE:
317                         displayDescribe( ld, base );
318                         break;
319
320                 case VERSION:
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 );
330                         break;
331
332                 case LIST:
333                         listTemplates( lowerCase( query ) );
334                         break;
335
336                 case SHOW:
337                         showTemplate( lowerCase( query ) );
338                         break;
339
340                 case CONSTRAINTS:
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, 
352                                 "    hold" );
353                         printFormatted( lineLength, TRUE, stdout, 
354                                 "    language=<string>" );
355                         printFormatted( lineLength, TRUE, stdout, 
356                                 "    linelength=<number>" );
357                         printFormatted( lineLength, TRUE, stdout, 
358                                 "    maxhits=<number>" );
359                         break;
360
361                 case COMMAND:
362                         printFormatted( lineLength, TRUE, stdout,
363                                 "Commands supported by this implementation are" );
364                         printFormatted( lineLength, TRUE, stdout,
365                                 "    command" );
366                         printFormatted( lineLength, TRUE, stdout,
367                                 "    constraints" );
368                         printFormatted( lineLength, TRUE, stdout,
369                                 "    describe" );
370                         printFormatted( lineLength, TRUE, stdout,
371                                 "    help" );
372                         printFormatted( lineLength, TRUE, stdout,
373                                 "    list" );
374                         printFormatted( lineLength, TRUE, stdout,
375                                 "    show" );
376                         printFormatted( lineLength, TRUE, stdout,
377                                 "    version" );
378                         break;
379
380                 case ERROR:
381                         break;
382
383                 }
384         } while ( holdConnection );
385         closelog();
386         ldap_unbind( ld );
387 }
388
389 static initialise()
390
391 {
392         char    buffer[BUFSIZ];
393
394         debug = FALSE;
395         maxHits = DEFAULT_SIZELIMIT;
396         maximumSize = maxHits;
397         outputFormat = NULL;
398         lineLength = DEFAULT_LINE_LENGTH;
399         ldaphost = DEFAULT_LDAPHOST;
400         defaultLanguage = DEFAULT_LANGUAGE;
401         locale = "";
402         base = NULL;
403         contact = NULL;
404         if ( gethostname( buffer, BUFSIZ ) == 0 )
405                 hostname = strdup( buffer );
406         else
407                 hostname = NULL;
408         user = NULL;
409         password = NULL;
410         helpDir = HELP_DIRECTORY;
411         configDir = CONFIG_DIRECTORY;
412         organisation = NULL;
413         banner = NULL;
414         log = FALSE;
415         numberOfTemplates = 0;
416         tableSize = TABLE_INCREMENT;
417         templateTranslationTable = NULL;
418 }