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