Newsgroups: fj.os.misc
Path: galaxy.trc.rwcp.or.jp!coconuts.jaist!wnoc-tyo-news!aist-nara!odins-suita!nuis!news.cc.nagoya-u.ac.jp!nfeed.gw.nagoya-u.ac.jp!vega2!arisawa
From: arisawa@vega.aichi-u.ac.jp (Kenji Arisawa)
Subject: Re: Plan9
Sender: news@vega2.aichi-u.ac.jp (News Master)
Message-ID: <EJ9685.I5@vega2.aichi-u.ac.jp>
Date: Fri, 7 Nov 1997 01:45:41 GMT
Lines: 195
References: <EJ7vGr.7o0@vega2.aichi-u.ac.jp>
Nntp-Posting-Host: vega
Organization: Aichi University Computer Center, Aichi University, Aichi, Japan.
X-Newsreader: mnews [version 1.19] 1995-07/21(Fri)
Xref: galaxy.trc.rwcp.or.jp fj.os.misc:1095
X-originally-archived-at: http://galaxy.rwcp.or.jp/text/cgi-bin/newsarticle2?ng=fj.os.misc&nb=1095&hd=a
X-reformat-date: Mon, 18 Oct 2004 15:18:22 +0900
X-reformat-comment: Tabs were expanded into 4 column tabstops by the Galaxy's archiver. See http://katsu.watanabe.name/ancientfj/galaxy-format.html for more info.

