very old code commited, ymmv
This commit is contained in:
60
CheckResolv/Makefile
Normal file
60
CheckResolv/Makefile
Normal file
@@ -0,0 +1,60 @@
|
||||
#-------------------------------------------------------------------
|
||||
#
|
||||
# CheckResolv
|
||||
#
|
||||
# editable configuration variables:
|
||||
|
||||
DESTDIR = /usr/local
|
||||
COPT = -g -ansi -Wall
|
||||
|
||||
#
|
||||
# you can now compile with "make checkresolv" and install it
|
||||
# with "su -c 'make install'"
|
||||
#
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
VERSION=0.25
|
||||
|
||||
all:
|
||||
@echo
|
||||
@echo " may be you can read (and edit) the Makefile before"
|
||||
@echo " trying to compile and run that kludge..."
|
||||
@echo
|
||||
@echo " for impatients: try \"make checkresolv\""
|
||||
@echo
|
||||
|
||||
checkresolv.o: checkresolv.c Makefile fonctions.h
|
||||
gcc $(COPT) -c -DVERSION=\"$(VERSION)\" -DTRACE=0 $<
|
||||
|
||||
fonctions.o: fonctions.c Makefile fonctions.h
|
||||
gcc $(COPT) -c -DVERSION=\"$(VERSION)\" -DTRACE=0 $<
|
||||
|
||||
checkresolv: checkresolv.o fonctions.o
|
||||
gcc $(COPT) $^ -o $@
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
#
|
||||
# install procedure is _also_ quick and dirty
|
||||
#
|
||||
install:
|
||||
install --strip checkresolv $(DESTDIR)/bin
|
||||
install checkresolv.man $(DESTDIR)/man/man1/checkresolv.1
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
FILES=*.c *.h Makefile CHANGELOG README TODO checkresolv.man *.html
|
||||
|
||||
TARNAME=checkresolv-$(VERSION).tar.gz
|
||||
|
||||
tarball: $(FILES)
|
||||
@echo "Tarball is" $(TARNAME)
|
||||
@ls $^ > MANIFEST ; \
|
||||
( cd .. ; \
|
||||
tar zcvf $(TARNAME) `sed 's/^/CheckResolv\//' CheckResolv/MANIFEST` )
|
||||
@date >> tarball
|
||||
@wc -c ../$(TARNAME)
|
||||
|
||||
lines: $(FILES)
|
||||
wc $(FILES) | sort -n
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
21
CheckResolv/README.md
Normal file
21
CheckResolv/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
```
|
||||
CheckResolv
|
||||
===========
|
||||
|
||||
This is a quick and dirty hack, built for chasing
|
||||
a LPRng latency problem. Usage is very simple:
|
||||
you give a hostname or an IP addr, and the soft
|
||||
try a few lookup and/or reverse lookup.
|
||||
|
||||
|
||||
Options are:
|
||||
-V display version
|
||||
-r do a reverse lookup
|
||||
-v increase verbosity
|
||||
-e print relateds env vars
|
||||
-t display time op operations
|
||||
|
||||
|
||||
Have a good life, don't release CO2 in the Ternet...
|
||||
|
||||
```
|
||||
12
CheckResolv/TODO
Normal file
12
CheckResolv/TODO
Normal file
@@ -0,0 +1,12 @@
|
||||
This is the TODO file for CheckResolv
|
||||
-------------------------------------
|
||||
|
||||
- virer les GNUismes du Makefile
|
||||
- check for potentials buffers overflows
|
||||
- write a really cut manpage
|
||||
|
||||
- add a function to analyze /etc/resolv.conf
|
||||
- add a function to check /etc/hosts
|
||||
|
||||
- build a fonction for detect DNS used by the resolver.
|
||||
|
||||
238
CheckResolv/checkresolv.c
Normal file
238
CheckResolv/checkresolv.c
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* CheckResolv
|
||||
* ===========
|
||||
*
|
||||
* quick and dirty debugging hack.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#define __USE_BSD
|
||||
#include <string.h>
|
||||
/* #undef __USE_BSD */
|
||||
#include <sys/time.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#define __USE_MISC
|
||||
#include <netdb.h> /* herror ? */
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "fonctions.h"
|
||||
|
||||
char * strdup(char *); /* DIRTY HACK */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* quick and dirty global variables */
|
||||
|
||||
int verbose = 0;
|
||||
int do_reverse = 0;
|
||||
int do_environ = 0;
|
||||
int do_timing = 0;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* parameter '*txt' is not used */
|
||||
int print_hostent(struct hostent *ph, char *txt)
|
||||
{
|
||||
char *ptr, **pptr;
|
||||
|
||||
printf("h_name: %s\n", ph->h_name);
|
||||
|
||||
pptr = ph->h_aliases;
|
||||
if (verbose) {
|
||||
printf("h_aliases: %p -> %p\n", pptr, *pptr);
|
||||
}
|
||||
|
||||
while ( (ptr = *(pptr)) != NULL ) {
|
||||
printf(" alias: %s\n", ptr);
|
||||
pptr++;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("h_addrtype: %d\n", ph->h_addrtype);
|
||||
printf("h_length: %d\n", ph->h_length);
|
||||
}
|
||||
|
||||
print_ip((struct in_addr **)ph->h_addr_list); /* strange cast */
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* If we have a list of IP addr, we can try a
|
||||
* reverse lookup, no ?
|
||||
*/
|
||||
int check_reverse(struct hostent *ph)
|
||||
{
|
||||
struct in_addr **liste;
|
||||
struct in_addr *addr;
|
||||
struct in_addr l_addr; /* Jules */
|
||||
struct hostent *revph;
|
||||
int nbre;
|
||||
double t1 , t2;
|
||||
char *ptmp;
|
||||
|
||||
if (do_timing) t1 = chronometre();
|
||||
|
||||
nbre = 0;
|
||||
liste = (struct in_addr **)ph->h_addr_list;
|
||||
|
||||
while (NULL != (addr = *liste++)) {
|
||||
l_addr = *addr; /* Jules */
|
||||
#if TRACE
|
||||
fprintf(stderr, "---> %p %p\n", addr, l_addr);
|
||||
#endif
|
||||
revph = gethostbyaddr(&l_addr, ph->h_length, ph->h_addrtype);
|
||||
if (NULL != revph) {
|
||||
/* taking over hidden string vars */
|
||||
ptmp = strdup(inet_ntoa(l_addr));
|
||||
if (NULL == ptmp) {
|
||||
fprintf(stderr, "no memory in %s, line %d\n",
|
||||
__FILE__, __LINE__);
|
||||
abort();
|
||||
}
|
||||
#if TRACE
|
||||
fprintf(stderr, "%s:%d %p %p\n", __func__, __LINE__,
|
||||
ptmp, revph->h_name);
|
||||
#endif
|
||||
printf("reverse %-16s -> %s\n", ptmp, revph->h_name);
|
||||
free(ptmp);
|
||||
}
|
||||
else {
|
||||
/* fprintf(stderr, "reverse ? wtf ?\n"); */
|
||||
herror("reverse lookup"); /* this func is obsolete ! */
|
||||
}
|
||||
nbre++;
|
||||
}
|
||||
|
||||
if (do_timing) {
|
||||
t2 = chronometre();
|
||||
if (nbre > 1)
|
||||
printf("reverse take %.3f s (%.3f s)\n", t2-t1, (t2-t1)/nbre);
|
||||
else
|
||||
printf("reverse take %.3f s.\n", t2-t1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
struct hostent *direct_lookup(char *hostname)
|
||||
{
|
||||
struct hostent *p_host;
|
||||
double t1 , t2;
|
||||
int foo;
|
||||
|
||||
if (do_timing) t1 = chronometre();
|
||||
p_host = gethostbyname(hostname);
|
||||
if (do_timing) t2 = chronometre();
|
||||
|
||||
if (p_host==NULL)
|
||||
{
|
||||
fprintf(stderr, "error %d on '%s'", h_errno, hostname);
|
||||
herror(" ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
foo = print_hostent(p_host, NULL);
|
||||
|
||||
if (do_timing) printf("gethostbyname take %.3f s.\n", t2 - t1);
|
||||
|
||||
return p_host;
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
int analyse(char *nom, int flag)
|
||||
{
|
||||
struct hostent *p_host;
|
||||
|
||||
p_host = direct_lookup(nom);
|
||||
|
||||
/*
|
||||
* new, 31 jan 2005, v 0.19
|
||||
* if the requested 'hostname' seems to be an ip address, can we
|
||||
* force a valid reverse lookup ?
|
||||
*/
|
||||
if (is_IP_addr(nom) && !do_reverse)
|
||||
{
|
||||
fprintf(stderr, "* if %s is a valid ip addr, try the '-r' switch.\n",
|
||||
nom);
|
||||
}
|
||||
|
||||
if (do_reverse && (p_host!=NULL))
|
||||
check_reverse(p_host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* Set some global flags, based on our environment
|
||||
* variable.
|
||||
*/
|
||||
void analyze_environ(void)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = getenv("CHECKRESOLV");
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
if ( ! strcmp("tech", ptr) ) {
|
||||
do_reverse = 1;
|
||||
do_timing = 1;
|
||||
}
|
||||
if ( ! strcmp("all", ptr) ) {
|
||||
do_reverse = 1;
|
||||
do_timing = 1;
|
||||
verbose = 1;
|
||||
do_environ = 1;
|
||||
}
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int foo;
|
||||
|
||||
char * liste_opt = "vrhteV";
|
||||
int option;
|
||||
|
||||
if (argc == 1) help_options();
|
||||
|
||||
while ((option=getopt(argc, argv, liste_opt)) != -1)
|
||||
{
|
||||
switch(option)
|
||||
{
|
||||
case 'v': verbose++; break;
|
||||
case 'r': do_reverse=1; break;
|
||||
case 'e': do_environ=1; break;
|
||||
case 't': do_timing=1; break;
|
||||
case 'h': usage(); break;
|
||||
case 'V': version(); break;
|
||||
}
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
fprintf(stderr, "argc %d optind %d\n", argc, optind);
|
||||
for (foo=optind; foo<argc; foo++)
|
||||
{
|
||||
fprintf(stderr, " %4d %s\n", foo, argv[foo]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* env vars can override command line options.
|
||||
*/
|
||||
analyze_environ();
|
||||
|
||||
for (foo=optind; foo<argc; foo++)
|
||||
{
|
||||
printf("------------( %s \n", argv[foo]);
|
||||
analyse(argv[foo], 0);
|
||||
}
|
||||
|
||||
if (do_environ) print_envvars(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
44
CheckResolv/checkresolv.html
Normal file
44
CheckResolv/checkresolv.html
Normal file
@@ -0,0 +1,44 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>CheckResolv</title>
|
||||
<meta name="keywords" content="resolver, BIND, DNS, resolv.conf">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>CheckResolv</h1>
|
||||
|
||||
<p>
|
||||
This is a <i>quick'n'dirty</i> tool for checking the configuration
|
||||
of your local resolver and/or DNS configuration. See the
|
||||
included manpage and source code for more explanations.
|
||||
</p>
|
||||
|
||||
<h2>options</h2>
|
||||
|
||||
<dl> <dt>-V <dd>display version number and exit.
|
||||
<dt>-h <dd>brief help on the command-line options.
|
||||
<dt>-v <dd>display various useless messages.
|
||||
<dt>-r <dd>do reverse lookup on IP address discovered.
|
||||
<dt>-e <dd>show content of a few environment var resolver-related.
|
||||
<dt>-t <dd>compute elapsed time of operation, not really accurate.
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
This software use only basic functions like <i>gethostbyname(3)</i>
|
||||
or <i>gethostbyaddr(3)</i>. Checkresolv use the more low-level
|
||||
of the resolver galaxy, so it works like any "lambda"
|
||||
application. Really nice when you have to catch a mysterious
|
||||
failure in a <small>LAMBDA</small> software.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The environmemt variable <tt>CHECKRESOLV</tt> control the verbosity.
|
||||
A value of <tt>tech</tt> add the display of reverse lookup and timings.
|
||||
And setting to <tt>all</tt> give you all the bells'n'whistles needed
|
||||
by geeks.
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
80
CheckResolv/checkresolv.man
Normal file
80
CheckResolv/checkresolv.man
Normal file
@@ -0,0 +1,80 @@
|
||||
.TH CheckResolv 1 "2005 September" "various OS" "Tonton Th"
|
||||
|
||||
.SH NAME
|
||||
checkresolv \- quick & dirty tool for checking sanity of resolver.
|
||||
|
||||
.SH SYNOPSIS
|
||||
\fBcheckresolv\fP -V
|
||||
.br
|
||||
\fBcheckresolv\fP [options] host.name
|
||||
.br
|
||||
\fBcheckresolv\fP [options] 42.51.69.406
|
||||
|
||||
.SH DESCRIPTION
|
||||
CheckResolv is a (not so) q'n'd tool for checking basic capacities and
|
||||
potentials bugs of your resolver configuration.
|
||||
I have started the dev of this thing when I was working hard on a remote
|
||||
nasty printing problems.
|
||||
It use only \fBgethostbyname\fP and \fBgethostbyaddr\fP functions,
|
||||
like any lambda applications.
|
||||
CheckResolv can also display environment variables who can modify the behaviour
|
||||
of this damned resolver, or give you some problems.
|
||||
|
||||
.SH OPTIONS
|
||||
.B -V
|
||||
display version number and exit.
|
||||
.br
|
||||
.B -h
|
||||
brief help on the command-line options.
|
||||
.br
|
||||
.B -v
|
||||
display various useless messages.
|
||||
.br
|
||||
.B -r
|
||||
do reverse lookup on IP address discovered.
|
||||
.br
|
||||
.B -e
|
||||
show content of a few environment vars resolver-related.
|
||||
.br
|
||||
.B -t
|
||||
compute elapsed time of operation, not really accurate.
|
||||
|
||||
.SH TIPS
|
||||
If you have a strange problem between two hosts, "don't panic". Take the time
|
||||
to compil CheckResolv on the two hosts, and run it with the -r option, first
|
||||
with the hostname, and after that, with the IP address.
|
||||
And do this two runs on the two hosts. So, you get four results.
|
||||
Now, use your brain...
|
||||
|
||||
.SH CONFIG FILE
|
||||
All your config files are belong to us. In the futur, may be you can
|
||||
put a list of env vars to display in a file.
|
||||
|
||||
.SH ENV VARS
|
||||
If the environment variable CHECKRESOLV is set to "tech", reverse lookup
|
||||
and timing are activated, very nice when your pop3 server take 42 seconds
|
||||
before you can get some silly answer.
|
||||
And "all" give you all the bells & whistles.
|
||||
This variable override command lines options.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR resolver (5),
|
||||
.BR host (1),
|
||||
.BR dig (1),
|
||||
.BR nslookup (1)
|
||||
|
||||
.SH BUGS
|
||||
Some are here, some are waiting in the dark. Hidden static storage is a pain.
|
||||
No IPv6 support. No Slackware package, no Debian package...
|
||||
|
||||
.SH COMPILATION
|
||||
Currently (2005 march), this software was only tested on Slackware 10.0 and
|
||||
Debian Sarge, but it can
|
||||
compile 'fine' on others Linux or *BSD flavors. IRIX is also a valuable target,
|
||||
because my troll-master use it...
|
||||
|
||||
.SH AUTHOR(S)
|
||||
Thierry (aka tth) Boudet, with help from @donis, Miod, Reynerie...
|
||||
|
||||
|
||||
|
||||
167
CheckResolv/fonctions.c
Normal file
167
CheckResolv/fonctions.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* CheckResolv
|
||||
* ===========
|
||||
* quick and dirty debugging hack.
|
||||
*
|
||||
* a bunch of various undocumented functions.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "fonctions.h"
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* return !0 if str seems to be a quadnumber ip address.
|
||||
*/
|
||||
int is_IP_addr(char *str)
|
||||
{
|
||||
int nbrdots, length, foo, flag;
|
||||
/* int o[4]; */
|
||||
|
||||
length = strlen(str);
|
||||
flag = nbrdots = 0;
|
||||
for (foo=0; foo<length; foo++)
|
||||
{
|
||||
if (str[foo]=='.') nbrdots++;
|
||||
else if ( ! isdigit(str[foo]) )
|
||||
return 0;
|
||||
}
|
||||
|
||||
return nbrdots==3;
|
||||
}
|
||||
/*
|
||||
* warning, this func is a kludge.
|
||||
*/
|
||||
/* ------------------------------------------------------------ */
|
||||
double chronometre(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
int foo;
|
||||
double ftemps;
|
||||
|
||||
foo = gettimeofday(&tv, NULL);
|
||||
if (foo) perror("get time of day");
|
||||
|
||||
ftemps = (double)tv.tv_sec + ((double)tv.tv_usec/1e6);
|
||||
return ftemps;
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
int print_ip(struct in_addr **liste)
|
||||
{
|
||||
struct in_addr *addr;
|
||||
|
||||
if (liste==NULL)
|
||||
{
|
||||
fprintf(stderr, "print addrip (%s:%d): liste is NULL\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(5);
|
||||
}
|
||||
|
||||
while ((addr = *liste++)!=NULL)
|
||||
{
|
||||
printf("ip: %s", inet_ntoa(*addr));
|
||||
/*
|
||||
* mmmm, must resolve globals vars...
|
||||
if (verbose)
|
||||
printf(" %8x", *addr);
|
||||
*/
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
static void print_onevar(char *name)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
if ((ptr=getenv(name)) == NULL)
|
||||
printf("%-29s is not defined\n", name);
|
||||
else
|
||||
printf("%-27s = '%s'\n", name, ptr);
|
||||
}
|
||||
|
||||
struct envvars
|
||||
{
|
||||
char *name;
|
||||
char *comment;
|
||||
} envvars[] =
|
||||
{
|
||||
{ "HOSTNAME", NULL },
|
||||
{ "HOSTALIASES", NULL },
|
||||
{ "http_proxy", NULL },
|
||||
{ "ftp_proxy", NULL },
|
||||
{ "PRINTER", NULL },
|
||||
{ "RESOLV_HOST_CONF", NULL },
|
||||
{ "RESOLV_SERV_ORDER", NULL },
|
||||
{ "RESOLV_SPOOF_CHECK", NULL },
|
||||
{ "RESOLV_MULTI", NULL },
|
||||
{ "RESOLV_REORDER", NULL },
|
||||
{ "CHECKRESOLV", NULL },
|
||||
{ "TONTON_TH", NULL },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* by the way, if you know another interesting env vars in
|
||||
* the resolver context...
|
||||
*/
|
||||
|
||||
int print_envvars(int flags)
|
||||
{
|
||||
struct envvars *pev;
|
||||
|
||||
puts("");
|
||||
pev = envvars;
|
||||
while (pev->name != NULL)
|
||||
{
|
||||
print_onevar(pev->name);
|
||||
pev++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
void help_options(void)
|
||||
{
|
||||
fputs("checkresolv [-v] [-r] [-e] [-t] hostname|ipaddr\n", stderr);
|
||||
fputs("checkresolv -h : more help\n", stderr);
|
||||
fputs("checkresolv -V : print version\n", stderr);
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr, "*** CheckResolv v %s *** by tth ***\n", VERSION);
|
||||
fputs("Usage:\n", stderr);
|
||||
fputs("\tcheckresolv [options] hostname | @ip\n", stderr);
|
||||
fputs("\n", stderr);
|
||||
fputs("options:\n", stderr);
|
||||
fputs("\t-V: display version number\n", stderr);
|
||||
fputs("\t-v: increase verbosity\n", stderr);
|
||||
fputs("\t-r: try a reverse lookup\n", stderr);
|
||||
fputs("\t-e: print some env vars\n", stderr);
|
||||
fputs("\t-t: print elapsed time\n", stderr);
|
||||
fputs("\n", stderr);
|
||||
fputs("environmemt variable:\n", stderr);
|
||||
fputs("\tname: CHECKRESOLV\n", stderr);
|
||||
fputs("\tvalue: \"tech\" reverse-lookup and timing\n", stderr);
|
||||
fputs("\tvalue: \"all\" all the bells & whistles\n", stderr);
|
||||
fputs("\n", stderr);
|
||||
exit(0);
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
void version(void)
|
||||
{
|
||||
printf("CheckResolv v %s by tth\n", VERSION);
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
17
CheckResolv/fonctions.h
Normal file
17
CheckResolv/fonctions.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* CheckResolv
|
||||
* ===========
|
||||
* quick and dirty debugging hack.
|
||||
*
|
||||
*/
|
||||
|
||||
int is_IP_addr(char *str);
|
||||
double chronometre(void);
|
||||
|
||||
int print_ip(struct in_addr **liste);
|
||||
|
||||
void help_options(void);
|
||||
void usage(void);
|
||||
void version(void);
|
||||
|
||||
int print_envvars(int flag);
|
||||
Reference in New Issue
Block a user