1
0
mirror of https://github.com/osmarks/ngircd.git synced 2024-12-12 01:40:27 +00:00

Merge branch 'bug145-ProvideHelp'

* bug145-ProvideHelp:
  Use "${docdir}/Commands.txt" as help text file
  Add a note that "help file" is updated on startup and REHASH only
  Add doc/Commands.txt which should document all commands
  Implement Help() function parsing and returning the help text
  Document "HelpFile" in sample-ngircd.conf and ngircd.conf.5
  Implement new configuration option "HelpFile"
  IRC_HELP(): Code cleanup
  Refactor Read_Motd() into Read_TextFile()
This commit is contained in:
Alexander Barton 2013-01-02 23:41:46 +01:00
commit 68cb1a8c2e
10 changed files with 382 additions and 32 deletions

View File

@ -1,6 +1,6 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors
#
# 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
@ -110,7 +110,7 @@ esac
# Add additional CFLAGS, eventually specified on the command line:
test -n "$CFLAGS_ADD" && CFLAGS="$CFLAGS $CFLAGS_ADD"
CFLAGS="$CFLAGS -DSYSCONFDIR='\"\$(sysconfdir)\"'"
CFLAGS="$CFLAGS -DSYSCONFDIR='\"\$(sysconfdir)\"' -DDOCDIR='\"\$(docdir)\"'"
# -- Headers --

View File

@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
*
* 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
@ -17,6 +17,7 @@
#define VERSION "??("__DATE__")"
#endif
#define SYSCONFDIR "/etc/ngircd"
#define DOCDIR "/usr/share/doc/ngircd"
#ifndef TARGET_VENDOR
#define TARGET_VENDOR "apple"

219
doc/Commands.txt Normal file
View File

@ -0,0 +1,219 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2013 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
-- Commands.txt --
This file lists all commands available on ngIRCd. It is written in a format
that is human readable as well as machine parseable and therefore can be used
as "help text file" of the daemon.
In short, the HELP command parses this file as following when a user user
issues a "HELP <cmd>" command:
1. Search the file for a line "- <cmd>",
2. Output all subsequent lines that start with a TAB (ASCII 9) character
to the client using NOTICE commands, treat lines containing a single "."
after the TAB as empty lines.
3. Break at the first line not starting with a TAB character.
This format allows to have information to each command stored in this file
which will not be sent to an IRC user requesting help which enables us to
have additional annotations stored here which further describe the origin,
implementation details, or limits of the specific command.
A special "Intro" block is returned to the user when the HELP command is
used without a command name:
- Intro
This is ngIRCd, a server software for Internet Relay Chat (IRC)
networks. You can find more information about ngIRCd on its homepage:
<http://ngircd.barton.de>
.
Use "HELP COMMANDS" to get a list of all available commands and
"HELP <command-name>" to get help for a specific IRC command, for
example "HELP quit" or "HELP privmsg".
General Commands
~~~~~~~~~~~~~~~~
- AWAY
- CAP
- CHARCONV
- HELP
HELP [<command>]
.
Show help information for a specific IRC <command>. The <command> name
is case-insensitive.
.
Use the command "HELP Commands" to get a list of all available commands.
The HELP command isn't specified by any RFC but implemented by most
daemons. If no help text could be read in, ngIRCd outputs a list of all
implemented commands when receiving a plain "HELP" command as well as
on "HELP Commands".
ngIRCd replies using "NOTICE" commands like ircd 2.10/2.11; other
implementations are using numerics 704, 705, and 706.
- MODE
- NICK
- NOTICE
- PASS
- PING
- PONG
- PRIVMSG
- QUIT
QUIT [<quit-message>]
.
End IRC session and disconnect from the server.
.
If a <quit-message> has been given, it is displayed to all the
channels that you are a member of when leaving.
- USER
- WALLOPS
- WEBIRC
Status and Informational Commands
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- INFO
- ISON
- LINKS
- LUSERS
- METADATA
- MOTD
- NAMES
- STATS
- TIME
- TRACE
- USERHOST
- VERSION
- WHO
- WHOIS
- WHOWAS
Channel Commands
~~~~~~~~~~~~~~~~
- INVITE
- JOIN
- KICK
- LIST
- PART
- TOPIC
Administrative Commands
~~~~~~~~~~~~~~~~~~~~~~~
- ADMIN
ADMIN [<server>]
.
Show administartive information about an IRC server in the network.
If no server name has been given, the local server will respond.
- CONNECT
- DIE
- DISCONNECT
- GLINE
- KILL
- KLINE
- OPER
- REHASH
- RESTART
IRC Service Commands
~~~~~~~~~~~~~~~~~~~~~~~~
- SERVICE
- SERVLIST
- SQUERY
- SVSNICK
Server Protocol Commands
~~~~~~~~~~~~~~~~~~~~~~~~
- CHANINFO
- ERROR
ERROR [<message> [<> [...]]]
.
Return an error message to the server. The first parameter, if given,
will be logged by the server, all further parameters are silently
ignored.
.
This command is silently ignored on non-server and non-service links.
- NJOIN
- SERVER
- SQUIT
Dummy Commands
~~~~~~~~~~~~~~
- SUMMON
- USERS
- GET
- POST

