1/* $NetBSD: gen-win32.h,v 1.1 2024/02/18 20:57:31 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16/* 17 * Copyright (c) 1987, 1993, 1994 18 * The Regents of the University of California. All rights reserved. 19 * 20 * Redistribution and use in source and binary forms, with or without 21 * modification, are permitted provided that the following conditions 22 * are met: 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 2. Redistributions in binary form must reproduce the above copyright 26 * notice, this list of conditions and the following disclaimer in the 27 * documentation and/or other materials provided with the distribution. 28 * 3. Neither the name of the University nor the names of its contributors 29 * may be used to endorse or promote products derived from this software 30 * without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 */ 44 45/* 46 * \note This file was adapted from the NetBSD project's source tree, RCS ID: 47 * NetBSD: getopt.c,v 1.15 1999/09/20 04:39:37 lukem Exp 48 * 49 * The primary change has been to rename items to the ISC namespace 50 * and format in the ISC coding style. 51 * 52 * This file is responsible for defining two operations that are not 53 * directly portable between Unix-like systems and Windows NT, option 54 * parsing and directory scanning. It is here because it was decided 55 * that the "gen" build utility was not to depend on libisc.a, so 56 * the functions declared in isc/commandline.h and isc/dir.h could not 57 * be used. 58 * 59 * The commandline stuff is pretty much a straight copy from the initial 60 * isc/commandline.c. The dir stuff was shrunk to fit the needs of gen.c. 61 */ 62 63#ifndef DNS_GEN_WIN32_H 64#define DNS_GEN_WIN32_H 1 65 66#include <stdbool.h> 67#include <stdio.h> 68#include <string.h> 69#include <time.h> 70#include <windows.h> 71 72#include <isc/lang.h> 73 74int isc_commandline_index = 1; /* Index into parent argv vector. */ 75int isc_commandline_option; /* Character checked for validity. */ 76 77char *isc_commandline_argument; /* Argument associated with option. */ 78char *isc_commandline_progname; /* For printing error messages. */ 79 80bool isc_commandline_errprint = true; /* Print error messages. */ 81bool isc_commandline_reset = true; /* Reset processing. */ 82 83#define BADOPT '?' 84#define BADARG ':' 85#define ENDOPT "" 86 87ISC_LANG_BEGINDECLS 88 89/* 90 * getopt -- 91 * Parse argc/argv argument vector. 92 */ 93int 94isc_commandline_parse(int argc, char *const *argv, const char *options) { 95 static char *place = ENDOPT; 96 char *option; /* Index into *options of option. */ 97 98 /* 99 * Update scanning pointer, either because a reset was requested or 100 * the previous argv was finished. 101 */ 102 if (isc_commandline_reset || *place == '\0') { 103 isc_commandline_reset = false; 104 105 if (isc_commandline_progname == NULL) { 106 isc_commandline_progname = argv[0]; 107 } 108 109 if (isc_commandline_index >= argc || 110 *(place = argv[isc_commandline_index]) != '-') 111 { 112 /* 113 * Index out of range or points to non-option. 114 */ 115 place = ENDOPT; 116 return (-1); 117 } 118 119 if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { 120 /* 121 * Found '--' to signal end of options. Advance 122 * index to next argv, the first non-option. 123 */ 124 isc_commandline_index++; 125 place = ENDOPT; 126 return (-1); 127 } 128 } 129 130 isc_commandline_option = *place++; 131 option = strchr(options, isc_commandline_option); 132 133 /* 134 * Ensure valid option has been passed as specified by options string. 135 * '-:' is never a valid command line option because it could not 136 * distinguish ':' from the argument specifier in the options string. 137 */ 138 if (isc_commandline_option == ':' || option == NULL) { 139 if (*place == '\0') { 140 isc_commandline_index++; 141 } 142 143 if (isc_commandline_errprint && *options != ':') { 144 fprintf(stderr, "%s: illegal option -- %c\n", 145 isc_commandline_progname, 146 isc_commandline_option); 147 } 148 149 return (BADOPT); 150 } 151 152 if (*++option != ':') { 153 /* 154 * Option does not take an argument. 155 */ 156 isc_commandline_argument = NULL; 157 158 /* 159 * Skip to next argv if at the end of the current argv. 160 */ 161 if (*place == '\0') { 162 ++isc_commandline_index; 163 } 164 } else { 165 /* 166 * Option needs an argument. 167 */ 168 if (*place != '\0') { 169 /* 170 * Option is in this argv, -D1 style. 171 */ 172 isc_commandline_argument = place; 173 } else if (argc > ++isc_commandline_index) { 174 /* 175 * Option is next argv, -D 1 style. 176 */ 177 isc_commandline_argument = argv[isc_commandline_index]; 178 } else { 179 /* 180 * Argument needed, but no more argv. 181 */ 182 place = ENDOPT; 183 184 /* 185 * Silent failure with "missing argument" return 186 * when ':' starts options string, per historical spec. 187 */ 188 if (*options == ':') { 189 return (BADARG); 190 } 191 192 if (isc_commandline_errprint) { 193 fprintf(stderr, 194 "%s: option requires an argument -- " 195 "%c\n", 196 isc_commandline_progname, 197 isc_commandline_option); 198 } 199 200 return (BADOPT); 201 } 202 203 place = ENDOPT; 204 205 /* 206 * Point to argv that follows argument. 207 */ 208 isc_commandline_index++; 209 } 210 211 return (isc_commandline_option); 212} 213 214typedef struct { 215 HANDLE handle; 216 WIN32_FIND_DATA find_data; 217 bool first_file; 218 char *filename; 219} isc_dir_t; 220 221bool 222start_directory(const char *path, isc_dir_t *dir) { 223 char pattern[_MAX_PATH], *p; 224 225 /* 226 * Need space for slash-splat and final NUL. 227 */ 228 if (strlen(path) + 3 > sizeof(pattern)) { 229 return (false); 230 } 231 232 strcpy(pattern, path); 233 234 /* 235 * Append slash (if needed) and splat. 236 */ 237 p = pattern + strlen(pattern); 238 if (p != pattern && p[-1] != '\\' && p[-1] != ':') { 239 *p++ = '\\'; 240 } 241 *p++ = '*'; 242 *p++ = '\0'; 243 244 dir->first_file = true; 245 246 dir->handle = FindFirstFile(pattern, &dir->find_data); 247 248 if (dir->handle == INVALID_HANDLE_VALUE) { 249 dir->filename = NULL; 250 return (false); 251 } else { 252 dir->filename = dir->find_data.cFileName; 253 return (true); 254 } 255} 256 257bool 258next_file(isc_dir_t *dir) { 259 if (dir->first_file) { 260 dir->first_file = false; 261 } else if (dir->handle != INVALID_HANDLE_VALUE) { 262 if (FindNextFile(dir->handle, &dir->find_data) == TRUE) { 263 dir->filename = dir->find_data.cFileName; 264 } else { 265 dir->filename = NULL; 266 } 267 } else { 268 dir->filename = NULL; 269 } 270 271 if (dir->filename != NULL) { 272 return (true); 273 } else { 274 return (false); 275 } 276} 277 278void 279end_directory(isc_dir_t *dir) { 280 if (dir->handle != INVALID_HANDLE_VALUE) { 281 FindClose(dir->handle); 282 } 283} 284 285inline struct tm * 286gmtime_r(const time_t *clock, struct tm *result) { 287 errno_t ret = gmtime_s(result, clock); 288 if (ret != 0) { 289 errno = ret; 290 return (NULL); 291 } 292 return (result); 293} 294 295ISC_LANG_ENDDECLS 296 297#endif /* DNS_GEN_WIN32_H */ 298