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
);
68 const goodies_t goodies
[] = {
69 { "!coffee", "A nice sexy waitress brings %s a big cup of coffee!" },
70 { "!coke", "A nice sexy waitress brings %s a cool bottle of coke!" },
71 { "!beer", "A nice sexy waitress brings %s a nice bottle of beer!" },
72 { "!tea", "A nice sexy waitress brings %s a cup of hot tea!" },
73 { "!pizza", "Someone calls Mario, and he brings %s a tasty hawaiian pizza!" },
77 gboolean
irc_query_names(gpointer data
)
79 irc_conn_t
*irc
= data
;
80 static gchar msg
[1024];
85 msg_len
= g_snprintf(msg
, sizeof msg
, "NAMES #%s\r\n", config
->channel
);
86 // send the message directly to avoid logging (prevent log file spamming)
87 send(irc
->socket
, msg
, msg_len
, MSG_NOSIGNAL
);
93 /* 'line' should be terminated by "\r\n" (CRLF) */
94 static void irc_log(irc_conn_t
*irc_conn
, const gchar
*line
, gboolean send
)
98 static gchar str
[256];
101 if (! irc_conn
->log_fd
)
106 strftime(str
, sizeof str
, "%F %T %z ", tp
);
108 log_line
= g_string_new(str
);
109 if (send
) // if we are sending a message, add our ident string
111 g_string_append_printf(log_line
, ":%s!n=%s@%s ",
112 config
->nickname
, config
->username
, config
->servername
);
114 g_string_append(log_line
, line
);
115 /* add \r\n if it is missing */
116 if (strncmp(log_line
->str
+ log_line
->len
- 2, "\r\n", 2) != 0)
118 g_string_append(log_line
, "\r\n");
120 fwrite(log_line
->str
, log_line
->len
, 1, irc_conn
->log_fd
);
121 fflush(irc_conn
->log_fd
);
122 g_string_free(log_line
, TRUE
);
126 static void irc_send_private_message(irc_conn_t
*irc_conn
, const gchar
*target
, const gchar
*format
, ...)
128 static gchar tmp_msg
[1024];
129 static gchar msg
[1024];
136 va_start(ap
, format
);
137 g_vsnprintf(tmp_msg
, sizeof tmp_msg
, format
, ap
);
140 msg_len
= g_snprintf(msg
, sizeof msg
, "PRIVMSG %s :%s, %s\r\n", target
, target
, tmp_msg
);
141 irc_send(irc_conn
, msg
, msg_len
);
145 static gchar
*get_nickname(const gchar
*line
, guint len
)
147 static gchar result
[20];
150 // :eht16!n=enrico@uvena.de PRIVMSG #eht16 :df
151 for (i
= 0; i
< len
; i
++)
153 if (line
[i
] == '!' || line
[i
] == '=' || j
>= 19)
159 result
[j
++] = line
[i
];
167 static gchar
*get_command_sender(const gchar
*line
, guint len
, const gchar
*command
)
170 gsize cmd_len
= strlen(command
);
172 // :eht16!n=enrico@uvena.de PRIVMSG GeanyTestBot :hi
173 for (i
= 0; i
< len
; i
++)
178 if (strncmp(command
, line
+ i
+ 1, cmd_len
) == 0)
180 static gchar name
[20];
181 g_snprintf(name
, sizeof(name
), "%s :", config
->nickname
);
182 // if the receiver of the message is me, then it's a private message and
183 // we return the sender's nickname, otherwise NULL
184 if (strncmp(name
, line
+ i
+ cmd_len
+ 2, strlen(config
->nickname
) + 2) == 0 ||
185 strncmp("KICK", command
, 4) == 0)
187 return get_nickname(line
, len
);
198 static gint
get_response(const gchar
*line
, guint len
)
200 static gchar result
[4];
202 gboolean in_response
= FALSE
;
204 // :kornbluth.freenode.net 353 GeanyTestBot @ #eht16 :GeanyTestBot eht16
205 // :kornbluth.freenode.net 366 GeanyTestBot #eht16 :End of /NAMES list.
206 for (i
= 0; i
< len
; i
++)
208 // before a response code
209 if (line
[i
] != ' ' && ! in_response
)
212 // after a response code
213 if (line
[i
] == ' ' && in_response
)
220 i
++; // skip the space
222 result
[j
++] = line
[i
];
231 const gchar
*irc_get_message(const gchar
*line
, guint len
)
233 static gchar result
[1024] = { 0 };
235 gint state
= 0; // represents the current part of the whole line, separated by spaces
237 // :eht16!n=enrico@uvena.de PRIVMSG #eht16 :df foo: var
239 for (i
= 0; i
< len
; i
++)
250 else if (line
[i
] != '\r' && line
[i
] != '\n')
252 result
[j
++] = line
[i
];
261 static const gchar
*irc_get_message_with_name(const gchar
*line
, guint len
, const gchar
*name
)
266 tmp
= irc_get_message(line
, len
);
267 name_len
= strlen(name
);
269 if (strncmp(tmp
, name
, name_len
) == 0)
276 // returns a nickname argument given to cmd, it may also be "cmd for nickname", then the "for" is
278 static const gchar
*get_argument_target(const gchar
*line
, guint len
, const gchar
*cmd
)
280 static gchar result
[20];
284 // :eht16!n=enrico@uvena.de PRIVMSG #eht16 :!beer for me
285 tmp
= irc_get_message(line
, len
);
288 parts
= g_strsplit(tmp
, " ", -1);
289 if (parts
== NULL
|| parts
[0] == NULL
)
295 // if cmd doesn't match, skip it
296 if (parts
[0] != NULL
&& strcmp(parts
[0], cmd
) != 0)
302 if (parts
[1] == NULL
)
308 if (strcmp("for", parts
[1]) == 0)
310 if (parts
[2] != NULL
)
312 if (strcmp(parts
[2], "me") == 0)
315 return NULL
; // if we return NULL, the nickname of the caller is used, aka "me"
318 g_strlcpy(result
, parts
[2], sizeof(result
));
321 g_strlcpy(result
, parts
[1], sizeof(result
));
323 else if (strcmp(parts
[1], "me") == 0)
326 return NULL
; // if we return NULL, the nickname of the caller is used, aka "me"
330 g_strlcpy(result
, parts
[1], sizeof(result
));
338 // Parses the line and puts the first argument in arg1, all further arguments are concatenated
339 // in arg2. arg1 and arg2 should be freed when no longer needed.
340 // If arg1 and arg2 were set successfully, TRUE is returned, if any error occurs, FALSE is returned
341 // and arg1 and arg2 are set to NULL.
342 static gboolean
get_argument_two(const gchar
*line
, guint len
, const gchar
*cmd
,
343 gchar
**arg1
, gchar
**arg2
)
351 // :eht16!n=enrico@uvena.de PRIVMSG #eht16 :!learn keyword text to be added
352 tmp
= irc_get_message(line
, len
);
354 // -> !learn keyword text to be added
355 parts
= g_strsplit(tmp
, " ", 3);
356 if (parts
== NULL
|| parts
[0] == NULL
)
362 // if cmd doesn't match, skip it
363 if (parts
[0] != NULL
&& strcmp(parts
[0], cmd
) != 0)
369 if (parts
[1] == NULL
|| parts
[2] == NULL
)
375 *arg1
= g_strdup(parts
[1]);
376 *arg2
= g_strdup(parts
[2]);
384 static void command_fortune(irc_conn_t
*irc_conn
)
386 GError
*error
= NULL
;
390 if (g_spawn_command_line_sync(config
->fortune_cmd
, &out
, &err
, NULL
, &error
))
394 gchar
**lines
= g_strsplit(out
, "\n", -1);
397 len
= g_strv_length(lines
);
398 for (i
= 0; i
< len
; i
++)
400 if (strlen(g_strchomp(lines
[i
])) > 0)
401 irc_send_message(irc_conn
, NULL
, lines
[i
]);
407 vomak_warning("Executing fortune failed (%s)", err
);
414 vomak_warning("Executing fortune failed (%s)", error
->message
);
420 static void command_moo(irc_conn_t
*irc_conn
)
422 gint32 rand
= g_random_int();
427 const gchar
*moo_str
[] = {
434 "..\"Have you mooed today?\"..\r\n",
438 for (i
= 0; moo_str
[i
] != NULL
; i
++)
440 irc_send_message(irc_conn
, NULL
, moo_str
[i
]);
445 irc_send_message(irc_conn
, NULL
, "I have Super Cow Powers. Have you mooed today?");
450 static void command_learn(irc_conn_t
*irc_conn
, const gchar
*line
, guint len
)
454 if (get_argument_two(line
, len
, "!learn", &arg1
, &arg2
))
456 gint result
= help_system_learn(arg1
, arg2
);
463 text
= g_strdup_printf("new keyword \"%s\" was added.", arg1
);
468 text
= g_strdup_printf("existing keyword \"%s\" was updated.", arg1
);
473 text
= g_strdup("an error occurred. Database not updated.");
477 irc_send_message(irc_conn
, get_nickname(line
, len
), "%s", text
);
484 irc_send_message(irc_conn
, get_nickname(line
, len
),
485 "wrong usage of !learn. Use \"?? learn\" for usage information.");
489 static void command_alias(irc_conn_t
*irc_conn
, const gchar
*line
, guint len
)
493 if (get_argument_two(line
, len
, "!alias", &arg1
, &arg2
))
495 // detect if arg2 has more than one word by scanning for spaces in
497 if (strchr(arg2
, ' '))
499 irc_send_message(irc_conn
, get_nickname(line
, len
),
500 "You gave me more than two arguments for !alias. I can not handle this.");
502 // check if the target actually exist and refuse if it doesn't exist
503 else if (g_hash_table_lookup(config
->data
, arg2
) == NULL
)
505 irc_send_message(irc_conn
, get_nickname(line
, len
),
506 "The given target for the alias does not exist. I will refuse your request.");
512 gchar
*alias
= g_strconcat("@", arg2
, NULL
);
514 result
= help_system_learn(arg1
, alias
);
520 text
= g_strdup_printf("new alias \"%s\" was added.", arg1
);
525 text
= g_strdup_printf("existing alias \"%s\" was updated.", arg1
);
530 text
= g_strdup("An error occurred. Database not updated.");
535 irc_send_message(irc_conn
, get_nickname(line
, len
), "%s", text
);
544 irc_send_message(irc_conn
, get_nickname(line
, len
),
545 "wrong usage of !alias. Use \"?? alias\" for usage information.");
549 static void command_goodies(irc_conn_t
*irc_conn
, const gchar
*line
, guint len
, gint goodie
)
551 const goodies_t
*g
= &goodies
[goodie
];
552 const gchar
*arg
= get_argument_target(line
, len
, g
->command
);
555 arg
= get_nickname(line
, len
);
557 irc_send_message(irc_conn
, NULL
,
562 static void process_command(irc_conn_t
*irc_conn
, const gchar
*line
, guint len
, const gchar
*content
)
565 if (strncmp(content
, "!test", 5) == 0)
567 irc_send_message(irc_conn
, get_nickname(line
, len
), "I don't like tests!");
570 else if (strncmp(content
, "!moo", 4) == 0)
572 command_moo(irc_conn
);
575 else if (config
->fortune_cmd
!= NULL
&& strncmp(content
, "!fortune", 8) == 0)
577 command_fortune(irc_conn
);
580 else if (strncmp(content
, "!coffee", 7) == 0)
582 command_goodies(irc_conn
, line
, len
, GOODIES_COFFEE
);
585 else if (strncmp(content
, "!coke", 5) == 0)
587 command_goodies(irc_conn
, line
, len
, GOODIES_COKE
);
590 else if (strncmp(content
, "!beer", 5) == 0)
592 command_goodies(irc_conn
, line
, len
, GOODIES_BEER
);
595 else if (strncmp(content
, "!pizza", 5) == 0)
597 command_goodies(irc_conn
, line
, len
, GOODIES_PIZZA
);
600 else if (strncmp(content
, "!tea", 5) == 0)
602 command_goodies(irc_conn
, line
, len
, GOODIES_TEA
);
605 else if (strncmp(content
, "!help", 5) == 0)
607 help_system_query("?? help");
611 * You have to register your bot with nickserv and add it to the access-list
612 * of your channel to make the !roulette-command work.
613 * This is just tested on FreeNode. Please feel free to write patches, that
614 * will make this work on other Networks.
616 else if (strncmp(content
, "!roulette", 9) == 0)
618 gint32 rand
= g_random_int();
619 static gint bullets_left
= 6;
621 if (rand
% 6 == 0 || bullets_left
<= 0)
623 irc_send_message(irc_conn
, NULL
, "*bang*");
624 irc_kick(irc_conn
, get_nickname(line
, len
));
630 irc_send_message(irc_conn
, NULL
, "*click*");
635 /// TODO require op privileges for !learn
636 else if (strncmp(content
, "!learn", 6) == 0)
638 command_learn(irc_conn
, line
, len
);
641 else if (strncmp(content
, "!alias", 6) == 0)
643 command_alias(irc_conn
, line
, len
);
648 static gboolean
process_line(irc_conn_t
*irc_conn
, const gchar
*line
, guint len
)
650 static gchar msg
[1024];
652 gint response
= get_response(line
, len
);
653 static gchar tmp_userlist
[1024];
655 const gchar
*content
;
656 static gboolean connected
= FALSE
;
658 // don't log the NAMES command's output (prevent log file spam)
659 if (response
!= 353 && response
!= 366)
660 irc_log(irc_conn
, line
, FALSE
);
662 // An error occurred, try to quit cleanly and print the error
663 if ((response
> 400 && response
< 503))
665 // ignore Freenode's info messages sent with error code 477
666 // (see http://freenode.net/faq.shtml#freenode-info)
667 if (response
!= 477 || strstr(line
, "[freenode-info]") == NULL
)
670 syslog(LOG_WARNING
, "received error: %d (%s)", response
, g_strstrip((gchar
*) line
));
672 g_print("Error: %s", line
);
687 content
= irc_get_message(line
, len
);
689 // retrieve user name list
692 if (tmp_userlist
[0] == '\0')
693 g_strlcpy(tmp_userlist
, strchr(content
, ':') + 1, sizeof(tmp_userlist
));
695 g_strlcat(tmp_userlist
, strchr(content
, ':') + 1, sizeof(tmp_userlist
));
697 // retrieve end of user name list
698 else if (response
== 366)
700 if (tmp_userlist
[0] != '\0')
702 set_user_list(tmp_userlist
);
703 tmp_userlist
[0] = '\0';
706 else if (! connected
)
708 // don't do anything else until we got finished connecting (to skip MOTD messages)
711 else if (strncmp("PING :", line
, 6) == 0)
713 msg_len
= g_snprintf(msg
, sizeof msg
, "PONG %s\r\n", line
+ 6); // 7 = "PING :"
714 debug("PONG: -%s-\n", msg
);
715 irc_send(irc_conn
, msg
, msg_len
);
717 // handle private message
718 else if ((priv_sender
= get_command_sender(line
, len
, "PRIVMSG")) != NULL
)
720 // to be able to send private messages to users, you need to register your bot's
721 // nickname with Nickserv (at least on Freenode)
722 irc_send_private_message(irc_conn
, priv_sender
, "I don't like private messages!");
724 // handle kicks (we were kicked, bastards)
725 else if (get_command_sender(line
, len
, "KICK") != NULL
)
727 if (config
->auto_rejoin
)
729 g_usleep(5000000); // just wait a little bit
730 msg_len
= g_snprintf(msg
, sizeof msg
, "JOIN #%s\r\n", config
->channel
);
731 irc_send(irc_conn
, msg
, msg_len
);
738 // Hi /me, acts on "hello $nickname" and "hi $nickname", hi and hello are case-insensitive
740 else if (strstr(content
, config
->nickname
) != NULL
)
742 const gchar
*tmp_msg
= irc_get_message_with_name(line
, len
, config
->nickname
);
744 if (strncasecmp("hi", content
, 2) == 0 || strncasecmp("hello", content
, 5) == 0 || strncasecmp("hey", content
, 3) == 0 ||
745 strcasecmp(", hi", tmp_msg
) == 0 || strcasecmp(", hello", tmp_msg
) == 0 || strcasecmp(", hey", tmp_msg
) == 0 ||
746 strcasecmp(": hi", tmp_msg
) == 0 || strcasecmp(": hello", tmp_msg
) == 0 || strcasecmp(": hey", tmp_msg
) == 0)
748 irc_send_message(irc_conn
, NULL
,
749 "Hi %s. My name is %s and I'm here to offer additional services to you! "
750 "Try \"?? help\" for general information and \"?? vomak\" for information about me.",
751 get_nickname(line
, len
), config
->nickname
);
753 else if (strncasecmp("thanks", content
, 6) == 0 || strncasecmp("thx", content
, 3) == 0 ||
754 strcasecmp(", thanks", tmp_msg
) == 0 || strcasecmp(", thx", tmp_msg
) == 0 ||
755 strcasecmp(": thanks", tmp_msg
) == 0 || strcasecmp(": thx", tmp_msg
) == 0)
757 irc_send_message(irc_conn
, get_nickname(line
, len
),
758 "no problem. It was a pleasure to serve you.");
762 else if (strncmp(content
, "?? ", 3) == 0)
764 help_system_query(content
);
766 // pass to process_command() to process other commands (!beer, !test, !learn, ...)
767 else if (*content
== '!')
769 process_command(irc_conn
, line
, len
, content
);
777 * Please note that this will not work on Networks without ChanServ, e.g. on
778 * Quakenet or IRCnet. Your Bot has to be registered with NickServ and to be
779 * added to the channel access list for this to work.
781 static gboolean
irc_toggle_op(irc_conn_t
*irc_conn
, gboolean request_op
)
784 static gchar msg
[1024];
787 if (irc_is_user_op(irc_conn
, "ChanServ"))
789 cmd
= (request_op
) ? "op" : "deop";
790 msg_len
= g_snprintf(msg
, sizeof msg
, "PRIVMSG ChanServ :%s #%s\r\n", cmd
, config
->channel
);
791 irc_send(irc_conn
, msg
, msg_len
);
795 return FALSE
; /* it seems we don't have a ChanServ bot */
799 static gboolean
irc_is_user_op(irc_conn_t
*irc_conn
, const gchar
*nickname
)
802 const gchar
*userlist
;
804 if (nickname
== NULL
)
807 userlist
= get_user_list();
809 if ( (pos
= strstr(userlist
, nickname
)) )
811 if ( (pos
- 1) >= userlist
&& (*(pos
- 1) == '@') )
819 irc_send_message(irc_conn
, NULL
,
820 "Hey. There are crazy things going on here. (O.o)");
822 syslog(LOG_WARNING
, "user %s not found in names list of #%s", nickname
, config
->channel
);
830 static void irc_kick(irc_conn_t
*irc_conn
, const gchar
*nickname
)
832 static gchar msg
[1024];
833 gboolean need_deop
= FALSE
;
838 if (! irc_is_user_op(irc_conn
, config
->nickname
))
840 // if irc_toggle_op fails, most probably we don't have a ChanServ and at this point we
841 // know we are not an op, so fail silently and don't try to kick
842 if (! irc_toggle_op(irc_conn
, TRUE
)) /// TODO: prüfen, ob das auch erfolreich war
847 // give the server a chance to set the op status for us before we make us of it,
848 // and let the victim read his *bang* message
851 msg_len
= g_snprintf(msg
, sizeof msg
, "KICK #%s %s\r\n", config
->channel
, nickname
);
852 irc_send(irc_conn
, msg
, msg_len
);
854 irc_toggle_op(irc_conn
, FALSE
);
858 static gboolean
input_cb(GIOChannel
*source
, GIOCondition cond
, gpointer data
)
863 irc_conn_t
*irc
= data
;
866 if (cond
& (G_IO_ERR
| G_IO_HUP
))
869 if ((buf_len
= socket_fd_gets(irc
->socket
, buf
, sizeof(buf
))) != -1)
871 ret
= process_line(irc
, buf
, buf_len
);
875 irc_conn_t
*irc
= data
;
877 if (cond
& (G_IO_IN
| G_IO_PRI
))
885 rv
= g_io_channel_read_line(source
, &buf
, &buf_len
, NULL
, &err
);
889 buf
[buf_len
] = '\0'; // skip trailing \r\n
891 process_line(irc
, buf
, buf_len
);
896 debug("%s: error: %s", __func__
, err
->message
);
901 while (rv
== G_IO_STATUS_NORMAL
|| rv
== G_IO_STATUS_AGAIN
);
902 debug("%s: status %d\n", __func__
, rv
);
909 void irc_send_message(irc_conn_t
*irc_conn
, const gchar
*target
, const gchar
*format
, ...)
911 static gchar tmp_msg
[1024];
912 static gchar msg
[1024];
916 va_start(ap
, format
);
917 g_vsnprintf(tmp_msg
, sizeof tmp_msg
, format
, ap
);
921 msg_len
= g_snprintf(msg
, sizeof msg
, "PRIVMSG #%s :%s, %s\r\n", config
->channel
, target
, tmp_msg
);
923 msg_len
= g_snprintf(msg
, sizeof msg
, "PRIVMSG #%s :%s\r\n", config
->channel
, tmp_msg
);
925 irc_send(irc_conn
, msg
, msg_len
);
929 // simple wrapper for send() to enable logging for sent commands
930 gint
irc_send(irc_conn_t
*irc_conn
, const gchar
*msg
, guint msg_len
)
932 irc_log(irc_conn
, msg
, TRUE
);
933 return send(irc_conn
->socket
, msg
, msg_len
, MSG_NOSIGNAL
);
937 void irc_goodbye(irc_conn_t
*irc
)
942 if (NZV(irc
->quit_msg
))
943 len
= g_snprintf(msg
, sizeof msg
, "QUIT :%s\r\n", irc
->quit_msg
);
945 len
= g_strlcpy(msg
, "QUIT :Good bye. It was a pleasure to serve you\r\n", sizeof msg
);
946 irc_send(irc
, msg
, len
);
950 void irc_logfile_reopen(irc_conn_t
*irc_conn
)
954 if (irc_conn
->log_fd
!= NULL
)
955 fclose(irc_conn
->log_fd
);
957 if (NZV(config
->logfile
))
959 irc_conn
->log_fd
= g_fopen(config
->logfile
, "a");
960 if (! irc_conn
->log_fd
)
961 vomak_warning("Logfile could not be opened.");
966 gint
irc_finalize(irc_conn_t
*irc_conn
)
968 if (irc_conn
->socket
< 0)
971 if (irc_conn
->lock_tag
> 0)
972 g_source_remove(irc_conn
->lock_tag
);
974 if (irc_conn
->log_fd
!= NULL
)
976 irc_log(irc_conn
, "Stop logging\r\n", FALSE
);
977 fclose(irc_conn
->log_fd
);
980 if (irc_conn
->read_ioc
)
982 g_io_channel_shutdown(irc_conn
->read_ioc
, TRUE
, NULL
);
983 g_io_channel_unref(irc_conn
->read_ioc
);
984 irc_conn
->read_ioc
= NULL
;
986 socket_fd_close(irc_conn
->socket
);
987 irc_conn
->socket
= -1;
989 g_free(irc_conn
->quit_msg
);
995 void irc_connect(irc_conn_t
*irc_conn
)
998 struct sockaddr_in their_addr
;
1004 // Connect the socket to the server
1005 if ((he
= gethostbyname(config
->server
)) == NULL
)
1007 perror("gethostbyname");
1011 if ((irc_conn
->socket
= socket(PF_INET
, SOCK_STREAM
, 0)) == -1)
1017 their_addr
.sin_family
= PF_INET
;
1018 their_addr
.sin_port
= htons(6667);
1019 their_addr
.sin_addr
= *((struct in_addr
*)he
->h_addr_list
[0]);
1020 memset(&(their_addr
.sin_zero
), '\0', 8);
1022 if (connect(irc_conn
->socket
, (struct sockaddr
*)&their_addr
, sizeof(struct sockaddr
)) == -1)
1028 if (NZV(config
->logfile
))
1030 irc_conn
->log_fd
= g_fopen(config
->logfile
, "a");
1031 if (irc_conn
->log_fd
)
1032 irc_log(irc_conn
, "Start logging\r\n", FALSE
);
1034 vomak_warning("Logfile could not be opened.");
1037 msg_len
= g_snprintf(msg
, sizeof(msg
), "USER %s %s %s :%s\r\n",
1038 config
->username
, config
->servername
, config
->servername
, config
->realname
);
1039 if (irc_send(irc_conn
, msg
, msg_len
) == -1)
1041 perror("send USER");
1043 // and how we are called
1044 msg_len
= g_snprintf(msg
, sizeof(msg
), "NICK %s\r\n", config
->nickname
);
1045 if (irc_send(irc_conn
, msg
, msg_len
) == -1)
1047 perror("send NICK");
1049 // identify our nick
1050 if (NZV(config
->nickserv_password
))
1052 msg_len
= g_snprintf(msg
, sizeof(msg
), "PRIVMSG nickserv :identify %s\r\n", config
->nickserv_password
);
1053 // don't use irc_send() here, no need to log our password
1054 if (send(irc_conn
->socket
, msg
, msg_len
, MSG_NOSIGNAL
) == -1)
1056 perror("send NICKSERV");
1060 msg_len
= g_snprintf(msg
, sizeof msg
, "JOIN #%s\r\n", config
->channel
);
1061 if (irc_send(irc_conn
, msg
, msg_len
) == -1)
1066 // input callback, attached to the main loop
1067 irc_conn
->read_ioc
= g_io_channel_unix_new(irc_conn
->socket
);
1068 //~ g_io_channel_set_flags(irc_conn.read_ioc, G_IO_FLAG_NONBLOCK, NULL);
1069 g_io_channel_set_encoding(irc_conn
->read_ioc
, NULL
, NULL
);
1070 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
);