You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
407 lines
10 KiB
407 lines
10 KiB
/***************************************************************************
|
|
common.c
|
|
-------------------
|
|
begin : Sun Jun 18 2000
|
|
copyright : (C) 2000 by Kamil Dobkowski
|
|
email : kamildobk@friko.onet.pl
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* 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. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include<stdio.h>
|
|
#include<errno.h>
|
|
#include<assert.h>
|
|
#include<stdlib.h>
|
|
#include<string.h>
|
|
#include<unistd.h>
|
|
#include<fcntl.h>
|
|
#include<sys/un.h>
|
|
#include<sys/stat.h>
|
|
#include<sys/types.h>
|
|
#include<sys/socket.h>
|
|
|
|
|
|
#include"common.h"
|
|
#include"msg.h"
|
|
|
|
#define KMATPLOT_EXECUTABLE "kmatplot"
|
|
#define MAX_APP_NUMBER 99999
|
|
#define STDOUT_FD 1
|
|
#define STDERR_FD 2
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
void _get_socket_name( int app_number, struct sockaddr_un *addr )
|
|
/*
|
|
* Returns a socket path for the given app number.
|
|
* Example: '/tmp/.kmatplot.root.1'
|
|
*/
|
|
{
|
|
int pos;
|
|
char buff[50];
|
|
|
|
sprintf(buff,"%d", app_number);
|
|
memset( (char *)addr, 0, sizeof(addr) );
|
|
addr->sun_family = AF_UNIX;
|
|
|
|
pos = 0;
|
|
strncpy( &addr->sun_path[pos], P_tmpdir, sizeof(addr->sun_path)-pos ); pos += strlen(P_tmpdir);
|
|
strncpy( &addr->sun_path[pos], "/.kmatplot.", sizeof(addr->sun_path)-pos ); pos += strlen("/.kmatplot.");
|
|
strncpy( &addr->sun_path[pos], getenv("USER"), sizeof(addr->sun_path)-pos ); pos += strlen(getenv("USER"));
|
|
strncpy( &addr->sun_path[pos], ".", sizeof(addr->sun_path)-pos ); pos += strlen(".");
|
|
strncpy( &addr->sun_path[pos], buff, sizeof(addr->sun_path)-pos );
|
|
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int _run_new_server( int app_number )
|
|
/*
|
|
* Runs a new kmatplot application and returns its app number.
|
|
*/
|
|
{
|
|
int pid;
|
|
int null_fd = 0;
|
|
int ssocket_fd = 0; /* socket for the server */
|
|
char buff[50];
|
|
struct sockaddr_un addr;
|
|
|
|
if ( (ssocket_fd=socket(AF_UNIX,SOCK_STREAM,0)) < 0 ) return 0;
|
|
|
|
if ( app_number > 0 ) {
|
|
/* Bind to the given app number. */
|
|
_get_socket_name( app_number, &addr );
|
|
if ( bind( ssocket_fd,
|
|
(struct sockaddr *)&addr,
|
|
strlen(addr.sun_path)+
|
|
sizeof(addr.sun_family)) < 0 ) { close(ssocket_fd); return -1; }
|
|
} else {
|
|
/* Find first unused app number */
|
|
do {
|
|
if ( app_number > MAX_APP_NUMBER ) return -1;
|
|
_get_socket_name( ++app_number, &addr );
|
|
} while( bind( ssocket_fd,
|
|
(struct sockaddr *)&addr,
|
|
strlen(addr.sun_path) +
|
|
sizeof(addr.sun_family )) < 0 );
|
|
}
|
|
|
|
listen( ssocket_fd, 1 );
|
|
/*null_fd = open("/dev/null", O_WRONLY );*/
|
|
sprintf( buff, "%d", ssocket_fd);
|
|
|
|
pid = fork();
|
|
|
|
/**
|
|
* Child process
|
|
*/
|
|
if ( pid == 0 ) {
|
|
/*dup2( null_fd, STDOUT_FD ); // put this into kmatplot !*/
|
|
/*dup2( null_fd, STDERR_FD ); */
|
|
execlp( KMATPLOT_EXECUTABLE, KMATPLOT_EXECUTABLE, "--fd", buff, NULL );
|
|
}
|
|
/**
|
|
* Parent process
|
|
*/
|
|
else if ( pid > 0 ) {
|
|
/*close( null_fd );*/
|
|
close( ssocket_fd );
|
|
return app_number;
|
|
}
|
|
/*
|
|
* Fork error
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int plot_connect( int app_number, int *return_app_number, int *return_socket_fd )
|
|
{
|
|
int err;
|
|
int socket_fd;
|
|
struct sockaddr_un addr;
|
|
|
|
if ( app_number < 0 ) return -1;
|
|
|
|
/**
|
|
* Auto-run a new server.
|
|
*/
|
|
if ( app_number == 0 ) {
|
|
app_number = _run_new_server( 0 );
|
|
}
|
|
if ( app_number == 0 ) return -1;
|
|
|
|
/*
|
|
* Connect to server.
|
|
*/
|
|
_get_socket_name( app_number, &addr );
|
|
|
|
if ( (socket_fd=socket(AF_UNIX,SOCK_STREAM,0)) < 0 ) return -1;
|
|
err = connect( socket_fd,
|
|
(struct sockaddr *)&addr,
|
|
sizeof(addr.sun_family)+
|
|
strlen(addr.sun_path) );
|
|
|
|
/*
|
|
* Server not running ?
|
|
*/
|
|
if ( err < 0 && ( errno == ECONNREFUSED || errno == ENOENT ) ) {
|
|
|
|
unlink( addr.sun_path );
|
|
close(socket_fd);
|
|
if ( _run_new_server( app_number ) == 0 ) return -1;
|
|
if ( (socket_fd=socket(AF_UNIX,SOCK_STREAM,0)) < 0 ) return -1;
|
|
if ( connect( socket_fd,
|
|
(struct sockaddr *)&addr,
|
|
sizeof(addr.sun_family)+
|
|
strlen(addr.sun_path) ) < 0 ) return -1;
|
|
}
|
|
|
|
if ( return_app_number ) *return_app_number = app_number;
|
|
if ( return_socket_fd ) *return_socket_fd = socket_fd;
|
|
|
|
return socket_fd;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int esizeof( EType type )
|
|
{
|
|
switch( type ) {
|
|
case EUChar: return sizeof(unsigned char);
|
|
case EShort: return sizeof(short);
|
|
case EUShort: return sizeof(unsigned short);
|
|
case ELong: return sizeof(long);
|
|
case EFloat: return sizeof(float);
|
|
case EDouble: return sizeof(double);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int _write_data( int fd, const char *data, int len )
|
|
{
|
|
int nleft;
|
|
int bytes;
|
|
const char *ptr;
|
|
|
|
ptr = data;
|
|
nleft = len;
|
|
while( nleft > 0 ) {
|
|
bytes = write( fd, ptr, nleft );
|
|
if ( bytes < 0 ) break; /* error */
|
|
nleft -= bytes;
|
|
ptr += bytes;
|
|
}
|
|
return(len - nleft);
|
|
}
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int _get_reply_code( int socket_fd )
|
|
{
|
|
int reply_code = -1;
|
|
int result = _read_data( socket_fd, (const char*)&reply_code, sizeof(reply_code) );
|
|
if ( result < sizeof(reply_code) ) reply_code = result;
|
|
return reply_code;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int _read_data( int fd, char *data, int len )
|
|
{
|
|
int nleft;
|
|
int nread;
|
|
|
|
nleft = len;
|
|
while( nleft > 0 ) {
|
|
nread = read( fd, data, nleft );
|
|
if ( nread < 0 ) return nread; /* error */
|
|
else
|
|
if ( nread == 0 ) break;
|
|
|
|
nleft -= nread;
|
|
data += nread;
|
|
}
|
|
|
|
return(len - nleft);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int plot_add_axes( int socket_fd, int axes_type )
|
|
{
|
|
hdr_t hdr;
|
|
int bytes;
|
|
|
|
if ( socket_fd < 0 ) return OpError;
|
|
|
|
hdr.a.type = MsgAddAxes;
|
|
hdr.a.dlen = 0;
|
|
hdr.a.plot = -1;
|
|
hdr.a.axes = axes_type;
|
|
|
|
/* Write header */
|
|
bytes = _write_data( socket_fd, (const char *)&hdr, sizeof(hdr) );
|
|
if ( bytes < (int )sizeof(hdr) ) return OpError;
|
|
|
|
return _get_reply_code(socket_fd);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int plot_remove_axes( int socket_fd, int axes_id )
|
|
{
|
|
hdr_t hdr;
|
|
int bytes;
|
|
|
|
if ( socket_fd < 0 ) return OpError;
|
|
|
|
hdr.a.type = MsgRemoveAxes;
|
|
hdr.a.dlen = 0;
|
|
hdr.a.plot = axes_id;
|
|
|
|
/* Write header */
|
|
bytes = _write_data( socket_fd, (const char *)&hdr, sizeof(hdr) );
|
|
if ( bytes < (int )sizeof(hdr) ) return OpError;
|
|
|
|
return _get_reply_code(socket_fd);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int plot_add_dataset( int socket_fd, int plot, PlotType type )
|
|
{
|
|
hdr_t hdr;
|
|
int bytes;
|
|
|
|
if ( socket_fd < 0 ) return OpError;
|
|
|
|
hdr.t.type = MsgAddDataset;
|
|
hdr.t.dlen = 0;
|
|
hdr.t.dnum = -1;
|
|
hdr.t.plot = plot;
|
|
hdr.t.ptype = type;
|
|
|
|
/* Write header */
|
|
bytes = _write_data( socket_fd, (const char *)&hdr, sizeof(hdr) );
|
|
if ( bytes < (int )sizeof(hdr) ) return OpError;
|
|
|
|
return _get_reply_code(socket_fd);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int plot_remove_dataset( int socket_fd, int plot, int number )
|
|
{
|
|
hdr_t hdr;
|
|
int bytes;
|
|
|
|
if ( socket_fd < 0 ) return OpError;
|
|
|
|
hdr.t.type = MsgRemoveDataset;
|
|
hdr.t.dlen = 0;
|
|
hdr.t.dnum = number;
|
|
hdr.t.plot = plot;
|
|
/*hdr.t.ptype = ;*/
|
|
|
|
/* Write header */
|
|
bytes = _write_data( socket_fd, (const char *)&hdr, sizeof(hdr) );
|
|
if ( bytes < (int )sizeof(hdr) ) return OpError;
|
|
|
|
return _get_reply_code(socket_fd);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int plot_remove_all_datasets( int socket_fd, int plot )
|
|
{
|
|
hdr_t hdr;
|
|
int bytes;
|
|
|
|
if ( socket_fd < 0 ) return OpError;
|
|
|
|
hdr.t.type = MsgRemoveAllDatasets;
|
|
hdr.t.dlen = 0;
|
|
hdr.t.dnum = -1;
|
|
hdr.t.plot = plot;
|
|
/*hdr.t.ptype = type;*/
|
|
|
|
/* Write header */
|
|
bytes = _write_data( socket_fd, (const char *)&hdr, sizeof(hdr) );
|
|
if ( bytes < (int )sizeof(hdr) ) return OpError;
|
|
|
|
return _get_reply_code(socket_fd);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
int plot_set_channel( int socket_fd, int plot, int dataset, int channel, EType etype, int rows, int cols, const void *data, int dlen, int pixelo, int lineo )
|
|
{
|
|
int bytes;
|
|
hdr_t hdr;
|
|
|
|
if ( socket_fd < 0 ) return OpError;
|
|
|
|
assert( plot >= 0 );
|
|
assert( rows > 0 );
|
|
assert( cols > 0 );
|
|
assert( dlen >= 0 );
|
|
assert( data );
|
|
|
|
/* Default values */
|
|
if ( pixelo == 0 ) pixelo = esizeof(etype);
|
|
if ( lineo == 0 ) lineo = cols * pixelo;
|
|
if ( dlen == 0 ) dlen = rows * cols * esizeof(etype);
|
|
|
|
hdr.c.type = MsgChannel;
|
|
hdr.c.dnum = dataset;
|
|
hdr.c.dlen = dlen;
|
|
hdr.c.plot = plot;
|
|
hdr.c.chan = channel;
|
|
hdr.c.rows = rows;
|
|
hdr.c.cols = cols;
|
|
hdr.c.etype = etype;
|
|
hdr.c.pixelo = pixelo;
|
|
hdr.c.lineo = lineo;
|
|
|
|
/* Write header */
|
|
bytes = _write_data( socket_fd, (const char *)&hdr, sizeof(hdr) );
|
|
if ( bytes < (int )sizeof(hdr) ) return OpError;
|
|
|
|
/** Write data */
|
|
bytes = _write_data( socket_fd, (const char *)data, dlen );
|
|
if ( bytes < dlen ) return OpError;
|
|
|
|
return _get_reply_code(socket_fd);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
|
|
int plot_set_property( int socket_fd, int plot, const char *property, const char *value )
|
|
{
|
|
if ( socket_fd < 0 ) return OpError;
|
|
return OpError;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------*/
|
|
|
|
|
|
void plot_disconnect( int socket_fd )
|
|
{
|
|
if ( socket_fd < 0 ) return;
|
|
close(socket_fd);
|
|
}
|
|
|