]> git.sur5r.net Git - openldap/blob - clients/ud/util.c
Apply patches from Hallvard and others to remove lint.
[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_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; 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 void
216 fatal( 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 int
227 isgroup( void )
228 {
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 void
257 format( char *str, int width, int lead )
258 {
259         char *s, *original, *leader = "";
260         register char *cp;
261
262 #ifdef DEBUG
263         if (debug & D_TRACE)
264                 printf("->format(%s, %d, %d)\n", str, width, lead);
265 #endif
266         if (lead >= width) {
267                 fprintf(stderr, "  Cannot format (%s, %d, %d)\n", str, width, lead);
268                 return;
269         }
270         if (lead > 0) {
271                 leader = (char *) Malloc((unsigned) (lead + 1));
272                 (void) memset(leader, ' ', lead);
273                 *(leader + lead) = '\0';
274         }
275
276         /*
277          *  Some compilers get really unhappy with this function since it
278          *  fiddles around with the first argument, which could be a string
279          *  constant.  We do a strdup() here so we can do whatever the hell
280          *  we want.
281          */
282         s = original = strdup(str);
283         for (;;) {
284                 if ((strlen(s) + lead) < width) {
285                         printf("%s%s\n", leader, s);
286                         Free(leader);
287                         Free(original);
288                         return; 
289                         /*NOTREACHED*/
290                 }
291                 cp = s + width - lead;
292                 while (!isspace(*cp) && (cp != s))
293                         cp--;
294                 *cp = '\0';
295                 while (isspace(*s))
296                         s++;
297                 printf("%s%s\n", leader, s);
298                 s = cp + 1;
299         }
300 }
301
302 /*
303  *  Print out the string 's' on a field of 'width' chracters.  The first line
304  *  should be indented 'first_indent' spaces, then followed by 'first_tag', 
305  *  and then followed by the first line of 's'.  Subsequent lines should be
306  *  indented 'indent' spaces, then followed by 'tag', and then followed by
307  *  subsequent lines of 's'.
308  */
309 void
310 format2(
311     char *s,
312     char *first_tag,
313     char *tag,
314     int first_indent,
315     int indent,
316     int width
317 )
318 {
319         char c, *fi, *i;
320         register char *cp;
321
322         if (first_tag == NULL)
323                 first_tag = "";
324         if (tag == NULL)
325                 tag = "";
326 #ifdef DEBUG
327         if (debug & D_TRACE)
328                 printf("format2(\"%s\", \"%s\", \"%s\", %1d, %1d, %1d)\n", s, 
329                                 first_tag, tag, first_indent, indent, width);
330 #endif
331
332         /* make sure the indents are sane */
333         if ((first_indent >= width) || (indent >= width)) {
334                 fprintf(stderr, "  Cannot format:  indent too large\n");
335                 return;
336         }
337
338         /* make the indentations */
339         if (first_indent > 0) {
340                 fi = (char *) Malloc((unsigned) (first_indent + 1));
341                 (void) memset(fi, ' ', first_indent);
342                 *(fi + first_indent) = '\0';
343         }
344         else
345                 fi = "";
346         if (indent > 0) {
347                 i = (char *) Malloc((unsigned) (indent + 1));
348                 (void) memset(i, ' ', indent);
349                 *(i + indent) = '\0';
350         }
351         else
352                 i = "";
353
354         /* now do the first line */
355         if ((strlen(s) + strlen(first_tag) + first_indent) < width) {
356                 printf("%s%s%s\n", fi, first_tag, s);
357                 Free(fi);
358                 Free(i);
359                 return; 
360                 /*NOTREACHED*/
361         }
362
363         /*
364          *  's' points to the beginning of the string we want to print.
365          *  We point 'cp' to the end of the maximum amount of text we
366          *  can print (i.e., total width less the indentation and the
367          *  length of the tag).  Once we have set 'cp' initially we
368          *  back it up to the first space character.
369          */
370         cp = s + width - first_indent - strlen(first_tag);
371         while (!isspace(*cp) && (cp != s))
372                 cp--;
373
374         /*
375          *  Once there, we change that space character to a null, print the
376          *  string, and then restore the space character.
377          */
378         c = *cp;
379         *cp = '\0';
380         printf("%s%s%s\n", fi, first_tag, s);
381         *cp = c;
382
383         /*
384          *  Since 'cp' may have been set to a space initially (and so no
385          *  back-tracking was performed), it could have a space after it
386          *  as well.  We should gobble up all of these since we don't want
387          *  unexpected leading blanks.
388          */  
389         for (s = cp + 1; isspace(*s); s++)
390                 ;
391
392         /* now do all of the other lines */
393         for (;;) {
394                 if ((strlen(s) + strlen(tag) + indent) < width) {
395                         printf("%s%s%s\n", i, tag, s);
396                         Free(fi);
397                         Free(i);
398                         return; 
399                         /*NOTREACHED*/
400                 }
401                 cp = s + width - indent - strlen(tag);
402                 while (!isspace(*cp) && (cp != s))
403                         cp--;
404                 c = *cp;
405                 *cp = '\0';
406                 printf("%s%s%s\n", i, tag, s);
407                 s = cp + 1;
408                 *cp = c;                        /* don't mess up 's' */
409         }
410 }
411
412 #define IN_A_QUOTE   0
413 #define OUT_OF_QUOTE 1
414
415 char *
416 strip_ignore_chars( char *cp )
417 {
418         int had_a_comma = FALSE;
419         int flag = OUT_OF_QUOTE;
420         register char *rcp, *cp1;
421         char *tmp;
422
423 #ifdef DEBUG
424         if (debug & D_TRACE)
425                 printf("strip_ignore_chars(%s)\n", cp);
426 #endif
427         for (rcp = cp; *rcp != '\0'; rcp++)
428                 if (isignorechar(*rcp) || (*rcp == '"'))
429                         break;
430         if (*rcp == '\0')
431                 return(cp);
432
433         cp1 = tmp = (char *) Malloc((unsigned) strlen(cp));
434         for (rcp = cp; *rcp != '\0'; rcp++) {
435                 /* toss quotes and flip the flag */
436                 if (*rcp == '"')
437                         flag = OUT_OF_QUOTE - flag;
438                 else if (isignorechar(*rcp)) {
439                         if (flag == OUT_OF_QUOTE)
440                                 *cp1++ = ' ';
441                         else
442                                 *cp1++ = *rcp;
443                 }
444                 else if (*rcp == ',') {
445                         *cp1++ = *rcp;
446                         had_a_comma = TRUE;
447                 }
448                 else 
449                         *cp1++ = *rcp;
450         }
451         *cp1 = '\0';
452
453         /* re-quote the name if it had a comma in it */
454         if (had_a_comma == TRUE) {
455                 rcp = cp1 = (char *) Malloc((unsigned) (strlen(tmp) + 3));
456                 *rcp++ = '"';
457                 *rcp = '\0';
458                 strcat(rcp, tmp);
459                 strcat(rcp, "\"");
460                 Free(tmp);
461                 tmp = cp1;
462         }
463         return(tmp);
464 }
465
466 char *
467 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 *
478 friendly_name( 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 int
493 isauniqname( 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 int
510 isadn( char *s )
511 {
512         register int i;
513
514         for (i = 0; attrlist[i].quipu_name != NULL; i++)
515                 if (!strcasecmp(s, attrlist[i].quipu_name))
516                         break;
517         if (attrlist[i].flags & ATTR_FLAG_IS_A_DN)
518                 return(TRUE);
519         return(FALSE);
520 }
521
522 char *
523 my_ldap_dn2ufn( char *s )
524 {
525         register char **cpp;
526         static char short_DN[BUFSIZ];
527
528         if (strstr(s, UD_BASE) == NULL)
529                 return(ldap_dn2ufn(s));
530         cpp = ldap_explode_dn(s, TRUE);
531         sprintf(short_DN, "%s, %s", *cpp, *(cpp + 1));
532         ldap_value_free(cpp);
533         return(short_DN);
534 }
535
536 /* return TRUE if this attribute should be printed as a URL */
537 int
538 isaurl( char *s )
539 {
540         register int i;
541
542         for (i = 0; attrlist[i].quipu_name != NULL; i++)
543                 if (!strcasecmp(s, attrlist[i].quipu_name))
544                         break;
545         if (attrlist[i].flags & ATTR_FLAG_IS_A_URL)
546                 return(TRUE);
547         return(FALSE);
548 }
549
550 /* return TRUE if this attribute should be printed as a date and time */
551 int
552 isadate( char *s )
553 {
554         register int i;
555
556         for (i = 0; attrlist[i].quipu_name != NULL; i++)
557                 if (!strcasecmp(s, attrlist[i].quipu_name))
558                         break;
559         if (attrlist[i].flags & ATTR_FLAG_IS_A_DATE)
560                 return(TRUE);
561         return(FALSE);
562 }
563
564 void *
565 Malloc( unsigned int size )
566 {
567         void *void_ptr;
568
569         void_ptr = (void *) malloc(size);
570         if (void_ptr == NULL) {
571                 perror("malloc");
572                 exit(-1);
573                 /*NOTREACHED*/
574         }
575         return(void_ptr);
576 }
577
578 void
579 Free( void *ptr )
580 {
581 #if 0
582         if (free(ptr) < 0) {
583                 perror("free");
584                 exit(-1);
585                 /*NOTREACHED*/
586         }
587 #else
588         free(ptr);
589 #endif
590         return;
591 }
592
593 char *
594 nextstr( char *s )
595 {
596         while (isspace(*s) && (*s != '\0'))
597                 s++;
598         if (s == NULL)
599                 return(NULL);
600         if (*s == '\0')
601                 return(NULL);
602         return(s);
603 }
604
605 void
606 free_mod_struct( LDAPMod *modp )
607 {
608         if (modp->mod_values != NULL)
609                 (void) ldap_value_free(modp->mod_values);
610         Free(modp->mod_type);
611         Free(modp);
612 }
613
614 void
615 StrFreeDup( char **ptr, char *new_value )
616 {
617         if (*ptr != NULL)
618                 Free(*ptr);
619         if (new_value == NULL)
620                 *ptr = NULL;
621         else
622                 *ptr = strdup(new_value);
623 }
624
625
626 int
627 confirm_action( char *msg )
628
629         char    tmp[SMALL_BUF_SIZE];
630         int     i;
631
632         if ( msg != NULL ) {
633                 putchar( '\n' );
634                 format( msg, 75, 2 );
635         }
636
637         printf("\n  Is this OK? ");
638         fflush(stdout);
639         tmp[0] = '\0';
640         fetch_buffer(tmp, sizeof(tmp), stdin);
641         i = strlen(tmp);
642         return( i > 0 &&
643             ( !strncasecmp(tmp, "YES", i) || !strncasecmp(tmp, "OK", i)));
644 }