diff options
author | Lars-Dominik Braun <PromyLOPh@lavabit.com> | 2009-05-09 16:07:05 +0200 |
---|---|---|
committer | Lars-Dominik Braun <PromyLOPh@lavabit.com> | 2009-05-09 16:09:08 +0200 |
commit | 619beb63a1748cd9ece96260bfb2e9484e52cb67 (patch) | |
tree | 12aeffdd99d378c088f3c3aad634bb5d3e9000b4 /src | |
parent | 2d49dfdd370852d5033b848fd69b6112368b7d20 (diff) | |
download | mpiosh-619beb63a1748cd9ece96260bfb2e9484e52cb67.tar.gz mpiosh-619beb63a1748cd9ece96260bfb2e9484e52cb67.tar.bz2 mpiosh-619beb63a1748cd9ece96260bfb2e9484e52cb67.zip |
Cleanup
Remove unused files, move mpiosh to src, ...
Diffstat (limited to 'src')
-rw-r--r-- | src/.gitignore | 2 | ||||
-rw-r--r-- | src/CMakeLists.txt | 10 | ||||
-rw-r--r-- | src/callback.c | 1273 | ||||
-rw-r--r-- | src/callback.h | 101 | ||||
-rw-r--r-- | src/cfg.c | 238 | ||||
-rw-r--r-- | src/cfg.h | 56 | ||||
-rw-r--r-- | src/cfgio.c | 654 | ||||
-rw-r--r-- | src/cfgio.h | 453 | ||||
-rw-r--r-- | src/command.c | 222 | ||||
-rw-r--r-- | src/command.h | 38 | ||||
-rw-r--r-- | src/config.h.in | 9 | ||||
-rw-r--r-- | src/global.c | 159 | ||||
-rw-r--r-- | src/global.h | 68 | ||||
-rw-r--r-- | src/mpiosh.c | 163 | ||||
-rw-r--r-- | src/mpiosh.h | 37 | ||||
-rw-r--r-- | src/readline.c | 212 | ||||
-rw-r--r-- | src/readline.h | 47 |
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(®ex, args[i], REG_NOSUB))) { + regerror(error, ®ex, 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(®ex, 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, ®ex, 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(®ex); +} + +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(®ex, args[i], REG_NOSUB))) { + regerror(error, ®ex, 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(®ex, (*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, ®ex, errortext, 100); + debugn(2, "file does not match: %s (%s)\n", + (*run)->d_name, errortext); + } + free(*run); + } + free(dentry); + } + } + i++; + } + regfree(®ex); + 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(®ex, args[i], REG_NOSUB))) { + regerror(error, ®ex, 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(®ex, 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, ®ex, errortext, 100); + debugn (2, "file does not match: %s (%s)\n", fname, errortext); + p = mpio_dentry_next(mpiosh.dev, mpiosh.card, p); + } + + } + } + i++; + } + regfree(®ex); + 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 */ |