IPC Home IPC Manual IPC Examples


ipcts(6)

Miscellaneous IPC Programming Examples

ipcts(6)


NAME

ipcts - the trivial services provided by inetd


DESCRIPTION

The following programming example implements the five trivial services, normally provided by the Internet super-server inetd: echo (RFC 862), time (RFC 868), daytime (RFC 867), chargen (RFC 864), and discard (RFC 863).

All five services are implemented in a single application, using different technics. The echo service is implemented as preforked server, the services chargen and discard as concurrent servers, the daytime service as iterative server, and the time service as iterative server using asynchronous event notification. All five services are accessible in the UNIX domain and in the Internet domain. Both the time and daytime services are implemented using Transaction TCP if supported by the underlying operating system.


SOURCE CODE

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <ipc.h>

static void	Echo(IPC, IpcCbInfo, void*);
static void	Time(IPC, IpcCbInfo, void*);
static void	Chargen(IPC, IpcCbInfo, void*);
static void	Discard(IPC, IpcCbInfo, void*);

int main(void)
{
   IpcCallbackRec	echo_cb    = { Echo,    NULL },
   			time_cb    = { Time,    NULL },
   			chargen_cb = { Chargen, NULL },
   			discard_cb = { Discard, NULL };
   IPC			dt_server, dt_client;
   IpcArg		args[5];
   int			nargs;

   IpcDaemonize();
   IpcOpenLog("ts");

   nargs = 0;
   IpcSetArg(&args[nargs++], IPC_MODE,        IPC_PREFORKED);
   IpcSetArg(&args[nargs++], IPC_PATH,        "/tmp/ts_echo");
   IpcSetArg(&args[nargs++], IPC_SERVICETYPE, IPC_SERVICES);
   IpcSetArg(&args[nargs++], IPC_SERVICE_CB,  &echo_cb);
   if(! IpcOpen("ts_echo", IPC_SERVER, args, nargs))
      IpcLog(LOG_ERR, "IpcOpen(echo): %M, %m"), exit(1);

   nargs = 0;
   IpcSetArg(&args[nargs++], IPC_TTCP,        TRUE);
   IpcSetArg(&args[nargs++], IPC_PATH,        "/tmp/ts_time");
   IpcSetArg(&args[nargs++], IPC_SERVICETYPE, IPC_SERVICES);
   IpcSetArg(&args[nargs++], IPC_CONNECT_CB,  &time_cb);
   if(! IpcOpen("ts_time", IPC_SERVER, args, nargs))
      IpcLog(LOG_ERR, "IpcOpen(time): %M, %m"), exit(1);

   nargs = 0;
   IpcSetArg(&args[nargs++], IPC_TTCP,        TRUE);
   IpcSetArg(&args[nargs++], IPC_PATH,        "/tmp/ts_daytime");
   IpcSetArg(&args[nargs++], IPC_SERVICETYPE, IPC_SERVICES);
   if(! (dt_server = IpcOpen("ts_daytime", IPC_SERVER, args, nargs)) )
      IpcLog(LOG_ERR, "IpcOpen(daytime): %M, %m"), exit(1);

   nargs = 0;
   IpcSetArg(&args[nargs++], IPC_MODE,        IPC_CONCURRENT);
   IpcSetArg(&args[nargs++], IPC_PATH,        "/tmp/ts_chargen");
   IpcSetArg(&args[nargs++], IPC_SERVICETYPE, IPC_SERVICES);
   IpcSetArg(&args[nargs++], IPC_SERVICE_CB,  &chargen_cb);
   if(! IpcOpen("ts_chargen", IPC_SERVER, args, nargs))
      IpcLog(LOG_ERR, "IpcOpen(chargen): %M, %m"), exit(1);

   nargs = 0;
   IpcSetArg(&args[nargs++], IPC_MODE,        IPC_CONCURRENT);
   IpcSetArg(&args[nargs++], IPC_PATH,        "/tmp/ts_discard");
   IpcSetArg(&args[nargs++], IPC_SERVICETYPE, IPC_SERVICES);
   IpcSetArg(&args[nargs++], IPC_SERVICE_CB,  &discard_cb);
   if(! IpcOpen("ts_discard", IPC_SERVER, args, nargs))
      IpcLog(LOG_ERR, "IpcOpen(discard): %M, %m"), exit(1);

   while( (dt_client = IpcSchedule(dt_server, IPC_WRITABLE, IPC_BLOCK)) ) {
      time_t	t = time(NULL);
      char	buf[256];

      (void) snprintf(buf, sizeof(buf), "%s\r\n", ctime(&t));
      (void) IpcSend(dt_client, buf, strlen(buf), IPC_MSG | IPC_EOF);
      IpcClose(dt_client);
   }

   /*NOTREACHED*/
   return 1;
}


static void Echo(IPC ipc, IpcCbInfo info, void *data)
{
   char		buf[BUFSIZ];
   int		n;

   while((n = IpcRecv(ipc, buf, sizeof(buf), 0)) > 0 &&
         IpcSend(ipc, buf, n, IPC_MSG) == n)
      ;
   IpcClose(ipc);
}


static void Time(IPC ipc, IpcCbInfo info, void *data)
{
   struct timeval	tv;
   u_long		secs = 2208988800UL; /* 01.01.1900-01.01.1970 */

   if(gettimeofday(&tv, NULL) == 0)
      secs += tv.tv_sec;

   secs = htonl(secs);
   (void) IpcSend(ipc, &secs, sizeof(secs), IPC_MSG | IPC_EOF);
   IpcClose(ipc);
}


#define	LEN	72
static void Chargen(IPC ipc, IpcCbInfo info, void *data)
{
   struct iovec	iovec[2];
   char		ring[256];
   char		text[LEN];
   char		crlf[2];
   char		*r, *rs, *rm;
   int		i;

   iovec[0].iov_len  = sizeof(text);
   iovec[1].iov_base = crlf;
   iovec[1].iov_len  = sizeof(crlf);

   crlf[0] = '\r';
   crlf[1] = '\n';

   for(rs = rm = ring, i = 0; i < 128; i++)
      if(isprint(i))
	 *rm++ = i;

   (void) memcpy(rm, rs, rm - rs);

   for(r = rs; ; r++) {
      if(r > rm)
	 r += rs - rm;

      iovec[0].iov_base = r;

      if(IpcSendV(ipc, iovec, 2, IPC_MSG) != sizeof(text) + sizeof(crlf))
	 break;
   }
   IpcClose(ipc);
}


static void Discard(IPC ipc, IpcCbInfo info, void *data)
{
   char		buf[BUFSIZ];

   while(IpcRecv(ipc, buf, sizeof(buf), 0) > 0)
      ;
   IpcClose(ipc);
}



IPC Home IPC Manual IPC Examples

Edited by: Mathias Etter; last change: Aug 05, 1999; revision: IPC Version 1.8.2; converted to HTML: Aug 10, 1999
Copyright © 1999 Mathias Etter, University of Ulm, Germany