![]() |
Icinga-core 1.4.0
next gen monitoring
|
00001 /***************************************************************************** 00002 * 00003 * SHARED.C - Random utility function for Icinga shared by CGIs and Core 00004 * 00005 * Copyright (c) 2010-2011 Nagios Core Development Team and Community Contributors 00006 * Copyright (c) 2010-2011 Icinga Development Team (http://www.icinga.org) 00007 * 00008 * License: 00009 * 00010 * This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License version 2 as 00012 * published by the Free Software Foundation. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00022 * 00023 *****************************************************************************/ 00024 00025 00026 #include "../include/config.h" 00027 #include "../include/common.h" 00028 00029 extern int date_format; 00030 00031 /* fix the problem with strtok() skipping empty options between tokens */ 00032 char *my_strtok(char *buffer, char *tokens) 00033 { 00034 char *token_position = NULL; 00035 char *sequence_head = NULL; 00036 static char *my_strtok_buffer = NULL; 00037 static char *original_my_strtok_buffer = NULL; 00038 00039 if (buffer != NULL) { 00040 my_free(original_my_strtok_buffer); 00041 if ((my_strtok_buffer = (char *)strdup(buffer)) == NULL) 00042 return NULL; 00043 original_my_strtok_buffer = my_strtok_buffer; 00044 } 00045 00046 sequence_head = my_strtok_buffer; 00047 00048 if (sequence_head[0] == '\x0') 00049 return NULL; 00050 00051 token_position = strchr(my_strtok_buffer, tokens[0]); 00052 00053 if (token_position == NULL) { 00054 my_strtok_buffer = strchr(my_strtok_buffer, '\x0'); 00055 return sequence_head; 00056 } 00057 00058 token_position[0] = '\x0'; 00059 my_strtok_buffer = token_position + 1; 00060 00061 return sequence_head; 00062 } 00063 00064 /* fixes compiler problems under Solaris, since strsep() isn't included */ 00065 /* this code is taken from the glibc source */ 00066 char *my_strsep(char **stringp, const char *delim) 00067 { 00068 char *begin, *end; 00069 00070 begin = *stringp; 00071 if (begin == NULL) 00072 return NULL; 00073 00074 /* A frequent case is when the delimiter string contains only one 00075 * character. Here we don't need to call the expensive `strpbrk' 00076 * function and instead work using `strchr'. */ 00077 if (delim[0] == '\0' || delim[1] == '\0') { 00078 char ch = delim[0]; 00079 00080 if (ch == '\0' || begin[0] == '\0') 00081 end = NULL; 00082 else { 00083 if (*begin == ch) 00084 end = begin; 00085 else 00086 end = strchr(begin + 1, ch); 00087 } 00088 } else { 00089 /* find the end of the token. */ 00090 end = strpbrk(begin, delim); 00091 } 00092 00093 if (end) { 00094 /* terminate the token and set *STRINGP past NUL character. */ 00095 *end++ = '\0'; 00096 *stringp = end; 00097 } else 00098 /* no more delimiters; this is the last token. */ 00099 *stringp = NULL; 00100 00101 return begin; 00102 } 00103 00104 /* open a file read-only via mmap() */ 00105 mmapfile *mmap_fopen(char *filename) 00106 { 00107 mmapfile *new_mmapfile = NULL; 00108 int fd = 0; 00109 void *mmap_buf = NULL; 00110 struct stat statbuf; 00111 int mode = O_RDONLY; 00112 unsigned long file_size = 0L; 00113 00114 if (filename == NULL) 00115 return NULL; 00116 00117 /* allocate memory */ 00118 if ((new_mmapfile = (mmapfile *) malloc(sizeof(mmapfile))) == NULL) 00119 return NULL; 00120 00121 /* open the file */ 00122 if ((fd = open(filename, mode)) == -1) { 00123 my_free(new_mmapfile); 00124 return NULL; 00125 } 00126 00127 /* get file info */ 00128 if ((fstat(fd, &statbuf)) == -1) { 00129 close(fd); 00130 my_free(new_mmapfile); 00131 return NULL; 00132 } 00133 00134 /* get file size */ 00135 file_size = (unsigned long)statbuf.st_size; 00136 00137 /* only mmap() if we have a file greater than 0 bytes */ 00138 if (file_size > 0) { 00139 00140 /* mmap() the file - allocate one extra byte for processing zero-byte files */ 00141 if ((mmap_buf = 00142 (void *)mmap(0, file_size, PROT_READ, MAP_PRIVATE, fd, 00143 0)) == MAP_FAILED) { 00144 close(fd); 00145 my_free(new_mmapfile); 00146 return NULL; 00147 } 00148 } else 00149 mmap_buf = NULL; 00150 00151 /* populate struct info for later use */ 00152 new_mmapfile->path = (char *)strdup(filename); 00153 new_mmapfile->fd = fd; 00154 new_mmapfile->file_size = (unsigned long)file_size; 00155 new_mmapfile->current_position = 0L; 00156 new_mmapfile->current_line = 0L; 00157 new_mmapfile->mmap_buf = mmap_buf; 00158 00159 return new_mmapfile; 00160 } 00161 00162 /* close a file originally opened via mmap() */ 00163 int mmap_fclose(mmapfile * temp_mmapfile) 00164 { 00165 00166 if (temp_mmapfile == NULL) 00167 return ERROR; 00168 00169 /* un-mmap() the file */ 00170 if (temp_mmapfile->file_size > 0L) 00171 munmap(temp_mmapfile->mmap_buf, temp_mmapfile->file_size); 00172 00173 /* close the file */ 00174 close(temp_mmapfile->fd); 00175 00176 /* free memory */ 00177 my_free(temp_mmapfile->path); 00178 my_free(temp_mmapfile); 00179 00180 return OK; 00181 } 00182 00183 /* gets one line of input from an mmap()'ed file */ 00184 char *mmap_fgets(mmapfile * temp_mmapfile) 00185 { 00186 char *buf = NULL; 00187 unsigned long x = 0L; 00188 int len = 0; 00189 00190 if (temp_mmapfile == NULL) 00191 return NULL; 00192 00193 /* size of file is 0 bytes */ 00194 if (temp_mmapfile->file_size == 0L) 00195 return NULL; 00196 00197 /* we've reached the end of the file */ 00198 if (temp_mmapfile->current_position >= temp_mmapfile->file_size) 00199 return NULL; 00200 00201 /* find the end of the string (or buffer) */ 00202 for (x = temp_mmapfile->current_position; x < temp_mmapfile->file_size; 00203 x++) { 00204 if (*((char *)(temp_mmapfile->mmap_buf) + x) == '\n') { 00205 x++; 00206 break; 00207 } 00208 } 00209 00210 /* calculate length of line we just read */ 00211 len = (int)(x - temp_mmapfile->current_position); 00212 00213 /* allocate memory for the new line */ 00214 if ((buf = (char *)malloc(len + 1)) == NULL) 00215 return NULL; 00216 00217 /* copy string to newly allocated memory and terminate the string */ 00218 memcpy(buf, 00219 ((char *)(temp_mmapfile->mmap_buf) + 00220 temp_mmapfile->current_position), len); 00221 buf[len] = '\x0'; 00222 00223 /* update the current position */ 00224 temp_mmapfile->current_position = x; 00225 00226 /* increment the current line */ 00227 temp_mmapfile->current_line++; 00228 00229 return buf; 00230 } 00231 00232 /* gets one line of input from an mmap()'ed file (may be contained on more than one line in the source file) */ 00233 char *mmap_fgets_multiline(mmapfile * temp_mmapfile) 00234 { 00235 char *buf = NULL; 00236 char *tempbuf = NULL; 00237 char *stripped = NULL; 00238 int len = 0; 00239 int len2 = 0; 00240 int end = 0; 00241 00242 if (temp_mmapfile == NULL) 00243 return NULL; 00244 00245 while (1) { 00246 00247 my_free(tempbuf); 00248 00249 if ((tempbuf = mmap_fgets(temp_mmapfile)) == NULL) 00250 break; 00251 00252 if (buf == NULL) { 00253 len = strlen(tempbuf); 00254 if ((buf = (char *)malloc(len + 1)) == NULL) 00255 break; 00256 memcpy(buf, tempbuf, len); 00257 buf[len] = '\x0'; 00258 } else { 00259 /* strip leading white space from continuation lines */ 00260 stripped = tempbuf; 00261 while (*stripped == ' ' || *stripped == '\t') 00262 stripped++; 00263 len = strlen(stripped); 00264 len2 = strlen(buf); 00265 if ((buf = 00266 (char *)realloc(buf, len + len2 + 1)) == NULL) 00267 break; 00268 strcat(buf, stripped); 00269 len += len2; 00270 buf[len] = '\x0'; 00271 } 00272 00273 if (len == 0) 00274 break; 00275 00276 /* handle Windows/DOS CR/LF */ 00277 if (len >= 2 && buf[len - 2] == '\r') 00278 end = len - 3; 00279 /* normal Unix LF */ 00280 else if (len >= 1 && buf[len - 1] == '\n') 00281 end = len - 2; 00282 else 00283 end = len - 1; 00284 00285 /* two backslashes found. unescape first backslash first and break */ 00286 if (end >= 1 && buf[end - 1] == '\\' && buf[end] == '\\') { 00287 buf[end] = '\n'; 00288 buf[end + 1] = '\x0'; 00289 break; 00290 } 00291 00292 /* one backslash found. continue reading the next line */ 00293 else if (end > 0 && buf[end] == '\\') 00294 buf[end] = '\x0'; 00295 00296 /* no continuation marker was found, so break */ 00297 else 00298 break; 00299 } 00300 00301 my_free(tempbuf); 00302 00303 return buf; 00304 } 00305 00306 /* strip newline, carriage return, and tab characters from beginning and end of a string */ 00307 void strip(char *buffer) 00308 { 00309 register int x, z; 00310 int len; 00311 00312 if (buffer == NULL || buffer[0] == '\x0') 00313 return; 00314 00315 /* strip end of string */ 00316 len = (int)strlen(buffer); 00317 for (x = len - 1; x >= 0; x--) { 00318 switch (buffer[x]) { 00319 case ' ': case '\n': case '\r': case '\t': 00320 buffer[x] = '\x0'; 00321 continue; 00322 } 00323 break; 00324 } 00325 00326 /* if we stripped all of it, just return */ 00327 if (!x) 00328 return; 00329 00330 /* save last position for later... */ 00331 z = x; 00332 00333 /* strip beginning of string (by shifting) */ 00334 /* NOTE: this is very expensive to do, so avoid it whenever possible */ 00335 for (x = 0;; x++) { 00336 switch (buffer[x]) { 00337 case ' ': case '\n': case '\r': case '\t': 00338 continue; 00339 } 00340 break; 00341 } 00342 00343 if (x > 0 && z > 0) { 00344 /* new length of the string after we stripped the end */ 00345 len = z + 1; 00346 00347 /* shift chars towards beginning of string to remove leading whitespace */ 00348 for (z = x; z < len; z++) 00349 buffer[z - x] = buffer[z]; 00350 buffer[len - x] = '\x0'; 00351 } 00352 } 00353 00354 /************************************************** 00355 *************** HASH FUNCTIONS ******************* 00356 **************************************************/ 00357 /* dual hash function */ 00358 int hashfunc(const char *name1, const char *name2, int hashslots) 00359 { 00360 unsigned int i, result; 00361 00362 result = 0; 00363 00364 if (name1) 00365 for (i = 0; i < strlen(name1); i++) 00366 result += name1[i]; 00367 00368 if (name2) 00369 for (i = 0; i < strlen(name2); i++) 00370 result += name2[i]; 00371 00372 result = result % hashslots; 00373 00374 return result; 00375 } 00376 00377 /* dual hash data comparison */ 00378 int compare_hashdata(const char *val1a, const char *val1b, const char *val2a, 00379 const char *val2b) 00380 { 00381 int result = 0; 00382 00383 /* NOTE: If hash calculation changes, update the compare_strings() function! */ 00384 00385 /* check first name */ 00386 if (val1a == NULL && val2a == NULL) 00387 result = 0; 00388 else if (val1a == NULL) 00389 result = 1; 00390 else if (val2a == NULL) 00391 result = -1; 00392 else 00393 result = strcmp(val1a, val2a); 00394 00395 /* check second name if necessary */ 00396 if (result == 0) { 00397 if (val1b == NULL && val2b == NULL) 00398 result = 0; 00399 else if (val1b == NULL) 00400 result = 1; 00401 else if (val2b == NULL) 00402 result = -1; 00403 else 00404 result = strcmp(val1b, val2b); 00405 } 00406 00407 return result; 00408 } 00409 /* 00410 * given a date/time in time_t format, produce a corresponding 00411 * date/time string, including timezone 00412 */ 00413 void get_datetime_string(time_t * raw_time, char *buffer, int buffer_length, 00414 int type) 00415 { 00416 time_t t; 00417 struct tm *tm_ptr, tm_s; 00418 int hour; 00419 int minute; 00420 int second; 00421 int month; 00422 int day; 00423 int year; 00424 char *weekdays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 00425 char *months[12] = 00426 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", 00427 "Oct", "Nov", "Dec" }; 00428 char *tzone = ""; 00429 00430 if (raw_time == NULL) 00431 time(&t); 00432 else 00433 t = *raw_time; 00434 00435 if (type == HTTP_DATE_TIME) 00436 tm_ptr = gmtime_r(&t, &tm_s); 00437 else 00438 tm_ptr = localtime_r(&t, &tm_s); 00439 00440 hour = tm_ptr->tm_hour; 00441 minute = tm_ptr->tm_min; 00442 second = tm_ptr->tm_sec; 00443 month = tm_ptr->tm_mon + 1; 00444 day = tm_ptr->tm_mday; 00445 year = tm_ptr->tm_year + 1900; 00446 00447 #ifdef HAVE_TM_ZONE 00448 tzone = (char *)(tm_ptr->tm_zone); 00449 #else 00450 tzone = (tm_ptr->tm_isdst) ? tzname[1] : tzname[0]; 00451 #endif 00452 00453 /* ctime() style date/time */ 00454 if (type == LONG_DATE_TIME) 00455 snprintf(buffer, buffer_length, "%s %s %d %02d:%02d:%02d %s %d", 00456 weekdays[tm_ptr->tm_wday], months[tm_ptr->tm_mon], day, 00457 hour, minute, second, tzone, year); 00458 00459 /* short date/time */ 00460 else if (type == SHORT_DATE_TIME) { 00461 if (date_format == DATE_FORMAT_EURO) 00462 snprintf(buffer, buffer_length, 00463 "%02d-%02d-%04d %02d:%02d:%02d", day, month, 00464 year, hour, minute, second); 00465 else if (date_format == DATE_FORMAT_ISO8601 00466 || date_format == DATE_FORMAT_STRICT_ISO8601) 00467 snprintf(buffer, buffer_length, 00468 "%04d-%02d-%02d%c%02d:%02d:%02d", year, month, 00469 day, 00470 (date_format == 00471 DATE_FORMAT_STRICT_ISO8601) ? 'T' : ' ', hour, 00472 minute, second); 00473 else 00474 snprintf(buffer, buffer_length, 00475 "%02d-%02d-%04d %02d:%02d:%02d", month, day, 00476 year, hour, minute, second); 00477 } 00478 00479 /* short date */ 00480 else if (type == SHORT_DATE) { 00481 if (date_format == DATE_FORMAT_EURO) 00482 snprintf(buffer, buffer_length, "%02d-%02d-%04d", day, 00483 month, year); 00484 else if (date_format == DATE_FORMAT_ISO8601 00485 || date_format == DATE_FORMAT_STRICT_ISO8601) 00486 snprintf(buffer, buffer_length, "%04d-%02d-%02d", year, 00487 month, day); 00488 else 00489 snprintf(buffer, buffer_length, "%02d-%02d-%04d", month, 00490 day, year); 00491 } 00492 00493 /* expiration date/time for HTTP headers */ 00494 else if (type == HTTP_DATE_TIME) 00495 snprintf(buffer, buffer_length, 00496 "%s, %02d %s %d %02d:%02d:%02d GMT", 00497 weekdays[tm_ptr->tm_wday], day, months[tm_ptr->tm_mon], 00498 year, hour, minute, second); 00499 00500 /* short time */ 00501 else 00502 snprintf(buffer, buffer_length, "%02d:%02d:%02d", hour, minute, 00503 second); 00504 00505 buffer[buffer_length - 1] = '\x0'; 00506 } 00507 00508 /* get days, hours, minutes, and seconds from a raw time_t format or total seconds */ 00509 void get_time_breakdown(unsigned long raw_time, int *days, int *hours, 00510 int *minutes, int *seconds) 00511 { 00512 unsigned long temp_time; 00513 int temp_days; 00514 int temp_hours; 00515 int temp_minutes; 00516 int temp_seconds; 00517 00518 temp_time = raw_time; 00519 00520 temp_days = temp_time / 86400; 00521 temp_time -= (temp_days * 86400); 00522 temp_hours = temp_time / 3600; 00523 temp_time -= (temp_hours * 3600); 00524 temp_minutes = temp_time / 60; 00525 temp_time -= (temp_minutes * 60); 00526 temp_seconds = (int)temp_time; 00527 00528 *days = temp_days; 00529 *hours = temp_hours; 00530 *minutes = temp_minutes; 00531 *seconds = temp_seconds; 00532 }