int handle_run(uint64_t con_id, struct message_request *request, char *pluginkey, struct api_error *error) { uint64_t callid; array *meta = NULL; string function_name; char *targetpluginkey; struct message_object args_object; if (!error || !request) return (-1); /* check params size */ if (request->params.size != 3) { error_set(error, API_ERROR_TYPE_VALIDATION, "Error dispatching run API request. Invalid params size"); return (-1); } if (request->params.obj[0].type == OBJECT_TYPE_ARRAY) meta = &request->params.obj[0].data.params; else { error_set(error, API_ERROR_TYPE_VALIDATION, "Error dispatching run API request. meta params has wrong type"); return (-1); } if (!meta) { error_set(error, API_ERROR_TYPE_VALIDATION, "Error dispatching run API request. meta params is NULL"); return (-1); } /* meta = [targetpluginkey, nil]*/ if (meta->size != 2) { error_set(error, API_ERROR_TYPE_VALIDATION, "Error dispatching run API request. Invalid meta params size"); return (-1); } /* extract meta information */ if (meta->obj[0].type != OBJECT_TYPE_STR) { error_set(error, API_ERROR_TYPE_VALIDATION, "Error dispatching run API request. meta elements have wrong type"); return (-1); } if (!meta->obj[0].data.string.str || meta->obj[0].data.string.length+1 != PLUGINKEY_STRING_SIZE) { error_set(error, API_ERROR_TYPE_VALIDATION, "Error dispatching run API request. Invalid meta params size"); return (-1); } targetpluginkey = meta->obj[0].data.string.str; to_upper(targetpluginkey); if (meta->obj[1].type != OBJECT_TYPE_NIL) { error_set(error, API_ERROR_TYPE_VALIDATION, "Error dispatching run API request. meta elements have wrong type"); return (-1); } if (request->params.obj[1].type != OBJECT_TYPE_STR) { error_set(error, API_ERROR_TYPE_VALIDATION, "Error dispatching run API request. function string has wrong type"); return (-1); } if (!request->params.obj[1].data.string.str) { error_set(error, API_ERROR_TYPE_VALIDATION, "Error dispatching register API request. Invalid meta params size"); return (-1); } function_name = request->params.obj[1].data.string; if (request->params.obj[2].type != OBJECT_TYPE_ARRAY) { error_set(error, API_ERROR_TYPE_VALIDATION, "Error dispatching run API request. function string has wrong type"); return (-1); } args_object = request->params.obj[2]; callid = (uint64_t) randommod(281474976710656LL); LOG_VERBOSE(VERBOSE_LEVEL_1, "generated callid %lu\n", callid); hashmap_put(uint64_t, ptr_t)(callids, callid, pluginkey); if (api_run(targetpluginkey, function_name, callid, args_object, con_id, request->msgid, error) == -1) { if (false == error->isset) error_set(error, API_ERROR_TYPE_VALIDATION, "Error executing run API request."); return (-1); } return (0); }
void l_ref_put(hashmap_p hash, char *name, LValue **ref) { hashmap_put(hash, name, ref, sizeof(ref)); }
static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, void *userdata, void *socketp) { sd_event_source *io; CurlGlue *g = userdata; uint32_t events = 0; int r; assert(curl); assert(g); io = hashmap_get(g->ios, FD_TO_PTR(s)); if (action == CURL_POLL_REMOVE) { if (io) { int fd; fd = sd_event_source_get_io_fd(io); assert(fd >= 0); sd_event_source_set_enabled(io, SD_EVENT_OFF); sd_event_source_unref(io); hashmap_remove(g->ios, FD_TO_PTR(s)); hashmap_remove(g->translate_fds, FD_TO_PTR(fd)); safe_close(fd); } return 0; } r = hashmap_ensure_allocated(&g->ios, &trivial_hash_ops); if (r < 0) { log_oom(); return -1; } r = hashmap_ensure_allocated(&g->translate_fds, &trivial_hash_ops); if (r < 0) { log_oom(); return -1; } if (action == CURL_POLL_IN) events = EPOLLIN; else if (action == CURL_POLL_OUT) events = EPOLLOUT; else if (action == CURL_POLL_INOUT) events = EPOLLIN|EPOLLOUT; if (io) { if (sd_event_source_set_io_events(io, events) < 0) return -1; if (sd_event_source_set_enabled(io, SD_EVENT_ON) < 0) return -1; } else { _cleanup_close_ int fd = -1; /* When curl needs to remove an fd from us it closes * the fd first, and only then calls into us. This is * nasty, since we cannot pass the fd on to epoll() * anymore. Hence, duplicate the fds here, and keep a * copy for epoll which we control after use. */ fd = fcntl(s, F_DUPFD_CLOEXEC, 3); if (fd < 0) return -1; if (sd_event_add_io(g->event, &io, fd, events, curl_glue_on_io, g) < 0) return -1; (void) sd_event_source_set_description(io, "curl-io"); r = hashmap_put(g->ios, FD_TO_PTR(s), io); if (r < 0) { log_oom(); sd_event_source_unref(io); return -1; } r = hashmap_put(g->translate_fds, FD_TO_PTR(fd), FD_TO_PTR(s)); if (r < 0) { log_oom(); hashmap_remove(g->ios, FD_TO_PTR(s)); sd_event_source_unref(io); return -1; } fd = -1; } return 0; }
int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) { _cleanup_closedir_ DIR *d = NULL; struct stat exclude_st; int r; if (keep_free == 0 && max_use == 0) return 0; if (exclude_fd >= 0) { if (fstat(exclude_fd, &exclude_st) < 0) return log_error_errno(errno, "Failed to fstat(): %m"); } /* This algorithm will keep deleting the oldest file of the * user with the most coredumps until we are back in the size * limits. Note that vacuuming for journal files is different, * because we rely on rate-limiting of the messages there, * to avoid being flooded. */ d = opendir("/var/lib/systemd/coredump"); if (!d) { if (errno == ENOENT) return 0; log_error_errno(errno, "Can't open coredump directory: %m"); return -errno; } for (;;) { _cleanup_(vacuum_candidate_hasmap_freep) Hashmap *h = NULL; struct vacuum_candidate *worst = NULL; struct dirent *de; uint64_t sum = 0; rewinddir(d); FOREACH_DIRENT(de, d, goto fail) { struct vacuum_candidate *c; struct stat st; uid_t uid; usec_t t; r = uid_from_file_name(de->d_name, &uid); if (r < 0) continue; if (fstatat(dirfd(d), de->d_name, &st, AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW) < 0) { if (errno == ENOENT) continue; log_warning("Failed to stat /var/lib/systemd/coredump/%s", de->d_name); continue; } if (!S_ISREG(st.st_mode)) continue; if (exclude_fd >= 0 && exclude_st.st_dev == st.st_dev && exclude_st.st_ino == st.st_ino) continue; r = hashmap_ensure_allocated(&h, NULL); if (r < 0) return log_oom(); t = timespec_load(&st.st_mtim); c = hashmap_get(h, UINT32_TO_PTR(uid)); if (c) { if (t < c->oldest_mtime) { char *n; n = strdup(de->d_name); if (!n) return log_oom(); free(c->oldest_file); c->oldest_file = n; c->oldest_mtime = t; } } else { _cleanup_(vacuum_candidate_freep) struct vacuum_candidate *n = NULL; n = new0(struct vacuum_candidate, 1); if (!n) return log_oom(); n->oldest_file = strdup(de->d_name); if (!n->oldest_file) return log_oom(); n->oldest_mtime = t; r = hashmap_put(h, UINT32_TO_PTR(uid), n); if (r < 0) return log_oom(); c = n; n = NULL; } c->n_files++; if (!worst || worst->n_files < c->n_files || (worst->n_files == c->n_files && c->oldest_mtime < worst->oldest_mtime)) worst = c; sum += st.st_blocks * 512; } if (!worst) break; r = vacuum_necessary(dirfd(d), sum, keep_free, max_use); if (r <= 0) return r; if (unlinkat(dirfd(d), worst->oldest_file, 0) < 0) { if (errno == ENOENT) continue; log_error_errno(errno, "Failed to remove file %s: %m", worst->oldest_file); return -errno; } else log_info("Removed old coredump %s.", worst->oldest_file); } return 0; fail: log_error_errno(errno, "Failed to read directory: %m"); return -errno; }
void hashmap_iput(hashmap *hm, unsigned int key, void *value, unsigned int value_len) { hashmap_put(hm, (char*)&key, sizeof(unsigned int), value, value_len); }
int main(int argc, char *argv[]) { char **args; char *type = "jcifs"; int verbose = 0; char *filename = NULL, *outname = NULL; char symtabpath[PATH_MAX + 1], *sp; struct hashmap macros; if (argc < 2) { usage: fprintf(stderr, "usage: %s [-v|-d] [-s <symtab>] [-t jcifs|java|samba|c] [-o outfile] [-Dmacro=defn] <filename>\n", argv[0]); return EXIT_FAILURE; } errno = 0; if (hashmap_init(¯os, 0, hash_text, cmp_text, NULL, NULL) == -1) { MMSG(""); return EXIT_FAILURE; } args = argv; args++; argc--; sp = symtabpath; #ifdef _DATADIR sp += sprintf(sp, "%s%c", _DATADIR, SEP); #endif sprintf(sp, "symtab%s.txt", type); while (argc) { if (strcmp(*args, "-v") == 0) { verbose++; } else if (strcmp(*args, "-d") == 0) { verbose += 2; } else if (strcmp(*args, "-s") == 0) { args++; argc--; if (!argc) { MMSG("-s requires a symtab path"); goto usage; } strncpy(symtabpath, *args, PATH_MAX); } else if (strcmp(*args, "-t") == 0) { args++; argc--; if (!argc) { MMSG("-t requires a type"); goto usage; } sp = symtabpath; #ifdef _DATADIR sp += sprintf(sp, "%s%c", _DATADIR, SEP); #endif type = *args; sprintf(sp, "symtab%s.txt", type); } else if (strncmp(*args, "-D", 2) == 0) { char *p, *macro, *defn = NULL; p = macro = (*args) + 2; for ( ;; p++) { if (*p == '\0') { if (p == macro) { macro = NULL; } else if (defn == NULL) { defn = "1"; } break; } else if (defn == NULL && isspace(*p)) { MMSG("invalid macro: %s", *args); goto usage; } else if (*p == '=') { if (p == macro) { MMSG("invalid macro: %s", *args); goto usage; } *p = '\0'; defn = p + 1; } } if (macro && hashmap_put(¯os, macro, defn) == -1) { MMSG(""); return EXIT_FAILURE; } } else if (strcmp(*args, "-o") == 0) { args++; argc--; if (!argc) { MMSG("-o requires a filename"); goto usage; } outname = *args; } else if (filename || **args == '-') { MMSG("Invalid argument: %s", *args); goto usage; } else { filename = *args; } args++; argc--; } if (!filename) { MMSG("A filename must be specified"); goto usage; } if (run(argc, argv, filename, outname, type, symtabpath, ¯os, verbose) == -1) { MMSG(""); return EXIT_FAILURE; } return EXIT_SUCCESS; }
static int process(const char *controller, const char *path, Hashmap *a, Hashmap *b, unsigned iteration) { Group *g; int r; FILE *f; pid_t pid; unsigned n; assert(controller); assert(path); assert(a); g = hashmap_get(a, path); if (!g) { g = hashmap_get(b, path); if (!g) { g = new0(Group, 1); if (!g) return -ENOMEM; g->path = strdup(path); if (!g->path) { group_free(g); return -ENOMEM; } r = hashmap_put(a, g->path, g); if (r < 0) { group_free(g); return r; } } else { assert_se(hashmap_move_one(a, b, path) == 0); g->cpu_valid = g->memory_valid = g->io_valid = g->n_tasks_valid = false; } } /* Regardless which controller, let's find the maximum number * of processes in any of it */ r = cg_enumerate_tasks(controller, path, &f); if (r < 0) return r; n = 0; while (cg_read_pid(f, &pid) > 0) n++; fclose(f); if (n > 0) { if (g->n_tasks_valid) g->n_tasks = MAX(g->n_tasks, n); else g->n_tasks = n; g->n_tasks_valid = true; } if (streq(controller, "cpuacct")) { uint64_t new_usage; char *p, *v; struct timespec ts; r = cg_get_path(controller, path, "cpuacct.usage", &p); if (r < 0) return r; r = read_one_line_file(p, &v); free(p); if (r < 0) return r; r = safe_atou64(v, &new_usage); free(v); if (r < 0) return r; assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); if (g->cpu_iteration == iteration - 1) { uint64_t x, y; x = ((uint64_t) ts.tv_sec * 1000000000ULL + (uint64_t) ts.tv_nsec) - ((uint64_t) g->cpu_timestamp.tv_sec * 1000000000ULL + (uint64_t) g->cpu_timestamp.tv_nsec); y = new_usage - g->cpu_usage; if (y > 0) { g->cpu_fraction = (double) y / (double) x; g->cpu_valid = true; } } g->cpu_usage = new_usage; g->cpu_timestamp = ts; g->cpu_iteration = iteration; } else if (streq(controller, "memory")) { char *p, *v; r = cg_get_path(controller, path, "memory.usage_in_bytes", &p); if (r < 0) return r; r = read_one_line_file(p, &v); free(p); if (r < 0) return r; r = safe_atou64(v, &g->memory); free(v); if (r < 0) return r; if (g->memory > 0) g->memory_valid = true; } else if (streq(controller, "blkio")) { char *p; uint64_t wr = 0, rd = 0; struct timespec ts; r = cg_get_path(controller, path, "blkio.io_service_bytes", &p); if (r < 0) return r; f = fopen(p, "re"); free(p); if (!f) return -errno; for (;;) { char line[LINE_MAX], *l; uint64_t k, *q; if (!fgets(line, sizeof(line), f)) break; l = strstrip(line); l += strcspn(l, WHITESPACE); l += strspn(l, WHITESPACE); if (first_word(l, "Read")) { l += 4; q = &rd; } else if (first_word(l, "Write")) { l += 5; q = ≀ } else continue; l += strspn(l, WHITESPACE); r = safe_atou64(l, &k); if (r < 0) continue; *q += k; } fclose(f); assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); if (g->io_iteration == iteration - 1) { uint64_t x, yr, yw; x = ((uint64_t) ts.tv_sec * 1000000000ULL + (uint64_t) ts.tv_nsec) - ((uint64_t) g->io_timestamp.tv_sec * 1000000000ULL + (uint64_t) g->io_timestamp.tv_nsec); yr = rd - g->io_input; yw = wr - g->io_output; if (yr > 0 || yw > 0) { g->io_input_bps = (yr * 1000000000ULL) / x; g->io_output_bps = (yw * 1000000000ULL) / x; g->io_valid = true; } } g->io_input = rd; g->io_output = wr; g->io_timestamp = ts; g->io_iteration = iteration; } return 0; }
#include <c_hashmap/hashmap.h> // All tests in this file adapted from example code in the original c_hashmap // package's main.c FEATURE(hashmap_put, "Hashmap put") SCENARIO("Put one value") GIVEN("a new hashmap") map_t map = hashmap_new(); WHEN("I put a new value in") int value = 42; int error = hashmap_put(map, "somekey", &value); THEN("the operation should be successful"); SHOULD_INT_EQUAL(error, (int)MAP_OK); hashmap_free(map); SCENARIO_END FEATURE_END FEATURE(hashmap_get, "Hashmap get") SCENARIO("Get an existing value") GIVEN("a hashmap with a value") map_t map = hashmap_new(); int value = 42; hashmap_put(map, "somekey", &value);
static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) { _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *old = NULL; bool keep; int r; assert(lldp); assert(n); assert(!n->lldp); keep = lldp_keep_neighbor(lldp, n); /* First retrieve the old entry for this MSAP */ old = hashmap_get(lldp->neighbor_by_id, &n->id); if (old) { sd_lldp_neighbor_ref(old); if (!keep) { lldp_neighbor_unlink(old); lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old); return 0; } if (lldp_neighbor_equal(n, old)) { /* Is this equal, then restart the TTL counter, but don't do anyting else. */ lldp_start_timer(lldp, old); lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old); return 0; } /* Data changed, remove the old entry, and add a new one */ lldp_neighbor_unlink(old); } else if (!keep) return 0; /* Then, make room for at least one new neighbor */ lldp_make_space(lldp, 1); r = hashmap_put(lldp->neighbor_by_id, &n->id, n); if (r < 0) goto finish; r = prioq_put(lldp->neighbor_by_expiry, n, &n->prioq_idx); if (r < 0) { assert_se(hashmap_remove(lldp->neighbor_by_id, &n->id) == n); goto finish; } n->lldp = lldp; lldp_start_timer(lldp, n); lldp_callback(lldp, old ? SD_LLDP_EVENT_UPDATED : SD_LLDP_EVENT_ADDED, n); return 1; finish: if (old) lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n); return r; }
void SetProperty(char* key, void * value){ if (!prop_map) prop_map = hashmap_new(); int error = hashmap_put(prop_map, key, value); assert(error==MAP_OK); }
int main(int argc, char *argv[]) { _cleanup_hashmap_free_free_ Hashmap *pids = NULL; _cleanup_endmntent_ FILE *f = NULL; struct mntent* me; int r; if (argc > 1) { log_error("This program takes no argument."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); f = setmntent("/etc/fstab", "r"); if (!f) { if (errno == ENOENT) { r = 0; goto finish; } r = log_error_errno(errno, "Failed to open /etc/fstab: %m"); goto finish; } pids = hashmap_new(NULL); if (!pids) { r = log_oom(); goto finish; } while ((me = getmntent(f))) { pid_t pid; int k; char *s; /* Remount the root fs, /usr and all API VFS */ if (!mount_point_is_api(me->mnt_dir) && !path_equal(me->mnt_dir, "/") && !path_equal(me->mnt_dir, "/usr")) continue; log_debug("Remounting %s", me->mnt_dir); pid = fork(); if (pid < 0) { r = log_error_errno(errno, "Failed to fork: %m"); goto finish; } if (pid == 0) { /* Child */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); (void) prctl(PR_SET_PDEATHSIG, SIGTERM); execv(MOUNT_PATH, STRV_MAKE(MOUNT_PATH, me->mnt_dir, "-o", "remount")); log_error_errno(errno, "Failed to execute " MOUNT_PATH ": %m"); _exit(EXIT_FAILURE); } /* Parent */ s = strdup(me->mnt_dir); if (!s) { r = log_oom(); goto finish; } k = hashmap_put(pids, PID_TO_PTR(pid), s); if (k < 0) { free(s); r = log_oom(); goto finish; } } r = 0; while (!hashmap_isempty(pids)) { siginfo_t si = {}; char *s; if (waitid(P_ALL, 0, &si, WEXITED) < 0) { if (errno == EINTR) continue; r = log_error_errno(errno, "waitid() failed: %m"); goto finish; } s = hashmap_remove(pids, PID_TO_PTR(si.si_pid)); if (s) { if (!is_clean_exit(si.si_code, si.si_status, EXIT_CLEAN_COMMAND, NULL)) { if (si.si_code == CLD_EXITED) log_error(MOUNT_PATH " for %s exited with exit status %i.", s, si.si_status); else log_error(MOUNT_PATH " for %s terminated by signal %s.", s, signal_to_string(si.si_status)); r = -ENOEXEC; } free(s); } } finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }
static int process( const char *controller, const char *path, Hashmap *a, Hashmap *b, unsigned iteration, Group **ret) { Group *g; int r; assert(controller); assert(path); assert(a); g = hashmap_get(a, path); if (!g) { g = hashmap_get(b, path); if (!g) { g = new0(Group, 1); if (!g) return -ENOMEM; g->path = strdup(path); if (!g->path) { group_free(g); return -ENOMEM; } r = hashmap_put(a, g->path, g); if (r < 0) { group_free(g); return r; } } else { r = hashmap_move_one(a, b, path); if (r < 0) return r; g->cpu_valid = g->memory_valid = g->io_valid = g->n_tasks_valid = false; } } if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES)) { _cleanup_fclose_ FILE *f = NULL; pid_t pid; r = cg_enumerate_processes(controller, path, &f); if (r == -ENOENT) return 0; if (r < 0) return r; g->n_tasks = 0; while (cg_read_pid(f, &pid) > 0) { if (arg_count == COUNT_USERSPACE_PROCESSES && is_kernel_thread(pid) > 0) continue; g->n_tasks++; } if (g->n_tasks > 0) g->n_tasks_valid = true; } else if (streq(controller, "pids") && arg_count == COUNT_PIDS) { _cleanup_free_ char *p = NULL, *v = NULL; r = cg_get_path(controller, path, "pids.current", &p); if (r < 0) return r; r = read_one_line_file(p, &v); if (r == -ENOENT) return 0; if (r < 0) return r; r = safe_atou64(v, &g->n_tasks); if (r < 0) return r; if (g->n_tasks > 0) g->n_tasks_valid = true; } else if (streq(controller, "cpuacct") && cg_unified() <= 0) { _cleanup_free_ char *p = NULL, *v = NULL; uint64_t new_usage; nsec_t timestamp; r = cg_get_path(controller, path, "cpuacct.usage", &p); if (r < 0) return r; r = read_one_line_file(p, &v); if (r == -ENOENT) return 0; if (r < 0) return r; r = safe_atou64(v, &new_usage); if (r < 0) return r; timestamp = now_nsec(CLOCK_MONOTONIC); if (g->cpu_iteration == iteration - 1 && (nsec_t) new_usage > g->cpu_usage) { nsec_t x, y; x = timestamp - g->cpu_timestamp; if (x < 1) x = 1; y = (nsec_t) new_usage - g->cpu_usage; g->cpu_fraction = (double) y / (double) x; g->cpu_valid = true; } g->cpu_usage = (nsec_t) new_usage; g->cpu_timestamp = timestamp; g->cpu_iteration = iteration; } else if (streq(controller, "memory")) { _cleanup_free_ char *p = NULL, *v = NULL; if (cg_unified() <= 0) r = cg_get_path(controller, path, "memory.usage_in_bytes", &p); else r = cg_get_path(controller, path, "memory.current", &p); if (r < 0) return r; r = read_one_line_file(p, &v); if (r == -ENOENT) return 0; if (r < 0) return r; r = safe_atou64(v, &g->memory); if (r < 0) return r; if (g->memory > 0) g->memory_valid = true; } else if ((streq(controller, "io") && cg_unified() > 0) || (streq(controller, "blkio") && cg_unified() <= 0)) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; bool unified = cg_unified() > 0; uint64_t wr = 0, rd = 0; nsec_t timestamp; r = cg_get_path(controller, path, unified ? "io.stat" : "blkio.io_service_bytes", &p); if (r < 0) return r; f = fopen(p, "re"); if (!f) { if (errno == ENOENT) return 0; return -errno; } for (;;) { char line[LINE_MAX], *l; uint64_t k, *q; if (!fgets(line, sizeof(line), f)) break; /* Trim and skip the device */ l = strstrip(line); l += strcspn(l, WHITESPACE); l += strspn(l, WHITESPACE); if (unified) { while (!isempty(l)) { if (sscanf(l, "rbytes=%" SCNu64, &k)) rd += k; else if (sscanf(l, "wbytes=%" SCNu64, &k)) wr += k; l += strcspn(l, WHITESPACE); l += strspn(l, WHITESPACE); } } else { if (first_word(l, "Read")) { l += 4; q = &rd; } else if (first_word(l, "Write")) { l += 5; q = ≀ } else continue; l += strspn(l, WHITESPACE); r = safe_atou64(l, &k); if (r < 0) continue; *q += k; } } timestamp = now_nsec(CLOCK_MONOTONIC); if (g->io_iteration == iteration - 1) { uint64_t x, yr, yw; x = (uint64_t) (timestamp - g->io_timestamp); if (x < 1) x = 1; if (rd > g->io_input) yr = rd - g->io_input; else yr = 0; if (wr > g->io_output) yw = wr - g->io_output; else yw = 0; if (yr > 0 || yw > 0) { g->io_input_bps = (yr * 1000000000ULL) / x; g->io_output_bps = (yw * 1000000000ULL) / x; g->io_valid = true; } } g->io_input = rd; g->io_output = wr; g->io_timestamp = timestamp; g->io_iteration = iteration; } if (ret) *ret = g; return 0; }
/** * Add one pair to the dom * @param p the pair to add * @param p_parent the pair parent ("pairs") * @param parents a hashmap of parents looking for children * @param orphans a hashmap of children looking for parents * @param id VAR param: parent ID to update * @return 1 if it worked OK else 0 */ int write_one_pair( pair *p, dom_item *p_parent, hashmap *parents, hashmap *orphans, int *id ) { int res = 1; dom_item *p_element = dom_object_create( "pair" ); if ( p_element != NULL ) { if ( pair_is_parent(p) ) { char id_str[32]; char p_key[32]; UChar u_key[32]; snprintf( id_str, 32, "%d", *id ); dom_add_attribute( p_element, dom_attribute_create("id",id_str) ); snprintf( p_key, 32, "%lx",(long)p ); ascii_to_uchar( p_key, u_key, 32 ); hashmap_put( parents, u_key, id_str ); (*id)++; // check if any orphans belong to this parent link_node *ln = hashmap_get( orphans, u_key ); if ( ln != NULL ) { char *id_str = hashmap_get( parents, u_key ); dom_item *child = link_node_obj( ln ); while ( child != NULL ) { dom_add_attribute( child, dom_attribute_create("parent", id_str) ); ln = link_node_next( ln ); if ( ln != NULL ) child = link_node_obj( ln ); else child = NULL; } hashmap_remove( orphans, u_key, NULL ); link_node_dispose( ln ); } } else if ( pair_is_child(p) ) { UChar u_key[32]; char p_key[32]; snprintf( p_key, 32, "%lx",(long)pair_parent(p) ); ascii_to_uchar( p_key, u_key, 32 ); char *id_str = hashmap_get( parents, u_key ); if ( id_str != NULL ) dom_add_attribute( p_element, dom_attribute_create("parent", id_str) ); else { link_node *children = hashmap_get( orphans, u_key ); if ( children == NULL ) { children = link_node_create(); if ( children != NULL ) { link_node_set_obj( children, p_element ); res = hashmap_put( orphans, u_key, children ); } } else { link_node *ln = link_node_create(); if ( ln != NULL ) { link_node_set_obj( ln, p_element ); link_node_append( children, ln ); } else res = 0; } } } if ( res ) { if ( pair_is_hint(p) ) { dom_add_attribute( p_element, dom_attribute_create("hint","true") ); } int bytes = bitset_allocated(pair_versions(p))*8; char *bit_str = calloc( bytes+1, 1 ); if ( bit_str != NULL ) { bitset_tostring( pair_versions(p), bit_str, bytes ); res = dom_add_attribute( p_element, dom_attribute_create("versions",bit_str) ); free( bit_str ); } if ( res && !pair_is_child(p) ) { char *utf8_data = to_utf8( pair_data(p), pair_len(p) ); if ( utf8_data != NULL ) { res = dom_add_text( p_element, utf8_data ); free( utf8_data ); } } dom_add_child( p_parent, p_element ); } } else res = 0; return res; }
void dispatch_table_put(string method, dispatch_info info) { hashmap_put(string, dispatch_info)(dispatch_table, method, info); }
/* * Read stdin line by line and print result of commands to stdout: * * hash key -> strhash(key) memhash(key) strihash(key) memihash(key) * put key value -> NULL / old value * get key -> NULL / value * remove key -> NULL / old value * iterate -> key1 value1\nkey2 value2\n... * size -> tablesize numentries * * perfhashmap method rounds -> test hashmap.[ch] performance */ int main(int argc, char *argv[]) { char line[1024]; struct hashmap map; int icase; /* init hash map */ icase = argc > 1 && !strcmp("ignorecase", argv[1]); hashmap_init(&map, (hashmap_cmp_fn) (icase ? test_entry_cmp_icase : test_entry_cmp), 0); /* process commands from stdin */ while (fgets(line, sizeof(line), stdin)) { char *cmd, *p1 = NULL, *p2 = NULL; int l1 = 0, l2 = 0, hash = 0; struct test_entry *entry; /* break line into command and up to two parameters */ cmd = strtok(line, DELIM); /* ignore empty lines */ if (!cmd || *cmd == '#') continue; p1 = strtok(NULL, DELIM); if (p1) { l1 = strlen(p1); hash = icase ? strihash(p1) : strhash(p1); p2 = strtok(NULL, DELIM); if (p2) l2 = strlen(p2); } if (!strcmp("hash", cmd) && l1) { /* print results of different hash functions */ printf("%u %u %u %u\n", strhash(p1), memhash(p1, l1), strihash(p1), memihash(p1, l1)); } else if (!strcmp("add", cmd) && l1 && l2) { /* create entry with key = p1, value = p2 */ entry = alloc_test_entry(hash, p1, l1, p2, l2); /* add to hashmap */ hashmap_add(&map, entry); } else if (!strcmp("put", cmd) && l1 && l2) { /* create entry with key = p1, value = p2 */ entry = alloc_test_entry(hash, p1, l1, p2, l2); /* add / replace entry */ entry = hashmap_put(&map, entry); /* print and free replaced entry, if any */ puts(entry ? get_value(entry) : "NULL"); free(entry); } else if (!strcmp("get", cmd) && l1) { /* lookup entry in hashmap */ entry = hashmap_get_from_hash(&map, hash, p1); /* print result */ if (!entry) puts("NULL"); while (entry) { puts(get_value(entry)); entry = hashmap_get_next(&map, entry); } } else if (!strcmp("remove", cmd) && l1) { /* setup static key */ struct hashmap_entry key; hashmap_entry_init(&key, hash); /* remove entry from hashmap */ entry = hashmap_remove(&map, &key, p1); /* print result and free entry*/ puts(entry ? get_value(entry) : "NULL"); free(entry); } else if (!strcmp("iterate", cmd)) { struct hashmap_iter iter; hashmap_iter_init(&map, &iter); while ((entry = hashmap_iter_next(&iter))) printf("%s %s\n", entry->key, get_value(entry)); } else if (!strcmp("size", cmd)) { /* print table sizes */ printf("%u %u\n", map.tablesize, map.size); } else if (!strcmp("intern", cmd) && l1) { /* test that strintern works */ const char *i1 = strintern(p1); const char *i2 = strintern(p1); if (strcmp(i1, p1)) printf("strintern(%s) returns %s\n", p1, i1); else if (i1 == p1) printf("strintern(%s) returns input pointer\n", p1); else if (i1 != i2) printf("strintern(%s) != strintern(%s)", i1, i2); else printf("%s\n", i1); } else if (!strcmp("perfhashmap", cmd) && l1 && l2) { perf_hashmap(atoi(p1), atoi(p2)); } else { printf("Unknown command %s\n", cmd); } } hashmap_free(&map, 1); return 0; }
int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; _cleanup_endmntent_ FILE *f = NULL; struct mntent* me; Hashmap *pids = NULL; if (argc > 1) { log_error("This program takes no argument."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); f = setmntent("/etc/fstab", "r"); if (!f) { if (errno == ENOENT) return EXIT_SUCCESS; log_error_errno(errno, "Failed to open /etc/fstab: %m"); return EXIT_FAILURE; } pids = hashmap_new(NULL); if (!pids) { log_error("Failed to allocate set"); goto finish; } ret = EXIT_SUCCESS; while ((me = getmntent(f))) { pid_t pid; int k; char *s; /* Remount the root fs, /usr and all API VFS */ if (!mount_point_is_api(me->mnt_dir) && !path_equal(me->mnt_dir, "/") && !path_equal(me->mnt_dir, "/usr")) continue; log_debug("Remounting %s", me->mnt_dir); pid = fork(); if (pid < 0) { log_error_errno(errno, "Failed to fork: %m"); ret = EXIT_FAILURE; continue; } if (pid == 0) { const char *arguments[5]; /* Child */ arguments[0] = "/bin/mount"; arguments[1] = me->mnt_dir; arguments[2] = "-o"; arguments[3] = "remount"; arguments[4] = NULL; execv("/bin/mount", (char **) arguments); log_error_errno(errno, "Failed to execute /bin/mount: %m"); _exit(EXIT_FAILURE); } /* Parent */ s = strdup(me->mnt_dir); if (!s) { log_oom(); ret = EXIT_FAILURE; continue; } k = hashmap_put(pids, UINT_TO_PTR(pid), s); if (k < 0) { log_error_errno(k, "Failed to add PID to set: %m"); ret = EXIT_FAILURE; continue; } } while (!hashmap_isempty(pids)) { siginfo_t si = {}; char *s; if (waitid(P_ALL, 0, &si, WEXITED) < 0) { if (errno == EINTR) continue; log_error_errno(errno, "waitid() failed: %m"); ret = EXIT_FAILURE; break; } s = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)); if (s) { if (!is_clean_exit(si.si_code, si.si_status, NULL)) { if (si.si_code == CLD_EXITED) log_error("/bin/mount for %s exited with exit status %i.", s, si.si_status); else log_error("/bin/mount for %s terminated by signal %s.", s, signal_to_string(si.si_status)); ret = EXIT_FAILURE; } free(s); } } finish: if (pids) hashmap_free_free(pids); return ret; }
static int do_execute(char **directories, usec_t timeout, char *argv[]) { _cleanup_hashmap_free_free_ Hashmap *pids = NULL; _cleanup_set_free_free_ Set *seen = NULL; char **directory; /* We fork this all off from a child process so that we can * somewhat cleanly make use of SIGALRM to set a time limit */ (void) reset_all_signal_handlers(); (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); pids = hashmap_new(NULL); if (!pids) return log_oom(); seen = set_new(&string_hash_ops); if (!seen) return log_oom(); STRV_FOREACH(directory, directories) { _cleanup_closedir_ DIR *d; struct dirent *de; d = opendir(*directory); if (!d) { if (errno == ENOENT) continue; return log_error_errno(errno, "Failed to open directory %s: %m", *directory); } FOREACH_DIRENT(de, d, break) { _cleanup_free_ char *path = NULL; pid_t pid; int r; if (!dirent_is_file(de)) continue; if (set_contains(seen, de->d_name)) { log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name); continue; } r = set_put_strdup(seen, de->d_name); if (r < 0) return log_oom(); path = strjoin(*directory, "/", de->d_name, NULL); if (!path) return log_oom(); if (null_or_empty_path(path)) { log_debug("%s is empty (a mask).", path); continue; } pid = fork(); if (pid < 0) { log_error_errno(errno, "Failed to fork: %m"); continue; } else if (pid == 0) { char *_argv[2]; assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); if (!argv) { _argv[0] = path; _argv[1] = NULL; argv = _argv; } else argv[0] = path; execv(path, argv); return log_error_errno(errno, "Failed to execute %s: %m", path); } log_debug("Spawned %s as " PID_FMT ".", path, pid); r = hashmap_put(pids, PID_TO_PTR(pid), path); if (r < 0) return log_oom(); path = NULL; } }
static int dracut_install(const char *src, const char *dst, bool isdir, bool resolvedeps, bool hashdst) { struct stat sb, db; _cleanup_free_ char *fulldstpath = NULL; _cleanup_free_ char *fulldstdir = NULL; int ret; bool src_exists = true; char *i = NULL; char *existing; log_debug("dracut_install('%s', '%s')", src, dst); existing = hashmap_get(items_failed, src); if (existing) { if (strcmp(existing, src) == 0) { log_debug("hash hit items_failed for '%s'", src); return 1; } } if (hashdst) { existing = hashmap_get(items, dst); if (existing) { if (strcmp(existing, dst) == 0) { log_debug("hash hit items for '%s'", dst); return 0; } } } if (lstat(src, &sb) < 0) { src_exists = false; if (!isdir) { i = strdup(src); hashmap_put(items_failed, i, i); /* src does not exist */ return 1; } } i = strdup(dst); if (!i) return -ENOMEM; hashmap_put(items, i, i); ret = asprintf(&fulldstpath, "%s%s", destrootdir, dst); if (ret < 0) { log_error("Out of memory!"); exit(EXIT_FAILURE); } ret = stat(fulldstpath, &sb); if (ret != 0 && (errno != ENOENT)) { log_error("ERROR: stat '%s': %m", fulldstpath); return 1; } if (ret == 0) { if (resolvedeps && S_ISREG(sb.st_mode) && (sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { log_debug("'%s' already exists, but checking for any deps", fulldstpath); ret = resolve_deps(src); } else log_debug("'%s' already exists", fulldstpath); /* dst does already exist */ return ret; } /* check destination directory */ fulldstdir = strdup(fulldstpath); fulldstdir[dir_len(fulldstdir)] = '\0'; ret = stat(fulldstdir, &db); if (ret < 0) { _cleanup_free_ char *dname = NULL; if (errno != ENOENT) { log_error("ERROR: stat '%s': %m", fulldstdir); return 1; } /* create destination directory */ log_debug("dest dir '%s' does not exist", fulldstdir); dname = strdup(dst); if (!dname) return 1; dname[dir_len(dname)] = '\0'; ret = dracut_install(dname, dname, true, false, true); if (ret != 0) { log_error("ERROR: failed to create directory '%s'", fulldstdir); return 1; } } if (isdir && !src_exists) { log_info("mkdir '%s'", fulldstpath); ret = mkdir(fulldstpath, 0755); return ret; } /* ready to install src */ if (S_ISDIR(sb.st_mode)) { log_info("mkdir '%s'", fulldstpath); ret = mkdir(fulldstpath, sb.st_mode | S_IWUSR); return ret; } if (S_ISLNK(sb.st_mode)) { _cleanup_free_ char *abspath = NULL; abspath = realpath(src, NULL); if (abspath == NULL) return 1; if (dracut_install(abspath, abspath, false, resolvedeps, hashdst)) { log_debug("'%s' install error", abspath); return 1; } if (lstat(abspath, &sb) != 0) { log_debug("lstat '%s': %m", abspath); return 1; } if (lstat(fulldstpath, &sb) != 0) { _cleanup_free_ char *absdestpath = NULL; ret = asprintf(&absdestpath, "%s%s", destrootdir, abspath); if (ret < 0) { log_error("Out of memory!"); exit(EXIT_FAILURE); } ln_r(absdestpath, fulldstpath); } if (arg_hmac) { /* copy .hmac files also */ hmac_install(src, dst, NULL); } return 0; } if (sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { if (resolvedeps) ret += resolve_deps(src); if (arg_hmac) { /* copy .hmac files also */ hmac_install(src, dst, NULL); } } log_debug("dracut_install ret = %d", ret); log_info("cp '%s' '%s'", src, fulldstpath); if (arg_hostonly) mark_hostonly(dst); ret += cp(src, fulldstpath); if (ret == 0 && logfile_f) dracut_log_cp(src); log_debug("dracut_install ret = %d", ret); return ret; }
int main(char* argv, int argc) { int index; int error; map_t mymap; char key_string[KEY_MAX_LENGTH]; data_struct_t* value; fprintf(stderr, "start...\n"); mymap = hashmap_new(); /* First, populate the hash map with ascending values */ for (index=0; index<KEY_COUNT; index+=1) { /* Store the key string along side the numerical value so we can free it later */ value = malloc(sizeof(data_struct_t)); //snprintf(value->key_string, KEY_MAX_LENGTH, "%s%d", KEY_PREFIX, index); snprintf(value->key_string, KEY_MAX_LENGTH, "%s", strings[index]); value->number = index; //fprintf(stderr, "value->key_string=%s, value->number=%d\n", // value->key_string, value->number); error = hashmap_put(mymap, value->key_string, value); assert(error==MAP_OK); } /* Now, check all of the expected values are there */ for (index=0; index<KEY_COUNT; index+=1) { //snprintf(key_string, KEY_MAX_LENGTH, "%s%d", KEY_PREFIX, index); snprintf(key_string, KEY_MAX_LENGTH, "%s", strings[index]); error = hashmap_get(mymap, key_string, (void**)(&value)); //fprintf(stderr, "error=%d, value->number=%d, index=(%d)\n", error, value->number, index); /* Make sure the value was both found and the correct number */ assert(error==MAP_OK); assert(value->number==index); } /* Make sure that a value that wasn't in the map can't be found */ snprintf(key_string, KEY_MAX_LENGTH, "%s%d", KEY_PREFIX, KEY_COUNT); //snprintf(key_string, KEY_MAX_LENGTH, "%s", KEY_COUNT); error = hashmap_get(mymap, key_string, (void**)(&value)); fprintf(stderr, "error=%d\n", error); /* Make sure the value was not found */ assert(error==MAP_MISSING); /* Free all of the values we allocated and remove them from the map */ for (index=0; index<KEY_COUNT; index+=1) { //snprintf(key_string, KEY_MAX_LENGTH, "%s%d", KEY_PREFIX, index); snprintf(key_string, KEY_MAX_LENGTH, "%s", strings[index]); error = hashmap_get(mymap, key_string, (void**)(&value)); assert(error==MAP_OK); error = hashmap_remove(mymap, key_string); assert(error==MAP_OK); free(value); } /* Now, destroy the map */ hashmap_free(mymap); return 1; }
/** * 和客户交互 * @param sockfd [description] * @param i [description] * @return [description] */ int client_interface(struct bufferevent *bev, client_t *client) { /*加锁*/ if (pthread_mutex_lock(&mutex) != 0) { perror("pthread_mutex_lock"); exit(EXIT_FAILURE); } char data[4096]; int nbytes; //接收数据 char buffer[MAX_BUF + 1]; bzero(buffer, MAX_BUF + 1); int n = 0; int str_len = 0; int last_len; while ((nbytes = EVBUFFER_LENGTH(bev->input)) > 0) { if (nbytes > 4096) nbytes = 4096; n += evbuffer_remove(bev->input, data, nbytes); str_len = strlen(data); last_len = (MAX_BUF - strlen(buffer)); if (last_len >= str_len) { strncat(buffer, data, str_len); } else { strncat(buffer, data, last_len); } } if (n <= 0) { /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; //客户端退出时 } //printf("第%d个客户端 IP:%s\n", i + 1, inet_ntoa(_client[i].addr.sin_addr)); //解析客户端信息 int flag = 0; int ret; char key[20]; sprintf(key, "%d", client->fd); client_elem *c_el; ret = hashmap_get(client_map, key, (void **)&c_el); assert(ret == HMAP_S_OK); _RTS_TRANSPORT_DATA _rts_transport_data; _rts_transport_data = RTS_transport_data_init(); if (RTS_transport_data_parse(buffer, &_rts_transport_data) == 0) { client_send(client, "{\"code\":\"0001\",\"message\":\"数据格式非法\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } if (!_rts_transport_data.action) { client_send(client, "{\"code\":\"0005\",\"message\":\"参数非法\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } if (strcmp(_rts_transport_data.action, "login") == 0) { //登录 if (strlen(_rts_transport_data.name) == 0 || strlen(_rts_transport_data.password) == 0) { client_send(client, "{\"code\":\"0005\",\"message\":\"参数非法\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } //验证用户名密码 _RTS_USER *_rts_user = user_get(0, _rts_transport_data.name); if (_rts_user->id <= 0) { client_send(client, "{\"code\":\"0003\",\"message\":\"用户名或密码错误\"}"); CLIENT_FREE(_rts_user); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } char *pwdhash = RTS_hash(_rts_transport_data.password, _rts_user->salt); if (strcmp(_rts_user->password, pwdhash) != 0) { client_send(client, "{\"code\":\"0003\",\"message\":\"用户名或密码错误\"}"); CLIENT_FREE(pwdhash); CLIENT_FREE(_rts_user); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } //用户名密码验证通过后,判断当前账号是否已登录 //这时应该已经拿到了用户的id if (c_el->token && strlen(c_el->token) > 0) { //该设备已经登录了账号,不能再做登录操作 client_send(client, "{\"code\":\"1004\",\"message\":\"该设备已经登录了账号,不能再做登录操作\"}"); CLIENT_FREE(pwdhash); CLIENT_FREE(_rts_user); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 1; } if (c_el->id == 0 || (c_el->token && strlen(c_el->token) == 0)) { //未登录,直接执行登录赋值操作 //登录成功,返回认证标示 char *unique = RTS_unique(); strncpy(_rts_transport_data.token, unique, MAX_TOKEN_LENGTH); CLIENT_FREE(unique); //重新设置client_map ret = hashmap_remove(client_map, c_el->key, (void **)&c_el); assert(ret == HMAP_S_OK); client_elem *new_c_el = (client_elem *)malloc(sizeof(client_elem)); sprintf(new_c_el->key, "%d", client->fd); new_c_el->addr = c_el->addr; new_c_el->client = client; new_c_el->id = _rts_user->id; new_c_el->name = (char *)malloc(MAX_NAME_LENGTH + 1); strncpy(new_c_el->name, _rts_transport_data.name, MAX_NAME_LENGTH); new_c_el->token = (char *)malloc(MAX_TOKEN_LENGTH + 1); strncpy(new_c_el->token, _rts_transport_data.token, MAX_TOKEN_LENGTH); free_client_elem(c_el, 0); ret = hashmap_put(client_map, new_c_el->key, new_c_el); assert(ret == HMAP_S_OK); //设置client_id_map client_id_elem *cid_el = (client_id_elem *)malloc(sizeof(client_id_elem)); sprintf(cid_el->key, "%d", _rts_user->id); cid_el->fd = client->fd; ret = hashmap_put(client_id_map, cid_el->key, cid_el); assert(ret == HMAP_S_OK); RTS_printf("[++登录成功++]: NAME:%s--IP:%s\n", _rts_transport_data.name, inet_ntoa(c_el->addr.sin_addr)); bzero(buf, MAX_BUF + 1); sprintf(buf, "{\"code\":\"0000\",\"message\":\"登录成功\",\"token\":\"%s\",\"id\":%d}", _rts_transport_data.token, _rts_user->id); client_send(client, buf); //修改登录成功标识 _RTS_USER _rts_user2 = user_init(); _rts_user2.id = _rts_user->id; _rts_user2.status = 1; user_edit(_rts_user2); CLIENT_FREE(pwdhash); CLIENT_FREE(_rts_user); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 1; } client_send(client, "{\"code\":\"1003\",\"message\":\"该用户已经在其他地方成功登录\"}"); CLIENT_FREE(pwdhash); CLIENT_FREE(_rts_user); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 1; } if (strcmp(_rts_transport_data.action, "message") == 0) { //聊天 if (strlen(_rts_transport_data.token) == 0 || !_rts_transport_data.toid || !_rts_transport_data.id || wcslen(_rts_transport_data.content) == 0) { client_send(client, "{\"code\":\"0005\",\"message\":\"参数非法\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } //认证信息失败,退出客户端 if (!c_el->token || (strcmp(_rts_transport_data.token, "bsh_test_$%1KP@'") != 0 && strcmp(_rts_transport_data.token, c_el->token) != 0)) { client_send(client, "{\"code\":\"0004\",\"message\":\"token非法\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } //判断登录者身份 if (!c_el->id || c_el->id != _rts_transport_data.id) { client_send(client, "{\"code\":\"0006\",\"message\":\"用户身份非法\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } bzero(key, 20); sprintf(key, "%d", _rts_transport_data.toid); client_id_elem *cid_el; ret = hashmap_get(client_id_map, key, (void **)&cid_el); printf("发给id:%s\n", key); if (ret == 0) { printf("get_toid:%s ret:%d fd:%d\n", key, ret, cid_el->fd); } if (ret == HMAP_E_NOTFOUND || !cid_el || !cid_el->fd) { client_send(client, "{\"code\":\"1002\",\"message\":\"对方不在线\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 1; } bzero(key, 20); sprintf(key, "%d", cid_el->fd); client_elem *to_c_el; ret = hashmap_get(client_map, key, (void **)&to_c_el); assert(ret == HMAP_S_OK); if (to_c_el->id == _rts_transport_data.id) { //如果接受者是自己,则发出警告 client_send(client, "{\"code\":\"1001\",\"message\":\"不能给自己发消息\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 1; } bzero(buf, MAX_BUF + 1); sprintf(buf, "{\"code\":\"0000\",\"message\":\"发送成功\",\"content\":\"%ls\"}", _rts_transport_data.content); client_send(to_c_el->client, buf); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 1; } if (strcmp(_rts_transport_data.action, "logout") == 0) { //logout if (strlen(_rts_transport_data.token) == 0 || !_rts_transport_data.id) { client_send(client, "{\"code\":\"0005\",\"message\":\"参数非法\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } //判断登录者身份 if (!c_el->id || c_el->id != _rts_transport_data.id) { client_send(client, "{\"code\":\"0006\",\"message\":\"用户身份非法\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } //认证信息失败,退出客户端 if (c_el->token && strcmp(_rts_transport_data.token, c_el->token) != 0) { client_send(client, "{\"code\":\"0004\",\"message\":\"token非法\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } client_send(client, "{\"code\":\"0000\",\"message\":\"退出成功\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } if (strcmp(_rts_transport_data.action, "register") == 0) { if (strlen(_rts_transport_data.name) == 0 || strlen(_rts_transport_data.password) == 0) { client_send(client, "{\"code\":\"0005\",\"message\":\"参数非法\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; } char *salt = RTS_rand(); char *pwdhash = RTS_hash(_rts_transport_data.password, salt); char *datetime = RTS_current_datetime(); _rts_transport_data.id = user_add(_rts_transport_data.name, pwdhash, salt, inet_ntoa(c_el->addr.sin_addr), datetime, 0); CLIENT_FREE(salt); CLIENT_FREE(pwdhash); CLIENT_FREE(datetime); if (_rts_transport_data.id == 0) { client_send(client, "{\"code\":\"1005\",\"message\":\"注册失败,该用户名已注册\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 1; } if (_rts_transport_data.id > 0) { bzero(buf, MAX_BUF + 1); sprintf(buf, "{\"code\":\"0000\",\"message\":\"注册成功\",\"id\":%d}", _rts_transport_data.id); client_send(client, buf); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 1; } client_send(client, "{\"code\":\"0007\",\"message\":\"注册失败,未知错误\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 1; } client_send(client, "{\"code\":\"0002\",\"message\":\"动作非法\"}"); /*解锁锁*/ if (pthread_mutex_unlock(&mutex) != 0) { perror("pthread_mutex_unlock"); exit(EXIT_FAILURE); } return 0; }
static int parse_line(const char *fname, unsigned line, const char *buffer) { Item *i, *existing; char *mode = NULL, *user = NULL, *group = NULL, *age = NULL; char type; Hashmap *h; int r, n = -1; assert(fname); assert(line >= 1); assert(buffer); i = new0(Item, 1); if (!i) { log_error("Out of memory"); return -ENOMEM; } if (sscanf(buffer, "%c " "%ms " "%ms " "%ms " "%ms " "%ms " "%n", &type, &i->path, &mode, &user, &group, &age, &n) < 2) { log_error("[%s:%u] Syntax error.", fname, line); r = -EIO; goto finish; } if (n >= 0) { n += strspn(buffer+n, WHITESPACE); if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) { i->argument = unquote(buffer+n, "\""); if (!i->argument) { log_error("Out of memory"); return -ENOMEM; } } } switch(type) { case CREATE_FILE: case TRUNCATE_FILE: case CREATE_DIRECTORY: case TRUNCATE_DIRECTORY: case CREATE_FIFO: case IGNORE_PATH: case REMOVE_PATH: case RECURSIVE_REMOVE_PATH: case RELABEL_PATH: case RECURSIVE_RELABEL_PATH: break; case CREATE_SYMLINK: if (!i->argument) { log_error("[%s:%u] Symlink file requires argument.", fname, line); r = -EBADMSG; goto finish; } break; case WRITE_FILE: if (!i->argument) { log_error("[%s:%u] Write file requires argument.", fname, line); r = -EBADMSG; goto finish; } break; case CREATE_CHAR_DEVICE: case CREATE_BLOCK_DEVICE: { unsigned major, minor; if (!i->argument) { log_error("[%s:%u] Device file requires argument.", fname, line); r = -EBADMSG; goto finish; } if (sscanf(i->argument, "%u:%u", &major, &minor) != 2) { log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i->argument); r = -EBADMSG; goto finish; } i->major_minor = makedev(major, minor); break; } default: log_error("[%s:%u] Unknown file type '%c'.", fname, line, type); r = -EBADMSG; goto finish; } i->type = type; if (!path_is_absolute(i->path)) { log_error("[%s:%u] Path '%s' not absolute.", fname, line, i->path); r = -EBADMSG; goto finish; } path_kill_slashes(i->path); if (arg_prefix && !path_startswith(i->path, arg_prefix)) { r = 0; goto finish; } if (user && !streq(user, "-")) { const char *u = user; r = get_user_creds(&u, &i->uid, NULL, NULL, NULL); if (r < 0) { log_error("[%s:%u] Unknown user '%s'.", fname, line, user); goto finish; } i->uid_set = true; } if (group && !streq(group, "-")) { const char *g = group; r = get_group_creds(&g, &i->gid); if (r < 0) { log_error("[%s:%u] Unknown group '%s'.", fname, line, group); goto finish; } i->gid_set = true; } if (mode && !streq(mode, "-")) { unsigned m; if (sscanf(mode, "%o", &m) != 1) { log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode); r = -ENOENT; goto finish; } i->mode = m; i->mode_set = true; } else i->mode = i->type == CREATE_DIRECTORY || i->type == TRUNCATE_DIRECTORY ? 0755 : 0644; if (age && !streq(age, "-")) { const char *a = age; if (*a == '~') { i->keep_first_level = true; a++; } if (parse_usec(a, &i->age) < 0) { log_error("[%s:%u] Invalid age '%s'.", fname, line, age); r = -EBADMSG; goto finish; } i->age_set = true; } h = needs_glob(i->type) ? globs : items; existing = hashmap_get(h, i->path); if (existing) { /* Two identical items are fine */ if (!item_equal(existing, i)) log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path); r = 0; goto finish; } r = hashmap_put(h, i->path, i); if (r < 0) { log_error("Failed to insert item %s: %s", i->path, strerror(-r)); goto finish; } i = NULL; r = 0; finish: free(user); free(group); free(mode); free(age); if (i) item_free(i); return r; }
//(DEV_UID *dev_uid, uint32_t device_type, uint32_t device_number) device_t* ressource_open(DEV_UID *virt_dev_uid, int32_t device_type, int32_t device_number){ //DEV_UID* real_UID = malloc(sizeof(DEV_UID)); DEV_UID* temp_UID = malloc(sizeof(DEV_UID)); virtual_dev_t *virtual_dev = (virtual_dev_t*)malloc(sizeof(virtual_dev_t)); virtual_dev->real_uid = (DEV_UID*)malloc(sizeof(DEV_UID)); virtual_dev_t *virtual_temp = NULL; device_t* device; any_t tmp; // virtual_devic zusammen bauen switch(device_type){ case(AP7000_UART_DEVICE): device = open_driver(temp_UID, AP7000_UART_DEVICE, device_number); virtual_dev->requested_device_type = device; virtual_dev->vdev_rxbuf = malloc(sizeof(SerialBuffer)); virtual_dev->vdev_txbuf = malloc(sizeof(SerialBuffer)); SerialBuffer_ctor( (SerialBuffer*)(virtual_dev->vdev_rxbuf) ); SerialBuffer_ctor( (SerialBuffer*)(virtual_dev->vdev_txbuf) ); uart1_set_rx_and_tx_buffer((SerialBuffer*)virtual_dev->vdev_txbuf,(SerialBuffer*)virtual_dev->vdev_rxbuf); break; case(AP7000_LED_DEVICE): break; default: break; } switch (*temp_UID) { case DEV_NOT_FREE: //generate new virtual UID an add to map *virt_dev_uid = generate_Virtual_UID(); //Find real uid in hashmap with key: device_type|device_number //hashmap_get(device_mapm) if(hashmap_get(device_to_real_uid_map,device_type|device_number,&tmp) == MAP_OK){ *temp_UID = *((DEV_UID*)tmp); virtual_dev->real_uid = temp_UID; }else{ while(1){} } if(hashmap_get(device_to_real_uid_map,device_type|device_number,&tmp) == MAP_OK){ hashmap_put(virt_uid_to_virt_dev_map,*virt_dev_uid, virtual_dev); // save pid to virtual_dev hashmap_put(pid_to_virt_dev_map, ptrRunningTask->pid, virtual_dev); virtual_dev->current_device_type = dev_null; return device; }else{ while(1){} } case DEV_NOT_FOUND: //TODO you're f****d... break; } *virt_dev_uid = generate_Virtual_UID(); *virtual_dev->real_uid = *temp_UID; virtual_dev->current_device_type = virtual_dev->requested_device_type; //add as first element hashmap_put(device_to_real_uid_map,device_type|device_number,(any_t)temp_UID); if(hashmap_get(device_to_real_uid_map,device_type|device_number,&tmp) == MAP_OK){ if(*temp_UID!=*(DEV_UID*)tmp){ while(1){}; } hashmap_put(virt_uid_to_virt_dev_map,*virt_dev_uid, virtual_dev); }else{ while(1){} } // save pid to virtual_dev hashmap_put(pid_to_virt_dev_map, ptrRunningTask->pid, virtual_dev); return device; }
void hashmap_sput(hashmap *hm, const char *key, void *value, unsigned int value_len) { hashmap_put(hm, key, strlen(key)+1, value, value_len); }
int bus_verify_polkit_async( sd_bus *bus, Hashmap **registry, sd_bus_message *m, const char *action, bool interactive, sd_bus_error *error, sd_bus_message_handler_t callback, void *userdata) { #ifdef ENABLE_POLKIT _cleanup_bus_message_unref_ sd_bus_message *pk = NULL; AsyncPolkitQuery *q; const char *sender; #endif _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; uid_t uid; int r; assert(bus); assert(registry); assert(m); assert(action); #ifdef ENABLE_POLKIT q = hashmap_get(*registry, m); if (q) { int authorized, challenge; /* This is the second invocation of this function, and * there's already a response from polkit, let's * process it */ assert(q->reply); if (sd_bus_message_is_method_error(q->reply, NULL)) { const sd_bus_error *e; /* Copy error from polkit reply */ e = sd_bus_message_get_error(q->reply); sd_bus_error_copy(error, e); /* Treat no PK available as access denied */ if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) return -EACCES; return sd_bus_error_get_errno(e); } r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}"); if (r >= 0) r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge); if (r < 0) return r; if (authorized) return 1; return -EACCES; } #endif r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds); if (r < 0) return r; r = sd_bus_creds_get_uid(creds, &uid); if (r < 0) return r; if (uid == 0) return 1; #ifdef ENABLE_POLKIT sender = sd_bus_message_get_sender(m); if (!sender) return -EBADMSG; r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func); if (r < 0) return r; r = sd_bus_message_new_method_call( bus, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority", "CheckAuthorization", &pk); if (r < 0) return r; r = sd_bus_message_append( pk, "(sa{sv})sa{ss}us", "system-bus-name", 1, "name", "s", sender, action, 0, interactive ? 1 : 0, NULL); if (r < 0) return r; q = new0(AsyncPolkitQuery, 1); if (!q) return -ENOMEM; q->request = sd_bus_message_ref(m); q->callback = callback; q->userdata = userdata; r = hashmap_put(*registry, m, q); if (r < 0) { async_polkit_query_free(bus, q); return r; } q->registry = *registry; r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial); if (r < 0) { async_polkit_query_free(bus, q); return r; } return 0; #endif return -EACCES; }
int set_put(Set *s, void *value) { return hashmap_put(MAKE_HASHMAP(s), value, value); }
int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; FILE *f = NULL; struct mntent* me; Hashmap *pids = NULL; if (argc > 1) { log_error("This program takes no argument."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_SYSLOG_OR_KMSG); log_parse_environment(); log_open(); umask(0022); if (!(f = setmntent("/etc/fstab", "r"))) { log_error("Failed to open /etc/fstab: %m"); goto finish; } if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) { log_error("Failed to allocate set"); goto finish; } ret = EXIT_SUCCESS; while ((me = getmntent(f))) { pid_t pid; int k; char *s; if (!mount_point_is_api(me->mnt_dir)) continue; log_debug("Remounting %s", me->mnt_dir); if ((pid = fork()) < 0) { log_error("Failed to fork: %m"); ret = 1; continue; } if (pid == 0) { const char *arguments[5]; /* Child */ arguments[0] = "/bin/mount"; arguments[1] = me->mnt_dir; arguments[2] = "-o"; arguments[3] = "remount"; arguments[4] = NULL; execv("/bin/mount", (char **) arguments); log_error("Failed to execute /bin/mount: %m"); _exit(EXIT_FAILURE); } /* Parent */ s = strdup(me->mnt_dir); if ((k = hashmap_put(pids, UINT_TO_PTR(pid), s)) < 0) { log_error("Failed to add PID to set: %s", strerror(-k)); ret = EXIT_FAILURE; continue; } } while (!hashmap_isempty(pids)) { siginfo_t si; char *s; zero(si); if (waitid(P_ALL, 0, &si, WEXITED) < 0) { if (errno == EINTR) continue; log_error("waitid() failed: %m"); ret = EXIT_FAILURE; break; } if ((s = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) { if (!is_clean_exit(si.si_code, si.si_status)) { if (si.si_code == CLD_EXITED) log_error("/bin/mount for %s exited with exit status %i.", s, si.si_status); else log_error("/bin/mount for %s terminated by signal %s.", s, signal_to_string(si.si_status)); ret = EXIT_FAILURE; } free(s); } } finish: if (pids) hashmap_free_free(pids); if (f) endmntent(f); return ret; }
static void init_backend(BuxtonConfig *config, BuxtonLayer *layer, BuxtonBackend **backend) { void *handle, *cast; _cleanup_free_ char *path = NULL; const char *name; char *error; int r; bool rb; module_init_func i_func; module_destroy_func d_func; BuxtonBackend *backend_tmp; assert(layer); assert(backend); if (layer->backend == BACKEND_GDBM) { name = "gdbm"; } else if (layer->backend == BACKEND_MEMORY) { name = "memory"; } else { buxton_log("Invalid backend type for layer: %s\n", layer->name); abort(); } backend_tmp = hashmap_get(config->backends, name); if (backend_tmp) { *backend = backend_tmp; return; } backend_tmp = malloc0(sizeof(BuxtonBackend)); if (!backend_tmp) { abort(); } r = asprintf(&path, "%s/%s.so", buxton_module_dir(), name); if (r == -1) { abort(); } /* Load the module */ handle = dlopen(path, RTLD_LAZY); if (!handle) { buxton_log("dlopen(): %s\n", dlerror()); abort(); } dlerror(); cast = dlsym(handle, "buxton_module_init"); if ((error = dlerror()) != NULL || !cast) { buxton_log("dlsym(): %s\n", error); abort(); } memcpy(&i_func, &cast, sizeof(i_func)); dlerror(); cast = dlsym(handle, "buxton_module_destroy"); if ((error = dlerror()) != NULL || !cast) { buxton_log("dlsym(): %s\n", error); abort(); } memcpy(&d_func, &cast, sizeof(d_func)); rb = i_func(backend_tmp); if (!rb) { buxton_log("buxton_module_init failed\n"); abort(); } if (!config->backends) { config->backends = hashmap_new(trivial_hash_func, trivial_compare_func); if (!config->backends) { abort(); } } r = hashmap_put(config->backends, name, backend_tmp); if (r != 1) { abort(); } backend_tmp->module = handle; backend_tmp->destroy = d_func; *backend = backend_tmp; }
int main() { char *o, *p, *line; queue *q; double *r, *s; double *pi = malloc(sizeof(double)); double *e = malloc(sizeof(double)); double *ans = malloc(sizeof(double)); *pi = 3.1415926535; *e = 2.7182818285; *ans = 0; hm = hashmap_new(); hashmap_put(hm, "pi", pi); hashmap_put(hm, "e", e); hashmap_put(hm, "ans", ans); /* read input using linenoise */ while((line = linenoise("> ")) != NULL) { /* add the line to history */ linenoiseHistoryAdd(line); /* check if there is an equals sign */ for (p = line; (*p != '\0') && (*p != '='); p++); if (*p == '\0') p = line; else { /* equals sign present */ /* check for spaces */ for (o = line; (*o != ' ') && (*o != '='); o++); *o = '\0'; p++; /* skip equals sign when parsing equation */ } q = syard_run(p); if (q == NULL) continue; #ifdef __DEBUG queue_foreach(q, testfunc, NULL); printf("\n"); #endif r = rpn_calc(q, variable_resolver, func_wl); if (r == NULL) continue; printf("= %g\n", *r); /* store ans */ *ans = *r; if (p != line) { /* equals sign present */ if ((s = hashmap_get(hm, line)) != NULL) { /* existing value, just overwrite it */ *s = *r; free(r); } else { /* new value */ hashmap_put(hm, line, r); } } else { /* no equals sign, so we're done with the number now */ free(r); } /* free storage and stuff */ linenoiseFree(line); } hashmap_iterate(hm, hm_cleaner, NULL); hashmap_destroy(hm); return 0; }
static int enumerate_dir_d(Hashmap *top, Hashmap *bottom, Hashmap *drops, const char *toppath, const char *drop) { _cleanup_free_ char *unit = NULL; _cleanup_free_ char *path = NULL; _cleanup_strv_free_ char **list = NULL; char **file; char *c; int r; assert(!endswith(drop, "/")); path = strjoin(toppath, "/", drop); if (!path) return -ENOMEM; log_debug("Looking at %s", path); unit = strdup(drop); if (!unit) return -ENOMEM; c = strrchr(unit, '.'); if (!c) return -EINVAL; *c = 0; r = get_files_in_directory(path, &list); if (r < 0) return log_error_errno(r, "Failed to enumerate %s: %m", path); STRV_FOREACH(file, list) { Hashmap *h; int k; char *p; char *d; if (!endswith(*file, ".conf")) continue; p = strjoin(path, "/", *file); if (!p) return -ENOMEM; d = p + strlen(toppath) + 1; log_debug("Adding at top: %s %s %s", d, special_glyph(ARROW), p); k = hashmap_put(top, d, p); if (k >= 0) { p = strdup(p); if (!p) return -ENOMEM; d = p + strlen(toppath) + 1; } else if (k != -EEXIST) { free(p); return k; } log_debug("Adding at bottom: %s %s %s", d, special_glyph(ARROW), p); free(hashmap_remove(bottom, d)); k = hashmap_put(bottom, d, p); if (k < 0) { free(p); return k; } h = hashmap_get(drops, unit); if (!h) { h = hashmap_new(&string_hash_ops); if (!h) return -ENOMEM; hashmap_put(drops, unit, h); unit = strdup(unit); if (!unit) return -ENOMEM; } p = strdup(p); if (!p) return -ENOMEM; log_debug("Adding to drops: %s %s %s %s %s", unit, special_glyph(ARROW), basename(p), special_glyph(ARROW), p); k = hashmap_put(h, basename(p), p); if (k < 0) { free(p); if (k != -EEXIST) return k; } }
static int do_execute( char **directories, usec_t timeout, gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX], void* const callback_args[_STDOUT_CONSUME_MAX], int output_fd, char *argv[], char *envp[], ExecDirFlags flags) { _cleanup_hashmap_free_free_ Hashmap *pids = NULL; _cleanup_strv_free_ char **paths = NULL; char **path, **e; int r; bool parallel_execution; /* We fork this all off from a child process so that we can somewhat cleanly make * use of SIGALRM to set a time limit. * * We attempt to perform parallel execution if configured by the user, however * if `callbacks` is nonnull, execution must be serial. */ parallel_execution = FLAGS_SET(flags, EXEC_DIR_PARALLEL) && !callbacks; r = conf_files_list_strv(&paths, NULL, NULL, CONF_FILES_EXECUTABLE|CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char* const*) directories); if (r < 0) return log_error_errno(r, "Failed to enumerate executables: %m"); if (parallel_execution) { pids = hashmap_new(NULL); if (!pids) return log_oom(); } /* Abort execution of this process after the timout. We simply rely on SIGALRM as * default action terminating the process, and turn on alarm(). */ if (timeout != USEC_INFINITY) alarm(DIV_ROUND_UP(timeout, USEC_PER_SEC)); STRV_FOREACH(e, envp) if (putenv(*e) != 0) return log_error_errno(errno, "Failed to set environment variable: %m"); STRV_FOREACH(path, paths) { _cleanup_free_ char *t = NULL; _cleanup_close_ int fd = -1; pid_t pid; t = strdup(*path); if (!t) return log_oom(); if (callbacks) { fd = open_serialization_fd(basename(*path)); if (fd < 0) return log_error_errno(fd, "Failed to open serialization file: %m"); } r = do_spawn(t, argv, fd, &pid); if (r <= 0) continue; if (parallel_execution) { r = hashmap_put(pids, PID_TO_PTR(pid), t); if (r < 0) return log_oom(); t = NULL; } else { r = wait_for_terminate_and_check(t, pid, WAIT_LOG); if (FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS)) { if (r < 0) continue; } else if (r > 0) return r; if (callbacks) { if (lseek(fd, 0, SEEK_SET) < 0) return log_error_errno(errno, "Failed to seek on serialization fd: %m"); r = callbacks[STDOUT_GENERATE](fd, callback_args[STDOUT_GENERATE]); fd = -1; if (r < 0) return log_error_errno(r, "Failed to process output from %s: %m", *path); } } }