|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)snake.c 4.1 (Berkeley) 7/4/83";
3: #endif
4:
5: /*
6: * snake - crt hack game.
7: *
8: * You move around the screen with arrow keys trying to pick up money
9: * without getting eaten by the snake. hjkl work as in vi in place of
10: * arrow keys. You can leave at the exit any time.
11: *
12: * compile as follows:
13: * cc -O snake.c move.c -o snake -lm -ltermlib
14: */
15:
16: #include "snake.h"
17: #include <pwd.h>
18:
19: /*
20: * If CHECKBUSY is defined, the file BUSY must be executable
21: * and must return a value which is used to determine the priority
22: * a which snake runs. A zero value means no nice.
23: * If BUSY does not exist, snake won't play.
24: */
25: #ifndef BUSY
26: #define BUSY "/usr/games/lib/busy"
27: #endif
28:
29: /*
30: * This is the data file for scorekeeping.
31: */
32: #ifndef SNAKERAWSCORES
33: #define SNAKERAWSCORES "/usr/games/lib/snakerawscores"
34: #endif
35:
36: /*
37: * If it exists, a log is kept here. Otherwise it isn't.
38: */
39: #ifndef LOGFILE
40: #define LOGFILE "/usr/games/lib/snake.log"
41: #endif
42:
43: #define PENALTY 10 /* % penalty for invoking spacewarp */
44:
45: #define EOT '\004'
46: #define LF '\n'
47: #define DEL '\177'
48:
49: #define ME 'I'
50: #define SNAKEHEAD 'S'
51: #define SNAKETAIL 's'
52: #define TREASURE '$'
53: #define GOAL '#'
54:
55: #define BSIZE 80
56:
57: struct point you;
58: struct point money;
59: struct point finish;
60: struct point snake[6];
61:
62: int loot, penalty;
63: int long tl, tm=0L;
64: int argcount;
65: char **argval;
66: int moves;
67: static char str[BSIZE];
68: char stri[BSIZE];
69: char *p;
70: char ch, savec;
71: char *kl, *kr, *ku, *kd;
72: int fast=1;
73: int repeat=1;
74: long tv;
75: char *tn;
76:
77: main(argc,argv)
78: int argc;
79: char **argv;
80: {
81: int i,k;
82: int j;
83: long time();
84: int stop();
85: extern char _sobuf[];
86:
87: argcount = argc;
88: argval = argv;
89: penalty = loot = 0;
90: getcap();
91: ccnt -= 2; lcnt -= 2; /* compensate for border */
92: busy();
93: time(&tv);
94:
95: for (i=1; i<argc; i++) {
96: switch(argv[i][1]) {
97: case 'd':
98: sscanf(argv[1], "-d%ld", &tv);
99: break;
100: case 'w': /* width */
101: case 'c': /* columns */
102: ccnt = atoi(argv[i]+2);
103: break;
104: case 'l': /* length */
105: case 'h': /* height */
106: case 'r': /* rows */
107: lcnt = atoi(argv[i]+2);
108: break;
109: default:
110: printf("bad option %s\n", argv[1]);
111: }
112: }
113:
114: srand((int)tv);
115: setbuf(stdout,_sobuf);
116: i = ((lcnt < ccnt) ? lcnt : ccnt); /* min screen edge */
117: if (i < 4) {
118: printf("Screen too small for a fair game\n");
119: done();
120: }
121: /*
122: * chunk is the amount of money the user gets for each $.
123: * The formula below tries to be fair for various screen sizes.
124: * We only pay attention to the smaller of the 2 edges, since
125: * that seems to be the bottleneck.
126: * This formula is a hyperbola which includes the following points:
127: * (24, $25) (original scoring algorithm)
128: * (12, $40) (experimentally derived by the "feel")
129: * (48, $15) (a guess)
130: * This will give a 4x4 screen $99/shot. We don't allow anything
131: * smaller than 4x4 because there is a 3x3 game where you can win
132: * an infinite amount of money.
133: */
134: if (i < 12) i = 12; /* otherwise it isn't fair */
135: /*
136: * Compensate for border. This really changes the game since
137: * the screen is two squares smaller but we want the default
138: * to be $25, and the high scores on small screens were a bit
139: * much anyway.
140: */
141: i += 2;
142: chunk = (675.0 / (i+6)) + 2.5; /* min screen edge */
143:
144: signal (SIGINT, stop);
145: putpad(TI); /* String to begin programs that use cm */
146: putpad(KS); /* Put terminal in keypad transmit mode */
147:
148: random(&finish);
149: random(&you);
150: random(&money);
151: random(&snake[0]);
152:
153: if ((orig.sg_ospeed < B9600) ||
154: ((! CM) && (! TA))) fast=0;
155: for(i=1;i<6;i++)
156: chase (&snake[i], &snake[i-1]);
157: setup();
158: mainloop();
159: }
160:
161: /* Main command loop */
162: mainloop()
163: {
164: int j, k;
165:
166: for (;;) {
167: int c,lastc,match;
168:
169: move(&you);
170: fflush(stdout);
171: if (((c = getchar() & 0177) <= '9') && (c >= '0')) {
172: ungetc(c,stdin);
173: j = scanf("%d",&repeat);
174: c = getchar() & 0177;
175: } else {
176: if (c != '.') repeat = 1;
177: }
178: if (c == '.') {
179: c = lastc;
180: }
181: if ((Klength > 0) &&
182: (c == *KL || c == *KR || c == *KU || c == *KD)) {
183: savec = c;
184: match = 0;
185: kl = KL;
186: kr = KR;
187: ku = KU;
188: kd = KD;
189: for (j=Klength;j>0;j--){
190: if (match != 1) {
191: match = 0;
192: if (*kl++ == c) {
193: ch = 'h';
194: match++;
195: }
196: if (*kr++ == c) {
197: ch = 'l';
198: match++;
199: }
200: if (*ku++ == c) {
201: ch = 'k';
202: match++;
203: }
204: if (*kd++ == c) {
205: ch = 'j';
206: match++;
207: }
208: if (match == 0) {
209: ungetc(c,stdin);
210: ch = savec;
211: /* Oops!
212: * This works if we figure it out on second character.
213: */
214: break;
215: }
216: }
217: savec = c;
218: if(j != 1) c = getchar() & 0177;
219: }
220: c = ch;
221: }
222: if (!fast) flushi();
223: lastc = c;
224: switch (c){
225: case CTRL(z):
226: case CTRL(c):
227: suspend();
228: continue;
229: case EOT:
230: case 'x':
231: case 0177: /* del or end of file */
232: ll();
233: length(moves);
234: logit("quit");
235: done();
236: case '!':
237: cook();
238: putchar('\n');
239: putchar(c);
240: fflush(stdout);
241: j = read(0,stri,BSIZE);
242: stri[j] = 0;
243: if (fork() == 0) {
244: setuid(getuid());
245: system(stri);
246: } else
247: wait(0);
248: printf("READY?\n");
249: fflush(stdout);
250: raw();
251: c = getchar();
252: ungetc(c,stdin);
253: putpad(KS);
254: putpad(TI);
255: point(&cursor,0,lcnt-1);
256: case CTRL(l):
257: setup();
258: winnings(cashvalue);
259: continue;
260: case 'p':
261: case 'd':
262: snap();
263: continue;
264: case 'w':
265: spacewarp(0);
266: continue;
267: case 'A':
268: repeat = you.col;
269: c = 'h';
270: break;
271: case 'H':
272: case 'S':
273: repeat = you.col - money.col;
274: c = 'h';
275: break;
276: case 'T':
277: repeat = you.line;
278: c = 'k';
279: break;
280: case 'K':
281: case 'E':
282: repeat = you.line - money.line;
283: c = 'k';
284: break;
285: case 'P':
286: repeat = ccnt - 1 - you.col;
287: c = 'l';
288: break;
289: case 'L':
290: case 'F':
291: repeat = money.col - you.col;
292: c = 'l';
293: break;
294: case 'B':
295: repeat = lcnt - 1 - you.line;
296: c = 'j';
297: break;
298: case 'J':
299: case 'C':
300: repeat = money.line - you.line;
301: c = 'j';
302: break;
303: }
304: for(k=1;k<=repeat;k++){
305: moves++;
306: switch(c) {
307: case 's':
308: case 'h':
309: case '\b':
310: if (you.col >0) {
311: if((fast)||(k == 1))
312: pchar(&you,' ');
313: you.col--;
314: if((fast) || (k == repeat) ||
315: (you.col == 0))
316: pchar(&you,ME);
317: }
318: break;
319: case 'f':
320: case 'l':
321: case ' ':
322: if (you.col < ccnt-1) {
323: if((fast)||(k == 1))
324: pchar(&you,' ');
325: you.col++;
326: if((fast) || (k == repeat) ||
327: (you.col == ccnt-1))
328: pchar(&you,ME);
329: }
330: break;
331: case CTRL(p):
332: case 'e':
333: case 'k':
334: case 'i':
335: if (you.line > 0) {
336: if((fast)||(k == 1))
337: pchar(&you,' ');
338: you.line--;
339: if((fast) || (k == repeat) ||
340: (you.line == 0))
341: pchar(&you,ME);
342: }
343: break;
344: case CTRL(n):
345: case 'c':
346: case 'j':
347: case LF:
348: case 'm':
349: if (you.line+1 < lcnt) {
350: if((fast)||(k == 1))
351: pchar(&you,' ');
352: you.line++;
353: if((fast) || (k == repeat) ||
354: (you.line == lcnt-1))
355: pchar(&you,ME);
356: }
357: break;
358: }
359:
360: if (same(&you,&money))
361: {
362: char xp[20];
363: struct point z;
364: loot += 25;
365: if(k < repeat)
366: pchar(&you,' ');
367: do {
368: random(&money);
369: } while (money.col == finish.col && money.line == finish.line ||
370: money.col < 5 && money.line == 0 ||
371: money.col == you.col && money.line == you.line);
372: pchar(&money,TREASURE);
373: winnings(cashvalue);
374: continue;
375: }
376: if (same(&you,&finish))
377: {
378: win(&finish);
379: ll();
380: cook();
381: printf("You have won with $%d.\n",cashvalue);
382: fflush(stdout);
383: logit("won");
384: post(cashvalue,0);
385: length(moves);
386: done(0);
387: }
388: if (pushsnake())break;
389: }
390: fflush(stdout);
391: }
392: }
393:
394: setup(){ /*
395: * setup the board
396: */
397: int i;
398:
399: clear();
400: pchar(&you,ME);
401: pchar(&finish,GOAL);
402: pchar(&money,TREASURE);
403: for(i=1; i<6; i++) {
404: pchar(&snake[i],SNAKETAIL);
405: }
406: pchar(&snake[0], SNAKEHEAD);
407: drawbox();
408: fflush(stdout);
409: }
410:
411: drawbox()
412: {
413: register int i;
414: struct point p;
415:
416: p.line = -1;
417: for (i= 0; i<ccnt; i++) {
418: p.col = i;
419: pchar(&p, '-');
420: }
421: p.col = ccnt;
422: for (i= -1; i<=lcnt; i++) {
423: p.line = i;
424: pchar(&p, '|');
425: }
426: p.col = -1;
427: for (i= -1; i<=lcnt; i++) {
428: p.line = i;
429: pchar(&p, '|');
430: }
431: p.line = lcnt;
432: for (i= 0; i<ccnt; i++) {
433: p.col = i;
434: pchar(&p, '-');
435: }
436: }
437:
438:
439: random(sp)
440: struct point *sp;
441: {
442: register int issame;
443: struct point p;
444: register int i;
445:
446: sp->col = sp->line = -1; /* impossible */
447: do {
448: issame = 0;
449: p.col = ((rand()>>8) & 0377)% ccnt;
450: p.line = ((rand()>>8) & 0377)% lcnt;
451:
452: /* make sure it's not on top of something else */
453: if (p.line == 0 && p.col <5) issame++;
454: if(same(&p, &you)) issame++;
455: if(same(&p, &money)) issame++;
456: if(same(&p, &finish)) issame++;
457: for (i=0; i<5; i++)
458: if(same(&p, &snake[i])) issame++;
459:
460: } while (issame);
461: *sp = p;
462: }
463:
464: busy()
465: {
466: FILE *pip, *popen();
467: char c;
468: int b,r;
469: float a;
470:
471: #ifdef CHECKBUSY
472: if (! strcmp (argval[0], "test")) return;
473: if ((access(BUSY,1) != 0) || (pip = popen(BUSY,"r")) == NULL){
474: printf("Sorry, no snake just now.\n");
475: done();
476: }
477: fscanf(pip,"%d",&b);
478: pclose(pip);
479: if (b > 20) {
480: printf("Sorry, the system is too heavily loaded right now.\n");
481: done();
482: }
483: nice(b);
484: #endif
485: }
486:
487: post(score, flag)
488: int score, flag;
489: {
490: int rawscores;
491: short uid = getuid();
492: short oldbest=0;
493: short allbwho=0, allbscore=0;
494: struct passwd *p, *getpwuid();
495:
496: /*
497: * Neg uid, 0, and 1 cannot have scores recorded.
498: */
499: if ((uid=getuid()) > 1 && (rawscores=open(SNAKERAWSCORES,2))>=0) {
500: /* Figure out what happened in the past */
501: read(rawscores, &allbscore, sizeof(short));
502: read(rawscores, &allbwho, sizeof(short));
503: lseek(rawscores, ((long)uid)*sizeof(short), 0);
504: read(rawscores, &oldbest, sizeof(short));
505: if (flag) return (score > oldbest ? 1 : 0);
506:
507: /* Update this jokers best */
508: if (score > oldbest) {
509: lseek(rawscores, ((long)uid)*sizeof(short), 0);
510: write(rawscores, &score, sizeof(short));
511: printf("You bettered your previous best of $%d\n", oldbest);
512: } else
513: printf("Your best to date is $%d\n", oldbest);
514:
515: /* See if we have a new champ */
516: p = getpwuid(allbwho);
517: if (p == NULL || score > allbscore) {
518: lseek(rawscores, (long)0, 0);
519: write(rawscores, &score, sizeof(short));
520: write(rawscores, &uid, sizeof(short));
521: if (p != NULL)
522: printf("You beat %s's old record of $%d!\n", p->pw_name, allbscore);
523: else
524: printf("You set a new record!\n");
525: } else
526: printf("The highest is %s with $%d\n", p->pw_name, allbscore);
527: close(rawscores);
528: } else
529: if (!flag)
530: printf("Unable to post score.\n");
531: return (1);
532: }
533:
534: /*
535: * Flush typeahead to keep from buffering a bunch of chars and then
536: * overshooting. This loses horribly at 9600 baud, but works nicely
537: * if the terminal gets behind.
538: */
539: flushi()
540: {
541: stty(0, &new);
542: }
543: int mx [8] = {
544: 0, 1, 1, 1, 0,-1,-1,-1};
545: int my [8] = {
546: -1,-1, 0, 1, 1, 1, 0,-1};
547: float absv[8]= {
548: 1, 1.4, 1, 1.4, 1, 1.4, 1, 1.4
549: };
550: int oldw=0;
551: chase (np, sp)
552: struct point *sp, *np;
553: {
554: /* this algorithm has bugs; otherwise the
555: snake would get too good */
556: struct point d;
557: int w, i, wt[8];
558: double sqrt(), v1, v2, vp, max;
559: point(&d,you.col-sp->col,you.line-sp->line);
560: v1 = sqrt( (double) (d.col*d.col + d.line*d.line) );
561: w=0;
562: max=0;
563: for(i=0; i<8; i++)
564: {
565: vp = d.col*mx[i] + d.line*my[i];
566: v2 = absv[i];
567: if (v1>0)
568: vp = ((double)vp)/(v1*v2);
569: else vp=1.0;
570: if (vp>max)
571: {
572: max=vp;
573: w=i;
574: }
575: }
576: for(i=0; i<8; i++)
577: {
578: point(&d,sp->col+mx[i],sp->line+my[i]);
579: wt[i]=0;
580: if (d.col<0 || d.col>=ccnt || d.line<0 || d.line>=lcnt)
581: continue;
582: if (d.line == 0 && d.col < 5) continue;
583: if (same(&d,&money)) continue;
584: if (same(&d,&finish)) continue;
585: wt[i]= i==w ? loot/10 : 1;
586: if (i==oldw) wt [i] += loot/20;
587: }
588: for(w=i=0; i<8; i++)
589: w+= wt[i];
590: vp = (( rand() >> 6 ) & 01777) %w;
591: for(i=0; i<8; i++)
592: if (vp <wt[i])
593: break;
594: else
595: vp -= wt[i];
596: if (i==8) {
597: printf("failure\n");
598: i=0;
599: while (wt[i]==0) i++;
600: }
601: oldw=w=i;
602: point(np,sp->col+mx[w],sp->line+my[w]);
603: }
604:
605: spacewarp(w)
606: int w;{
607: struct point p;
608: int j;
609:
610: random(&you);
611: point(&p,COLUMNS/2 - 8,LINES/2 - 1);
612: if (p.col < 0)
613: p.col = 0;
614: if (p.line < 0)
615: p.line = 0;
616: if (w) {
617: sprintf(str,"BONUS!!!");
618: loot = loot - penalty;
619: penalty = 0;
620: } else {
621: sprintf(str,"SPACE WARP!!!");
622: penalty += loot/PENALTY;
623: }
624: for(j=0;j<3;j++){
625: clear();
626: delay(5);
627: aprintf(&p,str);
628: delay(10);
629: }
630: setup();
631: winnings(cashvalue);
632: }
633: snap()
634: {
635: struct point p;
636: int i;
637:
638: if(you.line < 3){
639: pchar(point(&p,you.col,0),'-');
640: }
641: if(you.line > lcnt-4){
642: pchar(point(&p,you.col,lcnt-1),'_');
643: }
644: if(you.col < 10){
645: pchar(point(&p,0,you.line),'(');
646: }
647: if(you.col > ccnt-10){
648: pchar(point(&p,ccnt-1,you.line),')');
649: }
650: if (! stretch(&money)) if (! stretch(&finish)) delay(10);
651: if(you.line < 3){
652: point(&p,you.col,0);
653: remove(&p);
654: }
655: if(you.line > lcnt-4){
656: point(&p,you.col,lcnt-1);
657: remove(&p);
658: }
659: if(you.col < 10){
660: point(&p,0,you.line);
661: remove(&p);
662: }
663: if(you.col > ccnt-10){
664: point(&p,ccnt-1,you.line);
665: remove(&p);
666: }
667: fflush(stdout);
668: }
669: stretch(ps)
670: struct point *ps;{
671: struct point p;
672:
673: point(&p,you.col,you.line);
674: if(abs(ps->col-you.col) < 6){
675: if(you.line < ps->line){
676: for (p.line = you.line+1;p.line <= ps->line;p.line++)
677: pchar(&p,'v');
678: delay(10);
679: for (;p.line > you.line;p.line--)
680: remove(&p);
681: } else {
682: for (p.line = you.line-1;p.line >= ps->line;p.line--)
683: pchar(&p,'^');
684: delay(10);
685: for (;p.line < you.line;p.line++)
686: remove(&p);
687: }
688: return(1);
689: } else if(abs(ps->line-you.line) < 3){
690: p.line = you.line;
691: if(you.col < ps->col){
692: for (p.col = you.col+1;p.col <= ps->col;p.col++)
693: pchar(&p,'>');
694: delay(10);
695: for (;p.col > you.col;p.col--)
696: remove(&p);
697: } else {
698: for (p.col = you.col-1;p.col >= ps->col;p.col--)
699: pchar(&p,'<');
700: delay(10);
701: for (;p.col < you.col;p.col++)
702: remove(&p);
703: }
704: return(1);
705: }
706: return(0);
707: }
708:
709: surround(ps)
710: struct point *ps;{
711: struct point x;
712: int i,j;
713:
714: if(ps->col == 0)ps->col++;
715: if(ps->line == 0)ps->line++;
716: if(ps->line == LINES -1)ps->line--;
717: if(ps->col == COLUMNS -1)ps->col--;
718: aprintf(point(&x,ps->col-1,ps->line-1),"/*\\\r* *\r\\*/");
719: for (j=0;j<20;j++){
720: pchar(ps,'@');
721: delay(1);
722: pchar(ps,' ');
723: delay(1);
724: }
725: if (post(cashvalue,1)) {
726: aprintf(point(&x,ps->col-1,ps->line-1)," \ro.o\r\\_/");
727: delay(6);
728: aprintf(point(&x,ps->col-1,ps->line-1)," \ro.-\r\\_/");
729: delay(6);
730: }
731: aprintf(point(&x,ps->col-1,ps->line-1)," \ro.o\r\\_/");
732: }
733: win(ps)
734: struct point *ps;
735: {
736: struct point x;
737: int j,k;
738: int boxsize; /* actually diameter of box, not radius */
739:
740: boxsize = fast ? 10 : 4;
741: point(&x,ps->col,ps->line);
742: for(j=1;j<boxsize;j++){
743: for(k=0;k<j;k++){
744: pchar(&x,'#');
745: x.line--;
746: }
747: for(k=0;k<j;k++){
748: pchar(&x,'#');
749: x.col++;
750: }
751: j++;
752: for(k=0;k<j;k++){
753: pchar(&x,'#');
754: x.line++;
755: }
756: for(k=0;k<j;k++){
757: pchar(&x,'#');
758: x.col--;
759: }
760: }
761: fflush(stdout);
762: }
763:
764: pushsnake()
765: {
766: int i, bonus;
767: int issame = 0;
768:
769: /*
770: * My manual says times doesn't return a value. Furthermore, the
771: * snake should get his turn every time no matter if the user is
772: * on a fast terminal with typematic keys or not.
773: * So I have taken the call to times out.
774: */
775: for(i=4; i>=0; i--)
776: if (same(&snake[i], &snake[5]))
777: issame++;
778: if (!issame)
779: pchar(&snake[5],' ');
780: for(i=4; i>=0; i--)
781: snake[i+1]= snake[i];
782: chase(&snake[0], &snake[1]);
783: pchar(&snake[1],SNAKETAIL);
784: pchar(&snake[0],SNAKEHEAD);
785: for(i=0; i<6; i++)
786: {
787: if (same(&snake[i],&you))
788: {
789: surround(&you);
790: i = (cashvalue) % 10;
791: bonus = ((rand()>>8) & 0377)% 10;
792: ll();
793: printf("%d\n", bonus);
794: delay(30);
795: if (bonus == i) {
796: spacewarp(1);
797: logit("bonus");
798: flushi();
799: return(1);
800: }
801: if ( loot >= penalty ){
802: printf("You and your $%d have been eaten\n",cashvalue);
803: } else {
804: printf("The snake ate you. You owe $%d.\n",-cashvalue);
805: }
806: logit("eaten");
807: length(moves);
808: done();
809: }
810: }
811: return(0);
812: }
813:
814: remove(sp)
815: struct point *sp;
816: {
817: int j;
818:
819: if (same(sp,&money)) {
820: pchar(sp,TREASURE);
821: return(2);
822: }
823: if (same(sp,&finish)) {
824: pchar(sp,GOAL);
825: return(3);
826: }
827: if (same(sp,&snake[0])) {
828: pchar(sp,SNAKEHEAD);
829: return(4);
830: }
831: for(j=1;j<6;j++){
832: if(same(sp,&snake[j])){
833: pchar(sp,SNAKETAIL);
834: return(4);
835: }
836: }
837: if ((sp->col < 4) && (sp->line == 0)){
838: winnings(cashvalue);
839: if((you.line == 0) && (you.col < 4)) pchar(&you,ME);
840: return(5);
841: }
842: if (same(sp,&you)) {
843: pchar(sp,ME);
844: return(1);
845: }
846: pchar(sp,' ');
847: return(0);
848: }
849: winnings(won)
850: int won;
851: {
852: struct point p;
853:
854: p.line = p.col = 1;
855: if(won>0){
856: move(&p);
857: printf("$%d",won);
858: }
859: }
860:
861: stop(){
862: signal(SIGINT,1);
863: ll();
864: length(moves);
865: done();
866: }
867:
868: suspend()
869: {
870: char *sh;
871:
872: cook();
873: #ifdef SIGTSTP
874: kill(getpid(), SIGTSTP);
875: #else
876: sh = getenv("SHELL");
877: if (sh == NULL)
878: sh = "/bin/sh";
879: system(sh);
880: #endif
881: raw();
882: setup();
883: winnings(cashvalue);
884: }
885:
886: length(num)
887: int num;
888: {
889: printf("You made %d moves.\n",num);
890: }
891:
892: logit(msg)
893: char *msg;
894: {
895: FILE *logfile;
896: long t;
897:
898: if ((logfile=fopen(LOGFILE, "a")) != NULL) {
899: time(&t);
900: fprintf(logfile, "%s $%d %dx%d %s %s", getlogin(), cashvalue, lcnt, ccnt, msg, ctime(&t));
901: fclose(logfile);
902: }
903: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.