OSSP CVS Repository

ossp - Difference in ossp-pkg/l2/l2_ch_irc.c versions 1.1 and 1.2
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/l2/l2_ch_irc.c 1.1 -> 1.2

--- l2_ch_irc.c  2001/10/04 14:58:29     1.1
+++ l2_ch_irc.c  2001/10/19 13:06:35     1.2
@@ -24,47 +24,277 @@
 **  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 **  SUCH DAMAGE.
 **
-**  l2_ch_irc.c: internet relay chat channel implementation
+**  l2_ch_irc.c: Internet Relay Chat (IRC) channel implementation
 */
 
 #include "l2.h"
+#include "l2_p.h"
 
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <time.h>
+
+/* declare private channel configuration */
+typedef struct {
+    char *cpLocalProg;
+    char *cpLocalHost;
+    char *cpLocalUser;
+    char *cpPassword;
+    char *cpNickname;
+    char *cpUsername;
+    char *cpRealname;
+    char *cpChannel;
+    int   bJoin;
+    char *cpHost;
+    char *cpPort;
+    long nTimeout; 
+    sa_addr_t *saaServer;
+    sa_t *saServer;
+} l2_ch_irc_t;
+
+/* create channel */
 static l2_result_t hook_create(l2_context_t *ctx, l2_channel_t *ch)
 {
+    l2_ch_irc_t *cfg;
+    struct utsname uts;
+    struct passwd *pw;
+
+    /* allocate private channel configuration */
+    if ((cfg = (l2_ch_irc_t *)malloc(sizeof(l2_ch_irc_t))) == NULL)
+        return L2_ERR_ARG;
+
+    /* initialize configuration with reasonable defaults */
+    cfg->cpLocalProg = NULL;
+    if ((pw = getpwuid(getuid())) != NULL)
+        cfg->cpLocalUser = strdup(pw->pw_name);
+    else
+        cfg->cpLocalUser = l2_util_asprintf("uid#%d", getuid());
+    if (uname(&uts) == 0)
+        cfg->cpLocalHost = strdup(uts.nodename);
+    else
+        cfg->cpLocalHost = strdup("localhost");
+    cfg->cpPassword = strdup("*");
+    cfg->cpNickname = strdup(cfg->cpLocalUser);
+    cfg->cpUsername = l2_util_asprintf("%s@%s", cfg->cpLocalUser, cfg->cpLocalHost);
+    cfg->cpRealname = strdup(cfg->cpUsername);
+    cfg->cpChannel  = strdup("#l2");
+    cfg->bJoin      = 1;
+    cfg->cpHost     = NULL;
+    cfg->cpPort     = strdup("6667");
+    cfg->nTimeout   = 30;
+    cfg->saaServer  = NULL;
+    cfg->saServer   = NULL;
+
+    /* link private channel configuration into channel context */
+    ctx->vp = cfg;
+
     return L2_OK;
 }
 
+/* configure channel */
 static l2_result_t hook_configure(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap)
 {
-    return L2_OK;
+    l2_ch_irc_t *cfg = (l2_ch_irc_t *)ctx->vp;
+    l2_param_t pa[12]; 
+    l2_result_t rv;
+
+    /* feed and call generic parameter parsing engine */
+    L2_PARAM_SET(pa[0],  progname,  STRING, &cfg->cpLocalProg);
+    L2_PARAM_SET(pa[1],  localhost, STRING, &cfg->cpLocalHost);
+    L2_PARAM_SET(pa[2],  localuser, STRING, &cfg->cpLocalUser);
+    L2_PARAM_SET(pa[3],  nickname,  STRING, &cfg->cpNickname);
+    L2_PARAM_SET(pa[4],  username,  STRING, &cfg->cpUsername);
+    L2_PARAM_SET(pa[5],  realname,  STRING, &cfg->cpRealname);
+    L2_PARAM_SET(pa[6],  channel,   STRING, &cfg->cpChannel);
+    L2_PARAM_SET(pa[7],  join,      INT,    &cfg->bJoin);
+    L2_PARAM_SET(pa[8],  host,      STRING, &cfg->cpHost);
+    L2_PARAM_SET(pa[9],  port,      STRING, &cfg->cpPort);
+    L2_PARAM_SET(pa[10], timeout,   INT,    &cfg->nTimeout);
+    L2_PARAM_END(pa[11]);
+    rv = l2_util_setparams(pa, fmt, ap);
+
+    return rv;
 }
 
