- Fix: avoid infinite loop on mulitcast read thread if no data to read
Pre-ci test passed git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4000 818b1a75-f10b-46b9-bf7c-635c3b92a50f
@@ -0,0 +1,8 @@
|
||||
File: Readme.txt
|
||||
Author: Florian Kaltenberger
|
||||
Date: 11.2.09
|
||||
|
||||
This directory contains configuration files and maps for gpsdrive. gpsdrive displays your position and position of others (which are connected to the friends server) on a map. see man gpsdrive and man friendsd2 for details.
|
||||
|
||||
Copy the maps directory to your ~/.gpsdrive directory or merge it with the existing directory iff you have already created other maps.
|
||||
|
||||
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 117 KiB |
@@ -0,0 +1,29 @@
|
||||
top_Africa.jpg 1.82500 26.57917 24167707
|
||||
top_Americas.jpg 4.25000 -91.50000 38529708
|
||||
top_AsiaMiddleEast.jpg 34.33333 54.87500 17638272
|
||||
top_AsiaEast.jpg 32.78333 139.37500 24646780
|
||||
top_Australia.jpg -26.96667 134.12500 10990784
|
||||
top_BritishIsles.jpg 54.54167 -4.20833 3135892
|
||||
top_Europe.jpg 52.91667 12.41667 11823932
|
||||
top_Germany.jpg 51.50833 11.05000 3909032
|
||||
top_GPSWORLD.jpg 0.00000 0.00000 88067900
|
||||
top_JapanKorea.jpg 38.45833 135.15833 5379458
|
||||
top_NewZealand.jpg -40.85000 172.50000 4240306
|
||||
top_NorthAmerica.jpg 39.96667 -95.52500 20982408
|
||||
top_SouthAmerica.jpg -21.58333 -63.14583 21456356
|
||||
top_WorldEast.jpg 12.40000 68.00000 43055416
|
||||
expedia/map_98750_41.516_2.088.gif 41.51642 2.08774 98750
|
||||
expedia/map_3950_41.516_2.087.gif 41.51642 2.08732 3950
|
||||
expedia/map_47400_41.282_1.989.gif 41.28168 1.98933 47400
|
||||
expedia/map_3950_41.282_1.989.gif 41.28160 1.98929 3950
|
||||
expedia/map_98750_41.516_2.088.gif 41.51600 2.08802 98750
|
||||
expedia/map_98750_41.516_2.088.gif 41.51597 2.08801 98750
|
||||
expedia/map_3950_41.502_2.113.gif 41.50223 2.11301 3950
|
||||
expedia/map_3950_41.501_2.111.gif 41.50111 2.11116 3950
|
||||
expedia/map_3950_43.735_7.421.gif 43.73466 7.42114 3950
|
||||
expedia/map_3950_43.883_7.355.gif 43.88309 7.35546 3950
|
||||
expedia/map_27650000_43.847_7.448.gif 43.84667 7.44823 27650000
|
||||
expedia/map_3950_43.912_7.516.gif 43.91186 7.51550 3950
|
||||
expedia/map_3950_43.923_7.527.gif 43.92305 7.52726 3950
|
||||
expedia/map_3950_43.735_7.421.gif 43.73466 7.42114 3950
|
||||
expedia/map_3950_43.735_7.421.gif 43.73466 7.42114 3950
|
||||
@@ -0,0 +1,8 @@
|
||||
all: remserial
|
||||
|
||||
REMOBJ=remserial.o stty.o
|
||||
remserial: $(REMOBJ)
|
||||
$(CC) $(LDFLAGS) -o remserial $(REMOBJ)
|
||||
|
||||
clean:
|
||||
rm -f remserial *.o
|
||||
@@ -0,0 +1,150 @@
|
||||
Remserial
|
||||
---------
|
||||
|
||||
The remserial program acts as a communications bridge between a TCP/IP
|
||||
network port and a Linux device such as a serial port. Any character-oriented
|
||||
Linux /dev device will work.
|
||||
|
||||
The program can also use pseudo-ttys as the device. A pseudo-tty is like
|
||||
a serial port in that it has a /dev entry that can be opened by a program
|
||||
that expects a serial port device, except that instead of belonging to
|
||||
a physical serial device, the data can be intercepted by another program.
|
||||
The remserial program uses this to connect a network port to the
|
||||
"master" (programming) side of the pseudo-tty allowing the device driver
|
||||
(slave) side to be used by some program expecting a serial port. See example
|
||||
3 below for details.
|
||||
|
||||
The program can operate as a server accepting network connections from
|
||||
other machines, or as a client, connecting to remote machine that
|
||||
is running the remserial program or some other program that accepts
|
||||
a raw network connection. The network connection passes data as-is,
|
||||
there is no control protocol over the network socket.
|
||||
|
||||
Multiple copies of the program can run on the same computer at the same
|
||||
time assuming each is using a different network port and device.
|
||||
|
||||
Some examples:
|
||||
|
||||
1) Give access to a RS232 device over a network.
|
||||
|
||||
The computer with the serial port connected to the device (such as a
|
||||
data aquisition device) runs the remserial program:
|
||||
|
||||
remserial -d -p 23000 -s "9600 raw" /dev/ttyS0 &
|
||||
|
||||
This starts the program in daemon mode so that it runs in the background,
|
||||
it waits for connections on port 23000 and sets up the serial port
|
||||
/dev/ttyS0 at 9600 baud. Network connections to port 23000 from any
|
||||
machine can then read and write to the device attached to the serial port.
|
||||
|
||||
This can be started from /etc/rc.local or as an entry in /etc/inittab
|
||||
or set up as a system service with a file in /etc/rc.init/.
|
||||
|
||||
2) Connect an RS232 device to a specified server.
|
||||
|
||||
The computer with the serial port connected to the device (such as a
|
||||
data aquisition device) runs the remserial program:
|
||||
|
||||
remserial -d -r server-name -p 23000 -s "9600 raw" /dev/ttyS0 &
|
||||
|
||||
This would be used with case number 1 above creating an end-to-end serial
|
||||
port connection. What goes in the serial port on one machine would come
|
||||
out the serial port of the other machine. The ports could be running at
|
||||
different baud rates or other serial port settings.
|
||||
|
||||
3) Connect a Linux program that needs a serial port to a remote serial port.
|
||||
|
||||
Some programs are written to communicate directly with a serial port such
|
||||
as some data aquisition programs. The remserial program can use
|
||||
pseudo-ttys to fool the program into thinking that it is talking to a
|
||||
real serial port on the local machine:
|
||||
|
||||
remserial -d -r server-name -p 23000 -l /dev/remserial1 /dev/ptmx &
|
||||
|
||||
This creates a file called /dev/remserial1 which can be used by the
|
||||
data aquisition application as its serial port. Any data sent or received
|
||||
is passed to the remote server-name on port 23000 where a computer configured
|
||||
in case number 1 above passes it to a real serial port.
|
||||
|
||||
The remserial program uses the special pseudo-tty master device /dev/ptmx
|
||||
(see man ptmx) which creates a slave device that looks like a normal
|
||||
serial port named /dev/pts/something. Unfortunately, the actual device
|
||||
name created isn't consistent, so the remserial program creates a symbol
|
||||
link from the device name specified with the -l option to the /dev/pts/
|
||||
name that was created allowing the other application to be configured
|
||||
with a consistent device name.
|
||||
|
||||
4) Server farm console control.
|
||||
|
||||
Assuming multiple Linux servers (such as web servers) are set up to have a
|
||||
serial port as their console instead of a monitor/keyboard, their serial
|
||||
ports could be connected to a control server using a multi-port serial board.
|
||||
On the control server, a copy of remserial is run for each server:
|
||||
|
||||
remserial -d -p 23000 -s "115200 raw" /dev/ttyS0 &
|
||||
remserial -d -p 23001 -s "115200 raw" /dev/ttyS1 &
|
||||
remserial -d -p 23002 -s "115200 raw" /dev/ttyS2 &
|
||||
remserial -d -p 23003 -s "115200 raw" /dev/ttyS3 &
|
||||
etc.
|
||||
|
||||
From any computer on the local network, use a telnet program to connect
|
||||
to the control server on the appropriate port:
|
||||
|
||||
telnet control-server-name 23002
|
||||
|
||||
This would connect through the associated serial port to the desired server's
|
||||
console. This example would then give the user console access to the 3rd
|
||||
server.
|
||||
|
||||
Careful scripting such as using the Linux "expect" program could allow
|
||||
batches of commands to be run on each server.
|
||||
|
||||
Other Linux program useful with remserial
|
||||
-----------------------------------------
|
||||
|
||||
- nc - The netcat program is similar to remserial except that it creates
|
||||
connections between network ports and command line standard input and
|
||||
output.
|
||||
|
||||
For example, with case number 1 above, the following command run on
|
||||
another computer will send the contents of the named file out the
|
||||
serial port used by the remserial program:
|
||||
|
||||
nc server-name 23000 <file-name
|
||||
|
||||
Similarily, the following command will store incoming serial data in a file
|
||||
until the program is manually interrupted:
|
||||
|
||||
nc server-name 23000 >file-name
|
||||
|
||||
- telnet - The telnet program is normally used to log into a remote computer,
|
||||
but when used with network ports other than number 23, it operates in a
|
||||
raw data mode.
|
||||
|
||||
For example, with case number 1 above, the following command will allow
|
||||
the user of the telnet program to see incoming serial port data and
|
||||
type data on the keyboard to send to the serial port:
|
||||
|
||||
telnet server-name 23000
|
||||
|
||||
This is ideal for controlling the device connected to the serial port
|
||||
if it has some sort of command line interface usable over the serial port.
|
||||
|
||||
|
||||
remserial Usage:
|
||||
---------------
|
||||
|
||||
remserial [-r machinename] [-p netport] [-s "stty params"] device
|
||||
|
||||
-r machinename The remote machine name to connect to. If not
|
||||
specified, then this is the server side.
|
||||
-p netport Specifiy IP port# (default 23000)
|
||||
-s "stty params" If serial port, specify stty parameters, see man stty
|
||||
-d Run as daemon programs
|
||||
-x debuglevel Set debug level, 0 is default, 1,2 give more info
|
||||
-l linkname If the device is /dev/ptmx, creates a symbolic link
|
||||
to the corresponding slave pseudo-tty so that another
|
||||
application has a static device name to use.
|
||||
-m max-connections Maximum number of simultaneous client connections to allow
|
||||
device Character oriented device node such as /dev/ttyS0.
|
||||
|
||||
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
* remserial
|
||||
* Copyright (C) 2000 Paul Davis, pdavis@lpccomp.bc.ca
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* This program acts as a bridge either between a socket(2) and a
|
||||
* serial/parallel port or between a socket and a pseudo-tty.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
struct sockaddr_in addr,remoteaddr;
|
||||
int sockfd = -1;
|
||||
int server_port = 23000;
|
||||
int client_port = 22999;
|
||||
int debug = 0;
|
||||
int devfd;
|
||||
int *remotefd;
|
||||
char *machinename = NULL;
|
||||
char *sttyparms = NULL;
|
||||
static char *sdevname = NULL;
|
||||
char *linkname = NULL;
|
||||
int isdaemon = 0;
|
||||
fd_set fdsread,fdsreaduse;
|
||||
struct hostent *remotehost;
|
||||
extern char* ptsname(int fd);
|
||||
int curConnects = 0;
|
||||
|
||||
void sighandler (int sig);
|
||||
int connect_to (struct sockaddr_in *addr);
|
||||
void usage (char *progname);
|
||||
void link_slave (int fd);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int result;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
int maxfd = -1;
|
||||
char devbuf[512];
|
||||
int devbytes;
|
||||
int remoteaddrlen;
|
||||
int c;
|
||||
int waitlogged = 0;
|
||||
int maxConnects = 1;
|
||||
int writeonly = 0;
|
||||
register int i;
|
||||
|
||||
while ( (c=getopt(argc,argv,"dl:m:p:r:s:wx:")) != EOF )
|
||||
switch (c) {
|
||||
case 'd':
|
||||
isdaemon = 1;
|
||||
break;
|
||||
case 'l':
|
||||
linkname = optarg;
|
||||
break;
|
||||
case 'x':
|
||||
debug = atoi(optarg);
|
||||
break;
|
||||
case 'm':
|
||||
maxConnects = atoi(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
server_port = atoi(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
machinename = optarg;
|
||||
break;
|
||||
case 's':
|
||||
sttyparms = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
writeonly = 1;
|
||||
break;
|
||||
case '?':
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sdevname = argv[optind];
|
||||
remotefd = (int *) malloc (maxConnects * sizeof(int));
|
||||
|
||||
// struct group *getgrgid(gid_t gid);
|
||||
|
||||
printf("sdevname=%s,server_port=%d,stty=%s\n",sdevname,server_port,sttyparms);
|
||||
|
||||
openlog("remserial", LOG_PID, LOG_USER);
|
||||
|
||||
if (writeonly)
|
||||
devfd = open(sdevname,O_WRONLY);
|
||||
else
|
||||
devfd = open(sdevname,O_RDWR);
|
||||
|
||||
if ( devfd == -1 ) {
|
||||
syslog(LOG_ERR, "Open of %s failed: %m",sdevname);
|
||||
printf("Open of %s failed: %m",sdevname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (linkname)
|
||||
link_slave(devfd);
|
||||
|
||||
if ( sttyparms ) {
|
||||
set_tty(devfd,sttyparms);
|
||||
}
|
||||
|
||||
signal(SIGINT,sighandler);
|
||||
signal(SIGHUP,sighandler);
|
||||
signal(SIGTERM,sighandler);
|
||||
|
||||
if ( machinename ) {
|
||||
//-----------------------------------------------------------------
|
||||
// We are the client, Find the IP address for the remote machine
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
remotehost = gethostbyname(machinename);
|
||||
if ( !remotehost ) {
|
||||
syslog(LOG_ERR, "Couldn't determine address of %s", machinename );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Copy it into the addr structure */
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = 0;
|
||||
|
||||
//memcpy(&(addr.sin_addr),remotehost->h_addr_list[0], sizeof(struct in_addr));
|
||||
//addr.sin_port = htons(server_port);
|
||||
addr.sin_port = htons(0);
|
||||
|
||||
remotefd[curConnects] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if ( remotefd[curConnects] == -1 ) {
|
||||
syslog(LOG_ERR, "Can't open socket: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* Set up to listen on the given port */
|
||||
if( bind( remotefd[curConnects], (struct sockaddr*)(&addr), sizeof(struct sockaddr_in)) < 0 ) {
|
||||
syslog(LOG_ERR, "Couldn't bind port %d, aborting: %m",client_port );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
memcpy(&(addr.sin_addr),remotehost->h_addr_list[0], sizeof(struct in_addr));
|
||||
addr.sin_port = htons(server_port);
|
||||
if (connect(remotefd[curConnects], (struct sockaddr*)(&addr), sizeof(struct sockaddr_in)) < 0 ) {
|
||||
syslog(LOG_ERR, "Couldn't connect client socket to server socket, aborting: %m");
|
||||
exit(1);
|
||||
}
|
||||
if ( debug>1 )
|
||||
syslog(LOG_NOTICE,"Connected to remote UDP socket");
|
||||
|
||||
curConnects += 1;
|
||||
} else {
|
||||
//-------------------------------
|
||||
// We are the server
|
||||
//-------------------------------
|
||||
|
||||
/* Open the initial socket for communications */
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if ( sockfd == -1 ) {
|
||||
syslog(LOG_ERR, "Can't open socket: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = 0;
|
||||
addr.sin_port = htons(server_port);
|
||||
|
||||
/* Set up to listen on the given port */
|
||||
if( bind( sockfd, (struct sockaddr*)(&addr),
|
||||
sizeof(struct sockaddr_in)) < 0 ) {
|
||||
syslog(LOG_ERR, "Couldn't bind port %d, aborting: %m",server_port );
|
||||
exit(1);
|
||||
}
|
||||
if ( debug>1 )
|
||||
syslog(LOG_NOTICE,"Bound port");
|
||||
}
|
||||
|
||||
|
||||
if ( isdaemon ) {
|
||||
setsid();
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
}
|
||||
|
||||
/* Set up the files/sockets for the select() call */
|
||||
if ( sockfd != -1 ) {
|
||||
FD_SET(sockfd,&fdsread);
|
||||
if ( sockfd >= maxfd )
|
||||
maxfd = sockfd + 1;
|
||||
}
|
||||
|
||||
for (i=0 ; i<curConnects ; i++) {
|
||||
FD_SET(remotefd[i],&fdsread);
|
||||
if ( remotefd[i] >= maxfd )
|
||||
maxfd = remotefd[i] + 1;
|
||||
}
|
||||
|
||||
if (!writeonly) {
|
||||
FD_SET(devfd,&fdsread);
|
||||
if ( devfd >= maxfd )
|
||||
maxfd = devfd + 1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
||||
/* Wait for data from the listening socket, the device
|
||||
or the remote connection */
|
||||
fdsreaduse = fdsread;
|
||||
if ( select(maxfd,&fdsreaduse,NULL,NULL,NULL) == -1 )
|
||||
break;
|
||||
|
||||
/* Activity on the controlling socket, only on server */
|
||||
if ( !machinename && FD_ISSET(sockfd,&fdsreaduse) ) {
|
||||
remoteaddrlen = sizeof(struct sockaddr_in);
|
||||
devbytes = recvfrom(sockfd, devbuf, 512, 0, (struct sockaddr *) &remoteaddr, &remoteaddrlen);
|
||||
|
||||
|
||||
//if ( debug>1 && devbytes>0 )
|
||||
if (debug>1) {
|
||||
syslog(LOG_INFO,"Remote: %d bytes",devbytes);
|
||||
}
|
||||
printf("Socket Remote read: %d bytes\n",devbytes);
|
||||
|
||||
if ( devbytes == 0 ) {
|
||||
} else if ( devfd != -1 ) {
|
||||
if (connect(sockfd, (struct sockaddr*)(&remoteaddr), remoteaddrlen) < 0 ) {
|
||||
syslog(LOG_ERR, "Couldn't connect server socket to client socket, aborting: %m");
|
||||
exit(1);
|
||||
}
|
||||
// socket read/write
|
||||
//remotefd[curConnects] = sockfd;
|
||||
|
||||
/* Write the data to the device */
|
||||
result = write(devfd,devbuf,devbytes);
|
||||
if (result < 0) {
|
||||
printf("write(%d,devbuf,%d):%s", devfd, devbytes,strerror(result));
|
||||
} else {
|
||||
printf("Write to device returned %d", result);
|
||||
}
|
||||
fflush(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Data to read from the device */
|
||||
if ( FD_ISSET(devfd,&fdsreaduse) ) {
|
||||
devbytes = read(devfd,devbuf,512);
|
||||
//if ( debug>1 && devbytes>0 )
|
||||
if (debug>1) {
|
||||
syslog(LOG_INFO,"Device: %d bytes",devbytes);
|
||||
}
|
||||
printf("Device: %d bytes", devbytes);
|
||||
if ( devbytes <= 0 ) {
|
||||
if ( debug>0 ) {
|
||||
syslog(LOG_INFO,"%s closed",sdevname);
|
||||
printf("%s closed",sdevname);
|
||||
}
|
||||
close(devfd);
|
||||
FD_CLR(devfd,&fdsread);
|
||||
while (1) {
|
||||
devfd = open(sdevname,O_RDWR);
|
||||
if ( devfd != -1 )
|
||||
break;
|
||||
syslog(LOG_ERR, "Open of %s failed: %m", sdevname);
|
||||
if ( errno != EIO )
|
||||
exit(1);
|
||||
sleep(1);
|
||||
}
|
||||
if ( debug>0 )
|
||||
syslog(LOG_INFO,"%s re-opened",sdevname);
|
||||
if ( sttyparms )
|
||||
set_tty(devfd,sttyparms);
|
||||
if (linkname)
|
||||
link_slave(devfd);
|
||||
FD_SET(devfd,&fdsread);
|
||||
if ( devfd >= maxfd )
|
||||
maxfd = devfd + 1;
|
||||
} else {
|
||||
for (i=0 ; i<curConnects ; i++) {
|
||||
result = write(remotefd[i],devbuf,devbytes);
|
||||
if (result < 0) {
|
||||
printf("write(remotefd[%d]=%d,devbuf,%d):%s", i, remotefd[i], devbytes, strerror(result));
|
||||
} else {
|
||||
printf("Write to remotefd[%d]=%d returned %d", i, remotefd[i], result);
|
||||
}
|
||||
fflush(NULL);
|
||||
}
|
||||
if ( !machinename) {
|
||||
result = write(sockfd, devbuf,devbytes);
|
||||
if (result < 0) {
|
||||
printf("write(sockfd=%d,devbuf,%d):%s", sockfd, devbytes, strerror(result));
|
||||
} else {
|
||||
printf("Write to sockfd=%d returned %d", sockfd, result);
|
||||
}
|
||||
fflush(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Data to read from the remote system */
|
||||
for (i=0 ; i<curConnects ; i++)
|
||||
if (FD_ISSET(remotefd[i],&fdsreaduse) ) {
|
||||
|
||||
devbytes = read(remotefd[i],devbuf,512);
|
||||
|
||||
//if ( debug>1 && devbytes>0 )
|
||||
if (debug>1) {
|
||||
syslog(LOG_INFO,"Remote: %d bytes",devbytes);
|
||||
}
|
||||
printf("Remote: %d bytes",devbytes);
|
||||
|
||||
if ( devbytes == 0 ) {
|
||||
/*register int j;
|
||||
|
||||
syslog(LOG_NOTICE,"Connection closed");
|
||||
printf("Connection closed");
|
||||
close(remotefd[i]);
|
||||
FD_CLR(remotefd[i],&fdsread);
|
||||
curConnects--;
|
||||
for (j=i ; j<curConnects ; j++)
|
||||
remotefd[j] = remotefd[j+1];
|
||||
if ( machinename ) {
|
||||
// Wait for the server again
|
||||
remotefd[curConnects++] = connect_to(&addr);
|
||||
FD_SET(remotefd[curConnects-1],&fdsread);
|
||||
if ( remotefd[curConnects-1] >= maxfd )
|
||||
maxfd = remotefd[curConnects-1] + 1;
|
||||
}*/
|
||||
}
|
||||
else if ( devfd != -1 ) {
|
||||
/* Write the data to the device */
|
||||
result = write(devfd,devbuf,devbytes);
|
||||
if (result < 0) {
|
||||
printf("write(devfd=%d,devbuf,%d):%s", devfd, devbytes, strerror(result));
|
||||
} else {
|
||||
printf("Write to devfd=%d returned %d", devfd, result);
|
||||
}
|
||||
fflush(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
close(sockfd);
|
||||
for (i=0 ; i<curConnects ; i++)
|
||||
close(remotefd[i]);
|
||||
printf("End of program, normal exit\n");
|
||||
}
|
||||
|
||||
void sighandler(int sig)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( sockfd != -1 )
|
||||
close(sockfd);
|
||||
for (i=0 ; i<curConnects ; i++)
|
||||
close(remotefd[i]);
|
||||
if ( devfd != -1 )
|
||||
close(devfd);
|
||||
if (linkname)
|
||||
unlink(linkname);
|
||||
syslog(LOG_ERR,"Terminating on signal %d",sig);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void link_slave(int fd)
|
||||
{
|
||||
char *slavename;
|
||||
int status = grantpt(devfd);
|
||||
if (status != -1)
|
||||
status = unlockpt(devfd);
|
||||
if (status != -1) {
|
||||
slavename = ptsname(devfd);
|
||||
if (slavename) {
|
||||
// Safety first
|
||||
unlink(linkname);
|
||||
status = symlink(slavename, linkname);
|
||||
}
|
||||
else
|
||||
status = -1;
|
||||
}
|
||||
if (status == -1) {
|
||||
syslog(LOG_ERR, "Cannot create link for pseudo-tty: %m");
|
||||
printf("Cannot create link for pseudo-tty: %m");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
connect_to(struct sockaddr_in *addr)
|
||||
{
|
||||
int waitlogged = 0;
|
||||
int stat;
|
||||
extern int errno;
|
||||
int sockfd;
|
||||
|
||||
if ( debug>0 ) {
|
||||
unsigned long ip = ntohl(addr->sin_addr.s_addr);
|
||||
syslog(LOG_NOTICE, "Trying to connect to %d.%d.%d.%d",
|
||||
(int)(ip>>24)&0xff,
|
||||
(int)(ip>>16)&0xff,
|
||||
(int)(ip>>8)&0xff,
|
||||
(int)(ip>>0)&0xff);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
/* Open the socket for communications */
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 6);
|
||||
if ( sockfd == -1 ) {
|
||||
syslog(LOG_ERR, "Can't open socket: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Try to connect to the remote server,
|
||||
if it fails, keep trying */
|
||||
|
||||
stat = connect(sockfd, (struct sockaddr*)addr,
|
||||
sizeof(struct sockaddr_in));
|
||||
if ( debug>1 )
|
||||
if (stat == -1)
|
||||
syslog(LOG_NOTICE, "Connect status %d, errno %d: %m\n", stat,errno);
|
||||
else
|
||||
syslog(LOG_NOTICE, "Connect status %d\n", stat);
|
||||
|
||||
if ( stat == 0 )
|
||||
break;
|
||||
/* Write a message to syslog once */
|
||||
if ( ! waitlogged ) {
|
||||
syslog(LOG_NOTICE, "Waiting for server on %s port %d: %m", machinename,server_port );
|
||||
waitlogged = 1;
|
||||
}
|
||||
close(sockfd);
|
||||
sleep(10);
|
||||
}
|
||||
if ( waitlogged || debug>0 )
|
||||
syslog(LOG_NOTICE, "Connected to server %s port %d", machinename,server_port );
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
void usage(char *progname) {
|
||||
printf("Remserial version 1.3. Usage:\n");
|
||||
printf("remserial [-r machinename] [-p netport] [-s \"stty params\"] [-m maxconnect] device\n\n");
|
||||
|
||||
printf("-r machinename The remote machine name to connect to. If not\n");
|
||||
printf(" specified, then this is the server side.\n");
|
||||
printf("-p netport Specifiy IP port# (default 23000)\n");
|
||||
printf("-s \"stty params\" If serial port, specify stty parameters, see man stty\n");
|
||||
printf("-m max-connections Maximum number of simultaneous client connections to allow\n");
|
||||
printf("-d Run as a daemon program\n");
|
||||
printf("-x debuglevel Set debug level, 0 is default, 1,2 give more info\n");
|
||||
printf("-l linkname If the device name is a pseudo-tty, create a link to the slave\n");
|
||||
printf("-w Only write to the device, no reading\n");
|
||||
printf("device I/O device, either serial port or pseudo-tty master\n");
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* remserial
|
||||
* Copyright (C) 2000 Paul Davis, pdavis@lpccomp.bc.ca
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CFLG 0
|
||||
#define IFLG 1
|
||||
#define OFLG 2
|
||||
#define LFLG 3
|
||||
#define RFLG 4
|
||||
#define BFLG 5
|
||||
|
||||
extern int errno;
|
||||
|
||||
static struct sttyset {
|
||||
char *name;
|
||||
int which;
|
||||
int mask;
|
||||
int value;
|
||||
} sttynames[] = {
|
||||
{ "0", BFLG, 0, B0 },
|
||||
{ "50", BFLG, 0, B50 },
|
||||
{ "75", BFLG, 0, B75 },
|
||||
{ "110", BFLG, 0, B110 },
|
||||
{ "134", BFLG, 0, B134 },
|
||||
{ "150", BFLG, 0, B150 },
|
||||
{ "200", BFLG, 0, B200 },
|
||||
{ "300", BFLG, 0, B300 },
|
||||
{ "600", BFLG, 0, B600 },
|
||||
{ "1200", BFLG, 0, B1200 },
|
||||
{ "1800", BFLG, 0, B1800 },
|
||||
{ "2400", BFLG, 0, B2400 },
|
||||
{ "4800", BFLG, 0, B4800 },
|
||||
{ "9600", BFLG, 0, B9600 },
|
||||
{ "19200", BFLG, 0, B19200 },
|
||||
{ "38400", BFLG, 0, B38400 },
|
||||
#ifdef B57600
|
||||
{ "57600", BFLG, 0, B57600 },
|
||||
#endif
|
||||
#ifdef B115200
|
||||
{ "115200", BFLG, 0, B115200 },
|
||||
#endif
|
||||
#ifdef B230400
|
||||
{ "230400", BFLG, 0, B230400 },
|
||||
#endif
|
||||
{ "cs7", CFLG, CSIZE, CS7 },
|
||||
{ "cs8", CFLG, CSIZE, CS8 },
|
||||
{ "cstopb", CFLG, CSTOPB, CSTOPB },
|
||||
{ "cread", CFLG, CREAD, CREAD },
|
||||
{ "parenb", CFLG, PARENB, PARENB },
|
||||
{ "parodd", CFLG, PARODD, PARODD },
|
||||
{ "hubcl", CFLG, HUPCL, HUPCL },
|
||||
{ "clocal", CFLG, CLOCAL, CLOCAL },
|
||||
#ifdef CRTSCTS
|
||||
{ "crtscts", CFLG, CRTSCTS, CRTSCTS },
|
||||
#endif
|
||||
#ifdef ORTSFL
|
||||
{ "ortsfl", CFLG, ORTSFL, ORTSFL },
|
||||
#endif
|
||||
#ifdef CTSFLOW
|
||||
{ "ctsflow", CFLG, CTSFLOW, CTSFLOW },
|
||||
#endif
|
||||
#ifdef RTSFLOW
|
||||
{ "rtsflow", CFLG, RTSFLOW, RTSFLOW },
|
||||
#endif
|
||||
{ "ignbrk", IFLG, IGNBRK, IGNBRK },
|
||||
{ "brkint", IFLG, BRKINT, BRKINT },
|
||||
{ "ignpar", IFLG, IGNPAR, IGNPAR },
|
||||
{ "parmrk", IFLG, PARMRK, PARMRK },
|
||||
{ "inpck", IFLG, INPCK, INPCK },
|
||||
{ "istrip", IFLG, ISTRIP, ISTRIP },
|
||||
{ "inlcr", IFLG, INLCR, INLCR },
|
||||
{ "igncr", IFLG, IGNCR, IGNCR },
|
||||
{ "icrnl", IFLG, ICRNL, ICRNL },
|
||||
#ifdef IUCLC // Missing on OSX, FreeBSD
|
||||
{ "iuclc", IFLG, IUCLC, IUCLC },
|
||||
#endif
|
||||
{ "ixon", IFLG, IXON, IXON },
|
||||
{ "ixany", IFLG, IXANY, IXANY },
|
||||
{ "ixoff", IFLG, IXOFF, IXOFF },
|
||||
#ifdef IMAXBEL
|
||||
{ "imaxbel", IFLG, IMAXBEL, IMAXBEL },
|
||||
#endif
|
||||
{ "opost", OFLG, OPOST, OPOST },
|
||||
#ifdef ILCUC // Missing on OSX, FreeBSD
|
||||
{ "olcuc", OFLG, OLCUC, OLCUC },
|
||||
#endif
|
||||
{ "onlcr", OFLG, ONLCR, ONLCR },
|
||||
{ "ocrnl", OFLG, OCRNL, OCRNL },
|
||||
{ "onocr", OFLG, ONOCR, ONOCR },
|
||||
{ "onlret", OFLG, ONLRET, ONLRET },
|
||||
{ "ofil", OFLG, OFILL, OFILL },
|
||||
{ "ofdel", OFLG, OFDEL, OFDEL },
|
||||
{ "nl0", OFLG, NLDLY, NL0 },
|
||||
{ "nl1", OFLG, NLDLY, NL1 },
|
||||
{ "cr0", OFLG, CRDLY, CR0 },
|
||||
{ "cr1", OFLG, CRDLY, CR1 },
|
||||
{ "cr2", OFLG, CRDLY, CR2 },
|
||||
{ "cr3", OFLG, CRDLY, CR3 },
|
||||
{ "tab0", OFLG, TABDLY, TAB0 },
|
||||
{ "tab1", OFLG, TABDLY, TAB1 },
|
||||
{ "tab2", OFLG, TABDLY, TAB2 },
|
||||
{ "tab3", OFLG, TABDLY, TAB3 },
|
||||
{ "bs0", OFLG, BSDLY, BS0 },
|
||||
{ "bs1", OFLG, BSDLY, BS1 },
|
||||
{ "vt0", OFLG, VTDLY, VT0 },
|
||||
{ "vt1", OFLG, VTDLY, VT1 },
|
||||
{ "ff0", OFLG, FFDLY, FF0 },
|
||||
{ "ff1", OFLG, FFDLY, FF1 },
|
||||
{ "isig", LFLG, ISIG, ISIG },
|
||||
{ "icanon", LFLG, ICANON, ICANON },
|
||||
#ifdef XCASE // Missing on OSX, FreeBSD
|
||||
{ "xcase", LFLG, XCASE, XCASE },
|
||||
#endif
|
||||
{ "echo", LFLG, ECHO, ECHO },
|
||||
{ "echoe", LFLG, ECHOE, ECHOE },
|
||||
{ "echok", LFLG, ECHOK, ECHOK },
|
||||
{ "echonl", LFLG, ECHONL, ECHONL },
|
||||
{ "noflsh", LFLG, NOFLSH, NOFLSH },
|
||||
{ "tostop", LFLG, TOSTOP, TOSTOP },
|
||||
#ifdef ECHOCTL
|
||||
{ "echoctl", LFLG, ECHOCTL, ECHOCTL },
|
||||
#endif
|
||||
#ifdef ECHOPRT
|
||||
{ "echoprt", LFLG, ECHOPRT, ECHOPRT },
|
||||
#endif
|
||||
#ifdef ECHOKE
|
||||
{ "echoke", LFLG, ECHOKE, ECHOKE },
|
||||
#endif
|
||||
#ifdef FLUSHO
|
||||
{ "flusho", LFLG, FLUSHO, FLUSHO },
|
||||
#endif
|
||||
#ifdef PENDIN
|
||||
{ "pendin", LFLG, PENDIN, PENDIN },
|
||||
#endif
|
||||
{ "iexten", LFLG, IEXTEN, IEXTEN },
|
||||
#ifdef TOSTOP
|
||||
{ "tostop", LFLG, TOSTOP, TOSTOP },
|
||||
#endif
|
||||
{ "raw", RFLG, 0, 0 },
|
||||
{ NULL, 0, 0, 0 } };
|
||||
|
||||
static void
|
||||
set_this_tty(struct termios *term,struct sttyset *p,int turnon)
|
||||
{
|
||||
/*
|
||||
pdebug(5,"set_this_tty: setting %s on? %d\n",p->name,turnon);
|
||||
*/
|
||||
switch ( p->which ) {
|
||||
case CFLG:
|
||||
term->c_cflag &= ~(p->mask);
|
||||
if ( turnon )
|
||||
term->c_cflag |= p->value;
|
||||
break;
|
||||
case IFLG:
|
||||
term->c_iflag &= ~(p->mask);
|
||||
if ( turnon )
|
||||
term->c_iflag |= p->value;
|
||||
break;
|
||||
case OFLG:
|
||||
term->c_oflag &= ~(p->mask);
|
||||
if ( turnon )
|
||||
term->c_oflag |= p->value;
|
||||
break;
|
||||
case LFLG:
|
||||
term->c_lflag &= ~(p->mask);
|
||||
if ( turnon )
|
||||
term->c_lflag |= p->value;
|
||||
break;
|
||||
case RFLG:
|
||||
term->c_iflag = 0;
|
||||
term->c_oflag = 0;
|
||||
term->c_lflag = 0;
|
||||
term->c_cc[VMIN] = 1;
|
||||
term->c_cc[VTIME] = 0;
|
||||
break;
|
||||
case BFLG:
|
||||
cfsetispeed(term, p->value);
|
||||
cfsetospeed(term, p->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
set_tty(int fd,char *settings)
|
||||
{
|
||||
register char *p;
|
||||
register char *s;
|
||||
struct termios term;
|
||||
register int i;
|
||||
int mode;
|
||||
|
||||
/*
|
||||
pdebug(4,"set_tty: fd %d settings %s\n",fd,settings);
|
||||
*/
|
||||
if ( tcgetattr(fd,&term) == -1 ) {
|
||||
/*
|
||||
pdebug(4,"set_tty: cannot get settings for fd %d, error %d\n",
|
||||
fd,errno);
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = strdup(settings);
|
||||
p = strtok(s," \t\n");
|
||||
while (p) {
|
||||
mode = 1;
|
||||
if ( *p == '-' ) {
|
||||
mode = 0;
|
||||
p++;
|
||||
}
|
||||
for ( i=0 ; sttynames[i].name ; i++ ) {
|
||||
if ( !strcmp(p,sttynames[i].name) ) {
|
||||
set_this_tty(&term,&sttynames[i],mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
p = strtok(NULL," \t\n");
|
||||
}
|
||||
free(s);
|
||||
if ( tcsetattr(fd,TCSANOW,&term) == -1 ) {
|
||||
/*
|
||||
pdebug(4,"set_tty: cannot get settings for fd %d error %d\n",
|
||||
fd,errno);
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||