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