Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / argv.c
blob0b27e6b3ff3ab4a4db1fc0d8272f20bbbb703062
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* argv 3
6 /* SUMMARY
7 /* string array utilities
8 /* SYNOPSIS
9 /* #include <argv.h>
11 /* ARGV *argv_alloc(len)
12 /* ssize_t len;
14 /* ARGV *argv_free(argvp)
15 /* ARGV *argvp;
17 /* void argv_add(argvp, arg, ..., ARGV_END)
18 /* ARGV *argvp;
19 /* char *arg;
21 /* void argv_addn(argvp, arg, arg_len, ..., ARGV_END)
22 /* ARGV *argvp;
23 /* char *arg;
24 /* ssize_t arg_len;
26 /* void argv_terminate(argvp);
27 /* ARGV *argvp;
29 /* void argv_truncate(argvp, len);
30 /* ARGV *argvp;
31 /* ssize_t len;
32 /* DESCRIPTION
33 /* The functions in this module manipulate arrays of string
34 /* pointers. An ARGV structure contains the following members:
35 /* .IP len
36 /* The length of the \fIargv\fR array member.
37 /* .IP argc
38 /* The number of \fIargv\fR elements used.
39 /* .IP argv
40 /* An array of pointers to null-terminated strings.
41 /* .PP
42 /* argv_alloc() returns an empty string array of the requested
43 /* length. The result is ready for use by argv_add(). The array
44 /* is null terminated.
46 /* argv_add() copies zero or more strings and adds them to the
47 /* specified string array. The array is null terminated.
48 /* Terminate the argument list with a null pointer. The manifest
49 /* constant ARGV_END provides a convenient notation for this.
51 /* argv_addn() is like argv_add(), but each string is followed
52 /* by a string length argument.
54 /* argv_free() releases storage for a string array, and conveniently
55 /* returns a null pointer.
57 /* argv_terminate() null-terminates its string array argument.
59 /* argv_truncate() trucates its argument to the specified
60 /* number of entries, but does not reallocate memory. The
61 /* result is null-terminated.
62 /* SEE ALSO
63 /* msg(3) diagnostics interface
64 /* DIAGNOSTICS
65 /* Fatal errors: memory allocation problem.
66 /* LICENSE
67 /* .ad
68 /* .fi
69 /* The Secure Mailer license must be distributed with this software.
70 /* AUTHOR(S)
71 /* Wietse Venema
72 /* IBM T.J. Watson Research
73 /* P.O. Box 704
74 /* Yorktown Heights, NY 10598, USA
75 /*--*/
77 /* System libraries. */
79 #include <sys_defs.h>
80 #include <stdlib.h> /* 44BSD stdarg.h uses abort() */
81 #include <stdarg.h>
82 #include <string.h>
84 /* Application-specific. */
86 #include "mymalloc.h"
87 #include "msg.h"
88 #include "argv.h"
90 /* argv_free - destroy string array */
92 ARGV *argv_free(ARGV *argvp)
94 char **cpp;
96 for (cpp = argvp->argv; cpp < argvp->argv + argvp->argc; cpp++)
97 myfree(*cpp);
98 myfree((char *) argvp->argv);
99 myfree((char *) argvp);
100 return (0);
103 /* argv_alloc - initialize string array */
105 ARGV *argv_alloc(ssize_t len)
107 ARGV *argvp;
108 ssize_t sane_len;
111 * Make sure that always argvp->argc < argvp->len.
113 argvp = (ARGV *) mymalloc(sizeof(*argvp));
114 argvp->len = 0;
115 sane_len = (len < 2 ? 2 : len);
116 argvp->argv = (char **) mymalloc((sane_len + 1) * sizeof(char *));
117 argvp->len = sane_len;
118 argvp->argc = 0;
119 argvp->argv[0] = 0;
120 return (argvp);
123 /* argv_extend - extend array */
125 static void argv_extend(ARGV *argvp)
127 ssize_t new_len;
129 new_len = argvp->len * 2;
130 argvp->argv = (char **)
131 myrealloc((char *) argvp->argv, (new_len + 1) * sizeof(char *));
132 argvp->len = new_len;
135 /* argv_add - add string to vector */
137 void argv_add(ARGV *argvp,...)
139 char *arg;
140 va_list ap;
143 * Make sure that always argvp->argc < argvp->len.
145 #define ARGV_SPACE_LEFT(a) ((a)->len - (a)->argc - 1)
147 va_start(ap, argvp);
148 while ((arg = va_arg(ap, char *)) != 0) {
149 if (ARGV_SPACE_LEFT(argvp) <= 0)
150 argv_extend(argvp);
151 argvp->argv[argvp->argc++] = mystrdup(arg);
153 va_end(ap);
154 argvp->argv[argvp->argc] = 0;
157 /* argv_addn - add string to vector */
159 void argv_addn(ARGV *argvp,...)
161 char *arg;
162 ssize_t len;
163 va_list ap;
166 * Make sure that always argvp->argc < argvp->len.
168 va_start(ap, argvp);
169 while ((arg = va_arg(ap, char *)) != 0) {
170 if ((len = va_arg(ap, ssize_t)) < 0)
171 msg_panic("argv_addn: bad string length %ld", (long) len);
172 if (ARGV_SPACE_LEFT(argvp) <= 0)
173 argv_extend(argvp);
174 argvp->argv[argvp->argc++] = mystrndup(arg, len);
176 va_end(ap);
177 argvp->argv[argvp->argc] = 0;
180 /* argv_terminate - terminate string array */
182 void argv_terminate(ARGV *argvp)
186 * Trust that argvp->argc < argvp->len.
188 argvp->argv[argvp->argc] = 0;
191 /* argv_truncate - truncate string array */
193 void argv_truncate(ARGV *argvp, ssize_t len)
195 char **cpp;
198 * Sanity check.
200 if (len < 0)
201 msg_panic("argv_truncate: bad length %ld", (long) len);
203 if (len < argvp->argc) {
204 for (cpp = argvp->argv + len; cpp < argvp->argv + argvp->argc; cpp++)
205 myfree(*cpp);
206 argvp->argc = len;
207 argvp->argv[argvp->argc] = 0;