]> git.sur5r.net Git - openldap/blob - clients/ud/util.c
2efd2895d666f7ca457662f9d2eb638d78b14ef3
[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
17 #include <ac/stdlib.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
30 #include "ldap_defaults.h"
31 #include "ud.h"
32
33 void
34 printbase( char *lead, char *s )
35 {
36         register char **cp;
37         char **rdns;
38
39 #ifdef DEBUG
40         if (debug & D_TRACE)
41                 printf("->printbase(%s, %s)\n", lead, s);
42 #endif
43         if (s == NULL) {
44                 printf("%sroot\n", lead);
45                 return;
46         }
47         printf("%s", lead);
48         rdns = ldap_explode_dn(s, TRUE);
49         for (cp = rdns; ; ) {
50                 printf("%s", friendly_name(*cp));
51                 cp++;
52                 if (*cp == NULL) {
53                         printf("\n");
54                         break;
55                 }
56                 else
57                         printf(", ");
58         }
59         ldap_value_free(rdns);
60         return;
61 }
62
63 void
64 fetch_buffer( char *buffer, int length, FILE *where )
65 {
66         register int i;
67         char *p;
68
69 #ifdef DEBUG
70         if (debug & D_TRACE)
71                 printf("->fetch_buffer(%x, %d, %x)\n", buffer, length, where);
72 #endif
73         /*
74          *  Fetch a buffer and strip off any leading or trailing non-printing
75          *  characters, namely newlines and carriage returns.
76          */
77         if (fgets(buffer, length, where) == NULL) {
78                 if (feof(where))
79                         errno = 0;       /* so fatal() doesn't bitch */
80                 fatal("fgets");
81         }
82         for (i = strlen(buffer) - 1;
83              i >= 0 && !isprint((unsigned char) buffer[i]); i--)
84                 buffer[i] = '\0';
85
86         p = buffer;
87         while ( *p != '\0' ) {
88                 if ( isprint( (unsigned char) *p )) {
89                         ++p;
90                 } else {
91                         SAFEMEMCPY( p, p + 1, strlen( p + 1 ) + 1 ); 
92                 }
93         }
94
95 }
96
97 void
98 fatal( char *s )
99 {
100         if (errno != 0)
101                 perror(s);
102 #ifdef HAVE_KERBEROS
103         destroy_tickets();
104 #endif
105         exit( EXIT_FAILURE );
106 }
107
108 int
109 isgroup( void )
110 {
111         char **vp;
112         register int i;
113         int group = FALSE;
114
115 #ifdef DEBUG
116         if (debug & D_TRACE)
117                 printf("->isgroup()\n");
118 #endif
119         if ((i = attr_to_index("objectClass")) == -1)
120                 return(FALSE);
121         vp = Entry.attrs[i].values;
122         for (i = 0; *vp != NULL; vp++) {
123 #ifdef DEBUG
124                 i++;
125                 if (debug & D_GROUPS)
126                         printf("class #%1d: (%s)\n", i, *vp);
127 #endif
128                 if (!strcmp(*vp, "rfc822MailGroup"))
129                         group = TRUE;
130         }
131         return(group);
132 }
133
134 /*
135  *  Print out the string 's' on a field of 'width' chracters.  Each line
136  *  should be indented 'lead' characters.
137  */
138 void
139 format( char *str, int width, int lead )
140 {
141         char *s, *original, *leader = "";
142         register char *cp;
143
144 #ifdef DEBUG
145         if (debug & D_TRACE)
146                 printf("->format(%s, %d, %d)\n", str, width, lead);
147 #endif
148         if (lead >= width) {
149                 fprintf(stderr, "  Cannot format (%s, %d, %d)\n", str, width, lead);
150                 return;
151         }
152         if (lead > 0) {
153                 leader = (char *) Malloc((unsigned) (lead + 1));
154                 (void) memset(leader, ' ', lead);
155                 *(leader + lead) = '\0';
156         }
157
158         /*
159          *  Some compilers get really unhappy with this function since it
160          *  fiddles around with the first argument, which could be a string
161          *  constant.  We do a strdup() here so we can do whatever the hell
162          *  we want.
163          */
164         s = original = strdup(str);
165         for (;;) {
166                 if (((int) strlen(s) + lead) < width) {
167                         printf("%s%s\n", leader, s);
168                         Free(leader);
169                         Free(original);
170                         return; 
171                         /*NOTREACHED*/
172                 }
173                 cp = s + width - lead;
174                 while (!isspace((unsigned char)*cp) && (cp != s))
175                         cp--;
176                 *cp = '\0';
177                 while (isspace((unsigned char)*s))
178                         s++;
179                 printf("%s%s\n", leader, s);
180                 s = cp + 1;
181         }
182 }
183
184 /*
185  *  Print out the string 's' on a field of 'width' chracters.  The first line
186  *  should be indented 'first_indent' spaces, then followed by 'first_tag', 
187  *  and then followed by the first line of 's'.  Subsequent lines should be
188  *  indented 'indent' spaces, then followed by 'tag', and then followed by
189  *  subsequent lines of 's'.
190  */
191 void
192 format2(
193     char *s,
194     char *first_tag,
195     char *tag,
196     int first_indent,
197     int indent,
198     int width
199 )
200 {
201         char c, *fi, *i;
202         register char *cp;
203
204         if (first_tag == NULL)
205                 first_tag = "";
206         if (tag == NULL)
207                 tag = "";
208 #ifdef DEBUG
209         if (debug & D_TRACE)
210                 printf("format2(\"%s\", \"%s\", \"%s\", %1d, %1d, %1d)\n", s, 
211                                 first_tag, tag, first_indent, indent, width);
212 #endif
213
214         /* make sure the indents are sane */
215         if ((first_indent >= width) || (indent >= width)) {
216                 fprintf(stderr, "  Cannot format:  indent too large\n");
217                 return;
218         }
219
220         /* make the indentations */
221         if (first_indent > 0) {
222                 fi = (char *) Malloc((unsigned) (first_indent + 1));
223                 (void) memset(fi, ' ', first_indent);
224                 *(fi + first_indent) = '\0';
225         }
226         else
227                 fi = "";
228         if (indent > 0) {
229                 i = (char *) Malloc((unsigned) (indent + 1));
230                 (void) memset(i, ' ', indent);
231                 *(i + indent) = '\0';
232         }
233         else
234                 i = "";
235
236         /* now do the first line */
237         if (((int) strlen(s) + (int) strlen(first_tag) + first_indent) < width) {
238                 printf("%s%s%s\n", fi, first_tag, s);
239                 Free(fi);
240                 Free(i);
241                 return; 
242                 /*NOTREACHED*/
243         }
244
245         /*
246          *  's' points to the beginning of the string we want to print.
247          *  We point 'cp' to the end of the maximum amount of text we
248          *  can print (i.e., total width less the indentation and the
249          *  length of the tag).  Once we have set 'cp' initially we
250          *  back it up to the first space character.
251          */
252         cp = s + width - first_indent - strlen(first_tag);
253         while (!isspace((unsigned char)*cp) && (cp != s))
254                 cp--;
255
256         /*
257          *  Once there, we change that space character to a null, print the
258          *  string, and then restore the space character.
259          */
260         c = *cp;
261         *cp = '\0';
262         printf("%s%s%s\n", fi, first_tag, s);
263         *cp = c;
264
265         /*
266          *  Since 'cp' may have been set to a space initially (and so no
267          *  back-tracking was performed), it could have a space after it
268          *  as well.  We should gobble up all of these since we don't want
269          *  unexpected leading blanks.
270          */  
271         for (s = cp + 1; isspace((unsigned char)*s); s++)
272                 ;
273
274         /* now do all of the other lines */
275         for (;;) {
276                 if (((int) strlen(s) + (int) strlen(tag) + indent) < width) {
277                         printf("%s%s%s\n", i, tag, s);
278                         Free(fi);
279                         Free(i);
280                         return; 
281                         /*NOTREACHED*/
282                 }
283                 cp = s + width - indent - strlen(tag);
284                 while (!isspace((unsigned char)*cp) && (cp != s))
285                         cp--;
286                 c = *cp;
287                 *cp = '\0';
288                 printf("%s%s%s\n", i, tag, s);
289                 s = cp + 1;
290                 *cp = c;                        /* don't mess up 's' */
291         }
292 }
293
294 #define IN_A_QUOTE   0
295 #define OUT_OF_QUOTE 1
296
297 char *
298 strip_ignore_chars( char *cp )
299 {
300         int had_a_comma = FALSE;
301         int flag = OUT_OF_QUOTE;
302         register char *rcp, *cp1;
303         char *tmp;
304
305 #ifdef DEBUG
306         if (debug & D_TRACE)
307                 printf("strip_ignore_chars(%s)\n", cp);
308 #endif
309         for (rcp = cp; *rcp != '\0'; rcp++)
310                 if (isignorechar(*rcp) || (*rcp == '"'))
311                         break;
312         if (*rcp == '\0')
313                 return(cp);
314
315         cp1 = tmp = (char *) Malloc((unsigned) strlen(cp));
316         for (rcp = cp; *rcp != '\0'; rcp++) {
317                 /* toss quotes and flip the flag */
318                 if (*rcp == '"')
319                         flag = OUT_OF_QUOTE - flag;
320                 else if (isignorechar(*rcp)) {
321                         if (flag == OUT_OF_QUOTE)
322                                 *cp1++ = ' ';
323                         else
324                                 *cp1++ = *rcp;
325                 }
326                 else if (*rcp == ',') {
327                         *cp1++ = *rcp;
328                         had_a_comma = TRUE;
329                 }
330                 else 
331                         *cp1++ = *rcp;
332         }
333         *cp1 = '\0';
334
335         /* re-quote the name if it had a comma in it */
336         if (had_a_comma == TRUE) {
337                 rcp = cp1 = (char *) Malloc((unsigned) (strlen(tmp) + 3));
338                 *rcp++ = '"';
339                 *rcp = '\0';
340                 strcat(rcp, tmp);
341                 strcat(rcp, "\"");
342                 Free(tmp);
343                 tmp = cp1;
344         }
345         return(tmp);
346 }
347
348 char *
349 code_to_str( int i )
350 {
351         switch(i) {
352         case LDAP_MOD_ADD : return("ADD");
353         case LDAP_MOD_DELETE : return("DELETE");
354         case LDAP_MOD_REPLACE : return("REPLACE");
355         default : return("?????");
356         }
357 }
358
359 char *
360 friendly_name( char *s )
361 {
362         static LDAPFriendlyMap *map = NULL;
363         static char *cp;
364
365         cp = ldap_friendly_name(FRIENDLYFILE, s, &map);
366         if (cp == NULL)
367                 return(s);
368         return(cp);
369 }
370
371 #ifdef UOFM
372
373 /* return TRUE if s has the syntax of a uniqname */
374 int
375 isauniqname( char *s )
376 {
377         int i = strlen(s);
378
379         if ((i < 3) || (i > 8))         /* uniqnames are 3-8 chars */
380                 return(FALSE);
381         if (!isalpha((unsigned char)*s)) /* uniqnames begin with a letter */
382                 return(FALSE);
383         for ( ; *s != '\0'; s++)        /* uniqnames are alphanumeric */
384                 if (!isalnum((unsigned char)*s))
385                         return(FALSE);
386         return(TRUE);
387 }
388 #endif
389
390 /* return TRUE if this attribute should be printed as a DN */
391 int
392 isadn( char *s )
393 {
394         register int i;
395
396         for (i = 0; attrlist[i].quipu_name != NULL; i++)
397                 if (!strcasecmp(s, attrlist[i].quipu_name))
398                         break;
399         if (attrlist[i].flags & ATTR_FLAG_IS_A_DN)
400                 return(TRUE);
401         return(FALSE);
402 }
403
404 char *
405 my_ldap_dn2ufn( char *s )
406 {
407         register char **cpp;
408         static char short_DN[BUFSIZ];
409
410         if (strstr(s, NULL) == NULL)
411                 return(ldap_dn2ufn(s));
412         cpp = ldap_explode_dn(s, TRUE);
413         sprintf(short_DN, "%s, %s", *cpp, *(cpp + 1));
414         ldap_value_free(cpp);
415         return(short_DN);
416 }
417
418 /* return TRUE if this attribute should be printed as a URL */
419 int
420 isaurl( char *s )
421 {
422         register int i;
423
424         for (i = 0; attrlist[i].quipu_name != NULL; i++)
425                 if (!strcasecmp(s, attrlist[i].quipu_name))
426                         break;
427         if (attrlist[i].flags & ATTR_FLAG_IS_A_URL)
428                 return(TRUE);
429         return(FALSE);
430 }
431
432 /* return TRUE if this attribute should be printed as a date and time */
433 int
434 isadate( char *s )
435 {
436         register int i;
437
438         for (i = 0; attrlist[i].quipu_name != NULL; i++)
439                 if (!strcasecmp(s, attrlist[i].quipu_name))
440                         break;
441         if (attrlist[i].flags & ATTR_FLAG_IS_A_DATE)
442                 return(TRUE);
443         return(FALSE);
444 }
445
446 void *
447 Malloc( unsigned int size )
448 {
449         void *void_ptr;
450
451         void_ptr = (void *) malloc(size);
452         if (void_ptr == NULL) {
453                 perror("malloc");
454                 exit( EXIT_FAILURE );
455                 /*NOTREACHED*/
456         }
457         return(void_ptr);
458 }
459
460 void
461 Free( void *ptr )
462 {
463         free(ptr);
464 }
465
466 char *
467 nextstr( char *s )
468 {
469         while (isspace((unsigned char) *s) && (*s != '\0'))
470                 s++;
471         if (s == NULL)
472                 return(NULL);
473         if (*s == '\0')
474                 return(NULL);
475         return(s);
476 }
477
478 void
479 free_mod_struct( LDAPMod *modp )
480 {
481         if (modp->mod_values != NULL)
482                 (void) ldap_value_free(modp->mod_values);
483         Free(modp->mod_type);
484         Free(modp);
485 }
486
487 void
488 StrFreeDup( char **ptr, char *new_value )
489 {
490         if (*ptr != NULL)
491                 Free(*ptr);
492         if (new_value == NULL)
493                 *ptr = NULL;
494         else
495                 *ptr = strdup(new_value);
496 }
497
498
499 int
500 confirm_action( char *msg )
501
502         char    tmp[SMALL_BUF_SIZE];
503         int     i;
504
505         if ( msg != NULL ) {
506                 putchar( '\n' );
507                 format( msg, 75, 2 );
508         }
509
510         printf("\n  Is this OK? ");
511         fflush(stdout);
512         tmp[0] = '\0';
513         fetch_buffer(tmp, sizeof(tmp), stdin);
514         i = strlen(tmp);
515         return( i > 0 &&
516             ( !strncasecmp(tmp, "YES", i) || !strncasecmp(tmp, "OK", i)));
517 }