Nebula/src/interpreter.c
Mid Favila 0e9ed3e250 Start work on eliminating redundant variable usage. Prevent
an I-bar from showing up on the output frame. Move the copyright
notice out to a header file.
2022-08-21 21:35:28 -04:00

818 lines
20 KiB
C

/* --------------------------------------------------------------------- *
* interpreter.c *
* --------------------------------------------------------------------- *
* This file is part of the nebula irc client *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <string.h>
#include "main.h"
#include "interpreter.h"
#include "network.h"
#include "userlist.h"
extern systemStatusRecord sysState;
extern Widget userList; /* user list widget */
void interpretCommand(char *cmd)
{
char token1[MAX_INPUT_LEN+1];
char token2[MAX_INPUT_LEN+1];
char token3[MAX_INPUT_LEN+1];
if (strlen(cmd) <= 0)
return;
if (cmd[0] == '/')
{
int cmdCursor;
int i, k;
int cmdLen;
int token2Start;
cmdLen = strlen(cmd);
#ifdef DEBUG
assert(cmdLen <= MAX_INPUT_LEN);
#endif
cmdCursor = 1;
i = 0;
while (cmdCursor < cmdLen && cmd[cmdCursor] != ' ')
token1[i++] = cmd[cmdCursor++];
token1[i] = '\0';
#ifdef DEBUG
printf("Token 1: |%s|\n", token1);
#endif
k = 0;
cmdCursor++;
token2Start = cmdCursor;
while (cmdCursor < cmdLen && cmd[cmdCursor] != ' ')
token2[k++] = cmd[cmdCursor++];
token2[k] = '\0';
#ifdef DEBUG
printf("Token 2: |%s|\n", token2);
#endif
if (!strcmp(token1, "deop"))
{
if (strlen(token2) > 0)
doMode(sysState.currentChannel, "-o", token2, NULL, NULL);
} else if (!strcmp(token1, "msg"))
{
if (strlen(token2) > 0)
{
int l;
l = 0;
cmdCursor++;
while (cmdCursor < cmdLen)
token3[l++] = cmd[cmdCursor++];
token3[l] = '\0';
if (strlen(token3) > 0)
doPrivateMsg(token2, token3);
else
appendText("You fool, no message specified\n");
} else
appendText("You fool, no victim!\n");
} else if (!strcmp(token1, "nick"))
{
if (strlen(token2) > 0)
{
renameUserInList(sysState.myNick, token2, userList);
doNick(token2);
}
} else if (!strcmp(token1, "join"))
{
if (strlen(token2) > 0)
{
doJoin(token2);
}
} else if (!strcmp(token1, "ns"))
{
if (strlen(token2) > 0)
doPrivateMsg("nickserv", cmd+token2Start);
else
appendText("You fool, no message specified\n");
} else if (!strcmp(token1, "mode"))
{
char token4[MAX_INPUT_LEN+1];
char token5[MAX_INPUT_LEN+1];
char token6[MAX_INPUT_LEN+1];
token4[0] = '\0';
token5[0] = '\0';
token6[0] = '\0';
if (strlen(token2) > 0)
{
int l;
l = 0;
cmdCursor++;
while (cmdCursor < cmdLen && cmd[cmdCursor] != ' ')
token3[l++] = cmd[cmdCursor++];
token3[l] = '\0';
#ifdef DEBUG
printf("token3: %s\n", token3);
#endif
if (cmdCursor < cmdLen)
{
cmdCursor++;
l = 0;
while (cmdCursor < cmdLen && cmd[cmdCursor] != ' ')
token4[l++] = cmd[cmdCursor++];
token4[l] = '\0';
#ifdef DEBUG
printf("token4: %s\n", token3);
#endif
if (cmdCursor < cmdLen)
{
cmdCursor++;
l = 0;
while (cmdCursor < cmdLen && cmd[cmdCursor] != ' ')
token5[l++] = cmd[cmdCursor++];
token5[l] = '\0';
#ifdef DEBUG
printf("token5: %s\n", token5);
#endif
if (cmdCursor < cmdLen)
{
cmdCursor++;
l = 0;
while (cmdCursor < cmdLen)
token6[l++] = cmd[cmdCursor++];
token6[l] = '\0';
#ifdef DEBUG
printf("token6: %s\n", token6);
#endif
}
}
}
doMode(token2, token3, token4, token5, token6);
} else
appendText("You fool, no channel or user!\n");
} else if (!strcmp(token1, "op"))
{
if (strlen(token2) > 0)
doMode(sysState.currentChannel, "+o", token2, NULL, NULL);
} else if (!strcmp(token1, "part"))
{
if (strlen(token2) > 0)
{
removeAllUsersFromList(userList);
doPart(token2);
} else
appendText("PART: must specify a channel\n");
} else if (!strcmp(token1, "query"))
{
if (sysState.isConnected)
{
if (strlen(token2) > 0)
{
sysState.isInQuery = YES;
strcpy(sysState.currentQuery, token2);
} else
sysState.isInQuery = NO;
}
} else if (!strcmp(token1, "user"))
{
doUser(sysState.myUnixname, sysState.myHostName, sysState.serverName, sysState.myName);
} else if (!strcmp(token1, "whois"))
{
if (strlen(token2) > 0)
doWhois(token2);
} else if (!strcmp(token1, "me"))
{
doCTCPAction(sysState.currentChannel, cmd + token2Start);
} else if (!strcmp(token1, "ctcp"))
{ /* CTCP commands */
int l;
l = 0;
cmdCursor++;
while (cmdCursor < cmdLen)
token3[l++] = cmd[cmdCursor++];
token3[l] = '\0';
if (strlen(token3) > 0)
{
printf("Ctcp command: %s, recipient: %s\n", token3, token2);
if (!strcmp(token3, "version"))
{
doCTCPVersion(token2);
}
}
else
printf("You fool, no command specified\n");
} else if (!strcmp(token1, "quit"))
{
quitApplication();
} else if (!strcmp(token1, "server"))
{
if (strlen(token2) > 0)
connectToServer(token2, 6666);
} else
{ /* unrecongized command */
appendText("Unknown command: ");
appendText(token1);
appendText("\n");
}
} else if (sysState.isConnected)
{
if (sysState.isInQuery)
doPrivateMsg(sysState.currentQuery, cmd);
else if (sysState.isInChannel)
doPrivateMsg(sysState.currentChannel, cmd);
else
appendText("No command given and not explicit state.\n");
} else
appendText("Not connected\n");
}
void interpretMessage(char *inBuff)
{
if (inBuff[0] == ':')
{
char token1[MAX_COMMAND_LEN+1];
char token2[MAX_COMMAND_LEN+1];
char token3[MAX_COMMAND_LEN+1];
char token4[MAX_COMMAND_LEN+1];
char token5[MAX_COMMAND_LEN+1];
int k;
int buffCursor;
int buffLen;
buffLen = strlen(inBuff);
#ifdef DEBUG
assert(buffLen <= MAX_COMMAND_LEN);
#endif
k = 0;
buffCursor = 1;
while (buffCursor < buffLen && inBuff[buffCursor] != ' ')
token1[k++] = inBuff[buffCursor++];
token1[k] = '\0';
if (strlen(token1) > 0)
{
int l;
#ifdef DEBUG
printf ("sender is: |%s|\n", token1);
#endif
l = 0;
buffCursor++;
while (buffCursor < buffLen && inBuff[buffCursor] != ' ')
token2[l++] = inBuff[buffCursor++];
token2[l] = '\0';
if (strlen(token2) > 0)
{
int m;
int token3start;
#ifdef DEBUG
printf ("command is: |%s|\n", token2);
#endif
m = 0;
buffCursor++;
token3start = buffCursor;
while (buffCursor < buffLen && inBuff[buffCursor] != ' ')
token3[m++] = inBuff[buffCursor++];
token3[m] = '\0';
if (strlen(token3) > 0)
{
int n;
int token4start;
#ifdef DEBUG
printf ("recipient is: |%s|\n", token3);
#endif
n = 0;
buffCursor++;
if (inBuff[buffCursor] == ':')
buffCursor++;
token4start = buffCursor;
while (buffCursor < buffLen)
token4[n++] = inBuff[buffCursor++];
token4[n] = '\0';
#ifdef DEBUG
printf("full rest token4: |%s|\n", inBuff+token4start);
printf("Token4 is: |%s|, %d\n", token4, strlen(token4));
#endif
if (!strcmp(token2, "PRIVMSG"))
{
if (token4[0] == '\001')
{
int tok4Len;
tok4Len = strlen(token4);
if (token4[tok4Len-1] == '\001')
{
#ifdef DEBUG
printf ("should chop last 001\n");
#endif
token4[tok4Len-1] = '\0';
tok4Len--;
}
n = 0;
while (n < tok4Len && token4[n] != ' ')
n++;
if (token4[n] == ' ')
{
strcpy(token5, token4 + n + 1);
token4[n] = '\0';
#ifdef DEBUG
printf("Token5 is: |%s|\n", token5);
#endif
}
if (!strcmp(token4, "\001ACTION"))
{
handleAction(token1, token5);
} else if (!strcmp(inBuff+token4start, "\001VERSION\001"))
{
handleCTCPVersion(token1);
}
} else
{
if (sysState.isInChannel && (token3[0] == '#'|| token3[0] == '&'))
handleChannelMessage(token1, token4);
else
handlePrivateMessage(token1, token4);
}
} else if (!strcmp(token2, "NICK"))
{
char oldNick[MAX_NICK_LEN];
char *nickEnd;
nickEnd = strchr(token1, '!');
if (nickEnd)
{
strncpy(oldNick, token1, nickEnd-token1);
oldNick[nickEnd-token1] = '\0';
/* we crop out the leading : form token3 */
#ifdef DEBUG
printf("change %s to %s\n", oldNick, token3+1);
#endif
renameUserInList(oldNick, token3+1, userList);
}
} else if (!strcmp(token2, "NOTICE"))
{
handleNotice(token1, token4);
} else if (!strcmp(token2, "JOIN"))
{
handleJoinNotify(token1, token3);
} else if (!strcmp(token2, "MODE"))
{
handleMode(token1, token3, token4);
} else if (!strcmp(token2, "QUIT"))
{
handleQuitNotify(token1, inBuff+token3start+1);
} else if (!strcmp(token2, "PART"))
{
handlePartNotify(token1, inBuff+token3start+1);
} else if (!strcmp(token2, "001"))
{
handleCommandResponse(RPL_WELCOME, token4);
} else if (!strcmp(token2, "311"))
{
handleCommandResponse(RPL_WHOISUSER, token4);
} else if (!strcmp(token2, "312"))
{
handleCommandResponse(RPL_WHOISSERVER, token4);
} else if (!strcmp(token2, "313"))
{
handleCommandResponse(RPL_WHOISOPERATOR, token4);
} else if (!strcmp(token2, "317"))
{
handleCommandResponse(RPL_WHOISIDLE, token4);
} else if (!strcmp(token2, "318"))
{
handleCommandResponse(RPL_ENDOFWHOIS, token4);
} else if (!strcmp(token2, "319"))
{
handleCommandResponse(RPL_WHOISCHANNELS, token4);
} else if (!strcmp(token2, "353"))
{
handleCommandResponse(RPL_NAMREPLY, token4);
} else if (!strcmp(token2, "372"))
{
handleCommandResponse(RPL_MOTD, token4);
} else if (!strcmp(token2, "375"))
{
handleCommandResponse(RPL_MOTDSTART, token4);
} else if (!strcmp(token2, "376"))
{
handleCommandResponse(RPL_ENDOFMOTD, token4);
} else if (!strcmp(token2, "401"))
{
handleCommandResponse(ERR_NOSUCHNICK, token4);
} else if (!strcmp(token2, "403"))
{
handleCommandResponse(ERR_NOSUCHCHANNEL, token4);
} else if (!strcmp(token2, "404"))
{
handleCommandResponse(ERR_CANNOTSENDTOCHAN, token4);
} else if (!strcmp(token2, "433"))
{
handleCommandResponse(ERR_NICKNAMEINUSE, token4);
} else if (!strcmp(token2, "436"))
{
handleCommandResponse(ERR_NICKCOLLISION, token4);
} else
printf("got some : command message: %s\n", token2);
} /* token 3 */
} /* token 2*/
} /* token 1 */
/* commands not starting with : */
} else if (!strncmp(inBuff, "NOTICE", 6))
{
char token[MAX_COMMAND_LEN+1];
int i;
int len;
int delta;
delta = strlen("NOTICE") + 1;
i = 7;
len = strlen(inBuff);
#ifdef DEBUG
assert(len <= MAX_COMMAND_LEN);
#endif
while (i < len)
{
token[i-delta] = inBuff[i];
i++;
}
token[i-delta] = '\0';
#ifdef DEBUG
printf("Should handle notice with: %s\n", token);
#endif
handleNotice(0, token);
} else if (!strncmp(inBuff, "PING", strlen("PING")))
{
char token[MAX_COMMAND_LEN+1];
int i;
int len;
int delta;
delta = strlen("PING") + 1;
len = strlen(inBuff);
if (inBuff[delta] == ':')
delta++;
i = delta;
while (i < len)
{
token[i-delta] = inBuff[i];
i++;
}
token[i-delta] = '\0';
handlePing(token);
} else
{
printf("I got unknown: |%s|\n", inBuff);
}
}
void handlePing (char *sender)
{
#ifdef DEBUG
char msg[MAX_COMMAND_LEN+1];
strcpy(msg, "Got ping from: ");
strcat(msg, sender);
strcat(msg, "\n");
appendText(msg);
#endif
doPong(sender);
}
void handlePrivateMessage (char *sender, char *msg)
{
char tempStr[2*MAX_COMMAND_LEN+2];
char nick[MAX_COMMAND_LEN+1];
int i;
int senderLen;
senderLen = strlen(sender);
i = 0;
while (i < senderLen && sender[i] != '!')
i++;
if (sender[i] == '!')
strncpy(nick, sender, i);
nick[i] = '\0';
sprintf(tempStr, "[%s] %s\n", nick, msg);
appendText(tempStr);
}
void handleChannelMessage (char *sender, char *msg)
{
char tempStr[2*MAX_COMMAND_LEN+2];
char senderNick[MAX_COMMAND_LEN+1];
int i;
int nickLen;
i = 0;
nickLen = strlen(sender);
while (i < nickLen && sender[i] != '!')
{
senderNick[i] = sender[i];
i++;
}
senderNick[i] = '\0';
sprintf(tempStr, "%s: %s\n", senderNick, msg);
appendText(tempStr);
}
void handleNotice (char *sender, char *msg)
{
char tempStr[2*MAX_COMMAND_LEN+2];
char nick[MAX_COMMAND_LEN+1];
int i;
int senderLen;
if (sender)
{
senderLen = strlen(sender);
i = 0;
while (i < senderLen && sender[i] != '!')
i++;
if (sender[i] == '!')
strncpy(nick, sender, i);
nick[i] = '\0';
sprintf(tempStr, "# notice (%s) # : %s\n", nick, msg);
} else /* sender is NULL */
{
sprintf(tempStr, "# notice # : %s\n", msg);
}
appendText(tempStr);
}
void handleAction (char *sender, char *msg)
{
char tempStr[2*MAX_COMMAND_LEN+2];
char senderNick[MAX_COMMAND_LEN+1];
int i;
int nickLen;
i = 0;
nickLen = strlen(sender);
while (i < nickLen && sender[i] != '!')
{
senderNick[i] = sender[i];
i++;
}
senderNick[i] = '\0';
sprintf(tempStr, "--- %s %s\n", senderNick, msg);
appendText(tempStr);
}
void handleCommandResponse(int code, char *msg)
{
char tempStr[MAX_COMMAND_LEN+1];
switch (code)
{
case RPL_WELCOME:
if (!strncmp(msg, "Welcome to the Internet Relay Network", 37))
{
char *realNick;
char realNick2[MAX_NICK_LEN];
int nickLen;
int i;
realNick = msg + 38;
nickLen = strlen(realNick);;
i = 0;
while (i < nickLen && realNick[i] != '!')
{
realNick2[i] = realNick[i];
i++;
}
realNick2[i] = '\0';
if (strlen(realNick2) && strstr(sysState.myNick, realNick2))
{
printf("your real nick is: %s\n", realNick2);
strcpy(sysState.myNick, realNick2);
}
}
sprintf(tempStr, "> %s\n", msg);
appendText(tempStr);
break;
case RPL_WHOISUSER:
case RPL_WHOISSERVER:
case RPL_WHOISOPERATOR:
case RPL_WHOISIDLE:
case RPL_ENDOFWHOIS:
case RPL_WHOISCHANNELS:
sprintf(tempStr, "> %s\n", msg);
appendText(tempStr);
break;
case RPL_NAMREPLY:
handleNamesReply(msg);
break;
case RPL_MOTDSTART:
case RPL_MOTD:
case RPL_ENDOFMOTD:
sprintf(tempStr, "> %s\n", msg);
appendText(tempStr);
break;
case ERR_NOSUCHNICK:
sprintf(tempStr, "> %s\n", msg);
appendText(tempStr);
break;
case ERR_NOSUCHCHANNEL:
sprintf(tempStr, "> %s\n", msg);
appendText(tempStr);
break;
case ERR_CANNOTSENDTOCHAN:
sprintf(tempStr, "> %s\n", msg);
appendText(tempStr);
break;
case ERR_NICKNAMEINUSE:
sprintf(tempStr, "> %s\n", msg);
appendText(tempStr);
break;
case ERR_NICKCOLLISION:
sprintf(tempStr, "> %s\n", msg);
appendText(tempStr);
break;
default:
printf("Unknown command response: %d\n", code);
}
}
void handleJoinNotify(char *sender, char *channel)
{
char tempStr[2*MAX_COMMAND_LEN+2];
char senderNick[MAX_COMMAND_LEN+1];
int i;
int nickLen;
i = 0;
nickLen = strlen(sender);
while (i < nickLen && sender[i] != '!')
{
senderNick[i] = sender[i];
i++;
}
senderNick[i] = '\0';
sprintf(tempStr, "> %s joined %s\n", senderNick, channel);
appendText(tempStr);
if (senderNick[0] == '@' || senderNick[0] == '+')
addUserToList(senderNick+1, userList);
else
addUserToList(senderNick, userList);
}
void handleQuitNotify(char *sender, char *desc)
{
char tempStr[2*MAX_COMMAND_LEN+2];
char senderNick[MAX_COMMAND_LEN+1];
int i;
int nickLen;
i = 0;
nickLen = strlen(sender);
while (i < nickLen && sender[i] != '!')
{
senderNick[i] = sender[i];
i++;
}
senderNick[i] = '\0';
sprintf(tempStr, "> %s quit (%s)\n", senderNick, desc);
appendText(tempStr);
removeUserFromList(senderNick, userList);
}
void handlePartNotify(char *sender, char *desc)
{
char tempStr[2*MAX_COMMAND_LEN+2];
char senderNick[MAX_COMMAND_LEN+1];
int i;
int nickLen;
i = 0;
nickLen = strlen(sender);
while (i < nickLen && sender[i] != '!')
{
senderNick[i] = sender[i];
i++;
}
senderNick[i] = '\0';
sprintf(tempStr, "> %s parted (%s)\n", senderNick, desc);
appendText(tempStr);
removeUserFromList(senderNick, userList);
}
void handleNamesReply(char *message)
{
char nick[MAX_NICK_LEN+1];
char *beginNick, *endNick, *cursor;
int strLen;
strLen = strlen(message);
cursor = strchr(message, ':');
if (cursor == NULL)
return;
cursor++;
while (cursor-message < strLen)
{
beginNick = cursor;
endNick = strchr(cursor, ' ');
if (endNick == NULL)
endNick = message + strLen;
if (endNick - beginNick <= MAX_NICK_LEN)
{
strncpy(nick, beginNick, endNick - beginNick);
nick[endNick - beginNick] = '\0';
} else
{
strncpy(nick, beginNick, MAX_NICK_LEN);
nick[MAX_NICK_LEN] = '\0';
printf("Warning, %s was longer than %d characters.\n", nick, MAX_NICK_LEN);
}
#ifdef DEBUG
printf("Found user |%s|\n", nick);
#endif
if (nick[0] == '@' || nick[0] == '+')
addUserToList(nick+1, userList);
else
addUserToList(nick, userList);
cursor = endNick + 1;
}
}
void handleMode (char *sender, char *dest, char *msg)
{
char tempStr[3*MAX_COMMAND_LEN+2];
char nick[MAX_COMMAND_LEN+1];
char token1[MAX_COMMAND_LEN+1];
char token2[MAX_COMMAND_LEN+1];
int msgLen;
int buffCursor;
int i;
int nickLen;
nick[0] = '\0';
token1[0] = '\0';
token2[0] = '\0';
/* extract nick part from sender */
i = 0;
nickLen = strlen(sender);
while (i < nickLen && sender[i] != '!')
{
nick[i] = sender[i];
i++;
}
nick[i] = '\0';
buffCursor = 0;
msgLen = strlen(msg);
i = 0;
while (buffCursor < msgLen && msg[buffCursor] != ' ')
token1[i++] = msg[buffCursor++];
token1[i] = '\0';
if (strlen(token1) > 0)
{
int j;
j = 0;
buffCursor++;
while (buffCursor < msgLen)
token2[j++] = msg[buffCursor++];
token2[j] = '\0';
}
#ifdef DEBUG
printf("%s made %s to %s\n", nick, msg, dest);
#endif
if (!strcmp(token1, "+o"))
{
sprintf(tempStr, "- %s: %s gives Op to %s\n", dest, nick, token2);
appendText(tempStr);
} else if (!strcmp(token1, "-o"))
{
sprintf(tempStr, "- %s: %s removes Op from %s\n", dest, nick, token2);
appendText(tempStr);
}
}
void handleCTCPVersion (char *sender)
{
char tempStr[2*MAX_COMMAND_LEN+2];
char nick[MAX_COMMAND_LEN+1];
char localEcho[MAX_COMMAND_LEN+100];
int i;
int senderLen;
senderLen = strlen(sender);
i = 0;
while (i < senderLen && sender[i] != '!')
i++;
if (sender[i] == '!' || i == senderLen)
strncpy(nick, sender, i);
nick[i] = '\0';
sprintf(tempStr, ":%s NOTICE %s :\001VERSION %s:%s:%s\001\n", sysState.myNick, nick, CLIENT_NAME, CLIENT_VERSION, sysState.systemInfo);
sendLine(tempStr);
sprintf(localEcho, "[ sent Version to %s ]\n", nick);
appendText(localEcho);
}
#include "copyright.h"