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

/***************************************************************************
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);
}