~rcr/rirc

cac030ee2948001a3eb4dcfbd06a1536e958e134 — Richard Robbins a month ago 0c9e6ed
update docs
6 files changed, 211 insertions(+), 302 deletions(-)

A README
D README.md
D docs/birb.jpg
M docs/rirc.1
M src/rirc.c
M src/state.c
A README => README +47 -0
@@ 0,0 1,47 @@
 _ __(_)_ __ ___
| '__| | '__/ __|
| |  | | | | (__
|_|  |_|_|  \___|
=================

A minimalistic IRC client written in C.


Configure
---------

Configure compile time defaults by editing `config.h`.
To generate a default config file:

    $ make config.h


Install
-------

    $ make
    $ make install

Building rirc requires a c11 compiler, GNU gperf and GNU make.

    - https://www.gnu.org/software/gperf/
    - https://www.gnu.org/software/make/

The build toolchain and install paths can be configured via
standard environment variables, i.e.:

    $CC, $CFLAGS, $LDFLAGS, $DESTDIR, $PREFIX

The default install paths are:

    /usr/local/bin/rirc
    /usr/local/share/man/man1/rirc.1


Documentation
-------------

See `rirc --help` or `man rirc` for a summary of usage. For
complete documentation, refer to:

    https://rcr.io/rirc/

D README.md => README.md +0 -124
@@ 1,124 0,0 @@
<p align="center">
  <img src="https://raw.githubusercontent.com/rcr/rirc/master/docs/birb.jpg" alt="birb"/>
</p>

---

<p align="center">
  <a href="https://sonarcloud.io/dashboard?id=rirc">
    <img alt="sonarcloud" src="https://sonarcloud.io/api/project_badges/measure?project=rirc&metric=ncloc"/>
  </a>
  <a href="https://scan.coverity.com/projects/4940">
    <img alt="coverity" src="https://scan.coverity.com/projects/4940/badge.svg"/>
  </a>
  <a href="https://sonarcloud.io/dashboard?id=rirc">
    <img alt="sonarcloud" src="https://sonarcloud.io/api/project_badges/measure?project=rirc&metric=sqale_rating"/>
  </a>
  <a href="https://sonarcloud.io/dashboard?id=rirc">
    <img alt="sonarcloud" src="https://sonarcloud.io/api/project_badges/measure?project=rirc&metric=reliability_rating"/>
  </a>
  <a href="https://sonarcloud.io/dashboard?id=rirc">
    <img alt="sonarcloud" src="https://sonarcloud.io/api/project_badges/measure?project=rirc&metric=security_rating"/>
  </a>
</p>

---

# rirc

A minimalistic irc client written in C.

Connections are TLS enabled over port 6697 by default.

## Building, installing:

Building rirc from source requires a c11 compiler, GNU gperf and GNU make.

 - https://www.gnu.org/software/gperf/
 - https://www.gnu.org/software/make/

The build toolchain and install paths can be configured via standard
environment variables, i.e.:
```
CC, CFLAGS, LDFLAGS, DESTDIR, PREFIX
```

Default install paths:
```
/usr/local/bin/rirc
/usr/local/share/man/man1/rirc.1
```

Building, installing:
```
make
make install
```

## Configuring:

Configure rirc by editing `config.h`. Defaults are in `config.def.h`

## Usage:

```
rirc [-hv] [-s server [...]]

Info:
  -h, --help      Print help message and exit
  -v, --version   Print rirc version and exit

Server options:
  -s, --server=SERVER       Connect to SERVER
  -p, --port=PORT           Connect to SERVER using PORT
  -w, --pass=PASS           Connect to SERVER using PASS
  -u, --username=USERNAME   Connect to SERVER using USERNAME
  -r, --realname=REALNAME   Connect to SERVER using REALNAME
  -m, --mode=MODE           Connect to SERVER with user MODE
  -n, --nicks=NICKS         Comma separated list of nicks to use for SERVER
  -c, --chans=CHANNELS      Comma separated list of channels to join for SERVER

Server connection options:
   --ipv4                   Connect to server using only ipv4 addresses
   --ipv6                   Connect to server using only ipv6 addresses
   --tls-disable            Set server TLS disabled
   --tls-ca-file=PATH       Set server TLS CA cert file path
   --tls-ca-path=PATH       Set server TLS CA cert directory path
   --tls-cert=PATH          Set server TLS client cert file path
   --tls-verify=MODE        Set server TLS peer certificate verification mode

Server authentication options:
   --sasl=MECHANISM         Authenticate with SASL mechanism
   --sasl-user=USER         Authenticate with SASL user
   --sasl-pass=PASS         Authenticate with SASL pass
```

Commands:

```
  :clear
  :close
  :connect
  :disconnect
  :quit
```

Keys:

```
  ^N : go to next channel
  ^P : go to previous channel
  ^L : clear channel
  ^X : close channel
  ^C : cancel input/action
  ^U : scroll buffer up
  ^D : scroll buffer down
   ← : input cursor back
   → : input cursor forward
   ↑ : input history back
   ↓ : input history forward
```

## More info:

[https://rcr.io/rirc/](https://rcr.io/rirc/)

D docs/birb.jpg => docs/birb.jpg +0 -0
M docs/rirc.1 => docs/rirc.1 +80 -90
@@ 10,142 10,132 @@ rirc is a lightweight Internet Relay Chat client.
.PP
Connections are TLS enabled over port 6697 by default.
.SH OPTIONS
.TP 5
.TP 4
.B "-h, --help"
Print help message and exit
.TP
.B "-v, --version"
Print rirc version and exit
.SS Server options
.TP 5
.TP
.BI "-s, --server=" server
Connect to \fIserver\fP
Set connection \fIhostname\fP
.TP
.BI "-p, --port=" port
Connect to \fIserver\fP using \fIport\fP
Set connection \fIport\fP
.TP
.BI "-w, --pass=" pass
Connect to \fIserver\fP using \fIpass\fP
Set IRC \fIpassword\fP
.TP
.BI "-u, --username=" username
Connect to \fIserver\fP using \fIusername\fP
Set IRC \fIusername\fP
.TP
.BI "-r, --realname=" realname
Connect to \fIserver\fP using \fIrealname\fP
Set IRC \fIrealname\fP
.TP
.BI "-m, --mode=" mode
Connect to \fIserver\fP with user \fImode\fP
.BI "-m, --mode=" modes
Set IRC user \fImodes\fP
.TP
.BI "-n, --nicks=" nicks
Comma separated list of \fInicks\fP to use for \fIserver\fP
Set comma separated list of \fInicks\fP to use
.TP
.BI "-c, --chans=" chans
Comma separated list of \fIchannels\fP to join for \fIserver\fP
.SS Server connection options
.TP 5
.B --ipv4
Connect to \fIserver\fP using only ipv4 addresses
.TP
.B --ipv6
Connect to \fIserver\fP using only ipv6 addresses
Set comma separated list of \fIchannels\fP to join
.TP
.B --tls-disable
Set \fIserver\fP TLS disabled, default port to 6667
.BI --tls-cert= path
Set TLS client certificate file \fIpath\fP
.TP
.BI --tls-ca-file= path
Set \fIserver\fP TLS CA cert file \fIpath\fP
Set TLS peer certificate file \fIpath\fP
.TP
.BI --tls-ca-path= path
Set \fIserver\fP TLS CA cert directory \fIpath\fP
.TP
.BI --tls-cert= path
Set \fIserver\fP TLS client cert file \fIpath\fP
Set TLS peer certificate directory \fIpath\fP
.TP
.BI --tls-verify= mode
Set \fIserver\fP TLS peer certificate verification \fImode\fP:
Set TLS peer certificate verification \fImode\fP:
.EX
\(bu \fIdisabled\fP - cert is not verified
\(bu \fIoptional\fP - cert is verified, handshake continues on error
\(bu \fIrequired\fP - cert is verified, handshake is aborted on error (default)
.EE
.SS Server authentication options
.TP
.B --tls-disable
Set TLS disabled
.TP
.BI --sasl= mechanism
Authenticate with SASL \fImechanism\fP:
.EX
\(bu \fIplain\fP - requires \fI--sasl-user\fP and \fI--sasl-pass\fP
\(bu \fIexternal\fP - requires \fI--tls-cert\fP
\(bu \fIplain\fP    - requires \fI--sasl-user\fP and \fI--sasl-pass\fP
.EE
.TP
.BI --sasl-user= user
Authenticate with SASL \fIuser\fP
Authenticate with SASL \fIusername\fP
.TP
.BI --sasl-pass= pass
Authenticate with SASL \fIpass\fP
Authenticate with SASL \fIpassword\fP
.TP
.B --ipv4
Use IPv4 addresses only
.TP
.B --ipv6
Use IPv6 addresses only
.SH USAGE
.TS
l .
rirc is controlled by a combination of key bindings and commands, where:
rirc is controlled by a combination of keys and commands, where:
  <arg> denotes required arguments
  [arg] denotes optional arguments
.TE

.TS
.tab(;);
lb l .
Keys:
  ^N;go to next channel
  ^P;go to previous channel
  ^C;cancel current input/action
  ^L;clear current channel
  ^X;close current channel
  ^U;scroll current buffer up
  ^D;scroll current buffer down
  <left>;input cursor back
  <right>;input cursor forward
  <up>;input history back
  <down>;input history forward
.TE

.TS
l .
Commands beginning with ':' are interpreted as rirc commands
and control the local client, e.g.:
.TE

.TS
.tab(;);
lb l .
.TP
Commands:
  :clear;
  :close;
  :connect;
  :disconnect;
  :quit;
.TE

.TS
l .
Commands beginning with '/' are interpreted as IRC commands
and will be sent to the current server, e.g.:
.TE

.TS
.tab(;);
lb l .
 \fB:clear\fP
 \fB:close\fP
 \fB:connect\fP [hostname] [options]
 \fB:disconnect\fP
 \fB:quit\fP
.TP
Keys:
 \fB^N\fP   Go to next buffer
 \fB^P\fP   Go to previous buffer
 \fB^L\fP   Clear current buffer
 \fB^X\fP   Close current buffer
 \fB^U\fP   Scroll current buffer back
 \fB^D\fP   Scroll current buffer forward
 \fB^C\fP   Cancel current input/action
 \fB ←\fP   Input cursor back
 \fB →\fP   Input cursor forward
 \fB ↑\fP   Input history back
 \fB ↓\fP   Input history forward
.TP
IRC commands:
  /join;[target, [targets...]]
  /me;<message>
  /nick;[nick]
  /part;[target [targets...]] [part message]
  /privmsg;<target> <message>
  /quit;[quit message]
  /raw;<message>
.TE
.SH AUTHORS
.MT mail@rcr.io
Richard 'rcr' Robbins
.ME .
 \fB/away\fP [away message]
 \fB/join\fP [target, [targets...]]
 \fB/kick\fP <channel> <nick>
 \fB/mode\fP <target> <modes>
 \fB/nick\fP <nick>
 \fB/notice\fP <target> <message>
 \fB/part\fP [target] [message]
 \fB/privmsg\fP <target> <message>
 \fB/quit\fP [message]
 \fB/topic\fP [topic]
 \fB/topic-unset\fP
 \fB/whois\fP <target>
.TP
CTCP commands
 \fB/ctcp-action\fP <target> <message>
 \fB/ctcp-clientinfo\fP [target]
 \fB/ctcp-finger\fP [target]
 \fB/ctcp-ping\fP [target]
 \fB/ctcp-source\fP [target]
 \fB/ctcp-time\fP [target]
 \fB/ctcp-userinfo\fP [target]
 \fB/ctcp-version\fP [target]
.TP
IRCv3 commands
 \fB/cap-ls\fP
 \fB/cap-list\fP
.SH SEE ALSO
.UR https://rcr.io/rirc/
Additional documentation
.UE .
.SH AUTHORS
.MT mail@rcr.io
Richard 'rcr' Robbins
.ME .

M src/rirc.c => src/rirc.c +73 -77
@@ 66,35 66,31 @@ static const char *const rirc_help =
"\nrirc v"VERSION" ~ Richard C. Robbins <mail@rcr.io>"
"\n"
"\nUsage:"
"\n  rirc [-hv] [-s server [...]]"
"\n  rirc [-hv] [-s host [options] ...]"
"\n"
"\nInfo:"
"\n  -h, --help      Print help message and exit"
"\n  -v, --version   Print rirc version and exit"
"\n"
"\nServer options:"
"\n  -s, --server=SERVER       Connect to SERVER"
"\n  -p, --port=PORT           Connect to SERVER using PORT"
"\n  -w, --pass=PASS           Connect to SERVER using PASS"
"\n  -u, --username=USERNAME   Connect to SERVER using USERNAME"
"\n  -r, --realname=REALNAME   Connect to SERVER using REALNAME"
"\n  -m, --mode=MODE           Connect to SERVER with user MODE"
"\n  -n, --nicks=NICKS         Comma separated list of nicks to use for SERVER"
"\n  -c, --chans=CHANNELS      Comma separated list of channels to join for SERVER"
"\n"
"\nServer connection options:"
"\n   --ipv4                   Connect to server using only ipv4 addresses"
"\n   --ipv6                   Connect to server using only ipv6 addresses"
"\n   --tls-disable            Set server TLS disabled"
"\n   --tls-ca-file=PATH       Set server TLS CA cert file path"
"\n   --tls-ca-path=PATH       Set server TLS CA cert directory path"
"\n   --tls-cert=PATH          Set server TLS client cert file path"
"\n   --tls-verify=MODE        Set server TLS peer certificate verification mode"
"\n"
"\nServer authentication options:"
"\n   --sasl=MECHANISM         Authenticate with SASL mechanism"
"\n   --sasl-user=USER         Authenticate with SASL user"
"\n   --sasl-pass=PASS         Authenticate with SASL pass"
"\nOptions:"
"\n  -s, --server=HOST         Set connection hostname"
"\n  -p, --port=PORT           Set connection port"
"\n  -w, --pass=PASS           Set IRC password"
"\n  -u, --username=USERNAME   Set IRC username"
"\n  -r, --realname=REALNAME   Set IRC realname"
"\n  -m, --mode=MODE           Set IRC user modes"
"\n  -n, --nicks=NICKS         Set comma separated list of nicks to use"
"\n  -c, --chans=CHANNELS      Set comma separated list of channels to join"
"\n      --tls-cert=PATH       Set TLS client certificate file path"
"\n      --tls-ca-file=PATH    Set TLS peer certificate file path"
"\n      --tls-ca-path=PATH    Set TLS peer certificate directory path"
"\n      --tls-verify=MODE     Set TLS peer certificate verification mode"
"\n      --tls-disable         Set TLS disabled"
"\n      --sasl=MECHANISM      Authenticate with SASL mechanism"
"\n      --sasl-user=USER      Authenticate with SASL username"
"\n      --sasl-pass=PASS      Authenticate with SASL password"
"\n      --ipv4                Use IPv4 addresses only"
"\n      --ipv6                Use IPv6 addresses only"
"\n";

static const char *const rirc_version =


@@ 111,21 107,21 @@ rirc_opt_str(char c)
		case 's': return "-s/--server";
		case 'p': return "-p/--port";
		case 'w': return "-w/--pass";
		case 'n': return "-n/--nicks";
		case 'c': return "-c/--chans";
		case 'u': return "-u/--username";
		case 'r': return "-r/--realname";
		case 'm': return "-m/--mode";
		case '0': return "--ipv4";
		case '1': return "--ipv6";
		case '2': return "--tls-disable";
		case '3': return "--tls-ca-file";
		case '4': return "--tls-ca-path";
		case '5': return "--tls-cert";
		case '6': return "--tls-verify";
		case '7': return "--sasl";
		case '8': return "--sasl-user";
		case '9': return "--sasl-pass";
		case 'n': return "-n/--nicks";
		case 'c': return "-c/--chans";
		case '0': return "--tls-cert";
		case '1': return "--tls-ca-file";
		case '2': return "--tls-ca-path";
		case '3': return "--tls-verify";
		case '4': return "--tls-disable";
		case '5': return "--sasl";
		case '6': return "--sasl-user";
		case '7': return "--sasl-pass";
		case '8': return "--ipv4";
		case '9': return "--ipv6";
		default:
			fatal("unknown option flag '%c'", c);
	}


@@ 185,16 181,16 @@ rirc_parse_args(int argc, char **argv)
		{"chans",       required_argument, 0, 'c'},
		{"help",        no_argument,       0, 'h'},
		{"version",     no_argument,       0, 'v'},
		{"ipv4",        no_argument,       0, '0'},
		{"ipv6",        no_argument,       0, '1'},
		{"tls-disable", no_argument,       0, '2'},
		{"tls-ca-file", required_argument, 0, '3'},
		{"tls-ca-path", required_argument, 0, '4'},
		{"tls-cert",    required_argument, 0, '5'},
		{"tls-verify",  required_argument, 0, '6'},
		{"sasl",        required_argument, 0, '7'},
		{"sasl-user",   required_argument, 0, '8'},
		{"sasl-pass",   required_argument, 0, '9'},
		{"tls-cert",    required_argument, 0, '0'},
		{"tls-ca-file", required_argument, 0, '1'},
		{"tls-ca-path", required_argument, 0, '2'},
		{"tls-verify",  required_argument, 0, '3'},
		{"tls-disable", no_argument,       0, '4'},
		{"sasl",        required_argument, 0, '5'},
		{"sasl-user",   required_argument, 0, '6'},
		{"sasl-pass",   required_argument, 0, '7'},
		{"ipv4",        no_argument,       0, '8'},
		{"ipv6",        no_argument,       0, '9'},
		{0, 0, 0, 0}
	};



@@ 245,72 241,57 @@ rirc_parse_args(int argc, char **argv)
					return -1; \
				}

			case 'p': /* Connect using port */
			case 'p': /* Set connection port */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].port = optarg;
				break;

			case 'w': /* Connect using port */
			case 'w': /* Set IRC password */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].pass = optarg;
				break;

			case 'u': /* Connect using username */
			case 'u': /* Set IRC username */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].username = optarg;
				break;

			case 'r': /* Connect using realname */
			case 'r': /* Set IRC realname */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].realname = optarg;
				break;

			case 'm': /* Connect with user mode */
			case 'm': /* Set IRC user modes */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].mode = optarg;
				break;

			case 'n': /* Comma separated list of nicks to use */
			case 'n': /* Set comma separated list of nicks to use */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].nicks = optarg;
				break;

			case 'c': /* Comma separated list of channels to join */
			case 'c': /* Set comma separated list of channels to join */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].chans = optarg;
				break;

			case '0': /* Connect using ipv4 only */
				CHECK_SERVER_OPTARG(opt_c, 0);
				cli_servers[n_servers -1].ipv = IO_IPV_4;
				break;

			case '1': /* Connect using ipv6 only */
				CHECK_SERVER_OPTARG(opt_c, 0);
				cli_servers[n_servers -1].ipv = IO_IPV_6;
				break;

			case '2': /* Set server TLS disabled */
				CHECK_SERVER_OPTARG(opt_c, 0);
				cli_servers[n_servers -1].tls = IO_TLS_DISABLED;
			case '0': /* Set TLS client certificate file path */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].tls_cert = optarg;
				break;

			case '3': /* Set server TLS CA cert file path */
			case '1': /* Set TLS peer certificate file path */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].tls_ca_file = optarg;
				break;

			case '4': /* Set server TLS CA cert directory path */
			case '2': /* Set TLS peer certificate directory path */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].tls_ca_path = optarg;
				break;

			case '5': /* Set server TLS client cert file path */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].tls_cert = optarg;
				break;

			case '6': /* Set server TLS peer certificate verification mode */
			case '3': /* Set TLS peer certificate verification mode */
				CHECK_SERVER_OPTARG(opt_c, 1);
				if (!strcmp(optarg, "0") || !strcasecmp(optarg, "DISABLED")) {
					cli_servers[n_servers -1].tls_vrfy = IO_TLS_VRFY_DISABLED;


@@ 327,7 308,12 @@ rirc_parse_args(int argc, char **argv)
				arg_error("invalid option for '--tls-verify' '%s'", optarg);
				return -1;

			case '7': /* Authenticate with SASL mechanism */
			case '4': /* Set TLS disabled */
				CHECK_SERVER_OPTARG(opt_c, 0);
				cli_servers[n_servers -1].tls = IO_TLS_DISABLED;
				break;

			case '5': /* Authenticate with SASL mechanism */
				CHECK_SERVER_OPTARG(opt_c, 1);
				if (!strcasecmp(optarg, "EXTERNAL")) {
					cli_servers[n_servers - 1].sasl = optarg;


@@ 340,16 326,26 @@ rirc_parse_args(int argc, char **argv)
				arg_error("invalid option for '--sasl' '%s'", optarg);
				return -1;

			case '8': /* Authenticate with SASL user */
			case '6': /* Authenticate with SASL user */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].sasl_user = optarg;
				break;

			case '9': /* Authenticate with SASL pass */
			case '7': /* Authenticate with SASL pass */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].sasl_pass = optarg;
				break;

			case '8': /* Use IPv4 only */
				CHECK_SERVER_OPTARG(opt_c, 0);
				cli_servers[n_servers -1].ipv = IO_IPV_4;
				break;

			case '9': /* Use IPv6 only */
				CHECK_SERVER_OPTARG(opt_c, 0);
				cli_servers[n_servers -1].ipv = IO_IPV_6;
				break;

			#undef CHECK_SERVER_OPTARG

			case 'h':

