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