diff --git a/src/common/remoteio.c b/src/common/remoteio.c --- a/src/common/remoteio.c +++ b/src/common/remoteio.c @@ -27,12 +27,32 @@ #include /* local */ + +int _remoteio_ssh_open(struct remoteio *rem, struct remoteio_server *server); +int _remoteio_ssh_read(struct remoteio *rem, void *buf, size_t len, size_t *bytesread); +int _remoteio_ssh_write(struct remoteio *rem, void *buf, size_t len, size_t *bytesread); +int _remoteio_ssh_close(struct remoteio *rem); + +/** + lookup table for different methods of remoteio: + the enum remoteio_method is the index of the entry to use for that method. + Regardless, a NULL terminator is required because the configuration function + searches through this table for the method specified in the config file. +*/ +struct remoteio_method_funcmap funcmap[] = + { + /* [REMOTEIO_METHOD_SSH] */ + {&_remoteio_ssh_open, &_remoteio_ssh_read, &_remoteio_ssh_write, &_remoteio_ssh_close, "ssh"}, + {NULL, NULL, NULL, NULL, NULL} + }; + struct remoteio_server *remoteio_getserver(const struct remoteio_opts *opts, const char *servername); int remoteio_config(cfg_t *cfg, struct remoteio_opts *opts) { size_t numservers; size_t counter; + static int haslisted_methods = 0; struct remoteio_server *aserver; @@ -49,6 +69,7 @@ int remoteio_config(cfg_t *cfg, struct r for(counter = 0; counter < numservers; counter ++) { cfg_t *cfg_aserver; + char *method; cfg_aserver = cfg_getnsec(cfg, "server", counter); @@ -58,10 +79,25 @@ int remoteio_config(cfg_t *cfg, struct r aserver->name = strdup(cfg_title(cfg_aserver)); aserver->hostname = strdup(cfg_getstr(cfg_aserver, "hostname")); aserver->username = strdup(cfg_getstr(cfg_aserver, "username")); - if(strcmp(cfg_getstr(cfg_aserver, "method"), "ssh") == 0) - aserver->method = REMOTEIO_METHOD_SSH; - else - abort(); + + aserver->method = REMOTEIO_METHOD_MAX; + method = cfg_getstr(cfg_aserver, "method"); + for(counter = 0; funcmap[counter].name; counter ++) + if(strcmp(method, funcmap[counter].name) == 0) + aserver->method = REMOTEIO_METHOD_SSH; + if(aserver->method == REMOTEIO_METHOD_MAX) + { + fprintf(stderr, "No such method as %s\n", method); + if(!haslisted_methods) + { + fprintf(stderr, "Available methods:\n"); + for(counter = 0; funcmap[counter].name; counter ++) + fprintf(stderr, "\t%s\n", funcmap[counter].name); + + haslisted_methods ++; + } + abort(); + } if(counter < numservers - 1) { @@ -76,14 +112,18 @@ int remoteio_config(cfg_t *cfg, struct r -int remoteio_open(struct remoteio **rem, struct remoteio_opts *opts, const char *servername) +int remoteio_open(struct remoteio **remoteio, struct remoteio_opts *opts, const char *servername) { - char *userhost; - char *sshargs[] = {opts->ssh_command, NULL /* userhost */, "distrend", "-d", (char *)NULL}; - - int rtn; - struct remoteio_server *theserver; + struct remoteio *rem; + + int tmp; + + if(!opts) + { + fprintf(stderr, "%s:%d: no null opts!\n\tThis is a bug, please report it (after making sure it isn't already reported)\n", __FILE__, __LINE__); + return 1; + } theserver = remoteio_getserver(opts, servername); if(!theserver) @@ -92,28 +132,31 @@ int remoteio_open(struct remoteio **rem, return 1; } - if(theserver->method != REMOTEIO_METHOD_SSH) + if(theserver->method >= REMOTEIO_METHOD_MAX + || theserver->method < 0) { - fprintf(stderr, "%s:%d: Unsupported remoteio method %d\n", __FILE__, __LINE__, theserver->method); + fprintf(stderr, "%s:%d: Unsupported remoteio method %d\n\tThis is a bug, probably indicating memory corruption. This is, of course, probably my fault (not your hardware's) ;-)\n", __FILE__, __LINE__, theserver->method); return 1; } - - if(theserver->username) - _distren_asprintf(&userhost, "%s@%s", theserver->username, theserver->hostname); - else - userhost = strdup(theserver->hostname); - sshargs[1] = userhost; + rem = malloc(sizeof(struct remoteio)); + if(!rem) + { + fprintf(stderr, "OOM\n"); + return 2; + } + *remoteio = rem; - *rem = malloc(sizeof(struct remoteio)); - rtn = execio_open( &(*rem)->execio, "ssh", sshargs); - if(rtn) + rem->method = theserver->method; + rem->opts = opts; + + tmp = funcmap[theserver->method].open_func(rem, theserver); + if(tmp) { - fprintf(stderr, "error opening remoteio channel to server ``%s''" , servername); - free(*rem); - free(userhost); - return 1; + fprintf(stderr, "Error using method %s for server ``%s''", funcmap[theserver->method].name, servername); + free(rem); + *remoteio = NULL; + return tmp; } - free(userhost); return 0; } @@ -153,3 +196,43 @@ struct remoteio_server *remoteio_getserv return (struct remoteio_server *)NULL; } + + + + +/** + different remoteio methods' implementations: + */ + +/* + SSH, via execio +*/ + +int _remoteio_ssh_open(struct remoteio *rem, struct remoteio_server *server) +{ + char *userhost; + char *sshargs[] = {rem->opts->ssh_command, NULL /* userhost */, "distrend", "-d", (char *)NULL}; + + int rtn; + + if(server->username) + _distren_asprintf(&userhost, "%s@%s", server->username, server->hostname); + else + userhost = strdup(server->hostname); + sshargs[1] = userhost; + + rtn = execio_open( &rem->execio, "ssh", sshargs); + if(rtn) + { + fprintf(stderr, "error opening remoteio channel to ssh userhost ``%s''\n" , userhost); + free(userhost); + return 1; + } + free(userhost); + + return 0; +} + +int _remoteio_ssh_read(struct remoteio *rem, void *buf, size_t len, size_t *bytesread); +int _remoteio_ssh_write(struct remoteio *rem, void *buf, size_t len, size_t *bytesread); +int _remoteio_ssh_close(struct remoteio *rem);