View File

@ -1,6 +1,6 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors
# Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors
#
# 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
@ -12,6 +12,7 @@
.tmpl:
$(AM_V_GEN)sed \
-e "s@:ETCDIR:@${sysconfdir}@" \
-e "s@:DOCDIR:@${docdir}@" \
<$< >$@
SUFFIXES = .tmpl
@ -19,6 +20,7 @@ SUFFIXES = .tmpl
static_docs = \
Bopm.txt \
Capabilities.txt \
Commands.txt \
Contributing.txt \
FAQ.txt \
GIT.txt \

View File

@ -33,6 +33,10 @@
;AdminInfo2 = Location
;AdminEMail = admin@irc.server
# Text file which contains the ngIRCd help text. This file is required
# to display help texts when using the "HELP <cmd>" command.
;HelpFile = :DOCDIR:/Commands.txt
# Info text of the server. This will be shown by WHOIS and
# LINKS requests for example.
Info = Server Info Text

View File

@ -101,6 +101,12 @@ IRC network and must contain at least one dot (".") character.
Information about the server and the administrator, used by the ADMIN
command. This information is not required by the server but by RFC!
.TP
\fBHelpFile\fR (string)
Text file which contains the ngIRCd help text. This file is required
to display help texts when using the "HELP <cmd>" command.
Please note: Changes made to this file take effect when ngircd starts up
or is instructed to re-read its configuration file.
.TP
\fBInfo\fR (string)
Info text of the server. This will be shown by WHOIS and LINKS requests for
example.

View File

