xref: /csrg-svn/games/larn/fortune.c (revision 50017)
1*50017Ssellgren /*-
2*50017Ssellgren  * Copyright (c) 1991 The Regents of the University of California.
3*50017Ssellgren  * All rights reserved.
4*50017Ssellgren  *
5*50017Ssellgren  * %sccs.include.redist.c%
6*50017Ssellgren  */
7*50017Ssellgren 
8*50017Ssellgren #ifndef lint
9*50017Ssellgren static char sccsid[] = "@(#)fortune.c	5.4 (Berkeley) 06/06/91";
10*50017Ssellgren #endif /* not lint */
11*50017Ssellgren 
1236983Sbostic /* fortune.c		 Larn is copyrighted 1986 by Noah Morgan. */
13*50017Ssellgren 
1436983Sbostic #include <sys/types.h>
1536983Sbostic #include <sys/stat.h>
1636983Sbostic #include <fcntl.h>
17*50017Ssellgren #include <unistd.h>
18*50017Ssellgren #include <stdlib.h>
19*50017Ssellgren #include "header.h"
20*50017Ssellgren #include "pathnames.h"
2136983Sbostic 
2236983Sbostic /*
23*50017Ssellgren  * function to return a random fortune from the fortune file
2436983Sbostic  */
2536983Sbostic 
26*50017Ssellgren char *
27*50017Ssellgren fortune()
28*50017Ssellgren {
29*50017Ssellgren 	static int fd = -1;	/* true if we have load the fortune info */
30*50017Ssellgren 	static int nlines;	/* # lines in fortune database */
31*50017Ssellgren 	register int tmp;
3236983Sbostic 	register char *p;
33*50017Ssellgren 	char *base, **flines;
34*50017Ssellgren 	struct stat sb;
3536983Sbostic 
36*50017Ssellgren 	if (fd != -1)
37*50017Ssellgren 		return (flines[random() % nlines]);
3836983Sbostic 
39*50017Ssellgren 	if ((fd = open(_PATH_FORTS, O_RDONLY)) < 0)
40*50017Ssellgren 		return (NULL);
4136983Sbostic 
42*50017Ssellgren 	/* Find out how big fortune file is and get memory for it. */
43*50017Ssellgren 	if ((fstat(fd, &sb) < 0) ||
44*50017Ssellgren 	    ((base = malloc(1 + sb.st_size)) == NULL)) {
45*50017Ssellgren 		(void)close(fd);
46*50017Ssellgren 		goto bad;
47*50017Ssellgren 	}
4836983Sbostic 
49*50017Ssellgren 	/* Read in the entire fortune file. */
50*50017Ssellgren 	if (read(fd, base, sb.st_size) != sb.st_size) {
51*50017Ssellgren 		free(base);
52*50017Ssellgren 		goto bad;
53*50017Ssellgren 	}
54*50017Ssellgren 	base[sb.st_size] = '\0';	/* Final NULL termination. */
5536983Sbostic 
56*50017Ssellgren 	(void)close(fd);
57*50017Ssellgren 
58*50017Ssellgren 
59*50017Ssellgren 	/*
60*50017Ssellgren 	 * Count up all the lines (and NULL terminate) to know memory
61*50017Ssellgren 	 * needs.
62*50017Ssellgren 	 */
63*50017Ssellgren 	for (p = base; p < base + sb.st_size; p++)
64*50017Ssellgren 		if (*p == '\n') {
65*50017Ssellgren 			*p = '\0';
66*50017Ssellgren 			++nlines;
6736983Sbostic 		}
6836983Sbostic 
69*50017Ssellgren 	if (nlines <= 0) {
70*50017Ssellgren 		free(base);
71*50017Ssellgren 		goto bad;
7236983Sbostic 	}
73*50017Ssellgren 
74*50017Ssellgren 	/* Get memory for array of pointers to each fortune. */
75*50017Ssellgren 	if ((flines = malloc(nlines * sizeof(char *))) == NULL) {
76*50017Ssellgren 		free(base);
77*50017Ssellgren 		goto bad;
78*50017Ssellgren 	}
79*50017Ssellgren 
80*50017Ssellgren 	/* Now assign each pointer to a line. */
81*50017Ssellgren 	for (p = base, tmp = 0; tmp < nlines; ++tmp) {
82*50017Ssellgren 		flines[tmp] = p;
83*50017Ssellgren 		while (*p++);
84*50017Ssellgren 	}
85*50017Ssellgren 
86*50017Ssellgren 	return (flines[random() % nlines]);
87*50017Ssellgren 
88*50017Ssellgren bad:	fd = -1;
89*50017Ssellgren 	return (NULL);
90*50017Ssellgren }
91