aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore2
-rw-r--r--src/CMakeLists.txt10
-rw-r--r--src/callback.c1273
-rw-r--r--src/callback.h101
-rw-r--r--src/cfg.c238
-rw-r--r--src/cfg.h56
-rw-r--r--src/cfgio.c654
-rw-r--r--src/cfgio.h453
-rw-r--r--src/command.c222
-rw-r--r--src/command.h38
-rw-r--r--src/config.h.in9
-rw-r--r--src/global.c159
-rw-r--r--src/global.h68
-rw-r--r--src/mpiosh.c163
-rw-r--r--src/mpiosh.h37
-rw-r--r--src/readline.c212
-rw-r--r--src/readline.h47
17 files changed, 3742 insertions, 0 deletions
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..2e3941e
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,2 @@
+mpiosh
+config.h
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..7132b28
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,10 @@
+set (CMAKE_C_FLAGS -Wall)
+
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
+ ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR}/..)
+
+add_executable (mpiosh mpiosh.c callback.c readline.c command.c global.c
+ cfgio.c cfg.c)
+target_link_libraries (mpiosh mpio -lreadline -lncurses)
diff --git a/src/callback.c b/src/callback.c
new file mode 100644
index 0000000..e98a334
--- /dev/null
+++ b/src/callback.c
@@ -0,0 +1,1273 @@
+/* callback.c
+ *
+ * Author: Andreas Büsching <crunchy@tzi.de>
+ *
+ * $Id: callback.c,v 1.49 2006/01/21 18:33:20 germeier 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 "callback.h"
+
+#include <dirent.h>
+#include <grp.h>
+#include <pwd.h>
+#include <regex.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "mpiosh.h"
+#include "command.h"
+#include "cfg.h"
+
+#include "libmpio/debug.h"
+
+/* helper */
+BYTE
+mpiosh_ftype2ascii(BYTE ftype) {
+ switch(ftype)
+ {
+ case FTYPE_CONF:
+ case FTYPE_FONT:
+ case FTYPE_OTHER:
+ case FTYPE_MEMO:
+ case FTYPE_WAV:
+ case FTYPE_ENTRY:
+ case FTYPE_DIR:
+ case FTYPE_PLAIN:
+ return ftype;
+ case FTYPE_DIR_RECURSION:
+ return 'r';
+ case FTYPE_CHAN:
+ return 'c';
+ case FTYPE_MUSIC:
+ return '-';
+ default:
+ return '?';
+ }
+ return '?';
+}
+
+
+/* commands */
+void
+mpiosh_cmd_debug(char *args[])
+{
+ if (args[0] != NULL) {
+ if (!strcmp(args[0], "level")) {
+ debug_level(strtol(args[1], NULL, 0));
+ } else if (!strcmp(args[0], "file")) {
+ debug_file(args[1]);
+ } else if (!strcmp(args[0], "on")) {
+ if (debug_level_get() == -1)
+ debug_level(1);
+ else
+ fprintf(stderr, "debug already activated for level %d\n",
+ debug_level_get());
+ } else if (!strcmp(args[0], "off")) {
+ if (debug_level_get() == -1)
+ fprintf(stderr, "debug already deactivated\n");
+ else
+ debug_level(-1);
+ } else {
+ fprintf(stderr, "unknown debug command\n");
+ printf("debug [level|file|on|off] <value>\n");
+ }
+ } else {
+ fprintf(stderr, "error: no arguments given\n");
+ printf("debug [level|file|on|off] <value>\n");
+ }
+}
+
+void
+mpiosh_cmd_version(char *args[])
+{
+ UNUSED(args);
+
+ printf("MPIO shell %s\n\n", VERSION);
+}
+
+void
+mpiosh_cmd_help(char *args[])
+{
+ struct mpiosh_cmd_t *cmd = commands;
+ int ignore;
+
+ while (cmd->cmd) {
+ if (args[0] != NULL) {
+ char ** walk = args;
+ ignore = 1;
+
+ while(*walk) {
+ if (!strcmp(*walk, cmd->cmd)) {
+ ignore = 0;
+ break;
+ }
+ walk++;
+ }
+ } else
+ ignore = 0;
+
+ if (!ignore) {
+ printf("%s", cmd->cmd);
+ if (cmd->args)
+ printf(" %s\n", cmd->args);
+ else
+ printf("\n");
+ if (cmd->aliases) {
+ char **go = cmd->aliases;
+ printf(" alias:\n ");
+ while(*go) printf(( *(go+1) ? "%s" : "%s, "), *go++);
+ printf("\n");
+ }
+
+ if (cmd->info)
+ printf(" description:\n%s\n", cmd->info);
+ else
+ printf("\n");
+ }
+ cmd++;
+ }
+}
+
+void
+mpiosh_cmd_dir(char *args[])
+{
+ BYTE *p;
+ BYTE month, day, hour, minute, type;
+ CHAR fname[100];
+ WORD year;
+ DWORD fsize;
+
+ UNUSED(args);
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ p = mpio_directory_open(mpiosh.dev, mpiosh.card);
+ while (p != NULL) {
+ memset(fname, '\0', 100);
+
+ mpio_dentry_get(mpiosh.dev, mpiosh.card, p,
+ fname, 100,
+ &year, &month, &day,
+ &hour, &minute, &fsize,
+ &type);
+
+ printf ("%02d.%02d.%04d %02d:%02d %9d %c %s\n",
+ day, month, year, hour, minute, fsize,
+ mpiosh_ftype2ascii(type), fname);
+
+ p = mpio_dentry_next(mpiosh.dev, mpiosh.card, p);
+ }
+}
+
+void
+mpiosh_cmd_pwd(char *args[])
+{
+ CHAR pwd[INFO_LINE];
+
+ UNUSED(args);
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ mpio_directory_pwd(mpiosh.dev, mpiosh.card, pwd);
+ printf ("%s\n", pwd);
+
+}
+
+void
+mpiosh_cmd_mkdir(char *args[])
+{
+ CHAR pwd[INFO_LINE];
+ BYTE r;
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ r=mpio_directory_make(mpiosh.dev, mpiosh.card, args[0]);
+ if (r != MPIO_OK)
+ {
+ mpio_perror("ERROR");
+ }
+ mpio_sync(mpiosh.dev, mpiosh.card);
+
+}
+
+void
+mpiosh_cmd_cd(char *args[])
+{
+ CHAR pwd[INFO_LINE];
+ BYTE r;
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ if ( args[ 0 ] != NULL )
+ r=mpio_directory_cd(mpiosh.dev, mpiosh.card, args[0]);
+ else
+ r=mpio_directory_cd(mpiosh.dev, mpiosh.card, ".");
+
+ if (r != MPIO_OK)
+ {
+ mpio_perror("ERROR");
+ }
+
+ mpio_directory_pwd(mpiosh.dev, mpiosh.card, pwd);
+ printf ("directory is now: %s\n", pwd);
+
+}
+
+void
+mpiosh_cmd_info(char *args[])
+{
+ mpio_info_t info;
+
+ UNUSED(args);
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ mpio_get_info(mpiosh.dev, &info);
+
+ printf("firmware %s\n", info.firmware_id);
+ printf(" version : %s\n", info.firmware_version);
+ printf(" date : %s\n", info.firmware_date);
+ printf("model : %s\n", info.model);
+ printf("memory\n");
+ printf(" internal: %s\n", info.mem_internal);
+ printf(" external: %s\n", info.mem_external);
+}
+
+void
+mpiosh_cmd_mem(char *args[])
+{
+ DWORD free;
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+ MPIOSH_CHECK_ARG;
+
+ if (!strcmp(args[0], "e")) {
+ if (mpio_memory_free(mpiosh.dev, MPIO_EXTERNAL_MEM, &free)) {
+ mpiosh.card = MPIO_EXTERNAL_MEM;
+ mpiosh.prompt = PROMPT_EXT;
+ printf("external memory card is selected\n");
+ } else {
+ printf("no external memory card is available\n");
+ }
+
+ } else if (!strcmp(args[0], "i")) {
+ mpiosh.card = MPIO_INTERNAL_MEM;
+ mpiosh.prompt = PROMPT_INT;
+ printf("internal memory card is selected\n");
+ } else {
+ printf("can not select memory card '%s'\n", args[0]);
+ }
+}
+
+void
+mpiosh_cmd_open(char *args[])
+{
+ MPIOSH_CHECK_CONNECTION_OPEN;
+
+ UNUSED(args);
+
+ mpiosh.dev = mpio_init(mpiosh_callback_init);
+
+ printf("\n");
+
+ if (mpiosh.dev == NULL) {
+ mpio_perror("ERROR");
+ printf("could not open connection MPIO player\n");
+ }
+ else
+ printf("connection to MPIO player is opened\n");
+
+ if ((mpiosh.dev) && (mpiosh.config->charset))
+ mpio_charset_set(mpiosh.dev, mpiosh.config->charset);
+}
+
+void
+mpiosh_cmd_close(char *args[])
+{
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ UNUSED(args);
+
+ mpio_close(mpiosh.dev);
+ mpiosh.dev = NULL;
+
+ printf("connection to MPIO player is closed\n");
+}
+
+void
+mpiosh_cmd_quit(char *args[])
+{
+ if (mpiosh.dev) {
+ printf("\nclosing connection to MPIO player\nHave a nice day\n");
+ mpio_close(mpiosh.dev);
+ }
+
+ UNUSED(args);
+
+ if (mpiosh.config) {
+ mpiosh_config_write(mpiosh.config);
+ mpiosh_config_free(mpiosh.config);
+ }
+
+ exit(0);
+}
+
+BYTE
+mpiosh_callback_init(mpio_mem_t mem, int read, int total)
+{
+ switch(mem)
+ {
+ case MPIO_INTERNAL_MEM:
+ printf("\rinternal memory: " );
+ break;
+ case MPIO_EXTERNAL_MEM:
+ printf("\rexternal memory: " );
+ break;
+ default:
+ printf("\runknown memory: " );
+ }
+
+ printf("initialized %.2f %% ", ((double) read / total) * 100.0 );
+ fflush(stdout);
+
+ return mpiosh_cancel; // continue
+}
+
+BYTE
+mpiosh_callback_get(int read, int total)
+{
+ printf("\rretrieved %.2f %%", ((double) read / total) * 100.0 );
+ fflush(stdout);
+
+ if (mpiosh_cancel)
+ debug ("user cancelled operation\n");
+
+ return mpiosh_cancel; // continue
+}
+
+/* void */
+/* mpiosh_cmd_get(char *args[]) */
+/* { */
+/* MPIOSH_CHECK_CONNECTION_CLOSED; */
+/* MPIOSH_CHECK_ARG; */
+
+/* if (mpio_file_get(mpiosh.dev, mpiosh.card, args[0], */
+/* mpiosh_callback_get) == -1) { */
+/* mpio_perror("error"); */
+/* } */
+/* printf("\n"); */
+/* } */
+
+void
+mpiosh_cmd_mget(char *args[])
+{
+ BYTE * p;
+ int i = 0, error, ret;
+ regex_t regex;
+ CHAR fname[100];
+ CHAR errortext[100];
+ BYTE month, day, hour, minute, type;
+ WORD year;
+ DWORD fsize;
+ int found;
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+ MPIOSH_CHECK_ARG;
+
+ mpiosh_command_regex_fix(args);
+
+ while (args[i] != NULL) {
+ if ((error = regcomp(&regex, args[i], REG_NOSUB))) {
+ regerror(error, &regex, errortext, 100);
+ debugn (2, "error in regular expression: %s (%s)\n", args[i], errortext);
+ } else {
+ found = 0;
+ p = mpio_directory_open(mpiosh.dev, mpiosh.card);
+ while (p != NULL) {
+ memset(fname, '\0', 100);
+ mpio_dentry_get(mpiosh.dev, mpiosh.card, p, fname, 100,
+ &year, &month, &day, &hour, &minute, &fsize, &type);
+
+ if (!(error = regexec(&regex, fname, 0, NULL, 0))) {
+ found = 1;
+ printf("getting '%s' ... \n", fname);
+ if ((mpio_file_get(mpiosh.dev, mpiosh.card,
+ fname, mpiosh_callback_get)) == -1) {
+ if ((ret=mpio_errno()) == MPIO_ERR_USER_CANCEL) {
+ debug("cancelled operation\n");
+ mpio_perror("error");
+ break;
+ }
+ mpio_error_set(ret);
+ mpio_perror("error");
+ }
+ printf("\n");
+ if (mpiosh_cancel) {
+ debug("operation cancelled by user\n");
+ break;
+ }
+ } else {
+ regerror(error, &regex, errortext, 100);
+ debugn (2, "file does not match: %s (%s)\n", fname, errortext);
+ }
+
+ p = mpio_dentry_next(mpiosh.dev, mpiosh.card, p);
+ }
+ }
+ if (!found)
+ printf("file not found! (%s)\n", args[i]);
+ i++;
+ }
+
+
+ regfree(&regex);
+}
+
+BYTE
+mpiosh_callback_put(int read, int total)
+{
+ printf("\rwrote %.2f %%", ((double) read / total) * 100.0 );
+ fflush(stdout);
+
+ if ((mpiosh_cancel) && (!mpiosh_cancel_ack)) {
+ debug ("user cancelled operation\n");
+ mpiosh_cancel_ack = 1;
+ }
+
+ return mpiosh_cancel; // continue
+}
+
+/* void */
+/* mpiosh_cmd_put(char *args[]) */
+/* { */
+/* int size; */
+
+/* MPIOSH_CHECK_CONNECTION_CLOSED; */
+/* MPIOSH_CHECK_ARG; */
+
+/* if ((size = mpio_file_put(mpiosh.dev, mpiosh.card, args[0], FTYPE_MUSIC, */
+/* mpiosh_callback_put)) == -1) { */
+/* mpio_perror("error"); */
+/* } else { */
+/* mpio_sync(mpiosh.dev, mpiosh.card); */
+/* } */
+/* printf("\n"); */
+/* } */
+
+void
+mpiosh_cmd_mput(char *args[])
+{
+ char dir_buf[NAME_MAX];
+ int size, j, i = 0, error, written = 0;
+ struct dirent ** dentry, **run;
+ struct stat st;
+ regex_t regex;
+ CHAR errortext[100];
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+ MPIOSH_CHECK_ARG;
+
+ mpiosh_command_regex_fix(args);
+ getcwd(dir_buf, NAME_MAX);
+ while (args[i] != NULL) {
+ if ((error = regcomp(&regex, args[i], REG_NOSUB))) {
+ regerror(error, &regex, errortext, 100);
+ debugn (2, "error in regular expression: %s (%s)\n", args[i], errortext);
+ } else {
+ if ((size = scandir(dir_buf, &dentry, NULL, alphasort)) != -1) {
+ run = dentry;
+ for (j = 0; ((j < size) && (!mpiosh_cancel)); j++, run++) {
+ if (stat((*run)->d_name, &st) == -1) {
+ free(*run);
+ continue;
+ } else {
+ if (!S_ISREG(st.st_mode)) {
+ debugn(2, "not a regular file: '%s'\n", (*run)->d_name);
+ free(*run);
+ continue;
+ }
+ }
+
+ if (!(error = regexec(&regex, (*run)->d_name, 0, NULL, 0))) {
+ printf("putting '%s' ... \n", (*run)->d_name);
+ if (mpio_file_put(mpiosh.dev, mpiosh.card, (*run)->d_name,
+ 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)
+ continue;
+ break;
+ }
+ written = 1; /* we did write something, so do mpio_sync afterwards */
+
+ printf("\n");
+ } else {
+ regerror(error, &regex, errortext, 100);
+ debugn(2, "file does not match: %s (%s)\n",
+ (*run)->d_name, errortext);
+ }
+ free(*run);
+ }
+ free(dentry);
+ }
+ }
+ i++;
+ }
+ regfree(&regex);
+ if (mpiosh_cancel)
+ debug("operation cancelled by user\n");
+
+ if (written) {
+ mpio_sync(mpiosh.dev, mpiosh.card);
+ } else {
+ printf("file not found!\n");
+ }
+}
+
+BYTE
+mpiosh_callback_del(int read, int total)
+{
+ printf("\rdeleted %.2f %%", ((double) read / total) * 100.0 );
+ fflush(stdout);
+
+ if (mpiosh_cancel)
+ debug ("user cancelled operation\n");
+
+ return mpiosh_cancel; // continue
+}
+
+/* void */
+/* mpiosh_cmd_del(char *args[]) */
+/* { */
+/* int size; */
+
+/* MPIOSH_CHECK_CONNECTION_CLOSED; */
+/* MPIOSH_CHECK_ARG; */
+
+/* size = mpio_file_del(mpiosh.dev, mpiosh.card, args[0], mpiosh_callback_del); */
+/* mpio_sync(mpiosh.dev, mpiosh.card); */
+
+/* printf("\n"); */
+/* } */
+
+void
+mpiosh_cmd_mdel(char *args[])
+{
+ BYTE * p;
+ int i = 0;
+ int error;
+ regex_t regex;
+ int r;
+ CHAR fname[100];
+ CHAR errortext[100];
+ BYTE month, day, hour, minute, type;
+ WORD year;
+ DWORD fsize;
+ int deleted = 0;
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+ MPIOSH_CHECK_ARG;
+
+ mpiosh_command_regex_fix(args);
+ while (args[i] != NULL) {
+ if ((error = regcomp(&regex, args[i], REG_NOSUB))) {
+ regerror(error, &regex, errortext, 100);
+ debugn (2, "error in regular expression: %s (%s)\n", args[i], errortext);
+ } else {
+ p = mpio_directory_open(mpiosh.dev, mpiosh.card);
+ while ((p != NULL) && (!mpiosh_cancel)) {
+ memset(fname, '\0', 100);
+ mpio_dentry_get(mpiosh.dev, mpiosh.card, p, fname, 100,
+ &year, &month, &day, &hour, &minute, &fsize, &type);
+
+ if ((!(error = regexec(&regex, fname, 0, NULL, 0))) &&
+ (strcmp(fname, "..")) && (strcmp(fname, ".")))
+ {
+ /* this line has to be above the del, or we won't write
+ * the FAT and directory in case of an abort!!!
+ */
+ deleted=1;
+ printf("deleting '%s' ... \n", fname);
+ r = mpio_file_del(mpiosh.dev, mpiosh.card,
+ fname, mpiosh_callback_del);
+ printf("\n");
+ if (mpiosh_cancel) break;
+ /* if we delete a file, start again from the beginning,
+ because the directory has changed !! */
+ if (r != MPIO_OK)
+ {
+ mpio_perror("ERROR");
+ p = mpio_dentry_next(mpiosh.dev, mpiosh.card, p);
+ break;
+ }
+ p = mpio_directory_open(mpiosh.dev, mpiosh.card);
+ } else {
+ regerror(error, &regex, errortext, 100);
+ debugn (2, "file does not match: %s (%s)\n", fname, errortext);
+ p = mpio_dentry_next(mpiosh.dev, mpiosh.card, p);
+ }
+
+ }
+ }
+ i++;
+ }
+ regfree(&regex);
+ if (deleted) {
+ mpio_sync(mpiosh.dev, mpiosh.card);
+ } else {
+ printf("file not found!\n");
+ }
+}
+
+
+void
+mpiosh_cmd_dump(char *args[])
+{
+ BYTE *p;
+ BYTE month, day, hour, minute, type;
+ CHAR fname[256];
+ char *arg[2];
+ WORD year;
+ DWORD fsize;
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ UNUSED(args);
+
+ arg[1] = NULL;
+
+ p = mpio_directory_open(mpiosh.dev, mpiosh.card);
+ while ((p != NULL) && (!mpiosh_cancel)) {
+ arg[0] = fname; /* is this a memory leak?? -mager */
+ memset(fname, '\0', 256);
+
+ mpio_dentry_get(mpiosh.dev, mpiosh.card, p,
+ fname, 256,
+ &year, &month, &day,
+ &hour, &minute, &fsize, &type);
+
+ mpiosh_cmd_mget(arg);
+
+ p = mpio_dentry_next(mpiosh.dev, mpiosh.card, p);
+ }
+}
+
+void
+mpiosh_cmd_free(char *args[])
+{
+ DWORD free;
+ int kbytes;
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ UNUSED(args);
+
+ kbytes = mpio_memory_free(mpiosh.dev, mpiosh.card, &free);
+
+ printf("%d KB of %d KB are available\n", free, kbytes);
+}
+
+BYTE
+mpiosh_callback_format(int read, int total)
+{
+ printf("\rformatted %.2f %%", ((double) read / total) * 100.0 );
+ fflush(stdout);
+ return 0; // continue
+}
+
+void
+mpiosh_cmd_format(char *args[])
+{
+ CHAR answer[512];
+ CHAR *config, *fmconfig, *rconfig, *fontconfig;
+ int csize, fmsize, rsize, fontsize;
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ UNUSED(args);
+
+ printf("This will destroy all tracks saved on the memory card. "
+ "Are you sure (y/n)? ");
+
+ fgets(answer, 511, stdin);
+
+ if (answer[0] == 'y' || answer[0] == 'Y') {
+ if (mpiosh.card == MPIO_INTERNAL_MEM) {
+ printf("read config files from player\n");
+
+ /* save config files and write them back after formatting */
+ config = NULL;
+ fmconfig = NULL;
+ rconfig = NULL;
+ fontconfig = NULL;
+
+ csize = mpio_file_get_to_memory(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CONFIG_FILE, NULL, &config);
+ fmsize = mpio_file_get_to_memory(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CHANNEL_FILE, NULL, &fmconfig);
+ rsize = mpio_file_get_to_memory(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_MPIO_RECORD, NULL, &rconfig);
+ fontsize = mpio_file_get_to_memory(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_FONT_FON, NULL, &fontconfig);
+ }
+
+ printf("formatting memory...\n");
+
+ if (mpio_memory_format(mpiosh.dev, mpiosh.card,
+ mpiosh_callback_format) == -1)
+ printf("\nfailed\n");
+ else {
+ printf("\n");
+
+ if (mpiosh.card == MPIO_INTERNAL_MEM) {
+ printf("restoring saved config files\n");
+ /* restore everything we saved */
+ if (config)
+ if (mpio_file_put_from_memory(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CONFIG_FILE, FTYPE_CONF,
+ NULL, config, csize)==-1)
+ mpio_perror("error");
+ if (fmconfig)
+ if (mpio_file_put_from_memory(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CHANNEL_FILE, FTYPE_CHAN,
+ NULL, fmconfig, fmsize)==-1)
+ mpio_perror("error");
+ if (rconfig)
+ if (mpio_directory_make(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_MPIO_RECORD)!=MPIO_OK)
+ mpio_perror("error");
+ if (fontconfig)
+ if (mpio_file_put_from_memory(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_FONT_FON, FTYPE_FONT,
+ NULL, fontconfig, fontsize)==-1)
+ mpio_perror("error");
+
+ if (config || fmconfig || rconfig || fontconfig)
+ mpio_sync(mpiosh.dev, MPIO_INTERNAL_MEM);
+ if (config)
+ free(config);
+ if (fmconfig)
+ free(fmconfig);
+ if (rconfig)
+ free(rconfig);
+ if (fontconfig)
+ free(fontconfig);
+ }
+
+ }
+ mpiosh_cmd_health(NULL);
+ }
+}
+
+void
+mpiosh_cmd_switch(char *args[])
+{
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ if(args[0] && args[1] && !args[2]) {
+ if ((mpio_file_switch(mpiosh.dev, mpiosh.card,
+ args[0], args[1])) == -1) {
+ mpio_perror("error");
+ } else {
+ mpio_sync(mpiosh.dev, mpiosh.card);
+ }
+
+ } else {
+ fprintf(stderr, "error: wrong number of arguments given\n");
+ printf("switch <file1> <file2>\n");
+ }
+
+}
+
+void
+mpiosh_cmd_rename(char *args[])
+{
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ if(args[0] && args[1] && !args[2]) {
+ if ((mpio_file_rename(mpiosh.dev, mpiosh.card,
+ args[0], args[1])) == -1) {
+ mpio_perror("error");
+ } else {
+ mpio_sync(mpiosh.dev, mpiosh.card);
+ }
+
+ } else {
+ fprintf(stderr, "error: wrong number of arguments given\n");
+ printf("rename <oldfilename> <newfilename>\n");
+ }
+}
+
+void
+mpiosh_cmd_dump_mem(char *args[])
+{
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ UNUSED(args);
+
+ mpio_memory_dump(mpiosh.dev, mpiosh.card);
+
+}
+
+void
+mpiosh_cmd_health(char *args[])
+{
+ mpio_health_t health;
+ int i, lost, r;
+
+ UNUSED(args);
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ if ((r=mpio_health(mpiosh.dev, mpiosh.card, &health)) != MPIO_OK) {
+ printf("error: %s\n", mpio_strerror(r));
+ return;
+ }
+
+ if (mpiosh.card == MPIO_INTERNAL_MEM) {
+ lost=0;
+ printf("health status of internal memory:\n");
+ printf("=================================\n");
+ printf("%d chip%c (total/spare/broken)\n",
+ health.num, ((health.num==1)?' ':'s'));
+ for(i=0; i<health.num; i++) {
+ printf("chip #%d (%5d/%5d/%6d)\n", (i+1),
+ health.data[i].total,
+ health.data[i].spare,
+ health.data[i].broken);
+ lost+=health.data[i].broken;
+ }
+ if (lost)
+ printf("You have lost %d KB due to bad blocks.\n", lost*health.block_size);
+ }
+
+ if (mpiosh.card == MPIO_EXTERNAL_MEM) {
+ lost=0;
+ printf("health status of external memory:\n");
+ printf("=================================\n");
+ printf("%d zone%c (total/spare/broken)\n",
+ health.num, ((health.num==1)?' ':'s'));
+ for(i=0; i<health.num; i++) {
+ printf("zone #%d (%5d/%5d/%6d)\n", (i+1),
+ health.data[i].total,
+ health.data[i].spare,
+ health.data[i].broken);
+ if (health.data[i].spare<health.data[i].broken)
+ lost++;
+ }
+ if (lost)
+ printf("%d zone%s to many broken blocks, expect trouble! :-(\n", lost,
+ ((lost==1)?" has":"s have"));
+ }
+
+
+}
+
+void
+mpiosh_cmd_backup(char *args[])
+{
+ int size;
+ char filename[ 1024 ];
+ char *path;
+
+ UNUSED(args);
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ path = mpiosh_config_check_backup_dir( mpiosh.config, TRUE );
+
+ if ( !path ) {
+ fprintf( stderr, "error: could not create backup directory: %s\n",
+ path );
+ goto cleanup_backup;
+ }
+
+ printf( "backup %s ...\n", MPIO_CONFIG_FILE );
+ snprintf( filename, 1024, "%s%s", path, MPIO_CONFIG_FILE );
+ size = mpio_file_get_as( mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CONFIG_FILE,
+ filename,
+ mpiosh_callback_get );
+ if ( size == -1 ) goto cleanup_backup;
+ if ( !size )
+ debugn (1, "file does not exist: %s\n", MPIO_CONFIG_FILE );
+
+
+ if ( mpio_file_exists( mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_CHANNEL_FILE ) )
+ printf( "backup %s ...\n", MPIO_CHANNEL_FILE );
+ snprintf( filename, 1024, "%s%s", path, MPIO_CHANNEL_FILE );
+ size = mpio_file_get_as( mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CHANNEL_FILE,
+ filename,
+ mpiosh_callback_get );
+ if ( size == -1 ) goto cleanup_backup;
+ if ( !size )
+ debugn (2, "file does not exist: %s\n", MPIO_CHANNEL_FILE );
+
+ if ( mpio_file_exists( mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_FONT_FON ) )
+ printf( "backup %s ...\n", MPIO_FONT_FON );
+ snprintf( filename, 1024, "%s%s", path, MPIO_FONT_FON );
+ size = mpio_file_get_as( mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_FONT_FON,
+ filename,
+ mpiosh_callback_get );
+ if ( size == -1 ) goto cleanup_backup;
+ if ( !size )
+ debugn (2, "file does not exist: %s\n", MPIO_FONT_FON );
+
+ cleanup_backup:
+ free( path );
+ printf("\n");
+}
+
+void
+mpiosh_cmd_restore(char *args[])
+{
+ int size;
+ char filename[ 1024 ], answer[ 512 ];
+ char *path;
+
+ UNUSED(args);
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ path = mpiosh_config_check_backup_dir( mpiosh.config, FALSE );
+
+ if ( !path ) {
+ fprintf( stderr, "error: there is no backup: %s\n",
+ path );
+ goto cleanup_restore;
+ }
+
+ printf( "This will destroy the current configuration of your player. "
+ "Are you sure you want to restore the backup (y/n)? " );
+
+ fgets( answer, 511, stdin );
+
+ if (answer[0] != 'y' && answer[0] != 'Y')
+ goto cleanup_restore;
+
+ snprintf( filename, 1024, "%s%s", path, MPIO_FONT_FON );
+ if ( mpio_file_exists( mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_FONT_FON ) )
+ mpio_file_del( mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_FONT_FON, NULL );
+ size = mpio_file_put_as( mpiosh.dev, MPIO_INTERNAL_MEM,
+ filename,
+ MPIO_FONT_FON,
+ FTYPE_FONT, mpiosh_callback_put );
+ mpio_file_move( mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_FONT_FON, NULL );
+
+ snprintf( filename, 1024, "%s%s", path, MPIO_CHANNEL_FILE );
+ if ( mpio_file_exists( mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_CHANNEL_FILE ) )
+ mpio_file_del( mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_CHANNEL_FILE, NULL );
+ size = mpio_file_put_as( mpiosh.dev, MPIO_INTERNAL_MEM,
+ filename,
+ MPIO_CHANNEL_FILE,
+ FTYPE_CHAN, mpiosh_callback_put );
+ mpio_file_move( mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_CHANNEL_FILE, NULL );
+
+ snprintf( filename, 1024, "%s%s", path, MPIO_CONFIG_FILE );
+ if ( mpio_file_exists( mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_CONFIG_FILE ) )
+ mpio_file_del( mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_CONFIG_FILE, NULL );
+ size = mpio_file_put_as( mpiosh.dev, MPIO_INTERNAL_MEM,
+ filename,
+ MPIO_CONFIG_FILE,
+ FTYPE_CONF, mpiosh_callback_put );
+ mpio_file_move( mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_CONFIG_FILE, NULL );
+
+ cleanup_restore:
+ free( path );
+}
+
+
+#if 0
+void
+mpiosh_cmd_config(char *args[])
+{
+ BYTE *config_data;
+ int size;
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ if (args[0] != NULL) {
+ if (!strcmp(args[0], "read")) {
+ if ((size = mpio_file_get(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CONFIG_FILE, NULL))<=0) {
+ fprintf(stderr, "Could not read config file\n");
+ } else {
+ printf("done.\n");
+ }
+ } else if (!strcmp(args[0], "write")) {
+ printf("deleting old config file ...\n");
+ mpio_file_del(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CONFIG_FILE, NULL);
+ printf("writing new config file ...\n");
+ if (mpio_file_put(mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_CONFIG_FILE,
+ FTYPE_CONF, NULL)==-1)
+ mpio_perror("error");
+ mpio_sync(mpiosh.dev, MPIO_INTERNAL_MEM);
+ } else if (!strcmp(args[0], "show")) {
+ if ((size = mpio_file_get_to_memory(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CONFIG_FILE, NULL, &config_data))<=0) {
+ fprintf(stderr, "Could not read config file\n");
+ } else {
+ hexdump(config_data, size);
+
+ printf("current config:\n"
+ "===============\n");
+
+ printf("volume:\t\t%-2d\n", config_data[0x00]);
+ printf("repeat:\t\t");
+ switch(config_data[0x01])
+ {
+ case 0:
+ printf("normal\n");
+ break;
+ case 1:
+ printf("repeat one\n");
+ break;
+ case 2:
+ printf("repeat all\n");
+ break;
+ case 3:
+ printf("shuffel\n");
+ break;
+ case 4:
+ printf("intro\n");
+ break;
+ default:
+ printf("unknown\n" );
+ }
+
+
+ fprintf(stderr, "\nfinish my implementation please!\n");
+ fprintf(stderr, "config values seem to be model dependant :-(\n");
+
+ free(config_data);
+ }
+ } else {
+ fprintf(stderr, "unknown config command\n");
+ printf("config [read|write|show] channel\n");
+ }
+ } else {
+ fprintf(stderr, "error: no arguments given\n");
+ printf("config [read|write|show] <\n");
+ }
+}
+#endif
+
+void
+mpiosh_cmd_channel(char *args[])
+{
+ CHAR *channel_data, *p, name[17];
+ int size;
+ int i;
+ int chan;
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+
+ if (args[0] != NULL) {
+ if (!strcmp(args[0], "read")) {
+ if ((size = mpio_file_get(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CHANNEL_FILE, NULL))<=0) {
+ fprintf(stderr, "Could not read channel file\n");
+ } else {
+ printf("done.\n");
+ }
+ } else if (!strcmp(args[0], "write")) {
+ printf("deleting old config file ...\n");
+ mpio_file_del(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CHANNEL_FILE, NULL);
+ printf("writing new config file ...\n");
+ if (mpio_file_put(mpiosh.dev, MPIO_INTERNAL_MEM, MPIO_CHANNEL_FILE,
+ FTYPE_CHAN, NULL)==-1)
+ mpio_perror("error");
+ mpio_sync(mpiosh.dev, MPIO_INTERNAL_MEM);
+ } else if (!strcmp(args[0], "show")) {
+ if ((size = mpio_file_get_to_memory(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CHANNEL_FILE, NULL, &channel_data))<=0) {
+ fprintf(stderr, "Could not read channel file\n");
+ } else {
+ hexdump(channel_data, size);
+
+ i=0;
+ p=channel_data;
+ while ((i<20) && (*p))
+ {
+ memset(name, 0, 17);
+ strncpy(name, p, 16);
+ chan = (((p[16] * 0x100) + p[17]) - 0x600) + 1750;
+ printf("%2d. %-16s at %7.2f MHz\n", (i+1),
+ name, ((float)chan/20));
+ p+=18;
+ i++;
+ }
+ if (!i)
+ printf("no channel defined!\n");
+
+ memcpy(channel_data, "mager", 5);
+
+ printf("deleting old config file ...\n");
+ mpio_file_del(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CHANNEL_FILE, NULL);
+ printf("writing new config file ...\n");
+ if (mpio_file_put_from_memory(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_CHANNEL_FILE,
+ FTYPE_CHAN, NULL,
+ channel_data, size)==-1)
+ mpio_perror("error");
+ mpio_sync(mpiosh.dev, MPIO_INTERNAL_MEM);
+
+ free(channel_data);
+ }
+ } else {
+ fprintf(stderr, "unknown channel command\n");
+ printf("channel [read|write|show] channel\n");
+ }
+ } else {
+ fprintf(stderr, "error: no arguments given\n");
+ printf("channel [read|write|show] <\n");
+ }
+}
+
+void
+mpiosh_cmd_ldir(char *args[])
+{
+ char dir_buf[NAME_MAX];
+ struct dirent ** dentry, **run;
+ int count;
+
+ getcwd(dir_buf, NAME_MAX);
+ if (dir_buf != '\0') {
+ if ((count = scandir(dir_buf, &dentry, NULL, alphasort)) != -1) {
+ int j, i;
+ struct stat st;
+ struct passwd * pwd;
+ struct group * grp;
+ char time[12];
+ char rights[11];
+
+ run = dentry;
+ rights[10] = '\0';
+ for (i = 0; i < count; i++, run++) {
+ if (stat((*run)->d_name, &st) == -1) {
+ perror("stat");
+ } else {
+ rights[0] = *("?pc?dnb?-?l?s???" + (st.st_mode >> 12 & 0xf));
+ for (j = 0; j < 9; j++) {
+ if (st.st_mode & 1 << (8 - j))
+ rights[j + 1] = "rwxrwxrwx"[j];
+ else
+ rights[j + 1] = '-';
+ }
+
+ pwd = getpwuid(st.st_uid);
+ grp = getgrgid(st.st_gid);
+ strftime(time, 12, "%b %2d", localtime(&(st.st_mtime)));
+ if (pwd && grp) {
+ printf("%s %8s %8s %8d %10s %s\n",
+ rights, pwd->pw_name, grp->gr_name, (int)st.st_size,
+ time, (*run)->d_name);
+ } else if (pwd) {
+ printf("%s %8s %8d %8d %10s %s\n",
+ rights, pwd->pw_name, st.st_gid, (int)st.st_size,
+ time, (*run)->d_name);
+ } else if (grp) {
+ printf("%s %8d %8s %8d %10s %s\n",
+ rights, st.st_uid, grp->gr_name, (int)st.st_size,
+ time, (*run)->d_name);
+ } else {
+ printf("%s %8d %8d %8d %10s %s\n",
+ rights, st.st_uid, st.st_gid, (int)st.st_size,
+ time, (*run)->d_name);
+ }
+ }
+ free(*run);
+ }
+ free(dentry);
+ } else {
+ perror("scandir");
+ }
+ }
+}
+
+void
+mpiosh_cmd_lpwd(char *args[])
+{
+ char dir_buf[NAME_MAX];
+
+ UNUSED(args);
+
+ getcwd(dir_buf, NAME_MAX);
+
+ printf("%s\n", dir_buf);
+}
+
+void
+mpiosh_cmd_lcd(char *args[])
+{
+ MPIOSH_CHECK_ARG;
+
+ if (chdir(args[0])) {
+ perror ("error");
+ }
+}
+
+void
+mpiosh_cmd_lmkdir(char *args[])
+{
+ MPIOSH_CHECK_ARG;
+
+ if (mkdir(args[0], 0777)) {
+ perror("error");
+ }
+}
+
+void
+mpiosh_cmd_font_upload(char *args[])
+{
+ BYTE * p;
+ int size;
+
+ MPIOSH_CHECK_CONNECTION_CLOSED;
+ MPIOSH_CHECK_ARG;
+
+ /* check if fonts file already exists */
+ p = mpio_file_exists(mpiosh.dev, MPIO_INTERNAL_MEM,
+ MPIO_FONT_FON);
+ if (p) {
+ printf("Fontsfile already exists. Please delete it first!\n");
+ return;
+ }
+
+ printf("writing new font file ...\n");
+ if (mpio_file_put_as(mpiosh.dev, MPIO_INTERNAL_MEM,
+ args[0], MPIO_FONT_FON,
+ FTYPE_FONT, mpiosh_callback_put)==-1)
+ mpio_perror("error");
+
+ printf("\n");
+ mpio_sync(mpiosh.dev, MPIO_INTERNAL_MEM);
+
+}
+
+
+/* end of callback.c */
diff --git a/src/callback.h b/src/callback.h
new file mode 100644
index 0000000..00ffb86
--- /dev/null
+++ b/src/callback.h
@@ -0,0 +1,101 @@
+/* callback.h
+ *
+ * Author: Andreas Büsching <crunchy@tzi.de>
+ *
+ * $Id: callback.h,v 1.13 2003/06/27 12:21:21 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 CALLBACK_HH
+#define CALLBACK_HH
+
+#include "libmpio/mpio.h"
+
+/* mpio command callbacks */
+void mpiosh_cmd_debug(char *args[]);
+void mpiosh_cmd_version(char *args[]);
+void mpiosh_cmd_help(char *args[]);
+void mpiosh_cmd_dir(char *args[]);
+void mpiosh_cmd_pwd(char *args[]);
+void mpiosh_cmd_mkdir(char *args[]);
+void mpiosh_cmd_cd(char *args[]);
+void mpiosh_cmd_info(char *args[]);
+void mpiosh_cmd_mem(char *args[]);
+void mpiosh_cmd_open(char *args[]);
+void mpiosh_cmd_close(char *args[]);
+void mpiosh_cmd_quit(char *args[]);
+void mpiosh_cmd_get(char *args[]);
+void mpiosh_cmd_mget(char *args[]);
+void mpiosh_cmd_put(char *args[]);
+void mpiosh_cmd_mput(char *args[]);
+void mpiosh_cmd_del(char *args[]);
+void mpiosh_cmd_mdel(char *args[]);
+void mpiosh_cmd_dump(char *args[]);
+void mpiosh_cmd_free(char *args[]);
+void mpiosh_cmd_format(char *args[]);
+void mpiosh_cmd_switch(char *args[]);
+void mpiosh_cmd_rename(char *args[]);
+void mpiosh_cmd_dump_mem(char *args[]);
+void mpiosh_cmd_health(char *args[]);
+void mpiosh_cmd_backup(char *args[]);
+void mpiosh_cmd_restore(char *args[]);
+#if 0
+void mpiosh_cmd_config(char *args[]);
+#endif
+void mpiosh_cmd_channel(char *args[]);
+void mpiosh_cmd_id3(char *args[]);
+void mpiosh_cmd_id3_format(char *args[]);
+void mpiosh_cmd_font_upload(char *args[]);
+
+/* local command callbacks */
+void mpiosh_cmd_ldir(char *args[]);
+void mpiosh_cmd_lpwd(char *args[]);
+void mpiosh_cmd_lcd(char *args[]);
+void mpiosh_cmd_lmkdir(char *args[]);
+
+/* progress callbacks */
+BYTE mpiosh_callback_init(mpio_mem_t, int read, int total);
+BYTE mpiosh_callback_get(int read, int total);
+BYTE mpiosh_callback_put(int read, int total);
+BYTE mpiosh_callback_del(int read, int total);
+BYTE mpiosh_callback_format(int read, int total);
+
+/* check situation */
+
+#define MPIOSH_CHECK_CONNECTION_OPEN \
+ if (mpiosh.dev != NULL) { \
+ printf("connection to MPIO player is open\n"); \
+ return; \
+ }
+
+#define MPIOSH_CHECK_CONNECTION_CLOSED \
+ if (mpiosh.dev == NULL) { \
+ printf("connection to MPIO player is closed\n"); \
+ return; \
+ }
+
+#define MPIOSH_CHECK_ARG \
+ if (args[0] == NULL) { \
+ printf("error: no argument given\n"); \
+ return; \
+ }
+
+
+#endif
+
+/* end of callback.h */
diff --git a/src/cfg.c b/src/cfg.c
new file mode 100644
index 0000000..f8c672f
--- /dev/null
+++ b/src/cfg.c
@@ -0,0 +1,238 @@
+/* config.c
+ *
+ * Author: Andreas Buesching <crunchy@tzi.de>
+ *
+ * $Id: config.c,v 1.7 2003/06/27 13:40:23 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 "cfg.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, *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);
+ else
+ cfg->handle_global = 0;
+
+ 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);
+
+ /* initialise history */
+ using_history();
+
+ filename = malloc(strlen(CONFIG_USER) + strlen(CONFIG_HISTORY) + 1);
+ filename[0] = '\0';
+ strcat(filename, CONFIG_USER);
+ strcat(filename, CONFIG_HISTORY);
+ tmp = cfg_resolve_path(filename);
+
+ read_history(tmp);
+ 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)
+{
+ if (config->handle_global)
+ 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;
+ }
+ }
+
+ value = mpiosh_config_read_key(config, "mpiosh", "charset");
+ if (value) {
+ config->charset = strdup(value);
+ } else {
+ config->charset = NULL;
+ }
+
+ value = mpiosh_config_read_key(config, "mpiosh", "id3_rewriting");
+ if (value) {
+ if (!strcmp("on", value)) {
+ config->id3_rewriting = 1;
+ } else {
+ config->id3_rewriting = 0;
+ }
+ }
+
+ value = mpiosh_config_read_key(config, "mpiosh", "id3_format");
+ if (value) {
+ config->id3_format = strdup(value);
+ } else {
+ config->id3_format = strdup(MPIO_ID3_FORMAT);
+ }
+
+ }
+
+ return 1;
+}
+
+char *
+mpiosh_config_check_backup_dir( struct mpiosh_config_t *config, int create )
+{
+ DIR *dir;
+ char *path = cfg_resolve_path( CONFIG_BACKUP );
+ char *ret = path;
+
+ if ( ( dir = opendir( path ) ) == NULL )
+ if ( create ) {
+ if ( mkdir(path, 0777 ) )
+ ret = NULL;
+ } else
+ ret = NULL;
+ else
+ closedir(dir);
+
+ return ret;
+}
+
+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) {
+ char *tmp, *filename;
+
+ 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_key_set_value(config->handle_user,
+ "mpiosh", "id3_rewriting",
+ (config->id3_rewriting?"on":"off"));
+ cfg_key_set_value(config->handle_user,
+ "mpiosh", "id3_format", config->id3_format);
+
+ cfg_save(config->handle_user, 0);
+
+ /* save history */
+ filename = malloc(strlen(CONFIG_USER) + strlen(CONFIG_HISTORY) + 1);
+ filename[0] = '\0';
+ strcat(filename, CONFIG_USER);
+ strcat(filename, CONFIG_HISTORY);
+ tmp = cfg_resolve_path(filename);
+
+ printf("writing history to file %s\n", filename);
+ write_history(tmp);
+ free(tmp), free(filename);
+ }
+
+ return 1;
+}
+
+
+/* end of config.c */
diff --git a/src/cfg.h b/src/cfg.h
new file mode 100644
index 0000000..4157bd6
--- /dev/null
+++ b/src/cfg.h
@@ -0,0 +1,56 @@
+/* config.h
+ *
+ * Author: Andreas Buesching <crunchy@tzi.de>
+ *
+ * $Id: config.h,v 1.5 2003/06/27 13:40:23 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;
+ char *charset;
+ unsigned default_mem;
+
+ unsigned id3_rewriting;
+ char *id3_format;
+};
+
+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);
+
+char * mpiosh_config_check_backup_dir( struct mpiosh_config_t *config,
+ int create );
+
+#endif
+
+/* end of config.h */
+
diff --git a/src/cfgio.c b/src/cfgio.c
new file mode 100644
index 0000000..b8a1829
--- /dev/null
+++ b/src/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/src/cfgio.h b/src/cfgio.h
new file mode 100644
index 0000000..d58cd3f
--- /dev/null
+++ b/src/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/src/command.c b/src/command.c
new file mode 100644
index 0000000..9c42a8c
--- /dev/null
+++ b/src/command.c
@@ -0,0 +1,222 @@
+/* command.c
+ *
+ * Author: Andreas Buesching <crunchy@tzi.de>
+ *
+ * $Id: command.c,v 1.3 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 "command.h"
+
+char **
+mpiosh_command_split_line(char *line)
+{
+ char **cmds, *cmd;
+ int count = 1;
+ char *help, *copy = strdup(line);
+
+ help = copy;
+
+ while (*help)
+ if ((*help++ == ';') && (*(help) != '\0')) count++;
+ cmds = malloc(sizeof(char *) * (count + 1));
+
+ cmd = help = copy, count = 0;
+ while (*cmd == ' ') cmd++;
+ while (help) {
+ if (*help == '"') {
+ help++;
+ while (*help != '\0' && *help != '"') help++;
+ }
+
+ if (*help == '\0') break;
+ if (*help == ';') {
+ *help++ = '\0';
+ if (*help == '\0') break;
+ cmds[count++] = strdup(cmd);
+ while (*help == ' ') help++;
+ cmd = help;
+ }
+ help++;
+ }
+ if (cmd != '\0') {
+ cmds[count++] = strdup(cmd);
+ }
+
+ cmds[count] = NULL;
+ free(copy);
+
+ return cmds;
+}
+
+struct mpiosh_cmd_t *
+mpiosh_command_find(char *line)
+{
+ struct mpiosh_cmd_t *cmd = commands;
+
+ while (cmd->cmd) {
+ if (strstr(line, cmd->cmd) == line) {
+ if (line[strlen(cmd->cmd)] == ' ' ||
+ line[strlen(cmd->cmd)] == '\0')
+ return cmd;
+ } else if (cmd->aliases) {
+ char **go = cmd->aliases;
+ while (*go) {
+ if ((strstr(line, *go) == line) &&
+ ((line[strlen(*go)] == ' ') || (line[strlen(*go)] == '\0'))) {
+ return cmd;
+ }
+ go++;
+ }
+ }
+
+ cmd++;
+ }
+
+ return NULL;
+}
+
+void
+mpiosh_command_regex_fix(char *argv[])
+{
+ char **walk = argv;
+ char *new_pos, *help;
+ char buffer[512];
+
+ while (*walk) {
+ memset(buffer, '\0', 512);
+ help = *walk;
+ new_pos = buffer;
+ *new_pos++ = '^';
+ while (*help != '\0') {
+ if (*help == '*' && ((help == *walk) || (*(help - 1) != '.'))) {
+ *new_pos++ = '.';
+ *new_pos = *help;
+ } else if ((*help == '.') && (*(help + 1) != '*')) {
+ *new_pos++ = '\\';
+ *new_pos = *help;
+ } else if (*help == '?' && ((help == *walk) || (*(help - 1) != '\\'))) {
+ *new_pos = '.';
+ } else {
+ *new_pos = *help;
+ }
+
+ help++, new_pos++;
+ }
+ *new_pos = '$';
+ free(*walk);
+ *walk = strdup(buffer);
+
+ walk++;
+ }
+}
+
+char **
+mpiosh_command_get_args(char *line)
+{
+ char **args;
+ char *arg_start, *copy, *help, *prev;
+ int count = 0, i = 0, go = 1, in_quote = 0;
+
+ copy = strdup(line);
+ arg_start = strchr(copy, ' ');
+
+ if (arg_start == NULL) {
+ args = malloc(sizeof(char *));
+ args[0] = NULL;
+ return args;
+ }
+
+ while (*arg_start == ' ') arg_start++;
+
+ help = arg_start;
+ while (help <= (copy + strlen(copy))) {
+ if (*help == '"') {
+ help++;count++;
+
+ while (*help != '\0' && *help != '"')
+ help++;
+ help++;
+ while (*help == ' ') help++;
+ if (*help == '\0') break;
+ in_quote = 1;
+ } else if (((help > arg_start) && (*help == '\0')) ||
+ (*help == ' ' && (*(help + 1) != '\0') && (*(help + 1) != ' '))) {
+ count++;
+ in_quote = 0;
+ help++;
+ } else
+ help++;
+ }
+
+ args = malloc(sizeof(char *) * (count + 1));
+
+ help = prev = arg_start;
+ in_quote = 0;
+ while (go) {
+ if (*help == '"') in_quote = !in_quote, help++;
+ if (((*help == ' ') && !in_quote) || (in_quote && *help == '"') ||
+ (*help == '\0')) {
+ if (*help == '\0') {
+ go = 0;
+ if (*prev == '\0') break;
+ }
+
+ if (*prev == '"') {
+ if (*(help - 1) == '"')
+ *(help - 1) = '\0';
+ else
+ *help = '\0';
+
+ args[i++] = strdup(prev + 1);
+ } else {
+ *help = '\0';
+ args[i++] = strdup(prev);
+ }
+
+ if (go) {
+ help++;
+ if (in_quote) {
+ while (*help != '"') help++;
+ help++;
+ in_quote = 0;
+ } else
+ while (*help == ' ') help++;
+ prev = help;
+ }
+ } else
+ help++;
+ }
+ args[i] = NULL;
+
+ free(copy);
+
+ return args;
+}
+
+void
+mpiosh_command_free_args(char **args)
+{
+ char **arg = args;
+
+ while (*arg) free(*arg++);
+
+ free(args);
+}
+
+/* end of command.c */
diff --git a/src/command.h b/src/command.h
new file mode 100644
index 0000000..34dbc9b
--- /dev/null
+++ b/src/command.h
@@ -0,0 +1,38 @@
+/* command.h
+ *
+ * Author: Andreas Buesching <crunchy@tzi.de>
+ *
+ * $Id: command.h,v 1.2 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_COMMAND_HH
+#define MPIOSH_COMMAND_HH
+
+#include "mpiosh.h"
+
+/* command(-line) functions */
+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[]);
+void mpiosh_command_free_args(char **args);
+
+#endif
+
+/* end of command.h */
diff --git a/src/config.h.in b/src/config.h.in
new file mode 100644
index 0000000..bb60f14
--- /dev/null
+++ b/src/config.h.in
@@ -0,0 +1,9 @@
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+/* package name */
+#define PACKAGE "${PACKAGE}"
+#define VERSION "0.7.1-pre3"
+#define SYSCONFDIR "/etc"
+
+#endif /* _CONFIG_H */
diff --git a/src/global.c b/src/global.c
new file mode 100644
index 0000000..04fd9e7
--- /dev/null
+++ b/src/global.c
@@ -0,0 +1,159 @@
+/* global.c - containing global symbols for mpiosh
+ *
+ * Author: Andreas Buesching <crunchy@tzi.de>
+ *
+ * $Id: global.c,v 1.14 2003/06/27 12:21:21 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 "callback.h"
+#include "global.h"
+#include "readline.h"
+#include "cfg.h"
+
+/* structure containing current state */
+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;
+
+/* configuration filenames */
+const char *CONFIG_GLOBAL = SYSCONFDIR "/mpio/";
+const char *CONFIG_USER = "~/.mpio/";
+const char *CONFIG_BACKUP = "~/.mpio/backup/";
+const char *CONFIG_FILE = "mpioshrc";
+const char *CONFIG_HISTORY = "history";
+
+/* prompt strings */
+const char *PROMPT_INT = "\033[;1mmpio <i>\033[m ";
+const char *PROMPT_EXT = "\033[;1mmpio <e>\033[m ";
+
+struct mpiosh_cmd_t commands[] = {
+ { "debug", NULL , "[level|file|on|off] <value>",
+ " modify debugging options",
+ mpiosh_cmd_debug, NULL },
+ { "ver", NULL, NULL,
+ " version of mpio package",
+ mpiosh_cmd_version, NULL },
+ { "help", (char *[]){ "?", NULL }, "[<command>]",
+ " show information about known commands or just about <command>",
+ mpiosh_cmd_help, mpiosh_readline_comp_cmd },
+ { "dir", (char *[]){ "ls", "ll", NULL }, NULL,
+ " list content of current memory card",
+ mpiosh_cmd_dir, NULL },
+ { "pwd", NULL, NULL,
+ " print the current working directory",
+ mpiosh_cmd_pwd, NULL },
+ { "mkdir", (char *[]){ "md", NULL }, "<directory>",
+ " make a new directory",
+ mpiosh_cmd_mkdir, mpiosh_readline_comp_mpio_file },
+ { "cd", NULL, "<directory>",
+ " change the current working directory",
+ mpiosh_cmd_cd, mpiosh_readline_comp_mpio_file },
+ { "info", NULL, NULL,
+ " show information about MPIO player",
+ mpiosh_cmd_info, NULL },
+ { "mem", NULL, "[i|e]",
+ " set current memory card. 'i' selects the internal and 'e'\n"
+ " selects the external memory card (smart media card)",
+ mpiosh_cmd_mem, NULL },
+ { "open", NULL, NULL,
+ " open connect to MPIO player",
+ mpiosh_cmd_open, NULL },
+ { "close", NULL, NULL,
+ " close connect to MPIO player",
+ mpiosh_cmd_close, NULL },
+ { "quit", (char *[]){ "exit", NULL }, NULL,
+ " exit mpiosh and close the device",
+ mpiosh_cmd_quit, NULL },
+ { "mget", (char *[]){ "get", NULL }, "list of filenames and <regexp>",
+ " read all files matching the regular expression\n"
+ " from the selected memory card",
+ mpiosh_cmd_mget, mpiosh_readline_comp_mpio_file },
+ { "mput", (char *[]){ "put", NULL }, "list of filenames and <regexp>",
+ " write all local files matching the regular expression\n"
+ " to the selected memory card",
+ mpiosh_cmd_mput, NULL },
+ { "mdel", (char *[]){ "rm", "del", NULL }, "<regexp>",
+ " deletes all files matching the regular expression\n"
+ " from the selected memory card",
+ mpiosh_cmd_mdel, mpiosh_readline_comp_mpio_file },
+ { "dump", NULL, NULL,
+ " get all files of current memory card",
+ mpiosh_cmd_dump, NULL },
+ { "free", NULL, NULL,
+ " display amount of available bytes of current memory card",
+ mpiosh_cmd_free, NULL },
+ { "format", NULL, NULL,
+ " format current memory card",
+ mpiosh_cmd_format, NULL },
+ { "switch", NULL, "<file1> <file2>",
+ " switches the order of two files",
+ mpiosh_cmd_switch, mpiosh_readline_comp_mpio_file },
+ { "rename", (char *[]){ "ren", NULL }, "<oldfilename> <newfilename>",
+ " renames a file on the current memory card",
+ mpiosh_cmd_rename, mpiosh_readline_comp_mpio_file },
+ { "ldir", (char *[]){ "lls", NULL }, NULL,
+ " list local directory",
+ mpiosh_cmd_ldir, NULL },
+ { "lpwd", NULL, NULL,
+ " print current working directory",
+ mpiosh_cmd_lpwd, NULL },
+ { "lcd", NULL, NULL,
+ " change the current working directory",
+ mpiosh_cmd_lcd, NULL },
+ { "lmkdir", NULL, NULL,
+ " create a local directory",
+ mpiosh_cmd_lmkdir, NULL },
+ { "health", NULL, NULL,
+ " show the health status from the selected memory",
+ mpiosh_cmd_health, NULL },
+ { "font_upload", NULL, "[<fontfile>]",
+ " upload the give fontfile to the internal memory",
+ mpiosh_cmd_font_upload, NULL },
+ { "dump_memory", NULL, NULL,
+ " dump FAT, directory, spare area and the first 0x100 of the\n"
+ " selected memory card",
+ mpiosh_cmd_dump_mem, NULL },
+ { "backup", NULL, NULL,
+ " create a backup of all known configuration files.",
+ mpiosh_cmd_backup, NULL },
+ { "restore", NULL, NULL,
+ " restore an existing backup of all known configuration files.",
+ mpiosh_cmd_restore, NULL },
+#if 0
+ /* deactivated for the 0.6.0 release because the code is incomplete! -mager */
+ { "config", (char *[]) { "conf", NULL }, "[read|write|show]",
+ " give access to the configuration file of the MPIO player\n"
+ " read read the configuration file and dump it on the local disc\n"
+ " write write the configuration back to the MPIO player\n"
+ " show show the current configuration",
+ mpiosh_cmd_config, mpiosh_readline_comp_config },
+ { "channel", (char *[]) { "channels", "chan", NULL }, "[read|write|show]",
+ " give access to the radio channel file of the MPIO player\n"
+ " read read the channel file and dump it on the local disc\n"
+ " write write the channel file back to the MPIO player\n"
+ " show show the current channel configuration",
+ mpiosh_cmd_channel, mpiosh_readline_comp_config },
+#endif
+ { NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+/* end of global.c */
diff --git a/src/global.h b/src/global.h
new file mode 100644
index 0000000..1e52491
--- /dev/null
+++ b/src/global.h
@@ -0,0 +1,68 @@
+/* global.h
+ *
+ * Author: Andreas Buesching <crunchy@tzi.de>
+ *
+ * $Id: global.h,v 1.3 2003/06/27 12:21:22 crunchy Exp $
+ *
+ * Copyright (C) 2001-2003 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_GLOBAL_HH
+#define MPIOSH_GLOBAL_HH
+
+#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);
+
+struct mpiosh_t {
+ mpio_t * dev;
+ mpio_mem_t card;
+ const char * prompt;
+ struct mpiosh_config_t *config;
+};
+
+struct mpiosh_cmd_t {
+ char *cmd;
+ char **aliases;
+ char *args;
+ char *info;
+ mpiosh_cmd_callback_t cmd_func;
+ mpiosh_comp_callback_t comp_func;
+};
+
+/* global structures */
+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_BACKUP;
+extern const char *CONFIG_FILE;
+extern const char *CONFIG_HISTORY;
+
+extern const char *PROMPT_INT;
+extern const char *PROMPT_EXT;
+
+#endif
+
+/* end of global.h */
diff --git a/src/mpiosh.c b/src/mpiosh.c
new file mode 100644
index 0000000..e74278d
--- /dev/null
+++ b/src/mpiosh.c
@@ -0,0 +1,163 @@
+/* -*- linux-c -*- */
+
+/*
+ *
+ * $Id: mpiosh.c,v 1.27 2003/08/25 19:38:57 crunchy Exp $
+ *
+ * Author: Andreas Büsching <crunchy@tzi.de>
+ *
+ * mpiosh - user interface of the mpio library, providing access to
+ * some model of the MPIO mp3 players.
+ *
+ * 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 of the
+ * License, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "libmpio/debug.h"
+#include "libmpio/mpio.h"
+
+#include "callback.h"
+#include "command.h"
+#include "cfg.h"
+#include "readline.h"
+#include "mpiosh.h"
+
+/* mpiosh core functions */
+void
+mpiosh_init(void)
+{
+ /* set state */
+ mpiosh.dev = NULL;
+ 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");
+
+ if ((mpiosh.dev) && (mpiosh.config->charset))
+ mpio_charset_set(mpiosh.dev, mpiosh.config->charset);
+}
+
+void
+mpiosh_signal_handler(int signal)
+{
+ mpiosh_cancel = 1;
+ mpiosh_cancel_ack = 0;
+}
+
+int
+main(int argc, char *argv[]) {
+ char *line;
+ char **cmds, **walk;
+ struct mpiosh_cmd_t *cmd;
+ struct sigaction sigc;
+ int interactive = 1;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ setenv("mpio_debug", "", 0);
+ setenv("mpio_color", "", 0);
+
+ /* no unwanted interruption anymore */
+ sigc.sa_handler = mpiosh_signal_handler;
+ sigc.sa_flags = SA_NOMASK;
+
+ sigaction(SIGINT, &sigc, NULL);
+
+ /* init readline and history */
+ mpiosh_readline_init();
+ debug_init();
+ mpiosh_init();
+
+ if (!isatty(fileno(stdin))) {
+ interactive = 0;
+ mpiosh.prompt = NULL;
+ mpiosh_readline_pipe();
+ }
+
+ if( !isatty(fileno(stdout)) ) {
+ setvbuf( stdout, NULL, _IOLBF, 256 );
+ }
+
+ if (!mpiosh.dev && interactive) {
+ printf("ERROR: %s\n", mpio_strerror(mpio_errno()));
+ printf("could not find MPIO player.\n");
+ }
+
+ while ((line = readline(mpiosh.prompt))) {
+ if ((*line == '\0') || mpiosh_cancel) {
+ rl_clear_pending_input ();
+ mpiosh_cancel = 0;
+ mpiosh_cancel_ack = 0;
+ continue;
+ }
+
+ cmds = mpiosh_command_split_line(line);
+
+ if (cmds[0][0] == '\0') {
+ free(cmds);
+ continue;
+ }
+
+ walk = cmds;
+ while (*walk) {
+ cmd = mpiosh_command_find(*walk);
+
+ if (cmd) {
+ char ** help, **args = mpiosh_command_get_args(*walk);
+ help = args;
+
+ if (!interactive) debug("running... '%s'\n", *walk);
+ cmd->cmd_func(args);
+ mpiosh_command_free_args(args);
+ } else
+ fprintf(stderr, "unknown command: '%s'\n", *walk);
+
+/* if ((idx = history_search(line, -1)) != -1) */
+/* history_set_pos(idx); */
+/* else */
+ add_history(line);
+ free(*walk);
+ walk++;
+ }
+ free(cmds);
+
+ /* reset abort state */
+ mpiosh_cancel = 0;
+ }
+
+ mpiosh_cmd_quit(NULL);
+
+ return 0;
+}
diff --git a/src/mpiosh.h b/src/mpiosh.h
new file mode 100644
index 0000000..8291178
--- /dev/null
+++ b/src/mpiosh.h
@@ -0,0 +1,37 @@
+/* mpiosh.h
+ *
+ * Author: Andreas Büsching <crunchy@tzi.de>
+ *
+ * $Id: mpiosh.h,v 1.8 2002/10/12 20:06:22 crunchy Exp $
+ *
+ * Copyright (C) 2002 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_H_
+#define _MPIOSH_H_
+
+#include "libmpio/debug.h"
+
+#include "global.h"
+
+/* mpiosh core functions */
+void mpiosh_signal_handler(int signal);
+void mpiosh_init(void);
+
+#endif // _MPIOSH_H_
+
+/* end of mpiosh.h */
diff --git a/src/readline.c b/src/readline.c
new file mode 100644
index 0000000..afc78c0
--- /dev/null
+++ b/src/readline.c
@@ -0,0 +1,212 @@
+/* readline.c
+ *
+ * Author: Andreas Büsching <crunchy@tzi.de>
+ *
+ * $Id: readline.c,v 1.7 2003/04/23 08:34:16 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 "readline.h"
+
+#include "command.h"
+#include "mpiosh.h"
+
+/* readline extensions */
+void
+mpiosh_readline_init(void)
+{
+ rl_readline_name = "mpio";
+ rl_catch_signals = 0;
+ rl_completer_quote_characters = "\"\'";
+ rl_filename_quote_characters = " \"\' ";
+ rl_attempted_completion_function = mpiosh_readline_completion;
+ rl_event_hook = mpiosh_readline_cancel;
+}
+
+char *
+mpiosh_readline_comp_onoff(const char *text, int state)
+{
+ static const char * states[] = { "on", "off", NULL };
+ static const char ** st = states;
+ const char * ret = NULL;
+
+ if (state == 0) {
+ st = states;
+ }
+
+ while (*st) {
+ if (!strncmp(text, *st, strlen(text))) {
+ ret = *st;
+ st++;
+ break;
+ }
+ st++;
+ }
+
+ return (ret ? strdup(ret) : NULL);
+}
+
+char *
+mpiosh_readline_comp_cmd(const char *text, int state)
+{
+ static struct mpiosh_cmd_t *cmd = NULL;
+ static char **alias = NULL;
+ char *cmd_text = NULL;
+
+ if (state == 0) {
+ cmd = commands;
+ }
+
+ while (cmd->cmd) {
+ if (!alias) {
+ if ((*text == '\0') || (strstr(cmd->cmd, text) == cmd->cmd)) {
+ cmd_text = strdup(cmd->cmd);
+ if (cmd->aliases) alias = cmd->aliases;
+ else cmd++;
+ break;
+ }
+ if (cmd->aliases) alias = cmd->aliases;
+ else cmd++;
+ } else {
+ int break_it = 0;
+
+ while (*alias) {
+ if (strstr(*alias, text) == *alias) {
+ cmd_text = strdup(*alias);
+ alias++;
+ break_it = 1;
+ break;
+ }
+ alias++;
+ }
+ if (break_it) break;
+ if (*alias == NULL) cmd++, alias = NULL;
+ }
+ }
+
+ return cmd_text;
+}
+
+char *
+mpiosh_readline_comp_mpio_file(const char *text, int state)
+{
+ static BYTE *p;
+ char *arg = NULL;
+ BYTE month, day, hour, minute, type;
+ char fname[100];
+ WORD year;
+ DWORD fsize;
+
+ if (mpiosh.dev == NULL) {
+ rl_attempted_completion_over = 1;
+ return NULL;
+ }
+
+ if (state == 0) p = mpio_directory_open(mpiosh.dev, mpiosh.card);
+
+ while ((p != NULL) && (arg == NULL)) {
+ memset(fname, '\0', 100);
+
+ mpio_dentry_get(mpiosh.dev, mpiosh.card, p,
+ fname, 100,
+ &year, &month, &day,
+ &hour, &minute, &fsize, &type);
+
+ if (strstr(fname, text) == fname) {
+ arg = strdup(fname);
+ if (strchr(arg, ' ')) {
+ rl_filename_completion_desired = 1;
+ rl_filename_quoting_desired = 1;
+ }
+ }
+
+ p = mpio_dentry_next(mpiosh.dev, mpiosh.card, p);
+ }
+
+
+ return arg;
+}
+
+char *
+mpiosh_readline_comp_config(const char *text, int state)
+{
+ 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 res;
+}
+
+
+char **
+mpiosh_readline_completion(const char *text, int start, int end)
+{
+ char **matches = (char**)NULL;
+
+ UNUSED(end);
+
+ if (start == 0) /* command completion */
+ matches = rl_completion_matches(text, mpiosh_readline_comp_cmd);
+ else {
+ struct mpiosh_cmd_t *scmd;
+ char *cmd, *help= rl_line_buffer;
+
+ while (*help != ' ') help++;
+ cmd = malloc(help - rl_line_buffer + 1);
+ strncpy(cmd, rl_line_buffer, help - rl_line_buffer + 1);
+ cmd[help - rl_line_buffer] = '\0';
+
+ if ((scmd = mpiosh_command_find(cmd))) {
+ if (scmd->comp_func) {
+ matches = rl_completion_matches(text, scmd->comp_func);
+ }
+ }
+
+ free(cmd);
+ }
+
+ return matches;
+}
+
+int
+mpiosh_readline_cancel(void)
+{
+ if (mpiosh_cancel) rl_done = 1;
+
+ return 0;
+}
+
+void
+mpiosh_readline_noredisplay(void)
+{
+}
+
+void
+mpiosh_readline_pipe(void)
+{
+ rl_redisplay_function = mpiosh_readline_noredisplay;
+ rl_event_hook = NULL;
+}
+
+/* end of readline.c */
diff --git a/src/readline.h b/src/readline.h
new file mode 100644
index 0000000..a0bb08a
--- /dev/null
+++ b/src/readline.h
@@ -0,0 +1,47 @@
+/* readline.h
+ *
+ * Author: Andreas Büsching <crunchy@tzi.de>
+ *
+ * $Id: readline.h,v 1.3 2003/04/23 08:34:16 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_READLINE_HH
+#define MPIOSH_READLINE_HH
+
+#include <stdio.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+/* readline extensions */
+void mpiosh_readline_init(void);
+char **mpiosh_readline_completion(const char *text, int start, int end);
+
+void mpiosh_readline_noredisplay(void);
+void mpiosh_readline_pipe(void);
+int mpiosh_readline_cancel(void);
+
+char *mpiosh_readline_comp_cmd(const char *text, int state);
+char *mpiosh_readline_comp_onoff(const char *text, int state);
+char *mpiosh_readline_comp_mpio_file(const char *text, int state);
+char *mpiosh_readline_comp_config(const char *text, int state);
+
+#endif
+
+/* end of readline.h */