#
# 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
# 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 --
/*
* 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
#define VERSION "??("__DATE__")"
#endif
#define SYSCONFDIR "/etc/ngircd"
+#define DOCDIR "/usr/share/doc/ngircd"
#ifndef TARGET_VENDOR
#define TARGET_VENDOR "apple"
--- /dev/null
+
+ 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
#
# 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
.tmpl:
$(AM_V_GEN)sed \
-e "s@:ETCDIR:@${sysconfdir}@" \
+ -e "s@:DOCDIR:@${docdir}@" \
<$< >$@
SUFFIXES = .tmpl
static_docs = \
Bopm.txt \
Capabilities.txt \
+ Commands.txt \
Contributing.txt \
FAQ.txt \
GIT.txt \
;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
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.
/*
* 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
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 ));
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) {
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;
}
/**
- * 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;
}
/**
}
/* 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 */
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,
/** 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;
/** 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 ""
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));
/**
} /* 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)