3 * Copyright (c) 1990,1994 Regents of the University of Michigan.
6 * Redistribution and use in source and binary forms are permitted
7 * provided that this notice is preserved and that due credit is given
8 * to the University of Michigan at Ann Arbor. The name of the University
9 * may not be used to endorse or promote products derived from this
10 * software without specific prior written permission. This software
11 * is provided ``as is'' without express or implied warranty.
18 #include <ac/stdlib.h>
21 #include <ac/signal.h>
22 #include <ac/socket.h>
23 #include <ac/string.h>
24 #include <ac/syslog.h>
26 #include <ac/unistd.h>
29 #ifdef HAVE_SYS_RESOURCE_H
30 #include <sys/resource.h>
36 #include "ldap_defaults.h"
40 char *ldaphost = NULL;
44 char *filterfile = FILTERFILE;
45 char *templatefile = TEMPLATEFILE;
46 int rdncount = FINGER_RDNCOUNT;
48 static void do_query(void);
49 static void do_search(LDAP *ld, char *buf);
50 static void do_read(LDAP *ld, LDAPMessage *e);
55 fprintf( stderr, "usage: %s [-l] [-x ldaphost] [-p ldapport] [-b searchbase] [-f filterfile] [-t templatefile] [-c rdncount]\r\n", name );
60 main( int argc, char **argv )
65 struct sockaddr_in peername;
66 socklen_t peernamelen;
70 while ( (i = getopt( argc, argv, "f:ilp:t:x:p:b:c:" )) != EOF ) {
72 case 'f': /* ldap filter file */
73 filterfile = strdup( optarg );
76 case 'i': /* interactive */
80 case 'l': /* don't do syslogging */
84 case 't': /* ldap template file */
85 templatefile = strdup( optarg );
88 case 'x': /* specify ldap host */
89 ldaphost = strdup( optarg );
92 case 'p': /* specify ldap port */
93 ldapport = atoi( optarg );
96 case 'b': /* specify search base */
97 base = strdup( optarg );
100 case 'c': /* specify number of DN components to show */
101 rdncount = atoi( optarg );
109 if ( !interactive ) {
110 peernamelen = sizeof(peername);
111 if ( getpeername( 0, (struct sockaddr *)&peername,
112 &peernamelen ) != 0 ) {
113 perror( "getpeername" );
114 exit( EXIT_FAILURE );
119 if ( FINGER_BANNER != NULL && strcmp( FINGER_BANNER, "" ) != 0 ) {
120 printf( FINGER_BANNER );
125 if ( (myname = strrchr( argv[0], '/' )) == NULL )
126 myname = strdup( argv[0] );
128 myname = strdup( myname + 1 );
131 (void) SIGNAL( SIGPIPE, SIG_IGN );
136 openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
138 openlog( myname, OPENLOG_OPTIONS );
142 if ( dosyslog && !interactive ) {
143 hp = gethostbyaddr( (char *) &peername.sin_addr,
144 sizeof(peername.sin_addr), AF_INET );
145 syslog( LOG_INFO, "connection from %s (%s)",
146 (hp == NULL) ? "unknown" : hp->h_name,
147 inet_ntoa( peername.sin_addr ) );
159 int len, rc, tblsize;
160 struct timeval timeout;
164 if ( (ld = ldap_init( ldaphost, ldapport )) == NULL ) {
165 fprintf( stderr, FINGER_UNAVAILABLE );
166 perror( "ldap_init" );
167 exit( EXIT_FAILURE );
171 int limit = FINGER_SIZELIMIT;
172 ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &limit);
174 ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
176 if ( ldap_simple_bind_s( ld, NULL, NULL )
179 fprintf( stderr, FINGER_UNAVAILABLE );
180 ldap_perror( ld, "ldap_simple_bind_s" );
181 exit( EXIT_FAILURE );
185 tblsize = sysconf( _SC_OPEN_MAX );
186 #elif HAVE_GETDTABLESIZE
187 tblsize = getdtablesize();
189 tblsize = FD_SETSIZE;
193 if (tblsize > FD_SETSIZE) {
194 tblsize = FD_SETSIZE;
196 #endif /* FD_SETSIZE*/
198 timeout.tv_sec = FINGER_TIMEOUT;
201 FD_SET( fileno( stdin ), &readfds );
203 if ( (rc = select( tblsize, &readfds, 0, 0, &timeout )) <= 0 ) {
207 fprintf( stderr, "connection timed out on input\r\n" );
208 exit( EXIT_FAILURE );
211 if ( fgets( buf, sizeof(buf), stdin ) == NULL )
212 exit( EXIT_FAILURE );
216 /* strip off \r \n */
217 if ( buf[len - 1] == '\n' ) {
221 if ( buf[len - 1] == '\r' ) {
227 printf( "No campus-wide login information available. Info for this machine only:\r\n" );
229 execl( FINGER_CMD, FINGER_CMD, NULL );
233 /* skip and ignore stinking /w */
234 if ( strncmp( buf, "/W ", 2 ) == 0 ) {
240 for ( ; *p && isspace( (unsigned char) *p ); p++ )
248 spaces2dots( char *s )
258 do_search( LDAP *ld, char *buf )
262 int rc = 0, matches = 0, i;
265 LDAPFiltInfo *fi = NULL;
266 LDAPMessage *result, *e;
267 static char *attrs[] = { "cn", "title", "objectClass", "joinable",
268 #ifdef FINGER_SORT_ATTR
273 if ( (fd = ldap_init_getfilter( filterfile ))
275 fprintf( stderr, "Cannot open filter file (%s)\n",
277 exit( EXIT_FAILURE );
280 for ( fi = ldap_getfirstfilter( fd, "finger", buf );
282 fi = ldap_getnextfilter( fd ) )
284 tv.tv_sec = FINGER_TIMEOUT;
286 if ( (rc = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE,
287 fi->lfi_filter, attrs, 0, &tv, &result ))
288 != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
289 && rc != LDAP_TIMELIMIT_EXCEEDED )
291 fprintf( stderr, FINGER_UNAVAILABLE );
292 ldap_perror( ld, "ldap_search_st" );
293 exit( EXIT_FAILURE );
296 if ( (matches = ldap_count_entries( ld, result )) != 0 )
299 ldap_msgfree( result );
303 if ( rc == LDAP_SIZELIMIT_EXCEEDED ) {
304 printf( "(Partial results - a size limit was exceeded)\r\n" );
305 } else if ( rc == LDAP_TIMELIMIT_EXCEEDED ) {
306 printf( "(Partial results - a time limit was exceeded)\r\n" );
309 if ( matches == 0 ) {
310 printf( FINGER_NOMATCH );
312 } else if ( matches < 0 ) {
313 fprintf( stderr, "error return from ldap_count_entries\r\n" );
314 exit( EXIT_FAILURE );
315 } else if ( matches <= FINGER_LISTLIMIT ) {
316 printf( "%d %s match%s found for \"%s\":\r\n", matches,
317 fi->lfi_desc, matches > 1 ? "es" : "", buf );
320 for ( e = ldap_first_entry( ld, result ); e != NULL; ) {
322 e = ldap_next_entry( ld, e );
324 printf( "--------------------\r\n" );
328 printf( "%d %s matches for \"%s\":\r\n", matches,
332 #ifdef FINGER_SORT_ATTR
333 ldap_sort_entries( ld, &result, FINGER_SORT_ATTR, strcasecmp );
336 for ( e = ldap_first_entry( ld, result ); e != NULL;
337 e = ldap_next_entry( ld, e ) ) {
340 dn = ldap_get_dn( ld, e );
342 if ( (p = strchr( dn, ',' )) != NULL )
344 while ( *rdn && *rdn != '=' )
350 for ( i = 0; buf[i] != '\0'; i++ ) {
351 if ( buf[i] == '.' || buf[i] == '_' )
354 if ( strcasecmp( rdn, buf ) == 0 ) {
358 cn = ldap_get_values( ld, e, "cn" );
359 for ( i = 0; cn[i] != NULL; i++ ) {
360 last = strlen( cn[i] ) - 1;
361 if (isdigit((unsigned char) cn[i][last])) {
362 rdn = strdup( cn[i] );
368 title = ldap_get_values( ld, e, "title" );
371 printf( " %-20s %s\r\n", rdn,
372 title ? title[0] : "" );
373 if ( title != NULL ) {
374 for ( i = 1; title[i] != NULL; i++ )
375 printf( " %-20s %s\r\n", "",
381 ldap_value_free( title );
387 if ( result != NULL ) {
388 ldap_msgfree( result );
395 entry2textwrite( void *fp, char *buf, ber_len_t len )
397 return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
402 do_read( LDAP *ld, LDAPMessage *e )
404 static struct ldap_disptmpl *tmpllist;
405 static char *defattrs[] = { "mail", NULL };
406 static char *mailvals[] = FINGER_NOEMAIL;
407 static char **defvals[] = { mailvals, NULL };
409 ldap_init_templates( templatefile, &tmpllist );
411 if ( ldap_entry2text_search( ld, NULL, base, e, tmpllist, defattrs,
412 defvals, entry2textwrite, (void *)stdout, "\r\n", rdncount,
413 LDAP_DISP_OPT_DOSEARCHACTIONS ) != LDAP_SUCCESS ) {
414 ldap_perror( ld, "ldap_entry2text_search" );
415 exit( EXIT_FAILURE );
418 if ( tmpllist != NULL ) {
419 ldap_free_templates( tmpllist );