259 lines
6.2 KiB
C
259 lines
6.2 KiB
C
|
/*-------------------------------------------------------------------------
|
||
|
*
|
||
|
* support.c
|
||
|
* BeOS Support functions
|
||
|
*
|
||
|
* Copyright (c) 1999-2000, Cyril VELTER
|
||
|
*
|
||
|
*-------------------------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
#include "postgres.h"
|
||
|
|
||
|
/* Support Globals */
|
||
|
char* self_binary=NULL;
|
||
|
port_id beos_dl_port_in=0;
|
||
|
port_id beos_dl_port_out=0;
|
||
|
sem_id beos_shm_sem;
|
||
|
|
||
|
image_id beos_dl_open(char * filename)
|
||
|
{
|
||
|
image_id im;
|
||
|
|
||
|
/* Start the support server */
|
||
|
if (self_binary==NULL)
|
||
|
{
|
||
|
/* Can't start support server without binary name */
|
||
|
elog(NOTICE, "Error loading BeOS support server : can't find binary");
|
||
|
return B_ERROR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* If a port doesn't exist, lauch support server */
|
||
|
if ((beos_dl_port_in<=0)||(beos_dl_port_out<=0))
|
||
|
{
|
||
|
/* Create communication port */
|
||
|
beos_dl_port_in=create_port(50,"beos_support_in");
|
||
|
beos_dl_port_out=create_port(50,"beos_support_in");
|
||
|
|
||
|
|
||
|
if ((beos_dl_port_in<=0)||(beos_dl_port_out<=0))
|
||
|
{
|
||
|
elog(NOTICE, "Error loading BeOS support server : can't create communication ports");
|
||
|
return B_ERROR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
char Cmd[4000];
|
||
|
|
||
|
/* Build arg list */
|
||
|
sprintf(Cmd,"%s -beossupportserver %d %d &",self_binary,(int)beos_dl_port_in,(int)beos_dl_port_out);
|
||
|
|
||
|
/* Lauch process */
|
||
|
system(Cmd);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Add-on loading */
|
||
|
|
||
|
/* Send command '1' (load) to the support server */
|
||
|
write_port(beos_dl_port_in,1,filename,strlen(filename)+1);
|
||
|
|
||
|
/* Read Object Id */
|
||
|
read_port(beos_dl_port_out,&im,NULL,0);
|
||
|
|
||
|
/* Checking integrity */
|
||
|
if (im<0)
|
||
|
{
|
||
|
elog(NOTICE, "Can't load this add-on ");
|
||
|
return B_ERROR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Map text and data segment in our address space */
|
||
|
char datas[4000];
|
||
|
int32 area;
|
||
|
int32 resu;
|
||
|
void* add;
|
||
|
|
||
|
/* read text segment id and address */
|
||
|
read_port(beos_dl_port_out,&area,datas,4000);
|
||
|
read_port(beos_dl_port_out,(void*)&add,datas,4000);
|
||
|
/* map text segment in our address space */
|
||
|
resu=clone_area(datas,&add,B_EXACT_ADDRESS,B_READ_AREA|B_WRITE_AREA,area);
|
||
|
if (resu<0)
|
||
|
{
|
||
|
/* If we can't map, we are in reload case */
|
||
|
/* delete the mapping */
|
||
|
resu=delete_area(area_for(add));
|
||
|
/* Remap */
|
||
|
resu=clone_area(datas,&add,B_EXACT_ADDRESS,B_READ_AREA|B_WRITE_AREA,area);
|
||
|
if (resu<0)
|
||
|
{
|
||
|
elog(NOTICE, "Can't load this add-on : map text error");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* read text segment id and address */
|
||
|
read_port(beos_dl_port_out,&area,datas,4000);
|
||
|
read_port(beos_dl_port_out,(void*)&add,datas,4000);
|
||
|
/* map text segment in our address space */
|
||
|
resu=clone_area(datas,&add,B_EXACT_ADDRESS,B_READ_AREA|B_WRITE_AREA,area);
|
||
|
if (resu<0)
|
||
|
{
|
||
|
/* If we can't map, we are in reload case */
|
||
|
/* delete the mapping */
|
||
|
resu=delete_area(area_for(add));
|
||
|
/* Remap */
|
||
|
resu=clone_area(datas,&add,B_EXACT_ADDRESS,B_READ_AREA|B_WRITE_AREA,area);
|
||
|
if (resu<0)
|
||
|
{
|
||
|
elog(NOTICE, "Can't load this add-on : map data error");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return im;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
status_t beos_dl_close(image_id im)
|
||
|
{
|
||
|
/* unload add-on */
|
||
|
int32 resu;
|
||
|
write_port(beos_dl_port_in,2,&im,4);
|
||
|
read_port(beos_dl_port_out,&resu,NULL,0);
|
||
|
return resu;
|
||
|
}
|
||
|
|
||
|
/* Main support server loop */
|
||
|
|
||
|
void beos_startup(int argc,char** argv)
|
||
|
{
|
||
|
if (strlen(argv[0]) >= 10 && !strcmp(argv[0] + strlen(argv[0]) - 10, "postmaster"))
|
||
|
{
|
||
|
/* Shared memory cloning protection semaphore */
|
||
|
beos_shm_sem=create_sem(1,"beos_shm_sem");
|
||
|
}
|
||
|
|
||
|
if (argc > 1 && strcmp(argv[1], "-beossupportserver") == 0)
|
||
|
{
|
||
|
port_id port_in;
|
||
|
port_id port_out;
|
||
|
|
||
|
/* Get back port ids from arglist */
|
||
|
sscanf(argv[2],"%d",(int*)(&port_in));
|
||
|
sscanf(argv[3],"%d",(int*)(&port_out));
|
||
|
|
||
|
/* Main server loop */
|
||
|
for (;;)
|
||
|
{
|
||
|
int32 opcode=0;
|
||
|
char datas[4000];
|
||
|
|
||
|
/* Wait for a message from the backend :
|
||
|
1 : load a shared object
|
||
|
2 : unload a shared object
|
||
|
any other : exit support server */
|
||
|
read_port(port_in,&opcode,datas,4000);
|
||
|
|
||
|
switch(opcode)
|
||
|
{
|
||
|
image_id addon;
|
||
|
image_info info_im;
|
||
|
area_info info_ar;
|
||
|
|
||
|
/* Load Add-On */
|
||
|
case 1 :
|
||
|
|
||
|
/* Load shared object */
|
||
|
addon=load_add_on(datas);
|
||
|
|
||
|
/* send back the shared object Id */
|
||
|
write_port(port_out,addon,NULL,0);
|
||
|
|
||
|
/* Get Shared Object infos */
|
||
|
get_image_info(addon,&info_im);
|
||
|
|
||
|
/* get text segment info */
|
||
|
get_area_info(area_for(info_im.text),&info_ar);
|
||
|
/* Send back area_id of text segment */
|
||
|
write_port(port_out,info_ar.area,info_ar.name,strlen(info_ar.name)+1);
|
||
|
/* Send back real address of text segment */
|
||
|
write_port(port_out,(int)info_ar.address,info_ar.name,strlen(info_ar.name)+1);
|
||
|
|
||
|
|
||
|
/* get data segment info */
|
||
|
get_area_info(area_for(info_im.data),&info_ar);
|
||
|
/* Send back area_id of data segment */
|
||
|
write_port(port_out,info_ar.area,info_ar.name,strlen(info_ar.name)+1);
|
||
|
/* Send back real address of data segment */
|
||
|
write_port(port_out,(int)info_ar.address,info_ar.name,strlen(info_ar.name)+1);
|
||
|
break;
|
||
|
/* UnLoad Add-On */
|
||
|
case 2 :
|
||
|
/* Unload shared object and send back the result of the operation */
|
||
|
write_port(port_out,unload_add_on(*((int*)(datas))),NULL,0);
|
||
|
break;
|
||
|
/* Cleanup and exit */
|
||
|
default:
|
||
|
/* Free system resources */
|
||
|
delete_port(port_in);
|
||
|
delete_port(port_out);
|
||
|
/* Exit */
|
||
|
exit(0);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
/* Never be there */
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void beos_backend_startup(char * binary)
|
||
|
{
|
||
|
team_id ct;
|
||
|
thread_info inft;
|
||
|
char nom[50];
|
||
|
char nvnom[50];
|
||
|
area_info inf;
|
||
|
int32 cook=0;
|
||
|
|
||
|
/* remember full path binary name to load dl*/
|
||
|
self_binary=strdup(binary);
|
||
|
|
||
|
/* find the current team */
|
||
|
get_thread_info(find_thread(NULL),&inft);
|
||
|
ct=inft.team;
|
||
|
|
||
|
/* find all area with a name begining by pgsql and destroy / clone then */
|
||
|
|
||
|
/* This operation must be done by only one backend at a time */
|
||
|
if(acquire_sem(beos_shm_sem)==B_OK)
|
||
|
{
|
||
|
while (get_next_area_info(0, &cook, &inf) == B_OK)
|
||
|
{
|
||
|
strcpy(nom,inf.name);
|
||
|
strcpy(nvnom,inf.name);
|
||
|
nom[9]=0;
|
||
|
nvnom[5]='i';
|
||
|
if (!strcmp(nom,"SYSV_IPC_"))
|
||
|
{
|
||
|
void* add;
|
||
|
area_id ar;
|
||
|
add=inf.address;
|
||
|
delete_area(inf.area);
|
||
|
ar=find_area(inf.name);
|
||
|
clone_area(nvnom,&add,B_CLONE_ADDRESS,B_READ_AREA|B_WRITE_AREA,ar);
|
||
|
}
|
||
|
}
|
||
|
release_sem(beos_shm_sem);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Fatal error, exiting with error */
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|