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;
179 /* get nsswitch info of "automount */
180 conf
= __nsw_getconfig("automount", &pserr
);
182 /* find out if LDAP backend is configured */
184 for (lkp
= conf
->lookups
; lkp
!= NULL
; lkp
= lkp
->next
) {
185 if (strcmp(lkp
->service_name
, "ldap") == 0) {
190 /* free conf at the end of "if" bracket */
191 (void) __nsw_freeconfig(conf
);
194 /* if ldap is not configured, init_ldap is a no op */
195 if (!ldap_configured
)
198 rc
= __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P
, ¶mVal
, &errorp
);
199 if (rc
!= NS_LDAP_SUCCESS
|| !paramVal
|| !*paramVal
) {
200 syslog(LOG_ERR
, "Can not determine version of LDAP profile"
201 " that is used (%d, %s). Using version 2 profile"
202 " defaults", rc
, (errorp
&& errorp
->message
?
203 errorp
->message
: ""));
204 (void) __ns_ldap_freeError(&errorp
);
206 if (strcasecmp(*paramVal
, NS_LDAP_VERSION_1
) == 0)
208 (void) __ns_ldap_freeParam(¶mVal
);
213 trace_prt(1, "init_ldap: setting up for version 2\n");
214 automountKey
= "automountKey";
215 automountInformation
= "automountInformation";
216 defaultFilter
= "(&(objectClass=automount)(automountKey=%s))";
218 /* check for automountMapName mapped to nisMapName */
219 if (!isAttrMapped("automountMapName", "nisMapName"))
222 /* check for automountKey mapped to cn */
223 if (!isAttrMapped("automountKey", "cn"))
226 /* check for automountInformation mapped to nisMapEntry */
227 if (!isAttrMapped("automountInformation", "nisMapEntry"))
230 /* check for automountMap mapped to nisMap */
231 if (!isObjectMapped("automountMap", "nisMap"))
234 /* check for automount mapped to nisObject */
235 if (!isObjectMapped("automount", "nisObject"))
239 trace_prt(1, "init_ldap: encode = TRUE\n");
243 trace_prt(1, "init_ldap: setting up for version 1\n");
244 trace_prt(1, "init_ldap: encode = TRUE\n");
248 automountInformation
= "nisMapEntry";
249 defaultFilter
= "(&(objectClass=nisObject)(cn=%s))";
255 getmapent_ldap(char *key
, char *map
, struct mapline
*ml
,
256 char **stack
, char ***stkptr
, bool_t
*iswildcard
, bool_t isrestricted
)
258 char *ldap_line
= NULL
;
264 trace_prt(1, "getmapent_ldap called\n");
267 trace_prt(1, "getmapent_ldap: key=[ %s ]\n", key
);
272 nserr
= ldap_match(map
, key
, &ldap_line
, &ldap_len
);
274 if (nserr
== __NSW_NOTFOUND
) {
275 /* Try the default entry "*" */
276 if ((nserr
= ldap_match(map
, "\\2a", &ldap_line
,
288 * at this point we are sure that ldap_match
289 * succeeded so massage the entry by
290 * 1. ignoring # and beyond
291 * 2. trim the trailing whitespace
293 if (lp
= strchr(ldap_line
, '#'))
295 len
= strlen(ldap_line
);
297 nserr
= __NSW_NOTFOUND
;
300 lp
= &ldap_line
[len
- 1];
301 while (lp
> ldap_line
&& isspace(*lp
))
303 if (lp
== ldap_line
) {
304 nserr
= __NSW_NOTFOUND
;
307 (void) strncpy(ml
->linebuf
, ldap_line
, LINESZ
);
308 unquote(ml
->linebuf
, ml
->lineqbuf
);
309 nserr
= __NSW_SUCCESS
;
312 free((char *)ldap_line
);
315 trace_prt(1, "getmapent_ldap: exiting ...\n");
321 ldap_match(char *map
, char *key
, char **ldap_line
, int *ldap_len
)
323 char searchfilter
[LDAP_FILT_MAXSIZ
];
325 ns_ldap_result_t
*result
= NULL
;
326 ns_ldap_error_t
*errp
= NULL
;
327 ns_ldap_entry_t
*entry
= NULL
;
332 trace_prt(1, "ldap_match called\n");
333 trace_prt(1, "ldap_match: key =[ %s ]\n", key
);
337 * need to handle uppercase characters in the key because LDAP
338 * searches are case insensitive. Note, key = attribute automountKey.
341 ldapkey
= tosunds_str(key
);
346 trace_prt(1, "ldap_match: ldapkey =[ %s ]\n", ldapkey
);
349 (void) sprintf(searchfilter
, defaultFilter
, ldapkey
);
352 trace_prt(1, " ldap_match: Requesting list for %s in %s\n",
355 res
= __ns_ldap_list(map
, searchfilter
, NULL
,
356 NULL
, NULL
, 0, &result
, &errp
, NULL
, NULL
);
359 if (res
!= NS_LDAP_SUCCESS
)
361 " ldap_match: __ns_ldap_list FAILED (%d)\n", res
);
363 trace_prt(1, " ldap_match: __ns_ldap_list OK\n");
366 if (res
!= NS_LDAP_SUCCESS
&& res
!= NS_LDAP_NOTFOUND
) {
369 char errstr
[MAXERROR
];
370 (void) sprintf(errstr
,
371 gettext("ldap server can't list map,"
372 " '%s': '%s' - '%d'."),
373 map
, errp
->message
, errp
->status
);
374 syslog(LOG_ERR
, errstr
);
376 __ns_ldap_freeError(&errp
);
380 __ns_ldap_err2str(res
, &errmsg
);
381 syslog(LOG_ERR
, errmsg
);
385 __ns_ldap_freeResult(&result
);
386 return (ldap_err(res
));
389 if (res
== NS_LDAP_NOTFOUND
|| result
== NULL
||
390 result
->entries_count
== 0 || result
->entry
->attr_count
== 0) {
392 trace_prt(1, " ldap_match: no entries found\n");
394 __ns_ldap_freeError(&errp
);
396 __ns_ldap_freeResult(&result
);
397 return (__NSW_NOTFOUND
);
401 * get value of attribute nisMapEntry. This attribute contains a
402 * list of mount options AND mount location for a particular mount
410 * nisMapEntry: -rw,intr,nosuid,noquota hosta:/export/work
411 * ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
412 * ( mount options ) (remote mount location)
416 entry
= result
->entry
;
417 for (i
= 0; i
< entry
->attr_count
; i
++) {
418 ns_ldap_attr_t
*attr
;
420 attr
= entry
->attr_pair
[i
];
421 if (strcasecmp(attr
->attrname
, automountInformation
) == 0) {
426 attrval
= tounix_str(attr
->attrvalue
[0]);
428 attrval
= attr
->attrvalue
[0];
429 *ldap_len
= strlen(key
) + strlen(attrval
);
432 * so check for the length; it should be less than
435 if ((*ldap_len
+ 2) > LINESZ
) {
437 "ldap server map %s, entry for %s"
438 " is too long %d chars (max %d)",
439 map
, key
, (*ldap_len
+ 2), LINESZ
);
440 __ns_ldap_freeResult(&result
);
441 return (__NSW_UNAVAIL
);
443 *ldap_line
= (char *)malloc(*ldap_len
+ 2);
444 if (*ldap_line
== NULL
) {
445 syslog(LOG_ERR
, "ldap_match: malloc failed");
446 __ns_ldap_freeResult(&result
);
447 return (__NSW_UNAVAIL
);
450 (void) sprintf(*ldap_line
, "%s", attrval
);
456 __ns_ldap_freeError(&errp
);
457 __ns_ldap_freeResult(&result
);
460 return (__NSW_NOTFOUND
);
463 trace_prt(1, " ldap_match: found: %s\n", *ldap_line
);
465 return (__NSW_SUCCESS
);
469 loadmaster_ldap(char *mapname
, char *defopts
, char **stack
, char ***stkptr
)
471 char searchfilter
[LDAP_FILT_MAXSIZ
];
473 ns_ldap_result_t
*result
= NULL
;
474 ns_ldap_error_t
*errp
= NULL
;
475 struct loadmaster_cbdata master_cbdata
;
478 trace_prt(1, "loadmaster_ldap called\n");
480 master_cbdata
.ptr1
= defopts
;
481 master_cbdata
.ptr2
= stack
;
482 master_cbdata
.ptr3
= stkptr
;
484 /* filter gets all the entries for the specified mapname */
485 (void) sprintf(searchfilter
, defaultFilter
, "*");
488 trace_prt(1, "loadmaster_ldap: Requesting list for %s in %s\n",
489 searchfilter
, mapname
);
491 res
= __ns_ldap_list(mapname
, searchfilter
, NULL
, NULL
, NULL
,
492 0, &result
, &errp
, mastermap_callback_ldap
,
493 (void *) &master_cbdata
);
497 "loadmaster_ldap: __ns_ldap_list just returned: %d\n",
500 if (res
!= NS_LDAP_SUCCESS
) {
502 char errstr
[MAXERROR
];
504 (void) sprintf(errstr
, gettext(
505 "ldap server can't list map,"
506 "'%s': '%s' - '%d'."),
507 mapname
, errp
->message
, errp
->status
);
508 syslog(LOG_ERR
, errstr
);
510 __ns_ldap_freeError(&errp
);
514 __ns_ldap_err2str(res
, &errmsg
);
515 syslog(LOG_ERR
, errmsg
);
519 __ns_ldap_freeResult(&result
);
520 return (ldap_err(res
));
525 "loadmaster_ldap: calling __ns_ldap_freeResult...\n");
527 __ns_ldap_freeResult(&result
);
531 "loadmaster_ldap: about to return __NSW_SUCCESS...\n");
533 return (__NSW_SUCCESS
);
537 loaddirect_ldap(char *nsmap
, char *localmap
, char *opts
,
538 char **stack
, char ***stkptr
)
540 char searchfilter
[LDAP_FILT_MAXSIZ
];
542 ns_ldap_result_t
*result
= NULL
;
543 ns_ldap_error_t
*errp
= NULL
;
544 struct loaddirect_cbdata direct_cbdata
;
547 trace_prt(1, "loaddirect_ldap called\n");
550 direct_cbdata
.ptr1
= opts
;
551 direct_cbdata
.ptr2
= localmap
;
552 direct_cbdata
.ptr3
= stack
;
553 direct_cbdata
.ptr4
= stkptr
;
555 /* filter gets all the entries for the specified mapname */
556 (void) sprintf(searchfilter
, defaultFilter
, "*");
559 trace_prt(1, "loaddirect_ldap: Requesting list for %s in %s\n",
560 searchfilter
, nsmap
);
562 res
= __ns_ldap_list(nsmap
, searchfilter
, NULL
, NULL
,
563 NULL
, 0, &result
, &errp
,
564 directmap_callback
, (void *) &direct_cbdata
);
567 if (res
!= NS_LDAP_SUCCESS
) {
569 char errstr
[MAXERROR
];
571 (void) sprintf(errstr
,
572 gettext("ldap server can't list map,"
573 " '%s': '%s' - '%d'."),
574 nsmap
, errp
->message
, errp
->status
);
575 syslog(LOG_ERR
, errstr
);
577 __ns_ldap_freeError(&errp
);
581 __ns_ldap_err2str(res
, &errmsg
);
582 syslog(LOG_ERR
, errmsg
);
586 __ns_ldap_freeResult(&result
);
587 return (ldap_err(res
));
590 __ns_ldap_freeResult(&result
);
591 return (__NSW_SUCCESS
);
598 trace_prt(1, "ldap_err called\n");
602 case NS_LDAP_SUCCESS
:
603 return (__NSW_SUCCESS
);
605 case NS_LDAP_NOTFOUND
:
606 return (__NSW_NOTFOUND
);
608 case NS_LDAP_PARTIAL
:
609 return (__NSW_TRYAGAIN
);
612 return (__NSW_UNAVAIL
);
617 mastermap_callback_ldap(ns_ldap_entry_t
*entry
, void *udata
)
619 char *key
, *contents
, *pmap
, *opts
;
620 char dir
[LINESZ
], map
[LINESZ
], qbuff
[LINESZ
];
621 char cont_temp
[LINESZ
], key_temp
[LINESZ
];
622 int key_len
, contents_len
;
623 struct loadmaster_cbdata
*temp
= (struct loadmaster_cbdata
*)udata
;
624 char *defopts
= temp
->ptr1
;
625 char **stack
= temp
->ptr2
;
626 char ***stkptr
= temp
->ptr3
;
630 trace_prt(1, "mastermap_callback_ldap called\n");
631 trace_prt(1, "mastermap_callback_ldap: entry=%x\n", entry
);
634 "mastermap_callback_ldap: entry->attr_count=[ %d ]\n",
640 * For the current entry, obtain the values of the cn and the
641 * nisMapEntry attributes and the length of each value (cn=key,
642 * nisMapEntry=contents).
643 * We skip the description. Even though LDAP allows for multiple
644 * values per attribute, we take only the 1st value for each
645 * attribute because the automount data is organized as such.
651 for (i
= 0; i
< entry
->attr_count
; i
++) {
652 ns_ldap_attr_t
*attr
;
654 attr
= entry
->attr_pair
[i
];
657 "mastermap_callback_ldap: attr[%d]: %s=%s\n",
658 i
, attr
->attrname
, attr
->attrvalue
[0]);
660 if (strcasecmp(attr
->attrname
, automountInformation
) == 0) {
662 (void) strncpy(cont_temp
,
663 tounix_str(attr
->attrvalue
[0]), LINESZ
);
665 (void) strncpy(cont_temp
, attr
->attrvalue
[0],
667 contents
= cont_temp
;
668 contents_len
= strlen(contents
);
671 "mastermap_callback_ldap: contents=[ %s ],"
672 " contents_len=[ %d ]\n",
673 contents
, contents_len
);
676 if (strcasecmp(attr
->attrname
, automountKey
) == 0) {
678 (void) strncpy(key_temp
,
679 tounix_str(attr
->attrvalue
[0]), LINESZ
);
681 (void) strncpy(key_temp
, attr
->attrvalue
[0],
684 key_len
= strlen(key
);
687 "mastermap_callback_ldap: key=[ %s ],"
694 if (key_len
>= LINESZ
|| contents_len
>= LINESZ
)
696 if (key_len
< 2 || contents_len
< 2)
699 while (isspace(*contents
))
701 if (contents
== NULL
)
703 if (isspace(*key
) || *key
== '#')
706 (void) strncpy(dir
, key
, key_len
);
709 trace_prt(1, "mastermap_callback_ldap: dir= [ %s ]\n", dir
);
710 for (i
= 0; i
< LINESZ
; i
++)
712 if (macro_expand("", dir
, qbuff
, sizeof (dir
))) {
714 "%s in ldap server map: entry too long (max %d chars)",
715 dir
, sizeof (dir
) - 1);
718 (void) strncpy(map
, contents
, contents_len
);
719 map
[contents_len
] = '\0';
721 trace_prt(1, "mastermap_callback_ldap: map= [ %s ]\n", map
);
722 if (macro_expand("", map
, qbuff
, sizeof (map
))) {
724 "%s in ldap server map: entry too long (max %d chars)",
725 map
, sizeof (map
) - 1);
729 while (*pmap
&& isspace(*pmap
))
730 pmap
++; /* skip blanks in front of map */
732 while (*opts
&& !isspace(*opts
))
736 while (*opts
&& isspace(*opts
))
744 * Check for no embedded blanks.
746 if (strcspn(opts
, " ") == strlen(opts
)) {
749 "mastermap_callback_ldap: dir=[ %s ], pmap=[ %s ]\n",
751 dirinit(dir
, pmap
, opts
, 0, stack
, stkptr
);
755 /* get the value for the dn */
756 for (i
= 0; i
< entry
->attr_count
; i
++) {
757 ns_ldap_attr_t
*attr
;
759 attr
= entry
->attr_pair
[i
];
760 if (strcasecmp(attr
->attrname
, "dn")
762 dn
= attr
->attrvalue
[0];
767 "Warning: invalid entry for %s in ldap server"
768 " dn: %s ignored.\n",
772 trace_prt(1, "mastermap_callback_ldap exiting...\n");
777 directmap_callback(ns_ldap_entry_t
*entry
, void *udata
)
782 struct loaddirect_cbdata
*temp
= (struct loaddirect_cbdata
*)udata
;
783 char *opts
= temp
->ptr1
;
784 char *localmap
= temp
->ptr2
;
785 char **stack
= temp
->ptr3
;
786 char ***stkptr
= temp
->ptr4
;
790 * For the current entry, obtain the value and length of the cn i.e.
791 * the contents of key and its key length.
795 for (i
= 0; i
< entry
->attr_count
; i
++) {
796 ns_ldap_attr_t
*attr
;
798 attr
= entry
->attr_pair
[i
];
799 if (strcasecmp(attr
->attrname
, automountKey
) == 0) {
801 key
= tounix_str(attr
->attrvalue
[0]);
803 key
= attr
->attrvalue
[0];
804 key_len
= strlen(key
);
809 if (key_len
>= 100 || key_len
< 2)
812 if (isspace(*key
) || *key
== '#')
814 (void) strncpy(dir
, key
, key_len
);
817 dirinit(dir
, localmap
, opts
, 1, stack
, stkptr
);
823 getmapkeys_ldap(char *nsmap
, struct dir_entry
**list
, int *error
,
824 int *cache_time
, char **stack
, char ***stkptr
)
826 char searchfilter
[LDAP_FILT_MAXSIZ
];
828 ns_ldap_result_t
*result
= NULL
;
829 ns_ldap_error_t
*errp
= NULL
;
830 struct dir_cbdata readdir_cbdata
;
834 trace_prt(1, "getmapkeys_ldap called\n");
836 *cache_time
= RDDIR_CACHE_TIME
;
838 readdir_cbdata
.list
= list
;
839 readdir_cbdata
.last
= NULL
;
841 /* filter gets all the entries for the specified mapname */
842 (void) sprintf(searchfilter
, defaultFilter
, "*");
845 trace_prt(1, "getmapkeys_ldap: Requesting list for %s in %s\n",
846 searchfilter
, nsmap
);
848 res
= __ns_ldap_list(nsmap
, searchfilter
, NULL
, NULL
, NULL
, 0,
849 &result
, &errp
, readdir_callback
, (void *) &readdir_cbdata
);
852 trace_prt(1, " getmapkeys_ldap: __ns_ldap_list returned %d\n",
855 if (readdir_cbdata
.error
)
856 *error
= readdir_cbdata
.error
;
858 if (res
!= NS_LDAP_SUCCESS
&& res
!= NS_LDAP_NOTFOUND
) {
861 char errstr
[MAXERROR
];
862 (void) sprintf(errstr
, gettext(
863 "ldap server can't list map,"
864 " '%s': '%s' - '%d'."),
865 nsmap
, errp
->message
, errp
->status
);
866 syslog(LOG_ERR
, errstr
);
868 __ns_ldap_freeError(&errp
);
872 __ns_ldap_err2str(res
, &errmsg
);
873 syslog(LOG_ERR
, errmsg
);
877 __ns_ldap_freeResult(&result
);
880 return (ldap_err(res
));
883 __ns_ldap_freeResult(&result
);
885 return (__NSW_SUCCESS
);
889 readdir_callback(const ns_ldap_entry_t
*entry
, const void *udata
)
893 struct dir_cbdata
*temp
= (struct dir_cbdata
*)udata
;
894 struct dir_entry
**list
= temp
->list
;
895 struct dir_entry
*last
= temp
->last
;
899 trace_prt(1, "readdir_callback called\n");
901 * For the current entry, obtain the value and length of the cn i.e. the
902 * contents of key and its key length.
908 trace_prt(1, "readdir_callback: entry->attr_count=[ %d ]\n",
911 for (i
= 0; i
< entry
->attr_count
; i
++) {
912 ns_ldap_attr_t
*attr
;
914 attr
= entry
->attr_pair
[i
];
918 "readdir_callback: attr->attrname=[ %s ]\n",
921 if (strcasecmp(attr
->attrname
, automountKey
) == 0) {
923 key
= tounix_str(attr
->attrvalue
[0]);
925 key
= attr
->attrvalue
[0];
926 key_len
= strlen(key
);
930 "readdir_callback: key=[ %s ], key_len=[ %d ]\n",
937 if (key_len
>= 100 || key_len
< 2)
940 if (isspace(*key
) || *key
== '#')
944 * Wildcard entry should be ignored - following entries should continue
945 * to be read to corroborate with the way we search for entries in
946 * LDAP, i.e., first for an exact key match and then a wildcard
947 * if there's no exact key match.
949 if (key
[0] == '*' && key
[1] == '\0')
952 if (add_dir_entry(key
, list
, &last
)) {
953 temp
->error
= ENOMEM
;
961 trace_prt(1, "readdir_callback returning 0...\n");
967 * Puts CAPCHAR in front of uppercase characters or surrounds a set of
968 * contiguous uppercase characters with CAPCHARS and square brackets.
970 * For example (assuming CAPCHAR = '%'):
972 * if str = Abc, it returns %Abc
973 * if str = ABc, it returns %[AB]c
974 * if str = AbC, it returns %Ab%C
978 tosunds_str(char *str
)
980 static char buf
[BUFSIZ
];
981 int i
, j
, er
= FALSE
;
983 int openBracket
= FALSE
, closeBracket
= FALSE
;
986 (void) memset(buf
, 0, BUFSIZ
);
989 for (i
= 0; i
< strlen(str
); i
++) {
990 /* Check the current element */
991 if (isupper(str
[i
])) {
993 /* check the next element */
994 if (isupper(str
[i
+1])) {
995 if (openBracket
== FALSE
) {
1002 if (openBracket
== FALSE
) {
1006 openBracket
= FALSE
;
1007 closeBracket
= TRUE
;
1018 if (closeBracket
== TRUE
) {
1019 closeBracket
= FALSE
;
1031 syslog(LOG_ERR
, "Buffer size exceeded.");
1032 (void) memset(buf
, 0, BUFSIZ
);
1041 * Reverses what tosunds_str() did
1044 tounix_str(char *str
)
1046 static char buf
[BUFSIZ
];
1048 int openBracket
= FALSE
;
1050 (void) memset(buf
, 0, BUFSIZ
);
1053 for (i
= 0; i
< strlen(str
); i
++) {
1054 if (str
[i
] == '%') {
1055 if (isupper(str
[i
+1])) {
1057 } else if ((str
[i
+1] == '[') && (isupper(str
[i
+2]))) {
1061 } else if (str
[i
] == ']') {
1062 if ((isupper(str
[i
-1])) && (openBracket
== TRUE
))
1064 openBracket
= FALSE
;