/* @(#)osx.c 17.1.1.1 (ES0-DMD) 01/25/02 17:35:27 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) 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 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TYPE Module .NAME osx .LANGUAGE C .AUTHOR K. Banse ESO-IPG, Garching .CATEGORY Host operating system interfaces. Interprocess Communication .COMMENTS Interprocess communication routines for VMS. These routines allow the creation of asynchronous communication channels between processes. The communication channel is open by giving the channel name and the mode of opening. The function returns an integer number used to address the channel. The routines return always a non-negative integer number on successful return. Otherwise, a value of -1 is set to indicate an error condition and the variable ``oserror'' contains the symbolic error code. Symbolic error codes for each function to be defined. .HISTORY 1.00 890720 adapted from prototype version by M. Pucillo, Trieste .HISTORY 1.10 891102 fix related problem in osxopen (return kid!) KB .HISTORY 1.20 891211 fix 4th par. in SYS$ASSIGN (to NULL pointer) TM .HISTORY 1.30 900115 replace $DESCRIPTOR construct by exact commands KB .HISTORY 1.40 910909 redesign the osx !! KB ------------------------------------------------------------*/ #include #include #include /* VMS dependent include section */ #include #include #include #define BIT_0 0x1 typedef struct { short cond_value; short count; int info; } iostat_blk; struct ipccstat IPCC[MAX_IPCC]; static short channel[MAX_IPCC]; static iostat_blk iosb[MAX_IPCC]; static unsigned int retval; extern int oserror; extern int errno; int osxopen(channame, mode) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Opens communication channel for read or write. The variable mode defines the way of opening the file by constructing the OR of the following flags: - LOCAL (local communication channel) - CLIENT (client mode of opening : no priv. required) - IPC_READ (open the channel in READ mode) - IPC_WRITE (open the channel in WRITE mode) .RETURNS Upon successful completion a positive number with the channel identification is returned or -1 in case of error. .REMARKS System dependencies: -- VMS : SYS$CREMBX, $DESCRIPTOR, LIB$SIGNAL, open(2) ------------------------------------------------------------*/ char *channame[2]; /* physical channel name */ int mode; /* open mode */ { static int cid = 0; int kid; unsigned short chan; unsigned int maxmsg = 4096; unsigned int bufquo = 8192; char bzero = 0; char bone = 1; unsigned int izero = 0; struct dsc$descriptor_s lognam_desc; lognam_desc.dsc$w_length = strlen(channame[0]); lognam_desc.dsc$a_pointer = channame[0]; lognam_desc.dsc$b_class = DSC$K_CLASS_S; lognam_desc.dsc$b_dtype = DSC$K_DTYPE_T; if (cid >= MAX_IPCC) { oserror = EINVAL; return (-1); } for (kid=1; kid<=cid; kid++) /* look for free (closed) entry */ { if (IPCC[kid].status == CLOSED) goto slot_found; } kid = ++ cid; slot_found: switch (mode) { case 0: /* open channel in read mode, locally */ /* --------- local server ----------- */ retval = SYS$CREMBX(bone,&chan,maxmsg,bufquo,izero,izero,&lognam_desc); if (retval != SS$_NORMAL) LIB$SIGNAL (retval); IPCC[kid].status = OPENED_READ; IPCC[kid].omode = IPC_READ; IPCC[kid].type = LOCAL; channel[kid] = chan; break; case 1: /* open channel in write mode, locally */ /* --------- local server ------------ */ /* default IPCC number is set to 0 at opening */ retval = SYS$CREMBX(bone,&chan,maxmsg,bufquo,izero,izero,&lognam_desc); if (retval != SS$_NORMAL) LIB$SIGNAL (retval); IPCC[kid].status = OPENED_WRITE; IPCC[kid].omode = IPC_WRITE; IPCC[kid].type = LOCAL; channel[kid] = chan; break; case 4: /* open channel in read mode, locally */ /* --------- local client ----------- */ retval = SYS$ASSIGN(&lognam_desc,&chan,bzero,(struct dsc$descriptor *)NULL); if (retval != SS$_NORMAL) LIB$SIGNAL (retval); IPCC[kid].status = OPENED_READ; IPCC[kid].omode = IPC_READ; IPCC[kid].type = LOCAL | CLIENT; channel[kid] = chan; break; case 5: /* open channel in write mode, locally */ /* --------- local client ------------ */ /* default IPCC number is set to 0 at opening */ retval = SYS$ASSIGN(&lognam_desc,&chan,bzero,(struct dsc$descriptor *)NULL); if (retval != SS$_NORMAL) LIB$SIGNAL (retval); IPCC[kid].status = OPENED_WRITE; IPCC[kid].omode = IPC_WRITE; IPCC[kid].type = LOCAL | CLIENT; channel[kid] = chan; break; default: oserror = EINVAL; break; } return(oserror == 0 ? kid : -1); } int osxclose(cid) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Closes interprocess communication channel. The argument cid is the channel identification as obtained from osxopen. .RETURNS Value 0 on normal return. .REMARKS System dependencies: -- VMS: SYS$DASSGN, SYS$DELMBX, LIB$SIGNAL ------------------------------------------------------------*/ int cid; /* channel identification */ { if (cid < 0 || cid > MAX_IPCC) { oserror = EINVAL; return (-1); } IPCC[cid].status = CLOSED; if (IPCC[cid].type == LOCAL) { retval = SYS$DELMBX (channel[cid]); if (retval != SS$_NORMAL) LIB$SIGNAL (retval); } retval = SYS$DASSGN (channel[cid]); if (retval != SS$_NORMAL) LIB$SIGNAL (retval); return(0); } int osxread(cid, pbuf, nobytes) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Synchronous read from interprocess communication channel. The argument cid is the channel identification as obtained from osxopen. The function reads nobyt bytes from the channel and put the information into the buffer pointed by pbuf. .RETURNS Upon successful completion a value of 0 is returned. ( The function osxwait must be called after the asynchronous read. ) .REMARKS System dependencies: -- VMS:SYS$QIOW, LIB$SIGNAL ------------------------------------------------------------*/ int cid; /* channel identification */ char *pbuf; /* pointer to input buffer */ int nobytes; /* number of input bytes */ { unsigned short chan; unsigned short func = IO$_READVBLK; unsigned int nobyt; char bzero = 0; unsigned int izero = 0, ifour = 4; chan = channel[cid]; nobyt = (unsigned int)nobytes; if (cid < 0 || cid > MAX_IPCC ) { oserror = EINVAL; return (-1); } if (nobyt <= 0) return(0); /* the server does not wait on I/O - and uses osxinfo for synchronization */ if (IPCC[cid].type == LOCAL) retval = SYS$QIO (ifour, chan, func, &iosb[cid], izero, izero, pbuf, nobyt, izero, izero, izero, izero); /* the clients do an I/O with wait */ else retval = SYS$QIOW (izero, chan, func, &iosb[cid], izero, izero, pbuf, nobyt, izero, izero, izero, izero); if (retval != SS$_NORMAL) LIB$SIGNAL (retval); return(0); } int osxwrite(cid, pbuf, nobytes) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Synchronous write into interprocess communication channel. The argument cid is the channel identification as obtained from osxopen. The function writes nobyt bytes from the the buffer pointed by pbuf into the channel. .RETURNS Upon successful completion a value of 0 is returned. ( The function osxwait must be called after the asynchronous write.) .REMARKS System dependencies: -- VMS:SYS$QIOW, LIB$SIGNAL ------------------------------------------------------------*/ int cid; /* channel identification */ char *pbuf; /* pointer to output buffer */ int nobytes; /* number of output bytes */ { unsigned short chan; unsigned short func = IO$_WRITEVBLK; unsigned int nobyt; char bzero = 0; unsigned int izero = 0; chan = channel[cid]; nobyt = (unsigned int)nobytes; if (cid < 0 || cid > MAX_IPCC) { oserror = EINVAL; return (-1); } if (nobyt > 0) { retval = SYS$QIOW (izero, chan, func, &iosb[cid], izero, izero, pbuf, nobyt, izero, izero, izero, izero); if (retval != SS$_NORMAL) LIB$SIGNAL (retval); } return(0); } int osxinfo(cid, sec, usec) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Gets status of the interprocess communication channel. .RETURNS Upon successful completion a value of 0 is returned. .REMARKS System dependencies: -- UNIX: none ------------------------------------------------------------*/ int cid; /* channel identification */ int sec; /* seconds to wait in osxinfo */ int usec; /* millisecs to wait in osxinfo */ { short int iostat; long int milsecs, time[2]; unsigned int efmask; unsigned int ithree = 3; if (cid < 0 || cid > MAX_IPCC || usec < 0) { oserror = EINVAL; return (-1); } iostat = iosb[cid].cond_value; /* look at status of last read */ if (iostat == SS$_NORMAL) return (DATARDY); /* init mask to just wait for event flag #4 (from the QIO) */ efmask = 16; /* if sec or usec > 0, wait */ if (sec > 0) milsecs = (sec * 1000) + usec; else milsecs = usec; if (milsecs > 0) { time[1] = -1; time[0] = - (10000 * milsecs); retval = SYS$SETIMR(ithree,time,0,0); /* use event flag 3 */ if (retval & BIT_0) efmask = 24; /* set also bit 3 to 1 */ } retval = SYS$WFLOR(ithree,efmask); if (retval != SS$_NORMAL) LIB$SIGNAL(retval); /* now look again */ iostat = iosb[cid].cond_value; /* look at status of last read */ if (iostat == SS$_NORMAL) return (DATARDY); else return (NOCONN); } int osxgetservbyname(service) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Interface to the getservbyname(). .RETURNS The port number, or -1 if no port. .REMARKS Not implemented yet ------------------------------------------------------------*/ char *service; { return(-1); /* struct servent *sp; if ((sp = getservbyname(service,"tcp")) == NULL) return(-1); else return(sp->s_port); */ }