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