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