@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
*
* 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
@ -54,6 +54,7 @@ static CONF_SERVER New_Server;
static int New_Server_Idx;
static char Conf_MotdFile[FNAME_LEN];
static char Conf_HelpFile[FNAME_LEN];
static void Set_Defaults PARAMS(( bool InitServers ));
static bool Read_Config PARAMS(( bool TestOnly, bool IsStarting ));
@ -316,6 +317,7 @@ Conf_Test( void )
printf(" AdminInfo1 = %s\n", Conf_ServerAdmin1);
printf(" AdminInfo2 = %s\n", Conf_ServerAdmin2);
printf(" AdminEMail = %s\n", Conf_ServerAdminMail);
printf(" HelpFile = %s\n", Conf_HelpFile);
printf(" Info = %s\n", Conf_ServerInfo);
printf(" Listen = %s\n", Conf_ListenAddress);
if (Using_MotdFile) {
@ -701,8 +703,11 @@ Set_Defaults(bool InitServers)
Conf_ListenAddress = NULL;
array_free(&Conf_ListenPorts);
array_free(&Conf_Motd);
array_free(&Conf_Helptext);
strlcpy(Conf_MotdFile, SYSCONFDIR, sizeof(Conf_MotdFile));
strlcat(Conf_MotdFile, MOTD_FILE, sizeof(Conf_MotdFile));
strlcpy(Conf_HelpFile, DOCDIR, sizeof(Conf_HelpFile));
strlcat(Conf_HelpFile, HELP_FILE, sizeof(Conf_HelpFile));
strcpy(Conf_ServerPwd, "");
strlcpy(Conf_PidFile, PID_FILE, sizeof(Conf_PidFile));
Conf_UID = Conf_GID = 0;
@ -784,39 +789,44 @@ no_listenports(void)
}
/**
* Read MOTD ("message of the day") file.
* Read contents of a text file into an array.
*
* This function is used to read the MOTD and help text file, for exampe.
*
* @param filename Name of the file to read.
* @return true, when the file has been read in.
*/
static void
Read_Motd(const char *filename)
static bool
Read_TextFile(const char *Filename, const char *Name, array *Destination)
{
char line[127];
FILE *fp;
int line_no = 1;
if (*filename == '\0')
return;
if (*Filename == '\0')
return false;
fp = fopen(filename, "r");
fp = fopen(Filename, "r");
if (!fp) {
Config_Error(LOG_WARNING, "Can't read MOTD file \"%s\": %s",
filename, strerror(errno));
return;
Config_Error(LOG_WARNING, "Can't read %s file \"%s\": %s",
Name, Filename, strerror(errno));
return false;
}
array_free(&Conf_Motd);
Using_MotdFile = true;
array_free(Destination);
while (fgets(line, (int)sizeof line, fp)) {
ngt_TrimLastChr( line, '\n');
ngt_TrimLastChr(line, '\n');
/* add text including \0 */
if (!array_catb(&Conf_Motd, line, strlen(line) + 1)) {
Log(LOG_WARNING, "Cannot add MOTD text: %s", strerror(errno));
if (!array_catb(Destination, line, strlen(line) + 1)) {
Log(LOG_WARNING, "Cannot read/add \"%s\", line %d: %s",
Filename, line_no, strerror(errno));
break;
}
line_no++;
}
fclose(fp);
return true;
}
/**
@ -1037,8 +1047,16 @@ Read_Config(bool TestOnly, bool IsStarting)
}
/* No MOTD phrase configured? (re)try motd file. */
if (array_bytes(&Conf_Motd) == 0)
Read_Motd(Conf_MotdFile);
if (array_bytes(&Conf_Motd) == 0) {
if (Read_TextFile(Conf_MotdFile, "MOTD", &Conf_Motd))
Using_MotdFile = true;
}
/* Try to read ngIRCd help text file. */
(void)Read_TextFile(Conf_HelpFile, "help text", &Conf_Helptext);
if (!array_bytes(&Conf_Helptext))
Config_Error(LOG_WARNING,
"No help text available, HELP command will be of limited use.");
#ifdef SSL_SUPPORT
/* Make sure that all SSL-related files are readable */
@ -1305,6 +1323,12 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
Config_Error_TooLong(Line, Var);
return;
}
if (strcasecmp(Var, "HelpFile") == 0) {
len = strlcpy(Conf_HelpFile, Arg, sizeof(Conf_HelpFile));
if (len >= sizeof(Conf_HelpFile))
Config_Error_TooLong(Line, Var);
return;
}
if (strcasecmp(Var, "Listen") == 0) {
if (Conf_ListenAddress) {
Config_Error(LOG_ERR,

View File

@ -111,6 +111,9 @@ GLOBAL char Conf_ServerAdminMail[CLIENT_INFO_LEN];
/** Message of the day (MOTD) of this server */
GLOBAL array Conf_Motd;
/** Help text of this server */
GLOBAL array Conf_Helptext;
/** Array of ports this server should listen on */
GLOBAL array Conf_ListenPorts;

View File

@ -77,6 +77,9 @@
/** Name of the MOTD file. */
#define MOTD_FILE "/ngircd.motd"
/** Name of the help file. */
#define HELP_FILE "/Commands.txt"
/** Default chroot() directory. */
#define CHROOT_DIR ""

View File

@ -44,6 +44,7 @@ static bool Send_Message PARAMS((CLIENT *Client, REQUEST *Req, int ForceType,
static bool Send_Message_Mask PARAMS((CLIENT *from, char *command,
char *targetMask, char *message,
bool SendErrors));
static bool Help PARAMS((CLIENT *Client, const char *Topic));
/**
@ -315,29 +316,116 @@ IRC_TRACE( CLIENT *Client, REQUEST *Req )
} /* IRC_TRACE */
/**
* Handler for the IRC "HELP" command.
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool
IRC_HELP( CLIENT *Client, REQUEST *Req )
IRC_HELP(CLIENT *Client, REQUEST *Req)
{
COMMAND *cmd;
assert( Client != NULL );
assert( Req != NULL );
assert(Client != NULL);
assert(Req != NULL);
/* Bad number of arguments? */
if( Req->argc > 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
if (Req->argc > 1)
return IRC_WriteStrClient(Client, ERR_NORECIPIENT_MSG,
Client_ID(Client), Req->command);
cmd = Parse_GetCommandStruct( );
while( cmd->name )
{
if( ! IRC_WriteStrClient( Client, "NOTICE %s :%s", Client_ID( Client ), cmd->name )) return DISCONNECTED;
IRC_SetPenalty(Client, 2);
if ((Req->argc == 0 && array_bytes(&Conf_Helptext) > 0)
|| (Req->argc >= 1 && strcasecmp(Req->argv[0], "Commands") != 0)) {
/* Help text available and requested */
if (Req->argc >= 1)
return Help(Client, Req->argv[0]);
if (!Help(Client, "Intro"))
return DISCONNECTED;
return CONNECTED;
}
cmd = Parse_GetCommandStruct();
while(cmd->name) {
if (!IRC_WriteStrClient(Client, "NOTICE %s :%s",
Client_ID(Client), cmd->name))
return DISCONNECTED;
cmd++;
}
IRC_SetPenalty( Client, 2 );
return CONNECTED;
} /* IRC_HELP */
/**
* Send help for a given topic to the client.
*
* @param Client The client requesting help.
* @param Topoc The help topic requested.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Help(CLIENT *Client, const char *Topic)
{
char *line;
size_t helptext_len, len_str, idx_start, lines = 0;
bool in_article = false;
assert(Client != NULL);
assert(Topic != NULL);
helptext_len = array_bytes(&Conf_Helptext);
line = array_start(&Conf_Helptext);
while (helptext_len > 0) {
len_str = strlen(line) + 1;
assert(helptext_len >= len_str);
helptext_len -= len_str;
if (in_article) {
/* The first character in each article text line must
* be a TAB (ASCII 9) character which will be stripped
* in the output. If it is not a TAB, the end of the
* article has been reached. */
if (line[0] != '\t') {
if (lines > 0)
return CONNECTED;
else
break;
}
/* A single '.' character indicates an empty line */
if (line[1] == '.' && line[2] == '\0')
idx_start = 2;
else
idx_start = 1;
if (!IRC_WriteStrClient(Client, "NOTICE %s :%s",
Client_ID(Client),
&line[idx_start]))
return DISCONNECTED;
lines++;
} else {
if (line[0] == '-' && line[1] == ' '
&& strcasecmp(&line[2], Topic) == 0)
in_article = true;
}
line += len_str;
}
/* Help topic not found (or empty)! */
if (!IRC_WriteStrClient(Client, "NOTICE %s :No help for \"%s\" found!",
Client_ID(Client), Topic))
return DISCONNECTED;
return CONNECTED;
}
static char *
#ifdef ZLIB
Option_String(CONN_ID Idx)