2 * Copyright (c) 1990,1994 Regents of the University of Michigan.
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.
16 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
23 #include <sys/resource.h>
26 #include <sys/select.h>
35 #include "ldapconfig.h"
39 #endif /* USE_SYSCONF */
42 char *ldaphost = LDAPHOST;
43 int ldapport = LDAP_PORT;
44 char *base = FINGER_BASE;
46 char *filterfile = FILTERFILE;
47 char *templatefile = TEMPLATEFILE;
48 int rdncount = FINGER_RDNCOUNT;
58 fprintf( stderr, "usage: %s [-l] [-x ldaphost] [-p ldapport] [-f filterfile] [-t templatefile] [-c rdncount]\r\n", name );
68 unsigned long mypeer = -1;
70 struct sockaddr_in peername;
76 while ( (i = getopt( argc, argv, "f:ilp:t:x:p:c:" )) != EOF ) {
78 case 'f': /* ldap filter file */
79 filterfile = strdup( optarg );
82 case 'i': /* interactive */
86 case 'l': /* don't do syslogging */
90 case 't': /* ldap template file */
91 templatefile = strdup( optarg );
94 case 'x': /* specify ldap host */
95 ldaphost = strdup( optarg );
98 case 'p': /* specify ldap port */
99 ldapport = atoi( optarg );
102 case 'c': /* specify number of DN components to show */
103 rdncount = atoi( optarg );
111 if ( !interactive ) {
112 peernamelen = sizeof(peername);
113 if ( getpeername( 0, (struct sockaddr *)&peername,
114 &peernamelen ) != 0 ) {
115 perror( "getpeername" );
118 mypeer = (unsigned long) peername.sin_addr.s_addr;
122 if ( FINGER_BANNER != NULL && strcmp( FINGER_BANNER, "" ) != 0 ) {
123 printf( FINGER_BANNER );
128 if ( (myname = strrchr( argv[0], '/' )) == NULL )
129 myname = strdup( argv[0] );
131 myname = strdup( myname + 1 );
135 openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL4 );
137 openlog( myname, OPENLOG_OPTIONS );
141 if ( dosyslog && mypeer != -1 ) {
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 ) );
158 int len, rc, tblsize;
159 struct timeval timeout;
163 if ( (ld = ldap_open( ldaphost, ldapport )) == NULL ) {
164 fprintf( stderr, FINGER_UNAVAILABLE );
165 perror( "ldap_open" );
168 ld->ld_sizelimit = FINGER_SIZELIMIT;
169 ld->ld_deref = deref;
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" );
178 tblsize = sysconf( _SC_OPEN_MAX );
179 #else /* USE_SYSCONF */
180 tblsize = getdtablesize();
181 #endif /* USE_SYSCONF */
184 if (tblsize > FD_SETSIZE) {
185 tblsize = FD_SETSIZE;
187 #endif /* FD_SETSIZE*/
189 timeout.tv_sec = FINGER_TIMEOUT;
192 FD_SET( fileno( stdin ), &readfds );
194 if ( (rc = select( tblsize, &readfds, 0, 0, &timeout )) <= 0 ) {
198 fprintf( stderr, "connection timed out on input\r\n" );
202 if ( fgets( buf, sizeof(buf), stdin ) == NULL )
207 /* strip off \r \n */
208 if ( buf[len - 1] == '\n' ) {
212 if ( buf[len - 1] == '\r' ) {
218 printf( "No campus-wide login information available. Info for this machine only:\r\n" );
220 execl( FINGER_CMD, FINGER_CMD, NULL );
224 /* skip and ignore stinking /w */
225 if ( strncmp( buf, "/W ", 2 ) == 0 ) {
231 for ( ; *p && isspace( *p ); p++ )
249 static do_search( ld, buf )
255 int rc, matches, i, ufn;
258 LDAPMessage *result, *e;
259 static char *attrs[] = { "cn", "title", "objectClass", "joinable",
260 #ifdef FINGER_SORT_ATTR
264 extern int strcasecmp();
268 if ( strchr( buf, ',' ) != NULL ) {
269 ldap_ufn_setprefix( ld, base );
270 tv.tv_sec = FINGER_TIMEOUT;
272 ldap_ufn_timeout( (void *) &tv );
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" );
281 matches = ldap_count_entries( ld, result );
285 if ( (ld->ld_filtd = ldap_init_getfilter( filterfile ))
287 fprintf( stderr, "Cannot open filter file (%s)\n",
292 for ( fi = ldap_getfirstfilter( ld->ld_filtd, "finger", buf );
294 fi = ldap_getnextfilter( ld->ld_filtd ) )
296 tv.tv_sec = FINGER_TIMEOUT;
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 )
303 fprintf( stderr, FINGER_UNAVAILABLE );
304 ldap_perror( ld, "ldap_search_st" );
308 if ( (matches = ldap_count_entries( ld, result )) != 0 )
311 ldap_msgfree( result );
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" );
324 if ( matches == 0 ) {
325 printf( FINGER_NOMATCH );
327 } else if ( matches < 0 ) {
328 fprintf( stderr, "error return from ldap_count_entries\r\n" );
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 );
335 for ( e = ldap_first_entry( ld, result ); e != NULL; ) {
337 e = ldap_next_entry( ld, e );
339 printf( "--------------------\r\n" );
343 printf( "%d %s matches for \"%s\":\r\n", matches,
344 ufn ? "UFN" : fi->lfi_desc, buf );
347 #ifdef FINGER_SORT_ATTR
348 ldap_sort_entries( ld, &result, FINGER_SORT_ATTR, strcasecmp );
351 for ( e = ldap_first_entry( ld, result ); e != NULL;
352 e = ldap_next_entry( ld, e ) ) {
355 dn = ldap_get_dn( ld, e );
357 if ( (p = strchr( dn, ',' )) != NULL )
359 while ( *rdn && *rdn != '=' )
365 for ( i = 0; buf[i] != '\0'; i++ ) {
366 if ( buf[i] == '.' || buf[i] == '_' )
369 if ( strcasecmp( rdn, buf ) == 0 ) {
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] );
383 title = ldap_get_values( ld, e, "title" );
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", "",
396 ldap_value_free( title );
402 if ( result != NULL ) {
403 ldap_msgfree( result );
410 entry2textwrite( void *fp, char *buf, int len )
412 return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
416 static do_read( ld, e )
420 static struct ldap_disptmpl *tmpllist;
421 static char *defattrs[] = { "mail", NULL };
422 static char *mailvals[] = FINGER_NOEMAIL;
423 static char **defvals[] = { mailvals, NULL };
425 ldap_init_templates( templatefile, &tmpllist );
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" );
434 if ( tmpllist != NULL ) {
435 ldap_free_templates( tmpllist );