]> git.sur5r.net Git - openldap/blob - clients/finger/main.c
Remove extern declarations of library functions from source.c.
[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         unsigned long           mypeer = -1;
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                 mypeer = (unsigned long) peername.sin_addr.s_addr;
114         }
115
116 #ifdef FINGER_BANNER
117         if ( FINGER_BANNER != NULL && strcmp( FINGER_BANNER, "" ) != 0 ) {
118                 printf( FINGER_BANNER );
119                 fflush( stdout );
120         }
121 #endif
122
123         if ( (myname = strrchr( argv[0], '/' )) == NULL )
124                 myname = strdup( argv[0] );
125         else
126                 myname = strdup( myname + 1 );
127
128         if ( dosyslog ) {
129 #ifdef LOG_LOCAL4
130                 openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
131 #else
132                 openlog( myname, OPENLOG_OPTIONS );
133 #endif
134         }
135
136         if ( dosyslog && mypeer != (unsigned long) -1 ) {
137                 struct in_addr  addr;
138
139                 hp = gethostbyaddr( (char *) &mypeer, sizeof(mypeer), AF_INET );
140                 addr.s_addr = mypeer;
141                 syslog( LOG_INFO, "connection from %s (%s)", (hp == NULL) ?
142                     "unknown" : hp->h_name, inet_ntoa( addr ) );
143         }
144
145         do_query();
146
147         return( 0 );
148 }
149
150 static void
151 do_query( void )
152 {
153         char            buf[256];
154         int             len, rc, tblsize;
155         struct timeval  timeout;
156         fd_set          readfds;
157         LDAP            *ld;
158
159         if ( (ld = ldap_open( ldaphost, ldapport )) == NULL ) {
160                 fprintf( stderr, FINGER_UNAVAILABLE );
161                 perror( "ldap_open" );
162                 exit( 1 );
163         }
164
165         {
166                 int limit = FINGER_SIZELIMIT;
167                 ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &limit);
168         }
169         ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
170
171         if ( ldap_simple_bind_s( ld, NULL, NULL )
172                 != LDAP_SUCCESS )
173         {
174                 fprintf( stderr, FINGER_UNAVAILABLE );
175                 ldap_perror( ld, "ldap_simple_bind_s" );
176                 exit( 1 );
177         }
178
179 #ifdef HAVE_SYSCONF
180         tblsize = sysconf( _SC_OPEN_MAX );
181 #elif HAVE_GETDTABLESIZE
182         tblsize = getdtablesize();
183 #else
184         tblsize = FD_SETSIZE;
185 #endif
186
187 #ifdef FD_SETSIZE
188         if (tblsize > FD_SETSIZE) {
189                 tblsize = FD_SETSIZE;
190         }
191 #endif  /* FD_SETSIZE*/
192
193         timeout.tv_sec = FINGER_TIMEOUT;
194         timeout.tv_usec = 0;
195         FD_ZERO( &readfds );
196         FD_SET( fileno( stdin ), &readfds );
197
198         if ( (rc = select( tblsize, &readfds, 0, 0, &timeout )) <= 0 ) {
199                 if ( rc < 0 )
200                         perror( "select" );
201                 else
202                         fprintf( stderr, "connection timed out on input\r\n" );
203                 exit( 1 );
204         }
205
206         if ( fgets( buf, sizeof(buf), stdin ) == NULL )
207                 exit( 1 );
208
209         len = strlen( buf );
210
211         /* strip off \r \n */
212         if ( buf[len - 1] == '\n' ) {
213                 buf[len - 1] = '\0';
214                 len--;
215         }
216         if ( buf[len - 1] == '\r' ) {
217                 buf[len - 1] = '\0';
218                 len--;
219         }
220
221         if ( len == 0 ) {
222                 printf( "No campus-wide login information available.  Info for this machine only:\r\n" );
223                 fflush( stdout );
224                 execl( FINGER_CMD, FINGER_CMD, NULL );
225         } else {
226                 char    *p;
227
228                 /* skip and ignore stinking /w */
229                 if ( strncmp( buf, "/W ", 2 ) == 0 ) {
230                         p = buf + 2;
231                 } else {
232                         p = buf;
233                 }
234
235                 for ( ; *p && isspace( *p ); p++ )
236                         ;       /* NULL */
237
238                 do_search( ld, p );
239         }
240 }
241
242 static void
243 spaces2dots( char *s )
244 {
245         for ( ; *s; s++ ) {
246                 if ( *s == ' ' ) {
247                         *s = '.';
248                 }
249         }
250 }
251
252 static void
253 do_search( LDAP *ld, char *buf )
254 {
255         char            *dn, *rdn;
256         char            **title;
257         int             rc, matches, i, ufn;
258         struct timeval  tv;
259         LDAPFiltDesc    *fd;
260         LDAPFiltInfo    *fi;
261         LDAPMessage     *result, *e;
262         static char     *attrs[] = { "cn", "title", "objectClass", "joinable",
263 #ifdef FINGER_SORT_ATTR
264                                         FINGER_SORT_ATTR,
265 #endif
266                                         0 };
267
268         ufn = 0;
269 #ifdef FINGER_UFN
270         if ( strchr( buf, ',' ) != NULL ) {
271                 ldap_ufn_setprefix( ld, base );
272                 tv.tv_sec = FINGER_TIMEOUT;
273                 tv.tv_usec = 0;
274                 ldap_ufn_timeout( (void *) &tv );
275
276                 if ( (rc = ldap_ufn_search_s( ld, buf, attrs, 0, &result ))
277                     != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
278                         fprintf( stderr, FINGER_UNAVAILABLE );
279                         ldap_perror( ld, "ldap_search_st" );
280                         exit( 1 );
281                 }
282
283                 matches = ldap_count_entries( ld, result );
284                 ufn = 1;
285         } else {
286 #endif
287                 if ( (fd = ldap_init_getfilter( filterfile ))
288                     == NULL ) {
289                         fprintf( stderr, "Cannot open filter file (%s)\n",
290                             filterfile );
291                         exit( 1 );
292                 }
293
294                 for ( fi = ldap_getfirstfilter( fd, "finger", buf );
295                     fi != NULL;
296                     fi = ldap_getnextfilter( fd ) )
297                 {
298                         tv.tv_sec = FINGER_TIMEOUT;
299                         tv.tv_usec = 0;
300                         if ( (rc = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE,
301                             fi->lfi_filter, attrs, 0, &tv, &result ))
302                             != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
303                             && rc != LDAP_TIMELIMIT_EXCEEDED )
304                         {
305                                 fprintf( stderr, FINGER_UNAVAILABLE );
306                                 ldap_perror( ld, "ldap_search_st" );
307                                 exit( 1 );
308                         }
309
310                         if ( (matches = ldap_count_entries( ld, result )) != 0 )
311                                 break;
312
313                         ldap_msgfree( result );
314                         result = NULL;
315                 }
316 #ifdef FINGER_UFN
317         }
318 #endif
319
320         if ( rc == LDAP_SIZELIMIT_EXCEEDED ) {
321                 printf( "(Partial results - a size limit was exceeded)\r\n" );
322         } else if ( rc == LDAP_TIMELIMIT_EXCEEDED ) {
323                 printf( "(Partial results - a time limit was exceeded)\r\n" );
324         }
325
326         if ( matches == 0 ) {
327                 printf( FINGER_NOMATCH );
328                 fflush( stdout );
329         } else if ( matches < 0 ) {
330                 fprintf( stderr, "error return from ldap_count_entries\r\n" );
331                 exit( 1 );
332         } else if ( matches <= FINGER_LISTLIMIT ) {
333                 printf( "%d %s match%s found for \"%s\":\r\n", matches,
334                     ufn ? "UFN" : fi->lfi_desc, matches > 1 ? "es" : "", buf );
335                 fflush( stdout );
336
337                 for ( e = ldap_first_entry( ld, result ); e != NULL; ) {
338                         do_read( ld, e );
339                         e = ldap_next_entry( ld, e );
340                         if ( e != NULL ) {
341                                 printf( "--------------------\r\n" );
342                         }
343                 }
344         } else {
345                 printf( "%d %s matches for \"%s\":\r\n", matches,
346                     ufn ? "UFN" : fi->lfi_desc, buf );
347                 fflush( stdout );
348
349 #ifdef FINGER_SORT_ATTR
350                 ldap_sort_entries( ld, &result, FINGER_SORT_ATTR, strcasecmp );
351 #endif
352
353                 for ( e = ldap_first_entry( ld, result ); e != NULL;
354                     e = ldap_next_entry( ld, e ) ) {
355                         char    *p;
356
357                         dn = ldap_get_dn( ld, e );
358                         rdn = dn;
359                         if ( (p = strchr( dn, ',' )) != NULL )
360                                 *p = '\0';
361                         while ( *rdn && *rdn != '=' )
362                                 rdn++;
363                         if ( *rdn )
364                                 rdn++;
365
366                         /* hack attack */
367                         for ( i = 0; buf[i] != '\0'; i++ ) {
368                                 if ( buf[i] == '.' || buf[i] == '_' )
369                                         buf[i] = ' ';
370                         }
371                         if ( strcasecmp( rdn, buf ) == 0 ) {
372                                 char    **cn;
373                                 int     i, last;
374
375                                 cn = ldap_get_values( ld, e, "cn" );
376                                 for ( i = 0; cn[i] != NULL; i++ ) {
377                                         last = strlen( cn[i] ) - 1;
378                                         if ( isdigit( cn[i][last] ) ) {
379                                                 rdn = strdup( cn[i] );
380                                                 break;
381                                         }
382                                 }
383                         }
384                                         
385                         title = ldap_get_values( ld, e, "title" );
386
387                         spaces2dots( rdn );
388                         printf( "  %-20s    %s\r\n", rdn,
389                             title ? title[0] : "" );
390                         if ( title != NULL ) {
391                                 for ( i = 1; title[i] != NULL; i++ )
392                                         printf( "  %-20s    %s\r\n", "",
393                                             title[i] );
394                         }
395                         fflush( stdout );
396
397                         if ( title != NULL )
398                                 ldap_value_free( title );
399
400                         free( dn );
401                 }
402         }
403
404         if ( result != NULL ) {
405                 ldap_msgfree( result );
406         }
407         ldap_unbind( ld );
408 }
409
410
411 static int
412 entry2textwrite( void *fp, char *buf, int len )
413 {
414         return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
415 }
416
417
418 static void
419 do_read( LDAP *ld, LDAPMessage *e )
420 {
421         static struct ldap_disptmpl *tmpllist;
422         static char     *defattrs[] = { "mail", NULL };
423         static char     *mailvals[] = FINGER_NOEMAIL;
424         static char     **defvals[] = { mailvals, NULL };
425
426         ldap_init_templates( templatefile, &tmpllist );
427
428         if ( ldap_entry2text_search( ld, NULL, base, e, tmpllist, defattrs,
429             defvals, entry2textwrite, (void *)stdout, "\r\n", rdncount,
430             LDAP_DISP_OPT_DOSEARCHACTIONS ) != LDAP_SUCCESS ) {
431                 ldap_perror( ld, "ldap_entry2text_search" );
432                 exit( 1 );
433         }
434
435         if ( tmpllist != NULL ) {
436             ldap_free_templates( tmpllist );
437         }
438 }