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