+/* open channel */
 static l2_result_t hook_open(l2_context_t *ctx, l2_channel_t *ch)
 {
+    l2_ch_irc_t *cfg = (l2_ch_irc_t *)ctx->vp;
+    sa_rc_t rc;
+
+    /* make sure a path was set */
+    if (cfg->cpHost == NULL)
+        return L2_ERR_USE;
+
+    /* create socket address */
+    if ((rc = sa_addr_create(&cfg->saaServer)) != SA_OK)
+        return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
+    if ((rc = sa_addr_u2a(cfg->saaServer, "inet://%s:%s", 
+                          cfg->cpHost, cfg->cpPort)) != SA_OK)
+        return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
+
+    /* create socket */
+    if ((rc = sa_create(&cfg->saServer)) != SA_OK)
+        return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
+
+    /* configure socket parameters */
+    sa_timeout(cfg->saServer, SA_TIMEOUT_ALL, cfg->nTimeout, 0);
+    sa_timeout(cfg->saServer, SA_TIMEOUT_READ, 2, 0);
+    sa_buffer(cfg->saServer, SA_BUFFER_READ, 4096);
+    sa_buffer(cfg->saServer, SA_BUFFER_WRITE, 4096);
+
     return L2_OK;
 }
 
-static l2_result_t hook_write(l2_context_t *ctx, l2_channel_t *ch, l2_level_t level, const char *buf, size_t buf_size)
+/* write to channel */
+static l2_result_t hook_write(l2_context_t *ctx, l2_channel_t *ch,
+                              l2_level_t level, const char *buf, size_t buf_size)
 {
+    l2_ch_irc_t *cfg = (l2_ch_irc_t *)ctx->vp;
+    char caLine[1024];
+    sa_t *sa;
+    sa_addr_t *saa;
+    sa_rc_t sa_rv;
+    size_t n;
+    struct tm *tm;
+    time_t t;
+    char caDate[80];
+    
+    /* 
+     * Sample IRC client transaction for reference:
+     * | PASS secret
+     * | NICK rse
+     * | USER rse@engelschall.com 0 * :Ralf S. Engelschall
+     * | :irc.engelschall.com 001 rse :Welcome to the Internet Relay Network rse!~rse@dev10.dev.de.cw.net
+     * | :irc.engelschall.com 002 rse :Your host is irc.engelschall.com, running version 2.10.3p2
+     * | :irc.engelschall.com 003 rse :This server was created Wed Oct 17 2001 at 18:06:57 CEST
+     * | :irc.engelschall.com 004 rse irc.engelschall.com 2.10.3p2 aoOirwabeiIklmnoOpqrstv
+     * | :irc.engelschall.com 251 rse :There are 1 users and 0 services on 1 servers
+     * | :irc.engelschall.com 254 rse 11 :channels formed
+     * | :irc.engelschall.com 255 rse :I have 1 users, 0 services and 0 servers
+     * | :irc.engelschall.com 375 rse :- irc.engelschall.com Message of the Day - 
+     * | :irc.engelschall.com 372 rse :- 17/10/2001 19:32
+     * | :irc.engelschall.com 372 rse :- Welcome to the Engelschall VISP IRC Service.
+     * | :irc.engelschall.com 376 rse :End of MOTD command.
+     * | :rse MODE rse :+i
+     * | JOIN #dev
+     * | :rse!~rse@dev10.dev.de.cw.net JOIN :#dev
+     * | :irc.engelschall.com 353 rse = #dev :@rse 
+     * | :irc.engelschall.com 366 rse #dev :End of NAMES list.
+     * | PRIVMSG #dev :Sample log message line 1
+     * | PRIVMSG #dev :Sample log message line 2 
+     * | PRIVMSG #dev :Sample log message line 3
+     * | QUIT
+     * | ERROR :Closing Link: rse[~rse@dev10.dev.de.cw.net] (I Quit)
+     *
+     * For more details read:
+     * RFC 2812: Internet Relay Chat: Client Protocol; C. Kalt; April 2000.
+     */
+
+    /* establish connection to server */
+    saa = cfg->saaServer;
+    sa  = cfg->saServer;
+    if ((sa_rv = sa_connect(sa, saa)) != SA_OK)
+        return (sa_rv == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
+
+    /* determine current time */
+    t = time(NULL);
+    tm = localtime(&t);
+    strftime(caDate, sizeof(caDate), "%a, %d %b %Y %H:%M:%S %Z", tm);
+
+    /* write transaction to IRC server */
+    sa_writef(sa, "PASS %s\r\n", cfg->cpPassword);
+    sa_writef(sa, "NICK %s\r\n", cfg->cpNickname);
+    sa_writef(sa, "USER %s 0 * :%s\r\n", cfg->cpUsername, cfg->cpRealname);
+    if (cfg->bJoin)
+        sa_writef(sa, "JOIN %s\r\n", cfg->cpChannel);
+    sa_writef(sa, "PRIVMSG %s :", cfg->cpChannel);
+    if (cfg->cpLocalProg != NULL)
+        sa_writef(sa, "Program %s of user %s on host %s logged at %s:\r\n", 
+                   cfg->cpLocalProg, cfg->cpLocalUser, cfg->cpLocalHost, caDate);
+    else
+        sa_writef(sa, "A program of user %s on host %s logged at %s:\r\n", 
+                   cfg->cpLocalUser, cfg->cpLocalHost, caDate);
+    sa_writef(sa, "PRIVMSG %s :", cfg->cpChannel);
+    sa_write(sa, buf, buf_size-1, NULL);
+    sa_writef(sa, "\r\n");
+    if (cfg->bJoin)
+        sa_writef(sa, "PART %s\r\n", cfg->cpChannel);
+    sa_writef(sa, "QUIT\r\n");
+    sa_flush(sa);
+
+    /* shutdown write side of connection to server */
+    sa_shutdown(sa, "w");
+
+    /* still read server responses */
+    while (sa_readln(sa, caLine, sizeof(caLine), &n) == SA_OK)
+        ;
+
+    /* shutdown read side of connection to server */
+    sa_shutdown(sa, "r");
+
     return L2_OK;
 }
 
+/* close channel */
 static l2_result_t hook_close(l2_context_t *ctx, l2_channel_t *ch)
 {
+    l2_ch_irc_t *cfg = (l2_ch_irc_t *)ctx->vp;
+
+    /* destroy remote address */
+    if (cfg->saServer != NULL) {
+        sa_destroy(cfg->saServer);
+        cfg->saServer = NULL;
+    }
+    if (cfg->saaServer != NULL) {
+        sa_addr_destroy(cfg->saaServer);
+        cfg->saaServer = NULL;
+    }
+
     return L2_OK;
 }
 
+/* destroy channel */
 static l2_result_t hook_destroy(l2_context_t *ctx, l2_channel_t *ch)
 {
+    l2_ch_irc_t *cfg = (l2_ch_irc_t *)ctx->vp;
+
+    /* destroy channel configuration */
+    if (cfg->cpLocalProg != NULL)
+        free(cfg->cpLocalProg);
+    if (cfg->cpLocalHost != NULL)
+        free(cfg->cpLocalHost);
+    if (cfg->cpLocalUser != NULL)
+        free(cfg->cpLocalUser);
+    if (cfg->cpPassword != NULL)
+        free(cfg->cpPassword);
+    if (cfg->cpNickname != NULL)
+        free(cfg->cpNickname);
+    if (cfg->cpUsername != NULL)
+        free(cfg->cpUsername);
+    if (cfg->cpRealname != NULL)
+        free(cfg->cpRealname);
+    if (cfg->cpChannel != NULL)
+        free(cfg->cpChannel);
+    if (cfg->cpHost != NULL)
+        free(cfg->cpHost);
+    if (cfg->cpPort != NULL)
+        free(cfg->cpPort);
+    free(cfg);
+
     return L2_OK;
 }
 
+/* exported channel handler structure */
 l2_handler_t l2_handler_irc = {
     L2_CHANNEL_OUTPUT,
     hook_create,
     hook_configure,
     hook_open,
     hook_write,
+    NULL,
     hook_close,
     hook_destroy
 };

CVSTrac 2.0.1