V10/cmd/limiter.c
#include <sys/types.h>
#include <sys/filio.h>
#include <stdio.h>
#include <sys/stream.h>
extern int conn_ld;
extern int mesg_ld;
#define msglen(mp) ((mp)->losize + ((mp)->hisize<<8))
int count; /* max connections */
fd_set serving; /* clients being served */
int nserving;
fd_set waiting; /* clients waiting */
int nwaiting;
int fd; /* mounted fd */
main(ac, av)
int ac;
char *av[];
{
if(ac!=3)
die("usage: %s path count\n", av[0]);
fd=mountit(av[1]);
count=atoi(av[2]);
if(count<=0)
die("usage: %s path count\n", av[0]);
detach();
doit();
}
doit()
{
int i, n;
fd_set afds;
FD_ZERO(serving);
for(;;){
afds=serving;
FD_SET(fd, afds);
switch(n=select(NOFILE, &afds, 0, 10000L)){
case -1:
/* there's a bad fd in the group */
afds=serving;
for(i=0; i<NOFILE; i++)
if(FD_ISSET(i, afds))
dropclient(i);
break;
case 0:
/* timeout, try again */
break;
default:
/* look for new clients */
if(FD_ISSET(fd, afds)){
request();
n--;
}
/* someone needs servicing */
for(i=0; n && i<NOFILE; i++){
if(FD_ISSET(i, afds)){
dropclient(i);
n--;
}
}
break;
}
}
}
newclient(cfd)
int cfd;
{
FD_SET(cfd, waiting);
nwaiting++;
wtos();
}
dropclient(cfd)
int cfd;
{
FD_CLR(cfd, serving);
nserving--;
close(cfd);
wtos();
}
wtos()
{
int i=0;
struct mesg m;
while(nwaiting && nserving<count){
for(;i<NOFILE;i++){
if(FD_ISSET(i,waiting)){
nwaiting--;
nserving++;
FD_SET(i, serving);
FD_CLR(i, waiting);
m.losize = 0;
m.hisize = 0 >> 8;
m.type = M_HANGUP;
m.magic = MSGMAGIC;
if(ioctl(i, FIOACCEPT, (void *)0)<0
|| ioctl(i, FIOPUSHLD, &mesg_ld)<0
|| write(i, &m, sizeof(m))!=sizeof(m)){
close(i);
FD_CLR(i, serving);
nserving--;
continue;
}
}
}
}
}
request()
{
struct passfd pass;
if(ioctl(fd, FIORCVFD, &pass)<0)
abort();
newclient(pass.fd);
}
mountit(path)
char *path;
{
int pfd[2];
/* make a node to mount onto */
if (access(path,0)<0 && creat(path, 0666)<0)
die("can't creat %s\n", path);
/* get the stream to mount */
if (pipe(pfd) < 0)
die("out of pipes\n", 0);
if (ioctl(pfd[1], FIOPUSHLD, &conn_ld) < 0)
die("can't push line discipline\n", 0);
/* mount */
if (fmount(3, pfd[1], path, 0) < 0)
die("can't mount onto %s\n", path);
umask(0);
chmod(path, 0666);
close(pfd[1]);
return pfd[0];
}
detach()
{
switch(fork()){
case -1:
die("can't fork\n", 0);
case 0:
break;
default:
exit(0);
}
for(fd=0; fd<NSYSFILE; fd++)
close(fd);
setpgrp(getpid(), getpid());
}
die(a, b)
char *a;
{
fprintf(stderr, a, b);
exit(1);
}