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