]> jfr.im git - irc/gameservirc.git/blame - gameserv/tcpclient.cpp
Fixed the isalive(user) to isAlive(user->stats) in the timeoutevents
[irc/gameservirc.git] / gameserv / tcpclient.cpp
CommitLineData
85ce9d3e 1/*
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.
7 *
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.
10 *
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/.
13 */
14
15#include "sockhelp.h"
c7340cbd 16#include "options.h"
85ce9d3e 17#include "list.h"
18#include "aClient.h"
19#include "extern.h"
448a1531 20#include "flags.h"
85ce9d3e 21#include <stdio.h>
22#include <unistd.h>
23#include <string.h>
fb37ecc7 24#include <fstream>
85ce9d3e 25#include <stdlib.h>
ce61cdfa 26#include <fcntl.h>
27#include <signal.h>
28//#include <sys/types.h>
29//#include <sys/wait.h>
30//#include <errno.h>
31
fb37ecc7 32using std::ofstream;
33using std::ifstream;
ce61cdfa 34using std::cerr;
35using std::endl;
fb37ecc7 36
91c0b563 37char *PACKAGE = "GameServ";
0b259dff 38char *VERSION = "1.2.1 +devel";
173302fe 39
85ce9d3e 40int sock;
abbfcdb9 41int day;
44ea29f7 42
7996e5fd 43List<aClient> clients[U_TABLE_SIZE];
85ce9d3e 44
abbfcdb9 45void save_day();
46void load_day();
15838737 47void prettyIntro();
40251952 48void check_idles();
44ea29f7 49
ce61cdfa 50// Make this a daemon
51int daemon(int nochdir, int noclose);
52
53// Close all file descriptors from >= fd
54void closeall(int fd);
55
624c0352 56int main(int argc, char *argv[])
85ce9d3e 57{
e3ede4a7 58 char buffer[1024], buf[1024];
59 memset(buffer, 0, 1024);
60 memset(buf, 0, 1024);
61 int connected;
62 long lastidlecheck;
63 char *cmd, *source = NULL, *conf;
64 srand(time(NULL));
65 conf = new char[16];
66 strcpy(conf, "gameserv.conf");
624c0352 67
1579dfa2 68 /*
69 * This needs to be fixed to work for any number of arguments in any
70 * order
71 *
72 */
624c0352 73 if (argc > 1)
74 {
75 if ( argc > 2 || stricmp(argv[1], "--help") == 0)
76 {
77 cout << "Usage: gameserv [options] [configfile]" << endl;
78 cout << "Options:" << endl;
79 cout << "--help Displays this help dialogue" << endl;
80 return 1;
81 }
e3ede4a7 82 delete []conf;
83 conf = argv[1];
624c0352 84 }
85
15838737 86 prettyIntro();
624c0352 87
88 if (load_config_file(conf))
89 {
90 cout << "Config file loaded ok...\n"
91 << "Turning into a daemon" << endl;
92 }
93 else
94 exit(2);
324ab87f 95
e3ede4a7 96 if (argc <= 1)
97 delete []conf;
98
ce61cdfa 99 // Turn into a daemon
100 if (daemon(1,0) < 0)
101 {
102 perror("Could not turn into a daemon");
448a1531 103 exit(3);
ce61cdfa 104 }
05c527e6 105 init_masters();
106 load_gs_dbase();
107
108 if (load_monsters() == false)
109 goto end;
110
448a1531 111 shuttingdown = false;
112
113 char ignoreservers[32][256];
114 char *currentserver;
115 currentserver = strtok(ignoreserverslist, " ");
116 for (int server = 0; server < 32 && currentserver != NULL; server++)
117 {
118 strncpy(ignoreservers[server], currentserver, 255);
119 log("Placing %s on the server ignore list", currentserver);
120 currentserver = strtok(NULL, " ");
121 }
05c527e6 122
123 strcpy(boss.name, "Red Dragon");
124 strcpy(boss.weapon, "Breath of Unholy Fire");
125 boss.strength = 6667;
126 boss.gold = 2000000000;
127 boss.exp = 2000000000;
128 strcpy(boss.death, "You finally snuff out the deadly murderous "\
129 "dragon's dark flames. You have freed the land of its terror "\
130 "filled reign from above!");
131
448a1531 132
05c527e6 133 // This loop will retry the connection 3 times
134 for (int retry = 0; retry < 3 && !shuttingdown; retry++)
135 {
0b6098d5 136 connected = 1;
137 load_day();
05c527e6 138
448a1531 139
0b6098d5 140 long int loadtime = time(NULL);
141 long int currentTime;
142 long int oldTime = loadtime;
40251952 143
0b6098d5 144 lastidlecheck = loadtime;
05c527e6 145
0b6098d5 146 #ifdef DEBUGMODE
147 log("Setting primary Idle Check timestamp: %ld", lastidlecheck);
148 #endif
149 bool loaded = false;
150
151 ignore_pipe();
152 sock = make_connection(remoteport, SOCK_STREAM, remoteserver);
153 if (sock == -1) {
154 fprintf(stderr,"make_connection failed.\n");
85ce9d3e 155 unload_config_file();
156 return -1;
157 }
448a1531 158 log("%S socket connected.");
85ce9d3e 159
c7340cbd 160#ifdef UNREAL
85ce9d3e 161 raw("PROTOCTL NICKv2 VHP");
162 raw("PASS :%s", remotepass);
c7340cbd 163 raw("SERVER %s 1 :%s", servername, servername);
6f727d4c 164 raw("NICK %S 1 %d %S %s %s %d +w%s %s :%s v%s", time(NULL), gshost,
165 servername, time(NULL), (isBOper() ? "o" : ""), gshost, PACKAGE, VERSION);
85ce9d3e 166 raw(":%S JOIN %s", c_Forest);
03a4bdbb 167 raw(":%S MODE %s +tn", c_Forest);
c7340cbd 168#elif defined(BAHAMUT)
169 raw("PASS %s :TS", remotepass);
170 raw("SERVER %s 1 :%s", servername, servername);
6f727d4c 171 raw("NICK %S 1 %d +w%s %s %s %s 0 :GameServ", time(NULL), (isBOper() ? "o" : ""),
172 gsident, gshost, servername);
03a4bdbb 173 raw(":%s SJOIN %d %d %s +nt :@%S", servername, time(NULL), time(NULL), c_Forest);
581ec09e 174#elif defined(HYBRID)
175 raw("PASS %s :TS", remotepass);
176 raw("SERVER %s 1 :%s", servername, servername);
6f727d4c 177 raw("NICK %S 1 %d +w%s %s %s %s :GameServ", time(NULL), (isBOper() ? "o" : ""),
178 gsident, gshost, servername);
448a1531 179 raw(":%s SJOIN %ld %s +nt :@%S", servername, time(NULL), c_Forest);
e1c41a84 180#elif defined(P10)
181 // Server numeric is: [] <-- must be unique
182 raw("PASS :%s", remotepass);
183 raw("SERVER %s 1 %d %d P10 []AAF :%s", servername, time(NULL), time(NULL), servername);
6f727d4c 184 raw("[] N %S 1 %d %s %s %s DAqAoB %s :%S", time(NULL), gsident, gshost,
185 (isBOper() ? "+o" : "") gsnum);
03a4bdbb 186 raw("[] B %s %d +tn %s:o", c_Forest, time(NULL) - 864000, gsnum);
c7340cbd 187#endif
e1c41a84 188
189#if defined(P10)
190 raw("%s T %s :%s", gsnum, c_Forest, c_ForestTopic);
fc9d2643 191 raw("[] EB"); // End burst
581ec09e 192#else
193#ifndef HYBRID
85ce9d3e 194 raw(":%S MODE %s +o %S", c_Forest);
581ec09e 195#endif
c7340cbd 196 raw(":%S TOPIC %s :%s", c_Forest, c_ForestTopic);
e1c41a84 197#endif
85ce9d3e 198
199 sock_gets(sock,buffer,sizeof(buffer)-1); /* -1 added thanks to
200 David Duchene <dave@ltd.com> for pointing out the possible
201 buffer overflow resulting from the linefeed added below. */
202
203
9f8c2acc 204 #ifdef DEBUGMODE
205 log("Server: %s",buffer);
206 #endif
207
85ce9d3e 208 while (connected) {
209 if (sock_gets(sock,buffer,sizeof(buffer)) == -1) {
210 connected = 0;
211 }
212 strcpy(buf, buffer);
213
e1c41a84 214 #if !defined(P10)
85ce9d3e 215 if (buffer[0] == ':')
216 {
217 source = strtok(buf, " ");
218 cmd = strtok(NULL, " ");
219 }
220 else
221 cmd = strtok(buf, " ");
e1c41a84 222 #else
223 source = strtok(buf, " ");
224 cmd = strtok(NULL, " ");
225 #endif
85ce9d3e 226
9f8c2acc 227 #ifdef DEBUGMODE
228 log("Server: %s", buffer);
229 #endif
5963944b 230
bf2cabcd 231 // Wait N seconds then we're loaded.
5963944b 232 if (!loaded)
233 {
922daad7 234 if (time(NULL) >= welcomedelay + loadtime)
05c527e6 235 {
5963944b 236 loaded = true;
05c527e6 237 retry = 0; // Start the reconnection cycle over
238 }
5963944b 239 }
40251952 240 else
241 {
242 long TIME = time(NULL);
243 if (TIME - lastidlecheck >= idlecheckperiod)
244 {
245 check_idles();
246 lastidlecheck = TIME;
247 }
248 }
5963944b 249
922daad7 250 // Save the player data every updateperiod seconds
251 currentTime = time(NULL);
252 if (currentTime - oldTime >= updateperiod)
253 {
254 oldTime = currentTime;
0b6098d5 255 log("Saving to %s", playerdata);
922daad7 256 save_gs_dbase();
257 }
258
e1c41a84 259
260 #if !defined(P10)
85ce9d3e 261 if (stricmp(cmd, "PING") == 0) {
0a1518fa 262 char *timestamp;
263 timestamp = strtok(NULL, "");
264 raw("PONG %s", timestamp);
e1c41a84 265 #else
266 if (stricmp(cmd, "G") == 0) {
267 char *timestamp;
268 timestamp = strtok(NULL, " ");
269 raw("[] Z [] %s 0 %s", timestamp + 1, timestamp);
270 #endif
fc9d2643 271 #ifdef P10
272 } else if (stricmp(cmd, "EB") == 0) {
273 raw("[] EA");
274 #endif
0501fe18 275 } else if (stricmp(cmd, "VERSION") == 0) {
276 char *server;
277 server = strtok(NULL, " ");
278 server++;
2e9db9c4 279 raw(":%s 351 %s %s_%s. %s", servername, source+1, PACKAGE, VERSION, servername);
ba2a880f 280 #if !defined(P10)
85ce9d3e 281 } else if (strncmp(cmd, "NICK", 4) == 0) {
282 if (buffer[0] == ':')
283 {
284 aClient *tempPtr;
28f552b8 285 if ((tempPtr = find((source + 1))))
85ce9d3e 286 {
287 char *nick;
59dc3990 288 unsigned long oldhv, newhv;
85ce9d3e 289 nick = strtok(NULL, " ");
448a1531 290 oldhv = iHASH((unsigned char *) tempPtr->getNick());
291 newhv = iHASH((unsigned char *) nick);
85ce9d3e 292 tempPtr->setNick(nick);
59dc3990 293 clients[oldhv].remove(tempPtr);
294 clients[newhv].insertAtBack(tempPtr);
85ce9d3e 295 }
296 }
297 else
298 {
299 char *nick;
ba2a880f 300 #else
301 } else if (stricmp(cmd, "N") == 0 && strlen(source) == 2) {
302 {
ce61cdfa 303 char *nick, *realnick;
304 realnick = strtok(NULL, " ");
ba2a880f 305
ce61cdfa 306 for (int x = 0; x < 5; x++)
ba2a880f 307 nick = strtok(NULL, " ");
fc9d2643 308
ba2a880f 309 if (nick[0] == '+')
fc9d2643 310 {
311 #ifdef DEBUGMODE
312 log ("aClient has modes");
313 #endif
314
315 // Searching for the +r mode (extra parameter)
316 for (unsigned int count = 1; count < strlen(nick); count++)
317 {
318 if (nick[count] == 'r')
319 {
320 nick = strtok(NULL, " ");
321 break;
322 }
323 }
324 nick = strtok(NULL, " ");
325 }
ba2a880f 326 #endif
448a1531 327 aClient *newuser, *temp;
ba2a880f 328
85ce9d3e 329 nick = strtok(NULL, " ");
ba2a880f 330
ce61cdfa 331 #ifdef P10
332 newuser = new aClient(nick, realnick);
333 #else
334 newuser = new aClient(nick);
335 #endif
336
337
5963944b 338 if (loaded)
18b84d11 339
340 if (isWelcome())
341 {
342 #ifdef P10
343 notice(s_GameServ, nick, welcomemsg, realnick);
344 #else
345 notice(s_GameServ, nick, welcomemsg, nick);
346 #endif
347 }
448a1531 348 #ifdef P10
349 unsigned long hv = sHASH((unsigned char *) nick)
350 #else
351 unsigned long hv = iHASH((unsigned char *) nick);
352 #endif
353
354 temp = clients[hv].insertAtBack(newuser);
355
69fb5a93 356 #if defined(HYBRID) || defined(BAHAMUT)
448a1531 357 char *nickserver;
358 strtok(NULL, " ");
359 strtok(NULL, " ");
360 nickserver = strtok(NULL, " ");
361 if (nickserver[0] == '+')
362 strtok(NULL, " ");
363 strtok(NULL, " ");
364
903cd861 365 nickserver = strtok(NULL, " ");
366 for (int x = 0; x < 32; x++)
367 {
368 if (stricmp(ignoreservers[x], nickserver) == 0)
369 {
370 setIgnore(temp);
371 break;
372 }
373 }
374 #elif defined(UNREAL)
375 char *nickserver;
376 strtok(NULL, " ");
377 strtok(NULL, " ");
378 strtok(NULL, " ");
379 strtok(NULL, " ");
448a1531 380 nickserver = strtok(NULL, " ");
381 for (int x = 0; x < 32; x++)
382 {
383 if (stricmp(ignoreservers[x], nickserver) == 0)
384 {
385 setIgnore(temp);
386 break;
387 }
388 }
389 #endif
85ce9d3e 390 delete newuser;
391 }
ba2a880f 392 #if defined(P10)
393 } else if (stricmp(cmd, "Q") == 0) {
0b259dff 394// unsigned long hv = sHASH((unsigned char *) source);
ba2a880f 395 #else
85ce9d3e 396 } else if (stricmp(cmd, "QUIT") == 0) {
0b259dff 397// unsigned long hv = iHASH((unsigned char *) source);
ba2a880f 398 #endif
85ce9d3e 399 aClient *quitter;
fc9d2643 400 char z = source[0];
401
402 if (z == ':')
403 source++;
404
3f243b0b 405 if (!(quitter = find(source)))
406 {
407 log("Fatal Error: could not find %s in the "\
408 "clients list", source);
409 goto end;
410 }
411
412 logout(quitter);
413
414 if (z == ':')
415 source--;
416
417 /* Attempting to use the logout() function
fc9d2643 418 if ((quitter = find(source)))
7996e5fd 419 clients[hv].remove(quitter);
fc9d2643 420 if ((quitter = findIRCplayer(source)))
ee38284f 421 {
7f17db99 422 if (player_fight(quitter))
423 {
424 // Stop the fight on the other client
425 aClient *otherplayer = quitter->stats->battle;
426 otherplayer->stats->battle = NULL;
427 notice(s_GameServ, otherplayer->getNick(), "%s "\
428 "has quit IRC. The fight stops here.",
429 quitter->stats->name);
430 }
431 quitter->stats->battle = NULL;
432 quitter->stats->fight = NULL;
433 quitter->stats->master = NULL;
434
85bcf836 435 quitter->setNick("Not Playing");
a5316c52 436 #ifdef P10
85bcf836 437 quitter->setRealNick("Not Playing");
a5316c52 438 #endif
85bcf836 439 quitter->stats->client = NULL; // Unidentify them
ee38284f 440 }
3f243b0b 441 */
fc9d2643 442
ba2a880f 443 #if defined(P10)
444 } else if (stricmp(cmd, "P") == 0) {
445 char *rest, *dest;
446 char *longname;
447 longname = new char[strlen(s_GameServ) + strlen(servername) + 2];
448
449 sprintf(longname, "%S@%s", servername);
85ce9d3e 450
ba2a880f 451 dest = strtok(NULL, " ");
452 rest = strtok(NULL, "");
453 if (stricmp(dest, gsnum) == 0 || stricmp(dest, longname) == 0)
454 {
455 delete [] longname;
456 gameserv(source, rest);
457 }
6f727d4c 458 else if (stricmp(dest, c_Forest) == 0 && isListenOnCF())
ba2a880f 459 {
460 delete [] longname;
461 forest(source, rest);
462 }
463 #else
85ce9d3e 464 } else if (stricmp(cmd, "PRIVMSG") == 0) {
465 char *rest, *dest;
466 dest = strtok(NULL, " ");
467 rest = strtok(NULL, "");
ad7dfaa0 468 if (strnicmp(dest, s_GameServ, strlen(s_GameServ)) == 0)
85ce9d3e 469 gameserv(source, rest);
470 else if (stricmp(dest, c_Forest) == 0)
471 forest(source, rest);
ba2a880f 472 #endif
f2072f1a 473 #if defined(P10)
474 } else if (stricmp(cmd, "J") == 0) {
475 #else
85ce9d3e 476 } else if (stricmp(cmd, "JOIN") == 0) {
f2072f1a 477 #endif
85ce9d3e 478 char *channel;
f2072f1a 479 aClient *joiner;
85ce9d3e 480 channel = strtok(NULL, " ");
f2072f1a 481
482 char z = source[0];
483
484 if (z == ':')
485 source++;
486
487 joiner = find(source);
488
489 if (stricmp(channel, c_Forest) == 0 && is_playing(joiner))
490 {
491 #ifdef DEBUGMODE
492 log("Player %s (IRC: %s) joined %s",
493 joiner->stats->name,
494 #ifdef P10
495 joiner->getRealNick(),
496 #else
497 joiner->getNick(),
498 #endif
499 c_Forest);
500 #endif
501 raw(":%S MODE %s +v %s", c_Forest, (source));
502 }
503
504 if (z == ':')
505 source--;
c7340cbd 506
507 #if defined(BAHAMUT)
508 } else if (stricmp(cmd, "SJOIN") == 0) {
581ec09e 509 char *channel, *nick, *tmp, *rest;
c7340cbd 510 strtok(NULL, " "); // Ignore the TS
581ec09e 511#ifndef HYBRID
c7340cbd 512 strtok(NULL, " "); // Ignore the TS
581ec09e 513#endif
c7340cbd 514 channel = strtok(NULL, " ");
581ec09e 515 rest = strtok(NULL, "");
516 tmp = strchr(rest, ':');
517 tmp++;
518 nick = strtok(tmp, " ");
519 while (nick != NULL)
520 {
521 if (*nick == '@')
522 nick++;
523 if (*nick == '+')
524 nick++; // Assume for users set op and voice, they
525 // are never passed as +@nick
526 if (stricmp(channel, c_Forest) == 0 && is_playing(nick))
527 raw(":%S MODE %s +v %s", channel, nick);
528
529 nick = strtok(NULL, " ");
530 }
531#endif
85ce9d3e 532 } else {
9f8c2acc 533 #ifdef DEBUGMODE
534 log("Unrecognized Message: cmd = %s source = %s", cmd, source);
535 #endif
85ce9d3e 536 }
537 }
4dde2ed9 538
05c527e6 539 } // for loop for connection retry
540
4dde2ed9 541 end:
542
c8ada07e 543 save_gs_dbase();
abbfcdb9 544 save_day();
4dde2ed9 545
c8ada07e 546 delete_monsters();
547 delete_masters();
548
9f8c2acc 549 #ifdef DEBUGMODE
550 log("<CLOSED>");
551 #endif
552
85ce9d3e 553 close(sock);
554 unload_config_file();
555 return 0;
556}
557
558aClient *find(char *nick)
559{
560 return findbynick(nick);
561}
562
563aClient *find(const char *nick)
564{
565 return findbynick(nick);
566}
567
ce61cdfa 568#ifdef P10
569
570aClient *findbyrealnick(char *realnick)
571{
572 ListNode <aClient> *newPtr;
448a1531 573 unsigned long hv = sHASH((unsigned char *) realnick);
7996e5fd 574 newPtr = clients[hv].First();
ce61cdfa 575
576 aClient *client = NULL;
577
578 while (newPtr)
579 {
580 client = newPtr->getData();
581 if (stricmp(client->getRealNick(), realnick) == 0)
582 return client;
583 client = NULL;
584 newPtr = newPtr->Next();
585 }
586 return client;
587}
4e5760fd 588
589#else
590
591aClient *findbyrealnick(char *realnick)
592{
593 return findbynick(realnick);
594}
595
ce61cdfa 596#endif
85ce9d3e 597
598aClient *findbynick(char *nick)
599{
600 ListNode <aClient> *newPtr;
448a1531 601 #ifdef P10
602 unsigned long hv = sHASH((unsigned char *) nick);
603 #else
604 unsigned long hv = iHASH((unsigned char *) nick);
605 #endif
606
7996e5fd 607 newPtr = clients[hv].First();
85ce9d3e 608
609 aClient *client = NULL;
610
611 while (newPtr)
612 {
613 client = newPtr->getData();
23ec3ff4 614 #ifdef P10
23ec3ff4 615 if (strcmp(client->getNick(), nick) == 0)
616 #else
617 if (stricmp(client->getNick(), nick) == 0)
618 #endif
85ce9d3e 619 return client;
620 client = NULL;
621 newPtr = newPtr->Next();
622 }
623 return client;
624}
625
ee38284f 626aClient *findIRCplayer(const char *nick)
627{
628 ListNode <aClient> *newPtr;
629 aClient *p = NULL;
630
448a1531 631 p = find(nick);
632
633 if (!is_playing(p))
634 return NULL;
635
636 unsigned long hv = iHASH((unsigned char *) p->stats->name);
637
7996e5fd 638 for (newPtr = players[hv].First(); newPtr; newPtr = newPtr->Next())
ee38284f 639 {
640 p = newPtr->getData();
23ec3ff4 641 #ifdef P10
642 if (strcmp(p->getNick(), nick) == 0)
643 #else
644 if (stricmp(p->getNick(), nick) == 0)
645 #endif
ee38284f 646 return p;
647 p = NULL;
648 }
649 return NULL;
650}
40251952 651
0a1518fa 652aClient *findplayer(const char *name)
653{
654 ListNode <aClient> *newPtr;
655 Player *p = NULL;
448a1531 656 unsigned long hv = iHASH((unsigned char *) name);
7996e5fd 657 for (newPtr = players[hv].First(); newPtr; newPtr = newPtr->Next())
0a1518fa 658 {
659 p = newPtr->getData()->stats;
660 if (stricmp(p->name, name) == 0)
661 return newPtr->getData();
662 p = NULL;
663 }
664 return NULL;
665}
666
40251952 667void check_idles()
668{
669 ListNode <aClient> *newPtr;
670 Player *p = NULL;
671
672 for (int x = 0; x < U_TABLE_SIZE; x++)
673 {
674 for (newPtr = players[x].First(); newPtr; newPtr = newPtr->Next())
675 {
676 p = newPtr->getData()->stats;
677 if (timedOut(p))
678 {
679 timeOutEvent(p);
680 }
681 }
682 }
683}
684
85ce9d3e 685aClient *findbynick(const char *nick)
686{
687 ListNode <aClient> *newPtr;
448a1531 688 #ifdef P10
689 unsigned long hv = sHASH((unsigned char *) nick);
690 #else
691 unsigned long hv = iHASH((unsigned char *) nick);
692 #endif
693
7996e5fd 694 newPtr = clients[hv].First();
85ce9d3e 695
696 aClient *client = NULL;
697
698 while (newPtr)
699 {
700 client = newPtr->getData();
23ec3ff4 701 #ifdef P10
702 if (strcmp(client->getNick(), nick) == 0)
703 #else
704 if (stricmp(client->getNick(), nick) == 0)
705 #endif
85ce9d3e 706 return client;
707 client = NULL;
708 newPtr = newPtr->Next();
709 }
710 return client;
711}
712
abbfcdb9 713void load_day()
44ea29f7 714{
715 ifstream infile;
716
abbfcdb9 717 infile.open(".gsday");
44ea29f7 718
719 if (infile.fail())
720 {
9f8c2acc 721 #ifdef DEBUGMODE
abbfcdb9 722 log("Error opening .gsday");
9f8c2acc 723 #endif
724
44ea29f7 725 generate:
9f8c2acc 726 #ifdef DEBUGMODE
abbfcdb9 727 log("Generating new day");
9f8c2acc 728 #endif
abbfcdb9 729 struct tm *tm;
730 time_t ti;
731 time(&ti);
732 tm = localtime(&ti);
733
734 day = tm->tm_mday;
735
736 save_day();
44ea29f7 737 return;
738 }
739
abbfcdb9 740 infile >> day;
44ea29f7 741 infile.close();
abbfcdb9 742 if (day < 1 || day > 31)
44ea29f7 743 goto generate;
744}
745
abbfcdb9 746void save_day()
44ea29f7 747{
748 ofstream outfile;
749
abbfcdb9 750 outfile.open(".gsday");
44ea29f7 751
752 if (outfile.fail())
753 {
abbfcdb9 754 log("Error creating new file .gsday");
44ea29f7 755 return;
756 }
757
abbfcdb9 758 outfile << day << endl;
44ea29f7 759
760 outfile.close();
761}
762
ce61cdfa 763/* daemon() - detach process from user and disappear into the background
764 * returns -1 on failure, but you can't do much except exit in that case
765 * since we may already have forked. This is based on the BSD version,
766 * so the caller is responsible for things like the umask, etc.
767 */
768
769/* believed to work on all Posix systems */
770
771int daemon(int nochdir, int noclose)
772{
773 pid_t pid;
774 switch (pid = fork())
775 {
776 case 0: break;
777 case -1: return -1;
778 default: _exit(0); /* exit the original process */
779 }
780
781 if (setsid() < 0) /* shoudn't fail */
782 return -1;
783
784 /* dyke out this switch if you want to acquire a control tty in */
785 /* the future -- not normally advisable for daemons */
786
787 switch (pid = fork())
788 {
789 case 0: break;
790 case -1: return -1;
791 default:
792 ofstream outfile;
69ae096c 793 outfile.open(pidfile);
ce61cdfa 794 if (outfile.fail())
69ae096c 795 cerr << "Unable to open " << pidfile << endl;
ce61cdfa 796 outfile << pid << endl;
797 outfile.close();
798
799 _exit(0);
800 }
801
802 if (!nochdir)
803 chdir("/");
804
805 if (!noclose)
806 {
807 closeall(0);
808 open("/dev/null",O_RDWR);
809 dup(0); dup(0);
810 }
811
812 return 0;
813}
814
815
816/* closeall() -- close all FDs >= a specified value */
817
818void closeall(int fd)
819{
820 int fdlimit = sysconf(_SC_OPEN_MAX);
821
822 while (fd < fdlimit)
823 close(fd++);
824}
825
15838737 826void prettyIntro()
827{
828cout << endl;
829cout << " GGGG AAA MM MM EEEEEEE SSSSS EEEEEEE RRRRRR VV VV " << endl;
830cout << " GG GG AAAAA MMM MMM EE SS EE RR RR VV VV " << endl;
831cout << "GG AA AA MM MM MM EEEEE SSSSS EEEEE RRRRRR VV VV " << endl;
832cout << "GG GGG AAAAAAA MM MM EE SS EE RR RR VV VV " << endl;
833cout << "G G AA AA MM MM EEEEEEE SSSSS EEEEEEE RR RR VVV" << endl;
834cout << " GGGGG V\n\n" << endl;
835cout << "Version: " << VERSION << endl;
836}