commit - 21493731dffa0f5d9f62d24cdef290be6a6856fd
commit + 68cb1a8c2e507e7c99f787fab3540b904cfa1cc1
blob - 84e27508c793721cade924c8ee25f743affbddcd
blob + 732e55ee01388280e2e858a86b686dee0826dbb4
--- configure.ng
+++ configure.ng
#
# 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 --
blob - 6da74962c5551f56c32a456f3ecd7aace23d6998
blob + f4838276ecfddcb8bccd5a42b7fb1fc410d64a5d
--- contrib/MacOSX/config.h
+++ contrib/MacOSX/config.h
/*
* 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"
blob - /dev/null
blob + e9b78731080b6a8ed3785e233d4bfa2f551e4bbd (mode 644)
--- /dev/null
+++ doc/Commands.txt
+
+ 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
blob - 2b9b3aab5318a30cc4c1c398ec205ae93d4d0e87
blob + 04f74b6059acd132336f5527477d533297c6989a
--- doc/Makefile.am
+++ doc/Makefile.am
#
# 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 \
blob - 997a983d2bc08fbeb9bc9b2250bd487c631e779d
blob + 1c3998ad61368fca9448013206c2cd35e5187779
--- doc/sample-ngircd.conf.tmpl
+++ doc/sample-ngircd.conf.tmpl
;AdminInfo1 = Description
;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.
blob - e3f62c84ceb3432a64410cf65e5f6df83961115e
blob + 859c6a8ac0eb547b915e73fbed78cbf4e726c8a5
--- man/ngircd.conf.5.tmpl
+++ man/ngircd.conf.5.tmpl
\fBAdminInfo1\fR, \fBAdminInfo2\fR, \fBAdminEMail\fR (string)
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
blob - bea4d619a8c967f8a0e6ae18de8a767000da7af8
blob + d5a28bd7bfbe25ab3b8268781236edfe663954f2
--- src/ngircd/conf.c
+++ src/ngircd/conf.c
/*
* 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 false;
- if (*filename == '\0')
- return;
-
- 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 */
if (strcasecmp(Var, "Info") == 0) {
len = strlcpy(Conf_ServerInfo, Arg, sizeof(Conf_ServerInfo));
if (len >= sizeof(Conf_ServerInfo))
+ 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;
}
blob - f85a25fa08920a2945c02603d2c8d05cc0dde086
blob + ac42746c3a6872202435084bb55eaae544b7709f
--- src/ngircd/conf.h
+++ src/ngircd/conf.h
/** 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;
blob - ad9716fdefb6f2e807d7567911df146f4a43bfd4
blob + 3850b5810a0c8ad67e379339207bfe45ada45b97
--- src/ngircd/defines.h
+++ src/ngircd/defines.h
/** 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 ""
blob - a678f9048e68d0c27b43d55533e333621d730543
blob + e76abcb8a4af00250d819d00d332ca4a5cdc0f65
--- src/ngircd/irc.c
+++ src/ngircd/irc.c
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)