/** * prelude_daemonize: * @lockfile: Filename to a lockfile. * * Puts caller in background. * If @lockfile is not NULL, a lock for this program is created. * * The lockfile is automatically unlinked on exit. * * Returns: 0 on success, -1 if an error occured. */ int prelude_daemonize(const char *lockfile) { pid_t pid; int fd = 0, ret, i; if ( lockfile ) { ret = get_absolute_filename(lockfile); if ( ret < 0 ) return ret; } #if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ prelude_log(PRELUDE_LOG_ERR, "Daemonize call unsupported in this environment.\n"); pid = getpid(); #else pid = fork(); if ( pid < 0 ) return prelude_error_from_errno(errno); else if ( pid ) _exit(0); #endif if ( lockfile ) { fd = lockfile_get_exclusive(slockfile); if ( fd < 0 ) return fd; ret = lockfile_write_pid(fd, getpid()); if ( ret < 0 ) return ret; } #if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) setsid(); ret = chdir("/"); if ( ret < 0 ) prelude_log(PRELUDE_LOG_ERR, "could not change working directory to '/': %s.\n", strerror(errno)); umask(0); fd = open("/dev/null", O_RDWR); if ( fd < 0 ) return prelude_error_from_errno(errno); for ( i = 0; i <= 2; i++ ) { do { ret = dup2(fd, i); } while ( ret < 0 && errno == EINTR ); if ( ret < 0 ) return prelude_error_from_errno(errno); } close(fd); #endif return 0; }
/** * prelude_string_get_string_released: * @string: Pointer to a #prelude_string_t object. * @outptr: Pointer to an address where to store the released string. * * Get @string content, and release it so that further operation on * @string won't modify the returned content. * * Returns: 0 on success, or a negative value if an error occured. */ int prelude_string_get_string_released(prelude_string_t *string, char **outptr) { prelude_return_val_if_fail(string, prelude_error(PRELUDE_ERROR_ASSERTION)); *outptr = NULL; if ( ! string->index ) return 0; if ( ! (string->flags & PRELUDE_STRING_OWN_DATA) ) { *outptr = strdup(string->data.robuf); return (*outptr) ? 0 : prelude_error_from_errno(errno); } if ( string->index + 1 <= string->index ) return prelude_error(PRELUDE_ERROR_INVAL_LENGTH); *outptr = _prelude_realloc(string->data.rwbuf, string->index + 1); if ( ! *outptr ) return prelude_error_from_errno(errno); string->size = 0; string->index = 0; string->data.rwbuf = NULL; return 0; }
int _prelude_get_file_name_and_path(const char *str, char **name, char **path) { int ret = 0; char *ptr, pathname[PATH_MAX] = { 0 }; ptr = strrchr(str, '/'); if ( ! ptr ) { ret = find_absolute_path(_prelude_init_cwd, str, path); if ( ret < 0 ) return ret; *name = strdup(str); return (*name) ? 0 : prelude_error_from_errno(errno); } if ( *str != '/' ) { char needsep = 0; size_t cwdlen = strlen(_prelude_init_cwd); if ( cwdlen ) needsep = (_prelude_init_cwd[cwdlen - 1] != '/' ) ? '/' : '\0'; ret = snprintf(pathname, sizeof(pathname), "%s%c", _prelude_init_cwd, needsep); if ( ret < 0 || (size_t) ret >= sizeof(pathname) ) return prelude_error_from_errno(errno); } strncat(pathname, str, sizeof(pathname) - strlen(pathname)); normalize_path(pathname); ret = access(pathname, F_OK); if ( ret < 0 ) return prelude_error_from_errno(errno); ptr = strrchr(pathname, '/'); *path = strndup(pathname, ptr - pathname); if ( ! *path ) return prelude_error_from_errno(errno); *name = strdup(ptr + 1); if ( ! *name ) { free(*path); return prelude_error_from_errno(errno); } return 0; }
static int op_delete_line(config_t *cfg, unsigned int start, unsigned int end) { unsigned int i, j; if ( ! cfg->elements ) return 0; if ( start >= end || end > cfg->elements ) return -1; for ( i = start; i < end; i++ ) { free(cfg->content[i]); cfg->content[i] = NULL; } for ( i = end, j = start; i < cfg->elements; i++ ) cfg->content[j++] = cfg->content[i]; cfg->elements -= end - start; cfg->content = _prelude_realloc(cfg->content, cfg->elements * sizeof(char **)); if ( ! cfg->content ) return prelude_error_from_errno(errno); return 0; }
/** * prelude_string_clone: * @src: Pointer to an existing #prelude_string_t object. * @dst: Pointer to an address where to store the created #prelude_string_t object. * * Clone @src within a new #prelude_string_t object stored into @dst. * Data carried by @dst and @src are independant. * * Returns: 0 on success, or a negative value if an error occured. */ int prelude_string_clone(const prelude_string_t *src, prelude_string_t **dst) { int ret; prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION)); ret = prelude_string_new(dst); if ( ret < 0 ) return ret; (*dst)->size = src->size; (*dst)->index = src->index; (*dst)->flags |= PRELUDE_STRING_OWN_DATA; if ( src->size ) { (*dst)->data.rwbuf = malloc(src->size); if ( ! (*dst)->data.rwbuf ) { prelude_string_destroy(*dst); return prelude_error_from_errno(errno); } string_buf_copy(*dst, src->data.robuf, src->index); } return 0; }
/** * prelude_client_profile_new: * @ret: Pointer where to store the address of the created object. * @name: Name for this profile. * * Creates a new #prelude_client_profile_t object and store its * address into @ret. * * Returns: 0 on success or a negative value if an error occured. */ int prelude_client_profile_new(prelude_client_profile_t **ret, const char *name) { int retval; prelude_client_profile_t *cp; prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION)); retval = _prelude_client_profile_new(&cp); if ( retval < 0 ) return retval; cp->name = strdup(name); if ( ! cp->name ) { free(cp); return prelude_error_from_errno(errno); } retval = _prelude_client_profile_init(cp); if ( retval < 0 ) return retval; *ret = cp; return 0; }
static int allocate_more_chunk_if_needed(prelude_string_t *s, size_t needed_len) { int ret; char *ptr; size_t len; if ( ! needed_len ) len = BUFFER_CHUNK_SIZE; else len = MAX(needed_len - (s->size - s->index), s->size * BUFFER_GROWTH_FACTOR); if ( s->size + len < s->size ) return prelude_error(PRELUDE_ERROR_INVAL_LENGTH); if ( s->flags & PRELUDE_STRING_OWN_DATA ) { ptr = _prelude_realloc(s->data.rwbuf, s->size + len); if ( ! ptr ) return prelude_error_from_errno(errno); s->size += len; s->data.rwbuf = ptr; } else { ret = make_string_own(s, s->size + len); if ( ret < 0 ) return ret; } return 0; }
/** * idmef_time_new: * @time: Address where to store the created #idmef_time_t object. * * Creates an empty #idmef_time_t object and store it in @time. * * Returns: 0 on success, a negative value if an error occured. */ int idmef_time_new(idmef_time_t **time) { *time = calloc(1, sizeof(**time)); if ( ! *time ) return prelude_error_from_errno(errno); (*time)->refcount = 1; return 0; }
/** * idmef_time_new_from_gettimeofday: * @time: Address where to store the created #idmef_time_t object. * * Creates an #idmef_time_t object filled with information retrieved * using gettimeofday(), and stores it in @time. * * Returns: 0 on success, a negative value if an error occured. */ int idmef_time_new_from_gettimeofday(idmef_time_t **time) { int ret; struct timeval tv; ret = gettimeofday(&tv, NULL); if ( ret < 0 ) return prelude_error_from_errno(errno); return idmef_time_new_from_timeval(time, &tv); }
static int file_access_table_name_resolver(const idmef_path_t *path, char **table_name) { const char *child_name = idmef_path_get_name(path, idmef_path_get_depth(path) - 1); if ( strcmp(child_name, "permission") == 0 ) *table_name = strdup("Prelude_FileAccess_Permission"); else *table_name = strdup("Prelude_FileAccess"); return *table_name ? 0 : prelude_error_from_errno(errno); }
static int web_service_table_name_resolver(const idmef_path_t *path, char **table_name) { const char *child_name = idmef_path_get_name(path, idmef_path_get_depth(path) - 1); if ( strcmp(child_name, "arg") == 0 ) *table_name = strdup("Prelude_WebServiceArg"); else *table_name = strdup("Prelude_WebService"); return *table_name ? 0 : prelude_error_from_errno(errno); }
/** * prelude_string_new: * @string: Pointer where to store the created #prelude_string_t. * * Create a new #prelude_string_t object, and store in in @string. * * Returns: 0 on success, or a negative value if an error occured. */ int prelude_string_new(prelude_string_t **string) { *string = calloc(1, sizeof(**string)); if ( ! *string ) return prelude_error_from_errno(errno); (*string)->refcount = 1; prelude_list_init(&(*string)->_list); (*string)->flags = PRELUDE_STRING_OWN_STRUCTURE; return 0; }
int _prelude_client_profile_new(prelude_client_profile_t **ret) { *ret = calloc(1, sizeof(**ret)); if ( ! *ret ) return prelude_error_from_errno(errno); (*ret)->refcount = 1; (*ret)->uid = geteuid(); (*ret)->gid = getegid(); return 0; }
static int process_table_name_resolver(const idmef_path_t *path, char **table_name) { const char *child_name = idmef_path_get_name(path, idmef_path_get_depth(path) - 1); if ( strcmp(child_name, "arg") == 0 ) *table_name = strdup("Prelude_ProcessArg"); else if ( strcmp(child_name, "env") == 0 ) *table_name = strdup("Prelude_ProcessEnv"); else *table_name = strdup("Prelude_Process"); return *table_name ? 0 : prelude_error_from_errno(errno); }
/** * idmef_time_set_from_gettimeofday: * @time: Pointer to an #idmef_time_t object. * * Fills @time with information retrieved using gettimeofday(). * * Returns: 0 on success, a negative value if an error occured. */ int idmef_time_set_from_gettimeofday(idmef_time_t *time) { int ret; struct timeval tv; prelude_return_val_if_fail(time, prelude_error(PRELUDE_ERROR_ASSERTION)); ret = gettimeofday(&tv, NULL); if ( ret < 0 ) return prelude_error_from_errno(errno); return idmef_time_set_from_timeval(time, &tv); }
/** * prelude_client_profile_set_name: * @cp: Pointer to a #prelude_client_profile_t object. * @name: Name to associate the profile with. * * Sets the prelude client profile name. * * Returns: 0 on success or a negative value if an error occured. */ int prelude_client_profile_set_name(prelude_client_profile_t *cp, const char *name) { prelude_return_val_if_fail(cp, prelude_error(PRELUDE_ERROR_ASSERTION)); prelude_return_val_if_fail(name, prelude_error(PRELUDE_ERROR_ASSERTION)); if ( cp->name ) free(cp->name); cp->name = strdup(name); if ( ! cp->name ) return prelude_error_from_errno(errno); return 0; }
int prelude_get_gmt_offset_from_time(const time_t *utc, long *gmtoff) { time_t local; struct tm lt; if ( ! localtime_r(utc, <) ) return prelude_error_from_errno(errno); local = timegm(<); *gmtoff = local - *utc; return 0; }
static int string_buf_alloc(prelude_string_t *string, size_t len) { /* * include room for terminating \0. */ string->data.rwbuf = malloc(len + 1); if ( ! string->data.rwbuf ) return prelude_error_from_errno(errno); string->index = len; string->size = len + 1; return 0; }
static int message_table_name_resolver(const idmef_path_t *path, char **table_name) { const char *child_name = idmef_path_get_name(path, idmef_path_get_depth(path) - 1); if ( strcmp(child_name, "create_time") == 0 ) *table_name = strdup("Prelude_CreateTime"); else if ( strcmp(child_name, "detect_time") == 0 ) *table_name = strdup("Prelude_DetectTime"); else if ( strcmp(child_name, "analyzer_time") == 0 ) *table_name = strdup("Prelude_AnalyzerTime"); else return default_table_name_resolver(path, table_name); return *table_name ? 0 : prelude_error_from_errno(errno); }
static int lockfile_get_exclusive(const char *lockfile) { int fd; #if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) int ret; struct flock lock; #endif fd = open(lockfile, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); if ( fd < 0 ) return prelude_error_from_errno(errno); #if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); lock.l_type = F_WRLCK; /* write lock */ lock.l_start = 0; /* from offset 0 */ lock.l_whence = SEEK_SET; /* at the beginning of the file */ lock.l_len = 0; /* until EOF */ ret = fcntl(fd, F_SETLK, &lock); if ( ret < 0 ) { if ( errno == EACCES || errno == EAGAIN ) return prelude_error_verbose(PRELUDE_ERROR_DAEMONIZE_LOCK_HELD, "'%s' lock is held by another process", slockfile); close(fd); return prelude_error_from_errno(errno); } #endif /* * lock is now held until program exits. */ return fd; }
int prelude_log_set_logfile(const char *filename) { if ( ! filename && debug_logfile ) { fclose(debug_logfile); debug_logfile = NULL; } else { debug_logfile = fopen(filename, "a"); if ( ! debug_logfile ) return prelude_error_from_errno(errno); } return 0; }
static int lockfile_write_pid(int fd, pid_t pid) { int ret = -1; char buf[50]; /* * Resets file size to 0. */ #ifdef HAVE_FTRUNCATE ret = ftruncate(fd, 0); #elif HAVE_CHSIZE ret = chsize(fd, 0); #endif if ( ret < 0 ) return prelude_error_from_errno(errno); snprintf(buf, sizeof(buf), "%d\n", (int) pid); ret = write(fd, buf, strlen(buf)); if ( ret < 0 ) return prelude_error_from_errno(errno); return 0; }
static int resolve_addr(server_generic_t *server, const char *addr, unsigned int port) { struct addrinfo *ai; int ret, ai_family, ai_addrlen; #if ! ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) const char *unixpath = NULL; if ( is_unix_addr(&unixpath, addr) ) { ai_family = AF_UNIX; ai_addrlen = sizeof(struct sockaddr_un); } else { #endif ret = do_getaddrinfo(&ai, addr, port); if ( ret < 0 ) return ret; ai_family = ai->ai_family; ai_addrlen = ai->ai_addrlen; #if ! ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) } #endif server->sa = malloc(ai_addrlen); if ( ! server->sa ) { freeaddrinfo(ai); return prelude_error_from_errno(errno); } server->slen = ai_addrlen; server->sa->sa_family = ai_family; if ( ai_family != AF_UNIX ) { memcpy(server->sa, ai->ai_addr, ai->ai_addrlen); freeaddrinfo(ai); } #if ! ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) else { struct sockaddr_un *un = (struct sockaddr_un *) server->sa; strncpy(un->sun_path, unixpath, sizeof(un->sun_path)); } #endif return 0; }
/** * prelude_client_profile_set_prefix: * @cp: pointer on a #prelude_client_profile_t object. * @prefix: Prefix to use for various libprelude files. * * This function allow to dynamically change the prefix used to acess * libprelude related file. This is particularly usefull in case of * application running under certain condition (chroot). * * Returns: 0 on success, a negative value if an error occured. */ int prelude_client_profile_set_prefix(prelude_client_profile_t *cp, const char *prefix) { char *n; n = strdup(prefix); gl_lock_lock(lock); if ( user_prefix ) free(user_prefix); user_prefix = n; gl_lock_unlock(lock); return (n) ? 0 : prelude_error_from_errno(errno); }
static int make_string_own(prelude_string_t *s, size_t len) { char *ptr; ptr = malloc(len); if ( ! ptr ) return prelude_error_from_errno(errno); if ( s->data.robuf ) memcpy(ptr, s->data.robuf, s->index + 1); s->size = len; s->data.rwbuf = ptr; s->flags |= PRELUDE_STRING_OWN_DATA; return 0; }
/* * Appends a line to an array of line. * Takes the address of the array and the line to append as arguments. * * list must be NULL the first time this function is called, * in order to initialize indexing variable. */ static int op_append_line(config_t *cfg, char *line) { if ( ! line ) return 0; if ( cfg->elements + 1 < cfg->elements ) return -1; cfg->elements++; cfg->content = _prelude_realloc(cfg->content, cfg->elements * sizeof(char **)); if ( ! cfg->content ) return prelude_error_from_errno(errno); cfg->content[cfg->elements - 1] = line; return 0; }
static int config_save_value(config_t *cfg, int rtype, prelude_option_t *last, int is_last_cmd, char **prev, const char *option, const char *value, unsigned int *line) { int ret = 0; char buf[1024]; if ( ! (prelude_option_get_type(last) & PRELUDE_OPTION_TYPE_CFG) ) return -1; if ( rtype != PRELUDE_MSG_OPTION_SET && rtype != PRELUDE_MSG_OPTION_DESTROY ) return -1; if ( prelude_option_has_optlist(last) ) { if ( prelude_option_get_type(last) & PRELUDE_OPTION_TYPE_CONTEXT ) snprintf(buf, sizeof(buf), "%s=%s", option, (value) ? value : "default"); else snprintf(buf, sizeof(buf), "%s", option); if ( *prev ) free(*prev); *prev = strdup(buf); if ( ! *prev ) return prelude_error_from_errno(errno); if ( rtype == PRELUDE_MSG_OPTION_SET ) return _config_set(cfg, buf, NULL, NULL, line); else if ( is_last_cmd ) return _config_del(cfg, buf, NULL); } if ( rtype == PRELUDE_MSG_OPTION_SET ) ret = _config_set(cfg, *prev, option, value, line); else if ( is_last_cmd ) ret = _config_del(cfg, *prev, option); return ret; }
int prelude_get_gmt_offset_from_tm(struct tm *tm, long *gmtoff) { int tmp; time_t local, utc; /* * timegm will reset tm_isdst to 0 */ tmp = tm->tm_isdst; utc = timegm(tm); tm->tm_isdst = tmp; local = mktime(tm); if ( local == (time_t) -1 ) return prelude_error_from_errno(errno); *gmtoff = utc - mktime(tm); return 0; }
int server_generic_bind_numeric(server_generic_t *server, struct sockaddr *sa, socklen_t len, unsigned int port) { int ret; server->sa = malloc(len); if ( ! server->sa ) return prelude_error_from_errno(errno); server->slen = len; memcpy(server->sa, sa, len); ret = inet_server_start(server, server->sa, server->slen); if ( ret < 0 ) { free(server->sa); server->sa = NULL; return ret; } return sg_bind_common(server, port); }
/** * prelude_string_copy_dup: * @src: Pointer to a #prelude_string_t object to copy data from. * @dst: Pointer to a #prelude_string_t object to copy data to. * * Copy @src content within @dst. * The content is owned by @src and independent of @dst. * * Returns: 0 on success, or a negative value if an error occured. */ int prelude_string_copy_dup(const prelude_string_t *src, prelude_string_t *dst) { prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION)); prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION)); prelude_string_destroy_internal(dst); dst->size = src->size; dst->index = src->index; dst->flags |= PRELUDE_STRING_OWN_DATA; if ( src->size ) { dst->data.rwbuf = malloc(src->size); if ( ! dst->data.rwbuf ) return prelude_error_from_errno(errno); string_buf_copy(dst, src->data.robuf, src->index); } return 0; }