1338b8dc3SIngo Weinhold /*
2c6106a59SAxel Dörfler * Copyright 2002-2009, Haiku. All rights reserved.
33cb77ecfSAxel Dörfler * Distributed under the terms of the MIT License.
4338b8dc3SIngo Weinhold */
5338b8dc3SIngo Weinhold
63cb77ecfSAxel Dörfler
73cb77ecfSAxel Dörfler #include <dirent.h>
83cb77ecfSAxel Dörfler #include <errno.h>
93cb77ecfSAxel Dörfler #include <fcntl.h>
10338b8dc3SIngo Weinhold #include <stdlib.h>
11338b8dc3SIngo Weinhold #include <stdio.h>
123cb77ecfSAxel Dörfler #include <string.h>
13338b8dc3SIngo Weinhold #include <sys/stat.h>
143cb77ecfSAxel Dörfler #include <unistd.h>
15338b8dc3SIngo Weinhold
16c6106a59SAxel Dörfler #include <FindDirectory.h>
17338b8dc3SIngo Weinhold #include <OS.h>
18338b8dc3SIngo Weinhold
193cb77ecfSAxel Dörfler
203cb77ecfSAxel Dörfler static int
choose_file(const char * path)213cb77ecfSAxel Dörfler choose_file(const char *path)
22338b8dc3SIngo Weinhold {
233cb77ecfSAxel Dörfler struct dirent *dirent;
243cb77ecfSAxel Dörfler int count = 0;
253cb77ecfSAxel Dörfler int chosen;
263cb77ecfSAxel Dörfler
273cb77ecfSAxel Dörfler DIR *dir = opendir(path);
283cb77ecfSAxel Dörfler if (dir == NULL)
293cb77ecfSAxel Dörfler return -1;
303cb77ecfSAxel Dörfler
313cb77ecfSAxel Dörfler // count directory entries
323cb77ecfSAxel Dörfler
333cb77ecfSAxel Dörfler while ((dirent = readdir(dir)) != NULL) {
343cb77ecfSAxel Dörfler if (dirent->d_name[0] == '.')
353cb77ecfSAxel Dörfler continue;
363cb77ecfSAxel Dörfler
373cb77ecfSAxel Dörfler count++;
383cb77ecfSAxel Dörfler }
393cb77ecfSAxel Dörfler
40c5666be3SPhilippe Saint-Pierre if (count == 0) {
41c5666be3SPhilippe Saint-Pierre closedir(dir);
42c6106a59SAxel Dörfler return -1;
43c5666be3SPhilippe Saint-Pierre }
443cb77ecfSAxel Dörfler // choose and open entry
453cb77ecfSAxel Dörfler
463cb77ecfSAxel Dörfler chosen = rand() % count;
473cb77ecfSAxel Dörfler count = 0;
483cb77ecfSAxel Dörfler rewinddir(dir);
493cb77ecfSAxel Dörfler
503cb77ecfSAxel Dörfler while ((dirent = readdir(dir)) != NULL) {
513cb77ecfSAxel Dörfler if (dirent->d_name[0] == '.')
523cb77ecfSAxel Dörfler continue;
533cb77ecfSAxel Dörfler
543cb77ecfSAxel Dörfler if (chosen <= count) {
553cb77ecfSAxel Dörfler char name[PATH_MAX];
56338b8dc3SIngo Weinhold int fd;
573cb77ecfSAxel Dörfler
583cb77ecfSAxel Dörfler // build full path
593cb77ecfSAxel Dörfler strlcpy(name, path, sizeof(name));
603cb77ecfSAxel Dörfler strlcat(name, "/", sizeof(name));
613cb77ecfSAxel Dörfler strlcat(name, dirent->d_name, sizeof(name));
623cb77ecfSAxel Dörfler
633cb77ecfSAxel Dörfler fd = open(name, O_RDONLY);
643cb77ecfSAxel Dörfler if (fd >= 0) {
653cb77ecfSAxel Dörfler closedir(dir);
663cb77ecfSAxel Dörfler return fd;
673cb77ecfSAxel Dörfler }
683cb77ecfSAxel Dörfler }
693cb77ecfSAxel Dörfler count++;
703cb77ecfSAxel Dörfler }
713cb77ecfSAxel Dörfler
723cb77ecfSAxel Dörfler closedir(dir);
733cb77ecfSAxel Dörfler return -1;
743cb77ecfSAxel Dörfler }
753cb77ecfSAxel Dörfler
763cb77ecfSAxel Dörfler
773cb77ecfSAxel Dörfler int
main(int argc,char ** argv)783cb77ecfSAxel Dörfler main(int argc, char **argv)
793cb77ecfSAxel Dörfler {
80c6106a59SAxel Dörfler char path[PATH_MAX] = {'\0'};
81c6106a59SAxel Dörfler const char *file = path;
823cb77ecfSAxel Dörfler int fd;
833cb77ecfSAxel Dörfler char *buffer;
843cb77ecfSAxel Dörfler unsigned start, i;
853cb77ecfSAxel Dörfler unsigned count;
86338b8dc3SIngo Weinhold struct stat stat;
87338b8dc3SIngo Weinhold
883cb77ecfSAxel Dörfler srand(system_time() % INT_MAX);
893cb77ecfSAxel Dörfler
903cb77ecfSAxel Dörfler if (argc > 1) {
913cb77ecfSAxel Dörfler // if there are arguments, choose one randomly
923cb77ecfSAxel Dörfler file = argv[1 + (rand() % (argc - 1))];
93c6106a59SAxel Dörfler } else if (find_directory(B_SYSTEM_DATA_DIRECTORY, -1, false, path,
94c6106a59SAxel Dörfler sizeof(path)) == B_OK) {
95c6106a59SAxel Dörfler strlcat(path, "/fortunes", sizeof(path));
963cb77ecfSAxel Dörfler }
973cb77ecfSAxel Dörfler
983cb77ecfSAxel Dörfler fd = open(file, O_RDONLY, 0);
99338b8dc3SIngo Weinhold if (fd < 0) {
1003cb77ecfSAxel Dörfler fprintf(stderr, "Couldn't open %s: %s\n", file, strerror(errno));
1013cb77ecfSAxel Dörfler return 1;
102338b8dc3SIngo Weinhold }
103338b8dc3SIngo Weinhold
1043cb77ecfSAxel Dörfler if (fstat(fd, &stat) < 0) {
1053cb77ecfSAxel Dörfler fprintf(stderr, "stat() failed: %s\n", strerror(errno));
1063cb77ecfSAxel Dörfler return 1;
107338b8dc3SIngo Weinhold }
108338b8dc3SIngo Weinhold
1093cb77ecfSAxel Dörfler if (S_ISDIR(stat.st_mode)) {
110338b8dc3SIngo Weinhold close(fd);
111338b8dc3SIngo Weinhold
1123cb77ecfSAxel Dörfler fd = choose_file(file);
1133cb77ecfSAxel Dörfler if (fd < 0) {
1143cb77ecfSAxel Dörfler fprintf(stderr, "Could not find any fortune file.\n");
1153cb77ecfSAxel Dörfler return 1;
116338b8dc3SIngo Weinhold }
117338b8dc3SIngo Weinhold
1183cb77ecfSAxel Dörfler if (fstat(fd, &stat) < 0) {
1193cb77ecfSAxel Dörfler fprintf(stderr, "stat() failed: %s\n", strerror(errno));
1203cb77ecfSAxel Dörfler return 1;
1213cb77ecfSAxel Dörfler }
1223cb77ecfSAxel Dörfler }
1233cb77ecfSAxel Dörfler
1243cb77ecfSAxel Dörfler buffer = malloc(stat.st_size + 1);
1253cb77ecfSAxel Dörfler if (buffer == NULL) {
1263cb77ecfSAxel Dörfler fprintf(stderr, "Not enough memory.\n");
1273cb77ecfSAxel Dörfler return 1;
1283cb77ecfSAxel Dörfler }
1293cb77ecfSAxel Dörfler
1303cb77ecfSAxel Dörfler if (read(fd, buffer, stat.st_size) < 0) {
1313cb77ecfSAxel Dörfler fprintf(stderr, "Could not read from fortune file: %s\n",
1323cb77ecfSAxel Dörfler strerror(errno));
13340ee778cSRob Gill free(buffer);
134338b8dc3SIngo Weinhold return -1;
135338b8dc3SIngo Weinhold }
136338b8dc3SIngo Weinhold
1373cb77ecfSAxel Dörfler buffer[stat.st_size] = '\0';
1383cb77ecfSAxel Dörfler close(fd);
139338b8dc3SIngo Weinhold
1403cb77ecfSAxel Dörfler // count fortunes
141338b8dc3SIngo Weinhold
1423cb77ecfSAxel Dörfler count = 0;
1433cb77ecfSAxel Dörfler for (i = 0; i < stat.st_size - 2; i++) {
1443cb77ecfSAxel Dörfler if (!strncmp(buffer + i, "\n%\n", 3)) {
1453cb77ecfSAxel Dörfler count++;
1463cb77ecfSAxel Dörfler i += 3;
1473cb77ecfSAxel Dörfler }
148338b8dc3SIngo Weinhold }
149338b8dc3SIngo Weinhold
1503cb77ecfSAxel Dörfler if (!count) {
1513cb77ecfSAxel Dörfler printf("Out of cookies...\n");
15240ee778cSRob Gill free(buffer);
1533cb77ecfSAxel Dörfler return 0;
1543cb77ecfSAxel Dörfler }
1553cb77ecfSAxel Dörfler
1563cb77ecfSAxel Dörfler count = rand() % count;
1573cb77ecfSAxel Dörfler start = 0;
1583cb77ecfSAxel Dörfler
1593cb77ecfSAxel Dörfler // find beginning & end
1603cb77ecfSAxel Dörfler for (i = 0; i < stat.st_size - 2; i++) {
1613cb77ecfSAxel Dörfler if (!strncmp(buffer + i, "\n%\n", 3)) {
1623cb77ecfSAxel Dörfler if (count-- <= 0) {
1633cb77ecfSAxel Dörfler buffer[i] = '\0';
164338b8dc3SIngo Weinhold break;
165338b8dc3SIngo Weinhold }
1663cb77ecfSAxel Dörfler
1673cb77ecfSAxel Dörfler i += 3;
1683cb77ecfSAxel Dörfler start = i;
1693cb77ecfSAxel Dörfler }
170338b8dc3SIngo Weinhold }
171338b8dc3SIngo Weinhold
1723cb77ecfSAxel Dörfler puts(buffer + start);
173*246caab5SRyan Leavengood free(buffer);
174338b8dc3SIngo Weinhold return 0;
175338b8dc3SIngo Weinhold }
176