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