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