mirror of the now-defunct rocklinux.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

412 lines
8.3 KiB

  1. /* Bash (wallclock-time) profiler. Written by Clifford Wolf.
  2. *
  3. * Usage:
  4. * gcc -shared -fPIC -Wall -o config_helper.so config_helper.c
  5. * enable -f ./config_helper.so cfghlp
  6. *
  7. * Note: This builtin trusts that it is called correctly. If it is
  8. * called the wrong way, segfaults etc. are possible.
  9. */
  10. /* Some declarations copied from bash-2.05b headers */
  11. #include <stdint.h>
  12. typedef struct word_desc {
  13. char *word;
  14. int flags;
  15. } WORD_DESC;
  16. typedef struct word_list {
  17. struct word_list *next;
  18. WORD_DESC *word;
  19. } WORD_LIST;
  20. typedef int sh_builtin_func_t(WORD_LIST *);
  21. #define BUILTIN_ENABLED 0x1
  22. struct builtin {
  23. char *name;
  24. sh_builtin_func_t *function;
  25. int flags;
  26. char * const *long_doc;
  27. const char *short_doc;
  28. char *handle;
  29. };
  30. /* my hellobash builtin */
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <stdlib.h>
  34. #include <sys/time.h>
  35. #include <sys/types.h>
  36. #include <regex.h>
  37. struct package;
  38. struct package {
  39. int status;
  40. char stages[10];
  41. char *prio;
  42. char *repository;
  43. char *name;
  44. char *alias;
  45. char *version;
  46. char *prefix;
  47. /* flags must end with a space character
  48. (for easily searching for flags). */
  49. char *flags;
  50. struct package *next;
  51. };
  52. struct package *package_list = 0;
  53. int read_pkg_list(const char *file) {
  54. FILE *f = fopen(file, "r");
  55. struct package *pkg = package_list;
  56. struct package *pkg_tmp;
  57. char line[1024], *tok;
  58. int i;
  59. while (pkg) {
  60. free(pkg->prio);
  61. free(pkg->repository);
  62. free(pkg->name);
  63. free(pkg->alias);
  64. free(pkg->version);
  65. free(pkg->prefix);
  66. free(pkg->flags);
  67. pkg = (pkg_tmp=pkg)->next;
  68. free(pkg_tmp);
  69. }
  70. pkg = package_list = 0;
  71. while (fgets(line, 1024, f)) {
  72. pkg_tmp = calloc(1, sizeof(struct package));
  73. tok = strtok(line, " ");
  74. pkg_tmp->status = line[0] == 'X';
  75. tok = strtok(0, " ");
  76. for (i=0; i<10; i++)
  77. pkg_tmp->stages[i] = tok[i] != '-' ? tok[i] : 0;
  78. tok = strtok(0, " ");
  79. pkg_tmp->prio = strdup(tok);
  80. tok = strtok(0, " ");
  81. pkg_tmp->repository = strdup(tok);
  82. tok = strtok(0, " ");
  83. char *c = strchr(tok, '=');
  84. if (c)
  85. {
  86. pkg_tmp->name = malloc(c-tok+1);
  87. pkg_tmp->name[c-tok] = '\0';
  88. strncpy(pkg_tmp->name, tok, c-tok);
  89. pkg_tmp->alias = strdup(c+1);
  90. }
  91. else
  92. {
  93. pkg_tmp->name = strdup(tok);
  94. pkg_tmp->alias = strdup(tok);
  95. }
  96. tok = strtok(0, " ");
  97. pkg_tmp->version = strdup(tok);
  98. tok = strtok(0, " ");
  99. pkg_tmp->prefix = strdup(tok);
  100. tok = strtok(0, "\n");
  101. tok[strlen(tok)-1] = 0;
  102. pkg_tmp->flags = strdup(tok);
  103. if ( !package_list )
  104. pkg=package_list=pkg_tmp;
  105. else
  106. pkg=pkg->next=pkg_tmp;
  107. }
  108. fclose(f);
  109. return 0;
  110. }
  111. int write_pkg_list(const char *file) {
  112. FILE *f = fopen(file, "w");
  113. struct package *pkg = package_list;
  114. int i;
  115. while (pkg) {
  116. fprintf(f, "%c ", pkg->status ? 'X' : 'O');
  117. for (i=0; i<10; i++)
  118. fprintf(f, "%c", pkg->stages[i] ? pkg->stages[i] : '-');
  119. fprintf(f, " %s %s %s", pkg->prio, pkg->repository, pkg->name);
  120. if (strcmp(pkg->name, pkg->alias))
  121. fprintf(f, "=%s", pkg->alias);
  122. fprintf(f, " %s %s %s0\n", pkg->version, pkg->prefix, pkg->flags);
  123. pkg = pkg->next;
  124. }
  125. fclose(f);
  126. return 0;
  127. }
  128. regex_t * create_pkg_regex(const char* pattern)
  129. {
  130. char fullpattern[512];
  131. snprintf(fullpattern, 512, "[= ]%s ", pattern);
  132. regex_t *preg = malloc(sizeof(regex_t));
  133. int errcode = regcomp(preg, fullpattern,
  134. REG_EXTENDED | REG_ICASE | REG_NOSUB | REG_NEWLINE);
  135. if (errcode)
  136. {
  137. int errbuf_size = regerror(errcode, preg, 0, 0);
  138. char *errbuf = malloc(errbuf_size);
  139. regerror(errcode, preg, errbuf, errbuf_size);
  140. fprintf(stderr, "config_helper: create_pkg_regex(%s): %s\n",
  141. pattern, errbuf);
  142. free(errbuf);
  143. return NULL;
  144. }
  145. return preg;
  146. }
  147. char * create_pkg_line(struct package *pkg)
  148. {
  149. char *line = calloc(1024, sizeof(char));
  150. int i, offset = 0;
  151. offset += snprintf(line+offset, 1024-offset, "%c ",
  152. pkg->status ? 'X' : 'O');
  153. for (i=0; i<10; i++)
  154. offset += snprintf(line+offset, 1024-offset, "%c",
  155. pkg->stages[i] ? pkg->stages[i] : '-');
  156. offset += snprintf(line+offset, 1024-offset, " %s %s %s",
  157. pkg->prio, pkg->repository, pkg->name);
  158. if (strcmp(pkg->name, pkg->alias))
  159. offset += snprintf(line+offset, 1024-offset, "=%s", pkg->alias);
  160. offset += snprintf(line+offset, 1024-offset, " %s %s %s0\n",
  161. pkg->version, pkg->prefix, pkg->flags);
  162. return line;
  163. }
  164. int pkgcheck(const char *pattern, const char *mode)
  165. {
  166. struct package *pkg = package_list;
  167. char fullpattern[512];
  168. snprintf(fullpattern, 512, "[= ]%s ", pattern);
  169. regex_t *preg = create_pkg_regex(pattern);
  170. if (preg == NULL) return 0;
  171. while (pkg) {
  172. char *line = create_pkg_line(pkg);
  173. int match = !regexec(preg, line, 0, 0, 0);
  174. free(line);
  175. if (match)
  176. {
  177. switch (mode[0]) {
  178. case 'X':
  179. if (pkg->status) goto found;
  180. break;
  181. case 'O':
  182. if (!pkg->status) goto found;
  183. break;
  184. case '.':
  185. goto found;
  186. }
  187. }
  188. pkg = pkg->next;
  189. }
  190. regfree(preg);
  191. return 1;
  192. found:
  193. regfree(preg);
  194. return 0;
  195. }
  196. int pkgswitch(int mode, char **args)
  197. {
  198. struct package *pkg = package_list;
  199. struct package *last_pkg = 0;
  200. struct package *pkg_tmp = 0;
  201. regex_t *preg = create_pkg_regex(args[0]);
  202. if (preg == NULL) return 0;
  203. while (pkg) {
  204. char *line = create_pkg_line(pkg);
  205. int match = !regexec(preg, line, 0, 0, 0);
  206. free(line);
  207. if (match) {
  208. if ( !mode ) {
  209. *(last_pkg ? &(last_pkg->next) : &package_list) = pkg->next;
  210. free(pkg->prio);
  211. free(pkg->repository);
  212. free(pkg->name);
  213. free(pkg->alias);
  214. free(pkg->version);
  215. free(pkg->prefix);
  216. free(pkg->flags);
  217. pkg = (pkg_tmp=pkg)->next;
  218. free(pkg_tmp);
  219. continue;
  220. } else
  221. pkg->status = mode == 1;
  222. }
  223. pkg = (last_pkg=pkg)->next;
  224. }
  225. regfree(preg);
  226. return 0;
  227. }
  228. int pkgfork(char *pkgname, char *xpkg, char** opt)
  229. {
  230. struct package *fork, *pkg;
  231. int i, k;
  232. for (pkg = package_list; pkg; pkg = pkg->next)
  233. if (!strcmp(pkg->alias, pkgname))
  234. break;
  235. if (!pkg) return 1;
  236. fork = calloc(1, sizeof(struct package));
  237. fork->status = pkg->status;
  238. for (k=0; k<10; k++)
  239. fork->stages[k] = pkg->stages[k];
  240. fork->prio = strdup(pkg->prio);
  241. fork->repository = strdup(pkg->repository);
  242. fork->name = strdup(pkgname);
  243. fork->alias = strdup(xpkg);
  244. fork->version = strdup(pkg->version);
  245. fork->prefix = strdup(pkg->prefix);
  246. fork->flags = strdup(pkg->flags);
  247. fork->next = pkg->next;
  248. pkg->next = fork;
  249. for (i=0; *opt[i] && *opt[i+1]; i+=2)
  250. {
  251. if (!strcmp(opt[i], "status"))
  252. fork->status= opt[i+1][0] == 'X';
  253. else if (!strcmp(opt[i], "stages"))
  254. for (k=0; k<10; k++)
  255. fork->stages[k] = opt[i+1][k] != '-' ? opt[i+1][k] : 0;
  256. else if (!strcmp(opt[i], "priority"))
  257. {
  258. free(fork->prio);
  259. fork->prio = strdup(opt[i+1]);
  260. }
  261. else if (!strcmp(opt[i], "version"))
  262. {
  263. free(fork->version);
  264. fork->version = strdup(opt[i+1]);
  265. }
  266. else if (!strcmp(opt[i], "prefix"))
  267. {
  268. free(fork->prefix);
  269. fork->prefix = strdup(opt[+1]);
  270. }
  271. else if (!strcmp(opt[i], "flag"))
  272. {
  273. char buf[512], flag[512];
  274. snprintf(flag, 512, " %s ", opt[i+1]);
  275. if (! strstr(fork->flags, flag))
  276. {
  277. free(fork->flags);
  278. snprintf(buf, 512, "%s%s ", pkg->flags, opt[i+1]);
  279. fork->flags = strdup(buf);
  280. }
  281. }
  282. else if (!strcmp(opt[i], "unflag"))
  283. {
  284. char buf[512], flag[512];
  285. snprintf(flag, 512, " %s ", opt[i+1]);
  286. char *flagstart = strstr(fork->flags, flag);
  287. if (flagstart)
  288. {
  289. int len = flagstart - fork->flags + 1;
  290. strncpy(buf, fork->flags, len);
  291. strncpy(buf+len, flagstart+strlen(flag), 512-len);
  292. free(fork->flags);
  293. fork->flags = strdup(buf);
  294. }
  295. }
  296. }
  297. return 0;
  298. }
  299. int cfghlp_builtin(WORD_LIST *list)
  300. {
  301. char *args[10];
  302. int i;
  303. for (i=0; i<9 && list; i++) {
  304. args[i] = list->word->word;
  305. list = list->next;
  306. }
  307. for (; i<10; i++) {
  308. args[i] = "";
  309. }
  310. if (!strcmp(args[0],"pkg_in"))
  311. return read_pkg_list(args[1]);
  312. else if (!strcmp(args[0],"pkg_out"))
  313. return write_pkg_list(args[1]);
  314. else if (!strcmp(args[0],"pkgcheck"))
  315. return pkgcheck(args[1], args[2]);
  316. else if (!strcmp(args[0],"pkgremove"))
  317. return pkgswitch(0, args+1);
  318. else if (!strcmp(args[0],"pkgenable"))
  319. return pkgswitch(1, args+1);
  320. else if (!strcmp(args[0],"pkgdisable"))
  321. return pkgswitch(2, args+1);
  322. else if (!strcmp(args[0],"pkgfork"))
  323. return pkgfork(args[1], args[2], args+3);
  324. return 1;
  325. }
  326. char *cfghlp_doc[] = {
  327. "ROCK Linux Config Helper",
  328. 0
  329. };
  330. struct builtin cfghlp_struct = {
  331. "cfghlp",
  332. &cfghlp_builtin,
  333. BUILTIN_ENABLED,
  334. cfghlp_doc,
  335. "ROCK Linux Config Helper",
  336. 0
  337. };