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 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 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)); 133*40ee778cSRob 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"); 152*40ee778cSRob 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*40ee778cSRob Gill free(buffer) 174338b8dc3SIngo Weinhold return 0; 175338b8dc3SIngo Weinhold } 176