/*********************************************************************** * Factory routine -- connect to server and create remote device **********************************************************************/ static SoapySDR::Device *makeRemote(const SoapySDR::Kwargs &args) { if (args.count(SOAPY_REMOTE_KWARG_STOP) != 0) //probably wont happen { throw std::runtime_error("SoapyRemoteDevice() -- factory loop"); } if (args.count("remote") == 0) { throw std::runtime_error("SoapyRemoteDevice() -- missing URL"); } auto url = SoapyURL(args.at("remote")); //default url parameters when not specified if (url.getScheme().empty()) url.setScheme("tcp"); if (url.getService().empty()) url.setService(SOAPY_REMOTE_DEFAULT_SERVICE); return new SoapyRemoteDevice(url.toString(), translateArgs(args)); }
/*********************************************************************** * Discovery routine -- connect to server when key specified **********************************************************************/ static std::vector<SoapySDR::Kwargs> findRemote(const SoapySDR::Kwargs &args) { std::vector<SoapySDR::Kwargs> result; if (args.count(SOAPY_REMOTE_KWARG_STOP) != 0) return result; //no remote specified, use the discovery protocol if (args.count("remote") == 0) { //On non-windows platforms the endpoint instance can last the //duration of the process because it can be cleaned up safely. //Windows has issues cleaning up threads and sockets on exit. #ifndef _MSC_VER static #endif //_MSC_VER auto ssdpEndpoint = SoapySSDPEndpoint::getInstance(); //enable forces new search queries ssdpEndpoint->enablePeriodicSearch(true); //wait maximum timeout for replies std::this_thread::sleep_for(std::chrono::microseconds(SOAPY_REMOTE_SOCKET_TIMEOUT_US)); for (const auto &url : SoapySSDPEndpoint::getInstance()->getServerURLs()) { auto argsWithURL = args; argsWithURL["remote"] = url; const auto subResult = findRemote(argsWithURL); result.insert(result.end(), subResult.begin(), subResult.end()); } return result; } //otherwise connect to a specific url and enumerate auto url = SoapyURL(args.at("remote")); //default url parameters when not specified if (url.getScheme().empty()) url.setScheme("tcp"); if (url.getService().empty()) url.setService(SOAPY_REMOTE_DEFAULT_SERVICE); //try to connect to the remote server SoapySocketSession sess; SoapyRPCSocket s; int ret = s.connect(url.toString()); if (ret != 0) { SoapySDR::logf(SOAPY_SDR_ERROR, "SoapyRemote::find() -- connect(%s) FAIL: %s", url.toString().c_str(), s.lastErrorMsg()); return result; } //find transaction try { SoapyLogAcceptor logAcceptor(url.toString(), s); SoapyRPCPacker packer(s); packer & SOAPY_REMOTE_FIND; packer & translateArgs(args); packer(); SoapyRPCUnpacker unpacker(s); unpacker & result; //graceful disconnect SoapyRPCPacker packerHangup(s); packerHangup & SOAPY_REMOTE_HANGUP; packerHangup(); SoapyRPCUnpacker unpackerHangup(s); } catch (const std::exception &ex) { SoapySDR::logf(SOAPY_SDR_ERROR, "SoapyRemote::find() -- transact FAIL: %s", ex.what()); } //remove instances of the stop key from the result for (auto &resultArgs : result) { resultArgs.erase(SOAPY_REMOTE_KWARG_STOP); if (resultArgs.count("driver") != 0) { resultArgs["remote:driver"] = resultArgs.at("driver"); resultArgs.erase("driver"); } if (resultArgs.count("type") != 0) { resultArgs["remote:type"] = resultArgs.at("type"); resultArgs.erase("type"); } resultArgs["remote"] = url.toString(); } return result; }
/** * @function executeCommand * * @abstract Execute the command, using the given pipe as stdin. * @discussion Loads input / output files, create pipes, and forks off children * to execute the task. * * @param command - a struct representing the command * pipe - one end of a pipe to be used as stdin, or NULL if there is none * * @result Returns nothing. */ void executeCommand(Command* command, int inPipe) { if (strcmp(command->args->arg, "exit") == 0) { printf("Exiting\n"); exit(0); } else if (strcmp(command->args->arg, "cd") == 0 || strcmp(command->args->arg, "chdir") == 0) { // Change directories char* path; if (command->args->nextArg == NULL) { char buff[PATH_MAX]; char* username = getpwuid(getuid())->pw_name; sprintf(buff, "/home/%s", username); path = buff; } else { path = command->args->nextArg->arg; } if (chdir(path) == -1) { printf("%s\n", strerror(errno)); } return; } else if (strcmp(command->args->arg, "history") == 0) { // Print history or error as to why that cannot be done. print_sh_history(command); return; } else if (command->args->arg[0] == '!') { // If !n is argued, rerun the n-th line in history. rerun_cmd_n(command); return; } // Create a pipe if there is a next command int pipefd[2] = {-1, -1}; if (command->pipe_destination != NULL) { if (pipe(pipefd) == -1) { printf("%s\n", strerror(errno)); } } pid_t pid = fork(); if (pid < 0) { printf("Fork failed!\n"); exit(1); } else if (pid == 0) { char** args = translateArgs(command->args); // Load the input and output // Use the pipe if it exists // (output and input take precedence over pipe) int in_fd, out_fd; if (inPipe > -1) { dup2(inPipe, STDIN_FILENO); close(inPipe); } else if (command->input != NULL) { in_fd = open(command->input, O_RDONLY); if (in_fd == -1) { printf("Failed to open input file \n"); return; } dup2(in_fd, STDIN_FILENO); /* Replace stdin */ close(in_fd); } if (pipefd[1] > -1) { dup2(pipefd[1], STDOUT_FILENO); close(pipefd[1]); } else if (command->output != NULL) { out_fd = open(command->output, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IRGRP | S_IROTH); if (out_fd == -1) { printf("Failed to open output file \n"); return; } dup2(out_fd, STDOUT_FILENO); /* Replace stdout */ close(out_fd); } if (execvp(args[0], args) == -1) { printf("Could not execute %s!\n", args[0]); exit(1); } } else { // Recurse on the next command if there is one, pass along the pipe if (inPipe > -1) { close(inPipe); } if (pipefd[1] > -1) { close(pipefd[1]); } if (command->pipe_destination != NULL) { executeCommand(command->pipe_destination, pipefd[0]); } } }