2 * irc.c - this file is part of vomak - a very simple IRC bot
4 * Copyright 2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
5 * Copyright 2008 Dominic Hopf <dh(at)dmaphy(dot)de>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 #include <sys/types.h>
29 #include <netinet/in.h>
30 #include <sys/socket.h>
41 #include <glib/gstdio.h>
51 static void irc_kick(irc_conn_t
*irc_conn
, const gchar
*nickname
);
52 static gboolean
irc_is_user_op(irc_conn_t
*irc_conn
, const gchar
*nickname
);
67 const goodies_t goodies
[] = {
68 { "!coffee", "A nice sexy waitress brings %s a big cup of coffee!" },
69 { "!coke", "A nice sexy waitress brings %s a cool bottle of coke!" },
70 { "!beer", "A nice sexy waitress brings %s a nice bottle of beer!" },
71 { "!pizza", "Someone calls Mario, and he brings %s a tasty hawaiian pizza!" },
75 gboolean
irc_query_names(gpointer data
)
77 irc_conn_t
*irc
= data
;
78 static gchar msg
[1024];
83 msg_len
= g_snprintf(msg
, sizeof msg
, "NAMES #%s\r\n", config
->channel
);
84 // send the message directly to avoid logging (prevent log file spamming)
85 send(irc
->socket
, msg
, msg_len
, 0);
91 /* 'line' should be terminated by "\r\n" (CRLF) */
92 static void irc_log(irc_conn_t
*irc_conn
, const gchar
*line
, gboolean send
)
96 static gchar str
[256];
99 if (! irc_conn
->log_fd
)
104 strftime(str
, sizeof str
, "%F %T %z ", tp
);
106 log_line
= g_string_new(str
);
107 if (send
) // if we are sending a message, add our ident string
109 g_string_append_printf(log_line
, ":%s!n=%s@%s ",
110 config
->nickname
, config
->username
, config
->servername
);
112 g_string_append(log_line
, line
);
113 /* add \r\n if it is missing */
114 if (strncmp(log_line
->str
+ log_line
->len
- 2, "\r\n", 2) != 0)
116 g_string_append(log_line
, "\r\n");
118 fwrite(log_line
->str
, log_line
->len
, 1, irc_conn
->log_fd
);
119 fflush(irc_conn
->log_fd
);
120 g_string_free(log_line
, TRUE
);
124 static void irc_send_private_message(irc_conn_t
*irc_conn
, const gchar
*target
, const gchar
*format
, ...)
126 static gchar tmp_msg
[1024];
127 static gchar msg
[1024];
134 va_start(ap
, format
);
135 g_vsnprintf(tmp_msg
, sizeof tmp_msg
, format
, ap
);
138 msg_len
= g_snprintf(msg
, sizeof msg
, "PRIVMSG %s :%s, %s\r\n", target
, target
, tmp_msg
);
139 irc_send(irc_conn
, msg
, msg_len
);
143 static gchar
*get_nickname(const gchar
*line
, guint len
)
145 static gchar result
[20];
148 // :eht16!n=enrico@uvena.de PRIVMSG #eht16 :df
149 for (i
= 0; i
< len
; i
++)
151 if (line
[i
] == '!' || line
[i
] == '=' || j
>= 19)
157 result
[j
++] = line
[i
];
165 static gchar
*get_command_sender(const gchar
*line
, guint len
, const gchar
*command
)
168 gsize cmd_len
= strlen(command
);
170 // :eht16!n=enrico@uvena.de PRIVMSG GeanyTestBot :hi
171 for (i
= 0; i
< len
; i
++)
176 if (strncmp(command
, line
+ i
+ 1, cmd_len
) == 0)
178 static gchar name
[20];
179 g_snprintf(name
, sizeof(name
), "%s :", config
->nickname
);
180 // if the receiver of the message is me, then it's a private message and
181 // we return the sender's nickname, otherwise NULL
182 if (strncmp(name
, line
+ i
+ cmd_len
+ 2, strlen(config
->nickname
) + 2) == 0 ||
183 strncmp("KICK", command
, 4) == 0)
185 return get_nickname(line
, len
);
196 static gint
get_response(const gchar
*line
, guint len
)
198 static gchar result
[4];
200 gboolean in_response
= FALSE
;
202 // :kornbluth.freenode.net 353 GeanyTestBot @ #eht16 :GeanyTestBot eht16
203 // :kornbluth.freenode.net 366 GeanyTestBot #eht16 :End of /NAMES list.
204 for (i
= 0; i
< len
; i
++)
206 // before a response code
207 if (line
[i
] != ' ' && ! in_response
)
210 // after a response code
211 if (line
[i
] == ' ' && in_response
)
218 i
++; // skip the space
220 result
[j
++] = line
[i
];
229 const gchar
*irc_get_message(const gchar
*line
, guint len
)
231 static gchar result
[1024] = { 0 };
233 gint state
= 0; // represents the current part of the whole line, separated by spaces
235 // :eht16!n=enrico@uvena.de PRIVMSG #eht16 :df foo: var
237 for (i
= 0; i
< len
; i
++)
248 else if (line
[i
] != '\r' && line
[i
] != '\n')
250 result
[j
++] = line
[i
];
259 static const gchar
*irc_get_message_with_name(const gchar
*line
, guint len
, const gchar
*name
)
264 tmp
= irc_get_message(line
, len
);
265 name_len
= strlen(name
);
267 if (strncmp(tmp
, name
, name_len
) == 0)
274 // returns a nickname argument given to cmd, it may also be "cmd for nickname", then the "for" is
276 static const gchar
*get_argument_target(const gchar
*line
, guint len
, const gchar
*cmd
)
278 static gchar result
[20];
282 // :eht16!n=enrico@uvena.de PRIVMSG #eht16 :!beer for me
283 tmp
= irc_get_message(line
, len
);
286 parts
= g_strsplit(tmp
, " ", -1);
287 if (parts
== NULL
|| parts
[0] == NULL
)
293 // if cmd doesn't match, skip it
294 if (parts
[0] != NULL
&& strcmp(parts
[0], cmd
) != 0)
300 if (parts
[1] == NULL
)
306 if (strcmp("for", parts
[1]) == 0)
308 if (parts
[2] != NULL
)
310 if (strcmp(parts
[2], "me") == 0)
313 return NULL
; // if we return NULL, the nickname of the caller is used, aka "me"
316 g_strlcpy(result
, parts
[2], sizeof(result
));
319 g_strlcpy(result
, parts
[1], sizeof(result
));
321 else if (strcmp(parts
[1], "me") == 0)
324 return NULL
; // if we return NULL, the nickname of the caller is used, aka "me"
328 g_strlcpy(result
, parts
[1], sizeof(result
));
336 // Parses the line and puts the first argument in arg1, all further arguments are concatenated
337 // in arg2. arg1 and arg2 should be freed when no longer needed.
338 // If arg1 and arg2 were set successfully, TRUE is returned, if any error occurs, FALSE is returned
339 // and arg1 and arg2 are set to NULL.
340 static gboolean
get_argument_two(const gchar
*line
, guint len
, const gchar
*cmd
,
341 gchar
**arg1
, gchar
**arg2
)
349 // :eht16!n=enrico@uvena.de PRIVMSG #eht16 :!learn keyword text to be added
350 tmp
= irc_get_message(line
, len
);
352 // -> !learn keyword text to be added
353 parts
= g_strsplit(tmp
, " ", 3);
354 if (parts
== NULL
|| parts
[0] == NULL
)
360 // if cmd doesn't match, skip it
361 if (parts
[0] != NULL
&& strcmp(parts
[0], cmd
) != 0)
367 if (parts
[1] == NULL
|| parts
[2] == NULL
)
373 *arg1
= g_strdup(parts
[1]);
374 *arg2
= g_strdup(parts
[2]);
382 static void command_fortune(irc_conn_t
*irc_conn
)
384 GError
*error
= NULL
;
388 if (g_spawn_command_line_sync(config
->fortune_cmd
, &out
, &err
, NULL
, &error
))
390 if (out
!= NULL
&& *out
!= '\0')
392 gchar
**lines
= g_strsplit(out
, "\n", -1);
395 len
= g_strv_length(lines
);
396 for (i
= 0; i
< len
; i
++)
398 if (strlen(g_strchomp(lines
[i
])) > 0)
399 irc_send_message(irc_conn
, NULL
, lines
[i
]);
405 vomak_warning("Executing fortune failed (%s)", err
);
412 vomak_warning("Executing fortune failed (%s)", error
->message
);
418 static void command_moo(irc_conn_t
*irc_conn
)
420 gint32 rand
= g_random_int();
425 const gchar
*moo_str
[] = {
432 "..\"Have you mooed today?\"..\r\n",
436 for (i
= 0; moo_str
[i
] != NULL
; i
++)
438 irc_send_message(irc_conn
, NULL
, moo_str
[i
]);
443 irc_send_message(irc_conn
, NULL
, "I have Super Cow Powers. Have you mooed today?");
448 static void command_learn(irc_conn_t
*irc_conn
, const gchar
*line
, guint len
)
452 if (get_argument_two(line
, len
, "!learn", &arg1
, &arg2
))
454 gint result
= help_system_learn(arg1
, arg2
);
461 text
= g_strdup_printf("new keyword \"%s\" was added.", arg1
);
466 text
= g_strdup_printf("existing keyword \"%s\" was updated.", arg1
);
471 text
= g_strdup("an error occurred. Database not updated.");
475 irc_send_message(irc_conn
, get_nickname(line
, len
), "%s", text
);
482 irc_send_message(irc_conn
, get_nickname(line
, len
),
483 "wrong usage of !learn. Use \"?? learn\" for usage information.");
487 static void command_alias(irc_conn_t
*irc_conn
, const gchar
*line
, guint len
)
491 if (get_argument_two(line
, len
, "!alias", &arg1
, &arg2
))
493 // detect if arg2 has more than one word by scanning for spaces in
495 if (strchr(arg2
, ' '))
497 irc_send_message(irc_conn
, get_nickname(line
, len
),
498 "You gave me more than two arguments for !alias. I can not handle this.");
500 // check if the target actually exist and refuse if it doesn't exist
501 else if (g_hash_table_lookup(config
->data
, arg2
) == NULL
)
503 irc_send_message(irc_conn
, get_nickname(line
, len
),
504 "The given target for the alias does not exist. I will refuse your request.");
510 gchar
*alias
= g_strconcat("@", arg2
, NULL
);
512 result
= help_system_learn(arg1
, alias
);
518 text
= g_strdup_printf("new alias \"%s\" was added.", arg1
);
523 text
= g_strdup_printf("existing alias \"%s\" was updated.", arg1
);
528 text
= g_strdup("An error occurred. Database not updated.");
533 irc_send_message(irc_conn
, get_nickname(line
, len
), "%s", text
);
542 irc_send_message(irc_conn
, get_nickname(line
, len
),
543 "wrong usage of !alias. Use \"?? alias\" for usage information.");
547 static void command_goodies(irc_conn_t
*irc_conn
, const gchar
*line
, guint len
, gint goodie
)
549 const goodies_t
*g
= &goodies
[goodie
];
550 const gchar
*arg
= get_argument_target(line
, len
, g
->command
);
553 arg
= get_nickname(line
, len
);
555 irc_send_message(irc_conn
, NULL
,
560 static void process_command(irc_conn_t
*irc_conn
, const gchar
*line
, guint len
, const gchar
*content
)
563 if (strncmp(content
, "!test", 5) == 0)
565 irc_send_message(irc_conn
, get_nickname(line
, len
), "I don't like tests!");
568 else if (strncmp(content
, "!moo", 4) == 0)
570 command_moo(irc_conn
);
573 else if (config
->fortune_cmd
!= NULL
&& strncmp(content
, "!fortune", 8) == 0)
575 command_fortune(irc_conn
);
578 else if (strncmp(content
, "!coffee", 7) == 0)
580 command_goodies(irc_conn
, line
, len
, GOODIES_COFFEE
);
583 else if (strncmp(content
, "!coke", 5) == 0)
585 command_goodies(irc_conn
, line
, len
, GOODIES_COKE
);
588 else if (strncmp(content
, "!beer", 5) == 0)
590 command_goodies(irc_conn
, line
, len
, GOODIES_BEER
);
593 else if (strncmp(content
, "!pizza", 5) == 0)
595 command_goodies(irc_conn
, line
, len
, GOODIES_PIZZA
);
598 else if (strncmp(content
, "!help", 5) == 0)
600 help_system_query("?? help");
604 * You have to register your bot with nickserv and add it to the access-list
605 * of your channel to make the !roulette-command work.
606 * This is just tested on FreeNode. Please feel free to write patches, that
607 * will make this work on other Networks.
609 else if (strncmp(content
, "!roulette", 9) == 0)
611 gint32 rand
= g_random_int();
612 static gint bullets_left
= 6;
614 if (rand
% 6 == 0 || bullets_left
<= 0)
616 irc_send_message(irc_conn
, NULL
, "*bang*");
617 irc_kick(irc_conn
, get_nickname(line
, len
));
623 irc_send_message(irc_conn
, NULL
, "*click*");
628 /// TODO require op privileges for !learn
629 else if (strncmp(content
, "!learn", 6) == 0)
631 command_learn(irc_conn
, line
, len
);
634 else if (strncmp(content
, "!alias", 6) == 0)
636 command_alias(irc_conn
, line
, len
);
641 static gboolean
process_line(irc_conn_t
*irc_conn
, const gchar
*line
, guint len
)
643 static gchar msg
[1024];
645 gint response
= get_response(line
, len
);
646 static gchar tmp_userlist
[1024];
648 const gchar
*content
;
649 static gboolean connected
= FALSE
;
651 // don't log the NAMES command's output (prevent log file spam)
652 if (response
!= 353 && response
!= 366)
653 irc_log(irc_conn
, line
, FALSE
);
655 // An error occurred, try to quit cleanly and print the error
656 if ((response
> 400 && response
< 503))
658 // ignore Freenode's info messages sent with error code 477
659 // (see http://freenode.net/faq.shtml#freenode-info)
660 if (response
!= 477 || strstr(line
, "[freenode-info]") == NULL
)
663 syslog(LOG_WARNING
, "received error: %d (%s)", response
, g_strstrip((gchar
*) line
));
665 g_print("Error: %s", line
);
680 content
= irc_get_message(line
, len
);
682 // retrieve user name list
685 if (tmp_userlist
[0] == '\0')
686 g_strlcpy(tmp_userlist
, strchr(content
, ':') + 1, sizeof(tmp_userlist
));
688 g_strlcat(tmp_userlist
, strchr(content
, ':') + 1, sizeof(tmp_userlist
));
690 // retrieve end of user name list
691 else if (response
== 366)
693 if (tmp_userlist
[0] != '\0')
695 set_user_list(tmp_userlist
);
696 tmp_userlist
[0] = '\0';
699 else if (! connected
)
701 // don't do anything else until we got finished connecting (to skip MOTD messages)
704 else if (strncmp("PING :", line
, 6) == 0)
706 msg_len
= g_snprintf(msg
, sizeof msg
, "PONG %s\r\n", line
+ 6); // 7 = "PING :"
707 debug("PONG: -%s-\n", msg
);
708 irc_send(irc_conn
, msg
, msg_len
);
710 // handle private message
711 else if ((priv_sender
= get_command_sender(line
, len
, "PRIVMSG")) != NULL
)
713 // to be able to send private messages to users, you need to register your bot's
714 // nickname with Nickserv (at least on Freenode)
715 irc_send_private_message(irc_conn
, priv_sender
, "I don't like private messages!");
717 // handle kicks (we were kicked, bastards)
718 else if (get_command_sender(line
, len
, "KICK") != NULL
)
720 if (config
->auto_rejoin
)
722 g_usleep(5000000); // just wait a little bit
723 msg_len
= g_snprintf(msg
, sizeof msg
, "JOIN #%s\r\n", config
->channel
);
724 irc_send(irc_conn
, msg
, msg_len
);
731 // Hi /me, acts on "hello $nickname" and "hi $nickname", hi and hello are case-insensitive
733 else if (strstr(content
, config
->nickname
) != NULL
)
735 const gchar
*tmp_msg
= irc_get_message_with_name(line
, len
, config
->nickname
);
737 if (strncasecmp("hi", content
, 2) == 0 || strncasecmp("hello", content
, 5) == 0 || strncasecmp("hey", content
, 3) == 0 ||
738 strcasecmp(", hi", tmp_msg
) == 0 || strcasecmp(", hello", tmp_msg
) == 0 || strcasecmp(", hey", tmp_msg
) == 0 ||
739 strcasecmp(": hi", tmp_msg
) == 0 || strcasecmp(": hello", tmp_msg
) == 0 || strcasecmp(": hey", tmp_msg
) == 0)
741 irc_send_message(irc_conn
, NULL
,
742 "Hi %s. My name is %s and I'm here to offer additional services to you! "
743 "Try \"?? help\" for general information and \"?? vomak\" for information about me.",
744 get_nickname(line
, len
), config
->nickname
);
746 else if (strncasecmp("thanks", content
, 6) == 0 || strncasecmp("thx", content
, 3) == 0 ||
747 strcasecmp(", thanks", tmp_msg
) == 0 || strcasecmp(", thx", tmp_msg
) == 0 ||
748 strcasecmp(": thanks", tmp_msg
) == 0 || strcasecmp(": thx", tmp_msg
) == 0)
750 irc_send_message(irc_conn
, get_nickname(line
, len
),
751 "no problem. It was a pleasure to serve you.");
755 else if (strncmp(content
, "?? ", 3) == 0)
757 help_system_query(content
);
759 // pass to process_command() to process other commands (!beer, !test, !learn, ...)
760 else if (*content
== '!')
762 process_command(irc_conn
, line
, len
, content
);
770 * Please note that this will not work on Networks without ChanServ, e.g. on
771 * Quakenet or IRCnet. Your Bot has to be registered with NickServ and to be
772 * added to the channel access list for this to work.
774 static gboolean
irc_toggle_op(irc_conn_t
*irc_conn
, gboolean request_op
)
777 static gchar msg
[1024];
780 if (irc_is_user_op(irc_conn
, "ChanServ"))
782 cmd
= (request_op
) ? "op" : "deop";
783 msg_len
= g_snprintf(msg
, sizeof msg
, "PRIVMSG ChanServ :%s #%s\r\n", cmd
, config
->channel
);
784 irc_send(irc_conn
, msg
, msg_len
);
788 return FALSE
; /* it seems we don't have a ChanServ bot */
792 static gboolean
irc_is_user_op(irc_conn_t
*irc_conn
, const gchar
*nickname
)
795 const gchar
*userlist
;
797 if (nickname
== NULL
)
800 userlist
= get_user_list();
802 if ( (pos
= strstr(userlist
, nickname
)) )
804 if ( (pos
- 1) >= userlist
&& (*(pos
- 1) == '@') )
812 irc_send_message(irc_conn
, NULL
,
813 "Hey. There are crazy things going on here. (O.o)");
815 syslog(LOG_WARNING
, "user %s not found in names list of #%s", nickname
, config
->channel
);
823 static void irc_kick(irc_conn_t
*irc_conn
, const gchar
*nickname
)
825 static gchar msg
[1024];
826 gboolean need_deop
= FALSE
;
831 if (! irc_is_user_op(irc_conn
, config
->nickname
))
833 // if irc_toggle_op fails, most probably we don't have a ChanServ and at this point we
834 // know we are not an op, so fail silently and don't try to kick
835 if (! irc_toggle_op(irc_conn
, TRUE
)) /// TODO: prüfen, ob das auch erfolreich war
840 // give the server a chance to set the op status for us before we make us of it,
841 // and let the victim read his *bang* message
844 msg_len
= g_snprintf(msg
, sizeof msg
, "KICK #%s %s\r\n", config
->channel
, nickname
);
845 irc_send(irc_conn
, msg
, msg_len
);
847 irc_toggle_op(irc_conn
, FALSE
);
851 static gboolean
input_cb(GIOChannel
*source
, GIOCondition cond
, gpointer data
)
856 irc_conn_t
*irc
= data
;
859 if (cond
& (G_IO_ERR
| G_IO_HUP
))
862 if ((buf_len
= socket_fd_gets(irc
->socket
, buf
, sizeof(buf
))) != -1)
864 ret
= process_line(irc
, buf
, buf_len
);
868 irc_conn_t
*irc
= data
;
870 if (cond
& (G_IO_IN
| G_IO_PRI
))
878 rv
= g_io_channel_read_line(source
, &buf
, &buf_len
, NULL
, &err
);
882 buf
[buf_len
] = '\0'; // skip trailing \r\n
884 process_line(irc
, buf
, buf_len
);
889 debug("%s: error: %s", __func__
, err
->message
);
894 while (rv
== G_IO_STATUS_NORMAL
|| rv
== G_IO_STATUS_AGAIN
);
895 debug("%s: status %d\n", __func__
, rv
);
902 void irc_send_message(irc_conn_t
*irc_conn
, const gchar
*target
, const gchar
*format
, ...)
904 static gchar tmp_msg
[1024];
905 static gchar msg
[1024];
909 va_start(ap
, format
);
910 g_vsnprintf(tmp_msg
, sizeof tmp_msg
, format
, ap
);
914 msg_len
= g_snprintf(msg
, sizeof msg
, "PRIVMSG #%s :%s, %s\r\n", config
->channel
, target
, tmp_msg
);
916 msg_len
= g_snprintf(msg
, sizeof msg
, "PRIVMSG #%s :%s\r\n", config
->channel
, tmp_msg
);
918 irc_send(irc_conn
, msg
, msg_len
);
922 // simple wrapper for send() to enable logging for sent commands
923 gint
irc_send(irc_conn_t
*irc_conn
, const gchar
*msg
, guint msg_len
)
925 irc_log(irc_conn
, msg
, TRUE
);
926 return send(irc_conn
->socket
, msg
, msg_len
, 0);
930 void irc_goodbye(irc_conn_t
*irc
)
935 if (NZV(irc
->quit_msg
))
936 len
= g_snprintf(msg
, sizeof msg
, "QUIT :%s\r\n", irc
->quit_msg
);
938 len
= g_strlcpy(msg
, "QUIT :Good bye. It was a pleasure to serve you\r\n", sizeof msg
);
939 irc_send(irc
, msg
, len
);
943 void irc_logfile_reopen(irc_conn_t
*irc_conn
)
947 if (irc_conn
->log_fd
!= NULL
)
948 fclose(irc_conn
->log_fd
);
950 if (NZV(config
->logfile
))
952 irc_conn
->log_fd
= g_fopen(config
->logfile
, "a");
953 if (! irc_conn
->log_fd
)
954 vomak_warning("Logfile could not be opened.");
959 gint
irc_finalize(irc_conn_t
*irc_conn
)
961 if (irc_conn
->socket
< 0)
964 if (irc_conn
->lock_tag
> 0)
965 g_source_remove(irc_conn
->lock_tag
);
967 if (irc_conn
->log_fd
!= NULL
)
969 irc_log(irc_conn
, "Stop logging\r\n", FALSE
);
970 fclose(irc_conn
->log_fd
);
973 if (irc_conn
->read_ioc
)
975 g_io_channel_shutdown(irc_conn
->read_ioc
, TRUE
, NULL
);
976 g_io_channel_unref(irc_conn
->read_ioc
);
977 irc_conn
->read_ioc
= NULL
;
979 socket_fd_close(irc_conn
->socket
);
980 irc_conn
->socket
= -1;
982 g_free(irc_conn
->quit_msg
);
988 void irc_connect(irc_conn_t
*irc_conn
)
991 struct sockaddr_in their_addr
;
997 // Connect the socket to the server
998 if ((he
= gethostbyname(config
->server
)) == NULL
)
1000 perror("gethostbyname");
1004 if ((irc_conn
->socket
= socket(PF_INET
, SOCK_STREAM
, 0)) == -1)
1010 their_addr
.sin_family
= PF_INET
;
1011 their_addr
.sin_port
= htons(6667);
1012 their_addr
.sin_addr
= *((struct in_addr
*)he
->h_addr_list
[0]);
1013 memset(&(their_addr
.sin_zero
), '\0', 8);
1015 if (connect(irc_conn
->socket
, (struct sockaddr
*)&their_addr
, sizeof(struct sockaddr
)) == -1)
1021 if (NZV(config
->logfile
))
1023 irc_conn
->log_fd
= g_fopen(config
->logfile
, "a");
1024 if (irc_conn
->log_fd
)
1025 irc_log(irc_conn
, "Start logging\r\n", FALSE
);
1027 vomak_warning("Logfile could not be opened.");
1030 msg_len
= g_snprintf(msg
, sizeof(msg
), "USER %s %s %s :%s\r\n",
1031 config
->username
, config
->servername
, config
->servername
, config
->realname
);
1032 if (irc_send(irc_conn
, msg
, msg_len
) == -1)
1034 perror("send USER");
1036 // and how we are called
1037 msg_len
= g_snprintf(msg
, sizeof(msg
), "NICK %s\r\n", config
->nickname
);
1038 if (irc_send(irc_conn
, msg
, msg_len
) == -1)
1040 perror("send NICK");
1042 // identify our nick
1043 if (NZV(config
->nickserv_password
))
1045 msg_len
= g_snprintf(msg
, sizeof(msg
), "PRIVMSG nickserv :identify %s\r\n", config
->nickserv_password
);
1046 // don't use irc_send() here, no need to log our password
1047 if (send(irc_conn
->socket
, msg
, msg_len
, 0) == -1)
1049 perror("send NICKSERV");
1053 msg_len
= g_snprintf(msg
, sizeof msg
, "JOIN #%s\r\n", config
->channel
);
1054 if (irc_send(irc_conn
, msg
, msg_len
) == -1)
1059 // input callback, attached to the main loop
1060 irc_conn
->read_ioc
= g_io_channel_unix_new(irc_conn
->socket
);
1061 //~ g_io_channel_set_flags(irc_conn.read_ioc, G_IO_FLAG_NONBLOCK, NULL);
1062 g_io_channel_set_encoding(irc_conn
->read_ioc
, NULL
, NULL
);
1063 irc_conn
->lock_tag
= g_io_add_watch(irc_conn
->read_ioc
, G_IO_IN
|G_IO_PRI
|G_IO_ERR
, input_cb
, irc_conn
);