00001
00002 #include <microfeed/microfeedconfiguration.h>
00003 #include <microfeed/microfeedmisc.h>
00004
00005 #include <stdlib.h>
00006 #include <string.h>
00007 #include <sys/types.h>
00008 #include <sys/stat.h>
00009 #include <fcntl.h>
00010 #include <unistd.h>
00011
00012 struct _MicrofeedConfiguration {
00013 char* providers_environment_directory;
00014 char* providers_home_directory;
00015 char* publishers_environment_directory;
00016 char* publishers_home_directory;
00017 char** providers;
00018 const char** provider_directories;
00019 char** provider_names;
00020 char** publishers;
00021 const char** publisher_directories;
00022 };
00023
00024 static void free_string_array(char** string_array);
00025 static void get_providers(MicrofeedConfiguration* configuration, const char* directory, unsigned int* length_pointer);
00026 static void get_publishers(MicrofeedConfiguration* configuration, const char* directory, unsigned int* length_pointer);
00027 static void update_providers(MicrofeedConfiguration* configuration);
00028 static void update_publishers(MicrofeedConfiguration* configuration);
00029
00030 MicrofeedConfiguration* microfeed_configuration_new(void) {
00031 MicrofeedConfiguration* configuration;
00032 char* directory;
00033 size_t length;
00034
00035 configuration = microfeed_memory_allocate(MicrofeedConfiguration);
00036 if ((directory = getenv("MICROFEED_PROVIDERS_DIRECTORY"))) {
00037 configuration->providers_environment_directory = strdup(directory);
00038 }
00039 if ((directory = getenv("MICROFEED_PUBLISHERS_DIRECTORY"))) {
00040 configuration->publishers_environment_directory = strdup(directory);
00041 }
00042 if ((directory = getenv("HOME"))) {
00043 length = strlen(directory);
00044 configuration->providers_home_directory = microfeed_memory_allocate_bytes(length + 22);
00045 memcpy(configuration->providers_home_directory, directory, length);
00046 memcpy(configuration->providers_home_directory + length, "/.microfeed/providers", 22);
00047 configuration->publishers_home_directory = microfeed_memory_allocate_bytes(length + 23);
00048 memcpy(configuration->publishers_home_directory, directory, length);
00049 memcpy(configuration->publishers_home_directory + length, "/.microfeed/publishers", 23);
00050 }
00051 configuration->providers = NULL;
00052 configuration->provider_directories = NULL;
00053 configuration->provider_names = NULL;
00054 configuration->publishers = NULL;
00055 configuration->publisher_directories = NULL;
00056
00057 return configuration;
00058 }
00059
00060 void microfeed_configuration_free(MicrofeedConfiguration* configuration) {
00061 microfeed_configuration_invalidate(configuration);
00062 free(configuration->providers_environment_directory);
00063 free(configuration->publishers_environment_directory);
00064 microfeed_memory_free(configuration->providers_home_directory);
00065 microfeed_memory_free(configuration->publishers_home_directory);
00066 microfeed_memory_free(configuration);
00067 }
00068
00069 void microfeed_configuration_invalidate(MicrofeedConfiguration* configuration) {
00070 free_string_array(configuration->providers);
00071 configuration->providers = NULL;
00072 free_string_array(configuration->provider_names);
00073 configuration->provider_names = NULL;
00074 free_string_array(configuration->publishers);
00075 configuration->publishers = NULL;
00076
00077 free(configuration->provider_directories);
00078 configuration->provider_directories = NULL;
00079 free(configuration->publisher_directories);
00080 configuration->publisher_directories = NULL;
00081 }
00082
00083 char** microfeed_configuration_get_providers(MicrofeedConfiguration* configuration) {
00084 if (!configuration->providers) {
00085 update_providers(configuration);
00086 }
00087
00088 return configuration->providers;
00089 }
00090
00091 const char* microfeed_configuration_get_provider_name(MicrofeedConfiguration* configuration, const char* provider_identifier) {
00092 char* name = NULL;
00093 int index;
00094 char* filename;
00095 int difference;
00096 int fd;
00097 char buffer[1024];
00098 size_t length;
00099 size_t i;
00100
00101 if (!configuration->providers) {
00102 update_providers(configuration);
00103 }
00104 if (configuration->providers) {
00105 for (index = 0; configuration->providers[index] && (difference = strcmp(configuration->providers[index], provider_identifier)) < 0; index++) {
00106 }
00107 if (!difference) {
00108 if (!configuration->provider_names[index]) {
00109 filename = microfeed_util_string_concatenate(configuration->provider_directories[index], "/", provider_identifier, NULL);
00110 if ((fd = open(filename, O_RDONLY)) != -1) {
00111 if ((length = read(fd, buffer, 1023)) > 0) {
00112 for (i = 0; i < length && buffer[i] != '\n' && buffer[i] != '\r'; i++) {
00113 }
00114 buffer[i] = 0;
00115 configuration->provider_names[index] = strdup(buffer);
00116 }
00117 close(fd);
00118 }
00119 free(filename);
00120 }
00121 name = configuration->provider_names[index];
00122 }
00123 }
00124
00125 return name;
00126 }
00127
00128 const char* microfeed_configuration_get_provider_directory(MicrofeedConfiguration* configuration, const char* provider_identifier) {
00129 const char* directory = NULL;
00130 unsigned int index;
00131 int difference;
00132
00133 if (!configuration->providers) {
00134 update_providers(configuration);
00135 }
00136 if (configuration->providers) {
00137 for (index = 0; configuration->providers[index] && (difference = strcmp(configuration->providers[index], provider_identifier)) < 0; index++) {
00138 }
00139 if (!difference) {
00140 directory = configuration->provider_directories[index];
00141 }
00142 }
00143
00144 return directory;
00145 }
00146
00147 const char* microfeed_configuration_get_publisher_directory(MicrofeedConfiguration* configuration, const char* publisher_identifier) {
00148 const char* directory = NULL;
00149 unsigned int index;
00150 int difference;
00151
00152 if (!configuration->publishers) {
00153 update_publishers(configuration);
00154 }
00155 if (configuration->publishers) {
00156 for (index = 0, difference = 1; configuration->publishers[index] && (difference = strcmp(configuration->publishers[index], publisher_identifier)) < 0; index++) {
00157 }
00158 if (!difference) {
00159 directory = configuration->publisher_directories[index];
00160 }
00161 }
00162
00163 return directory;
00164 }
00165
00166 const char* microfeed_configuration_get_default_publisher_directory(MicrofeedConfiguration* configuration) {
00167
00168 return (configuration->publishers_environment_directory ? configuration->publishers_environment_directory : configuration->publishers_home_directory);
00169 }
00170
00171 static void free_string_array(char** string_array) {
00172 unsigned int i;
00173
00174 if (string_array) {
00175 for (i = 0; string_array[i]; i++) {
00176 free(string_array[i]);
00177 }
00178 free(string_array);
00179 }
00180 }
00181
00182 static void get_providers(MicrofeedConfiguration* configuration, const char* directory, unsigned int* length_pointer) {
00183 DIR* dir;
00184 struct dirent* dirent;
00185 int i;
00186 int order;
00187
00188 if ((dir = opendir(directory))) {
00189 while ((dirent = readdir(dir))) {
00190 if (dirent->d_name[0] != '.') {
00191 for (i = 0; i < *length_pointer; i++) {
00192 if ((order = strcmp(configuration->providers[i], dirent->d_name)) >= 0) {
00193 break;
00194 }
00195 }
00196 if (i == *length_pointer || order != 0) {
00197 (*length_pointer)++;
00198 configuration->providers = (char**)realloc(configuration->providers, (*length_pointer + 1) * sizeof(char*));
00199 configuration->provider_directories = (const char**)realloc(configuration->provider_directories, *length_pointer * sizeof(char*));
00200 configuration->provider_names = (char**)realloc(configuration->provider_names, *length_pointer * sizeof(char*));
00201 if (i < *length_pointer) {
00202 memmove(configuration->providers + i + 1, configuration->providers + i, (*length_pointer - i - 1) * sizeof(char*));
00203 }
00204 configuration->providers[i] = strdup(dirent->d_name);
00205 configuration->provider_directories[i] = directory;
00206 configuration->provider_names[i] = NULL;
00207 configuration->providers[*length_pointer] = NULL;
00208 }
00209 }
00210 }
00211 closedir(dir);
00212 }
00213 }
00214
00215 static void get_publishers(MicrofeedConfiguration* configuration, const char* directory, unsigned int* length_pointer) {
00216 DIR* dir;
00217 struct dirent* dirent;
00218 int i;
00219 int order;
00220
00221 if ((dir = opendir(directory))) {
00222 while ((dirent = readdir(dir))) {
00223 if (dirent->d_name[0] != '.') {
00224 for (i = 0; i < *length_pointer; i++) {
00225 if ((order = strcmp(configuration->publishers[i], dirent->d_name)) >= 0) {
00226 break;
00227 }
00228 }
00229 if (i == *length_pointer || order != 0) {
00230 (*length_pointer)++;
00231 configuration->publishers = (char**)realloc(configuration->publishers, (*length_pointer + 1) * sizeof(char*));
00232 configuration->publisher_directories = (const char**)realloc(configuration->publisher_directories, *length_pointer * sizeof(char*));
00233 if (i < *length_pointer) {
00234 memmove(configuration->publishers + i + 1, configuration->publishers + i, (*length_pointer - i - 1) * sizeof(char*));
00235 memmove(configuration->publisher_directories + i + 1, configuration->publisher_directories + i, (*length_pointer - i - 1) * sizeof(char*));
00236 }
00237 configuration->publishers[i] = strdup(dirent->d_name);
00238 configuration->publisher_directories[i] = directory;
00239 configuration->publishers[*length_pointer] = NULL;
00240 }
00241 }
00242 }
00243 closedir(dir);
00244 }
00245 }
00246
00247 static void update_providers(MicrofeedConfiguration* configuration) {
00248 unsigned int length;
00249
00250 length = 0;
00251 if (configuration->providers_environment_directory) {
00252 get_providers(configuration, configuration->providers_environment_directory, &length);
00253 }
00254 if (configuration->providers_home_directory) {
00255 get_providers(configuration, configuration->providers_home_directory, &length);
00256 }
00257 get_providers(configuration, "/usr/local/lib/microfeed/providers", &length);
00258 get_providers(configuration, "/usr/lib/microfeed/providers", &length);
00259 }
00260
00261 static void update_publishers(MicrofeedConfiguration* configuration) {
00262 unsigned int length;
00263
00264 length = 0;
00265 if (configuration->publishers_environment_directory) {
00266 get_publishers(configuration, configuration->publishers_environment_directory, &length);
00267 }
00268 if (configuration->publishers_home_directory) {
00269 get_publishers(configuration, configuration->publishers_home_directory, &length);
00270 }
00271 get_publishers(configuration, "/usr/local/lib/microfeed/publishers", &length);
00272 get_publishers(configuration, "/usr/lib/microfeed/publishers", &length);
00273 }