Sync usage with man page.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / sane_basename.c
blob5fe596c6836bfc5a18925994575ca5c3bbbb8979
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* sane_basename 3
6 /* SUMMARY
7 /* split pathname into last component and parent directory
8 /* SYNOPSIS
9 /* #include <stringops.h>
11 /* char *sane_basename(buf, path)
12 /* VSTRING *buf;
13 /* const char *path;
15 /* char *sane_dirname(buf, path)
16 /* VSTRING *buf;
17 /* const char *path;
18 /* DESCRIPTION
19 /* These functions split a pathname into its last component
20 /* and its parent directory, excluding any trailing "/"
21 /* characters from the input. The result is a pointer to "/"
22 /* when the input is all "/" characters, or a pointer to "."
23 /* when the input is a null pointer or zero-length string.
25 /* sane_basename() and sane_dirname() differ as follows
26 /* from standard basename() and dirname() implementations:
27 /* .IP \(bu
28 /* They can use caller-provided storage or private storage.
29 /* .IP \(bu
30 /* They never modify their input.
31 /* .PP
32 /* sane_basename() returns a pointer to string with the last
33 /* pathname component.
35 /* sane_dirname() returns a pointer to string with the parent
36 /* directory. The result is a pointer to "." when the input
37 /* contains no '/' character.
39 /* Arguments:
40 /* .IP buf
41 /* Result storage. If a null pointer is specified, each function
42 /* uses its own private memory that is overwritten upon each call.
43 /* .IP path
44 /* The input pathname.
45 /* LICENSE
46 /* .ad
47 /* .fi
48 /* The Secure Mailer license must be distributed with this
49 /* software.
50 /* AUTHOR(S)
51 /* Wietse Venema
52 /* IBM T.J. Watson Research
53 /* P.O. Box 704
54 /* Yorktown Heights, NY 10598, USA
55 /*--*/
57 /* System library. */
59 #include <sys_defs.h>
60 #include <string.h>
62 /* Utility library. */
64 #include <vstring.h>
65 #include <stringops.h>
67 #define STR(x) vstring_str(x)
69 /* sane_basename - skip directory prefix */
71 char *sane_basename(VSTRING *bp, const char *path)
73 static VSTRING *buf;
74 const char *first;
75 const char *last;
78 * Your buffer or mine?
80 if (bp == 0) {
81 bp = buf;
82 if (bp == 0)
83 bp = buf = vstring_alloc(10);
87 * Special case: return "." for null or zero-length input.
89 if (path == 0 || *path == 0)
90 return (STR(vstring_strcpy(bp, ".")));
93 * Remove trailing '/' characters from input. Return "/" if input is all
94 * '/' characters.
96 last = path + strlen(path) - 1;
97 while (*last == '/') {
98 if (last == path)
99 return (STR(vstring_strcpy(bp, "/")));
100 last--;
104 * The pathname does not end in '/'. Skip to last '/' character if any.
106 first = last - 1;
107 while (first >= path && *first != '/')
108 first--;
110 return (STR(vstring_strncpy(bp, first + 1, last - first)));
113 /* sane_dirname - keep directory prefix */
115 char *sane_dirname(VSTRING *bp, const char *path)
117 static VSTRING *buf;
118 const char *last;
121 * Your buffer or mine?
123 if (bp == 0) {
124 bp = buf;
125 if (bp == 0)
126 bp = buf = vstring_alloc(10);
130 * Special case: return "." for null or zero-length input.
132 if (path == 0 || *path == 0)
133 return (STR(vstring_strcpy(bp, ".")));
136 * Remove trailing '/' characters from input. Return "/" if input is all
137 * '/' characters.
139 last = path + strlen(path) - 1;
140 while (*last == '/') {
141 if (last == path)
142 return (STR(vstring_strcpy(bp, "/")));
143 last--;
147 * This pathname does not end in '/'. Skip to last '/' character if any.
149 while (last >= path && *last != '/')
150 last--;
151 if (last < path) /* no '/' */
152 return (STR(vstring_strcpy(bp, ".")));
155 * Strip trailing '/' characters from dirname (not strictly needed).
157 while (last > path && *last == '/')
158 last--;
160 return (STR(vstring_strncpy(bp, path, last - path + 1)));
163 #ifdef TEST
164 #include <vstring_vstream.h>
166 int main(int argc, char **argv)
168 VSTRING *buf = vstring_alloc(10);
169 char *dir;
170 char *base;
172 while (vstring_get_nonl(buf, VSTREAM_IN) > 0) {
173 dir = sane_dirname((VSTRING *) 0, STR(buf));
174 base = sane_basename((VSTRING *) 0, STR(buf));
175 vstream_printf("input=\"%s\" dir=\"%s\" base=\"%s\"\n",
176 STR(buf), dir, base);
178 vstream_fflush(VSTREAM_OUT);
179 vstring_free(buf);
180 return (0);
183 #endif