2 * Copyright (c) 1991, 1993
3 * Regents of the University of Michigan. All rights reserved.
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.
18 #include <ac/string.h>
28 static char *time2text(char *ldtimestr, int dateonly);
29 static long gtime(struct tm *tm);
32 * When displaying entries, display only these attributes, and in this
35 static char *person_attr_print_order[] = {
39 "facsimileTelephoneNumber",
44 "multiLineDescription",
57 static char *group_attr_print_order[] = {
59 "facsimileTelephoneNumber",
62 "multiLineDescription",
81 parse_answer( LDAPMessage *s )
86 register LDAPMessage *ep;
91 printf("->parse_answer(%x)\n", s);
98 printf(" Done clearing entry\n");
100 for (ep = ldap_first_entry(ld, s); ep != NULL; ep = ldap_next_entry(ld, ep)) {
103 printf(" Determining DN and name\n");
105 Entry.DN = ldap_get_dn(ld, ep);
108 printf(" DN = %s\n", Entry.DN);
110 rdns = ldap_explode_dn(Entry.DN, TRUE);
113 printf(" Name = %s\n", *rdns);
115 Entry.name = strdup(*rdns);
116 ldap_value_free(rdns);
117 for (ap = ldap_first_attribute(ld, ep, &cookie); ap != NULL; ap = ldap_next_attribute(ld, ep, cookie)) {
121 printf("parsing ap = %s\n", ap);
123 if ((idx = attr_to_index(ap)) < 0) {
124 printf(" Unknown attribute \"%s\"\n", ap);
127 add_value(&(Entry.attrs[idx]), ep, ap);
132 printf(" Done parsing entry\n");
137 add_value( struct attribute *attr, LDAPMessage *ep, char *ap )
140 char **vp, **tp, **avp;
144 printf("->add_value(%x, %x, %s)\n", attr, ep, ap);
146 vp = (char **) ldap_get_values(ld, ep, ap);
149 * Fill in the attribute structure for this attribute. This
150 * stores away the values (using strdup()) and the count. Terminate
151 * the list with a NULL pointer.
153 * attr->quipu_name has already been set during initialization.
155 if ((attr->number_of_values = ldap_count_values(vp)) > 0) {
156 attr->values = (char **) Malloc((unsigned) ((attr->number_of_values + 1) * sizeof(char *)));
159 for (i = 1, tp = vp; *tp != NULL; i++, tp++) {
162 printf(" value #%d %s\n", i, *tp);
165 * The 'name' field of the Entry structure already has
166 * has the first part of the DN copied into it. Thus,
167 * we don't need to save it away here again. Also, by
168 * tossing it away here, we make printing this info out
169 * a bit easier later.
171 if (!strcmp(ap, "cn") && !strcmp(*tp, Entry.name)) {
172 attr->number_of_values--;
175 *avp++ = strdup(*tp);
183 print_an_entry( void )
186 char is_a_group, **order;
187 char *sub_list[MAX_VALUES], buf[SMALL_BUF_SIZE];
191 printf("->print_an_entry()\n");
193 printf(" \"%s\"\n", Entry.name);
196 * If the entry is a group, find all of the subscribers to that
197 * group. A subscriber is an entry that *points* to a group entry,
198 * and a member is an entry that is included as part of a group
201 * We also need to select the appropriate output format here.
203 is_a_group = isgroup();
205 order = (char **) group_attr_print_order;
206 n = find_all_subscribers(sub_list, Entry.DN);
209 printf(" Group \"%s\" has %d subscribers\n",
214 order = (char **) person_attr_print_order;
216 for (i = 0; order[i] != NULL; i++) {
217 idx = attr_to_index(order[i]);
219 if (debug & D_PRINT) {
220 printf(" ATTR #%2d = %s [%s] (%d values)\n", i + 1,
221 Entry.attrs[idx].output_string,
222 Entry.attrs[idx].quipu_name,
223 Entry.attrs[idx].number_of_values);
228 if (Entry.attrs[idx].number_of_values == 0)
231 print_DN(Entry.attrs[idx]);
232 else if (isaurl(order[i]))
233 print_URL(Entry.attrs[idx]);
234 else if (isadate(order[i])) {
235 /* fix time and date, then call usual routine */
236 Entry.attrs[idx].values[0] =
237 time2text(Entry.attrs[idx].values[0], FALSE);
238 print_values(Entry.attrs[idx]);
241 print_values(Entry.attrs[idx]);
245 * If it is a group, then we should print the subscriber list (if
246 * there are any). If there are a lot of them, prompt the user
247 * before printing them.
249 if (is_a_group && (n > 0)) {
250 char *label = "Subscribers: ";
252 if (n > TOO_MANY_TO_PRINT) {
253 printf(" There are %d subscribers. Print them? ", n);
255 fetch_buffer(buf, sizeof(buf), stdin);
256 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
259 format2((char *) my_ldap_dn2ufn(sub_list[n - 1]), label, (char *) NULL, 2,
260 2 + strlen(label) + 1, col_size);
261 for (n--; n > 0; n--)
262 format2((char *) my_ldap_dn2ufn(sub_list[n - 1]), (char *) NULL,
263 (char *) NULL, 2 + strlen(label),
264 2 + strlen(label) + 2, col_size);
270 #define OUT_LABEL_LEN 20
272 /* prints the values associated with an attribute */
274 print_values( struct attribute A )
277 register char *cp, **vp;
278 char out_buf[MED_BUF_SIZE], *padding = NULL;
283 printf("->print_values(%x)\n", A);
285 if (A.number_of_values == 0)
287 if ((vp = A.values) == NULL)
291 * Pad out the output string label so that it fills the
292 * whole field of length OUT_LABEL_LEN.
295 i = OUT_LABEL_LEN - strlen(A.output_string);
297 printf("Output string for \"%s\" is too long. Maximum length is %d characters\n", A.quipu_name, OUT_LABEL_LEN);
300 if (isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values == 0)) {
301 A.output_string = "Members";
302 i = OUT_LABEL_LEN - strlen(A.output_string);
303 padding = (char *) Malloc((unsigned) (i + 1));
304 (void) memset(padding, ' ', i);
305 *(padding + i) = '\0';
306 sprintf(out_buf, "%s:%s", A.output_string, padding);
308 else if (!(isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values > 0))) {
309 padding = (char *) Malloc((unsigned) (i + 1));
310 (void) memset(padding, ' ', i);
311 *(padding + i) = '\0';
312 sprintf(out_buf, "%s:%s", A.output_string, padding);
315 * If this happens to be a group, then do not print the output
316 * string if we have already printed out some members.
318 else if (isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values > 0)) {
319 padding = (char *) Malloc((unsigned) (OUT_LABEL_LEN + 2));
320 (void) memset(padding, ' ', OUT_LABEL_LEN + 1);
321 *(padding + OUT_LABEL_LEN + 1) = '\0';
322 sprintf(out_buf, "%s", padding);
324 lead = strlen(out_buf) + 2;
326 printf(" %s", out_buf);
327 for (i = 0; *vp != NULL; i++, vp++) {
329 if (!strncmp(A.output_string, "Home a", 6) || !strncmp(A.output_string, "Business a", 10)) {
330 printf(" %s", out_buf);
333 for (k = lead; k > 0; k--)
337 for (cp = *vp; *cp != '\0'; cp++) {
340 if (!strncmp(A.output_string, "Home a", 6) || !strncmp(A.output_string, "Business a", 10) || !strcmp(A.quipu_name, "multiLineDescription")) {
342 for (k = lead; k > 0; k--)
344 while (isspace(*(cp + 1)))
365 /* prints the DN's associated with an attribute */
367 print_DN( struct attribute A )
371 char out_buf[MED_BUF_SIZE], *padding = NULL;
375 printf("->print_DN(%x)\n", A);
377 if (A.number_of_values == 0)
380 * Pad out the output string label so that it fills the
381 * whole field of length OUT_LABEL_LEN.
383 i = OUT_LABEL_LEN - strlen(A.output_string);
385 padding = (char *) Malloc((unsigned) (i + 1));
386 (void) memset(padding, ' ', i);
387 *(padding + i) = '\0';
388 sprintf(out_buf, "%s:%s", A.output_string, padding);
389 (void) Free(padding);
391 lead = strlen(out_buf) + 2;
394 format2((char *) my_ldap_dn2ufn(*vp), out_buf, (char *) NULL, 2, lead + 1, col_size);
395 for (vp++; *vp != NULL; vp++) {
396 format2((char *) my_ldap_dn2ufn(*vp), (char *) NULL, (char *) NULL, lead,
409 printf("->clear_entry()\n");
410 if ((debug & D_PRINT) && (Entry.name != NULL))
411 printf(" Clearing entry \"%s\"\n", Entry.name);
413 if (Entry.DN != NULL)
415 if (Entry.name != NULL)
417 Entry.may_join = FALSE;
418 Entry.subscriber_count = -1;
419 Entry.DN = Entry.name = NULL;
421 /* clear all of the values associated with all attributes */
422 for (i = 0; attrlist[i].quipu_name != NULL; i++) {
425 printf(" Clearing attribute \"%s\" -- ",
426 Entry.attrs[i].quipu_name);
428 if (Entry.attrs[i].values == NULL) {
431 printf(" no values, skipping\n");
437 printf(" freeing %d values\n",
438 Entry.attrs[i].number_of_values);
440 Entry.attrs[i].number_of_values = 0;
441 ldap_value_free(Entry.attrs[i].values);
442 Entry.attrs[i].values = (char **) NULL;
445 * Note: We do not clear either of the char * fields
446 * since they will always be applicable.
452 attr_to_index( char *s )
456 for (i = 0; attrlist[i].quipu_name != NULL; i++)
457 if (!strcasecmp(s, attrlist[i].quipu_name))
463 initialize_attribute_strings( void )
467 for (i = 0; attrlist[i].quipu_name != NULL; i++)
468 Entry.attrs[i].quipu_name = attrlist[i].quipu_name;
469 for (i = 0; attrlist[i].quipu_name != NULL; i++)
470 Entry.attrs[i].output_string = attrlist[i].output_string;
473 /* prints the URL/label pairs associated with an attribute */
475 print_URL( struct attribute A )
479 char out_buf[MED_BUF_SIZE], *padding = NULL;
483 printf("->print_URL(%x)\n", A);
485 if (A.number_of_values == 0)
488 * Pad out the output string label so that it fills the
489 * whole field of length OUT_LABEL_LEN.
491 i = OUT_LABEL_LEN - strlen(A.output_string);
493 padding = (char *) Malloc((unsigned) (i + 1));
494 (void) memset(padding, ' ', i);
495 *(padding + i) = '\0';
496 sprintf(out_buf, "%s:%s", A.output_string, padding);
498 lead = strlen(out_buf) + 2;
501 print_one_URL(*vp, 2, out_buf, lead);
502 for (vp++; *vp != NULL; vp++)
503 print_one_URL(*vp, lead, (char *) NULL, lead);
510 print_one_URL( char *s, int label_lead, char *tag, int url_lead )
515 for (cp = s; !isspace(*cp) && (*cp != '\0'); cp++)
522 for (cp++; isspace(*cp); cp++)
526 cp = "(no description available)";
527 format2(cp, tag, (char *) NULL, label_lead, label_lead + 1, col_size);
528 for (i = url_lead + 2; i > 0; i--)
535 #define GET2BYTENUM( p ) (( *p - '0' ) * 10 + ( *(p+1) - '0' ))
538 time2text( char *ldtimestr, int dateonly )
541 char *p, *timestr, zone, *fmterr = "badly formatted time";
544 memset( (char *)&t, 0, sizeof( struct tm ));
545 if ( strlen( ldtimestr ) < 13 ) {
549 for ( p = ldtimestr; p - ldtimestr < 12; ++p ) {
550 if ( !isdigit( *p )) {
556 t.tm_year = GET2BYTENUM( p ); p += 2;
557 t.tm_mon = GET2BYTENUM( p ) - 1; p += 2;
558 t.tm_mday = GET2BYTENUM( p ); p += 2;
559 t.tm_hour = GET2BYTENUM( p ); p += 2;
560 t.tm_min = GET2BYTENUM( p ); p += 2;
561 t.tm_sec = GET2BYTENUM( p ); p += 2;
563 if (( zone = *p ) == 'Z' ) { /* GMT */
564 zone = '\0'; /* no need to indicate on screen, so we make it null */
567 gmttime = gtime( &t );
568 timestr = ctime( &gmttime );
570 timestr[ strlen( timestr ) - 1 ] = zone; /* replace trailing newline */
572 SAFEMEMCPY( timestr + 11, timestr + 20, strlen( timestr + 20 ) + 1 );
576 return( strdup( timestr ) );
580 /* gtime.c - inverse gmtime */
584 /* gtime(): the inverse of localtime().
585 This routine was supplied by Mike Accetta at CMU many years ago.
589 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
593 (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
595 #define YEAR(y) ((y) >= 100 ? (y) : (y) + 1900)
600 gtime( struct tm *tm )
609 register long result;
611 if ((sec = tm -> tm_sec) < 0 || sec > 59
612 || (mins = tm -> tm_min) < 0 || mins > 59
613 || (hour = tm -> tm_hour) < 0 || hour > 24
614 || (mday = tm -> tm_mday) < 1 || mday > 31
615 || (mon = tm -> tm_mon + 1) < 1 || mon > 12)
621 year = YEAR (tm -> tm_year);
624 for (i = 1970; i < year; i++)
625 result += dysize (i);
626 if (dysize (year) == 366 && mon >= 3)
629 result += dmsize[mon - 1];
631 result = 24 * result + hour;
632 result = 60 * result + mins;
633 result = 60 * result + sec;