argv.c revision 1.1.1.1
1/* $NetBSD: argv.c,v 1.1.1.1 2009/06/23 10:08:58 tron Exp $ */ 2 3/*++ 4/* NAME 5/* argv 3 6/* SUMMARY 7/* string array utilities 8/* SYNOPSIS 9/* #include <argv.h> 10/* 11/* ARGV *argv_alloc(len) 12/* ssize_t len; 13/* 14/* ARGV *argv_free(argvp) 15/* ARGV *argvp; 16/* 17/* void argv_add(argvp, arg, ..., ARGV_END) 18/* ARGV *argvp; 19/* char *arg; 20/* 21/* void argv_addn(argvp, arg, arg_len, ..., ARGV_END) 22/* ARGV *argvp; 23/* char *arg; 24/* ssize_t arg_len; 25/* 26/* void argv_terminate(argvp); 27/* ARGV *argvp; 28/* 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. 45/* 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. 50/* 51/* argv_addn() is like argv_add(), but each string is followed 52/* by a string length argument. 53/* 54/* argv_free() releases storage for a string array, and conveniently 55/* returns a null pointer. 56/* 57/* argv_terminate() null-terminates its string array argument. 58/* 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/*--*/ 76 77/* System libraries. */ 78 79#include <sys_defs.h> 80#include <stdlib.h> /* 44BSD stdarg.h uses abort() */ 81#include <stdarg.h> 82#include <string.h> 83 84/* Application-specific. */ 85 86#include "mymalloc.h" 87#include "msg.h" 88#include "argv.h" 89 90/* argv_free - destroy string array */ 91 92ARGV *argv_free(ARGV *argvp) 93{ 94 char **cpp; 95 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); 101} 102 103/* argv_alloc - initialize string array */ 104 105ARGV *argv_alloc(ssize_t len) 106{ 107 ARGV *argvp; 108 ssize_t sane_len; 109 110 /* 111 * Make sure that always argvp->argc < argvp->len. 112 */ 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); 121} 122 123/* argv_extend - extend array */ 124 125static void argv_extend(ARGV *argvp) 126{ 127 ssize_t new_len; 128 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; 133} 134 135/* argv_add - add string to vector */ 136 137void argv_add(ARGV *argvp,...) 138{ 139 char *arg; 140 va_list ap; 141 142 /* 143 * Make sure that always argvp->argc < argvp->len. 144 */ 145#define ARGV_SPACE_LEFT(a) ((a)->len - (a)->argc - 1) 146 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); 152 } 153 va_end(ap); 154 argvp->argv[argvp->argc] = 0; 155} 156 157/* argv_addn - add string to vector */ 158 159void argv_addn(ARGV *argvp,...) 160{ 161 char *arg; 162 ssize_t len; 163 va_list ap; 164 165 /* 166 * Make sure that always argvp->argc < argvp->len. 167 */ 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); 175 } 176 va_end(ap); 177 argvp->argv[argvp->argc] = 0; 178} 179 180/* argv_terminate - terminate string array */ 181 182void argv_terminate(ARGV *argvp) 183{ 184 185 /* 186 * Trust that argvp->argc < argvp->len. 187 */ 188 argvp->argv[argvp->argc] = 0; 189} 190 191/* argv_truncate - truncate string array */ 192 193void argv_truncate(ARGV *argvp, ssize_t len) 194{ 195 char **cpp; 196 197 /* 198 * Sanity check. 199 */ 200 if (len < 0) 201 msg_panic("argv_truncate: bad length %ld", (long) len); 202 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; 208 } 209} 210