"Fossies" - the Fresh Open Source Software archive 
Member "oidentd-2.0.8/src/oidentd_options.c" of archive oidentd-2.0.8.tar.gz:
/*
** oidentd_options.c - oidentd command-line handler.
** Copyright (C) 2001-2006 Ryan McCabe <ryan@numb.org>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License, version 2,
** as published by the Free Software Foundation.
**
** 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-1307, USA
*/
#define _GNU_SOURCE
#include <config.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <syslog.h>
#include <getopt.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <oidentd.h>
#include <oidentd_util.h>
#include <oidentd_missing.h>
#include <oidentd_inet_util.h>
#include <oidentd_user_db.h>
#include <oidentd_options.h>
#ifdef MASQ_SUPPORT
# define OPTSTRING "a:c:C:def::g:hiIl:mo::p:P:qr:St:u:Uv"
extern in_port_t fwdport;
#else
# define OPTSTRING "a:c:C:deg:hiIl:o::p:P:qr:St:u:Uv"
#endif
extern struct sockaddr_storage proxy;
extern char *failuser;
extern char *ret_os;
extern char *config_file;
extern u_int32_t timeout;
extern u_int32_t connection_limit;
extern in_port_t listen_port;
extern struct sockaddr_storage *addr;
extern uid_t uid;
extern gid_t gid;
static void print_usage(void);
static void print_version(void);
static inline void enable_opt(u_int32_t option);
static const struct option longopts[] = {
{"address", required_argument, 0, 'a'},
{"charset", required_argument, 0, 'c'},
{"config", required_argument, 0, 'C'},
{"debug", no_argument, 0, 'd'},
{"error", no_argument, 0, 'e'},
{"group", required_argument, 0, 'g'},
{"help", no_argument, 0, 'h'},
{"foreground", no_argument, 0, 'i'},
{"stdio", no_argument, 0, 'I'},
{"limit", required_argument, 0, 'l'},
{"other", optional_argument, 0, 'o'},
{"port", required_argument, 0, 'p'},
{"quiet", no_argument, 0, 'q'},
{"reply", required_argument, 0, 'r'},
{"nosyslog", no_argument, 0, 'S'},
{"timeout", required_argument, 0, 't'},
{"user", required_argument, 0, 'u'},
#ifdef HAVE_LIBUDB
{"udb", no_argument, 0, 'U'},
#endif
{"version", no_argument, 0, 'v'},
#ifdef MASQ_SUPPORT
{"forward", optional_argument, 0, 'f'},
{"masquerade", no_argument, 0, 'm'},
#endif
{"proxy", required_argument, 0, 'P'},
{NULL, 0, NULL, 0}
};
static u_int32_t flags;
/*
** Returns true if "option" is enabled, false if it isn't.
*/
inline bool opt_enabled(u_int32_t option) {
return ((flags & option) != 0);
}
/*
** Enables "option."
*/
static inline void enable_opt(u_int32_t option) {
flags |= option;
}
/*
** Disables "option."
*/
inline void disable_opt(u_int32_t option) {
flags &= ~option;
}
/*
** Parse any arguments passed to the program.
** Returns 0 on success, -1 on failure.
*/
int get_options(int argc, char *const argv[]) {
int opt;
char *temp_os;
char *charset = NULL;
#ifdef MASQ_SUPPORT
if (get_port(DEFAULT_FPORT, &fwdport) == -1) {
o_log(NORMAL, "Fatal: Bad port: \"%s\"", DEFAULT_FPORT);
return (-1);
}
fwdport = htons(fwdport);
#endif
connection_limit = 0xffffffff;
config_file = xstrdup(CONFFILE);
temp_os = xstrdup("UNIX");
if (get_port(DEFAULT_PORT, &listen_port) == -1) {
o_log(NORMAL, "Fatal: Bad port: \"%s\"", DEFAULT_PORT);
return (-1);
}
while ((opt = getopt_long(argc, argv, OPTSTRING, longopts, NULL)) != EOF) {
switch (opt) {
case 'a': {
struct sockaddr_storage *temp_ss =
xmalloc(sizeof(struct sockaddr_storage));
if (get_addr(optarg, temp_ss) == -1) {
o_log(NORMAL, "Fatal: Unknown host: \"%s\"", optarg);
free(temp_ss);
return (-1);
}
addr = temp_ss;
break;
}
case 'c':
if (charset != NULL)
free(charset);
charset = xstrdup(optarg);
break;
case 'C':
if (config_file != NULL)
free(config_file);
config_file = xstrdup(optarg);
break;
case 'd':
enable_opt(DEBUG_MSGS);
break;
case 'e':
enable_opt(HIDE_ERRORS);
break;
#ifdef MASQ_SUPPORT
case 'f':
{
const char *p;
if (optarg == NULL)
p = DEFAULT_FPORT;
else
p = optarg;
if (get_port(p, &fwdport) == -1) {
o_log(NORMAL, "Fatal: Bad port: \"%s\"", p);
return (-1);
}
fwdport = htons(fwdport);
enable_opt(FORWARD);
break;
}
case 'm':
enable_opt(MASQ);
break;
#endif
case 'P':
{
if (get_addr(optarg, &proxy) == -1) {
o_log(NORMAL, "Fatal: Unknown host: \"%s\"", optarg);
return (-1);
}
enable_opt(PROXY);
break;
}
case 'g':
enable_opt(CHANGE_GID);
if (find_group(optarg, &gid) == -1) {
o_log(NORMAL, "Fatal: Unknown group: \"%s\"", optarg);
return (-1);
}
break;
/* pre-connected, as when run from inetd */
case 'I':
enable_opt(STDIO | FOREGROUND);
break;
/* do not become a daemon */
case 'i':
enable_opt(FOREGROUND);
break;
case 'l':
{
u_int32_t temp_limit;
char *end;
temp_limit = strtoul(optarg, &end, 10);
if (*end != '\0') {
o_log(NORMAL, "Fatal: Not a valid number: \"%s\"", optarg);
return (-1);
}
connection_limit = temp_limit;
}
case 'o':
if (temp_os != NULL)
free(temp_os);
if (optarg != NULL) {
char *p;
temp_os = xstrdup(optarg);
p = strchr(temp_os, '\n');
if (p != NULL)
*p = '\0';
p = strchr(temp_os, '\r');
if (p != NULL)
*p = '\0';
} else
temp_os = xstrdup("OTHER");
break;
case 'p':
if (get_port(optarg, &listen_port) == -1) {
o_log(NORMAL, "Fatal: Bad port: \"%s\"", optarg);
return (-1);
}
break;
case 'q':
enable_opt(QUIET);
break;
case 'r':
if (failuser != NULL)
free(failuser);
failuser = xstrdup(optarg);
break;
case 'S':
enable_opt(NOSYSLOG);
break;
case 't':
{
char *end;
timeout = strtoul(optarg, &end, 10);
if (*end != '\0') {
o_log(NORMAL, "Fatal: Bad timeout value: \"%s\"", optarg);
return (-1);
}
break;
}
case 'u':
enable_opt(CHANGE_UID);
if (find_user(optarg, &uid) == -1) {
o_log(NORMAL, "Fatal: Unknown user: \"%s\"", optarg);
return (-1);
}
break;
#ifdef HAVE_LIBUDB
case 'U':
enable_opt(USEUDB);
break;
#endif
case 'v':
print_version();
return (-1);
case 'h':
default:
print_usage();
return (-1);
}
}
if (charset != NULL) {
size_t len = strlen(temp_os) + strlen(charset) + 4;
ret_os = xmalloc(len);
snprintf(ret_os, len, "%s , %s", temp_os, charset);
free(temp_os);
free(charset);
} else
ret_os = temp_os;
if (opt_enabled(DEBUG_MSGS) && opt_enabled(QUIET)) {
o_log(NORMAL, "Fatal: The debug and quiet flags are incompatible");
return (-1);
}
/*
** If no user was specified, use a reasonable default.
*/
if (!opt_enabled(CHANGE_UID)) {
if (find_user("nobody", &uid) == -1) {
o_log(NORMAL,
"user \"nobody\" does not exist. Using %u as default UID",
DEFAULT_UID);
uid = DEFAULT_UID;
}
}
/*
** If no group is specified, use a reasonable default.
*/
if (!opt_enabled(CHANGE_GID)) {
if (find_group("nobody", &gid) == -1) {
if (find_group("nogroup", &gid) == -1) {
o_log(NORMAL,
"Groups \"nobody\" and \"nogroup\" do not exist. Using %u as default GID",
DEFAULT_GID);
gid = DEFAULT_GID;
}
}
}
return (0);
}
static void print_usage(void) {
const char usage[] =
"\nUsage: oidentd [options]\n"
"-a or --address <address> Bind to <address>\n"
"-c or --charset <charset> Specify an alternate charset\n"
"-C or --config <config file> Use the specifed file instead of /etc/oidentd.conf\n"
"-d or --debug Enable debugging\n"
"-e or --error Return \"UNKNOWN-ERROR\" for all errors\n"
#ifdef MASQ_SUPPORT
"-f or --forward [<port>] Forward requests for masqueraded hosts to the host on port <port>\n"
"-m or --masquerade Enable support for IP masquerading\n"
#endif
"-P or --proxy <host> <host> acts as a proxy, forwarding connections to us\n"
"-g or --group <group> Run with specified group or GID\n"
"-i or --foreground Don't run as a daemon\n"
"-I or --stdio Service a single client connected to stdin/stdout then exit (use when oidentd is running from inetd/xinetd/etc).\n"
"-l or --limit <number> Limit the number of open connections to the specified number\n"
"-o or --other [<os>] Return <os> instead of the operating system. Uses \"OTHER\" if no argument is given.\n"
"-p or --port <port> Listen for connections on specified port\n"
"-q or --quiet Suppress normal logging\n"
"-S or --nosyslog Write messages to stderr not syslog\n"
"-t or --timeout <seconds> Wait for <seconds> before closing connection\n"
"-u or --user <user> Run as specified user or UID\n"
#ifdef HAVE_LIBUDB
"-U or --udb Perform lookups in UDB shared memory tables\n"
#endif
"-v or --version Display version information and exit\n"
"-r or --reply <string> If a query fails, pretend it succeeded, returning <string>\n"
"-h or --help This help message\n";
print_version();
printf("%s", usage);
}
static void print_version(void) {
printf("%s\n", PACKAGE_STRING);
printf("Written by %s <%s>\n", PACKAGE_AUTHOR, PACKAGE_BUGREPORT);
printf("%s\n", PACKAGE_WEBSITE);
}