]> git.sur5r.net Git - openldap/blob - clients/finger/main.c
Take address of enclosing structure (in_addr), not member (s_addr).
[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 #include "disptmpl.h"
34
35 #include "ldapconfig.h"
36
37
38 int     dosyslog = 1;
39 char    *ldaphost = NULL;
40 int     ldapport = 0;
41 char    *base = NULL;
42 int     deref;
43 char    *filterfile = FILTERFILE;
44 char    *templatefile = TEMPLATEFILE;
45 int     rdncount = FINGER_RDNCOUNT;
46
47 static void do_query(void);
48 static void do_search(LDAP *ld, char *buf);
49 static void do_read(LDAP *ld, LDAPMessage *e);
50
51 static void
52 usage( char *name )
53 {
54         fprintf( stderr, "usage: %s [-l] [-x ldaphost] [-p ldapport] [-f filterfile] [-t templatefile] [-c rdncount]\r\n", name );
55         exit( 1 );
56 }
57
58 int
59 main( int argc, char **argv )
60 {
61         int                     i;
62         char                    *myname;
63         struct hostent          *hp;
64         struct sockaddr_in      peername;
65         int                     peernamelen;
66         int                     interactive = 0;
67
68         deref = FINGER_DEREF;
69         while ( (i = getopt( argc, argv, "f:ilp:t:x:p:c:" )) != EOF ) {
70                 switch( i ) {
71                 case 'f':       /* ldap filter file */
72                         filterfile = strdup( optarg );
73                         break;
74
75                 case 'i':       /* interactive */
76                         interactive = 1;
77                         break;
78
79                 case 'l':       /* don't do syslogging */
80                         dosyslog = 0;
81                         break;
82
83                 case 't':       /* ldap template file */
84                         templatefile = strdup( optarg );
85                         break;
86
87                 case 'x':       /* specify ldap host */
88                         ldaphost = strdup( optarg );
89                         break;
90
91                 case 'p':       /* specify ldap port */
92                         ldapport = atoi( optarg );
93                         break;
94
95                 case 'c':       /* specify number of DN components to show */
96                         rdncount = atoi( optarg );
97                         break;
98
99                 default:
100                         usage( argv[0] );
101                 }
102         }
103
104         if ( !interactive ) {
105                 peernamelen = sizeof(peername);
106                 if ( getpeername( 0, (struct sockaddr *)&peername,
107                     &peernamelen ) != 0 ) {
108                         perror( "getpeername" );
109                         exit( 1 );
110                 }
111         }
112
113 #ifdef FINGER_BANNER
114         if ( FINGER_BANNER != NULL && strcmp( FINGER_BANNER, "" ) != 0 ) {
115                 printf( FINGER_BANNER );
116                 fflush( stdout );
117         }
118 #endif
119
120         if ( (myname = strrchr( argv[0], '/' )) == NULL )
121                 myname = strdup( argv[0] );
122         else
123                 myname = strdup( myname + 1 );
124
125 #ifdef SIGPIPE
126         (void) SIGNAL( SIGPIPE, SIG_IGN );
127 #endif
128
129         if ( dosyslog ) {
130 #ifdef LOG_LOCAL4
131                 openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
132 #else
133                 openlog( myname, OPENLOG_OPTIONS );
134 #endif
135         }
136
137         if ( dosyslog && !interactive ) {
138                 hp = gethostbyaddr( (char *) &peername.sin_addr,
139                                     sizeof(peername.sin_addr), AF_INET );
140                 syslog( LOG_INFO, "connection from %s (%s)",
141                         (hp == NULL) ? "unknown" : hp->h_name,
142                         inet_ntoa( peername.sin_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         ld->ld_sizelimit = FINGER_SIZELIMIT;
165         ld->ld_deref = deref;
166
167         if ( ldap_simple_bind_s( ld, NULL, NULL )
168                 != LDAP_SUCCESS )
169         {
170                 fprintf( stderr, FINGER_UNAVAILABLE );
171                 ldap_perror( ld, "ldap_simple_bind_s" );
172                 exit( 1 );
173         }
174
175 #ifdef HAVE_SYSCONF
176         tblsize = sysconf( _SC_OPEN_MAX );
177 #elif HAVE_GETDTABLESIZE
178         tblsize = getdtablesize();
179 #else
180         tblsize = FD_SETSIZE;
181 #endif
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( (unsigned char) *p ); p++ )
232                         ;       /* NULL */
233
234                 do_search( ld, p );
235         }
236 }
237
238 static void
239 spaces2dots( char *s )
240 {
241         for ( ; *s; s++ ) {
242                 if ( *s == ' ' ) {
243                         *s = '.';
244                 }
245         }
246 }
247
248 static void
249 do_search( LDAP *ld, char *buf )
250 {
251         char            *dn, *rdn;
252         char            **title;
253         int             rc, matches, i, ufn;
254         struct timeval  tv;
255         LDAPFiltInfo    *fi;
256         LDAPMessage     *result, *e;
257         static char     *attrs[] = { "cn", "title", "objectClass", "joinable",
258 #ifdef FINGER_SORT_ATTR
259                                         FINGER_SORT_ATTR,
260 #endif
261                                         0 };
262
263         ufn = 0;
264 #ifdef FINGER_UFN
265         if ( strchr( buf, ',' ) != NULL ) {
266                 ldap_ufn_setprefix( ld, base );
267                 tv.tv_sec = FINGER_TIMEOUT;
268                 tv.tv_usec = 0;
269                 ldap_ufn_timeout( (void *) &tv );
270
271                 if ( (rc = ldap_ufn_search_s( ld, buf, attrs, 0, &result ))
272                     != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
273                         fprintf( stderr, FINGER_UNAVAILABLE );
274                         ldap_perror( ld, "ldap_search_st" );
275                         exit( 1 );
276                 }
277
278                 matches = ldap_count_entries( ld, result );
279                 ufn = 1;
280         } else {
281 #endif
282                 if ( (ld->ld_filtd = ldap_init_getfilter( filterfile ))
283                     == NULL ) {
284                         fprintf( stderr, "Cannot open filter file (%s)\n",
285                             filterfile );
286                         exit( 1 );
287                 }
288
289                 for ( fi = ldap_getfirstfilter( ld->ld_filtd, "finger", buf );
290                     fi != NULL;
291                     fi = ldap_getnextfilter( ld->ld_filtd ) )
292                 {
293                         tv.tv_sec = FINGER_TIMEOUT;
294                         tv.tv_usec = 0;
295                         if ( (rc = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE,
296                             fi->lfi_filter, attrs, 0, &tv, &result ))
297                             != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
298                             && rc != LDAP_TIMELIMIT_EXCEEDED )
299                         {
300                                 fprintf( stderr, FINGER_UNAVAILABLE );
301                                 ldap_perror( ld, "ldap_search_st" );
302                                 exit( 1 );
303                         }
304
305                         if ( (matches = ldap_count_entries( ld, result )) != 0 )
306                                 break;
307
308                         ldap_msgfree( result );
309                         result = NULL;
310                 }
311 #ifdef FINGER_UFN
312         }
313 #endif
314
315         if ( rc == LDAP_SIZELIMIT_EXCEEDED ) {
316                 printf( "(Partial results - a size limit was exceeded)\r\n" );
317         } else if ( rc == LDAP_TIMELIMIT_EXCEEDED ) {
318                 printf( "(Partial results - a time limit was exceeded)\r\n" );
319         }
320
321         if ( matches == 0 ) {
322                 printf( FINGER_NOMATCH );
323                 fflush( stdout );
324         } else if ( matches < 0 ) {
325                 fprintf( stderr, "error return from ldap_count_entries\r\n" );
326                 exit( 1 );
327         } else if ( matches <= FINGER_LISTLIMIT ) {
328                 printf( "%d %s match%s found for \"%s\":\r\n", matches,
329                     ufn ? "UFN" : fi->lfi_desc, matches > 1 ? "es" : "", buf );
330                 fflush( stdout );
331
332                 for ( e = ldap_first_entry( ld, result ); e != NULL; ) {
333                         do_read( ld, e );
334                         e = ldap_next_entry( ld, e );
335                         if ( e != NULL ) {
336                                 printf( "--------------------\r\n" );
337                         }
338                 }
339         } else {
340                 printf( "%d %s matches for \"%s\":\r\n", matches,
341                     ufn ? "UFN" : fi->lfi_desc, buf );
342                 fflush( stdout );
343
344 #ifdef FINGER_SORT_ATTR
345                 ldap_sort_entries( ld, &result, FINGER_SORT_ATTR, strcasecmp );
346 #endif
347
348                 for ( e = ldap_first_entry( ld, result ); e != NULL;
349                     e = ldap_next_entry( ld, e ) ) {
350                         char    *p;
351
352                         dn = ldap_get_dn( ld, e );
353                         rdn = dn;
354                         if ( (p = strchr( dn, ',' )) != NULL )
355                                 *p = '\0';
356                         while ( *rdn && *rdn != '=' )
357                                 rdn++;
358                         if ( *rdn )
359                                 rdn++;
360
361                         /* hack attack */
362                         for ( i = 0; buf[i] != '\0'; i++ ) {
363                                 if ( buf[i] == '.' || buf[i] == '_' )
364                                         buf[i] = ' ';
365                         }
366                         if ( strcasecmp( rdn, buf ) == 0 ) {
367                                 char    **cn;
368                                 int     i, last;
369
370                                 cn = ldap_get_values( ld, e, "cn" );
371                                 for ( i = 0; cn[i] != NULL; i++ ) {
372                                         last = strlen( cn[i] ) - 1;
373                                         if (isdigit((unsigned char) cn[i][last])) {
374                                                 rdn = strdup( cn[i] );
375                                                 break;
376                                         }
377                                 }
378                         }
379                                         
380                         title = ldap_get_values( ld, e, "title" );
381
382                         spaces2dots( rdn );
383                         printf( "  %-20s    %s\r\n", rdn,
384                             title ? title[0] : "" );
385                         if ( title != NULL ) {
386                                 for ( i = 1; title[i] != NULL; i++ )
387                                         printf( "  %-20s    %s\r\n", "",
388                                             title[i] );
389                         }
390                         fflush( stdout );
391
392                         if ( title != NULL )
393                                 ldap_value_free( title );
394
395                         free( dn );
396                 }
397         }
398
399         if ( result != NULL ) {
400                 ldap_msgfree( result );
401         }
402         ldap_unbind( ld );
403 }
404
405
406 static int
407 entry2textwrite( void *fp, char *buf, int len )
408 {
409         return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
410 }
411
412
413 static void
414 do_read( LDAP *ld, 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 }