From: Guido Serassio Date: Mon, 30 Jun 2008 10:57:35 +0000 (+0200) Subject: Windows port: forward port of 2.7 lib functions updates X-Git-Tag: SQUID_3_1_0_1~49^2~181 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=63b81f1358cbd117169ecea7fdb2af3052f1aacf;p=thirdparty%2Fsquid.git Windows port: forward port of 2.7 lib functions updates - Implement crypt() on Windows - Implement getopt() on Windows - Implement dirent-style opendir(), readdir(), closedir(), rewinddir(), seekdir() and telldir() on Windows --- diff --git a/CREDITS b/CREDITS index 22712c7f74..89affeba6c 100755 --- a/CREDITS +++ b/CREDITS @@ -318,6 +318,41 @@ lib/strnstr.cc: ============================================================================== +lib/getopt.c: + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; + +============================================================================== + src/external_acl.c Copyright (C) 2002 MARA Systems AB, Sweden diff --git a/lib/Makefile.am b/lib/Makefile.am old mode 100644 new mode 100755 index bacf40d9b0..4781a6d1fc --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -53,7 +53,13 @@ noinst_LIBRARIES = \ libntlmauth.a \ $(LIBSSPWIN32) \ @LIBREGEX@ +# +# dirent.c, ecnrypt.c and getopt.c are needed for native Windows support. +# EXTRA_libmiscutil_a_SOURCES = \ + dirent.c \ + encrypt.c \ + getopt.c \ md5.c \ Profiler.c \ strsep.c \ diff --git a/lib/dirent.c b/lib/dirent.c new file mode 100755 index 0000000000..73ddc05235 --- /dev/null +++ b/lib/dirent.c @@ -0,0 +1,316 @@ +/* + * $Id$ + * + * Implement dirent-style opendir(), readdir(), closedir(), rewinddir(), + * seekdir() and telldir on Windows - Based on mingw-runtime package sources. + * AUTHOR: Guido Serassio + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * Original file info follow: + * + * dirent.c + * This file has no copyright assigned and is placed in the Public Domain. + * This file is a part of the mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER within the package. + * + * Derived from DIRLIB.C by Matt J. Weinstein + * This note appears in the DIRLIB.H + * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 + * + * Updated by Jeremy Bettis + * Significantly revised and rewinddir, seekdir and telldir added by Colin + * Peters + * + */ + +#include "util.h" + +/* The following code section is part of the native Windows Squid port */ +#if defined(_SQUID_MSWIN_) +#include +#include +#include +#include +#include + +#define WIN32_LEAN_AND_MEAN +#include /* for GetFileAttributes */ + +#define SUFFIX ("*") +#define SLASH ("\\") + + +/* + * opendir + * + * Returns a pointer to a DIR structure appropriately filled in to begin + * searching a directory. + */ +DIR * +opendir(const CHAR * szPath) +{ + DIR *nd; + unsigned int rc; + CHAR szFullPath[MAX_PATH]; + + errno = 0; + + if (!szPath) { + errno = EFAULT; + return (DIR *) 0; + } + if (szPath[0] == '\0') { + errno = ENOTDIR; + return (DIR *) 0; + } + /* Attempt to determine if the given path really is a directory. */ + rc = GetFileAttributes(szPath); + if (rc == (unsigned int) -1) { + /* call GetLastError for more error info */ + errno = ENOENT; + return (DIR *) 0; + } + if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) { + /* Error, entry exists but not a directory. */ + errno = ENOTDIR; + return (DIR *) 0; + } + /* Make an absolute pathname. */ + _fullpath(szFullPath, szPath, MAX_PATH); + + /* Allocate enough space to store DIR structure and the complete + * directory path given. */ + nd = (DIR *) malloc(sizeof(DIR) + (strlen(szFullPath) + + strlen(SLASH) + + strlen(SUFFIX) + 1) + * sizeof(CHAR)); + + if (!nd) { + /* Error, out of memory. */ + errno = ENOMEM; + return (DIR *) 0; + } + /* Create the search expression. */ + strcpy(nd->dd_name, szFullPath); + + /* Add on a slash if the path does not end with one. */ + if (nd->dd_name[0] != '\0' + && strchr(nd->dd_name, '/') != nd->dd_name + + strlen(nd->dd_name) - 1 + && strchr(nd->dd_name, '\\') != nd->dd_name + + strlen(nd->dd_name) - 1) { + strcat(nd->dd_name, SLASH); + } + /* Add on the search pattern */ + strcat(nd->dd_name, SUFFIX); + + /* Initialize handle to -1 so that a premature closedir doesn't try + * to call _findclose on it. */ + nd->dd_handle = -1; + + /* Initialize the status. */ + nd->dd_stat = 0; + + /* Initialize the dirent structure. ino and reclen are invalid under + * Win32, and name simply points at the appropriate part of the + * findfirst_t structure. */ + nd->dd_dir.d_ino = 0; + nd->dd_dir.d_reclen = 0; + nd->dd_dir.d_namlen = 0; + memset(nd->dd_dir.d_name, 0, FILENAME_MAX); + + return nd; +} + + +/* + * readdir + * + * Return a pointer to a dirent structure filled with the information on the + * next entry in the directory. + */ +struct dirent * +readdir(DIR * dirp) +{ + errno = 0; + + /* Check for valid DIR struct. */ + if (!dirp) { + errno = EFAULT; + return (struct dirent *) 0; + } + if (dirp->dd_stat < 0) { + /* We have already returned all files in the directory + * (or the structure has an invalid dd_stat). */ + return (struct dirent *) 0; + } else if (dirp->dd_stat == 0) { + /* We haven't started the search yet. */ + /* Start the search */ + dirp->dd_handle = _findfirst(dirp->dd_name, &(dirp->dd_dta)); + + if (dirp->dd_handle == -1) { + /* Whoops! Seems there are no files in that + * directory. */ + dirp->dd_stat = -1; + } else { + dirp->dd_stat = 1; + } + } else { + /* Get the next search entry. */ + if (_findnext(dirp->dd_handle, &(dirp->dd_dta))) { + /* We are off the end or otherwise error. + * _findnext sets errno to ENOENT if no more file + * Undo this. */ + DWORD winerr = GetLastError(); + if (winerr == ERROR_NO_MORE_FILES) + errno = 0; + _findclose(dirp->dd_handle); + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } else { + /* Update the status to indicate the correct + * number. */ + dirp->dd_stat++; + } + } + + if (dirp->dd_stat > 0) { + /* Successfully got an entry. Everything about the file is + * already appropriately filled in except the length of the + * file name. */ + dirp->dd_dir.d_namlen = strlen(dirp->dd_dta.name); + strcpy(dirp->dd_dir.d_name, dirp->dd_dta.name); + return &dirp->dd_dir; + } + return (struct dirent *) 0; +} + + +/* + * closedir + * + * Frees up resources allocated by opendir. + */ +int +closedir(DIR * dirp) +{ + int rc; + + errno = 0; + rc = 0; + + if (!dirp) { + errno = EFAULT; + return -1; + } + if (dirp->dd_handle != -1) { + rc = _findclose(dirp->dd_handle); + } + /* Delete the dir structure. */ + free(dirp); + + return rc; +} + +/* + * rewinddir + * + * Return to the beginning of the directory "stream". We simply call findclose + * and then reset things like an opendir. + */ +void +rewinddir(DIR * dirp) +{ + errno = 0; + + if (!dirp) { + errno = EFAULT; + return; + } + if (dirp->dd_handle != -1) { + _findclose(dirp->dd_handle); + } + dirp->dd_handle = -1; + dirp->dd_stat = 0; +} + +/* + * telldir + * + * Returns the "position" in the "directory stream" which can be used with + * seekdir to go back to an old entry. We simply return the value in stat. + */ +long +telldir(DIR * dirp) +{ + errno = 0; + + if (!dirp) { + errno = EFAULT; + return -1; + } + return dirp->dd_stat; +} + +/* + * seekdir + * + * Seek to an entry previously returned by telldir. We rewind the directory + * and call readdir repeatedly until either dd_stat is the position number + * or -1 (off the end). This is not perfect, in that the directory may + * have changed while we weren't looking. But that is probably the case with + * any such system. + */ +void +seekdir(DIR * dirp, long lPos) +{ + errno = 0; + + if (!dirp) { + errno = EFAULT; + return; + } + if (lPos < -1) { + /* Seeking to an invalid position. */ + errno = EINVAL; + return; + } else if (lPos == -1) { + /* Seek past end. */ + if (dirp->dd_handle != -1) { + _findclose(dirp->dd_handle); + } + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } else { + /* Rewind and read forward to the appropriate index. */ + rewinddir(dirp); + + while ((dirp->dd_stat < lPos) && readdir(dirp)); + } +} +#endif /* _SQUID_MSWIN_ */ diff --git a/lib/encrypt.c b/lib/encrypt.c new file mode 100755 index 0000000000..f5ee0942e0 --- /dev/null +++ b/lib/encrypt.c @@ -0,0 +1,309 @@ +/* encrypt.c - providing 56 bit DES encryption + * Copyright (C) 1991 Jochen Obalek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include + +#define BS 64 +#define BS2 32 +#define KS 48 +#define KS2 24 +#define IS 56 +#define IS2 28 + +static char schluessel[16][KS]; + + +static char PC1[] = +{ + 56, 48, 40, 32, 24, 16, 8, 0, + 57, 49, 41, 33, 25, 17, 9, 1, + 58, 50, 42, 34, 26, 18, 10, 2, + 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, + 61, 53, 45, 37, 29, 21, 13, 5, + 60, 52, 44, 36, 28, 20, 12, 4, + 27, 19, 11, 3 +}; + + +static char PC2[] = +{ + 13, 16, 10, 23, 0, 4, 2, 27, + 14, 5, 20, 9, 22, 18, 11, 3, + 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, + 50, 44, 32, 47, 43, 48, 38, 55, + 33, 52, 45, 41, 49, 35, 28, 31 +}; + + +static char IP[] = +{ + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7, + 56, 48, 40, 32, 24, 16, 8, 0, + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6 +}; + + +static char EP[] = +{ + 7, 39, 15, 47, 23, 55, 31, 63, + 6, 38, 14, 46, 22, 54, 30, 62, + 5, 37, 13, 45, 21, 53, 29, 61, + 4, 36, 12, 44, 20, 52, 28, 60, + 3, 35, 11, 43, 19, 51, 27, 59, + 2, 34, 10, 42, 18, 50, 26, 58, + 1, 33, 9, 41, 17, 49, 25, 57, + 0, 32, 8, 40, 16, 48, 24, 56 +}; + + +static char E0[] = +{ + 31, 0, 1, 2, 3, 4, 3, 4, + 5, 6, 7, 8, 7, 8, 9, 10, + 11, 12, 11, 12, 13, 14, 15, 16, + 15, 16, 17, 18, 19, 20, 19, 20, + 21, 22, 23, 24, 23, 24, 25, 26, + 27, 28, 27, 28, 29, 30, 31, 0 +}; + + +static char E[KS]; + + +static char PERM[] = +{ + 15, 6, 19, 20, 28, 11, 27, 16, + 0, 14, 22, 25, 4, 17, 30, 9, + 1, 7, 23, 13, 31, 26, 2, 8, + 18, 12, 29, 5, 21, 10, 3, 24 +}; + + +static char S_BOX[][64] = +{ + { + 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, + 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8, + 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, + 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13 + }, + { + 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14, + 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, + 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2, + 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9 + }, + { + 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10, + 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, + 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, + 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12 + }, + { + 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, + 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9, + 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, + 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14 + }, + { + 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1, + 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, + 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13, + 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3 + }, + { + 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5, + 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8, + 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, + 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13 + }, + { + 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, + 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6, + 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, + 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12 + }, + { + 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4, + 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, + 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, + 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11 + } +}; + +static void +perm(a, e, pc, n) + register char *a, *e; + register char *pc; + int n; +{ + for (; n--; pc++, a++) + *a = e[*pc]; +} + +static void +crypt_main(nachr_l, nachr_r, schl) + register char *nachr_l, *nachr_r; + register char *schl; +{ + char tmp[KS]; + register int sbval; + register char *tp = tmp; + register char *e = E; + register int i, j; + + for (i = 0; i < 8; i++) { + for (j = 0, sbval = 0; j < 6; j++) + sbval = (sbval << 1) | (nachr_r[*e++] ^ *schl++); + sbval = S_BOX[i][sbval]; + for (tp += 4, j = 4; j--; sbval >>= 1) + *--tp = sbval & 1; + tp += 4; + } + + e = PERM; + for (i = 0; i < BS2; i++) + *nachr_l++ ^= tmp[*e++]; +} + +void +encrypt(char *nachr, int decr) +{ + char (*schl)[KS] = decr ? schluessel + 15 : schluessel; + char tmp[BS]; + int i; + + perm(tmp, nachr, IP, BS); + + for (i = 8; i--;) { + crypt_main(tmp, tmp + BS2, *schl); + if (decr) + schl--; + else + schl++; + crypt_main(tmp + BS2, tmp, *schl); + if (decr) + schl--; + else + schl++; + } + + perm(nachr, tmp, EP, BS); +} + +void +setkey(char *schl) +{ + char tmp1[IS]; + register unsigned int ls = 0x7efc; + register int i, j, k; + register int shval = 0; + register char *akt_schl; + + memcpy(E, E0, KS); + perm(tmp1, schl, PC1, IS); + + for (i = 0; i < 16; i++) { + shval += 1 + (ls & 1); + akt_schl = schluessel[i]; + for (j = 0; j < KS; j++) { + if ((k = PC2[j]) >= IS2) { + if ((k += shval) >= IS) + k = (k - IS2) % IS2 + IS2; + } else if ((k += shval) >= IS2) + k %= IS2; + *akt_schl++ = tmp1[k]; + } + ls >>= 1; + } +} + +char * +crypt(const char *wort, const char *salt) +{ + static char retkey[14]; + char key[BS + 2]; + char *k; + int tmp, keybyte; + int i, j; + + memset(key, 0, BS + 2); + + for (k = key, i = 0; i < BS; i++) { + if (!(keybyte = *wort++)) + break; + k += 7; + for (j = 0; j < 7; j++, i++) { + *--k = keybyte & 1; + keybyte >>= 1; + } + k += 8; + } + + setkey(key); + memset(key, 0, BS + 2); + + for (k = E, i = 0; i < 2; i++) { + retkey[i] = keybyte = *salt++; + if (keybyte > 'Z') + keybyte -= 'a' - 'Z' - 1; + if (keybyte > '9') + keybyte -= 'A' - '9' - 1; + keybyte -= '.'; + + for (j = 0; j < 6; j++, keybyte >>= 1, k++) { + if (!(keybyte & 1)) + continue; + tmp = *k; + *k = k[24]; + k[24] = tmp; + } + } + + for (i = 0; i < 25; i++) + encrypt(key, 0); + + for (k = key, i = 0; i < 11; i++) { + for (j = keybyte = 0; j < 6; j++) { + keybyte <<= 1; + keybyte |= *k++; + } + + keybyte += '.'; + if (keybyte > '9') + keybyte += 'A' - '9' - 1; + if (keybyte > 'Z') + keybyte += 'a' - 'Z' - 1; + retkey[i + 2] = keybyte; + } + + retkey[i + 2] = 0; + + if (!retkey[1]) + retkey[1] = *retkey; + + return retkey; +} diff --git a/lib/getopt.c b/lib/getopt.c new file mode 100755 index 0000000000..f5d4a51f27 --- /dev/null +++ b/lib/getopt.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +int opterr = 1, /* if error message should be printed */ + optind = 1, /* index into parent argv vector */ + optopt, /* character checked for validity */ + optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +/* + * getopt -- + * Parse argc/argv argument vector. + */ +int +getopt(nargc, nargv, ostr) + int nargc; + char *const *nargv; + const char *ostr; +{ + static char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc || *(place = nargv[optind]) != '-') { + place = EMSG; + return (-1); + } + if (place[1] && *++place == '-') { /* found "--" */ + ++optind; + place = EMSG; + return (-1); + } + } /* option letter okay? */ + if ((optopt = (int) *place++) == (int) ':' || + !(oli = strchr(ostr, optopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (optopt == (int) '-') + return (-1); + if (!*place) + ++optind; + if (opterr && *ostr != ':') + (void) fprintf(stderr, + "%s: illegal option -- %c\n", __FILE__, optopt); + return (BADCH); + } + if (*++oli != ':') { /* don't need argument */ + optarg = NULL; + if (!*place) + ++optind; + } else { /* need an argument */ + if (*place) /* no white space */ + optarg = place; + else if (nargc <= ++optind) { /* no arg */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (opterr) + (void) fprintf(stderr, + "%s: option requires an argument -- %c\n", + __FILE__, optopt); + return (BADCH); + } else /* white space */ + optarg = nargv[optind]; + place = EMSG; + ++optind; + } + return (optopt); /* dump back option letter */ +}