M src/state.c => src/state.c +11 -11
@@ 744,12 744,11 @@ command_connect(struct channel *c, char *args)
					action(action_error, "connect: '-c/--chans' requires an argument");
					return;
				}
			} else if (!strcmp(arg, "--ipv4")) {
				ipv = IO_IPV_4;
			} else if (!strcmp(arg, "--ipv6")) {
				ipv = IO_IPV_6;
			} else if (!strcmp(arg, "--tls-disable")) {
				tls = IO_TLS_DISABLED;
			} else if (!strcmp(arg, "--tls-cert")) {
				if (!(tls_cert = irc_strsep(&args))) {
					action(action_error, "connect: '--tls-cert' requires an argument");
					return;
				}
			} else if (!strcmp(arg, "--tls-ca-file")) {
				if (!(tls_ca_file = irc_strsep(&args))) {
					action(action_error, "connect: '--tls-ca-file' requires an argument");


@@ 760,11 759,6 @@ command_connect(struct channel *c, char *args)
					action(action_error, "connect: '--tls-ca-path' requires an argument");
					return;
				}
			} else if (!strcmp(arg, "--tls-cert")) {
				if (!(tls_cert = irc_strsep(&args))) {
					action(action_error, "connect: '--tls-cert' requires an argument");
					return;
				}
			} else if (!strcmp(arg, "--tls-verify")) {
				if (!(arg = irc_strsep(&args))) {
					action(action_error, "connect: '--tls-verify' requires an argument");


@@ 779,6 773,8 @@ command_connect(struct channel *c, char *args)
					action(action_error, "connect: invalid option for '--tls-verify' '%s'", arg);
					return;
				}
			} else if (!strcmp(arg, "--tls-disable")) {
				tls = IO_TLS_DISABLED;
			} else if (!strcmp(arg, "--sasl")) {
				if (!(sasl = irc_strsep(&args))) {
					action(action_error, "connect: '--sasl' requires an argument");


@@ 801,6 797,10 @@ command_connect(struct channel *c, char *args)
					action(action_error, "connect: '--sasl-pass' requires an argument");
					return;
				}
			} else if (!strcmp(arg, "--ipv4")) {
				ipv = IO_IPV_4;
			} else if (!strcmp(arg, "--ipv6")) {
				ipv = IO_IPV_6;
			} else {
				action(action_error, "connect: unknown option '%s'", arg);
				return;