/* --8<--8<--8<--8<--
*
* Copyright (C) 2000-2009 Smithsonian Astrophysical Observatory
*
* This file is part of IPC-XPA
*
* IPC-XPA 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 3 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, see <http://www.gnu.org/licenses/>.
*
* -->8-->8-->8-->8-- */
#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <xpa.h>
#include "util.h"
#ifdef __cplusplus
}
#endif
#define X_MAXSERVERS "max_servers"
#define L_MAXSERVERS strlen(X_MAXSERVERS)
#define X_MODE "mode"
#define L_MODE strlen(X_MODE)
/* catch error from pre 2.1 server -- if we find this error, we know the
access point is available */
#define OLD_SERVER(s) strstr(s, "invalid xpa command in initialization string")
typedef XPA IPC_XPA_RAW;
MODULE = IPC::XPA PACKAGE = IPC::XPA
IPC_XPA_RAW
_Open(mode)
char* mode
CODE:
RETVAL = XPAOpen(mode);
OUTPUT:
RETVAL
IPC_XPA_RAW
nullXPA()
CODE:
RETVAL = NULL;
OUTPUT:
RETVAL
void
_Close(xpa)
IPC_XPA_RAW xpa
CODE:
XPAClose(xpa);
void
_Get(xpa, xtemplate, paramlist, mode, max_servers )
IPC_XPA_RAW xpa
char* xtemplate
char* paramlist
char* mode
int max_servers
PREINIT:
char **bufs;
size_t *lens;
char **names;
char **messages;
int i;
int ns;
PPCODE:
/* allocate return arrays */
New( 0, bufs, max_servers, char *);
New( 0, lens, max_servers, size_t);
New( 0, names, max_servers, char *);
New( 0, messages, max_servers, char *);
/* send request to server */
ns = XPAGet(xpa, xtemplate, paramlist, mode, bufs, lens,
names, messages, max_servers);
/* convert result into something Perlish */
EXTEND(SP, 2*ns);
for ( i = 0 ; i < ns ; i++ )
{
/* push the name of the server */
PUSHs( sv_2mortal(newSVpv(names[i],0)) );
/* push a reference to the hash onto the stack */
PUSHs( sv_2mortal(newRV_noinc((SV*)
cdata2hash_Get(bufs[i],lens[i],names[i],
messages[i] ))) );
free( names[i] );
free( messages[i] );
}
/* free up memory that's no longer needed */
Safefree( bufs );
Safefree( lens );
Safefree( names );
Safefree( messages );
#undef NMARGS
#define NMARGS 3
void
_Set(xpa, xtemplate, paramlist, mode, buf, len, max_servers )
IPC_XPA_RAW xpa
char* xtemplate
char* paramlist
char* mode
char* buf
long len
int max_servers
PREINIT:
char **bufs;
int *lens;
char **names;
char **messages;
int i;
int ns;
int n = 1;
PPCODE:
/* allocate return arrays */
New( 0, names, max_servers, char *);
New( 0, messages, max_servers, char *);
/* send request to server */
ns = XPASet(xpa, xtemplate, paramlist, mode, buf, len,
names, messages, max_servers);
/* convert result into something Perlish */
EXTEND(SP, 2*ns);
for ( i = 0 ; i < ns ; i++ )
{
/* push the name of the server */
PUSHs( sv_2mortal(newSVpv(names[i],0)) );
/* Now, push a reference to the hash onto the stack */
PUSHs( sv_2mortal(newRV_noinc((SV*)
cdata2hash_Set(names[i], messages[i] ))) );
free( names[i] );
free( messages[i] );
}
/* free up memory that's no longer needed */
Safefree( names );
Safefree( messages );
void
_Info(xpa, xtemplate, paramlist, mode, max_servers )
IPC_XPA_RAW xpa
char* xtemplate
char* paramlist
char* mode
int max_servers
PREINIT:
char **names;
char **messages;
int i;
int ns;
PPCODE:
/* allocate return arrays */
New( 0, names, max_servers, char *);
New( 0, messages, max_servers, char *);
/* send request to server */
ns = XPAInfo(xpa, xtemplate, paramlist, mode,
names, messages, max_servers);
/* convert result into something Perlish */
EXTEND(SP, 2*ns);
for ( i = 0 ; i < ns ; i++ )
{
/* push the name of the server */
PUSHs( sv_2mortal(newSVpv(names[i],0)) );
/* Now, push a reference to the hash onto the stack */
PUSHs( sv_2mortal(newRV_noinc((SV*)
cdata2hash_Set(names[i], messages[i] ))) );
free( names[i] );
free( messages[i] );
}
/* free up memory that's no longer needed */
Safefree( names );
Safefree( messages );
void
_NSLookup(xpa, tname, ttype)
IPC_XPA_RAW xpa
char* tname
char* ttype
PREINIT:
char **xclasses;
char **names;
char **methods;
char **infos;
int i;
int ns;
PPCODE:
ns = XPANSLookup( xpa, tname, ttype, &xclasses, &names,
&methods, &infos );
/* convert result into something Perlish */
EXTEND(SP, ns);
for ( i = 0 ; i < ns ; i++ )
{
/* Now, push a reference to the hash onto the stack */
PUSHs( sv_2mortal(newRV_noinc((SV*)
cdata2hash_Lookup(xclasses[i],
names[i],
methods[i],
infos[i]
))) );
free( xclasses[i] );
free( names[i] );
free( methods[i] );
free( infos[i] );
}
if ( ns > 0 )
{
free( xclasses );
free( names );
free( methods );
free( infos );
}
void
_Access(xpa, xtemplate, paramlist, mode, max_servers )
IPC_XPA_RAW xpa
char* xtemplate
char* paramlist
char* mode
int max_servers
PREINIT:
char **names;
char **messages;
int i;
int ns;
PPCODE:
/* allocate return arrays */
New( 0, names, max_servers, char *);
New( 0, messages, max_servers, char *);
/* send request to server */
ns = XPAAccess(xpa, xtemplate, paramlist, mode,
names, messages, max_servers);
/* convert result into something Perlish */
EXTEND(SP, 2*ns);
for ( i = 0 ; i < ns ; i++ )
{
/* push the name of the server */
PUSHs( sv_2mortal(newSVpv(names[i],0)) );
/* older servers than 2.1 will react with an error
to the access command; they're there (because
we see the error) */
if ( messages[i] && OLD_SERVER(messages[i]) )
{
free( messages[i] );
messages[i] = NULL;
}
/* Now, push a reference to the hash onto the stack */
PUSHs( sv_2mortal(newRV_noinc((SV*)
cdata2hash_Set(names[i], messages[i] ))) );
free( names[i] );
free( messages[i] );
}
/* free up memory that's no longer needed */
Safefree( names );
Safefree( messages );