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.
31 extern void * Malloc();
33 extern char * my_ldap_dn2ufn();
36 * When displaying entries, display only these attributes, and in this
39 static char *person_attr_print_order[] = {
43 "facsimileTelephoneNumber",
48 "multiLineDescription",
61 static char *group_attr_print_order[] = {
63 "facsimileTelephoneNumber",
66 "multiLineDescription",
89 register LDAPMessage *ep;
95 printf("->parse_answer(%x)\n", s);
102 printf(" Done clearing entry\n");
104 for (ep = ldap_first_entry(ld, s); ep != NULL; ep = ldap_next_entry(ld, ep)) {
107 printf(" Determining DN and name\n");
109 Entry.DN = ldap_get_dn(ld, ep);
112 printf(" DN = %s\n", Entry.DN);
114 rdns = ldap_explode_dn(Entry.DN, TRUE);
117 printf(" Name = %s\n", *rdns);
119 Entry.name = strdup(*rdns);
120 ldap_value_free(rdns);
121 for (ap = ldap_first_attribute(ld, ep, &cookie); ap != NULL; ap = ldap_next_attribute(ld, ep, cookie)) {
125 printf("parsing ap = %s\n", ap);
127 if ((idx = attr_to_index(ap)) < 0) {
128 printf(" Unknown attribute \"%s\"\n", ap);
131 add_value(&(Entry.attrs[idx]), ep, ap);
136 printf(" Done parsing entry\n");
140 add_value(attr, ep, ap)
141 struct attribute *attr;
146 char **vp, **tp, **avp;
150 printf("->add_value(%x, %x, %s)\n", attr, ep, ap);
152 vp = (char **) ldap_get_values(ld, ep, ap);
155 * Fill in the attribute structure for this attribute. This
156 * stores away the values (using strdup()) and the count. Terminate
157 * the list with a NULL pointer.
159 * attr->quipu_name has already been set during initialization.
161 if ((attr->number_of_values = ldap_count_values(vp)) > 0) {
162 attr->values = (char **) Malloc((unsigned) ((attr->number_of_values + 1) * sizeof(char *)));
165 for (i = 1, tp = vp; *tp != NULL; i++, tp++) {
168 printf(" value #%d %s\n", i, *tp);
171 * The 'name' field of the Entry structure already has
172 * has the first part of the DN copied into it. Thus,
173 * we don't need to save it away here again. Also, by
174 * tossing it away here, we make printing this info out
175 * a bit easier later.
177 if (!strcmp(ap, "cn") && !strcmp(*tp, Entry.name)) {
178 attr->number_of_values--;
181 *avp++ = strdup(*tp);
191 char is_a_group, **order;
192 char *sub_list[MAX_VALUES], buf[SMALL_BUF_SIZE];
193 extern int col_size, isaurl(), isadn();
194 static char *time2text();
198 printf("->print_an_entry()\n");
200 printf(" \"%s\"\n", Entry.name);
203 * If the entry is a group, find all of the subscribers to that
204 * group. A subscriber is an entry that *points* to a group entry,
205 * and a member is an entry that is included as part of a group
208 * We also need to select the appropriate output format here.
210 is_a_group = isgroup();
212 order = (char **) group_attr_print_order;
213 n = find_all_subscribers(sub_list, Entry.DN);
216 printf(" Group \"%s\" has %d subscribers\n",
221 order = (char **) person_attr_print_order;
223 for (i = 0; order[i] != NULL; i++) {
224 idx = attr_to_index(order[i]);
226 if (debug & D_PRINT) {
227 printf(" ATTR #%2d = %s [%s] (%d values)\n", i + 1,
228 Entry.attrs[idx].output_string,
229 Entry.attrs[idx].quipu_name,
230 Entry.attrs[idx].number_of_values);
235 if (Entry.attrs[idx].number_of_values == 0)
238 print_DN(Entry.attrs[idx]);
239 else if (isaurl(order[i]))
240 print_URL(Entry.attrs[idx]);
241 else if (isadate(order[i])) {
242 /* fix time and date, then call usual routine */
243 Entry.attrs[idx].values[0] =
244 time2text(Entry.attrs[idx].values[0], FALSE);
245 print_values(Entry.attrs[idx]);
248 print_values(Entry.attrs[idx]);
252 * If it is a group, then we should print the subscriber list (if
253 * there are any). If there are a lot of them, prompt the user
254 * before printing them.
256 if (is_a_group && (n > 0)) {
257 char *label = "Subscribers: ";
259 if (n > TOO_MANY_TO_PRINT) {
260 printf(" There are %d subscribers. Print them? ", n);
262 fetch_buffer(buf, sizeof(buf), stdin);
263 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
266 format2((char *) my_ldap_dn2ufn(sub_list[n - 1]), label, (char *) NULL, 2,
267 2 + strlen(label) + 1, col_size);
268 for (n--; n > 0; n--)
269 format2((char *) my_ldap_dn2ufn(sub_list[n - 1]), (char *) NULL,
270 (char *) NULL, 2 + strlen(label),
271 2 + strlen(label) + 2, col_size);
277 #define OUT_LABEL_LEN 20
279 /* prints the values associated with an attribute */
284 register char *cp, **vp;
285 char out_buf[MED_BUF_SIZE], *padding = NULL;
290 printf("->print_values(%x)\n", A);
292 if (A.number_of_values == 0)
294 if ((vp = A.values) == NULL)
298 * Pad out the output string label so that it fills the
299 * whole field of length OUT_LABEL_LEN.
302 i = OUT_LABEL_LEN - strlen(A.output_string);
304 printf("Output string for \"%s\" is too long. Maximum length is %d characters\n", A.quipu_name, OUT_LABEL_LEN);
307 if (isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values == 0)) {
308 A.output_string = "Members";
309 i = OUT_LABEL_LEN - strlen(A.output_string);
310 padding = (char *) Malloc((unsigned) (i + 1));
311 (void) memset(padding, ' ', i);
312 *(padding + i) = '\0';
313 sprintf(out_buf, "%s:%s", A.output_string, padding);
315 else if (!(isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values > 0))) {
316 padding = (char *) Malloc((unsigned) (i + 1));
317 (void) memset(padding, ' ', i);
318 *(padding + i) = '\0';
319 sprintf(out_buf, "%s:%s", A.output_string, padding);
322 * If this happens to be a group, then do not print the output
323 * string if we have already printed out some members.
325 else if (isgroup() && !strcmp(A.quipu_name, "mail") && (Entry.attrs[attr_to_index("member")].number_of_values > 0)) {
326 padding = (char *) Malloc((unsigned) (OUT_LABEL_LEN + 2));
327 (void) memset(padding, ' ', OUT_LABEL_LEN + 1);
328 *(padding + OUT_LABEL_LEN + 1) = '\0';
329 sprintf(out_buf, "%s", padding);
331 lead = strlen(out_buf) + 2;
333 printf(" %s", out_buf);
334 for (i = 0; *vp != NULL; i++, vp++) {
336 if (!strncmp(A.output_string, "Home a", 6) || !strncmp(A.output_string, "Business a", 10)) {
337 printf(" %s", out_buf);
340 for (k = lead; k > 0; k--)
344 for (cp = *vp; *cp != '\0'; cp++) {
347 if (!strncmp(A.output_string, "Home a", 6) || !strncmp(A.output_string, "Business a", 10) || !strcmp(A.quipu_name, "multiLineDescription")) {
349 for (k = lead; k > 0; k--)
351 while (isspace(*(cp + 1)))
372 /* prints the DN's associated with an attribute */
378 char out_buf[MED_BUF_SIZE], *padding = NULL;
383 printf("->print_DN(%x)\n", A);
385 if (A.number_of_values == 0)
388 * Pad out the output string label so that it fills the
389 * whole field of length OUT_LABEL_LEN.
391 i = OUT_LABEL_LEN - strlen(A.output_string);
393 padding = (char *) Malloc((unsigned) (i + 1));
394 (void) memset(padding, ' ', i);
395 *(padding + i) = '\0';
396 sprintf(out_buf, "%s:%s", A.output_string, padding);
397 (void) Free(padding);
399 lead = strlen(out_buf) + 2;
402 format2((char *) my_ldap_dn2ufn(*vp), out_buf, (char *) NULL, 2, lead + 1, col_size);
403 for (vp++; *vp != NULL; vp++) {
404 format2((char *) my_ldap_dn2ufn(*vp), (char *) NULL, (char *) NULL, lead,
413 extern struct attribute attrlist[];
417 printf("->clear_entry()\n");
418 if ((debug & D_PRINT) && (Entry.name != NULL))
419 printf(" Clearing entry \"%s\"\n", Entry.name);
421 if (Entry.DN != NULL)
423 if (Entry.name != NULL)
425 Entry.may_join = FALSE;
426 Entry.subscriber_count = -1;
427 Entry.DN = Entry.name = NULL;
429 /* clear all of the values associated with all attributes */
430 for (i = 0; attrlist[i].quipu_name != NULL; i++) {
433 printf(" Clearing attribute \"%s\" -- ",
434 Entry.attrs[i].quipu_name);
436 if (Entry.attrs[i].values == NULL) {
439 printf(" no values, skipping\n");
445 printf(" freeing %d values\n",
446 Entry.attrs[i].number_of_values);
448 Entry.attrs[i].number_of_values = 0;
449 ldap_value_free(Entry.attrs[i].values);
450 Entry.attrs[i].values = (char **) NULL;
453 * Note: We do not clear either of the char * fields
454 * since they will always be applicable.
463 extern struct attribute attrlist[];
465 for (i = 0; attrlist[i].quipu_name != NULL; i++)
466 if (!strcasecmp(s, attrlist[i].quipu_name))
471 void initialize_attribute_strings()
474 extern struct entry Entry;
475 extern struct attribute attrlist[];
477 for (i = 0; attrlist[i].quipu_name != NULL; i++)
478 Entry.attrs[i].quipu_name = attrlist[i].quipu_name;
479 for (i = 0; attrlist[i].quipu_name != NULL; i++)
480 Entry.attrs[i].output_string = attrlist[i].output_string;
483 /* prints the URL/label pairs associated with an attribute */
489 char out_buf[MED_BUF_SIZE], *padding = NULL;
493 printf("->print_URL(%x)\n", A);
495 if (A.number_of_values == 0)
498 * Pad out the output string label so that it fills the
499 * whole field of length OUT_LABEL_LEN.
501 i = OUT_LABEL_LEN - strlen(A.output_string);
503 padding = (char *) Malloc((unsigned) (i + 1));
504 (void) memset(padding, ' ', i);
505 *(padding + i) = '\0';
506 sprintf(out_buf, "%s:%s", A.output_string, padding);
508 lead = strlen(out_buf) + 2;
511 print_one_URL(*vp, 2, out_buf, lead);
512 for (vp++; *vp != NULL; vp++)
513 print_one_URL(*vp, lead, (char *) NULL, lead);
519 print_one_URL(s, label_lead, tag, url_lead)
530 for (cp = s; !isspace(*cp) && (*cp != '\0'); cp++)
537 for (cp++; isspace(*cp); cp++)
541 cp = "(no description available)";
542 format2(cp, tag, (char *) NULL, label_lead, label_lead + 1, col_size);
543 for (i = url_lead + 2; i > 0; i--)
550 #define GET2BYTENUM( p ) (( *p - '0' ) * 10 + ( *(p+1) - '0' ))
553 time2text( char *ldtimestr, int dateonly )
556 char *p, *timestr, zone, *fmterr = "badly formatted time";
560 memset( (char *)&t, 0, sizeof( struct tm ));
561 if ( strlen( ldtimestr ) < 13 ) {
565 for ( p = ldtimestr; p - ldtimestr < 12; ++p ) {
566 if ( !isdigit( *p )) {
572 t.tm_year = GET2BYTENUM( p ); p += 2;
573 t.tm_mon = GET2BYTENUM( p ) - 1; p += 2;
574 t.tm_mday = GET2BYTENUM( p ); p += 2;
575 t.tm_hour = GET2BYTENUM( p ); p += 2;
576 t.tm_min = GET2BYTENUM( p ); p += 2;
577 t.tm_sec = GET2BYTENUM( p ); p += 2;
579 if (( zone = *p ) == 'Z' ) { /* GMT */
580 zone = '\0'; /* no need to indicate on screen, so we make it null */
583 gmttime = gtime( &t );
584 timestr = ctime( &gmttime );
586 timestr[ strlen( timestr ) - 1 ] = zone; /* replace trailing newline */
588 strcpy( timestr + 11, timestr + 20 );
592 return( strdup( timestr ) );
596 /* gtime.c - inverse gmtime */
598 #if !defined( MACOS ) && !defined( _WIN32 ) && !defined( DOS )
599 #include <sys/time.h>
602 /* gtime(): the inverse of localtime().
603 This routine was supplied by Mike Accetta at CMU many years ago.
607 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
611 (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
613 #define YEAR(y) ((y) >= 100 ? (y) : (y) + 1900)
617 static long gtime ( struct tm *tm )
626 register long result;
628 if ((sec = tm -> tm_sec) < 0 || sec > 59
629 || (mins = tm -> tm_min) < 0 || mins > 59
630 || (hour = tm -> tm_hour) < 0 || hour > 24
631 || (mday = tm -> tm_mday) < 1 || mday > 31
632 || (mon = tm -> tm_mon + 1) < 1 || mon > 12)
638 year = YEAR (tm -> tm_year);
641 for (i = 1970; i < year; i++)
642 result += dysize (i);
643 if (dysize (year) == 366 && mon >= 3)
646 result += dmsize[mon - 1];
648 result = 24 * result + hour;
649 result = 60 * result + mins;
650 result = 60 * result + sec;