mirror of
https://git.proxmox.com/git/proxmox-spamassassin
synced 2025-04-28 16:01:29 +00:00
352 lines
9.8 KiB
C
352 lines
9.8 KiB
C
/* <@LICENSE>
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to you under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
* </@LICENSE>
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include "getopt.h"
|
|
|
|
#ifdef WIN32
|
|
|
|
#ifdef _MSC_VER
|
|
/* ignore MSVC++ warnings that are annoying and hard to remove:
|
|
4702 unreachable code
|
|
(there is an unreachable assert(0) in case somehow it is reached)
|
|
*/
|
|
#pragma warning( disable : 4702 )
|
|
#endif
|
|
|
|
#endif /* WIN32 */
|
|
|
|
#define OPTERRCOLON (1)
|
|
#define OPTERRNF (2)
|
|
#define OPTERRARG (3)
|
|
|
|
char *spamc_optarg;
|
|
int spamc_optreset = 0;
|
|
int spamc_optind = 1;
|
|
int spamc_opterr = 1;
|
|
int spamc_optopt;
|
|
|
|
static int
|
|
optiserr(int argc, char * const *argv, int oint, const char *optstr,
|
|
int optchr, int err)
|
|
{
|
|
(void) argc; /* not used */
|
|
(void) optstr; /* not used */
|
|
if(spamc_opterr)
|
|
{
|
|
fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1);
|
|
switch(err)
|
|
{
|
|
case OPTERRCOLON:
|
|
fprintf(stderr, ": in flags\n");
|
|
break;
|
|
case OPTERRNF:
|
|
fprintf(stderr, "option not found %c\n", argv[oint][optchr]);
|
|
break;
|
|
case OPTERRARG:
|
|
fprintf(stderr, "argument required for option %c\n", argv[oint][optchr]);
|
|
break;
|
|
default:
|
|
fprintf(stderr, "unknown\n");
|
|
break;
|
|
}
|
|
}
|
|
spamc_optopt = argv[oint][optchr];
|
|
return('?');
|
|
}
|
|
|
|
static int
|
|
longoptiserr(int argc, char * const *argv, int oint, int err)
|
|
{
|
|
(void) argc; /* not used */
|
|
if(spamc_opterr)
|
|
{
|
|
fprintf(stderr, "Error in argument %d : ", oint);
|
|
switch(err)
|
|
{
|
|
case OPTERRCOLON:
|
|
fprintf(stderr, ": in flags\n");
|
|
break;
|
|
case OPTERRNF:
|
|
fprintf(stderr, "option not found %s\n", argv[oint]);
|
|
break;
|
|
case OPTERRARG:
|
|
fprintf(stderr, "argument required for option %s\n", argv[oint]);
|
|
break;
|
|
default:
|
|
fprintf(stderr, "unknown\n");
|
|
break;
|
|
}
|
|
}
|
|
return('?');
|
|
}
|
|
|
|
int
|
|
spamc_getopt(int argc, char* const *argv, const char *optstr)
|
|
{
|
|
static int optchr = 0;
|
|
static int dash = 0; /* have already seen the - */
|
|
|
|
char *cp;
|
|
|
|
if (spamc_optreset)
|
|
spamc_optreset = optchr = dash = 0;
|
|
if(spamc_optind >= argc)
|
|
return(EOF);
|
|
if(!dash && (argv[spamc_optind][0] != '-'))
|
|
return(EOF);
|
|
if(!dash && (argv[spamc_optind][0] == '-') && !argv[spamc_optind][1])
|
|
{
|
|
/*
|
|
* use to specify stdin. Need to let pgm process this and
|
|
* the following args
|
|
*/
|
|
return(EOF);
|
|
}
|
|
if((argv[spamc_optind][0] == '-') && (argv[spamc_optind][1] == '-'))
|
|
{
|
|
/* -- indicates end of args */
|
|
spamc_optind++;
|
|
return(EOF);
|
|
}
|
|
if(!dash)
|
|
{
|
|
assert((argv[spamc_optind][0] == '-') && argv[spamc_optind][1]);
|
|
dash = 1;
|
|
optchr = 1;
|
|
}
|
|
|
|
/* Check if the guy tries to do a -: kind of flag */
|
|
assert(dash);
|
|
if(argv[spamc_optind][optchr] == ':')
|
|
{
|
|
dash = 0;
|
|
spamc_optind++;
|
|
return(optiserr(argc, argv, spamc_optind-1, optstr, optchr, OPTERRCOLON));
|
|
}
|
|
cp = strchr(optstr, argv[spamc_optind][optchr]);
|
|
if(!cp)
|
|
{
|
|
int errind = spamc_optind;
|
|
int errchr = optchr;
|
|
|
|
if(!argv[spamc_optind][optchr+1])
|
|
{
|
|
dash = 0;
|
|
spamc_optind++;
|
|
}
|
|
else
|
|
optchr++;
|
|
return(optiserr(argc, argv, errind, optstr, errchr, OPTERRNF));
|
|
}
|
|
if(cp[1] == ':')
|
|
{
|
|
dash = 0;
|
|
spamc_optind++;
|
|
if(spamc_optind == argc)
|
|
return(optiserr(argc, argv, spamc_optind-1, optstr, optchr, OPTERRARG));
|
|
spamc_optarg = argv[spamc_optind++];
|
|
return(*cp);
|
|
}
|
|
else
|
|
{
|
|
if(!argv[spamc_optind][optchr+1])
|
|
{
|
|
dash = 0;
|
|
spamc_optind++;
|
|
}
|
|
else
|
|
optchr++;
|
|
return(*cp);
|
|
}
|
|
assert(0);
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
spamc_getopt_long(int argc, char * const argv[],
|
|
const char *optstring, struct option *longopts,
|
|
int *longindex)
|
|
{
|
|
static int optchr = 0;
|
|
static int dash = 0;
|
|
char *cp, *longopt;
|
|
char *bp, *opt = NULL;
|
|
int i, longoptlen;;
|
|
|
|
spamc_optarg = NULL; /* clear any left over state from previous option */
|
|
if(spamc_optreset)
|
|
spamc_optreset = optchr = dash = 0;
|
|
if(spamc_optind >= argc) {
|
|
return(EOF);
|
|
}
|
|
if(!dash && (argv[spamc_optind][0] != '-')) {
|
|
return(EOF);
|
|
}
|
|
if(!dash && (argv[spamc_optind][0] == '-') && !argv[spamc_optind][1]) {
|
|
/* used to specify stdin */
|
|
return(EOF);
|
|
}
|
|
if((argv[spamc_optind][0] == '-') && (argv[spamc_optind][1] == '-')
|
|
&& !argv[spamc_optind][2]) {
|
|
/* used to specify end of args */
|
|
return(EOF);
|
|
}
|
|
if((argv[spamc_optind][0] == '-') && argv[spamc_optind][1] &&
|
|
(argv[spamc_optind][1] != '-')) {
|
|
/* short option */
|
|
optchr = 1;
|
|
if(argv[spamc_optind][optchr] == ':')
|
|
return(optiserr(argc, argv, spamc_optind++, optstring, optchr, OPTERRCOLON));
|
|
|
|
cp = strchr(optstring, argv[spamc_optind++][optchr]);
|
|
if(cp == NULL)
|
|
return(optiserr(argc, argv, spamc_optind-1, optstring, optchr, OPTERRNF));
|
|
if(cp[1] == ':') {
|
|
/* requires an argument */
|
|
if(!argv[spamc_optind] || (argv[spamc_optind][0] == '-') ||
|
|
(spamc_optind >= argc)) {
|
|
return(optiserr(argc, argv, spamc_optind-1, optstring, optchr, OPTERRARG));
|
|
}
|
|
spamc_optarg = argv[spamc_optind++];
|
|
return(*cp);
|
|
} else {
|
|
dash = 0;
|
|
return(*cp);
|
|
}
|
|
}
|
|
if((argv[spamc_optind][0] == '-') && (argv[spamc_optind][1] == '-') &&
|
|
argv[spamc_optind][2]) {
|
|
/* long option */
|
|
optchr = 2;
|
|
longopt = argv[spamc_optind++];
|
|
if(longopt[2] == ':')
|
|
return(longoptiserr(argc, argv, spamc_optind, OPTERRCOLON));
|
|
longoptlen = strlen(longopt) - 2;
|
|
if((bp = strchr(longopt, '='))) {
|
|
opt = strdup(bp+1);
|
|
if (opt == NULL) {
|
|
fprintf(stderr, "%s: %s\n", argv[0], strerror(errno));
|
|
exit(1);
|
|
}
|
|
longoptlen -= strlen(bp);
|
|
}
|
|
|
|
for(i=0; ; i++) {
|
|
/* changed to longopts[i].name[0] == 0 - bug 7148 */
|
|
if((longopts[i].name == NULL) || (longopts[i].name[0] == 0)) {
|
|
free(opt);
|
|
return(longoptiserr(argc, argv, spamc_optind-1, OPTERRNF));
|
|
}
|
|
if(((strncmp(longopt+2, longopts[i].name, longoptlen)) == 0) && (strlen(longopts[i].name) == longoptlen)) {
|
|
*longindex = i;
|
|
if(longopts[i].has_arg == required_argument) {
|
|
if(((spamc_optind >= argc) || (!argv[spamc_optind]) || (argv[spamc_optind][0] == '-')) &&
|
|
(opt == NULL)) {
|
|
free(opt);
|
|
return(longoptiserr(argc, argv, spamc_optind-1, OPTERRARG));
|
|
}
|
|
if(opt != NULL) {
|
|
spamc_optarg = opt;
|
|
} else {
|
|
spamc_optarg = argv[spamc_optind++];
|
|
}
|
|
} else if(longopts[i].has_arg == optional_argument) {
|
|
if(((spamc_optind < argc) && (argv[spamc_optind]) && (argv[spamc_optind][0] != '-')) ||
|
|
(opt != NULL)) {
|
|
if(opt != NULL) {
|
|
spamc_optarg = opt;
|
|
} else {
|
|
spamc_optarg = argv[spamc_optind++];
|
|
}
|
|
}
|
|
}
|
|
if(longopts[i].flag == NULL) {
|
|
return(longopts[i].val);
|
|
} else {
|
|
*longopts[i].flag = longopts[i].val;
|
|
return(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(0); /* should never reach here */
|
|
}
|
|
|
|
#ifdef TESTGETOPT
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
int c, l;
|
|
extern char *spamc_optarg;
|
|
extern int spamc_optind;
|
|
int aflg = 0;
|
|
int bflg = 0;
|
|
int errflg = 0;
|
|
char *ofile = NULL;
|
|
struct option longopts[] = {
|
|
{ "test", required_argument, 0, 't' },
|
|
};
|
|
|
|
while ((c = spamc_getopt(argc, argv, "abo:")) != EOF)
|
|
switch (c) {
|
|
case 'a':
|
|
if (bflg)
|
|
errflg++;
|
|
else
|
|
aflg++;
|
|
break;
|
|
case 'b':
|
|
if (aflg)
|
|
errflg++;
|
|
else
|
|
bflg++;
|
|
break;
|
|
case 'o':
|
|
ofile = spamc_optarg;
|
|
(void)printf("ofile = %s\n", ofile);
|
|
break;
|
|
case '?':
|
|
errflg++;
|
|
}
|
|
|
|
while((l = spamc_getopt_long(argc, argv, "t:", longopts, &l)) != EOF)
|
|
switch(l) {
|
|
case 't':
|
|
printf("--test = %s\n",spamc_optarg);
|
|
break;
|
|
}
|
|
|
|
if (errflg) {
|
|
(void)fprintf(stderr,
|
|
"usage: cmd [-a|-b] [-o <filename>] files...\n");
|
|
exit (2);
|
|
}
|
|
/*for ( ; spamc_optind < argc; spamc_optind++)
|
|
* (void)printf("%s\n", argv[spamc_optind]);
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
#endif /* TESTGETOPT */
|