]> git.sur5r.net Git - openldap/blob - clients/ud/util.c
merged with autoconf branch
[openldap] / clients / ud / util.c
1 /*
2  * Copyright (c) 1992, 1993  Regents of the University of Michigan.
3  * All rights reserved.
4  *
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.
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16 #include <stdlib.h>
17
18 #include <ac/ctype.h>
19 #include <ac/errno.h>
20 #include <ac/signal.h>
21 #include <ac/string.h>
22 #include <ac/termios.h>
23 #include <ac/time.h>
24 #include <ac/unistd.h>
25
26 #include <lber.h>
27 #include <ldap.h>
28 #include <ldapconfig.h>
29
30 #include "ud.h"
31
32 #ifdef DEBUG
33 extern int debug;
34 #endif
35
36 char * mygetpass(prompt)
37 char *prompt;
38 {
39 #if defined(DOS) || defined(VMS)
40         static char buf[256];
41         int i, c;
42
43 #ifdef DEBUG
44         if (debug & D_TRACE)
45                 printf("->mygetpass(%s)\n", prompt);
46 #endif
47         printf("%s", prompt);
48         i = 0;
49         while ( (c = getch()) != EOF && c != '\n' && c != '\r' )
50                 buf[i++] = c;
51         if ( c == EOF )
52                 return( NULL );
53         buf[i] = '\0';
54         return (buf);
55 #else
56         int no_pass = 0;
57         char i, j, k;
58         TERMIO_TYPE ttyb;
59         TERMFLAG_TYPE flags;
60         static char pbuf[513];
61         register char *p;
62         register int c;
63         FILE *fi;
64         RETSIGTYPE (*sig)();
65
66 #ifdef DEBUG
67         if (debug & D_TRACE)
68                 printf("->mygetpass(%s)\n", prompt);
69 #endif
70         /*
71          *  Stolen from the getpass() routine.  Can't use the plain
72          *  getpass() for two reasons.  One is that LDAP passwords
73          *  can be really, really long - much longer than 8 chars.
74          *  The second is that we like to make this client available
75          *  out of inetd via a Merit asynch port, and we need to be
76          *  able to do telnet control codes to turn on and off line
77          *  blanking.
78          */
79         if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
80                 fi = stdin;
81         else
82                 setbuf(fi, (char *)NULL);
83         sig = SIGNAL (SIGINT, SIG_IGN);
84         if (fi != stdin) {
85                 if (GETATTR(fileno(fi), &ttyb) < 0)
86                         perror("GETATTR");
87         }
88         flags = GETFLAGS( ttyb );
89         SETFLAGS( ttyb, flags & ~ECHO );
90         if (fi != stdin) {
91                 if (SETATTR(fileno(fi), &ttyb) < 0)
92                         perror("SETATTR");
93         }
94
95         /*  blank the line if through Merit */
96         if (fi == stdin) {
97                 printf("%c%c%c", 255, 251, 1);
98                 fflush(stdout);
99                 (void) scanf("%c%c%c", &i, &j, &k);
100                 fflush(stdin);
101         }
102
103         /* fetch the password */
104         fprintf(stdout, "%s", prompt); 
105         fflush(stdout);
106         for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) {
107                 if (c == '\r')
108                         break;
109                 if (p < &pbuf[512])
110                         *p++ = c;
111         }
112         if (c == EOF)
113                 no_pass = 1;
114         else {
115                 *p = '\0';
116                 if (*(p - 1) == '\r')
117                         *(p - 1) = '\0';
118         }
119
120         /*  unblank the line if through Merit */
121         if (fi == stdin) {
122                 printf("%c%c%c", 255, 252, 1);
123                 fflush(stdout);
124                 (void) scanf("%c%c%c", &i, &j, &k);
125                 fflush(stdin);
126                 printf("\n"); fflush(stdout);
127         }
128         fprintf(stdout, "\n"); 
129         fflush(stdout);
130
131         /* tidy up */
132         SETFLAGS( ttyb, flags );
133         if (fi != stdin) {
134                 if (SETATTR(fileno(fi), &ttyb) < 0)
135                         perror("SETATTR");
136         }
137         (void) SIGNAL (SIGINT, sig);
138         if (fi != stdin)
139                 (void) fclose(fi);
140         else
141                 i = getchar();
142         if (no_pass)
143                 return(NULL);
144         return(pbuf);
145 #endif /* DOS */
146 }
147
148 void printbase(lead, s)
149 char *lead, *s;
150 {
151         register char **cp;
152         char **rdns;
153         char * friendly_name();
154
155 #ifdef DEBUG
156         if (debug & D_TRACE)
157                 printf("->printbase(%s, %s)\n", lead, s);
158 #endif
159         if (s == NULL) {
160                 printf("%sroot\n", lead);
161                 return;
162         }
163         printf("%s", lead);
164         rdns = ldap_explode_dn(s, TRUE);
165         for (cp = rdns; ; ) {
166                 printf("%s", friendly_name(*cp));
167                 cp++;
168                 if (*cp == NULL) {
169                         printf("\n");
170                         break;
171                 }
172                 else
173                         printf(", ");
174         }
175         ldap_value_free(rdns);
176         return;
177 }
178
179 fetch_buffer(buffer, length, where)
180 char *buffer;
181 int length;
182 FILE *where;
183 {
184         extern LDAP *ld;
185         register int i;
186         char *p;
187
188 #ifdef DEBUG
189         if (debug & D_TRACE)
190                 printf("->fetch_buffer(%x, %d, %x)\n", buffer, length, where);
191 #endif
192         /*
193          *  Fetch a buffer and strip off any leading or trailing non-printing
194          *  characters, namely newlines and carriage returns.
195          */
196         if (fgets(buffer, length, where) == NULL) {
197                 if (feof(where))
198                         errno = 0;       /* so fatal() doesn't bitch */
199                 fatal("fgets");
200         }
201         for (i = strlen(buffer) - 1; i >= 0 && !isprint(buffer[i]); i--)
202                 buffer[i] = '\0';
203
204         p = buffer;
205         while ( *p != '\0' ) {
206                 if ( isprint( *p )) {
207                         ++p;
208                 } else {
209                         strcpy( p, p + 1 ); 
210                 }
211         }
212
213 }
214
215 fatal(s)
216 char *s;
217 {
218         if (errno != 0)
219                 perror(s);
220 #ifdef HAVE_KERBEROS
221         destroy_tickets();
222 #endif
223         exit(-1);
224 }
225
226 isgroup()
227 {
228         extern struct entry Entry;
229         char **vp;
230         register int i;
231         int group = FALSE;
232
233 #ifdef DEBUG
234         if (debug & D_TRACE)
235                 printf("->isgroup()\n");
236 #endif
237         if ((i = attr_to_index("objectClass")) == -1)
238                 return(FALSE);
239         vp = Entry.attrs[i].values;
240         for (i = 0; *vp != NULL; vp++) {
241 #ifdef DEBUG
242                 i++;
243                 if (debug & D_GROUPS)
244                         printf("class #%1d: (%s)\n", i, *vp);
245 #endif
246                 if (!strcmp(*vp, "rfc822MailGroup"))
247                         group = TRUE;
248         }
249         return(group);
250 }
251
252 /*
253  *  Print out the string 's' on a field of 'width' chracters.  Each line
254  *  should be indented 'lead' characters.
255  */
256 format(str, width, lead)
257 char *str;
258 int width, lead;
259 {
260         char *s, *original, *leader = "";
261         register char *cp;
262         void * Malloc();
263         void Free();
264
265 #ifdef DEBUG
266         if (debug & D_TRACE)
267                 printf("->format(%s, %d, %d)\n", str, width, lead);
268 #endif
269         if (lead >= width) {
270                 fprintf(stderr, "  Cannot format (%s, %d, %d)\n", str, width, lead);
271                 return;
272         }
273         if (lead > 0) {
274                 leader = (char *) Malloc((unsigned) (lead + 1));
275                 (void) memset(leader, ' ', lead);
276                 *(leader + lead) = '\0';
277         }
278
279         /*
280          *  Some compilers get really unhappy with this function since it
281          *  fiddles around with the first argument, which could be a string
282          *  constant.  We do a strdup() here so we can do whatever the hell
283          *  we want.
284          */
285         s = original = strdup(str);
286         for (;;) {
287                 if ((strlen(s) + lead) < width) {
288                         printf("%s%s\n", leader, s);
289                         Free(leader);
290                         Free(original);
291                         return; 
292                         /*NOTREACHED*/
293                 }
294                 cp = s + width - lead;
295                 while (!isspace(*cp) && (cp != s))
296                         cp--;
297                 *cp = '\0';
298                 while (isspace(*s))
299                         s++;
300                 printf("%s%s\n", leader, s);
301                 s = cp + 1;
302         }
303 }
304
305 /*
306  *  Print out the string 's' on a field of 'width' chracters.  The first line
307  *  should be indented 'first_indent' spaces, then followed by 'first_tag', 
308  *  and then followed by the first line of 's'.  Subsequent lines should be
309  *  indented 'indent' spaces, then followed by 'tag', and then followed by
310  *  subsequent lines of 's'.
311  */
312 format2(s, first_tag, tag, first_indent, indent, width)
313 char *s, *first_tag, *tag;
314 int first_indent, indent, width;
315 {
316         char c, *fi, *i;
317         register char *cp;
318         void * Malloc();
319         void Free();
320
321         if (first_tag == NULL)
322                 first_tag = "";
323         if (tag == NULL)
324                 tag = "";
325 #ifdef DEBUG
326         if (debug & D_TRACE)
327                 printf("format2(\"%s\", \"%s\", \"%s\", %1d, %1d, %1d)\n", s, 
328                                 first_tag, tag, first_indent, indent, width);
329 #endif
330
331         /* make sure the indents are sane */
332         if ((first_indent >= width) || (indent >= width)) {
333                 fprintf(stderr, "  Cannot format:  indent too large\n");
334                 return;
335         }
336
337         /* make the indentations */
338         if (first_indent > 0) {
339                 fi = (char *) Malloc((unsigned) (first_indent + 1));
340                 (void) memset(fi, ' ', first_indent);
341                 *(fi + first_indent) = '\0';
342         }
343         else
344                 fi = "";
345         if (indent > 0) {
346                 i = (char *) Malloc((unsigned) (indent + 1));
347                 (void) memset(i, ' ', indent);
348                 *(i + indent) = '\0';
349         }
350         else
351                 i = "";
352
353         /* now do the first line */
354         if ((strlen(s) + strlen(first_tag) + first_indent) < width) {
355                 printf("%s%s%s\n", fi, first_tag, s);
356                 Free(fi);
357                 Free(i);
358                 return; 
359                 /*NOTREACHED*/
360         }
361
362         /*
363          *  's' points to the beginning of the string we want to print.
364          *  We point 'cp' to the end of the maximum amount of text we
365          *  can print (i.e., total width less the indentation and the
366          *  length of the tag).  Once we have set 'cp' initially we
367          *  back it up to the first space character.
368          */
369         cp = s + width - first_indent - strlen(first_tag);
370         while (!isspace(*cp) && (cp != s))
371                 cp--;
372
373         /*
374          *  Once there, we change that space character to a null, print the
375          *  string, and then restore the space character.
376          */
377         c = *cp;
378         *cp = '\0';
379         printf("%s%s%s\n", fi, first_tag, s);
380         *cp = c;
381
382         /*
383          *  Since 'cp' may have been set to a space initially (and so no
384          *  back-tracking was performed), it could have a space after it
385          *  as well.  We should gobble up all of these since we don't want
386          *  unexpected leading blanks.
387          */  
388         for (s = cp + 1; isspace(*s); s++)
389                 ;
390
391         /* now do all of the other lines */
392         for (;;) {
393                 if ((strlen(s) + strlen(tag) + indent) < width) {
394                         printf("%s%s%s\n", i, tag, s);
395                         Free(fi);
396                         Free(i);
397                         return; 
398                         /*NOTREACHED*/
399                 }
400                 cp = s + width - indent - strlen(tag);
401                 while (!isspace(*cp) && (cp != s))
402                         cp--;
403                 c = *cp;
404                 *cp = '\0';
405                 printf("%s%s%s\n", i, tag, s);
406                 s = cp + 1;
407                 *cp = c;                        /* don't mess up 's' */
408         }
409 }
410
411 #define IN_A_QUOTE   0
412 #define OUT_OF_QUOTE 1
413
414 char * strip_ignore_chars(cp)
415 char *cp;
416 {
417         int had_a_comma = FALSE;
418         int flag = OUT_OF_QUOTE;
419         register char *rcp, *cp1;
420         char *tmp;
421         void * Malloc();
422         void Free();
423
424 #ifdef DEBUG
425         if (debug & D_TRACE)
426                 printf("strip_ignore_chars(%s)\n", cp);
427 #endif
428         for (rcp = cp; *rcp != '\0'; rcp++)
429                 if (isignorechar(*rcp) || (*rcp == '"'))
430                         break;
431         if (*rcp == '\0')
432                 return(cp);
433
434         cp1 = tmp = (char *) Malloc((unsigned) strlen(cp));
435         for (rcp = cp; *rcp != '\0'; rcp++) {
436                 /* toss quotes and flip the flag */
437                 if (*rcp == '"')
438                         flag = OUT_OF_QUOTE - flag;
439                 else if (isignorechar(*rcp)) {
440                         if (flag == OUT_OF_QUOTE)
441                                 *cp1++ = ' ';
442                         else
443                                 *cp1++ = *rcp;
444                 }
445                 else if (*rcp == ',') {
446                         *cp1++ = *rcp;
447                         had_a_comma = TRUE;
448                 }
449                 else 
450                         *cp1++ = *rcp;
451         }
452         *cp1 = '\0';
453
454         /* re-quote the name if it had a comma in it */
455         if (had_a_comma == TRUE) {
456                 rcp = cp1 = (char *) Malloc((unsigned) (strlen(tmp) + 3));
457                 *rcp++ = '"';
458                 *rcp = '\0';
459                 strcat(rcp, tmp);
460                 strcat(rcp, "\"");
461                 Free(tmp);
462                 tmp = cp1;
463         }
464         return(tmp);
465 }
466
467 char * code_to_str(int i)
468 {
469         switch(i) {
470         case LDAP_MOD_ADD : return("ADD");
471         case LDAP_MOD_DELETE : return("DELETE");
472         case LDAP_MOD_REPLACE : return("REPLACE");
473         default : return("?????");
474         }
475 }
476
477 char * friendly_name(s)
478 char *s;
479 {
480         static FriendlyMap *map = NULL;
481         static char *cp;
482
483         cp = ldap_friendly_name(FRIENDLYFILE, s, &map);
484         if (cp == NULL)
485                 return(s);
486         return(cp);
487 }
488
489 #ifdef UOFM
490
491 /* return TRUE if s has the syntax of a uniqname */
492 isauniqname(s)
493 char *s;
494 {
495         int i = strlen(s);
496
497         if ((i < 3) || (i > 8))         /* uniqnames are 3-8 chars */
498                 return(FALSE);
499         if (!isalpha(*s))               /* uniqnames begin with a letter */
500                 return(FALSE);
501         for ( ; *s != '\0'; s++)        /* uniqnames are alphanumeric */
502                 if (!isalnum(*s))
503                         return(FALSE);
504         return(TRUE);
505 }
506 #endif
507
508 /* return TRUE if this attribute should be printed as a DN */
509 isadn(s)
510 char *s;
511 {
512         register int i;
513         extern struct attribute attrlist[];
514
515         for (i = 0; attrlist[i].quipu_name != NULL; i++)
516                 if (!strcasecmp(s, attrlist[i].quipu_name))
517                         break;
518         if (attrlist[i].flags & ATTR_FLAG_IS_A_DN)
519                 return(TRUE);
520         return(FALSE);
521 }
522
523 char * my_ldap_dn2ufn(s)
524 char *s;
525 {
526         register char **cpp;
527         static char short_DN[BUFSIZ];
528
529         if (strstr(s, UD_BASE) == NULL)
530                 return(ldap_dn2ufn(s));
531         cpp = ldap_explode_dn(s, TRUE);
532         sprintf(short_DN, "%s, %s", *cpp, *(cpp + 1));
533         ldap_value_free(cpp);
534         return(short_DN);
535 }
536
537 /* return TRUE if this attribute should be printed as a URL */
538 isaurl(s)
539 char *s;
540 {
541         register int i;
542         extern struct attribute attrlist[];
543
544         for (i = 0; attrlist[i].quipu_name != NULL; i++)
545                 if (!strcasecmp(s, attrlist[i].quipu_name))
546                         break;
547         if (attrlist[i].flags & ATTR_FLAG_IS_A_URL)
548                 return(TRUE);
549         return(FALSE);
550 }
551
552 /* return TRUE if this attribute should be printed as a date and time */
553 isadate(s)
554 char *s;
555 {
556         register int i;
557         extern struct attribute attrlist[];
558
559         for (i = 0; attrlist[i].quipu_name != NULL; i++)
560                 if (!strcasecmp(s, attrlist[i].quipu_name))
561                         break;
562         if (attrlist[i].flags & ATTR_FLAG_IS_A_DATE)
563                 return(TRUE);
564         return(FALSE);
565 }
566
567 void * Malloc(size)
568 unsigned int size;
569 {
570         void *void_ptr;
571
572         void_ptr = (void *) malloc(size);
573         if (void_ptr == NULL) {
574                 perror("malloc");
575                 exit(-1);
576                 /*NOTREACHED*/
577         }
578         return(void_ptr);
579 }
580
581 void Free(ptr)
582 char *ptr;
583 {
584 #ifndef STDC_HEADERS
585         if (free(ptr) < 0) {
586                 perror("free");
587                 exit(-1);
588                 /*NOTREACHED*/
589         }
590 #else
591         free(ptr);
592 #endif
593         return;
594 }
595
596 char * nextstr(s)
597 char *s;
598 {
599         while (isspace(*s) && (*s != '\0'))
600                 s++;
601         if (s == NULL)
602                 return(NULL);
603         if (*s == '\0')
604                 return(NULL);
605         return(s);
606 }
607
608 void free_mod_struct(modp)
609 LDAPMod *modp;
610 {
611         void Free();
612
613         if (modp->mod_values != NULL)
614                 (void) ldap_value_free(modp->mod_values);
615         Free(modp->mod_type);
616         Free(modp);
617 }
618
619 void StrFreeDup(ptr, new_value)
620 char **ptr, *new_value;
621 {
622         void Free();
623
624         if (*ptr != NULL)
625                 Free(*ptr);
626         if (new_value == NULL)
627                 *ptr = NULL;
628         else
629                 *ptr = strdup(new_value);
630 }
631
632
633 confirm_action( msg )
634         char    *msg;
635
636         char    tmp[SMALL_BUF_SIZE];
637         int     i;
638
639         if ( msg != NULL ) {
640                 putchar( '\n' );
641                 format( msg, 75, 2 );
642         }
643
644         printf("\n  Is this OK? ");
645         fflush(stdout);
646         tmp[0] = '\0';
647         fetch_buffer(tmp, sizeof(tmp), stdin);
648         i = strlen(tmp);
649         return( i > 0 &&
650             ( !strncasecmp(tmp, "YES", i) || !strncasecmp(tmp, "OK", i)));
651 }