/* Bash (wallclock-time) profiler. Written by Clifford Wolf. * * Usage: * gcc -shared -fPIC -Wall -o config_helper.so config_helper.c * enable -f ./config_helper.so cfghlp * * Note: This builtin trusts that it is called correctly. If it is * called the wrong way, segfaults etc. are possible. */ /* Some declarations copied from bash-2.05b headers */ #include typedef struct word_desc { char *word; int flags; } WORD_DESC; typedef struct word_list { struct word_list *next; WORD_DESC *word; } WORD_LIST; typedef int sh_builtin_func_t(WORD_LIST *); #define BUILTIN_ENABLED 0x1 struct builtin { char *name; sh_builtin_func_t *function; int flags; char * const *long_doc; const char *short_doc; char *handle; }; /* my hellobash builtin */ #include #include #include #include struct package; struct package { int status; char stages[10]; char *prio; char *repository; char *name; char *alias; char *version; char *prefix; char *flags; struct package *next; }; struct package *package_list = 0; int read_pkg_list(const char *file) { FILE *f = fopen(file, "r"); struct package *pkg = package_list; struct package *pkg_tmp; char line[1024], *tok; int i; while (pkg) { free(pkg->prio); free(pkg->repository); free(pkg->name); free(pkg->alias); free(pkg->version); free(pkg->prefix); free(pkg->flags); pkg = (pkg_tmp=pkg)->next; free(pkg_tmp); } pkg = package_list = 0; while (fgets(line, 1024, f)) { pkg_tmp = calloc(1, sizeof(struct package)); tok = strtok(line, " "); pkg_tmp->status = line[0] == 'X'; tok = strtok(0, " "); for (i=0; i<10; i++) pkg_tmp->stages[i] = tok[i] != '-' ? tok[i] : 0; tok = strtok(0, " "); pkg_tmp->prio = strdup(tok); tok = strtok(0, " "); pkg_tmp->repository = strdup(tok); tok = strtok(0, " "); pkg_tmp->name = strdup(tok); pkg_tmp->alias = strdup(tok); tok = strtok(0, " "); pkg_tmp->version = strdup(tok); tok = strtok(0, " "); pkg_tmp->prefix = strdup(tok); tok = strtok(0, "\n"); tok[strlen(tok)-2] = 0; pkg_tmp->flags = strdup(tok); if ( !package_list ) pkg=package_list=pkg_tmp; else pkg=pkg->next=pkg_tmp; } fclose(f); return 0; } int write_pkg_list(const char *file) { FILE *f = fopen(file, "w"); struct package *pkg = package_list; int i; while (pkg) { fprintf(f, "%c ", pkg->status ? 'X' : 'O'); for (i=0; i<10; i++) fprintf(f, "%c", pkg->stages[i] ? pkg->stages[i] : '-'); fprintf(f, " %s %s %s", pkg->prio, pkg->repository, pkg->name); if (strcmp(pkg->name, pkg->alias)) fprintf(f, "=%s", pkg->alias); fprintf(f, " %s %s %s 0\n", pkg->version, pkg->prefix, pkg->flags); pkg = pkg->next; } fclose(f); return 0; } int pkgcheck(const char *pattern, const char *mode) { struct package *pkg = package_list; char *pattern_copy = strdup(pattern); char *pat_list[10]; int i; pat_list[0] = strtok(pattern_copy, "|"); for (i=1; i<10; i++) if ( !(pat_list[i] = strtok(0, "|")) ) break; while (pkg) { for (i=0; i<10 && pat_list[i]; i++) if (!strcmp(pkg->alias, pat_list[i])) switch (mode[0]) { case 'X': if (pkg->status) goto found; break; case 'O': if (!pkg->status) goto found; break; case '.': goto found; } pkg = pkg->next; } free(pattern_copy); return 1; found: free(pattern_copy); return 0; } int pkgswitch(int mode, char **args) { struct package *pkg = package_list; struct package *last_pkg = 0; struct package *pkg_tmp = 0; int i; while (pkg) { for (i=0; *args[i]; i++) if (!strcmp(pkg->alias, args[i])) { if ( !mode ) { *(last_pkg ? &(last_pkg->next) : &package_list) = pkg->next; free(pkg->prio); free(pkg->repository); free(pkg->name); free(pkg->alias); free(pkg->version); free(pkg->prefix); free(pkg->flags); pkg = (pkg_tmp=pkg)->next; free(pkg_tmp); continue; } else pkg->status = mode == 1; } pkg = (last_pkg=pkg)->next; } return 0; } int cfghlp_builtin(WORD_LIST *list) { char *args[10]; int i; for (i=0; i<9 && list; i++) { args[i] = list->word->word; list = list->next; } for (; i<10; i++) { args[i] = ""; } if (!strcmp(args[0],"pkg_in")) return read_pkg_list(args[1]); if (!strcmp(args[0],"pkg_out")) return write_pkg_list(args[1]); if (!strcmp(args[0],"pkgcheck")) return pkgcheck(args[1], args[2]); if (!strcmp(args[0],"pkgremove")) return pkgswitch(0, args+1); if (!strcmp(args[0],"pkgenable")) return pkgswitch(1, args+1); if (!strcmp(args[0],"pkgdisable")) return pkgswitch(2, args+1); return 1; } char *cfghlp_doc[] = { "ROCK Linux Config Helper", 0 }; struct builtin cfghlp_struct = { "cfghlp", &cfghlp_builtin, BUILTIN_ENABLED, cfghlp_doc, "ROCK Linux Config Helper", 0 };