ipcts(6) |
Miscellaneous IPC Programming Examples |
ipcts(6) |
ipcts - the trivial services provided by inetd
The following programming example implements the five trivial services, normally provided by the Internet super-serverinetd
: 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.
#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); }