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