/* * variable_add() * * dodaje zmienn± do listy zmiennych. * * - name - nazwa, * - short_name - krótka nazwa, * - type - typ zmiennej, * - display - czy i jak ma wy¶wietlaæ, * - ptr - wska¼nik do zmiennej, * - notify - funkcja powiadomienia, * - map - mapa warto¶ci, * - dyndisplay - funkcja sprawdzaj±ca czy wy¶wietliæ zmienn±. * * zwraca 0 je¶li siê uda³o, je¶li nie to -1. */ int variable_add(const char *name, const char *short_name, int type, int display, void *ptr, void (*notify)(const char*), struct value_map *map, int (*dyndisplay)(const char *name)) { struct variable v; list_t l; if (!name || (type != VAR_FOREIGN && !short_name)) return -1; if (type != VAR_FOREIGN) { for (l = variables; l; l = l->next) { struct variable *v = l->data; if (!strcmp(v->short_name, short_name)) { fprintf(stderr, "Error! Variable short name conflict:\n- short name: \"%s\"\n- existing variable: \"%s\"\n- conflicting variable: \"%s\"\n\nPress any key to continue...", short_name, v->name, name); getchar(); } } } memset(&v, 0, sizeof(v)); v.name = xstrdup(name); v.name_hash = ekg_hash(name); v.type = type; if (short_name) strlcpy(v.short_name, short_name, sizeof(v.short_name)); v.display = display; v.ptr = ptr; v.notify = notify; v.map = map; v.dyndisplay = dyndisplay; return (list_add(&variables, &v, sizeof(v)) ? 0 : -1); }
/* * variable_remove() * * usuwa zmienn±. */ int variable_remove(plugin_t *plugin, const char *name) { int hash; GSList *vl; if (!name) return -1; hash = ekg_hash(name); for (vl = variables; vl; vl = vl->next) { variable_t *v = vl->data; if (!v->name) continue; if (hash == v->name_hash && plugin == v->plugin && !xstrcasecmp(name, v->name)) { variables_remove(v); return 0; } } return -1; }
/* * variable_find() * * znajduje strukturê `variable' opisuj±c± zmienn± o podanej nazwie. * * - name. */ struct variable *variable_find(const char *name) { list_t l; int hash; if (!name) return NULL; hash = ekg_hash(name); for (l = variables; l; l = l->next) { struct variable *v = l->data; if (!v->ptr) continue; if (v->name_hash == hash && !strcasecmp(v->name, name)) return v; } return NULL; }
/** * jogger_checkoutfile() * * Tries to open given file (check), and reads it, if expected (checkout). * It is designed to be proof to special file problems (especially named pipe ones). * * @param file - filename to open. * @param data - pointer to store file contents or NULL, if don't want to read it. * @param len - pointer to store filelength or NULL, if not needed. * @param hash - pointer to store filehash or NULL, if not needed. * @param maxlen - maximum filesize to accept (not counting additional NUL) or 0, if n/a. * @param quiet - if set, don't output anything to __status. * * @return 0 on success, errno on failure. */ static int jogger_checkoutfile(const char *file, char **data, int *len, char **hash, const int maxlen, const int quiet) { static char jogger_hash[sizeof(int)*2+3]; int mylen, fs, fd; const char *fn = prepare_path_user(file); if (!fn) return EINVAL; if ((fd = open(fn, O_RDONLY|O_NONBLOCK)) == -1) { /* we use O_NONBLOCK to get rid of FIFO problems */ const int err = errno; if (err == ENXIO) printq("io_nonfile", file); else printq("io_cantopen", file, strerror(err)); return err; } { struct stat st; if ((fstat(fd, &st) == -1) || !S_ISREG(st.st_mode)) { close(fd); printq("io_nonfile", file); return EISDIR; /* nearest, I think */ } fs = st.st_size; } int bufsize = (fs ? (maxlen && fs > maxlen ? maxlen+1 : fs+1) : 0x4000); /* we leave 1 byte for additional NUL */ char *out = xmalloc(bufsize); void *p = out; int _read = 0, res; { int cf = fcntl(fd, F_GETFL); if (cf == -1) /* evil thing */ cf = 0; else cf &= ~O_NONBLOCK; fcntl(fd, F_SETFL, cf); } while ((res = read(fd, p, bufsize-_read))) { if (res == -1) { const int err = errno; if (err != EINTR && err != EAGAIN) { close(fd); printq("io_cantread", file, strerror(errno)); return err; } } else { _read += res; if (maxlen && _read > maxlen) { xfree(out); printq("io_toobig", file, ekg_itoa(_read > fs ? _read : fs), ekg_itoa(maxlen)); return EFBIG; } else if (_read == bufsize) { /* fs sucks? */ bufsize += 0x4000; out = xrealloc(out, bufsize); p = out+_read; } else p += res; } } close(fd); if (_read == 0) { xfree(out); printq("io_emptyfile", file); return EINVAL; /* like mmap() */ } else if (_read+1 != bufsize) { out = xrealloc(out, _read+1); out[_read] = 0; /* add NUL */ } mylen = xstrlen(out); if (fs && _read > fs) printq("io_expanded", file, ekg_itoa(_read), ekg_itoa(fs)); else if (_read < fs) printq("io_truncated", file, ekg_itoa(_read), ekg_itoa(fs)); if (_read > mylen) printq("io_binaryfile", file, ekg_itoa(mylen), ekg_itoa(_read)); if (len) *len = _read; /* I don't want to write my own hashing function, so using EKG2 one * it will fail to hash data after any \0 in file, if there're any * but we also aren't prepared to handle them */ if (hash) { char sizecont[8]; snprintf(sizecont, 8, "0x%%0%lux", sizeof(int)*2); snprintf(jogger_hash, sizeof(int)*2+3, sizecont, ekg_hash(out)); *hash = jogger_hash; } if (data) *data = out; else xfree(out); return 0; }