/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1982-2010 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* mkservice varname pathname
* eloop [-t timeout]
* Written by David Korn
* AT&T Labs
*/
static const char mkservice_usage[] =
"[-?\n@(#)$Id: mkservice (AT&T Research) 2001-06-13 $\n]"
"[+NAME? mkservice - create a shell server ]"
"[+DESCRIPTION?\bmkservice\b creates a tcp or udp server that is "
"implemented by shell functions.]"
"\btcp\b or \budp\b protocol is used. \aportno\a is the port "
"number that the service will use.]"
"[+?The shell variable \avarname\a is associated with the service. This "
"variable can have subvariables that keeps the state of all "
"active connections. The functions \avarname\a\b.accept\b, "
"\avarname\a\b.action\b and \avarname\a\b.close\b implement the "
"service as follows:]{"
"[+accept?This function is invoked when a client tries to connect "
"to the service. It is called with an argument which "
"is the file descriptor number associated with the "
"accepted connection. If the function returns a non-zero "
"value, this connection will be closed.]"
"[+action?This function is invoked when there is data waiting "
"to be read from one of the active connections. It is "
"called with the file descriptor number that has data "
"to be read. If the function returns a non-zero "
"value, this connection will be closed.]"
"[+close?This function is invoked when the connection is closed.]"
"}"
"[+?If \avarname\a is unset, then all active connection, and the service "
"itself will be closed.]"
""
"\n"
"\nvarname service_path\n"
"\n"
"[+EXIT STATUS?]{"
"[+0?Success.]"
"[+>0?An error occurred.]"
"}"
"[+SEE ALSO?\beloop\b(1)]"
;
static const char eloop_usage[] =
"[-?\n@(#)$Id: eloop (AT&T Research) 2001-06-13 $\n]"
"[+NAME? eloop - process event loop]"
"[+DESCRIPTION?\beloop\b causes the shell to block waiting for events "
"to process. By default, \beloop\b does not return.]"
"[t]#[timeout?\atimeout\a is the number of milliseconds to wait "
"without receiving any events to process.]"
"\n"
"\n\n"
"\n"
"[+EXIT STATUS?If no timeout is specified, \beloop\b will not return "
"unless interrupted. Otherwise]{"
"[+0?The specified timeout interval occurred.]"
"[+>0?An error occurred.]"
"}"
"[+SEE ALSO?\bmkservice\b(1)]"
;
#include "defs.h"
#include <cmd.h>
#include <error.h>
#include <nval.h>
#define ACCEPT 0
#ifndef O_SERVICE
#endif
static const char* disctab[] =
{
"accept",
"action",
"close",
0
};
struct Service_s
{
short fd;
int refcount;
void *context;
};
static short *file_list;
static int npoll;
static int nready;
static int ready;
static int (*covered_fdnotify)(int, int);
{
register int i;
service_list[fd] = 0;
for(i=0; i < npoll; i++)
{
{
return(1);
}
}
return(0);
}
{
if (covered_fdnotify)
if(fd2!=SH_FDCLOSE)
{
register int i;
service_list[fd1] = 0;
for(i=0; i < npoll; i++)
{
{
return(0);
}
}
}
{
}
return(0);
}
{
{
if(fd>=0)
{
}
}
{
service_list[fd] = 0;
if(r<0)
}
}
{
register int i;
if (fd >= 0)
while(1)
{
if(special)
for(i=0; i < npoll; i++)
{
if(service_list[file_list[i]])
}
#if 1
#endif
errno = 0;
#ifdef DEBUG
#endif
#ifdef DEBUG
for(i=0; i < nready; i++)
#endif
#if 1
#endif
if(nready<=0)
return(errno? -1: 0);
{
ready = 1;
return(fd);
}
}
}
static int service_init(void)
{
return(1);
}
{
static int init;
if (!init)
init = service_init();
}
{
int fd;
if (fd >= 0)
{
if (nq)
{
av[2] = 0;
{
return -1;
}
}
}
return fd;
}
{
int r=0;
if(close)
else
if (nq)
{
av[2] = 0;
}
return r > 0 ? -1 : 1;
}
{
return 0;
}
{
register const char* cp;
register int i;
{
continue;
else
{
if (action)
else
}
}
/* try the next level */
}
{
if (!val)
if (!val)
{
register int i;
{
if(service_list[i]==sp)
{
close(i);
break;
}
}
return;
}
}
{
sizeof(Service_t),
0,
0,
};
{
register char* var;
register char* path;
register int fd;
for (;;)
{
{
case 0:
break;
case ':':
continue;
case '?':
continue;
}
break;
}
{
}
else
return(0);
}
{
for (;;)
{
{
case 0:
break;
case 't':
continue;
case ':':
continue;
case '?':
continue;
}
break;
}
while(1)
{
break;
}
return(errno != 0);
}