$BM-_7(B@$B0&CNBg3X$G$9(B

$B4d:,$5$s(B:
>$B$b$7$+$9$k$H!"(Bu9fs$B$N%=!<%9$r$$$8$C$F!"(Bsocket$B$N%*%W%7%g%s$r?'!9%3(B
>$B%M%/%j2s$9I,MW$,$"$k$+$b$7$l$^$;$s$M(B...
$BC<Kv$K9T57$NNI$$=*$o$jJ}$rMW5a$7$J$$$G!"8e;OKv$O%5!<%P$,9T$&$N$,K\L?(B
$B$J$N$G$7$g$&$M!#$=$3$G(Bsocket$B%*%W%7%g%s$H$7$F9M$($i$l$k$N$O(B
setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on))
$B$,9M$($i$l(B
$B<B:]$K(B u9fs $B$K$O$3$N%*%W%7%g%s$,@_Dj$5$l$F$$$k$N$G$9$,!"(B.... 

man socket $B$+$i$N0zMQ(B
       SO_KEEPALIVE $B$,(B
      $B%;%C%H$5$l$F$$$F!"@\B3$,(B2$B;~4V%"%$%I%k>uBV$K$"$k>l9g!"(B TCP $B%W%m%H%3%k$O(B
      $B@\B3$,@8$-$F$$$k$+$I$&$+$r3NG'$9$k$?$a$K!"(B75$BICKh$K(B "keepalive"$B%Q%1%C%H(B
      $B$rAw$j$^$9!#$3$l$i$NE>Aw$O%f!<%6!<$K$O8+$($J$$$?$a!"(B recv()  $B%3!<%k$G(B
      $BFI$`$3$H$O$G$-$^$;$s!#%j%b!<%H!&%7%9%F%`$,(B10$BJ,0JFb$K1~Ez$7$J$$>l9g(B(
      $B$9$J$o$A!"(B"keepalive"$B%Q%1%C%H$,(B8$B2sAw$i$l$?8e(B)$B!"<!$N%=%1%C%H%3!<%k(B($BNc$((B
      $B$P(B recv())  $B$O%(%i!<$K$J$j!"(B [ETIMEDOUT] $B$,(B errno $B$K%;%C%H$5$l$^$9!#(B

2$B;~4V$OD9$9$.$k$N$G$9$M!&!&(B
$B$3$N;~4V$rNc$($P(B5$BJ,$K=L$a$k$3$H$O2DG=$J$N$G$7$g$&$,!"(B
$B$I$3$r$I$&$$$8$C$?$iNI$$$+:#$N$H$3$mJ,$+$j$^$;$s!#(B


$B4d:,$5$s$OEvA3$b$&:n$C$F$*$i$l$k$H;W$$$^$9$,!"KM$,;H$C$F$$$k(B
listen 
$B$H8@$&%W%m%0%i%`$rE:IU$7$FCV$-$^$9!#$J$+$J$+=EJu$7$F$$$^$9!#(B


/*
*listen - a user level inetd
*usage: listen [-ehv] [-p proto] port path args ...
*options:
*-h: help
*-v: verbose
*-e: restrain stderr of the invoked process to be connected to network.
*    This option may be usefull for debugging.
*-p: protocol is currently only tcp and udp
*compile:
*cc -o listen listen.c
*examples:
*listen -ev 4000 ~/bin/uu9fs uu9fs -l .
*port number:
*0 - 1023: system port
*1024 -  : user's port
*bugs:
*proto is currently only tcp and udp
*
*coded by
*Kenar ( Kenji Arisawa )
*E-mail: arisawa@aichi-u.ac.jp
*
*Ref:
*W.R.Stivens:"UNIX Network Programming", p.339(Jap.ed.)
*/

/* MEMO
*  listen 4000 sh
*  does not work because of ^M that is sent by terminal
*  A option to cut ^M may be required.
*/


#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <ctype.h>

typedef unsigned char uchar;


#define YES (1)
#define NO(0)
#define ERR (-1)

void usage()
{fputs("usage: listen [-ehv] [-p proto] port path args ...\n",stderr);
exit(0);
}

void err(char *s)
{perror(s);
exit(3);
}

/* do something */
void doit(int s, char *path, char *argv[], int e)
/* s: socket
path: program path to be invoked
args: arguments to pass the program
e: eflag - restrain dup stderr
*/
{/* redirect s to 0,1,2 */
dup2(s,0);
dup2(s,1);
if(!e) dup2(s,2);
close(s);
execv(path,argv);
/* never reached in success */
}

void debug(char *msg,struct sockaddr_in *sa)
{uchar *s;
structin_addr *p;
p = &(sa->sin_addr);
s = (char *)p;
fprintf(stderr,"%s\n",msg);
fprintf(stderr,"family: %d\n",sa->sin_family);
fprintf(stderr,"port: %d\n",sa->sin_port);
fprintf(stderr,"addr: %d.%d.%d.%d\n",s[0],s[1],s[2],s[3]);
}

int main(int argc, char *argv[])
{int ch;
int vflag=0;
int eflag=0;
char *proto=0; /* protocol */
int s; /* socket */
int ns; /* new socket */
int clilen;
struct sockaddr_in serv_addr, cli_addr;
int status;
int port=0;
int i;
char *path=0;
char **args=0;
extern int optind;
extern char *optarg;

while ((ch = getopt(argc,argv,"p:ehv")) != EOF){
switch (ch){
case 'e':
eflag = YES;
break;
case 'h':
usage();
case 'v':
vflag = YES;
break;
case 'p':
proto = optarg;
break;
default:
usage();
}
}
i = optind;
if(i < argc) port = atoi(argv[i++]);
if(i < argc) path = argv[i++];
if(i < argc) args = &argv[i];

if(!port || !path || !args) usage();

if(!proto || strcmp(proto,"tcp") == 0)
s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
else if(strcmp(proto,"udp") == 0)
s = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
else
err("unknown protocol type");

if(s == ERR) err("socket not open");

memset((char *)&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(port);
status = bind(s,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
if(status == ERR) err("bind error");

if(vflag){
fprintf(stderr,"path=%s\n",path);
fprintf(stderr,"args:");
for(i = 0; args[i]; i++) fprintf(stderr," %s",args[i]);
fprintf(stderr,"\n");
debug("started",&serv_addr);
}
status = listen(s,5);
if(status == ERR) err("listen error");for(;;){
clilen = sizeof(cli_addr);
ns = accept(s,(struct sockaddr *)&cli_addr,&clilen);
if(ns == ERR) err("accept error");
if(vflag) debug("excited",&cli_addr);

if(fork() == 0) { /* child process */
close(s);
doit(ns,path,args,eflag); /* do something */
exit(0);
}

close(ns);
}
}
