]> git.sur5r.net Git - openldap/blob - clients/finger/main.c
pass struct in_addr.s_addr*, not long*, to gethostbyaddr
[openldap] / clients / finger / main.c
1 /*
2  * Copyright (c) 1990,1994 Regents of the University of Michigan.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of Michigan at Ann Arbor. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16 #include <stdlib.h>
17
18 #include <ac/ctype.h>
19 #include <ac/signal.h>
20 #include <ac/socket.h>
21 #include <ac/string.h>
22 #include <ac/syslog.h>
23 #include <ac/time.h>
24 #include <ac/unistd.h>
25 #include <ac/wait.h>
26
27 #ifdef HAVE_SYS_RESOURCE_H
28 #include <sys/resource.h>
29 #endif
30
31 #include "lber.h"
32 #include "ldap.h"
33
34 #include "disptmpl.h"
35
36 #include "ldapconfig.h"
37
38
39 int     dosyslog = 1;
40 char    *ldaphost = NULL;
41 int     ldapport = 0;
42 char    *base = NULL;
43 int     deref;
44 char    *filterfile = FILTERFILE;
45 char    *templatefile = TEMPLATEFILE;
46 int     rdncount = FINGER_RDNCOUNT;
47
48 static void do_query(void);
49 static void do_search(LDAP *ld, char *buf);
50 static void do_read(LDAP *ld, LDAPMessage *e);
51
52 static void
53 usage( char *name )
54 {
55         fprintf( stderr, "usage: %s [-l] [-x ldaphost] [-p ldapport] [-f filterfile] [-t templatefile] [-c rdncount]\r\n", name );
56         exit( 1 );
57 }
58
59 int
60 main( int argc, char **argv )
61 {
62         int                     i;
63         char                    *myname;
64         struct hostent          *hp;
65         struct sockaddr_in      peername;
66         int                     peernamelen;
67         int                     interactive = 0;
68
69         deref = FINGER_DEREF;
70         while ( (i = getopt( argc, argv, "f:ilp:t:x:p:c:" )) != EOF ) {
71                 switch( i ) {
72                 case 'f':       /* ldap filter file */
73                         filterfile = strdup( optarg );
74                         break;
75
76                 case 'i':       /* interactive */
77                         interactive = 1;
78                         break;
79
80                 case 'l':       /* don't do syslogging */
81                         dosyslog = 0;
82                         break;
83
84                 case 't':       /* ldap template file */
85                         templatefile = strdup( optarg );
86                         break;
87
88                 case 'x':       /* specify ldap host */
89                         ldaphost = strdup( optarg );
90                         break;
91
92                 case 'p':       /* specify ldap port */
93                         ldapport = atoi( optarg );
94                         break;
95
96                 case 'c':       /* specify number of DN components to show */
97                         rdncount = atoi( optarg );
98                         break;
99
100                 default:
101                         usage( argv[0] );
102                 }
103         }
104
105         if ( !interactive ) {
106                 peernamelen = sizeof(peername);
107                 if ( getpeername( 0, (struct sockaddr *)&peername,
108                     &peernamelen ) != 0 ) {
109                         perror( "getpeername" );
110                         exit( 1 );
111                 }
112         }
113
114 #ifdef FINGER_BANNER
115         if ( FINGER_BANNER != NULL && strcmp( FINGER_BANNER, "" ) != 0 ) {
116                 printf( FINGER_BANNER );
117                 fflush( stdout );
118         }
119 #endif
120
121         if ( (myname = strrchr( argv[0], '/' )) == NULL )
122                 myname = strdup( argv[0] );
123         else
124                 myname = strdup( myname + 1 );
125
126         if ( dosyslog ) {
127 #ifdef LOG_LOCAL4
128                 openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
129 #else
130                 openlog( myname, OPENLOG_OPTIONS );
131 #endif
132         }
133
134         if ( dosyslog && !interactive ) {
135                 hp = gethostbyaddr( (char *) &peername.sin_addr.s_addr,
136                                     sizeof(peername.sin_addr.s_addr), AF_INET );
137                 syslog( LOG_INFO, "connection from %s (%s)",
138                         (hp == NULL) ? "unknown" : hp->h_name,
139                         inet_ntoa( peername.sin_addr ) );
140         }
141
142         do_query();
143
144         return( 0 );
145 }
146
147 static void
148 do_query( void )
149 {
150         char            buf[256];
151         int             len, rc, tblsize;
152         struct timeval  timeout;
153         fd_set          readfds;
154         LDAP            *ld;
155
156         if ( (ld = ldap_open( ldaphost, ldapport )) == NULL ) {
157                 fprintf( stderr, FINGER_UNAVAILABLE );
158                 perror( "ldap_open" );
159                 exit( 1 );
160         }
161
162         {
163                 int limit = FINGER_SIZELIMIT;
164                 ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &limit);
165         }
166         ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
167
168         if ( ldap_simple_bind_s( ld, NULL, NULL )
169                 != LDAP_SUCCESS )
170         {
171                 fprintf( stderr, FINGER_UNAVAILABLE );
172                 ldap_perror( ld, "ldap_simple_bind_s" );
173                 exit( 1 );
174         }
175
176 #ifdef HAVE_SYSCONF
177         tblsize = sysconf( _SC_OPEN_MAX );
178 #elif HAVE_GETDTABLESIZE
179         tblsize = getdtablesize();
180 #else
181         tblsize = FD_SETSIZE;
182 #endif
183
184 #ifdef FD_SETSIZE
185         if (tblsize > FD_SETSIZE) {
186                 tblsize = FD_SETSIZE;
187         }
188 #endif  /* FD_SETSIZE*/
189
190         timeout.tv_sec = FINGER_TIMEOUT;
191         timeout.tv_usec = 0;
192         FD_ZERO( &readfds );
193         FD_SET( fileno( stdin ), &readfds );
194
195         if ( (rc = select( tblsize, &readfds, 0, 0, &timeout )) <= 0 ) {
196                 if ( rc < 0 )
197                         perror( "select" );
198                 else
199                         fprintf( stderr, "connection timed out on input\r\n" );
200                 exit( 1 );
201         }
202
203         if ( fgets( buf, sizeof(buf), stdin ) == NULL )
204                 exit( 1 );
205
206         len = strlen( buf );
207
208         /* strip off \r \n */
209         if ( buf[len - 1] == '\n' ) {
210                 buf[len - 1] = '\0';
211                 len--;
212         }
213         if ( buf[len - 1] == '\r' ) {
214                 buf[len - 1] = '\0';
215                 len--;
216         }
217
218         if ( len == 0 ) {
219                 printf( "No campus-wide login information available.  Info for this machine only:\r\n" );
220                 fflush( stdout );
221                 execl( FINGER_CMD, FINGER_CMD, NULL );
222         } else {
223                 char    *p;
224
225                 /* skip and ignore stinking /w */
226                 if ( strncmp( buf, "/W ", 2 ) == 0 ) {
227                         p = buf + 2;
228                 } else {
229                         p = buf;
230                 }
231
232                 for ( ; *p && isspace( *p ); p++ )
233                         ;       /* NULL */
234
235                 do_search( ld, p );
236         }
237 }
238
239 static void
240 spaces2dots( char *s )
241 {
242         for ( ; *s; s++ ) {
243                 if ( *s == ' ' ) {
244                         *s = '.';
245                 }
246         }
247 }
248
249 static void
250 do_search( LDAP *ld, char *buf )
251 {
252         char            *dn, *rdn;
253         char            **title;
254         int             rc, matches, i, ufn;
255         struct timeval  tv;
256         LDAPFiltDesc    *fd;
257         LDAPFiltInfo    *fi;
258         LDAPMessage     *result, *e;
259         static char     *attrs[] = { "cn", "title", "objectClass", "joinable",
260 #ifdef FINGER_SORT_ATTR
261                                         FINGER_SORT_ATTR,
262 #endif
263                                         0 };
264
265         ufn = 0;
266 #ifdef FINGER_UFN
267         if ( strchr( buf, ',' ) != NULL ) {
268                 ldap_ufn_setprefix( ld, base );
269                 tv.tv_sec = FINGER_TIMEOUT;
270                 tv.tv_usec = 0;
271                 ldap_ufn_timeout( (void *) &tv );
272
273                 if ( (rc = ldap_ufn_search_s( ld, buf, attrs, 0, &result ))
274                     != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
275                         fprintf( stderr, FINGER_UNAVAILABLE );
276                         ldap_perror( ld, "ldap_search_st" );
277                         exit( 1 );
278                 }
279
280                 matches = ldap_count_entries( ld, result );
281                 ufn = 1;
282         } else {
283 #endif
284                 if ( (fd = ldap_init_getfilter( filterfile ))
285                     == NULL ) {
286                         fprintf( stderr, "Cannot open filter file (%s)\n",
287                             filterfile );
288                         exit( 1 );
289                 }
290
291                 for ( fi = ldap_getfirstfilter( fd, "finger", buf );
292                     fi != NULL;
293                     fi = ldap_getnextfilter( fd ) )
294                 {
295                         tv.tv_sec = FINGER_TIMEOUT;
296                         tv.tv_usec = 0;
297                         if ( (rc = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE,
298                             fi->lfi_filter, attrs, 0, &tv, &result ))
299                             != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
300                             && rc != LDAP_TIMELIMIT_EXCEEDED )
301                         {
302                                 fprintf( stderr, FINGER_UNAVAILABLE );
303                                 ldap_perror( ld, "ldap_search_st" );
304                                 exit( 1 );
305                         }
306
307                         if ( (matches = ldap_count_entries( ld, result )) != 0 )
308                                 break;
309
310                         ldap_msgfree( result );
311                         result = NULL;
312                 }
313 #ifdef FINGER_UFN
314         }
315 #endif
316
317         if ( rc == LDAP_SIZELIMIT_EXCEEDED ) {
318                 printf( "(Partial results - a size limit was exceeded)\r\n" );
319         } else if ( rc == LDAP_TIMELIMIT_EXCEEDED ) {
320                 printf( "(Partial results - a time limit was exceeded)\r\n" );
321         }
322
323         if ( matches == 0 ) {
324                 printf( FINGER_NOMATCH );
325                 fflush( stdout );
326         } else if ( matches < 0 ) {
327                 fprintf( stderr, "error return from ldap_count_entries\r\n" );
328                 exit( 1 );
329         } else if ( matches <= FINGER_LISTLIMIT ) {
330                 printf( "%d %s match%s found for \"%s\":\r\n", matches,
331                     ufn ? "UFN" : fi->lfi_desc, matches > 1 ? "es" : "", buf );
332                 fflush( stdout );
333
334                 for ( e = ldap_first_entry( ld, result ); e != NULL; ) {
335                         do_read( ld, e );
336                         e = ldap_next_entry( ld, e );
337                         if ( e != NULL ) {
338                                 printf( "--------------------\r\n" );
339                         }
340                 }
341         } else {
342                 printf( "%d %s matches for \"%s\":\r\n", matches,
343                     ufn ? "UFN" : fi->lfi_desc, buf );
344                 fflush( stdout );
345
346 #ifdef FINGER_SORT_ATTR
347                 ldap_sort_entries( ld, &result, FINGER_SORT_ATTR, strcasecmp );
348 #endif
349
350                 for ( e = ldap_first_entry( ld, result ); e != NULL;
351                     e = ldap_next_entry( ld, e ) ) {
352                         char    *p;
353
354                         dn = ldap_get_dn( ld, e );
355                         rdn = dn;
356                         if ( (p = strchr( dn, ',' )) != NULL )
357                                 *p = '\0';
358                         while ( *rdn && *rdn != '=' )
359                                 rdn++;
360                         if ( *rdn )
361                                 rdn++;
362
363                         /* hack attack */
364                         for ( i = 0; buf[i] != '\0'; i++ ) {
365                                 if ( buf[i] == '.' || buf[i] == '_' )
366                                         buf[i] = ' ';
367                         }
368                         if ( strcasecmp( rdn, buf ) == 0 ) {
369                                 char    **cn;
370                                 int     i, last;
371
372                                 cn = ldap_get_values( ld, e, "cn" );
373                                 for ( i = 0; cn[i] != NULL; i++ ) {
374                                         last = strlen( cn[i] ) - 1;
375                                         if ( isdigit( cn[i][last] ) ) {
376                                                 rdn = strdup( cn[i] );
377                                                 break;
378                                         }
379                                 }
380                         }
381                                         
382                         title = ldap_get_values( ld, e, "title" );
383
384                         spaces2dots( rdn );
385                         printf( "  %-20s    %s\r\n", rdn,
386                             title ? title[0] : "" );
387                         if ( title != NULL ) {
388                                 for ( i = 1; title[i] != NULL; i++ )
389                                         printf( "  %-20s    %s\r\n", "",
390                                             title[i] );
391                         }
392                         fflush( stdout );
393
394                         if ( title != NULL )
395                                 ldap_value_free( title );
396
397                         free( dn );
398                 }
399         }
400
401         if ( result != NULL ) {
402                 ldap_msgfree( result );
403         }
404         ldap_unbind( ld );
405 }
406
407
408 static int
409 entry2textwrite( void *fp, char *buf, int len )
410 {
411         return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
412 }
413
414
415 static void
416 do_read( LDAP *ld, LDAPMessage *e )
417 {
418         static struct ldap_disptmpl *tmpllist;
419         static char     *defattrs[] = { "mail", NULL };
420         static char     *mailvals[] = FINGER_NOEMAIL;
421         static char     **defvals[] = { mailvals, NULL };
422
423         ldap_init_templates( templatefile, &tmpllist );
424
425         if ( ldap_entry2text_search( ld, NULL, base, e, tmpllist, defattrs,
426             defvals, entry2textwrite, (void *)stdout, "\r\n", rdncount,
427             LDAP_DISP_OPT_DOSEARCHACTIONS ) != LDAP_SUCCESS ) {
428                 ldap_perror( ld, "ldap_entry2text_search" );
429                 exit( 1 );
430         }
431
432         if ( tmpllist != NULL ) {
433             ldap_free_templates( tmpllist );
434         }
435 }