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