home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
octa21fs.zip
/
octave
/
mkfifo
/
nmpserv.c
< prev
Wrap
C/C++ Source or Header
|
2000-01-15
|
8KB
|
360 lines
/*
** ****************************************************************************
** This is the server the mkfifo command connects to. This program creates
** a named pipe which is used for communication between the mkfifo routine
** and the server. The mkfifo sends the name of the named pipe, which should
** be created and then receives the return code.
** (c) Klaus Gebhardt, 1997
** ****************************************************************************
*/
/*
** ****************************************************************************
** This was written for the OS/2 port of Octave, but it is not part of Octave!
** You can use the code UNMODIFIED. If you think changes are necessary,
** please send me a mail (gebhardt@crunch.ikp.physik.th-darmstadt.de).
** Thanks,
** Klaus Gebhardt
** ****************************************************************************
*/
#include "mkfifo.h"
#include "nmp.h"
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* List of all named pipes */
int _named_pipes_ = 0;
_named_pipe_ *_nmp_list_ = NULL;
/* For accessing the pipe. */
static APIRET apiret;
static HPIPE hpipe;
static ULONG count, dummy = 0;
/* Name and access mode of the pipe */
static char name[1024];
static mode_t mode;
static int result;
/*
** Add a named pipe to the list of the already existing named pipes and
** a thread for it. Return 0 on success, -1 on error out of memory, -2 unable
** to start the thread.
*/
static int add_to_nmp_list ()
{
void *next;
void *prev;
_named_pipe_ *nmp;
nmp = (_named_pipe_ *) malloc (sizeof(_named_pipe_));
if (!nmp) return -1;
nmp->name = strdup (name);
if (!nmp->name) return -1;
nmp->mode = mode;
/*
** Start a new thread to move the data from one end of the pipe
** to the other.
*/
DosResetEventSem (_hev_, &dummy);
nmp->tid = _beginthread (nmp_thread, NULL, 65536, (void *) nmp);
DosWaitEventSem (_hev_, SEM_INDEFINITE_WAIT);
if ((nmp->tid == -1) || (nmp->result == -1))
{
free ((char *) nmp->name);
free (nmp);
return -1;
}
prev = NULL;
next = (void *) _nmp_list_;
while (next != NULL)
{
prev = next;
next = ((_named_pipe_ *) next)->next;
}
nmp->prev = prev;
nmp->next = NULL;
if (prev) ((_named_pipe_ *) prev)->next = nmp;
else _nmp_list_ = nmp;
_named_pipes_++;
return 0;
}
/*
** Search for the named pipe, which name is given in the argument, and
** return a pointer to its named pipe structure. Return NULL on error.
*/
static _named_pipe_ *lookup_nmp_list ()
{
void *next;
void *prev;
prev = NULL;
next = (void *) _nmp_list_;
while (next != NULL)
{
if (!stricmp (((_named_pipe_ *) next)->name, name))
return ((_named_pipe_ *) next);
prev = next;
next = ((_named_pipe_ *) next)->next;
}
return ((_named_pipe_ *) NULL);
}
/* Remove a named pipe from the list. */
static int remove_nmp_from_list ()
{
void *next;
void *prev;
_named_pipe_ *nmp;
nmp = lookup_nmp_list ();
if (nmp)
{
prev = nmp->prev;
next = nmp->next;
if (prev) ((_named_pipe_ *) prev)->next = next;
else _nmp_list_ = next;
if (next) ((_named_pipe_ *) next)->prev = prev;
nmp->tid = -1;
_named_pipes_--;
free (nmp);
return 0;
}
return -1;
}
/* Replace all '/' in name with '\\' */
static void os2_path ()
{
char *c;
c = name;
while (*c)
{
if ((*c) == '/') (*c) = '\\';
c++;
}
}
/* Create a new named pipe. */
static int create_nmp ()
{
int rc;
apiret = DosRead (hpipe, &mode, sizeof(mode), &count);
if (apiret || (count != sizeof(mode))) return -1;
apiret = DosRead (hpipe, name, sizeof(name), &count);
if (apiret) return -1;
os2_path ();
if (lookup_nmp_list ()) rc = -1;
else rc = add_to_nmp_list ();
apiret = DosWrite (hpipe, &rc, sizeof(rc), &count);
if (apiret || (count != sizeof(rc))) return -1;
return 0;
}
/* Remove one named pipe. */
static int remove_nmp ()
{
int rc;
apiret = DosRead (hpipe, name, sizeof(name), &count);
if (apiret) return -1;
os2_path ();
rc = remove_nmp_from_list ();
apiret = DosWrite (hpipe, &rc, sizeof(rc), &count);
if (apiret || (count != sizeof(rc))) return -1;
return 0;
}
/* Send a list of all active named pipes to the client. */
static int list_nmps ()
{
_named_pipe_ *nmp;
int i, j;
apiret = DosWrite (hpipe, &_named_pipes_, sizeof(_named_pipes_), &count);
if (apiret || (count != sizeof(_named_pipes_))) return -1;
nmp = _nmp_list_;
for (i=0; i<_named_pipes_; i++)
{
apiret = DosRead (hpipe, &j, sizeof(j), &count);
if (apiret || (count != sizeof(j)) || (i != j)) return -1;
apiret = DosWrite (hpipe, nmp->name, strlen (nmp->name) + 1, &count);
if (apiret || (count != strlen (nmp->name) + 1)) return -1;
nmp = (_named_pipe_ *) nmp->next;
}
return 0;
}
/* Tell how many named pipes are closed, before exiting. */
static int close_server ()
{
apiret = DosWrite (hpipe, &_named_pipes_, sizeof(_named_pipes_), &count);
if (apiret || (count != sizeof(_named_pipes_))) return -1;
return 0;
}
/* Unknown command is sent to the server. */
static int unknown_cmd ()
{
int error = -1;
apiret = DosWrite (hpipe, &error, sizeof(error), &count);
if (apiret || (count != sizeof(error))) return -1;
return 0;
}
void APIENTRY cleanup_on_exit (ULONG ulTermCode)
{
_named_pipe_ *nmp;
nmp = _nmp_list_;
while (_named_pipes_ > 0)
{
strcpy (name, nmp->name);
os2_path ();
remove_nmp_from_list ();
nmp = (_named_pipe_ *) nmp->next;
}
DosExitList (EXLST_EXIT, 0);
}
/* The main program for the server. */
int main (int argc, char *argv[])
{
int mkfifo_cmd;
int i, noexit = 0;
if (argc > 2) exit (-1);
if (argc == 2)
{
if (stricmp ("--noexit", argv[1])) exit (-1);
noexit = 1;
}
DosExitList (EXLST_ADD, cleanup_on_exit);
DosCreateEventSem (NULL, &_hev_, 0L, (BOOL32) 0);
/*
** Create the named pipe for communication between mkfifo and the server.
** This must be a two-way message pipe.
*/
apiret = DosCreateNPipe (_MKFIFO_NAMED_PIPE_, &hpipe, NP_ACCESS_DUPLEX,
NP_WAIT | NP_TYPE_MESSAGE | NP_READMODE_MESSAGE |
0x01, 1024L, 1024L, -1);
if (apiret == 231) return 1;
if (apiret != 0) return -1;
do
{
if (DosConnectNPipe (hpipe)) goto error;
apiret = DosRead (hpipe, &mkfifo_cmd, sizeof(mkfifo_cmd), &count);
if (apiret || (count != sizeof(mkfifo_cmd))) goto error;
switch (mkfifo_cmd)
{
case _MKFIFO_CREATE_NMP_:
result = create_nmp ();
break;
case _MKFIFO_REMOVE_NMP_:
result = remove_nmp ();
break;
case _MKFIFO_LIST_NMPS_:
result = list_nmps ();
break;
case _MKFIFO_EXIT_SERVER_:
result = close_server ();
break;
default:
result = unknown_cmd ();
break;
}
if (DosDisConnectNPipe (hpipe)) goto error;
}
while ((mkfifo_cmd != _MKFIFO_EXIT_SERVER_) &&
((_named_pipes_ > 0) || noexit));
DosClose (hpipe);
return 0;
error:
DosDisConnectNPipe (hpipe);
DosClose (hpipe);
return result;
}