aboutsummaryrefslogtreecommitdiff
path: root/irc/irc.c
diff options
context:
space:
mode:
Diffstat (limited to 'irc/irc.c')
-rw-r--r--irc/irc.c908
1 files changed, 908 insertions, 0 deletions
diff --git a/irc/irc.c b/irc/irc.c
new file mode 100644
index 0000000..7246f21
--- /dev/null
+++ b/irc/irc.c
@@ -0,0 +1,908 @@
+/************************************************************************
+ * IRC - Internet Relay Chat, irc/irc.c
+ * Copyright (C) 1990 Jarkko Oikarinen and
+ * University of Oulu, Computing Center
+ *
+ * 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
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef lint
+static char rcsid[] = "@(#)$Id: irc.c,v 1.6 1998/12/13 00:02:35 kalt Exp $";
+#endif
+
+#include "os.h"
+#include "c_defines.h"
+#define IRC_C
+#include "c_externs.h"
+#undef IRC_C
+
+#define DEPTH 10
+#define KILLMAX 2 /* Number of kills to accept to really die */
+ /* this is to prevent looping with /unkill */
+
+#ifdef AUTOMATON
+#ifdef DOCURSES
+#undef DOCURSES
+#endif
+#ifdef DOTERMCAP
+#undef DOTERMCAP
+#endif
+#endif /* AUTOMATON */
+
+struct Command commands[] = {
+ { (void (*)()) 0, "SIGNOFF", SERVER_CMD, "\0\0", MSG_QUIT },
+ { do_bye, "QUIT", LOCAL_FUNC, "\0\0", MSG_QUIT },
+ { do_bye, "EXIT", LOCAL_FUNC, "\0\0", MSG_QUIT },
+ { do_bye, "BYE", LOCAL_FUNC, "\0\0", MSG_QUIT },
+ { do_kill, "KILL", LOCAL_FUNC, "\0\0", MSG_KILL },
+ { (void (*)()) 0, "SUMMON", SERVER_CMD, "\0\0", MSG_SUMMON },
+ { (void (*)()) 0, "STATS", SERVER_CMD, "\0\0", MSG_STATS },
+ { (void (*)()) 0, "USERS", SERVER_CMD, "\0\0", MSG_USERS },
+ { (void (*)()) 0, "TIME", SERVER_CMD, "\0\0", MSG_TIME },
+ { (void (*)()) 0, "DATE", SERVER_CMD, "\0\0", MSG_TIME },
+ { (void (*)()) 0, "NAMES", SERVER_CMD, "\0\0", MSG_NAMES },
+ { (void (*)()) 0, "NICK", SERVER_CMD, "\0\0", MSG_NICK },
+ { (void (*)()) 0, "WHO", SERVER_CMD, "\0\0", MSG_WHO },
+ { (void (*)()) 0, "WHOIS", SERVER_CMD, "\0\0", MSG_WHOIS },
+ { (void (*)()) 0, "WHOWAS", SERVER_CMD, "\0\0", MSG_WHOWAS },
+ { do_kill, "LEAVE", LOCAL_FUNC, "\0\0", MSG_PART },
+ { do_kill, "PART", LOCAL_FUNC, "\0\0", MSG_PART },
+ { (void (*)()) 0, "WOPS", SERVER_CMD, "\0\0", MSG_WALLOPS },
+ { do_channel, "JOIN", LOCAL_FUNC, "\0\0", MSG_JOIN },
+ { do_channel, "CHANNEL", LOCAL_FUNC, "\0\0", MSG_JOIN },
+#ifdef VMSP
+ { do_exec, "EXEC", LOCAL_FUNC, "\0\0", "EXEC" },
+ { do_oper, "OPER", LOCAL_FUNC, "\0\0", "OPER" },
+#endif
+#ifdef GETPASS
+ { do_oper, "OPER", LOCAL_FUNC, "\0\0", "OPER" },
+#else
+ { (void (*)()) 0, "OPER", SERVER_CMD, "\0\0", MSG_OPER },
+#endif
+ { do_away, "AWAY", LOCAL_FUNC, "\0\0", MSG_AWAY },
+ { do_mypriv, "MSG", LOCAL_FUNC, "\0\0", MSG_PRIVATE },
+ { do_kill, "TOPIC", LOCAL_FUNC, "\0\0", MSG_TOPIC },
+ { do_cmdch, "CMDCH", LOCAL_FUNC, "\0\0", "CMDCH" },
+ { (void (*)()) 0, "INVITE", SERVER_CMD, "\0\0", MSG_INVITE },
+ { (void (*)()) 0, "INFO", SERVER_CMD, "\0\0", MSG_INFO },
+ { (void (*)()) 0, "LIST", SERVER_CMD, "\0\0", MSG_LIST },
+ { (void (*)()) 0, "KILL", SERVER_CMD, "\0\0", MSG_KILL },
+ { do_quote, "QUOTE", LOCAL_FUNC, "\0\0", "QUOTE" },
+ { (void (*)()) 0, "LINKS", SERVER_CMD, "\0\0", MSG_LINKS },
+ { (void (*)()) 0, "ADMIN", SERVER_CMD, "\0\0", MSG_ADMIN },
+ { do_ignore, "IGNORE", LOCAL_FUNC, "\0\0", "IGNORE" },
+ { (void (*)()) 0, "TRACE", SERVER_CMD, "\0\0", MSG_TRACE },
+ { do_help, "HELP", LOCAL_FUNC, "\0\0", "HELP" },
+ { do_log, "LOG", LOCAL_FUNC, "\0\0", "LOG" },
+ { (void (*)()) 0, "VERSION", SERVER_CMD, "\0\0", MSG_VERSION },
+ { do_clear, "CLEAR", LOCAL_FUNC, "\0\0", "CLEAR" },
+ { (void (*)()) 0, "REHASH", SERVER_CMD, "\0\0", MSG_REHASH },
+ { do_query, "QUERY", LOCAL_FUNC, "\0\0", "QUERY" },
+ { (void (*)()) 0, "LUSERS", SERVER_CMD, "\0\0", MSG_LUSERS },
+ { (void (*)()) 0, "MOTD", SERVER_CMD, "\0\0", MSG_MOTD },
+ { do_unkill, "UNKILL", LOCAL_FUNC, "\0\0", "UNKILL" },
+ { do_server, "SERVER", LOCAL_FUNC, "\0\0", "SERVER" },
+ { (void (*)()) 0, "MODE", SERVER_CMD, "\0\0", MSG_MODE },
+#ifdef MSG_MAIL
+ { (void (*)()) 0, "MAIL", SERVER_CMD, "\0\0", MSG_MAIL },
+#endif
+ { do_kick, "KICK", LOCAL_FUNC, "\0\0", MSG_KICK },
+ { (void (*)()) 0, "USERHOST",SERVER_CMD, "\0\0", MSG_USERHOST },
+ { (void (*)()) 0, "ISON", SERVER_CMD, "\0\0", MSG_ISON },
+ { (void (*)()) 0, "CONNECT", SERVER_CMD, "\0\0", MSG_CONNECT },
+ { do_kill, "SQUIT", LOCAL_FUNC, "\0\0", MSG_SQUIT },
+ { (void (*)()) 0, "SERVLIST",SERVER_CMD, "\0\0", MSG_SERVLIST },
+ { do_kill, "SQUERY", LOCAL_FUNC, "\0\0", MSG_SQUERY },
+ { do_kill, "NOTICE", LOCAL_FUNC, "\0\0", MSG_NOTICE },
+ { (void (*)()) 0, (char *) 0, 0, "\0\0", (char *) 0 }
+};
+
+aChannel *channel = NULL;
+aClient me, *client = &me;
+anUser meUser; /* User block for 'me' --msa */
+FILE *logfile = NULL;
+char buf[BUFSIZE];
+char *querychannel;
+int portnum, termtype = CURSES_TERM;
+int debuglevel = DEBUG_ERROR;
+int unkill_flag = 0, cchannel = 0;
+int QuitFlag = 0;
+
+static int KillCount = 0;
+static int apu = 0; /* Line number we're currently on screen */
+static int sock; /* Server socket fd */
+static char currserver[HOSTLEN + 1];
+
+#if defined(HPUX) || defined(SVR3) || defined(SVR4)
+char logbuf[BUFSIZ];
+#endif
+
+#ifdef MAIL50
+int ucontext = 0, perslength;
+char persname[81];
+
+struct itmlst
+ null_list[] = {{0,0,0,0}},
+ gplist[] = {{80, MAIL$_USER_PERSONAL_NAME,
+ &persname, &perslength}};
+#endif
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ static char usage[] =
+ "Usage: %s [-c channel] [-k passwd] [-p port] [-i] [-w] [-s] [nickname [server]]\n";
+ char channel[BUFSIZE+1];
+ int length, mode = 0;
+ struct passwd *userdata;
+ char *cp, *argv0=argv[0], *nickptr, *servptr, *getenv(), ch;
+
+ if ((cp = rindex(argv0, '/')) != NULL)
+ argv0 = ++cp;
+ portnum = PORTNUM;
+ *buf = *currserver = '\0';
+ channel[0] = '\0';
+ me.user = &meUser;
+ me.from = &me;
+ me.info = (char *) malloc(REALLEN);
+ setuid(getuid());
+ version = make_version();
+
+ while (argc > 1 && argv[1][0] == '-') {
+ switch(ch = argv[1][1])
+ {
+ case 'h':
+ printf(usage, argv0);
+ exit(1);
+ break;
+ case 'p':
+ length = 0;
+ if (argv[1][2] != '\0')
+ length = atoi(&argv[1][2]);
+ else if (argc > 2) {
+ length = atoi(argv[2]);
+ argv++;
+ argc--;
+ }
+ if (length <= 0) {
+ printf(usage, argv0);
+ exit(1);
+ }
+ cchannel = length;
+ break;
+ case 'c':
+ if (argv[1][2] != '\0')
+ strncpy(channel, &argv[1][2], BUFSIZE);
+ else if (argc > 2) {
+ strncpy(channel, argv[2], BUFSIZE);
+ argv++;
+ argc--;
+ }
+ if (!channel[0]) {
+ printf(usage, argv0);
+ exit(1);
+ }
+ break;
+ case 'i':
+ mode |= FLAGS_INVISIBLE;
+ break;
+ case 'w':
+ mode |= FLAGS_WALLOP;
+ break;
+ case 'k':
+ if (argv[1][2] != '\0')
+ strncpy(me.passwd, &argv[1][2], PASSWDLEN);
+ else if (argc > 2) {
+ strncpy(me.passwd, argv[2], PASSWDLEN);
+ argv++;
+ argc--;
+ }
+ if (!me.passwd[0]) {
+ printf(usage, argv0);
+ exit(1);
+ }
+ break;
+#ifdef DOTERMCAP
+ case 's':
+ termtype = TERMCAP_TERM;
+ break;
+#endif
+ case 'v':
+ (void)printf("irc %s\n", version);
+ exit(0);
+ }
+ argv++;
+ argc--;
+ }
+
+ me.name[0] = me.buffer[0] = '\0';
+ me.next = NULL;
+ me.status = STAT_ME;
+ if ((servptr = getenv("IRCSERVER")))
+ strncpyzt(currserver, servptr, HOSTLEN);
+ if (argc > 2)
+ strncpyzt(currserver, argv[2], HOSTLEN);
+
+ do {
+ QuitFlag = 0;
+ if (unkill_flag < 0)
+ unkill_flag += 2;
+#ifdef UPHOST
+ if (!*currserver)
+ strncpyzt(currserver, UPHOST, HOSTLEN);
+#else
+ if (!*currserver)
+ strncpyzt(currserver, me.sockhost, HOSTLEN);
+#endif
+ if (cchannel > 0)
+ portnum = cchannel;
+
+ sock = client_init(currserver, portnum, &me);
+ if (sock < 0) {
+ printf("sock < 0\n");
+ exit(1);
+ }
+ userdata = getpwuid(getuid());
+ if (strlen(userdata->pw_name) >= (size_t) USERLEN) {
+ userdata->pw_name[USERLEN-1] = '\0';
+ }
+ if (strlen(userdata->pw_gecos) >= (size_t) REALLEN) {
+ userdata->pw_gecos[REALLEN-1] = '\0';
+ }
+ /* FIX: jtrim@orion.cair.du.edu -- 3/14/88
+ & jto@tolsun.oulu.fi */
+ if (!*me.name) {
+ if (argc >= 2) {
+ strncpy(me.name, argv[1], NICKLEN);
+ } else if ((nickptr = getenv("IRCNICK"))) {
+ strncpy(me.name, nickptr, NICKLEN);
+ } else
+#ifdef AUTOMATON
+ strncpy(me.name, a_myname(), NICKLEN);
+#else
+ strncpy(me.name, userdata->pw_name ,NICKLEN);
+#endif
+ }
+ me.name[NICKLEN] = '\0';
+ /* END FIX */
+
+ if (argv0[0] == ':') {
+ strcpy(me.sockhost, "OuluBox");
+ strncpy(me.info, &argv0[1], REALLEN);
+ strncpy(meUser.username, argv[1], USERLEN);
+ } else {
+ sprintf(me.sockhost, "%d", mode);
+ if ((cp = getenv("IRCNAME")))
+ strncpy(me.info, cp, REALLEN);
+ else if ((cp = getenv("NAME")))
+ strncpy(me.info, cp, REALLEN);
+ else {
+#ifdef AUTOMATON
+ strncpy(me.info, a_myreal(), REALLEN);
+#else
+ strncpy(me.info,real_name(userdata),REALLEN);
+#endif
+ if (me.info[0] == '\0')
+ strcpy(me.info, "*real name unknown*");
+ }
+#ifdef AUTOMATON
+ strncpy(meUser.username, a_myuser(), USERLEN);
+#else
+ strncpy(meUser.username,userdata->pw_name,USERLEN);
+#endif
+ }
+ meUser.server = mystrdup(me.sockhost);
+ meUser.username[USERLEN] = '\0';
+ me.info[REALLEN] = '\0';
+ me.fd = sock;
+#ifdef AUTOMATON
+ a_init();
+#endif
+#ifdef DOCURSES
+ if (termtype == CURSES_TERM) {
+ initscr();
+ signal(SIGINT, quit_intr);
+ signal(SIGTSTP, suspend_irc);
+ noecho();
+ crmode();
+ clear();
+ refresh();
+ }
+#endif
+#ifdef DOTERMCAP
+ if (termtype == TERMCAP_TERM) {
+ printf("Io on !\n");
+ io_on(1);
+ clearscreen();
+ }
+#endif
+ if (me.passwd[0])
+ sendto_one(&me, "PASS %s", me.passwd);
+ sendto_one(&me, "NICK %s", me.name);
+ sendto_one(&me, "USER %s %s %s :%s", meUser.username,
+ me.sockhost, meUser.server, me.info);
+ querychannel = (char *)malloc(strlen(me.name) + 1);
+ strcpy(querychannel, me.name); /* Kludge? */
+ if (channel[0])
+ do_channel(channel, "JOIN");
+ myloop(sock);
+ if (logfile)
+ do_log(NULL, NULL);
+ printf("Press any key.");
+ refresh();
+ getchar();
+ printf("\n");
+#ifdef DOCURSES
+ if (termtype == CURSES_TERM) {
+ echo();
+ nocrmode();
+ endwin();
+ }
+#endif
+#ifdef DOTERMCAP
+ if (termtype == TERMCAP_TERM)
+ io_off();
+#endif
+ apu = 0;
+ } while (unkill_flag && KillCount++ < KILLMAX);
+ exit(0);
+}
+
+void intr()
+{
+ if (logfile)
+ do_log(NULL, NULL);
+
+#ifdef DOCURSES
+ if (termtype == CURSES_TERM) {
+ echo();
+ nocrmode();
+ endwin();
+ }
+#endif
+#ifdef DOTERMCAP
+ if (termtype == TERMCAP_TERM)
+ io_off();
+#endif
+ exit(0);
+}
+
+void myloop(sock)
+int sock;
+{
+ write_statusline();
+#ifdef DOTERMCAP
+ if (termtype == TERMCAP_TERM)
+ put_statusline();
+#endif
+ client_loop(sock);
+}
+
+#define QUERYLEN 50
+
+static char cmdch = '/';
+static char queryuser[QUERYLEN+2] = "";
+
+void do_cmdch(ptr, temp)
+char *ptr, *temp;
+{
+ if (BadPtr(ptr)) {
+ putline("Error: Command character not changed");
+ return;
+ }
+ cmdch = *ptr;
+}
+
+void do_quote(ptr, temp)
+char *ptr, *temp;
+{
+ if (BadPtr(ptr)) {
+ putline("*** Error: Empty command");
+ return;
+ }
+ sendto_one(&me,"%s", ptr);
+}
+
+void do_query(ptr, temp)
+char *ptr, *temp;
+{
+ if (BadPtr(ptr)) {
+ sprintf(buf, "*** Ending a private chat with %s", queryuser);
+ putline(buf);
+ queryuser[0] = '\0';
+ } else {
+ strncpyzt(queryuser, ptr, QUERYLEN);
+ sprintf(buf, "*** Beginning a private chat with %s",
+ queryuser);
+ putline(buf);
+ }
+}
+
+void do_mypriv(buf1, buf2)
+char *buf1, *buf2;
+{
+ char *tmp = index(buf1, ' ');
+
+ if (tmp == NULL) {
+ putline("*** Error: Empty message not sent");
+ return;
+ }
+ if (buf1[0] == ',' && buf1[1] == ' ') {
+ sendto_one(&me, "PRIVMSG %s :%s", last_to_me(NULL), &buf1[2]);
+ last_from_me(last_to_me(NULL));
+ *(tmp++) = '\0';
+ sprintf(buf,"-> !!*%s* %s", last_to_me(NULL), tmp);
+ putline(buf);
+ } else if (buf1[0] == '.' && buf1[1] == ' ') {
+ sendto_one(&me, "PRIVMSG %s :%s", last_from_me(NULL), &buf1[2]);
+ *(tmp++) = '\0';
+ sprintf(buf,"-> ##*%s* %s", last_from_me(NULL), tmp);
+ putline(buf);
+ } else {
+ *(tmp++) = '\0';
+ sendto_one(&me, "PRIVMSG %s :%s", buf1, tmp);
+ last_from_me(buf1);
+ if (*buf1 == '#' || *buf1 == '&' || *buf1 == '+' || atoi(buf1))
+ sprintf(buf, "%s> %s", buf1, tmp);
+ else
+ sprintf(buf,"->%s> %s", buf1, tmp);
+ putline(buf);
+ }
+}
+
+void do_myqpriv(buf1, buf2)
+char *buf1, *buf2;
+{
+ if (BadPtr(buf1)) {
+ putline("*** Error: Empty message not sent");
+ return;
+ }
+ sendto_one(&me, "PRIVMSG %s :%s", queryuser, buf1);
+
+ sprintf(buf,"-> *%s* %s", queryuser, buf1);
+ putline(buf);
+}
+
+void do_mytext(buf1, temp)
+char *buf1, *temp;
+{
+ sendto_one(&me, "PRIVMSG %s :%s", querychannel, buf1);
+ sprintf(buf,"%s> %s", querychannel, buf1);
+ putline(buf);
+}
+
+void do_unkill(buf, temp)
+char *buf, *temp;
+{
+ if (unkill_flag)
+ unkill_flag = 0;
+ else
+ unkill_flag = 1;
+
+ sprintf(buf, "*** Unkill feature turned %s",
+ (unkill_flag) ? "on" : "off");
+ putline(buf);
+}
+
+void do_bye(buf, tmp)
+char *buf, *tmp;
+{
+ unkill_flag = 0;
+ sendto_one(&me, "%s :%s", tmp, buf);
+}
+
+/* KILL, PART, SQUIT, TOPIC "CMD PARA1 [:PARA2]" */
+void do_kill(buf1, tmp)
+char *buf1, *tmp;
+{
+ char *b2;
+
+ b2 = index(buf1, SPACE); /* find end of servername */
+ if (b2) /* comment */
+ {
+ *b2 = 0;
+ sendto_one(&me, "%s %s :%s", tmp, buf1, b2 + 1);
+ }
+ else
+ sendto_one(&me, "%s %s", tmp, buf1);
+ if (*tmp == 'P') { /* PART */
+ free(querychannel);
+ querychannel = (char *)malloc(strlen(me.name) + 1);
+ strcpy(querychannel, me.name); /* Kludge? */
+ }
+}
+
+/* "CMD PARA1 PARA2 [:PARA3]" */
+void do_kick(buf1, tmp)
+char *buf1, *tmp;
+{
+ char *b2, *b3 = NULL;
+
+ b2 = index(buf1, SPACE); /* find end of channel name */
+ if (b2)
+ b3 = index(b2 + 1, SPACE); /* find end of victim name */
+ if (b3)
+ {
+ *b3 = 0;
+ sendto_one(&me, "%s %s :%s", tmp, buf1, b3 + 1);
+ }
+ else
+ sendto_one(&me, "%s %s :No comment", tmp, buf1);
+}
+
+/* "CMD :PARA1" */
+void do_away(buf1, tmp)
+char *buf1, *tmp;
+{
+ sendto_one(&me, "%s :%s", tmp, buf1);
+}
+
+void do_server(buf, tmp)
+char *buf, *tmp;
+{
+ strncpyzt(currserver, buf, HOSTLEN);
+ unkill_flag -= 2;
+ sendto_one(&me,"QUIT");
+ close(sock);
+ QuitFlag = 1;
+}
+
+void sendit(line)
+char *line;
+{
+ char *ptr = NULL;
+ struct Command *cmd = commands;
+
+ KillCount = 0;
+ if (line[0] != cmdch) {
+ if (*queryuser)
+ do_myqpriv(line, NULL);
+ else
+ do_mytext(line, NULL);
+ return /* 0 */ ;
+ }
+ if (line[1] == ' ')
+ do_mytext(&line[2], NULL);
+ else if (line[1]) {
+ for ( ; cmd->name; cmd++)
+ if ((ptr = mycncmp(&line[1], cmd->name)))
+ break;
+ if (!cmd->name)
+ putline("*** Error: Unknown command");
+ else {
+ switch (cmd->type)
+ {
+ case SERVER_CMD:
+ sendto_one(&me, "%s %s", cmd->extra, ptr);
+ break;
+ case LOCAL_FUNC:
+ (*cmd->func)(ptr, cmd->extra);
+ return;
+ break;
+ default:
+ putline("*** Error: Data error in irc.h");
+ break;
+ }
+ }
+ }
+}
+
+char *mycncmp(str1, str2)
+char *str1, *str2;
+{
+ int flag = 0;
+ char *s1;
+
+ for (s1 = str1; *s1 != ' ' && *s1 && *str2; s1++, str2++) {
+ /* if (!isascii(*s1)) */
+ if (*s1 & 0x80)
+ return 0;
+ *s1 = toupper(*s1);
+ if (*s1 != *str2)
+ flag = 1;
+ }
+ if (*s1 && *s1 != ' ' && *str2 == '\0')
+ return 0;
+ if (flag)
+ return 0;
+ if (*s1)
+ return s1 + 1;
+ else
+ return s1;
+}
+
+void do_clear(buf, temp)
+char *buf, *temp;
+{
+#ifdef DOCURSES
+ char header[HEADERLEN];
+
+ if (termtype == CURSES_TERM) {
+ apu = 0;
+ sprintf(header, IRCHEADER ,version, me.name, currserver);
+ clear();
+ standout();
+ mvaddstr(LINES - 2, 0, header);
+ standend();
+ refresh();
+ }
+#endif
+#ifdef DOTERMCAP
+ if (termtype == TERMCAP_TERM)
+ clearscreen();
+#endif
+}
+
+void putline(line)
+char *line;
+
+{
+ char *ptr, *ptr2;
+
+#ifdef DOCURSES
+ char ch='\0';
+ /* int pagelen = LINES - 3; not used -Armin */
+ int rmargin = COLS - 1;
+#endif
+
+ /*
+ ** This is a *safe* client--filter out all possibly dangerous
+ ** codes from the messages (this sets them as "_").
+ */
+ if (line)
+ for (ptr = line; *ptr; ptr++)
+ if ((*ptr < 32 && *ptr != 7 && *ptr != 9) ||
+ (*ptr > 126))
+ *ptr = '_';
+
+ ptr = line;
+
+#ifdef DOCURSES
+ if (termtype == CURSES_TERM) {
+ while (ptr) {
+
+/* first, see if we have to chop the string into pieces */
+
+ if (strlen(ptr) > (size_t) rmargin) {
+ ch = ptr[rmargin];
+ ptr[rmargin] = '\0';
+ ptr2 = &ptr[rmargin - 1];
+ }
+ else
+ ptr2 = NULL;
+
+/* move cursor to correct position and place line */
+
+ move(apu,0);
+ addstr(ptr);
+ if (logfile)
+ fprintf(logfile, "%s\n", ptr);
+
+/* now see if we are at the end of the page, and take action */
+
+#ifndef SCROLLINGCLIENT
+ /* clear one line. */
+ addstr("\n\n");
+ if (++apu > LINES - 4) {
+ apu = 0;
+ move(0,0);
+ clrtoeol();
+ }
+
+#else /* doesn't work, dumps core :-( */
+
+ if(++apu > LINES - 4) {
+ char header[HEADERLEN];
+ /* erase status line */
+ move(LINES - 2, 0 );
+ clrtobot();
+ refresh();
+ /* scroll screen */
+ scrollok(stdscr,TRUE);
+ move(LINES - 1, 0 );
+ addstr("\n\n\n\n");
+ refresh();
+ apu -= 4;
+ /* redraw status line */
+ sprintf(header, IRCHEADER, version,
+ me.name, currserver);
+ standout();
+ mvaddstr(LINES - 2, 0, header);
+ standend();
+ tulosta_viimeinen_rivi();
+ } else
+ addstr( "\n\n" );
+#endif
+
+/* finally, if this is a multiple-line line, munge things up so that
+ we print the next line. overwrites the end of the previous line. */
+
+ ptr = ptr2;
+ if (ptr2) {
+ *ptr2++ = '+';
+ *ptr2 = ch;
+ }
+ }
+ refresh();
+ }
+#endif
+#ifdef DOTERMCAP
+ if (termtype == TERMCAP_TERM)
+ tcap_putline(line);
+#endif
+#ifdef AUTOMATON
+ puts(line);
+#endif
+}
+
+int unixuser()
+{
+ return(!StrEq(me.sockhost,"OuluBox"));
+}
+
+void do_log(ptr, temp)
+char *ptr, *temp;
+{
+ time_t tloc;
+ char buf[150];
+ char *ptr2;
+
+ if (!unixuser())
+ return;
+ if (!logfile) { /* logging currently off */
+ if (BadPtr(ptr))
+ putline("*** You must specify a filename to log to.");
+ else {
+ if (!(logfile = fopen(ptr, "a"))) {
+ sprintf(buf,
+ "*** Error: Can't open log file %s.\n",
+ ptr);
+ putline(buf);
+ } else {
+#if defined(HPUX) || defined(SVR3) || defined(SVR4)
+ setvbuf(logfile,logbuf,_IOLBF,sizeof(logbuf));
+#else
+# if !defined(_SEQUENT_) && !defined(SVR4)
+ setlinebuf(logfile);
+# endif
+#endif
+ time(&tloc);
+ sprintf(buf,
+ "*** IRC session log started at %s",
+ ctime(&tloc));
+ ptr2 = rindex(buf, '\n');
+ *ptr2 = '.';
+ putline(buf);
+ }
+ }
+ } else { /* logging currently on */
+ if (BadPtr(ptr)) {
+
+ time(&tloc);
+ sprintf(buf, "*** IRC session log ended at %s",
+ ctime(&tloc));
+ ptr2 = rindex(buf, '\n');
+ *ptr2 = '.';
+ putline(buf);
+ fclose(logfile);
+ logfile = NULL;
+ } else
+ putline("*** Your session is already being logged.");
+ }
+}
+
+/* remember the commas */
+#define LASTKEEPLEN (MAXRECIPIENTS * (NICKLEN+1))
+
+char *last_to_me(sender)
+char *sender;
+{
+ static char name[LASTKEEPLEN+1] = ",";
+
+ if (sender)
+ strncpyzt(name, sender, sizeof(name));
+
+ return (name);
+}
+
+char *last_from_me(recipient)
+char *recipient;
+{
+ static char name[LASTKEEPLEN+1] = ".";
+
+ if (recipient)
+ strncpyzt(name, recipient, sizeof(name));
+
+ return (name);
+}
+
+/*
+ * Left out until it works with VMS as well..
+ */
+
+#ifdef GETPASS
+do_oper(ptr, xtra)
+char *ptr, *xtra;
+{
+ extern char *getmypass();
+
+ if (BadPtr(ptr))
+ ptr = getmypass("Enter nick & password: ");
+
+ sendto_one(&me, "%s %s", xtra, ptr);
+}
+#endif
+
+/* Fake routine (it's only in server...) */
+
+void do_channel(ptr, xtra)
+char *ptr, *xtra;
+{
+ char *p1;
+
+ if (BadPtr(ptr)) {
+ putline("*** Which channel do you want to join?");
+ return;
+ }
+
+ free((char *)querychannel);
+
+ if ((querychannel = (char *)malloc(strlen(ptr) + 1)))
+ {
+ /* Copy only channel name from *ptr -Vesa */
+ strcpy(buf, ptr);
+ if ((p1 = index(buf, ' ')))
+ *p1 = '\0';
+ if ((p1 = rindex(buf, ','))) /* The last channel */
+ strcpy(querychannel, p1 + 1);
+ else /* The only channel */
+ strcpy(querychannel, buf);
+ }
+ else
+ printf("Blah! Out of memory?\n");
+
+ sendto_one(&me, "%s %s", xtra, ptr);
+}
+
+void write_statusline()
+{
+#ifdef DOCURSES
+ char header[HEADERLEN];
+
+ if (termtype == CURSES_TERM) {
+ sprintf(header, IRCHEADER, version, me.name, currserver);
+ standout();
+ mvaddstr(LINES - 2, 0, header);
+ standend();
+ }
+#endif
+}
+
+RETSIGTYPE quit_intr(s)
+int s;
+{
+ signal(SIGINT, SIG_IGN);
+#ifdef DOCURSES
+ if (termtype == CURSES_TERM) {
+ clear();
+ refresh();
+ echo();
+ nocrmode();
+ endwin();
+ }
+#endif
+ exit(0);
+}