4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
34 #include <sys/param.h>
35 #include <sys/types.h>
37 #include <rpcsvc/nfs_prot.h>
38 #include <sys/errno.h>
40 #include "automount.h"
41 #include "../../../lib/libsldap/common/ns_sldap.h"
44 * LDAP schema used for automounter:
46 * automountMapName: mapname i.e. auto_home, etc.
47 * automountKey: contains the key i.e. the mount point
48 * automountInformation: contains the mount options and remote mount location
49 * description: an optional description (not used by automounter)
51 * For example, if auto_direct has the following line of data:
53 * /work -rw,intr,nosuid,noquota hosta:/export/work
55 * Then this would map to the the following LDAP entry:
57 * dn: automountKey=/work,automountMapName=auto_direct,...
59 * automountInformation: -rw,intr,nosuid,noquota hosta:/export/work
61 * objectclass: automount
65 * dn: automountMapName=auto_direct,...
66 * automountMapName: auto_direct
68 * objectClass: automountMap
70 * Note that the schema can be mapped and SSD's can be used to relocate
71 * the default location of these entries.
78 static char *automountKey
= NULL
;
79 static char *automountInformation
= NULL
;
80 static char *defaultFilter
= NULL
;
81 static int encode
= 0;
83 static int mastermap_callback_ldap();
84 static int directmap_callback();
85 static int ldap_err(int);
86 static int ldap_match();
87 static int readdir_callback();
89 struct loadmaster_cbdata
{
95 struct loaddirect_cbdata
{
103 struct dir_entry
**list
;
104 struct dir_entry
*last
;
108 static char *tosunds_str(char *);
109 static char *tounix_str(char *);
112 isAttrMapped(char *orig
, char *mapped
)
115 char **mappedschema
= NULL
;
117 mappedschema
= __ns_ldap_getMappedAttributes("automount", orig
);
118 if (mappedschema
== NULL
)
120 if (strcasecmp(mappedschema
[0], mapped
) != 0) {
121 for (s
= mappedschema
; *s
!= NULL
; s
++)
126 for (s
= mappedschema
; *s
!= NULL
; s
++)
133 isObjectMapped(char *orig
, char *mapped
)
136 char **mappedschema
= NULL
;
138 mappedschema
= __ns_ldap_getMappedObjectClass("automount", orig
);
139 if (mappedschema
== NULL
)
141 if (strcasecmp(mappedschema
[0], mapped
) != 0) {
142 for (s
= mappedschema
; *s
!= NULL
; s
++)
147 for (s
= mappedschema
; *s
!= NULL
; s
++)
154 init_ldap(char **stack
, char ***stkptr
)
157 * Check for version of the profile the client is using
159 * For version 1 profiles we do encoding of attributes
160 * and use nisMap and nisObject schema for backward compatibility.
162 * For version 2 profiles we don't do encoding and use
163 * automountMap and automount as default attributes (which can
164 * then be overridden in libsldap if schema mapping is configured
167 * If profile version is not available, use version 2 as default
168 * and syslog message.
171 void **paramVal
= NULL
;
172 ns_ldap_error_t
*errorp
= NULL
;
173 struct __nsw_switchconfig
*conf
= NULL
;
174 struct __nsw_lookup
*lkp
= NULL
;
175 enum __nsw_parse_err pserr
;
176 int ldap_configured
= 0;
183 /* get nsswitch info of "automount */
184 conf
= __nsw_getconfig("automount", &pserr
);
186 /* find out if LDAP backend is configured */
188 for (lkp
= conf
->lookups
; lkp
!= NULL
; lkp
= lkp
->next
) {
189 if (strcmp(lkp
->service_name
, "ldap") == 0) {
194 /* free conf at the end of "if" bracket */
195 (void) __nsw_freeconfig(conf
);
198 /* if ldap is not configured, init_ldap is a no op */
199 if (!ldap_configured
)
202 rc
= __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P
, ¶mVal
, &errorp
);
203 if (rc
!= NS_LDAP_SUCCESS
|| !paramVal
|| !*paramVal
) {
204 syslog(LOG_ERR
, "Can not determine version of LDAP profile"
205 " that is used (%d, %s). Using version 2 profile"
206 " defaults", rc
, (errorp
&& errorp
->message
?
207 errorp
->message
: ""));
208 (void) __ns_ldap_freeError(&errorp
);
210 if (strcasecmp(*paramVal
, NS_LDAP_VERSION_1
) == 0)
212 (void) __ns_ldap_freeParam(¶mVal
);
217 trace_prt(1, "init_ldap: setting up for version 2\n");
218 automountKey
= "automountKey";
219 automountInformation
= "automountInformation";
220 defaultFilter
= "(&(objectClass=automount)(automountKey=%s))";
222 /* check for automountMapName mapped to nisMapName */
223 if (!isAttrMapped("automountMapName", "nisMapName"))
226 /* check for automountKey mapped to cn */
227 if (!isAttrMapped("automountKey", "cn"))
230 /* check for automountInformation mapped to nisMapEntry */
231 if (!isAttrMapped("automountInformation", "nisMapEntry"))
234 /* check for automountMap mapped to nisMap */
235 if (!isObjectMapped("automountMap", "nisMap"))
238 /* check for automount mapped to nisObject */
239 if (!isObjectMapped("automount", "nisObject"))
243 trace_prt(1, "init_ldap: encode = TRUE\n");
247 trace_prt(1, "init_ldap: setting up for version 1\n");
248 trace_prt(1, "init_ldap: encode = TRUE\n");
252 automountInformation
= "nisMapEntry";
253 defaultFilter
= "(&(objectClass=nisObject)(cn=%s))";
259 getmapent_ldap(char *key
, char *map
, struct mapline
*ml
,
260 char **stack
, char ***stkptr
, bool_t
*iswildcard
, bool_t isrestricted
)
262 char *ldap_line
= NULL
;
268 trace_prt(1, "getmapent_ldap called\n");
271 trace_prt(1, "getmapent_ldap: key=[ %s ]\n", key
);
276 nserr
= ldap_match(map
, key
, &ldap_line
, &ldap_len
);
278 if (nserr
== __NSW_NOTFOUND
) {
279 /* Try the default entry "*" */
280 if ((nserr
= ldap_match(map
, "\\2a", &ldap_line
,
292 * at this point we are sure that ldap_match
293 * succeeded so massage the entry by
294 * 1. ignoring # and beyond
295 * 2. trim the trailing whitespace
297 if (lp
= strchr(ldap_line
, '#'))
299 len
= strlen(ldap_line
);
301 nserr
= __NSW_NOTFOUND
;
304 lp
= &ldap_line
[len
- 1];
305 while (lp
> ldap_line
&& isspace(*lp
))
307 if (lp
== ldap_line
) {
308 nserr
= __NSW_NOTFOUND
;
311 (void) strncpy(ml
->linebuf
, ldap_line
, LINESZ
);
312 unquote(ml
->linebuf
, ml
->lineqbuf
);
313 nserr
= __NSW_SUCCESS
;
316 free((char *)ldap_line
);
319 trace_prt(1, "getmapent_ldap: exiting ...\n");
325 ldap_match(char *map
, char *key
, char **ldap_line
, int *ldap_len
)
327 char searchfilter
[LDAP_FILT_MAXSIZ
];
329 ns_ldap_result_t
*result
= NULL
;
330 ns_ldap_error_t
*errp
= NULL
;
331 ns_ldap_entry_t
*entry
= NULL
;
336 trace_prt(1, "ldap_match called\n");
337 trace_prt(1, "ldap_match: key =[ %s ]\n", key
);
341 * need to handle uppercase characters in the key because LDAP
342 * searches are case insensitive. Note, key = attribute automountKey.
345 ldapkey
= tosunds_str(key
);
350 trace_prt(1, "ldap_match: ldapkey =[ %s ]\n", ldapkey
);
353 (void) sprintf(searchfilter
, defaultFilter
, ldapkey
);
356 trace_prt(1, " ldap_match: Requesting list for %s in %s\n",
359 res
= __ns_ldap_list(map
, searchfilter
, NULL
,
360 NULL
, NULL
, 0, &result
, &errp
, NULL
, NULL
);
363 if (res
!= NS_LDAP_SUCCESS
)
365 " ldap_match: __ns_ldap_list FAILED (%d)\n", res
);
367 trace_prt(1, " ldap_match: __ns_ldap_list OK\n");
370 if (res
!= NS_LDAP_SUCCESS
&& res
!= NS_LDAP_NOTFOUND
) {
373 char errstr
[MAXERROR
];
374 (void) sprintf(errstr
,
375 gettext("ldap server can't list map,"
376 " '%s': '%s' - '%d'."),
377 map
, errp
->message
, errp
->status
);
378 syslog(LOG_ERR
, errstr
);
380 __ns_ldap_freeError(&errp
);
384 __ns_ldap_err2str(res
, &errmsg
);
385 syslog(LOG_ERR
, errmsg
);
389 __ns_ldap_freeResult(&result
);
390 return (ldap_err(res
));
393 if (res
== NS_LDAP_NOTFOUND
|| result
== NULL
||
394 result
->entries_count
== 0 || result
->entry
->attr_count
== 0) {
396 trace_prt(1, " ldap_match: no entries found\n");
398 __ns_ldap_freeError(&errp
);
400 __ns_ldap_freeResult(&result
);
401 return (__NSW_NOTFOUND
);
405 * get value of attribute nisMapEntry. This attribute contains a
406 * list of mount options AND mount location for a particular mount
414 * nisMapEntry: -rw,intr,nosuid,noquota hosta:/export/work
415 * ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
416 * ( mount options ) (remote mount location)
420 entry
= result
->entry
;
421 for (i
= 0; i
< entry
->attr_count
; i
++) {
422 ns_ldap_attr_t
*attr
;
424 attr
= entry
->attr_pair
[i
];
425 if (strcasecmp(attr
->attrname
, automountInformation
) == 0) {
430 attrval
= tounix_str(attr
->attrvalue
[0]);
432 attrval
= attr
->attrvalue
[0];
433 *ldap_len
= strlen(key
) + strlen(attrval
);
436 * so check for the length; it should be less than
439 if ((*ldap_len
+ 2) > LINESZ
) {
441 "ldap server map %s, entry for %s"
442 " is too long %d chars (max %d)",
443 map
, key
, (*ldap_len
+ 2), LINESZ
);
444 __ns_ldap_freeResult(&result
);
445 return (__NSW_UNAVAIL
);
447 *ldap_line
= (char *)malloc(*ldap_len
+ 2);
448 if (*ldap_line
== NULL
) {
449 syslog(LOG_ERR
, "ldap_match: malloc failed");
450 __ns_ldap_freeResult(&result
);
451 return (__NSW_UNAVAIL
);
454 (void) sprintf(*ldap_line
, "%s", attrval
);
460 __ns_ldap_freeError(&errp
);
461 __ns_ldap_freeResult(&result
);
464 return (__NSW_NOTFOUND
);
467 trace_prt(1, " ldap_match: found: %s\n", *ldap_line
);
469 return (__NSW_SUCCESS
);
473 loadmaster_ldap(char *mapname
, char *defopts
, char **stack
, char ***stkptr
)
475 char searchfilter
[LDAP_FILT_MAXSIZ
];
477 ns_ldap_result_t
*result
= NULL
;
478 ns_ldap_error_t
*errp
= NULL
;
479 struct loadmaster_cbdata master_cbdata
;
482 trace_prt(1, "loadmaster_ldap called\n");
484 master_cbdata
.ptr1
= defopts
;
485 master_cbdata
.ptr2
= stack
;
486 master_cbdata
.ptr3
= stkptr
;
488 /* filter gets all the entries for the specified mapname */
489 (void) sprintf(searchfilter
, defaultFilter
, "*");
492 trace_prt(1, "loadmaster_ldap: Requesting list for %s in %s\n",
493 searchfilter
, mapname
);
495 res
= __ns_ldap_list(mapname
, searchfilter
, NULL
, NULL
, NULL
,
496 0, &result
, &errp
, mastermap_callback_ldap
,
497 (void *) &master_cbdata
);
501 "loadmaster_ldap: __ns_ldap_list just returned: %d\n",
504 if (res
!= NS_LDAP_SUCCESS
) {
506 char errstr
[MAXERROR
];
508 (void) sprintf(errstr
, gettext(
509 "ldap server can't list map,"
510 "'%s': '%s' - '%d'."),
511 mapname
, errp
->message
, errp
->status
);
512 syslog(LOG_ERR
, errstr
);
514 __ns_ldap_freeError(&errp
);
518 __ns_ldap_err2str(res
, &errmsg
);
519 syslog(LOG_ERR
, errmsg
);
523 __ns_ldap_freeResult(&result
);
524 return (ldap_err(res
));
529 "loadmaster_ldap: calling __ns_ldap_freeResult...\n");
531 __ns_ldap_freeResult(&result
);
535 "loadmaster_ldap: about to return __NSW_SUCCESS...\n");
537 return (__NSW_SUCCESS
);
541 loaddirect_ldap(char *nsmap
, char *localmap
, char *opts
,
542 char **stack
, char ***stkptr
)
544 char searchfilter
[LDAP_FILT_MAXSIZ
];
546 ns_ldap_result_t
*result
= NULL
;
547 ns_ldap_error_t
*errp
= NULL
;
548 struct loaddirect_cbdata direct_cbdata
;
551 trace_prt(1, "loaddirect_ldap called\n");
554 direct_cbdata
.ptr1
= opts
;
555 direct_cbdata
.ptr2
= localmap
;
556 direct_cbdata
.ptr3
= stack
;
557 direct_cbdata
.ptr4
= stkptr
;
559 /* filter gets all the entries for the specified mapname */
560 (void) sprintf(searchfilter
, defaultFilter
, "*");
563 trace_prt(1, "loaddirect_ldap: Requesting list for %s in %s\n",
564 searchfilter
, nsmap
);
566 res
= __ns_ldap_list(nsmap
, searchfilter
, NULL
, NULL
,
567 NULL
, 0, &result
, &errp
,
568 directmap_callback
, (void *) &direct_cbdata
);
571 if (res
!= NS_LDAP_SUCCESS
) {
573 char errstr
[MAXERROR
];
575 (void) sprintf(errstr
,
576 gettext("ldap server can't list map,"
577 " '%s': '%s' - '%d'."),
578 nsmap
, errp
->message
, errp
->status
);
579 syslog(LOG_ERR
, errstr
);
581 __ns_ldap_freeError(&errp
);
585 __ns_ldap_err2str(res
, &errmsg
);
586 syslog(LOG_ERR
, errmsg
);
590 __ns_ldap_freeResult(&result
);
591 return (ldap_err(res
));
594 __ns_ldap_freeResult(&result
);
595 return (__NSW_SUCCESS
);
602 trace_prt(1, "ldap_err called\n");
606 case NS_LDAP_SUCCESS
:
607 return (__NSW_SUCCESS
);
609 case NS_LDAP_NOTFOUND
:
610 return (__NSW_NOTFOUND
);
612 case NS_LDAP_PARTIAL
:
613 return (__NSW_TRYAGAIN
);
616 return (__NSW_UNAVAIL
);
621 mastermap_callback_ldap(ns_ldap_entry_t
*entry
, void *udata
)
623 char *key
, *contents
, *pmap
, *opts
;
624 char dir
[LINESZ
], map
[LINESZ
], qbuff
[LINESZ
];
625 char cont_temp
[LINESZ
], key_temp
[LINESZ
];
626 int key_len
, contents_len
;
627 struct loadmaster_cbdata
*temp
= (struct loadmaster_cbdata
*)udata
;
628 char *defopts
= temp
->ptr1
;
629 char **stack
= temp
->ptr2
;
630 char ***stkptr
= temp
->ptr3
;
634 trace_prt(1, "mastermap_callback_ldap called\n");
635 trace_prt(1, "mastermap_callback_ldap: entry=%x\n", entry
);
638 "mastermap_callback_ldap: entry->attr_count=[ %d ]\n",
644 * For the current entry, obtain the values of the cn and the
645 * nisMapEntry attributes and the length of each value (cn=key,
646 * nisMapEntry=contents).
647 * We skip the description. Even though LDAP allows for multiple
648 * values per attribute, we take only the 1st value for each
649 * attribute because the automount data is organized as such.
655 for (i
= 0; i
< entry
->attr_count
; i
++) {
656 ns_ldap_attr_t
*attr
;
658 attr
= entry
->attr_pair
[i
];
661 "mastermap_callback_ldap: attr[%d]: %s=%s\n",
662 i
, attr
->attrname
, attr
->attrvalue
[0]);
664 if (strcasecmp(attr
->attrname
, automountInformation
) == 0) {
666 (void) strncpy(cont_temp
,
667 tounix_str(attr
->attrvalue
[0]), LINESZ
);
669 (void) strncpy(cont_temp
, attr
->attrvalue
[0],
671 contents
= cont_temp
;
672 contents_len
= strlen(contents
);
675 "mastermap_callback_ldap: contents=[ %s ],"
676 " contents_len=[ %d ]\n",
677 contents
, contents_len
);
680 if (strcasecmp(attr
->attrname
, automountKey
) == 0) {
682 (void) strncpy(key_temp
,
683 tounix_str(attr
->attrvalue
[0]), LINESZ
);
685 (void) strncpy(key_temp
, attr
->attrvalue
[0],
688 key_len
= strlen(key
);
691 "mastermap_callback_ldap: key=[ %s ],"
698 if (key_len
>= LINESZ
|| contents_len
>= LINESZ
)
700 if (key_len
< 2 || contents_len
< 2)
703 while (isspace(*contents
))
705 if (contents
== NULL
)
707 if (isspace(*key
) || *key
== '#')
710 (void) strncpy(dir
, key
, key_len
);
713 trace_prt(1, "mastermap_callback_ldap: dir= [ %s ]\n", dir
);
714 for (i
= 0; i
< LINESZ
; i
++)
716 if (macro_expand("", dir
, qbuff
, sizeof (dir
))) {
718 "%s in ldap server map: entry too long (max %d chars)",
719 dir
, sizeof (dir
) - 1);
722 (void) strncpy(map
, contents
, contents_len
);
723 map
[contents_len
] = '\0';
725 trace_prt(1, "mastermap_callback_ldap: map= [ %s ]\n", map
);
726 if (macro_expand("", map
, qbuff
, sizeof (map
))) {
728 "%s in ldap server map: entry too long (max %d chars)",
729 map
, sizeof (map
) - 1);
733 while (*pmap
&& isspace(*pmap
))
734 pmap
++; /* skip blanks in front of map */
736 while (*opts
&& !isspace(*opts
))
740 while (*opts
&& isspace(*opts
))
748 * Check for no embedded blanks.
750 if (strcspn(opts
, " ") == strlen(opts
)) {
753 "mastermap_callback_ldap: dir=[ %s ], pmap=[ %s ]\n",
755 dirinit(dir
, pmap
, opts
, 0, stack
, stkptr
);
759 /* get the value for the dn */
760 for (i
= 0; i
< entry
->attr_count
; i
++) {
761 ns_ldap_attr_t
*attr
;
763 attr
= entry
->attr_pair
[i
];
764 if (strcasecmp(attr
->attrname
, "dn")
766 dn
= attr
->attrvalue
[0];
771 "Warning: invalid entry for %s in ldap server"
772 " dn: %s ignored.\n",
776 trace_prt(1, "mastermap_callback_ldap exiting...\n");
781 directmap_callback(ns_ldap_entry_t
*entry
, void *udata
)
786 struct loaddirect_cbdata
*temp
= (struct loaddirect_cbdata
*)udata
;
787 char *opts
= temp
->ptr1
;
788 char *localmap
= temp
->ptr2
;
789 char **stack
= temp
->ptr3
;
790 char ***stkptr
= temp
->ptr4
;
794 * For the current entry, obtain the value and length of the cn i.e.
795 * the contents of key and its key length.
799 for (i
= 0; i
< entry
->attr_count
; i
++) {
800 ns_ldap_attr_t
*attr
;
802 attr
= entry
->attr_pair
[i
];
803 if (strcasecmp(attr
->attrname
, automountKey
) == 0) {
805 key
= tounix_str(attr
->attrvalue
[0]);
807 key
= attr
->attrvalue
[0];
808 key_len
= strlen(key
);
813 if (key_len
>= 100 || key_len
< 2)
816 if (isspace(*key
) || *key
== '#')
818 (void) strncpy(dir
, key
, key_len
);
821 dirinit(dir
, localmap
, opts
, 1, stack
, stkptr
);
827 getmapkeys_ldap(char *nsmap
, struct dir_entry
**list
, int *error
,
828 int *cache_time
, char **stack
, char ***stkptr
)
830 char searchfilter
[LDAP_FILT_MAXSIZ
];
832 ns_ldap_result_t
*result
= NULL
;
833 ns_ldap_error_t
*errp
= NULL
;
834 struct dir_cbdata readdir_cbdata
;
842 trace_prt(1, "getmapkeys_ldap called\n");
844 *cache_time
= RDDIR_CACHE_TIME
;
846 readdir_cbdata
.list
= list
;
847 readdir_cbdata
.last
= NULL
;
849 /* filter gets all the entries for the specified mapname */
850 (void) sprintf(searchfilter
, defaultFilter
, "*");
853 trace_prt(1, "getmapkeys_ldap: Requesting list for %s in %s\n",
854 searchfilter
, nsmap
);
856 res
= __ns_ldap_list(nsmap
, searchfilter
, NULL
, NULL
, NULL
, 0,
857 &result
, &errp
, readdir_callback
, (void *) &readdir_cbdata
);
860 trace_prt(1, " getmapkeys_ldap: __ns_ldap_list returned %d\n",
863 if (readdir_cbdata
.error
)
864 *error
= readdir_cbdata
.error
;
866 if (res
!= NS_LDAP_SUCCESS
&& res
!= NS_LDAP_NOTFOUND
) {
869 char errstr
[MAXERROR
];
870 (void) sprintf(errstr
, gettext(
871 "ldap server can't list map,"
872 " '%s': '%s' - '%d'."),
873 nsmap
, errp
->message
, errp
->status
);
874 syslog(LOG_ERR
, errstr
);
876 __ns_ldap_freeError(&errp
);
880 __ns_ldap_err2str(res
, &errmsg
);
881 syslog(LOG_ERR
, errmsg
);
885 __ns_ldap_freeResult(&result
);
888 return (ldap_err(res
));
891 __ns_ldap_freeResult(&result
);
893 return (__NSW_SUCCESS
);
897 readdir_callback(const ns_ldap_entry_t
*entry
, const void *udata
)
901 struct dir_cbdata
*temp
= (struct dir_cbdata
*)udata
;
902 struct dir_entry
**list
= temp
->list
;
903 struct dir_entry
*last
= temp
->last
;
907 trace_prt(1, "readdir_callback called\n");
909 * For the current entry, obtain the value and length of the cn i.e. the
910 * contents of key and its key length.
916 trace_prt(1, "readdir_callback: entry->attr_count=[ %d ]\n",
919 for (i
= 0; i
< entry
->attr_count
; i
++) {
920 ns_ldap_attr_t
*attr
;
922 attr
= entry
->attr_pair
[i
];
926 "readdir_callback: attr->attrname=[ %s ]\n",
929 if (strcasecmp(attr
->attrname
, automountKey
) == 0) {
931 key
= tounix_str(attr
->attrvalue
[0]);
933 key
= attr
->attrvalue
[0];
934 key_len
= strlen(key
);
938 "readdir_callback: key=[ %s ], key_len=[ %d ]\n",
945 if (key_len
>= 100 || key_len
< 2)
948 if (isspace(*key
) || *key
== '#')
952 * Wildcard entry should be ignored - following entries should continue
953 * to be read to corroborate with the way we search for entries in
954 * LDAP, i.e., first for an exact key match and then a wildcard
955 * if there's no exact key match.
957 if (key
[0] == '*' && key
[1] == '\0')
960 if (add_dir_entry(key
, list
, &last
)) {
961 temp
->error
= ENOMEM
;
969 trace_prt(1, "readdir_callback returning 0...\n");
975 * Puts CAPCHAR in front of uppercase characters or surrounds a set of
976 * contiguous uppercase characters with CAPCHARS and square brackets.
978 * For example (assuming CAPCHAR = '%'):
980 * if str = Abc, it returns %Abc
981 * if str = ABc, it returns %[AB]c
982 * if str = AbC, it returns %Ab%C
986 tosunds_str(char *str
)
988 static char buf
[BUFSIZ
];
989 int i
, j
, er
= FALSE
;
991 int openBracket
= FALSE
, closeBracket
= FALSE
;
994 (void) memset(buf
, 0, BUFSIZ
);
997 for (i
= 0; i
< strlen(str
); i
++) {
998 /* Check the current element */
999 if (isupper(str
[i
])) {
1001 /* check the next element */
1002 if (isupper(str
[i
+1])) {
1003 if (openBracket
== FALSE
) {
1010 if (openBracket
== FALSE
) {
1014 openBracket
= FALSE
;
1015 closeBracket
= TRUE
;
1026 if (closeBracket
== TRUE
) {
1027 closeBracket
= FALSE
;
1039 syslog(LOG_ERR
, "Buffer size exceeded.");
1040 (void) memset(buf
, 0, BUFSIZ
);
1049 * Reverses what tosunds_str() did
1052 tounix_str(char *str
)
1054 static char buf
[BUFSIZ
];
1056 int openBracket
= FALSE
;
1058 (void) memset(buf
, 0, BUFSIZ
);
1061 for (i
= 0; i
< strlen(str
); i
++) {
1062 if (str
[i
] == '%') {
1063 if (isupper(str
[i
+1])) {
1065 } else if ((str
[i
+1] == '[') && (isupper(str
[i
+2]))) {
1069 } else if (str
[i
] == ']') {
1070 if ((isupper(str
[i
-1])) && (openBracket
== TRUE
))
1072 openBracket
= FALSE
;