diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | configure.in | 1 | ||||
-rw-r--r-- | etc/Makefile.am | 1 | ||||
-rw-r--r-- | etc/mpio/mpioshrc | 5 | ||||
-rw-r--r-- | mpiosh/Makefile.am | 19 | ||||
-rw-r--r-- | mpiosh/callback.c | 17 | ||||
-rw-r--r-- | mpiosh/cfgio.c | 654 | ||||
-rw-r--r-- | mpiosh/cfgio.h | 453 | ||||
-rw-r--r-- | mpiosh/command.c | 6 | ||||
-rw-r--r-- | mpiosh/command.h | 4 | ||||
-rw-r--r-- | mpiosh/config.c | 162 | ||||
-rw-r--r-- | mpiosh/config.h | 48 | ||||
-rw-r--r-- | mpiosh/global.c | 21 | ||||
-rw-r--r-- | mpiosh/global.h | 36 | ||||
-rw-r--r-- | mpiosh/mpiosh.c | 38 | ||||
-rw-r--r-- | mpiosh/readline.c | 23 |
18 files changed, 1448 insertions, 60 deletions
@@ -1,3 +1,17 @@ +2002-10-29 Andreas Buesching <crunchy@tzi.de> + + * mpiosh/mpiosh.c (mpiosh_init): uses the new configuration file + support to initialise the shell + + * etc/mpio/mpioshrc: add a sample configuration file will be + install as a global configuration file in + @sysconfdir@/mpio/mpioshrc + + * mpiosh/cfgio.c, mpiosh/cfgio.c, mpiosh/config.c, + mpiosh/config.h: added these new files to support global and user + configuration files. + + 2002-10-27 Markus Germeier <mager@tzi.de> * libmpio/mpio.{c,h}: split mpio_file_{get,put} into several diff --git a/Makefile.am b/Makefile.am index 8bf1d26..3b1ac82 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=kernel libmpio mpiosh +SUBDIRS=kernel libmpio mpiosh etc sbin_SCRIPTS=mkmpiodev EXTRA_DIST=mpio.spec mkmpiodev
\ No newline at end of file @@ -1,4 +1,4 @@ -$Id: TODO,v 1.16 2002/10/13 17:14:51 germeier Exp $ +$Id: TODO,v 1.17 2002/10/29 20:03:34 crunchy Exp $ * Kernel Module - the MPIO can no multitasking, so: @@ -39,4 +39,6 @@ $Id: TODO,v 1.16 2002/10/13 17:14:51 germeier Exp $ - using stdin for reading command sequences [DONE] - fill: uses current local directory to fill the current memory card + options: random, best(?) + - configuration files [almost DONE] + - save command history diff --git a/configure.in b/configure.in index 3af68e4..4fd895a 100644 --- a/configure.in +++ b/configure.in @@ -72,6 +72,7 @@ AC_OUTPUT( kernel/Makefile libmpio/Makefile mpiosh/Makefile + etc/Makefile mpio.spec ) diff --git a/etc/Makefile.am b/etc/Makefile.am new file mode 100644 index 0000000..02f1137 --- /dev/null +++ b/etc/Makefile.am @@ -0,0 +1 @@ +sysconf_DATA = mpio/mpioshrc
\ No newline at end of file diff --git a/etc/mpio/mpioshrc b/etc/mpio/mpioshrc new file mode 100644 index 0000000..516b7d0 --- /dev/null +++ b/etc/mpio/mpioshrc @@ -0,0 +1,5 @@ +[mpiosh] +default_mem=internal +prompt_int=[;1mmpio <i>[m +prompt_ext=[;1mmpio <e>[m + diff --git a/mpiosh/Makefile.am b/mpiosh/Makefile.am index d6586a8..ed5843e 100644 --- a/mpiosh/Makefile.am +++ b/mpiosh/Makefile.am @@ -2,7 +2,22 @@ INCLUDES=-I.. bin_PROGRAMS=mpiosh -mpiosh_SOURCES=mpiosh.c callback.c readline.c command.c global.c +mpiosh_SOURCES = mpiosh.c \ + callback.c \ + readline.c \ + command.c \ + global.c \ + cfgio.c \ + config.c + +AM_CFLAGS=-DSYSCONFDIR=\"@sysconfdir@\" + mpiosh_LDADD=../libmpio/libmpio.la -lreadline -lncurses -noinst_HEADERS=mpiosh.h callback.h readline.h command.h global.h
\ No newline at end of file +noinst_HEADERS = mpiosh.h \ + callback.h \ + readline.h \ + command.h \ + global.h \ + cfgio.h \ + config.h
\ No newline at end of file diff --git a/mpiosh/callback.c b/mpiosh/callback.c index 24cb402..dfd8474 100644 --- a/mpiosh/callback.c +++ b/mpiosh/callback.c @@ -2,7 +2,7 @@ * * Author: Andreas Büsching <crunchy@tzi.de> * - * $Id: callback.c,v 1.29 2002/10/27 17:37:27 germeier Exp $ + * $Id: callback.c,v 1.30 2002/10/29 20:03:34 crunchy Exp $ * * Copyright (C) 2001 Andreas Büsching <crunchy@tzi.de> * @@ -76,8 +76,8 @@ mpiosh_cmd_version(char *args[]) void mpiosh_cmd_help(char *args[]) { - mpiosh_cmd_t *cmd = commands; - int ignore; + struct mpiosh_cmd_t *cmd = commands; + int ignore; while (cmd->cmd) { if (args[0] != NULL) { @@ -418,17 +418,17 @@ mpiosh_cmd_mput(char *args[]) FTYPE_MUSIC, mpiosh_callback_put) == -1) { mpio_perror("error"); /* an existing file is no reason for a complete abort!! */ - if (mpio_errno()==MPIO_ERR_FILE_EXISTS) + if (mpio_errno() == MPIO_ERR_FILE_EXISTS) continue; break; } - written=1; /* we did write something, so do mpio_sync afterwards */ + written = 1; /* we did write something, so do mpio_sync afterwards */ printf("\n"); } else { regerror(error, ®ex, errortext, 100); - debugn (2, "file does not match: %s (%s)\n", - (*run)->d_name, errortext); + debugn(2, "file does not match: %s (%s)\n", + (*run)->d_name, errortext); } free(*run); } @@ -646,7 +646,7 @@ mpiosh_cmd_dump_mem(char *args[]) void mpiosh_cmd_config(char *args[]) { - BYTE *config_data, *p; + BYTE *config_data; int size; MPIOSH_CHECK_CONNECTION_CLOSED; @@ -715,7 +715,6 @@ mpiosh_cmd_config(char *args[]) fprintf(stderr, "error: no arguments given\n"); printf("config [read|write|show] <\n"); } - } void diff --git a/mpiosh/cfgio.c b/mpiosh/cfgio.c new file mode 100644 index 0000000..b8a1829 --- /dev/null +++ b/mpiosh/cfgio.c @@ -0,0 +1,654 @@ +#include "cfgio.h" + +#include <sys/stat.h> +#include <unistd.h> + +/*************************************************** + * help!!! functions + ***************************************************/ + +char * +cfg_resolve_path(const char *filename) +{ + char *fn = NULL; + + if (filename[0] != '~') return strdup(filename); + + if (filename[1] == '/' ) { + /* own home directory */ + char *home; + if ((home = getenv ("HOME")) == NULL) { + fn = strdup(filename); + } else { + fn = (char *)malloc(strlen(home) + strlen(filename+1) + 1); + sprintf(fn, "%s%s", home,filename+1); + } + } else { + /* other home directory */ + struct passwd *pw; + char *dir = strchr(filename, '/'); + size_t len = (size_t)(dir - filename-1); + char user[len]; + strncpy(user, filename+1, len); + user[len] = '\0'; + + if (!(pw = getpwnam(user))) { + fn = strdup(filename); + } else { + fn = (char *) malloc(strlen(pw->pw_dir) + strlen(dir) + 1); + sprintf (fn, "%s%s",pw->pw_dir, dir); + } + } + + return fn; +} + +/*************************************************** + * open functions + ***************************************************/ +int cfg_save(CfgHandle *h, int cl){ + if (h && h->file) { + FILE *f = h->file; + CfgGroup *group; + group = h->first; + + while (group) { + CfgKey *key; + fprintf(f, "[%s]\n", group->name); + key = group->first; + while (key) { + fprintf(f, "%s=%s\n", key->name, key->value ? key->value : ""); + key = key->next; + } + fprintf(f, "\n"); + group = group->next; + } + if (cl) return cfg_close(h); + return 0; + } + return -1; +} + +int cfg_save_as(CfgHandle *h, const char* filename, int err, int cl){ + if (h && filename) { + int res; + res = cfg_handle_change_filename(h, filename); + if (res) return res; + res = cfg_open(h, err, "w+"); + if (res) return res; + return cfg_save(h,cl); + } + return -1; +} + + +int cfg_read(CfgHandle *h, int cl){ + if (h && h->file){ + char *gname = NULL; + FILE* file = h->file; + int offset; + char *line = (char*)malloc(_CFG_MAX_LINE_SIZE); + while ((line = fgets(line, _CFG_MAX_LINE_SIZE, file)) != NULL) { + for (offset = strlen(line); offset > 0 && isspace(line[offset-1]); line[--offset] = '\0'); + for (offset = 0;isspace(line[offset]); offset++); + switch (line[offset]) { + case '#': + case '\0': break; + case '[': + free (gname); + gname = strdup(line+offset+1); + gname[strlen(gname)-1] = '\0'; + cfg_group_new(h, gname); + break; + default: { + char *k, *v, *vo, *p; + size_t len; + int i; + p = strchr(line+offset, '='); + if (p) { + len = (size_t)(p - (line+offset) + 1); + k = (char*)malloc(len); + k = strncpy(k, line+offset, len); + k[len-1] = '\0'; + for (i = strlen(k); i > 0 && isspace(k[i-1]); k[--i] = '\0'); + v = (char*)malloc(strlen(p+1)+1); + /* v = (char*)malloc(strlen(p+1)); */ + v = strcpy(v, p+1); + for (vo = v; isspace(vo[0]); vo++); + /* for (vo = v+1; isspace(vo[0]); vo++); */ + cfg_key_new_with_value(h, gname, k, vo); + free (v); + } else { + len = (size_t)(strlen(line) - offset + 1); + k = (char*)malloc(len); + k = strncpy(k, line+offset, len); + k[len-1] = '\0'; + vo = NULL; + cfg_key_new_with_value(h, gname, k, vo); + } + + free (k); + } + } + } + free (line); + free (gname); + if (cl) return cfg_close(h); + return 0; + } + return -1; +} + + +int cfg_open_file(CfgHandle* h, const char* filename, int reportErrors, const char* mode){ + if ((h->file = fopen (filename, mode)) != NULL) { + return 0; + } else { + if (reportErrors) { + fprintf (stderr, "Can't open configuration file \"%s\": %s\n", + filename, strerror (errno)); + } + return -1; + } +} + +char * +cfg_find_file(char **files, char **pathes) +{ + /* e.g.: + char *files[] = { ".blarc", "blarc", "bla", NULL }; + char *pathes[] = { "/", "/usr/etc/", "/etc/", NULL }; */ + char **file, **path = pathes; + char *options_file = NULL, *help = NULL; + struct stat s; + + while (*path) { + file = files; + while(*file) { + free(options_file); + options_file = (char *)malloc(sizeof(char) * ( + strlen(*path) + + strlen(*file) + 1)); + sprintf(options_file, "%s%s", *path, *file); + help = cfg_resolve_path(options_file); + if (!stat(help, &s)) { + free(options_file); + return help; + } + free(help); + file++; + } + path++; + } + free(options_file); + + return NULL; +} + +int +cfg_open_user_file(CfgHandle *h, const char* filename, + int reportErrors, const char* mode) +{ + char *fn = cfg_resolve_path(filename); + int ret = cfg_open_file(h, fn, reportErrors, mode); + + free(fn); + + return ret; +} + +int cfg_open(CfgHandle* h, int reportErrors, const char* mode){ + int res; + const char *filename; + if (!h || !h->filename || !mode) return -1; + filename = h->filename; + if (filename[0] == '~') { + /* Absolute Path of a Users HomeDir */ + res = cfg_open_user_file (h, filename, reportErrors, mode); + } else if (filename[0] == '/') { + /* Absolute pathname: try it - there are no alternatives */ + res = cfg_open_file (h, filename, reportErrors, mode); + } else { + /* Relative pathname: try current directory first */ + res = cfg_open_file (h, filename, 0, mode); + } + return res; +} + +int cfg_open_read (CfgHandle *handle, const char* filename, int err, int cl){ + if (handle && filename) { + int res; + res = cfg_handle_change_filename(handle, filename); + if (res) return res; + res = cfg_open(handle, err, "r"); + if (res) return res; + return cfg_read(handle,cl); + } + else return -1; +} + +int cfg_close (CfgHandle* h){ + if (!h || !h->file) return -1; + fclose (h->file); + h->file = NULL; + return 0; +} + + +/*************************************************** + * commons + ***************************************************/ + +CfgGroup* cfg_find_group(CfgHandle* h, const char* g){ + CfgGroup *tmp; + if (h == NULL || g == NULL) return NULL; + tmp = h->first; + while (tmp && strcmp(tmp->name, g) != 0) tmp = tmp->next; + return tmp; +} + +CfgKey* cfg_find_key(CfgGroup* g, const char* key){ + CfgKey* tmp; + if (g == NULL || key == NULL) return NULL; + tmp = g->first; + while (tmp && strcmp(tmp->name, key) != 0) tmp = tmp->next; + return tmp; +} + +/*************************************************** + * cfg_handle_... + ***************************************************/ + +CfgHandle* cfg_handle_new_with_filename (const char* filename, int read){ + CfgHandle* h; + h = (CfgHandle*)malloc(sizeof(CfgHandle)); + if (!h) return NULL; + + h->filename = filename ? strdup(filename) : NULL; + h->file = NULL; + h->first = h->last = NULL; + + if (read) { + int r = cfg_open_read(h, filename, 0, 1); + if (r != 0) { + cfg_handle_free(h); + return NULL; + } + } + + return h; +} + +CfgHandle* cfg_handle_new (){ + return cfg_handle_new_with_filename(NULL,0); +} + + +int cfg_handle_change_filename(CfgHandle *h, const char* filename){ + if (h && filename) { + if (h->file) return -2; + free (h->filename); + h->filename = strdup(filename); + return 0; + } + else return -1; +} + + +int cfg_handle_add_group(CfgHandle* h, CfgGroup* g){ + if (h && g) { + CfgGroup* last = h->last; + if (last) { + last->next = g; + g->prev = last; + } else { + h->first = g; + } + h->last = g; + g->pp = h; + return 0; + } + else + return -1; +} + +void cfg_handle_free (CfgHandle* h){ + CfgGroup *ga, *gb; + CfgKey *ka, *kb; + if (!h) return; + ga = h->first; + if (h->file) fclose (h->file); + while (ga){ + gb = ga->next; + ka = ga->first; + while (ka) { + kb = ka->next; + free (ka->name); + free (ka->value); + free (ka); + ka = kb; + } + free (ga->name); + free (ga); + ga = gb; + } + free (h); +} + + +/*************************************************** + * cfg_group_... + ***************************************************/ + +int cfg_group_exist(CfgHandle* h, const char* name){ + if (h == NULL || name == NULL) + return -1; + else { + CfgGroup* tmp = h->first; + while (tmp && strcmp(tmp->name,name) != 0 ) + tmp = tmp->next; + if (tmp != NULL) return -1; + } + return 0; +} + +int cfg_group_new (CfgHandle* handle, const char* name){ + if (cfg_find_group(handle, name) == NULL) { + CfgGroup* g = (CfgGroup*)malloc(sizeof(CfgGroup)); + if (!g) return -1; + g->name = strdup(name); + g->prev = NULL; + g->next = NULL; + g->first = NULL; + g->last = NULL; + g->pp = NULL; + return cfg_handle_add_group(handle, g); + } else + return -1; +} + +int cfg_group_add_key(CfgGroup* g, CfgKey* k){ + if (g && k) { + CfgKey* last = g->last; + if (last) { + last->next = k; + k->prev = last; + } else { + g->first = k; + } + + g->last = k; + k->pp = g; + return 0; + } else + return -1; +} + +void cfg_group_free(CfgHandle* h, const char* name){ + if (h && name) { + CfgGroup *tmp, *prev, *next; + CfgKey *a, *b; + tmp = cfg_find_group(h, name); + if (!tmp) return; + + a = tmp->first; + while (a) { + b = a->next; + free (a->name); + free (a->value); + free (a); + a = b; + } + + prev = tmp->prev; + next = tmp->next; + + free (tmp->name); + if (prev) { + prev->next = next; + } else { + tmp->pp->first= next; + } + + if (next) { + next->prev = prev; + } else { + tmp->pp->last = prev; + } + + free(tmp); + } +} + +/*************************************************** + * cfg_key_... + ***************************************************/ + +int +cfg_key_new (CfgHandle* h, const char* g, const char* key) +{ + CfgGroup *group; + if ((group = cfg_find_group(h, g)) == NULL) return -1; + // if (cfg_find_key(group, key) != NULL) return -1; + if (h && g && key) { + CfgKey* k = (CfgKey*)malloc(sizeof(CfgKey)); + if (!k) return -1; + k->name = strdup(key); + k->value = NULL; + k->prev = NULL; + k->next = NULL; + k->pp = NULL; + return cfg_group_add_key(group, k); + } else + return -1; +} + +int +cfg_key_new_with_value(CfgHandle* h, const char* g, const char* key, + const char* value) +{ + if (cfg_key_new (h, g, key) == 0) { + CfgKey* tmp = cfg_find_group(h, g)->last; + if (!tmp) return -1; + tmp->value = ((value == NULL) ? NULL : strdup(value)); + return 0; + } else + return -1; +} + +int +cfg_key_set_value(CfgHandle* h, const char* g, const char* key, + const char* value) +{ + if (h && g && key && value) { + CfgKey* tmp = cfg_find_key(cfg_find_group(h,g), key); + if (!tmp) return -1; + free (tmp->value); + tmp->value = ((value == NULL) ? NULL : strdup(value)); + return 0; + } else return -1; +} + +int +cfg_key_set_uint_value (CfgHandle *h, const char* g, const char* key, + unsigned int value) +{ + char dest[30]; + sprintf(dest,"%ud", value); + return cfg_key_set_value(h, g, key, dest); +} + +int +cfg_key_set_int_value (CfgHandle *h, const char* g, const char* key, + int value) +{ + char dest[30]; + sprintf(dest,"%d", value); + return cfg_key_set_value(h, g, key, dest); +} + +int +cfg_key_set_double_value (CfgHandle *h, const char* g, const char* key, + double value) +{ + char dest[30]; + sprintf(dest,"%e",value); + return cfg_key_set_value(h, g, key, dest); +} + +int +cfg_key_set_float_value (CfgHandle *h, const char* g, const char* key, + float value) +{ + char dest[30]; + sprintf(dest,"%f",value); + return cfg_key_set_value(h, g, key, dest); +} + +int +cfg_key_set_bool_value (CfgHandle *h, const char* g, const char* key, + bool value) +{ + char dest[2]; + sprintf(dest, "%1d", value); + return cfg_key_set_value(h, g, key, dest); +} + +int +cfg_key_set_char_value (CfgHandle *h, const char* g, const char* key, + char value) +{ + char dest[2]; + sprintf(dest, "%c",value); + return cfg_key_set_value(h, g, key, dest); +} + +const char* +cfg_key_get_value(CfgHandle* h, const char* g, const char* key) +{ + if (h && g && key) { + CfgKey* tmp = cfg_find_key(cfg_find_group(h,g), key); + if (!tmp) return NULL; + return tmp->value; + } else + return NULL; +} + +int +cfg_key_get_value_as_bool(CfgHandle* h, const char* g, const char* key, + bool* res){ + char *endptr; + const char *nptr = cfg_key_get_value(h, g, key); + if (!nptr) return -1; + if (!strcasecmp(nptr, "yes") || !strcasecmp(nptr, "true")) + *res = TRUE; + else + *res = FALSE; + + return (int)*endptr; +} + +int +cfg_key_get_value_as_uint(CfgHandle* h, const char* g, const char* key, + unsigned int* res){ + char *endptr; + const char *nptr = cfg_key_get_value(h, g, key); + if (!nptr) return -1; + *res = (unsigned int)strtoul(nptr, &endptr, 10); + return (int)*endptr; +} + +int +cfg_key_get_value_as_int(CfgHandle* h, const char* g, const char* key, + int* res) +{ + char *endptr; + const char *nptr = cfg_key_get_value(h, g, key); + if (!nptr) return -1; + *res = (int)strtol(nptr, &endptr, 10); + return (int)*endptr; +} + +int +cfg_key_get_value_as_ushort(CfgHandle* h, const char* g, const char* key, + unsigned short* res) +{ + char *endptr; + const char *nptr = cfg_key_get_value(h, g, key); + if (!nptr) return -1; + *res = (unsigned short)strtoul(nptr, &endptr, 10); + return (int)*endptr; +} + +int +cfg_key_get_value_as_short(CfgHandle* h, const char* g, const char* key, + short* res) +{ + char *endptr; + const char *nptr = cfg_key_get_value(h, g, key); + if (!nptr) return -1; + *res = (short)strtol(nptr, &endptr, 10); + return (int)*endptr; +} + +int +cfg_key_get_value_as_double(CfgHandle* h, const char* g, const char* key, + double* res) +{ + char *endptr; + const char *nptr = cfg_key_get_value(h, g, key); + if (!nptr) return -1; + *res = (double)strtod(nptr, &endptr); + return (int)*endptr; +} + +int +cfg_key_get_value_as_float(CfgHandle* h, const char* g, const char* key, + float* res) +{ + char *endptr; + const char *nptr = cfg_key_get_value(h, g, key); + if (!nptr) return -1; + *res = (float)strtod(nptr, &endptr); + return (int)*endptr; +} + +void +cfg_key_free (CfgHandle* h, const char* g, const char* key) +{ + if (h && g && key) { + CfgKey *tmp, *prev, *next; + tmp = cfg_find_key(cfg_find_group(h,g), key); + if (!tmp) return; + prev = tmp->prev; + next = tmp->next; + + free (tmp->name); + free (tmp->value); + + if (prev) { + prev->next = next; + } else { + tmp->pp->first = next; + } + + if (next) { + next->prev = prev; + } else { + tmp->pp->last = prev; + } + + free (tmp); + } +} + +void +cfg_key_for_each (CfgHandle* h, const char* grp, cfg_key_func func) +{ + CfgGroup *tmp = cfg_find_group(h,grp); + + if (tmp && func) { + CfgKey *k = tmp->first; + while(k) func(k), k = k->next; + } +} diff --git a/mpiosh/cfgio.h b/mpiosh/cfgio.h new file mode 100644 index 0000000..d58cd3f --- /dev/null +++ b/mpiosh/cfgio.h @@ -0,0 +1,453 @@ +/* configreader and -writer + * + * Source in ANSI C, except function strdup + * needs _BSD_SOURCE or _SVID_SOURCE defined, if compiled ANSI + * Thomas Buntrock (bunti@tzi.de) + * + * Comments in configfile are allowed, but ONLY at the BEGINNING of a line + * When reading a config then writing the same, all comments will be removed + * + * The groupname MUST be put exactly between two square braces, e.g. [Name]. + * Any Spaces in between are interpreted as part of the name. + * + * Keys and their value are separated by "=". Leading and following spaces + * are removed. + * Spaces right before and after the "=" are removed. Spaces in the value + * will remain. + * Keys without value are accepted, BUT the "=" is MANDATORY. + * + * A config line MUST NOT be longer than _CFG_MAX_LINE_SIZE (default: 256) + * + */ + +#ifndef _CFG_IO_H +#define _CFG_IO_H + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <pwd.h> +#include <sys/types.h> +#include <ctype.h> + +#define _CFG_MAX_LINE_SIZE 256 + +/* define bool */ +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +typedef unsigned char bool; + +struct _CFG_Key { + char *name; + char *value; + struct _CFG_Key* prev; + struct _CFG_Key* next; + struct _CFG_Group* pp; +}; + +struct _CFG_Group { + char *name; + struct _CFG_Group* prev; + struct _CFG_Group* next; + struct _CFG_Key* first; + struct _CFG_Key* last; + struct _CFG_Handle* pp; +}; + +struct _CFG_Handle { + FILE *file; + char *filename; + struct _CFG_Group *first; + struct _CFG_Group *last; +}; + + +typedef struct _CFG_Key CfgKey; +typedef struct _CFG_Group CfgGroup; +typedef struct _CFG_Handle CfgHandle; +typedef int (*cfg_key_func)(CfgKey *key); + +char *cfg_resolve_path(const char *filename); + +/* + * files: a list of files + * e.g. char *files[] = { ".blarc", ".bla", "blarc", NULL }; + * + * paths: a list of paths + * e.g. char *paths[] = { "~/", "/etc/" "etc/", NULL}; + * + * select the first path and iterates through the files, + * then select the next path... + * + * returns the first match of: path/file + */ +char *cfg_find_file (char **files, char **paths); + +/* + * Save the config + * + * close: close the file after saving + * + * returns 0 on success or -1 on failure + */ +int cfg_save (CfgHandle *handle, int close); + +/* + * Save the config with another filename + * + * handle : the config handle + * filename : the new filename + * reportErrors: 0 does not report errors the stderr + * close : close the file after saving + * + * returns 0 on success or -1 on failure + */ +int cfg_save_as (CfgHandle *handle, const char* filename, + int reportErrors, int close); +/* + * Read config file + * requires the Handle to be associated to a file and being opened + * + * handle: the config handle + * close : close the file after reading + * + * returns 0 on success or -1 on failure + */ +int cfg_read (CfgHandle *handle, int close); + +/* + * Open a file to read or save + * + * handle : the config handle + * reportErrors: write errors to stderr + * mode : the mode the file should be opened with (man 3 fopen) + * + * returns 0 on success or -1 on failure + */ +int cfg_open (CfgHandle *handle, int reportErrors, + const char* mode); +/* + * Open a file in read mode + * + * handle : the config handle + * filename : the filename of the config file + * reportErrors: write errors to stderr + * close : close the file after reading + * + * returns 0 on success or -1 on failure + */ +int cfg_open_read (CfgHandle *handle, const char* filename, + int reportErrors, int close); +/* + * Close the file + * + * h: the config handle + * + * returns 0 on success or -1 if the handle was NULL or the was already closed + */ +int cfg_close (CfgHandle *h); + +/* + * Create a new empty file handle + * + * returns the pointer to the new handle + */ +CfgHandle* cfg_handle_new (); + +/* + * Create a new filehandle + * + * filename: the filename of the configfile + * read : read the config file + * + * returns the pointer to the new handle + */ +CfgHandle* cfg_handle_new_with_filename (const char* filename, int read); + +/* + * Change the filename of the config file + * only the internal filename ist changed, to apply on disk you need to call + * cfg_save + * + * filename: new filename + * + * returns 0 on success or -1 on failure + */ +int cfg_handle_change_filename (CfgHandle *h, const char* filename); + +/* + * Delete the handle + * An opened file will be closed + * + * h: the config handle + */ +void cfg_handle_free (CfgHandle* h); + +/* + * Create a new group within the config + * + * handle: the config handle + * name : name of the group + * + * returns 0 on success or -1 on failure + */ +int cfg_group_new (CfgHandle* handle, const char* name); + +/* + * Delete a group within the config + * All keys within this group will be delete as well + * + * handle: the config handle + * name : the name of the group + */ +void cfg_group_free (CfgHandle* handle, const char* name); + +/* + * returns a handle to the group g if found. + * + * handle: the config handle + * name : the name of the group to search for + */ +CfgGroup* cfg_find_group(CfgHandle* h, const char* g); + +/* + * Create a new key within a group within the config + * + * h : the config handle + * g : name of the group + * key: name of the key + * + * returns 0 on success or -1 on failure + */ +int cfg_key_new (CfgHandle* h, const char* g, const char* key); + +/* + * Create a new key within the group within the config and set its value + * + * h : the config handle + * g : name of the group + * key : name of the key + * value: value for the key + * + * returns 0 on success or -1 on failure + */ +int cfg_key_new_with_value (CfgHandle* h, const char* g, const char* key, + const char* value); + +/* + * Set the value for a specific key within a group of the config + * + * h : the config handle + * g : name of the group + * key : name of the key + * value: value for the key + * + * returns 0 on success or -1 on failure + */ +int cfg_key_set_value (CfgHandle* h, const char* g, const char* key, + const char* value); + +/* + * Set the value for a specific key within a group of the config + * + * h : the config handle + * g : name of the group + * key : name of the key + * value: value for the key + * + * returns 0 on success or -1 on failure + */ +int cfg_key_set_uint_value (CfgHandle *h, const char* g, const char* key, + unsigned int value); + +/* + * Set the value for a specific key within a group of the config + * + * h : the config handle + * g : name of the group + * key : name of the key + * value: value for the key + * + * returns 0 on success or -1 on failure + */ +int cfg_key_set_int_value (CfgHandle *h, const char* g, const char* key, + int value); + +/* + * Set the value for a specific key within a group of the config + * + * h : the config handle + * g : name of the group + * key : name of the key + * value: value for the key + * + * returns 0 on success or -1 on failure + */ +int cfg_key_set_double_value (CfgHandle *h, const char* g, const char* key, + double value); + +/* + * Set the value for a specific key within a group of the config + * + * h : the config handle + * g : name of the group + * key : name of the key + * value: value for the key + * + * returns 0 on success or -1 on failure + */ +int cfg_key_set_float_value (CfgHandle *h, const char* g, const char* key, + float value); + +/* + * Set the value for a specific key within a group of the config + * + * h : the config handle + * g : name of the group + * key : name of the key + * value: value for the key + * + * returns 0 on success or -1 on failure + */ +int cfg_key_set_bool_value (CfgHandle *h, const char* g, const char* key, + bool value); + +/* + * Set the value for a specific key within a group of the config + * + * h : the config handle + * g : name of the group + * key : name of the key + * value: value for the key + * + * returns 0 on success or -1 on failure + */ +int cfg_key_set_char_value (CfgHandle *h, const char* g, const char* key, + char value); + +/* + * Delete a key of a group within the config + * + * h : the config handle + * g : name of the group + * key : name of the key + */ +void cfg_key_free (CfgHandle* h, const char* g, const char* key); + +/* + * Get the value of a key within a group of the config + * + * h : the config handle + * g : name of the group + * key: name of the key + * res: the result will be stored in this variable + * + * returns 0 on success or -1 on failure + */ +int cfg_key_get_value_as_bool (CfgHandle* h, const char* g, const char* key, + bool *res); + +/* + * Get the value of a key within a group of the config + * + * h : the config handle + * g : name of the group + * key: name of the key + * res: the result will be stored in this variable + * + * returns 0 on success or -1 on failure + */ +int cfg_key_get_value_as_uint (CfgHandle* h, const char* g, const char* key, + unsigned int *res); + +/* + * Get the value of a key within a group of the config + * + * h : the config handle + * g : name of the group + * key: name of the key + * res: the result will be stored in this variable + * + * returns 0 on success or -1 on failure + */ +int cfg_key_get_value_as_int (CfgHandle* h, const char* g, const char* key, + int *res); + +/* + * Get the value of a key within a group of the config + * + * h : the config handle + * g : name of the group + * key: name of the key + * res: the result will be stored in this variable + * + * returns 0 on success or -1 on failure + */ +int cfg_key_get_value_as_ushort (CfgHandle* h, const char* g, const char* key, + unsigned short *res); + +/* + * Get the value of a key within a group of the config + * + * h : the config handle + * g : name of the group + * key: name of the key + * res: the result will be stored in this variable + * + * returns 0 on success or -1 on failure + */ +int cfg_key_get_value_as_short (CfgHandle* h, const char* g, const char* key, + short *res); + +/* + * Get the value of a key within a group of the config + * + * h : the config handle + * g : name of the group + * key: name of the key + * res: the result will be stored in this variable + * + * returns 0 on success or -1 on failure + */ +int cfg_key_get_value_as_double (CfgHandle* h, const char* g, const char* key, + double *res); + +/* + * Get the value of a key within a group of the config + * + * h : the config handle + * g : name of the group + * key: name of the key + * res: the result will be stored in this variable + * + * returns 0 on success or -1 on failure + */ +int cfg_key_get_value_as_float (CfgHandle* h, const char* g, const char* key, + float *res); + +/* + * Get the value of a key within a group of the config + * + * h : the config handle + * g : name of the group + * key: name of the key + * + * returns the value of the key or NULL if empty + */ +const char* cfg_key_get_value (CfgHandle* h, const char* g, const char* key); + +/* + * iterators through key value pairs of a group + * + * h : the config handle + * grp : name of the group + * func: pointer to the function to call with each element + * + * returns the value of the key or NULL if empty + */ +void cfg_key_for_each (CfgHandle* h, const char* grp, cfg_key_func func); +#endif /* _CFG_IO_H */ diff --git a/mpiosh/command.c b/mpiosh/command.c index 338ee8d..9c42a8c 100644 --- a/mpiosh/command.c +++ b/mpiosh/command.c @@ -2,7 +2,7 @@ * * Author: Andreas Buesching <crunchy@tzi.de> * - * $Id: command.c,v 1.2 2002/10/12 20:06:22 crunchy Exp $ + * $Id: command.c,v 1.3 2002/10/29 20:03:35 crunchy Exp $ * * Copyright (C) 2001 Andreas Büsching <crunchy@tzi.de> * @@ -64,10 +64,10 @@ mpiosh_command_split_line(char *line) return cmds; } -mpiosh_cmd_t * +struct mpiosh_cmd_t * mpiosh_command_find(char *line) { - mpiosh_cmd_t *cmd = commands; + struct mpiosh_cmd_t *cmd = commands; while (cmd->cmd) { if (strstr(line, cmd->cmd) == line) { diff --git a/mpiosh/command.h b/mpiosh/command.h index 1374385..34dbc9b 100644 --- a/mpiosh/command.h +++ b/mpiosh/command.h @@ -2,7 +2,7 @@ * * Author: Andreas Buesching <crunchy@tzi.de> * - * $Id: command.h,v 1.1 2002/10/12 18:31:45 crunchy Exp $ + * $Id: command.h,v 1.2 2002/10/29 20:03:35 crunchy Exp $ * * Copyright (C) 2001 Andreas Büsching <crunchy@tzi.de> * @@ -27,7 +27,7 @@ #include "mpiosh.h" /* command(-line) functions */ -mpiosh_cmd_t *mpiosh_command_find(char *line); +struct mpiosh_cmd_t *mpiosh_command_find(char *line); char **mpiosh_command_split_line(char *line); char **mpiosh_command_get_args(char *line); void mpiosh_command_regex_fix(char *argv[]); diff --git a/mpiosh/config.c b/mpiosh/config.c new file mode 100644 index 0000000..330bfea --- /dev/null +++ b/mpiosh/config.c @@ -0,0 +1,162 @@ +/* config.c + * + * Author: Andreas Buesching <crunchy@tzi.de> + * + * $Id: config.c,v 1.1 2002/10/29 20:03:35 crunchy Exp $ + * + * Copyright (C) 2001 Andreas Büsching <crunchy@tzi.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" +#include "global.h" + +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> + +struct mpiosh_config_t * +mpiosh_config_new(void) +{ + struct mpiosh_config_t * cfg = malloc(sizeof(struct mpiosh_config_t)); + char *filename; + char *tmp; + struct stat st; + + cfg->prompt_int = cfg->prompt_ext = NULL; + cfg->default_mem = MPIO_INTERNAL_MEM; + + filename = malloc(strlen(CONFIG_GLOBAL) + strlen(CONFIG_FILE) + 1); + filename[0] = '\0'; + strcat(filename, CONFIG_GLOBAL); + strcat(filename, CONFIG_FILE); + tmp = cfg_resolve_path(filename); + + if (stat(tmp, &st) != -1) + cfg->handle_global = + cfg_handle_new_with_filename(tmp, 1); + + free(tmp), free(filename); + filename = malloc(strlen(CONFIG_USER) + strlen(CONFIG_FILE) + 1); + filename[0] = '\0'; + strcat(filename, CONFIG_USER); + strcat(filename, CONFIG_FILE); + tmp = cfg_resolve_path(filename); + + if (stat(tmp, &st) != -1) + cfg->handle_user = + cfg_handle_new_with_filename(tmp, 1); + else + cfg->handle_user = + cfg_handle_new_with_filename(tmp, 0); + + free(tmp), free(filename); + + return cfg; +} + +const char * +mpiosh_config_read_key(struct mpiosh_config_t *config, const char *group, + const char *key) +{ + char *value = NULL; + + if (config->handle_user) + value = (char *)cfg_key_get_value(config->handle_user, + group, key); + else if (config->handle_global) + value = (char *)cfg_key_get_value(config->handle_global, + group, key); + + return value; +} + +void +mpiosh_config_free(struct mpiosh_config_t *config) +{ + cfg_close(config->handle_global); + cfg_close(config->handle_user); + free(config->prompt_int); + free(config->prompt_ext); + free(config); +} + +int +mpiosh_config_read(struct mpiosh_config_t *config) +{ + if (config) { + const char *value; + + value = mpiosh_config_read_key(config, "mpiosh", "prompt_int"); + if (value) { + config->prompt_int = strdup(value); + } else { + config->prompt_int = strdup(PROMPT_INT); + } + + value = mpiosh_config_read_key(config, "mpiosh", "prompt_ext"); + if (value) { + config->prompt_ext = strdup(value); + } else { + config->prompt_ext = strdup(PROMPT_EXT); + } + + value = mpiosh_config_read_key(config, "mpiosh", "default_mem"); + if (value) { + if (!strcmp("internal", value)) { + config->default_mem = MPIO_INTERNAL_MEM; + } else if (!strcmp("external", value)) { + config->default_mem = MPIO_EXTERNAL_MEM; + } + } + } + + return 1; +} + +int +mpiosh_config_write(struct mpiosh_config_t *config) +{ + DIR *dir; + char *path = cfg_resolve_path(CONFIG_USER); + + if ((dir = opendir(path)) == NULL) + mkdir(path, 0777); + else + closedir(dir); + + free(path); + + if (config->handle_user) { + cfg_key_set_value(config->handle_user, + "mpiosh", "prompt_int", config->prompt_int); + cfg_key_set_value(config->handle_user, + "mpiosh", "prompt_ext", config->prompt_ext); + if (config->default_mem == MPIO_EXTERNAL_MEM) + cfg_key_set_value(config->handle_user, + "mpiosh", "default_mem", "external"); + else + cfg_key_set_value(config->handle_user, + "mpiosh", "default_mem", "internal"); + + cfg_save(config->handle_user, 0); + } + + return 1; +} + + +/* end of config.c */ diff --git a/mpiosh/config.h b/mpiosh/config.h new file mode 100644 index 0000000..24ca437 --- /dev/null +++ b/mpiosh/config.h @@ -0,0 +1,48 @@ +/* config.h + * + * Author: Andreas Buesching <crunchy@tzi.de> + * + * $Id: config.h,v 1.1 2002/10/29 20:03:35 crunchy Exp $ + * + * Copyright (C) 2001 Andreas Büsching <crunchy@tzi.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef MPIOSH_CONFIG_HH +#define MPIOSH_CONFIG_HH + +#include "cfgio.h" + +struct mpiosh_config_t { + CfgHandle *handle_global; + CfgHandle *handle_user; + + char *prompt_int; + char *prompt_ext; + unsigned default_mem; +}; + +struct mpiosh_config_t *mpiosh_config_new(void); +void mpiosh_config_free(struct mpiosh_config_t *config); + +const char *mpiosh_config_read_key(struct mpiosh_config_t *config, + const char *group, const char *key); +int mpiosh_config_read(struct mpiosh_config_t *config); +int mpiosh_config_write(struct mpiosh_config_t *config); + +#endif + +/* end of config.h */ diff --git a/mpiosh/global.c b/mpiosh/global.c index d300f62..554652e 100644 --- a/mpiosh/global.c +++ b/mpiosh/global.c @@ -2,7 +2,7 @@ * * Author: Andreas Buesching <crunchy@tzi.de> * - * $Id: global.c,v 1.4 2002/10/27 02:45:28 germeier Exp $ + * $Id: global.c,v 1.5 2002/10/29 20:03:35 crunchy Exp $ * * Copyright (C) 2001 Andreas Büsching <crunchy@tzi.de> * @@ -26,17 +26,24 @@ #include "readline.h" /* structure containing current state */ -mpiosh_t mpiosh; +struct mpiosh_t mpiosh; +struct mpiosh_config_t config; /* flag indicating a user-interrupt of the current command */ -int mpiosh_cancel = 0; -int mpiosh_cancel_ack = 0; +int mpiosh_cancel = 0; +int mpiosh_cancel_ack = 0; + +/* configuration filenames */ +const char *CONFIG_GLOBAL = SYSCONFDIR "/mpio/"; +const char *CONFIG_USER = "~/.mpio/"; +const char *CONFIG_FILE = "mpioshrc"; +const char *CONFIG_HISTORY = "~/.mpio/mpiosh_history"; /* prompt strings */ -const char *PROMPT_INT = "\033[;1mmpio <i>\033[m "; -const char *PROMPT_EXT = "\033[;1mmpio <e>\033[m "; +const char *PROMPT_INT = "\033[;1mmpio <i>\033[m "; +const char *PROMPT_EXT = "\033[;1mmpio <e>\033[m "; -mpiosh_cmd_t commands[] = { +struct mpiosh_cmd_t commands[] = { { "debug", NULL , "[level|file|on|off] <value>", " modify debugging options", mpiosh_cmd_debug, NULL }, diff --git a/mpiosh/global.h b/mpiosh/global.h index 4800d68..a807c4a 100644 --- a/mpiosh/global.h +++ b/mpiosh/global.h @@ -2,7 +2,7 @@ * * Author: Andreas Buesching <crunchy@tzi.de> * - * $Id: global.h,v 1.1 2002/10/12 20:06:22 crunchy Exp $ + * $Id: global.h,v 1.2 2002/10/29 20:03:35 crunchy Exp $ * * Copyright (C) 2001 Andreas Büsching <crunchy@tzi.de> * @@ -26,31 +26,39 @@ #include "libmpio/mpio.h" +#include "config.h" + /* type definitions */ typedef void(*mpiosh_cmd_callback_t)(char *args[]); typedef char *(*mpiosh_comp_callback_t)(const char *text, int state); -typedef struct { - mpio_t * dev; - mpio_mem_t card; - const char * prompt; -} mpiosh_t; +struct mpiosh_t { + mpio_t * dev; + mpio_mem_t card; + const char * prompt; + struct mpiosh_config_t *config; +}; -typedef struct { - char * cmd; - char ** aliases; - char * args; - char * info; +struct mpiosh_cmd_t { + char *cmd; + char **aliases; + char *args; + char *info; mpiosh_cmd_callback_t cmd_func; mpiosh_comp_callback_t comp_func; -} mpiosh_cmd_t; +}; /* global structures */ -extern mpiosh_t mpiosh; -extern mpiosh_cmd_t commands[]; +extern struct mpiosh_t mpiosh; +extern struct mpiosh_cmd_t commands[]; extern int mpiosh_cancel; extern int mpiosh_cancel_ack; +extern const char *CONFIG_GLOBAL; +extern const char *CONFIG_USER; +extern const char *CONFIG_FILE; +extern const char *CONFIG_HISTORY; + extern const char *PROMPT_INT; extern const char *PROMPT_EXT; diff --git a/mpiosh/mpiosh.c b/mpiosh/mpiosh.c index f5896a5..5ed1faa 100644 --- a/mpiosh/mpiosh.c +++ b/mpiosh/mpiosh.c @@ -2,7 +2,7 @@ /* * - * $Id: mpiosh.c,v 1.20 2002/10/12 20:06:22 crunchy Exp $ + * $Id: mpiosh.c,v 1.21 2002/10/29 20:03:35 crunchy Exp $ * * Author: Andreas Büsching <crunchy@tzi.de> * @@ -26,6 +26,7 @@ * */ #include <signal.h> +#include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -34,6 +35,7 @@ #include "callback.h" #include "command.h" +#include "config.h" #include "readline.h" #include "mpiosh.h" @@ -41,9 +43,26 @@ void mpiosh_init(void) { + /* set state */ mpiosh.dev = NULL; - mpiosh.card = MPIO_INTERNAL_MEM; - mpiosh.prompt = PROMPT_INT; + mpiosh.config = NULL; + mpiosh.prompt = NULL; + + /* read configuration */ + mpiosh.config = mpiosh_config_new(); + if (mpiosh.config) + mpiosh_config_read(mpiosh.config); + + mpiosh.card = mpiosh.config->default_mem; + if (mpiosh.config->default_mem == MPIO_EXTERNAL_MEM) + mpiosh.prompt = mpiosh.config->prompt_ext; + else + mpiosh.prompt = mpiosh.config->prompt_int; + + /* inital mpio library */ + mpiosh.dev = mpio_init(mpiosh_callback_init); + + printf("\n"); } void @@ -55,9 +74,9 @@ mpiosh_signal_handler(int signal) int main(int argc, char *argv[]) { - char * line; - char ** cmds, **walk; - mpiosh_cmd_t * cmd; + char *line; + char **cmds, **walk; + struct mpiosh_cmd_t *cmd; struct sigaction sigc; int interactive = 1; @@ -80,13 +99,6 @@ main(int argc, char *argv[]) { debug_init(); mpiosh_init(); - mpiosh.dev = mpio_init(mpiosh_callback_init); - printf("\n"); - - if (mpiosh.card == MPIO_INTERNAL_MEM) - mpiosh.prompt = PROMPT_INT; - else - mpiosh.prompt = PROMPT_EXT; if (!isatty(fileno(stdin))) { interactive = 0; diff --git a/mpiosh/readline.c b/mpiosh/readline.c index cd72591..8b97219 100644 --- a/mpiosh/readline.c +++ b/mpiosh/readline.c @@ -2,7 +2,7 @@ * * Author: Andreas Büsching <crunchy@tzi.de> * - * $Id: readline.c,v 1.4 2002/10/18 08:39:23 crunchy Exp $ + * $Id: readline.c,v 1.5 2002/10/29 20:03:35 crunchy Exp $ * * Copyright (C) 2001 Andreas Büsching <crunchy@tzi.de> * @@ -41,10 +41,9 @@ mpiosh_readline_init(void) char * mpiosh_readline_comp_cmd(const char *text, int state) { - static mpiosh_cmd_t * cmd = NULL; - static char ** alias = NULL; - - char *cmd_text = NULL; + static struct mpiosh_cmd_t *cmd = NULL; + static char **alias = NULL; + char *cmd_text = NULL; if (state == 0) { cmd = commands; @@ -123,9 +122,17 @@ mpiosh_readline_comp_mpio_file(const char *text, int state) char * mpiosh_readline_comp_config(const char *text, int state) { - char *arg = NULL; + static char *args[] = { "put", "write", "show", NULL }; + static char **arg = NULL; + char *res = NULL; + + if (state == 0) arg = args; + if (*arg && (strstr(*arg, text) == *arg)) { + res = strdup(*arg); + arg++; + } - return arg; + return res; } @@ -139,7 +146,7 @@ mpiosh_readline_completion(const char *text, int start, int end) if (start == 0) /* command completion */ matches = rl_completion_matches(text, mpiosh_readline_comp_cmd); else { - mpiosh_cmd_t *scmd; + struct mpiosh_cmd_t *scmd; char *cmd, *help= rl_line_buffer; while (*help != ' ') help++; |