Go to the documentation of this file.00001
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <unistd.h>
00049 #include <string.h>
00050 #include <signal.h>
00051 #include <poll.h>
00052
00053 #include <vector>
00054
00055 #include "port.h"
00056
00057 using namespace std;
00058
00059
00060 vector<Port*> service_ports;
00061 vector<Port*> client_ports;
00062 vector<struct pollfd> pollfds;
00063
00064
00065 void handle_term(int signum) {
00066 vector<Port*>::iterator iter;
00067 for(iter = service_ports.begin(); iter != service_ports.end(); ++iter) {
00068 delete *iter;
00069 }
00070 for(iter = client_ports.begin(); iter != client_ports.end(); ++iter) {
00071 delete *iter;
00072 }
00073
00074 fflush(stderr);
00075 fflush(stdout);
00076
00077
00078
00079
00080 if( signum == SIGABRT ) {
00081 signal(SIGABRT, SIG_DFL);
00082 abort();
00083 }
00084
00085 printf("\nExiting virtual-serial\n");
00086 exit(0);
00087 }
00088
00089
00090 void print_help(const char* executable_name) {
00091 printf("Usage: \n"
00092 "1: %s [service] [client] [options]\n"
00093 "2: %s --service [ports] --client [ports] [options]\n"
00094 "\n"
00095 "1: Creates a pair of terminals and pipes them to each other\n"
00096 "[service] and [client] are port specification strings.\n"
00097 "\n"
00098 "2: Similar to 1, but it is possible to have multiple ports at either end\n"
00099 "of the connection. [ports] is a list of port specification strings.\n"
00100 "\n"
00101 "Port specification: \n"
00102 "serial:devname,baudrate - Use a real serial port\n"
00103 "pty:path - Create a pty, with symlink at given path\n"
00104 "path - Equivalent to pty:path\n"
00105 "\n"
00106 "With multiple ports, a char received on a given service port will be\n"
00107 "transmitted to all client ports, but not to other service ports. The\n"
00108 "converse holds for chars received on client ports.\n"
00109 "\n"
00110 "Options:\n"
00111 "--service [ports] Specify additional service ports. Each of [ports]\n"
00112 " is a port specification string. If this option is\n"
00113 " specified multiple times, port lists will be added\n"
00114 "--client [ports] Same as --service, but for client ports.\n"
00115 ,
00116 executable_name, executable_name);
00117 }
00118
00119
00120 void pass_data(vector<Port*>& from_ports, vector<Port*>& to_ports) {
00121 vector<Port*>::iterator from_iter, to_iter;
00122 for( from_iter = from_ports.begin(); from_iter < from_ports.end(); ++from_iter)
00123 {
00124 if ((*from_iter)->poll_revents() == POLLIN) {
00125 char buff[1024];
00126 int count = (*from_iter)->read(buff, sizeof(buff));
00127 for( to_iter = to_ports.begin();
00128 to_iter < to_ports.end(); ++to_iter )
00129 {
00130 (*to_iter)->write(buff, count);
00131 }
00132 }
00133 }
00134 }
00135
00136
00137 void update_blocking()
00138 {
00139 poll(&pollfds[0], pollfds.size(), 1000);
00140 pass_data(service_ports, client_ports);
00141 pass_data(client_ports, service_ports);
00142 }
00143
00144
00145 int main(int argc, char *argv[]) {
00146
00147
00148
00149
00150
00151 setvbuf(stdout, 0, _IOLBF, 64);
00152
00153 if( argc < 3 ) {
00154 print_help(argv[0]);
00155 return 1;
00156 }
00157
00158
00159 vector<const char*> service_strs;
00160 vector<const char*> client_strs;
00161
00162
00163
00164 int cur_arg = 1;
00165
00166
00167
00168 if( strncmp(argv[1], "--", 2) ) {
00169 service_strs.push_back(argv[1]);
00170 client_strs.push_back(argv[2]);
00171 cur_arg = 3;
00172 }
00173
00174
00175 for(; cur_arg<argc; ++cur_arg) {
00176 if( !strcmp(argv[cur_arg], "--service") ) {
00177
00178 while( (cur_arg+1 < argc) && strncmp(argv[cur_arg+1],"--",2) ) {
00179 ++cur_arg;
00180 if (argv[cur_arg][0] != '_') {
00181 service_strs.push_back(argv[cur_arg]);
00182 }
00183 }
00184 } else if( !strcmp(argv[cur_arg], "--client") ) {
00185
00186 while( (cur_arg+1 < argc) && strncmp(argv[cur_arg+1],"--",2) ) {
00187 ++cur_arg;
00188 if (argv[cur_arg][0] != '_') {
00189 client_strs.push_back(argv[cur_arg]);
00190 }
00191 }
00192 } else {
00193 fprintf(stderr,"Unrecognized option: %s\n", argv[cur_arg]);
00194 exit(1);
00195 }
00196 }
00197
00198
00199 if( service_strs.empty() ) {
00200 fprintf(stderr, "At least one service port must be specified!\n");
00201 exit(1);
00202 }
00203 if( client_strs.empty() ) {
00204 fprintf(stderr, "At least one client port must be specified!\n");
00205 exit(1);
00206 }
00207
00208
00209
00210
00211
00212 signal(SIGINT, handle_term);
00213 signal(SIGTERM, handle_term);
00214 signal(SIGABRT, handle_term);
00215
00216
00217 {
00218 pollfds.resize(service_strs.size() + client_strs.size());
00219 vector<struct pollfd>::iterator pollfd_iter = pollfds.begin();
00220 vector<const char*>::iterator str_iter;
00221
00222 for(str_iter = service_strs.begin(); str_iter != service_strs.end(); ++str_iter, ++pollfd_iter) {
00223 service_ports.push_back(Port::create(*str_iter, &*pollfd_iter));
00224 }
00225 for(str_iter = client_strs.begin(); str_iter != client_strs.end(); ++str_iter, ++pollfd_iter) {
00226 client_ports.push_back(Port::create(*str_iter, &*pollfd_iter));
00227 }
00228 }
00229
00230 while(1) {
00231 update_blocking();
00232 }
00233 }
00234