/************************************************************************ * Copyright (C) 2001 Thomas Schulz * * */ static char rcsid[] = "$Id: ic35mgr.c,v 1.20 2001/11/20 23:08:35 thosch Exp $"; /* * * * IC35 manager * * * ************************************************************************* * * * ??? is "fixme" mark: sections of code needing fixes * * * * conditional compile on NO_LOGSIM: if #defined, logging of the * * IC35 communications as well as simulated communication are NOT * * supported, default WITH logging and com-simulation support. * * * * for usage run ic35mgr -h or see function usage() below. * * * ************************************************************************/ #include /* printf(), .. */ #include /* malloc(), free() */ #include /* memcpy(), strcpy() ..*/ #include /* islower(), .. */ #include /* getopt(), optarg, .. */ #include /* struct tm, time() .. */ #include /* struct utimbuf, .. */ #include #include #include #include #include "util.h" /* FALSE, .. */ #include "comio.h" /* COM_SIMINIT(), .. */ #include "mgrtrans.h" /* IC35mgr transactions */ NOTUSED(rcsid) extern char * pkgvers; /* these are all */ extern char * pkgdate; /* in versinfo.c, which is */ extern char * bldinfo; /* auto-generated by Makefile */ /* ==================================== */ /* IC35 manager commands */ /* ==================================== */ /* report IC35 status * ------------------ */ static int ic35mgrstat( char * devname, char * statfname ) { int mmcnum; int rval; char label[11+1]; if ( (rval = mconnect( devname, statfname )) != OK ) return rval; for ( mmcnum = 1; mmcnum <= 2; ++mmcnum ) { if ( (rval = mmc_status( mmcnum )) < 0 ) break; if ( rval != 0 ) { if ( (rval = mmc_label( mmcnum, label )) < 0 ) break; message( "MMCard%d found, label: \"%s\"", mmcnum, label ); } else { message( "MMCard%d not present", mmcnum ); } } mdisconnect(); return rval; } /* backup IC35 database to file * ---------------------------- */ static int ic35backup( char * devname, char * fname ) { int rval; if ( (rval = mconnect( devname, NULL )) != OK ) return rval; rval = readdatabase( fname ); mdisconnect(); return rval; } /* restore IC35 database from file * ------------------------------- */ static int ic35restore( char * devname, char * fname ) { int rval; if ( (rval = mconnect( devname, NULL )) != OK ) return rval; rval = writedatabase( fname ); mdisconnect(); return rval; } /* list IC35 MMCard(s) directories * ------------------------------- * list looks like: * MMCardn "Label" * size filetimestamp attr filepath * nnnnnnnnnn yyyy-mm-dd hh:mm:ss xxx MMCard1\subdir\filename.ext */ static int mmcdirlist( char * dirpath ) { MMCDIR * dirp; MMCDIRENT * dirent; size_t pfxlen; char * subdir; char attrtext[4+1]; int rval, rc; if ( (dirp = mmc_opendir( dirpath )) == NULL ) return ERR; pfxlen = strlen( dirpath ) + 1; rval = OK; while ( (dirent = mmc_readdir( dirp )) != NULL ) { switch ( dirent->attr ) { case MMCattrDirectory: strcpy( attrtext, "dir" ); break; case MMCattrArchive: strcpy( attrtext, "arc" ); break; default: sprintf( attrtext, "0x%02X", dirent->attr & 0xFF ); } printf( "%10ld %s %4s %s\\%s\n", dirent->size, mmctstampstr( dirent->tstamp ), attrtext, dirpath, dirent->name ); fflush( stdout ); if ( dirent->attr & MMCattrDirectory && strcmp( dirent->name, ".." ) != 0 && (subdir = malloc( pfxlen + strlen(dirent->name) + 1 )) != NULL ) { sprintf( subdir, "%s\\%s", dirpath, dirent->name ); rc = mmcdirlist( subdir ); if ( rval == OK ) rval = rc; free( subdir ); } } rc = mmc_closedir( dirp ); if ( rval == OK ) rval = rc; return rval; /* errcode of first failure or success OK */ } static int ic35mmcdir( char * devname ) { int mmcnum; int rval; char label[11+1]; char dirpath[7+1]; if ( (rval = mconnect( devname, NULL )) != OK ) return rval; for ( mmcnum = 1; mmcnum <= 2; ++mmcnum ) { if ( (rval = mmc_status( mmcnum )) < 0 ) break; if ( rval == 0 ) { message( "MMCard%d not present", mmcnum ); continue; } if ( (rval = mmc_label( 1, label )) < 0 ) break; printf( "MMCard%d \"%s\"\n", mmcnum, label ); fflush( stdout ); sprintf( dirpath, "MMCard%d", mmcnum ); if ( (rval = mmcdirlist( dirpath )) < 0 ) break; } mdisconnect(); return rval; } /* ==================================== */ /* IC35 MMCard file commands */ /* ==================================== */ #define MINBLKSZ 1 /* min.blocksize */ #define MAXBLKSZ 16350 /* max.blocksize (found by experiments) */ #define ERR_mmcpfx -1 #define ERR_mmcnum -2 #define ERR_mmcslash -3 #define ERR_mmcbadpath -4 static char * MMCard = "MMCard"; static int blocksize; /* read/write buffer size mmcget/mmcput */ /* check,convert MMCard path to IC35 format & get MMCard number * ------------------------------------------------------ * the ic35path will be checked (slash means / or \): * - prefix must be "MMCard" in lowercase or uppercase or mixed * - MMCard number after prefix must be '1' or '2' * - slash after MMCard number (unless the path ends there) * - no adjacent slashes * - at most one dot between slashes * - max. 8 characters after slash until dot or slash or end * - max. 3 characters after dot until slash or end * the ic35path will be translated to match IC35 requirements: * translate '/' to '\' dir separators and lowercase to upper. * the translation is done in place, i.e. the argument string * is modified. * returns: * -1 ERR, missing "MMCard" prefix * -2 ERR, bad MMCard number (not 1,2) * -3 ERR, missing slash/backslash after "MMCard[12]" * -4 ERR, bad path component (too long, >1 dot, adjacent slashes) * * parameter mode: if 1 create directories */ static int _ic35mmcpath( char * ic35path , int mode) { MMCDIR * mdirp; int mmcnum; char * ptr; char * pdot; char * pslash; /* check/set "MMCard" prefix in ic35fpath */ if ( strncasecmp( ic35path, MMCard, strlen(MMCard) ) != 0 || ! isdigit( ic35path[strlen(MMCard)] ) ) return ERR_mmcpfx; /* error: missing MMCard prefix */ memcpy( ic35path, MMCard, strlen(MMCard) ); /* check MMCard number and slash/backslash after prefix */ ptr = ic35path + strlen(MMCard); if ( *ptr != '1' && *ptr != '2' ) return ERR_mmcnum; /* error: bad MMCard number */ mmcnum = *ptr - '0'; ++ptr; if ( *ptr == 0 ) return mmcnum; /* allow just MMCard */ if ( *ptr == '/' ) *ptr = '\\'; if ( *ptr != '\\' ) return ERR_mmcslash; /* error: miss slash/backslash */ /* check path components for 8+3, too many dots, etc. */ pslash = ptr++; pdot = NULL; do { switch ( *ptr ) { case '/': case '\\': if (mode == 1) { /* create directory if it does not yet exist */ *ptr = 0; if ((mdirp = mmc_opendir(ic35path)) == NULL) mdirp = mmc_createdir(ic35path); mmc_closedir(mdirp); } *ptr = '\\'; /* fall through */ case '\0': if ( ptr - (pslash+1) == 0 ) { if (*ptr == 0) *pslash = 0; /* remove trailing slash */ else return ERR_mmcbadpath; /* error: adjacent slashes */ } if ( (pdot != NULL && ptr - (pdot+1) > 3) || (pdot == NULL && ptr - (pslash+1) > 8) ) return ERR_mmcbadpath; /* error: too long since slash */ pslash = ptr; pdot = NULL; break; case '.': if ( pdot != NULL ) return ERR_mmcbadpath; /* error: too many dots */ if ( ptr - (pslash+1) > 8 ) return ERR_mmcbadpath; /* error: too long before dot */ pdot = ptr; break; } } while ( *ptr++ ); /* convert ic35path '/' to '\\', lowercase to uppercase */ for ( ptr = ic35path+strlen(MMCard); *ptr; ++ptr ) { if ( islower( *ptr ) ) *ptr = (char)toupper( *ptr ); } return mmcnum; } /* output MMCard path error message * -------------------------------- */ static void _mmcpatherror( int errnum, char * ic35path ) { switch ( errnum ) { case ERR_mmcpfx: error( "missing \"%s\" prefix in IC35 filepath: %s", MMCard, ic35path ); break; case ERR_mmcnum: error( "bad MMCard number in IC35 filepath: %s", ic35path ); break; case ERR_mmcslash: error( "missing \\ or / in IC35 filepath: %s", ic35path ); break; case ERR_mmcbadpath: default: error( "bad path component in IC35 filepath: %s", ic35path ); break; } } /* get filename from IC35 MMCard path * ---------------------------------- * derive local filename from base filename in ic35path, i.e. leading * directory components removed, and translate to lowercase. * the buffer for the local filename is strdup()'d and shall be freed * by caller. */ static char * _dupic35fname( char * ic35path, int mode) { char * ptr; char * fname; /* create copy */ if ( (fname = strdup( ic35path )) == NULL ) return NULL; /* convert to unix filename, creating dirs on the way */ ptr = fname; while (*ptr) { if (*ptr == '\\' || *ptr == '/') { if ( mode == 1 ) { /* create subdir */ *ptr = 0; if (mkdir(fname, 0700) < 0 && errno != EEXIST ) { perror(fname); } } *ptr++ = '/'; } else { *ptr++ = tolower( *ptr ); } } return fname; } static void progress( int mode, char* ipath, char *upath, ulong curr, ulong total) { fprintf( stderr, "\r%s %s %s %s %ld", mode? "read": "write", ipath, mode? "->" : "<-", upath, (curr+511)/1024); if (total) fprintf( stderr, "/%ldk, %ld%% ", (total+511)/1024, curr*100/total); else fprintf( stderr, "k "); } /* read file from IC35 MMCard * -------------------------- * the ic35path will be translated to match IC35 requirements: * translate '/' to '\' dir separators and lowercase to upper. * on absent local filename (NULL or empty string) derive it from * base filename in ic35path, i.e. leading directory components * removed, translated to lowercase. * e.g. mmcard1/Ic35\App\Reversi.APP will be translated * to MMCard1\IC35\APP\REVERSI.APP and local file reversi.app * the local file's timestamp will be set to the IC35 file's. * (but IC35 seems to errorneously set the IC35 file's timestamp * to the time of read, although the IC35 file is not modified!?) * */ static int mmcget( char * ic35path, char * a_fname ) { int rbuffsize = 5 * 1024; char * fname; MMCFILE * mmcfp; MMCDIRENT * mmcfstat; FILE * fp; struct utimbuf ftime; uchar * buff; size_t blen; int rlen; ulong frlen; int rval = OK; ulong size; if ( MINBLKSZ <= blocksize && blocksize <= MAXBLKSZ ) rbuffsize = blocksize; else if ( blocksize != 0 ) error( "bad buffer size %d, using default %d", blocksize, rbuffsize ); /* create fname from basename(ic35path) if absent */ if ( a_fname && *a_fname ) { fname = a_fname; } else if ( (fname = _dupic35fname( ic35path, 1 )) == NULL ) { error( "no memory for local filename from %s", ic35path ); return ERR; } if ( (mmcfp = mmc_openfile( ic35path, MMCopenexist )) != NULL ) { if ( (mmcfstat = mmc_statfile( mmcfp )) != NULL ) { size = mmcfstat->size; if ( (buff = malloc( blen = rbuffsize )) != NULL ) { if ( (fp = fopen( fname, "w" )) != NULL ) { rval = OK; frlen = 0; progress( 1, ic35path, fname, frlen, size ); while ( (rlen = mmc_readfile( mmcfp, buff, blen )) > 0 ) { frlen += rlen; progress( 1, ic35path, fname, frlen, size ); if ( fwrite( buff, 1, rlen, fp ) != rlen ) { error( "write error %s: %s (%d)", fname, strerror(errno), errno ); rval = ERR; break; } } fclose( fp ); if ( rlen == 0 && rval == OK ) { ftime.actime = time( NULL ); ftime.modtime = mmctstampunixtime( mmcfstat->tstamp ); utime( fname, &ftime ); /* set file modtime from IC35 */ fprintf( stderr, "\n" ); } else /* mmc_readfile() or fwrite() failed */ rval = ERR; } else /* (fp = fopen()) == NULL */ error( "cannot open %s: %s (%d)", fname, strerror(errno), errno ); free( buff ); } else /* (buff = malloc()) == NULL */ error( "no memory for read buffer (%d)", rbuffsize ); } else /* mmc_statfile() failed */ rval = ERR; mmc_closefile( mmcfp ); } else /* mmc_openfile() failed */ rval = ERR; if ( fname != a_fname ) free( fname ); return rval; } static int ic35mmcget( char * devname, char * ic35path, char * a_fname ) { int mmcnum; int rval; /* check ic35path, check/set "MMCard" prefix and */ /* convert '/' to '\\', lowercase to uppercase */ if ( (mmcnum = _ic35mmcpath( ic35path, 0 )) < 0 ) { _mmcpatherror( mmcnum, ic35path ); return ERR; } /* connect to IC35 in SyncStation via serial device */ if ( (rval = mconnect( devname, NULL )) != OK ) return rval; /* get MMCard status (else other MMCard ops would fail) */ if ( (rval = mmc_status( mmcnum )) <= 0 ) { if ( rval == 0 ) message( "MMCard%d not present", mmcnum ); mdisconnect(); return ERR; } /* read file from IC35 MMCard */ rval = mmcget( ic35path, a_fname); /* cleanup and disconnect from IC35 */ mdisconnect(); return rval; } /* get complete tree from IC35 MMCard(s) * ------------------------------- * dirpath = subdir from which to start * * * */ static int mmcgettree( char * dirpath ) { MMCDIR * dirp; MMCDIRENT * dirent; size_t pfxlen; char * subdir; char * ic35path; int rval, rc; if ( (dirp = mmc_opendir( dirpath )) == NULL ) return ERR; pfxlen = strlen( dirpath ) + 1; rval = OK; while ( (dirent = mmc_readdir( dirp )) != NULL ) { switch ( dirent->attr ) { case MMCattrDirectory: if (strcmp(dirent->name, ".." ) != 0 && (subdir = malloc( pfxlen + strlen(dirent->name) + 1 )) != NULL ) { sprintf(subdir, "%s\\%s", dirpath, dirent->name ); rc = mmcgettree(subdir); if ( rval == OK ) rval = rc; free(subdir); } break; case MMCattrArchive: ic35path = malloc(pfxlen + strlen(dirent->name) + 1 ); sprintf(ic35path, "%s\\%s", dirpath, dirent->name); mmcget(ic35path, NULL); free(ic35path); break; default: } } rc = mmc_closedir( dirp ); if ( rval == OK ) rval = rc; return rval; /* errcode of first failure or success OK */ } static int ic35mmcgettree( char * devname, char * ic35path) { int mmcnum; int rval; char dirpath[7+1]; if (ic35path) { /* check ic35path, check/set "MMCard" prefix and */ /* convert '/' to '\\', lowercase to uppercase */ if ( (mmcnum = _ic35mmcpath( ic35path, 0 )) < 0 ) { _mmcpatherror( mmcnum, ic35path ); return ERR; } if ( (rval = mconnect( devname, NULL )) != OK ) return rval; if ( (rval = mmc_status( mmcnum )) == 0 ) { message( "MMCard%d not present", mmcnum ); rval = ERR; } else if (rval > 0) rval = mmcgettree( ic35path ); } else { if ( (rval = mconnect( devname, NULL )) != OK ) return rval; for ( mmcnum = 1; mmcnum <= 2; ++mmcnum ) { if ( (rval = mmc_status( mmcnum )) < 0 ) break; if ( rval == 0 ) { message( "MMCard%d not present", mmcnum ); continue; } sprintf( dirpath, "MMCard%d", mmcnum ); if ( (rval = mmcgettree( dirpath )) < 0 ) break; } } mdisconnect(); return rval; } /* write file to IC35 MMCard * ------------------------- * see ic35mmcget() comment about ic35path conversions and deriving * fname from it if a_fname is NULL or empty. */ static int mmcput(char * ic35path, char * a_fname ) { int wbuffsize = 2 * 1024; MMCFILE * mmcfp; FILE * fp; uchar * buff; size_t blen; char * fname; int rlen; ulong fwlen; ulong size; int rval = OK; struct stat statbuf; if ( MINBLKSZ <= blocksize && blocksize <= MAXBLKSZ ) wbuffsize = blocksize; else if ( blocksize != 0 ) error( "bad buffer size %d, using default %d", blocksize, wbuffsize ); /* create fname from basename(ic35path) if absent */ if ( a_fname && *a_fname ) { fname = a_fname; } else if ( (fname = _dupic35fname( ic35path, 0 )) == NULL ) { error( "no memory for local filename from %s", ic35path ); return ERR; } /* write file to IC35 MMCard */ if ( (mmcfp = mmc_openfile( ic35path, MMCcreatrunc )) != NULL ) { if ( (buff = malloc( blen = wbuffsize )) != NULL ) { if ( (fp = fopen( fname, "r" )) != NULL ) { rval = OK; fwlen = 0; stat(fname, &statbuf); size = statbuf.st_size; progress( 0, ic35path, fname, fwlen, size ); while ( (rlen = fread( buff, 1, blen, fp )) > 0 ) { if ( mmc_writefile( mmcfp, buff, rlen ) != rlen ) { rval = ERR; break; } fwlen += rlen; progress( 0, ic35path, fname, fwlen, size ); } if ( rlen <= 0 && feof( fp ) && rval == OK ) { fprintf( stderr, "\n" ); } else { /* fread() or mmc_writefile() failed */ if ( rval != ERR ) error( "read error %s: %s (%d)", fname, strerror(errno), errno ); rval = ERR; } fclose( fp ); } else /* (fp = fopen()) == NULL */ error( "cannot open %s: %s (%d)", fname, strerror(errno), errno ); free( buff ); } else /* (buff = malloc()) == NULL */ error( "no memory for write buffer (%d)", wbuffsize ); mmc_closefile( mmcfp ); } else /* mmc_openfile() failed */ rval = ERR; if ( fname != a_fname ) free( fname ); return rval; } static int ic35mmcput( char * devname, char * ic35path, char * a_fname ) { int mmcnum; int rval; /* check ic35path, check/set "MMCard" prefix and */ /* convert '/' to '\\', lowercase to uppercase */ if ( (mmcnum = _ic35mmcpath( ic35path, 0 )) < 0 ) { _mmcpatherror( mmcnum, ic35path ); return ERR; } /* connect to IC35 in SyncStation via serial device */ if ( (rval = mconnect( devname, NULL )) != OK ) return rval; /* get MMCard status (else other MMCard ops would fail) */ if ( (rval = mmc_status( mmcnum )) <= 0 ) { if ( rval == 0 ) message( "MMCard%d not present", mmcnum ); mdisconnect(); return ERR; } rval = mmcput(ic35path, a_fname ); /* cleanup and disconnect from IC35 */ mdisconnect(); return rval; } /* put complete tree to IC35 MMCard(s) * ------------------------------- * dirpath = subdir from which to start * * * */ static int mmcputtree( char * dirpath ) { DIR * dirp; struct dirent * dirent; size_t pfxlen; char * path; int rval, rc; int mmcnum; struct stat statbuf; if ( (dirp = opendir( dirpath )) == NULL ) return ERR; pfxlen = strlen( dirpath ) + 1; rval = OK; while ( (dirent = readdir( dirp )) != NULL ) { if (strcmp(dirent->d_name, ".." ) == 0) continue; if (strcmp(dirent->d_name, "." ) == 0) continue; path = malloc(pfxlen + strlen(dirent->d_name) + 1 ); if (path == NULL) { rval = ERR; break; } sprintf(path, "%s/%s", dirpath, dirent->d_name); if (stat(path, &statbuf) == -1) { rval = ERR; break; } if (S_ISDIR(statbuf.st_mode)) { rval = mmcputtree(path); } else if (S_ISREG(statbuf.st_mode)) { /* convert to IC35 name */ if ( (mmcnum = _ic35mmcpath( path, 1)) < 0 ) { _mmcpatherror( mmcnum, path ); return ERR; } mmcput(path, NULL); } free(path); } rc = closedir( dirp ); if ( rval == OK ) rval = rc; return rval; /* errcode of first failure or success OK */ } static int ic35mmcputtree( char * devname, char * ic35path) { int mmcnum; int rval; char * tmp; /* check ic35path, check/set "MMCard" prefix and */ /* convert '/' to '\\', lowercase to uppercase */ tmp = strdup(ic35path); mmcnum = _ic35mmcpath( tmp, 0 ); free(tmp); if ( mmcnum < 0 ) { _mmcpatherror( mmcnum, tmp ); return ERR; } if ( (rval = mconnect( devname, NULL )) != OK ) return rval; if ( (rval = mmc_status( mmcnum )) == 0 ) { message( "MMCard%d not present", mmcnum ); rval = ERR; } else if (rval > 0) rval = mmcputtree( ic35path ); mdisconnect(); return rval; } /* delete file on IC35 MMCard * ------------------------- */ static int ic35mmcdel( char * devname, char * ic35path ) { int mmcnum; int rval; /* check ic35path, check/set "MMCard" prefix and */ /* convert '/' to '\\', lowercase to uppercase */ if ( (mmcnum = _ic35mmcpath( ic35path, 0 )) < 0 ) { _mmcpatherror( mmcnum, ic35path ); return ERR; } /* connect to IC35 in SyncStation via serial device */ if ( (rval = mconnect( devname, NULL )) != OK ) return rval; /* get MMCard status (else delete MMCard file fails) */ if ( (rval = mmc_status( mmcnum )) > 0 ) { message( "delete %s", ic35path ); rval = mmc_delfile( ic35path ); /* delete IC35 MMCard file */ } else if ( rval == 0 ) { message( "MMCard%d not present", mmcnum ); rval = ERR; } /* disconnect from IC35 */ mdisconnect(); return rval; } /* -------------------- M A I N - program ----------------------------- */ static void versinfo( void ) { printf( "IC35manager for GNU/Linux %s (%s)\n", pkgvers, pkgdate ); printf( "%s\n", bldinfo ); printf( "Copyright (C) 2001 Thomas Schulz\n" "This is free software; see the GNU General Public Licence version 2 in\n" "the file named COPYING for copying conditions. There is NO warranty.\n" ); } static void usage( void ) { static char * usetext[] = { "usage: ic35mgr [option..] command [argument..]", "commands and arguments are:", " status [FILE] report IC35 status (and write to FILE)", " backup FILE backup IC35 database to FILE", " restore FILE restore IC35 database from FILE", " mmcdir list contents of IC35 MMCard(s)", " mmcdel IC35PATH delete MMCard file IC35PATH", " mmcget IC35PATH [FILE] read FILE from IC35PATH on IC35 MMCard", " mmcgettree [IC35PATH] read file tree starting at IC35PATH on IC35 MMCard", " mmcput IC35PATH [FILE] write FILE to IC35PATH on IC35 MMCard", " mmcputtree IC35PATH write file tree starting at IC35PATH to IC35 MMCard", " IC35PATH e.g. MMCard1/ic35/app/reversi.app will be", " converted to MMCard1\\IC35\\APP\\REVERSI.APP on IC35", " filename FILE is taken from IC35PATH if absent", "options in short and long form are:", " -d DEV --device=DEV serial device with IC35 connected, default /dev/ic35", " -b SIZE --blocksize=SIZE block size for mmcget / mmcput, default 5120 / 2048", " -n NINC --nice=NINC lower process priority for restore,mmcput, default 2", #ifndef NO_LOGSIM " -l FILE --logfile=FILE log communications to FILE, default no logging", " -s FILE --simfile=FILE simulate communication with IC35 using FILE", " (create simulation FILE from logfile with 'ic35log')", #endif " -V --version show version information and exit", " -h --help show this help and exit", NULL }; char ** lptr; for ( lptr = usetext; *lptr != NULL; ++lptr ) printf( "%s\n", *lptr ); } int main( int argc, char *argv[] ) { static struct option const long_opts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { "device", required_argument, NULL, 'd' }, { "blocksize", required_argument, NULL, 'b' }, { "nice", required_argument, NULL, 'n' }, #ifndef NO_LOGSIM { "logfile", required_argument, NULL, 'l' }, { "simfile", required_argument, NULL, 's' }, #endif { NULL, 0, NULL, 0 } }; char * devname = "/dev/ic35"; char * nicearg = "2"; char * command = NULL; #ifndef NO_LOGSIM char * logfname = NULL; char * simfname = NULL; #endif int rval; /* * parse command line */ for ( ; ; ) { switch ( getopt_long( argc, argv, #ifndef NO_LOGSIM "l:s:" #endif "d:b:hV", long_opts, NULL ) ) { default: /* invalid option */ fprintf( stderr, "use 'ic35mgr --help' for more information\n" ); return 1; case 'h': /* show Help and exit */ usage(); return 0; case 'V': /* show Version and exit */ versinfo(); return 0; case 'd': /* serial Device where IC35 */ devname = optarg; continue; case 'b': /* buffer size for mmcget,put */ blocksize = atoi( optarg ); continue; case 'n': /* nice processs priority */ nicearg = optarg; continue; #ifndef NO_LOGSIM case 'l': /* communication logfile */ logfname = optarg; continue; case 's': /* simulate: no communication */ simfname = optarg; continue; #endif /*NO_LOGSIM*/ case -1: /* end of options */ break; } break; } if ( argc < optind+1 ) { fatal( "missing command\n" "use 'ic35mgr --help' for more information" ); return 1; } if ( atoi( nicearg ) == 0 && !isdigit(*nicearg) ) { fatal( "non-integer nice argument: %s", nicearg ); return 1; } com_waitnice( atoi( nicearg ) ); /* * initial info to logfile: date,time, version, command line * if 'logfname' is NULL or empty, nothing will be logged. */ LOG_INIT(( logfname, "ic35mgr", 0 )); LOG_PROGINFO(( "ic35mgr", pkgvers, pkgdate, bldinfo )); LOG_ARGSINFO(( argc, argv )); /* * setup simulated communication if requested */ COM_SIMINIT(( simfname )); /* * process command */ command = argv[optind]; /* note command */ argv += optind, argc -= optind; /* skip options */ rval = 1; if ( strcmp( command, "status" ) == 0 ) { if ( argc <= 2 ) rval = ic35mgrstat( devname, argc > 1 ? argv[1] /*???*/ : "/tmp/ic35.stat" ); else error( "too many arguments" ); } else if ( strcmp( command, "backup" ) == 0 ) { if ( argc == 2 ) rval = ic35backup( devname, argv[1] ); else error( argc < 2 ? "missing backup file" : "too many arguments" ); } else if ( strcmp( command, "restore" ) == 0 ) { if ( argc == 2 ) rval = ic35restore( devname, argv[1] ); else error( argc < 2 ? "missing restore file" : "too many arguments" ); } else if ( strcmp( command, "mmcdir" ) == 0 ) { if ( argc == 1 ) rval = ic35mmcdir( devname ) == OK ? 0 : 1; else error( "too many arguments" ); } else if ( strcmp( command, "mmcdel" ) == 0 ) { if ( argc == 2 ) rval = ic35mmcdel( devname, argv[1] ) == OK ? 0 : 1; else error( argc < 2 ? "missing ic35path" : "too many arguments" ); } else if ( strcmp( command, "mmcget" ) == 0 ) { if ( argc == 2 || argc == 3 ) rval = ic35mmcget( devname, argv[1], argc == 3 ? argv[2] : NULL ); else error( argc < 2 ? "missing ic35path" : "too many arguments" ); } else if ( strcmp( command, "mmcgettree" ) == 0 ) { if ( argc == 1 || argc == 2 ) rval = ic35mmcgettree( devname, argc == 2 ? argv[1] : NULL ); else error( "too many arguments" ); } else if ( strcmp( command, "mmcput" ) == 0 ) { if ( argc == 2 || argc == 3 ) rval = ic35mmcput( devname, argv[1], argc == 3 ? argv[2] : NULL ); else error( argc < 2 ? "missing ic35path,file" : "too many arguments" ); } else if ( strcmp( command, "mmcputtree" ) == 0 ) { if ( argc == 2 ) rval = ic35mmcputtree( devname, argv[1]); else error( argc < 2 ? "missing ic35path,file" : "too many arguments" ); } else { error( "unsupported command: %s", command ); rval = 1; } if ( rval != OK ) rval = 1; LOG_CLOSE(()); return rval; }