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>
33 extern void * Malloc();
35 extern char * my_ldap_dn2ufn();
37 static char *time2text();
41 * When displaying entries, display only these attributes, and in this
44 static char *person_attr_print_order[] = {
48 "facsimileTelephoneNumber",
53 "multiLineDescription",
66 static char *group_attr_print_order[] = {
68 "facsimileTelephoneNumber",
71 "multiLineDescription",
94 register LDAPMessage *ep;
100 printf("->parse_answer(%x)\n", s);
107 printf(" Done clearing entry\n");
109 for (ep = ldap_first_entry(ld, s); ep != NULL; ep = ldap_next_entry(ld, ep)) {
112 printf(" Determining DN and name\n");
114 Entry.DN = ldap_get_dn(ld, ep);
117 printf(" DN = %s\n", Entry.DN);
119 rdns = ldap_explode_dn(Entry.DN, TRUE);
122 printf(" Name = %s\n", *rdns);
124 Entry.name = strdup(*rdns);
125 ldap_value_free(rdns);
126 for (ap = ldap_first_attribute(ld, ep, &cookie); ap != NULL; ap = ldap_next_attribute(ld, ep, cookie)) {
130 printf("parsing ap = %s\n", ap);
132 if ((idx = attr_to_index(ap)) < 0) {
133 printf(" Unknown attribute \"%s\"\n", ap);
136 add_value(&(Entry.attrs[idx]), ep, ap);
141 printf(" Done parsing entry\n");
145 add_value(attr, ep, ap)
146 struct attribute *attr;
151 char **vp, **tp, **avp;
155 printf("->add_value(%x, %x, %s)\n", attr, ep, ap);
157 vp = (char **) ldap_get_values(ld, ep, ap);
160 * Fill in the attribute structure for this attribute. This
161 * stores away the values (using strdup()) and the count. Terminate
162 * the list with a NULL pointer.
164 * attr->quipu_name has already been set during initialization.
166 if ((attr->number_of_values = ldap_count_values(vp)) > 0) {
167 attr->values = (char **) Malloc((unsigned) ((attr->number_of_values + 1) * sizeof(char *)));
170 for (i = 1, tp = vp; *tp != NULL; i++, tp++) {
173 printf(" value #%d %s\n", i, *tp);
176 * The 'name' field of the Entry structure already has
177 * has the first part of the DN copied into it. Thus,
178 * we don't need to save it away here again. Also, by
179 * tossing it away here, we make printing this info out
180 * a bit easier later.
182 if (!strcmp(ap, "cn") && !strcmp(*tp, Entry.name)) {
183 attr->number_of_values--;
186 *avp++ = strdup(*tp);
196 char is_a_group, **order;
197 char *sub_list[MAX_VALUES], buf[SMALL_BUF_SIZE];
198 extern int col_size, isaurl(), isadn();
202 printf("->print_an_entry()\n");
204 printf(" \"%s\"\n", Entry.name);
207 * If the entry is a group, find all of the subscribers to that
208 * group. A subscriber is an entry that *points* to a group entry,
209 * and a member is an entry that is included as part of a group
212 * We also need to select the appropriate output format here.
214 is_a_group = isgroup();
216 order = (char **) group_attr_print_order;
217 n = find_all_subscribers(sub_list, Entry.DN);
220 printf(" Group \"%s\" has %d subscribers\n",
225 order = (char **) person_attr_print_order;
227 for (i = 0; order[i] != NULL; i++) {
228 idx = attr_to_index(order[i]);
230 if (debug & D_PRINT) {
231 printf(" ATTR #%2d = %s [%s] (%d values)\n", i + 1,
232 Entry.attrs[idx].output_string,
233 Entry.attrs[idx].quipu_name,
234 Entry.attrs[idx].number_of_values);
239 if (Entry.attrs[idx].number_of_values == 0)
242 print_DN(Entry.attrs[idx]);
243 else if (isaurl(order[i]))
244 print_URL(Entry.attrs[idx]);
245 else if (isadate(order[i])) {
246 /* fix time and date, then call usual routine */
247 Entry.attrs[idx].values[0] =
248 time2text(Entry.attrs[idx].values[0], FALSE);
249 print_values(Entry.attrs[idx]);
252 print_values(Entry.attrs[idx]);
256 * If it is a group, then we should print the subscriber list (if
257 * there are any). If there are a lot of them, prompt the user
258 * before printing them.
260 if (is_a_group && (n > 0)) {
261 char *label = "Subscribers: ";
263 if (n > TOO_MANY_TO_PRINT) {
264 printf(" There are %d subscribers. Print them? ", n);
266 fetch_buffer(buf, sizeof(buf), stdin);
267 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
270 format2((char *) my_ldap_dn2ufn(sub_list[n - 1]), label, (char *) NULL, 2,
271 2 + strlen(label) + 1, col_size);
272 for (n--; n > 0; n--)
273 format2((char *) my_ldap_dn2ufn(sub_list[n - 1]), (char *) NULL,
274 (char *) NULL, 2 + strlen(label),
275 2 + strlen(label) + 2, col_size);
281 #define OUT_LABEL_LEN 20
283 /* prints the values associated with an attribute */
288 register char *cp, **vp;
289 char out_buf[MED_BUF_SIZE], *padding = NULL;
294 printf("->print_values(%x)\n", A);
296 if (A.number_of_values == 0)
298 if ((vp = A.values) == NULL)
302 * Pad out the output string label so that it fills the
303 * whole field of length OUT_LABEL_LEN.
306 i = OUT_LABEL_LEN - strlen(A.output_string);
308 printf("Output string for \"%s\" is too long. Maximum length is %d characters\n", A.quipu_name, OUT_LABEL_LEN);
311 if (isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values == 0)) {
312 A.output_string = "Members";
313 i = OUT_LABEL_LEN - strlen(A.output_string);
314 padding = (char *) Malloc((unsigned) (i + 1));
315 (void) memset(padding, ' ', i);
316 *(padding + i) = '\0';
317 sprintf(out_buf, "%s:%s", A.output_string, padding);
319 else if (!(isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values > 0))) {
320 padding = (char *) Malloc((unsigned) (i + 1));
321 (void) memset(padding, ' ', i);
322 *(padding + i) = '\0';
323 sprintf(out_buf, "%s:%s", A.output_string, padding);
326 * If this happens to be a group, then do not print the output
327 * string if we have already printed out some members.
329 else if (isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values > 0)) {
330 padding = (char *) Malloc((unsigned) (OUT_LABEL_LEN + 2));
331 (void) memset(padding, ' ', OUT_LABEL_LEN + 1);
332 *(padding + OUT_LABEL_LEN + 1) = '\0';
333 sprintf(out_buf, "%s", padding);
335 lead = strlen(out_buf) + 2;
337 printf(" %s", out_buf);
338 for (i = 0; *vp != NULL; i++, vp++) {
340 if (!strncmp(A.output_string, "Home a", 6) || !strncmp(A.output_string, "Business a", 10)) {
341 printf(" %s", out_buf);
344 for (k = lead; k > 0; k--)
348 for (cp = *vp; *cp != '\0'; cp++) {
351 if (!strncmp(A.output_string, "Home a", 6) || !strncmp(A.output_string, "Business a", 10) || !strcmp(A.quipu_name, "multiLineDescription")) {
353 for (k = lead; k > 0; k--)
355 while (isspace(*(cp + 1)))
376 /* prints the DN's associated with an attribute */
382 char out_buf[MED_BUF_SIZE], *padding = NULL;
387 printf("->print_DN(%x)\n", A);
389 if (A.number_of_values == 0)
392 * Pad out the output string label so that it fills the
393 * whole field of length OUT_LABEL_LEN.
395 i = OUT_LABEL_LEN - strlen(A.output_string);
397 padding = (char *) Malloc((unsigned) (i + 1));
398 (void) memset(padding, ' ', i);
399 *(padding + i) = '\0';
400 sprintf(out_buf, "%s:%s", A.output_string, padding);
401 (void) Free(padding);
403 lead = strlen(out_buf) + 2;
406 format2((char *) my_ldap_dn2ufn(*vp), out_buf, (char *) NULL, 2, lead + 1, col_size);
407 for (vp++; *vp != NULL; vp++) {
408 format2((char *) my_ldap_dn2ufn(*vp), (char *) NULL, (char *) NULL, lead,
417 extern struct attribute attrlist[];
421 printf("->clear_entry()\n");
422 if ((debug & D_PRINT) && (Entry.name != NULL))
423 printf(" Clearing entry \"%s\"\n", Entry.name);
425 if (Entry.DN != NULL)
427 if (Entry.name != NULL)
429 Entry.may_join = FALSE;
430 Entry.subscriber_count = -1;
431 Entry.DN = Entry.name = NULL;
433 /* clear all of the values associated with all attributes */
434 for (i = 0; attrlist[i].quipu_name != NULL; i++) {
437 printf(" Clearing attribute \"%s\" -- ",
438 Entry.attrs[i].quipu_name);
440 if (Entry.attrs[i].values == NULL) {
443 printf(" no values, skipping\n");
449 printf(" freeing %d values\n",
450 Entry.attrs[i].number_of_values);
452 Entry.attrs[i].number_of_values = 0;
453 ldap_value_free(Entry.attrs[i].values);
454 Entry.attrs[i].values = (char **) NULL;
457 * Note: We do not clear either of the char * fields
458 * since they will always be applicable.
467 extern struct attribute attrlist[];
469 for (i = 0; attrlist[i].quipu_name != NULL; i++)
470 if (!strcasecmp(s, attrlist[i].quipu_name))
475 void initialize_attribute_strings()
478 extern struct entry Entry;
479 extern struct attribute attrlist[];
481 for (i = 0; attrlist[i].quipu_name != NULL; i++)
482 Entry.attrs[i].quipu_name = attrlist[i].quipu_name;
483 for (i = 0; attrlist[i].quipu_name != NULL; i++)
484 Entry.attrs[i].output_string = attrlist[i].output_string;
487 /* prints the URL/label pairs associated with an attribute */
493 char out_buf[MED_BUF_SIZE], *padding = NULL;
497 printf("->print_URL(%x)\n", A);
499 if (A.number_of_values == 0)
502 * Pad out the output string label so that it fills the
503 * whole field of length OUT_LABEL_LEN.
505 i = OUT_LABEL_LEN - strlen(A.output_string);
507 padding = (char *) Malloc((unsigned) (i + 1));
508 (void) memset(padding, ' ', i);
509 *(padding + i) = '\0';
510 sprintf(out_buf, "%s:%s", A.output_string, padding);
512 lead = strlen(out_buf) + 2;
515 print_one_URL(*vp, 2, out_buf, lead);
516 for (vp++; *vp != NULL; vp++)
517 print_one_URL(*vp, lead, (char *) NULL, lead);
523 print_one_URL(s, label_lead, tag, url_lead)
534 for (cp = s; !isspace(*cp) && (*cp != '\0'); cp++)
541 for (cp++; isspace(*cp); cp++)
545 cp = "(no description available)";
546 format2(cp, tag, (char *) NULL, label_lead, label_lead + 1, col_size);
547 for (i = url_lead + 2; i > 0; i--)
554 #define GET2BYTENUM( p ) (( *p - '0' ) * 10 + ( *(p+1) - '0' ))
557 time2text( char *ldtimestr, int dateonly )
560 char *p, *timestr, zone, *fmterr = "badly formatted time";
563 memset( (char *)&t, 0, sizeof( struct tm ));
564 if ( strlen( ldtimestr ) < 13 ) {
568 for ( p = ldtimestr; p - ldtimestr < 12; ++p ) {
569 if ( !isdigit( *p )) {
575 t.tm_year = GET2BYTENUM( p ); p += 2;
576 t.tm_mon = GET2BYTENUM( p ) - 1; p += 2;
577 t.tm_mday = GET2BYTENUM( p ); p += 2;
578 t.tm_hour = GET2BYTENUM( p ); p += 2;
579 t.tm_min = GET2BYTENUM( p ); p += 2;
580 t.tm_sec = GET2BYTENUM( p ); p += 2;
582 if (( zone = *p ) == 'Z' ) { /* GMT */
583 zone = '\0'; /* no need to indicate on screen, so we make it null */
586 gmttime = gtime( &t );
587 timestr = ctime( &gmttime );
589 timestr[ strlen( timestr ) - 1 ] = zone; /* replace trailing newline */
591 strcpy( timestr + 11, timestr + 20 );
595 return( strdup( timestr ) );
599 /* gtime.c - inverse gmtime */
603 /* gtime(): the inverse of localtime().
604 This routine was supplied by Mike Accetta at CMU many years ago.
608 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
612 (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
614 #define YEAR(y) ((y) >= 100 ? (y) : (y) + 1900)
618 static long gtime ( struct tm *tm )
627 register long result;
629 if ((sec = tm -> tm_sec) < 0 || sec > 59
630 || (mins = tm -> tm_min) < 0 || mins > 59
631 || (hour = tm -> tm_hour) < 0 || hour > 24
632 || (mday = tm -> tm_mday) < 1 || mday > 31
633 || (mon = tm -> tm_mon + 1) < 1 || mon > 12)
639 year = YEAR (tm -> tm_year);
642 for (i = 1970; i < year; i++)
643 result += dysize (i);
644 if (dysize (year) == 366 && mon >= 3)
647 result += dmsize[mon - 1];
649 result = 24 * result + hour;
650 result = 60 * result + mins;
651 result = 60 * result + sec;