]>
jfr.im git - irc/gameservirc.git/blob - gameserv/tcpclient.cpp
2 * This file is provided for use with the unix-socket-faq. It is public
3 * domain, and may be copied freely. There is no copyright on it. The
4 * original work was by Vic Metcalfe (vic@brutus.tlug.org), and any
5 * modifications made to that work were made with the understanding that
6 * the finished work would be in the public domain.
8 * If you have found a bug, please pass it on to me at the above address
9 * acknowledging that there will be no copyright on your work.
11 * The most recent version of this file, and the unix-socket-faq can be
12 * found at http://www.interlog.com/~vic/sock-faq/.
27 //#include <sys/types.h>
28 //#include <sys/wait.h>
38 char *PACKAGE
= "GameServ";
39 char *VERSION
= "1.1.9";
44 List
<aClient
> clients
;
51 int daemon(int nochdir
, int noclose
);
53 // Close all file descriptors from >= fd
54 void closeall(int fd
);
56 int main(int argc
, char *argv
[])
58 char buffer
[1024], buf
[1024];
60 char *cmd
, *source
= NULL
, *conf
= "gameserv.conf";
65 if ( argc
> 2 || stricmp(argv
[1], "--help") == 0)
67 cout
<< "Usage: gameserv [options] [configfile]" << endl
;
68 cout
<< "Options:" << endl
;
69 cout
<< "--help Displays this help dialogue" << endl
;
72 conf
= new char[strlen(argv
[1])];
73 strcpy(conf
, argv
[1]);
78 if (load_config_file(conf
))
80 cout
<< "Config file loaded ok...\n"
81 << "Turning into a daemon" << endl
;
89 perror("Could not turn into a daemon");
94 sock
= make_connection(remoteport
, SOCK_STREAM
, remoteserver
);
96 fprintf(stderr
,"make_connection failed.\n");
102 raw("PROTOCTL NICKv2 VHP");
103 raw("PASS :%s", remotepass
);
104 raw("SERVER %s 1 :%s", servername
, servername
);
105 raw("NICK %S 1 %d %S %s %s %d +owghraAxNt %s :%s v%s", time(NULL
), gshost
,
106 servername
, time(NULL
), gshost
, PACKAGE
, VERSION
);
107 raw(":%S JOIN %s", c_Forest
);
108 raw(":%S MODE %s +mtn", c_Forest
);
109 #elif defined(BAHAMUT)
110 raw("PASS %s :TS", remotepass
);
111 raw("SERVER %s 1 :%s", servername
, servername
);
112 raw("NICK %S 1 %d +o %s %s %s 0 :GameServ", time(NULL
), gsident
, gshost
,
114 raw(":%s SJOIN %d %d %s +mnt :@%S", servername
, time(NULL
), time(NULL
), c_Forest
);
115 #elif defined(HYBRID)
116 raw("PASS %s :TS", remotepass
);
117 raw("SERVER %s 1 :%s", servername
, servername
);
118 raw("NICK %S 1 %d +o %s %s %s :GameServ", time(NULL
), gsident
, gshost
,
120 // Sending a timestamp of 1 to force ops.
121 raw(":%s SJOIN 1 %s +ntm :@%S", servername
, c_Forest
);
123 // Server numeric is: [] <-- must be unique
124 raw("PASS :%s", remotepass
);
125 raw("SERVER %s 1 %d %d P10 []AAF :%s", servername
, time(NULL
), time(NULL
), servername
);
126 raw("[] N %S 1 %d %s %s DAqAoB %s :%S", time(NULL
), gsident
, gshost
, gsnum
);
127 raw("[] B %s %d +tnm %s:o", c_Forest
, time(NULL
) - 864000, gsnum
);
131 raw("%s T %s :%s", gsnum
, c_Forest
, c_ForestTopic
);
132 raw("[] EB"); // End burst
135 raw(":%S MODE %s +o %S", c_Forest
);
137 raw(":%S TOPIC %s :%s", c_Forest
, c_ForestTopic
);
140 sock_gets(sock
,buffer
,sizeof(buffer
)-1); /* -1 added thanks to
141 David Duchene <dave@ltd.com> for pointing out the possible
142 buffer overflow resulting from the linefeed added below. */
146 log("Server: %s",buffer
);
149 strcpy(boss
.name
, "Red Dragon");
150 strcpy(boss
.weapon
, "Breath of Unholy Fire");
151 boss
.strength
= 6667;
152 boss
.gold
= 2000000000;
153 boss
.exp
= 2000000000;
154 strcpy(boss
.death
, "You finally snuff out the deadly murderous "\
155 "dragon's dark flames. You have freed the land of its terror "\
156 "filled reign from above!");
161 long int loadtime
= time(NULL
);
162 long int currentTime
;
163 long int oldTime
= loadtime
;
166 if (load_monsters() == false)
170 if (sock_gets(sock
,buffer
,sizeof(buffer
)) == -1) {
176 if (buffer
[0] == ':')
178 source
= strtok(buf
, " ");
179 cmd
= strtok(NULL
, " ");
182 cmd
= strtok(buf
, " ");
184 source
= strtok(buf
, " ");
185 cmd
= strtok(NULL
, " ");
189 log("Server: %s", buffer
);
192 // Wait N seconds then we're loaded.
195 if (time(NULL
) >= welcomedelay
+ loadtime
)
199 // Save the player data every updateperiod seconds
200 currentTime
= time(NULL
);
201 if (currentTime
- oldTime
>= updateperiod
)
203 oldTime
= currentTime
;
209 if (stricmp(cmd
, "PING") == 0) {
211 timestamp
= strtok(NULL
, "");
212 raw("PONG %s", timestamp
);
214 if (stricmp(cmd
, "G") == 0) {
216 timestamp
= strtok(NULL
, " ");
217 raw("[] Z [] %s 0 %s", timestamp
+ 1, timestamp
);
220 } else if (stricmp(cmd
, "EB") == 0) {
223 } else if (stricmp(cmd
, "VERSION") == 0) {
225 server
= strtok(NULL
, " ");
227 raw(":%s 351 %s %s_%s. %s", servername
, source
+1, PACKAGE
, VERSION
, servername
);
229 } else if (strncmp(cmd
, "NICK", 4) == 0) {
230 if (buffer
[0] == ':')
233 if ((tempPtr
= find((source
+ 1))))
236 nick
= strtok(NULL
, " ");
237 tempPtr
->setNick(nick
);
244 } else if (stricmp(cmd
, "N") == 0 && strlen(source
) == 2) {
246 char *nick
, *realnick
;
247 realnick
= strtok(NULL
, " ");
249 for (int x
= 0; x
< 5; x
++)
250 nick
= strtok(NULL
, " ");
255 log ("aClient has modes");
258 // Searching for the +r mode (extra parameter)
259 for (unsigned int count
= 1; count
< strlen(nick
); count
++)
261 if (nick
[count
] == 'r')
263 nick
= strtok(NULL
, " ");
267 nick
= strtok(NULL
, " ");
272 nick
= strtok(NULL
, " ");
275 newuser
= new aClient(nick
, realnick
);
277 newuser
= new aClient(nick
);
283 notice(s_GameServ
, nick
, welcomemsg
, realnick
);
285 notice(s_GameServ
, nick
, welcomemsg
, nick
);
288 clients
.insertAtBack(newuser
);
292 } else if (stricmp(cmd
, "Q") == 0) {
294 } else if (stricmp(cmd
, "QUIT") == 0) {
302 if ((quitter
= find(source
)))
303 clients
.remove(quitter
);
304 if ((quitter
= findIRCplayer(source
)))
306 quitter
->setNick("!NULL!");
307 quitter
->stats
->user
= NULL
; // Unidentify them
314 } else if (stricmp(cmd
, "P") == 0) {
317 longname
= new char[strlen(s_GameServ
) + strlen(servername
) + 2];
319 sprintf(longname
, "%S@%s", servername
);
321 dest
= strtok(NULL
, " ");
322 rest
= strtok(NULL
, "");
323 if (stricmp(dest
, gsnum
) == 0 || stricmp(dest
, longname
) == 0)
326 gameserv(source
, rest
);
328 else if (stricmp(dest
, c_Forest
) == 0)
331 forest(source
, rest
);
334 } else if (stricmp(cmd
, "PRIVMSG") == 0) {
336 dest
= strtok(NULL
, " ");
337 rest
= strtok(NULL
, "");
338 if (strnicmp(dest
, s_GameServ
, strlen(s_GameServ
)) == 0)
339 gameserv(source
, rest
);
340 else if (stricmp(dest
, c_Forest
) == 0)
341 forest(source
, rest
);
343 } else if (stricmp(cmd
, "JOIN") == 0) {
345 channel
= strtok(NULL
, " ");
346 if (stricmp(channel
, c_Forest
) == 0 && is_playing(source
+ 1))
347 raw(":%S MODE %s +v %s", c_Forest
, (source
+ 1));
350 } else if (stricmp(cmd
, "SJOIN") == 0) {
351 char *channel
, *nick
, *tmp
, *rest
;
352 strtok(NULL
, " "); // Ignore the TS
354 strtok(NULL
, " "); // Ignore the TS
356 channel
= strtok(NULL
, " ");
357 rest
= strtok(NULL
, "");
358 tmp
= strchr(rest
, ':');
360 nick
= strtok(tmp
, " ");
366 nick
++; // Assume for users set op and voice, they
367 // are never passed as +@nick
368 if (stricmp(channel
, c_Forest
) == 0 && is_playing(nick
))
369 raw(":%S MODE %s +v %s", channel
, nick
);
371 nick
= strtok(NULL
, " ");
376 log("Unrecognized Message: cmd = %s source = %s", cmd
, source
);
394 unload_config_file();
398 aClient
*find(char *nick
)
400 return findbynick(nick
);
403 aClient
*find(const char *nick
)
405 return findbynick(nick
);
410 aClient
*findbyrealnick(char *realnick
)
412 ListNode
<aClient
> *newPtr
;
413 newPtr
= clients
.First();
415 aClient
*client
= NULL
;
419 client
= newPtr
->getData();
420 if (stricmp(client
->getRealNick(), realnick
) == 0)
423 newPtr
= newPtr
->Next();
430 aClient
*findbyrealnick(char *realnick
)
432 return findbynick(realnick
);
437 aClient
*findbynick(char *nick
)
439 ListNode
<aClient
> *newPtr
;
440 newPtr
= clients
.First();
442 aClient
*client
= NULL
;
446 client
= newPtr
->getData();
448 if (strcmp(client
->getNick(), nick
) == 0)
450 if (stricmp(client
->getNick(), nick
) == 0)
454 newPtr
= newPtr
->Next();
459 aClient
*findIRCplayer(const char *nick
)
461 ListNode
<aClient
> *newPtr
;
464 for (newPtr
= players
.First(); newPtr
; newPtr
= newPtr
->Next())
466 p
= newPtr
->getData();
468 if (strcmp(p
->getNick(), nick
) == 0)
470 if (stricmp(p
->getNick(), nick
) == 0)
477 aClient
*findplayer(const char *name
)
479 ListNode
<aClient
> *newPtr
;
482 for (newPtr
= players
.First(); newPtr
; newPtr
= newPtr
->Next())
484 p
= newPtr
->getData()->stats
;
485 if (stricmp(p
->name
, name
) == 0)
486 return newPtr
->getData();
492 aClient
*findbynick(const char *nick
)
494 ListNode
<aClient
> *newPtr
;
495 newPtr
= clients
.First();
497 aClient
*client
= NULL
;
501 client
= newPtr
->getData();
503 if (strcmp(client
->getNick(), nick
) == 0)
505 if (stricmp(client
->getNick(), nick
) == 0)
509 newPtr
= newPtr
->Next();
518 infile
.open(".gsday");
523 log("Error opening .gsday");
528 log("Generating new day");
543 if (day
< 1 || day
> 31)
551 outfile
.open(".gsday");
555 log("Error creating new file .gsday");
559 outfile
<< day
<< endl
;
564 /* daemon() - detach process from user and disappear into the background
565 * returns -1 on failure, but you can't do much except exit in that case
566 * since we may already have forked. This is based on the BSD version,
567 * so the caller is responsible for things like the umask, etc.
570 /* believed to work on all Posix systems */
572 int daemon(int nochdir
, int noclose
)
575 switch (pid
= fork())
579 default: _exit(0); /* exit the original process */
582 if (setsid() < 0) /* shoudn't fail */
585 /* dyke out this switch if you want to acquire a control tty in */
586 /* the future -- not normally advisable for daemons */
588 switch (pid
= fork())
594 outfile
.open(pidfile
);
596 cerr
<< "Unable to open " << pidfile
<< endl
;
597 outfile
<< pid
<< endl
;
609 open("/dev/null",O_RDWR
);
617 /* closeall() -- close all FDs >= a specified value */
619 void closeall(int fd
)
621 int fdlimit
= sysconf(_SC_OPEN_MAX
);
630 cout
<< " GGGG AAA MM MM EEEEEEE SSSSS EEEEEEE RRRRRR VV VV " << endl
;
631 cout
<< " GG GG AAAAA MMM MMM EE SS EE RR RR VV VV " << endl
;
632 cout
<< "GG AA AA MM MM MM EEEEE SSSSS EEEEE RRRRRR VV VV " << endl
;
633 cout
<< "GG GGG AAAAAAA MM MM EE SS EE RR RR VV VV " << endl
;
634 cout
<< "G G AA AA MM MM EEEEEEE SSSSS EEEEEEE RR RR VVV" << endl
;
635 cout
<< " GGGGG V\n\n" << endl
;
636 cout
<< "Version: " << VERSION
<< endl
;