This is fayca.c in view mode; [Download] [Up]
/* FAYCA - For All You Chat Addicts, simple chat system. */
/* Written by Werner Almesberger almesber@nessie.cs.id.ethz.ch */
/* */
/* When Who Vers What */
/* 18-DEC-1991 WA 0.09 Started logging changes. Fixed use of */
/* SO_REUSEADDR. */
/* 27-DEC-1991 WA 0.10 ANSIfied the source. Fixed a memory leak. Added */
/* sticky first nicks. Added /J, /T, $FAYCA/announce, */
/* $FAYCA/motd and $FAYCA/journal. */
/* 28-DEC-1992 WA 0.11 Ported to Linux (with slightly defective TELNET) */
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef NEXT /* fix this all! */
#define PATH_MAX 1024
#include <sys/types.h>
#include <sys/uio.h>
#include <signal.h>
#else
#include <malloc.h>
#endif
#include <netinet/in.h>
#include <arpa/telnet.h>
#ifdef linux
#include <linux/time.h>
#include <linux/types.h>
#endif
#define SYS_NAME "Fayca" /* system name */
#define ENTRY_CHANNEL "4" /* login channel */
#define LOGIN "(login)" /* login nick name */
#define MAX_ID 16 /* maximum length of a nick name or a channel name */
#define TERM_WIDTH 79 /* maximum usable terminal width */
#define MAX_LINE TERM_WIDTH /* maximum input line length */
#define PORT 1991 /* port number */
#define MAX_USERS 8 /* maximum number of simultaneous users */
#define JOURNAL_LOW 150 /* journal cache dimensions */
#define JOURNAL_HIGH 250
#define JOURNAL_MAX 200 /* maximum request size (entries) */
#define JOURNAL_DFL 10 /* default request size */
#define READ_CHUNK 1024 /* message read block size */
#define REJECT "Sorry, the maximum user limit has been reached."
#define MAX_JOU_TYPE 10 /* journal type name length */
#define JOU_SIGNON "Signon"
#define JOU_SIGNOFF "Signoff"
#define JOU_DISCONN "Disconnect"
enum state {s_normal,s_iac,s_do,s_dont,s_will,s_wont,s_esc,s_csi};
typedef struct _user {
char *first_nick,*nick,*channel;
char buffer[MAX_LINE+1],prev[MAX_LINE+1];
char *eol,*cursor;
enum state state;
int socket,dead;
struct _user *next;
} USER;
typedef struct _journal {
char type[MAX_JOU_TYPE+1];
char date[15+1];
char nick[MAX_ID+1];
} JOURNAL;
USER *users;
JOURNAL cache[JOURNAL_HIGH],result[JOURNAL_MAX];
int port,user_count = 0,jou_file = 0,jou_size = 0;
char *announce = NULL,*motd = NULL,*reject = NULL;
static void sys_tell(USER *user,char *msg);
static void signoff(USER *user,int abort);
static void crash(char *msg)
{
fprintf(stderr,"CRASH: %s\n",msg);
exit(1);
}
static int is(char *a,char *b)
{
while (*a || *b) {
if ((islower(*a) ? *a : tolower(*a)) != (islower(*b) ? *b :
tolower(*b))) return 0;
a++;
b++;
}
return 1;
}
static int contains(char *a,char *b)
{
char *walk_a,*walk_b;
if (!*b) return 1;
while (*a) {
for (walk_a = a,walk_b = b; *walk_a && *walk_b; walk_a++,walk_b++)
if ((islower(*walk_a) ? *walk_a : tolower(*walk_a)) !=
(islower(*walk_b) ? *walk_b : tolower(*walk_b))) break;
if (!*walk_b) return 1;
a++;
}
return 0;
}
static void journal_add(char *type,char *nick)
{
int size,count;
time_t now;
if (jou_size == JOURNAL_HIGH) {
if (jou_file) {
if (write(jou_file,cache,size = sizeof(JOURNAL)*(JOURNAL_HIGH-
JOURNAL_LOW)) == size) jou_size -= JOURNAL_HIGH-JOURNAL_LOW;
else {
close(jou_file);
jou_file = 0;
}
}
if (!jou_file) jou_size--;
for (count = 0; count < jou_size; count++)
memcpy(&cache[count],&cache[count+(JOURNAL_HIGH-jou_size)],
sizeof(JOURNAL));
}
strcpy(cache[jou_size].type,type);
time(&now);
strncpy(cache[jou_size].date,ctime(&now)+4,15);
cache[jou_size].date[15] = 0;
strcpy(cache[jou_size].nick,nick);
jou_size++;
}
static int journal_scan(int limit,char *str)
{
int current,walk;
current = JOURNAL_MAX-1;
for (walk = jou_size-1; walk >= 0; walk--) {
if (contains(cache[walk].nick,str) || contains(cache[walk].date,str)
|| contains(cache[walk].type,str)) {
memcpy(&result[current],&cache[walk],sizeof(JOURNAL));
current--;
if (!--limit) return 0;
}
}
/* ... */
return limit;
}
static int journal_get(int limit,char *str)
{
int remaining,count;
if ((remaining = journal_scan(limit,str)) == limit) return 0;
for (count = 0; count < limit-remaining; count++)
memcpy(&result[count],&result[count+remaining+(JOURNAL_MAX-limit)],
sizeof(JOURNAL));
return limit-remaining;
}
static int name_okay(USER *user,char *name)
{
if (name == NULL || !*name) {
sys_tell(user,"Name is missing");
return 0;
}
if (strlen(name) > MAX_ID) {
sys_tell(user,"Name is too long");
return 0;
}
while (*name) {
if (isalnum(*name) || *name == '_' || *name == '-' || *name == '&' ||
*name == '.') name++;
else {
sys_tell(user,"Invalid characters in name");
return 0;
}
}
return 1;
}
static void remove_user(USER *user)
{
USER **walk;
walk = &users;
while (*walk != user) walk = &(*walk)->next;
*walk = user->next;
if (user->nick) {
free(user->nick);
if (user->nick != user->first_nick) free(user->first_nick);
}
free(user);
user_count--;
}
static void join_channel(USER *user,char *channel)
{
USER *walk;
for (walk = users; walk; walk = walk->next)
if (walk->channel && is(channel,walk->channel)) break;
if (walk) user->channel = walk->channel;
else {
if ((user->channel = malloc(strlen(channel)+1)) == NULL)
crash("Out of memory");
strcpy(user->channel,channel);
}
}
static void leave_channel(USER *user)
{
USER *walk;
for (walk = users; walk; walk = walk->next)
if (walk != user && walk->channel && is(walk->channel,user->channel))
break;
if (walk == NULL) free(user->channel);
user->channel = NULL;
}
static void output(USER *user,char *msg)
{
int len;
if (write(user->socket,msg,len = strlen(msg)) < len) signoff(user,1);
}
static void send_msg(USER *user,char *prefix,char *msg,int *left)
{
char temp[MAX_LINE+MAX_LINE];
int len;
len = strlen(strcat(strcat(strcpy(temp,prefix)," "),msg));
while (len < *left) temp[len++] = ' ';
temp[len] = 0;
*left = 0;
strcat(temp,"\r\n");
output(user,temp);
}
static void send_user(USER *user,char *prefix,char *msg)
{
char *here,*next,copy;
char temp[MAX_LINE+1];
int p_len,left;
int from_end,from_beg;
if (user->dead) return;
if (left = user->eol-user->buffer) output(user,"\r");
p_len = strlen(prefix);
while (strlen(msg)+p_len+2 >= TERM_WIDTH) {
for (here = msg+TERM_WIDTH-2-p_len; here > msg && *here != ' ';
here--);
if (here != msg) next = here+1;
else {
here = msg+TERM_WIDTH-2-p_len;
next = here+1;
}
copy = *(here+1);
*(here+1) = 0;
send_msg(user,prefix,msg,&left);
*(here+1) = copy;
msg = next;
}
send_msg(user,prefix,msg,&left);
if (user->buffer != user->eol) {
*user->eol = 0;
output(user,user->buffer);
if (from_end = user->eol-user->cursor) {
from_beg = user->cursor-user->buffer+1;
if (from_end > from_beg) {
copy = *user->cursor;
*user->cursor = 0;
output(user,"\r");
output(user,user->buffer);
*user->cursor = copy;
}
else {
memset(temp,8,from_end);
temp[from_end] = 0;
output(user,temp);
}
}
}
}
static void send_channel(char *channel,char *prefix,char *msg,USER *except)
{
USER *walk;
for (walk = users; walk; walk = walk->next)
if (walk != except && walk->channel && (channel == NULL ||
is(channel,walk->channel))) send_user(walk,prefix,msg);
}
static void sys_tell(USER *user,char *msg)
{
char prefix[MAX_ID+5];
sprintf(prefix,"|*%s*|",SYS_NAME);
send_user(user,prefix,msg);
}
static void sys_say(char *channel,char *msg,USER *exclude)
{
char prefix[MAX_ID+5];
sprintf(prefix,"|-%s-|",SYS_NAME);
send_channel(channel,prefix,msg,exclude);
}
static void tell(USER *from,USER *to,char *msg)
{
char prefix[MAX_ID+5];
sprintf(prefix,"<*%s*>",from->nick);
send_user(to,prefix,msg);
}
static void say(USER *from,char *msg)
{
char prefix[MAX_ID+3];
sprintf(prefix,"<%s>",from->nick);
send_channel(from->channel,prefix,msg,from);
}
static void signoff(USER *user,int abort)
{
char msg[MAX_LINE];
if (user->channel) {
sprintf(msg,"%s has left the %s system%s",user->nick,SYS_NAME,abort ?
" (disconnected)" : "");
sys_say(NULL,msg,abort ? user : NULL);
if (abort) journal_add(JOU_DISCONN,user->first_nick);
else journal_add(JOU_SIGNOFF,user->first_nick);
}
if (abort) shutdown(user->socket,2);
close(user->socket);
if (user->channel) leave_channel(user);
if (abort) user->dead = 1;
else remove_user(user);
}
static void help(USER *user)
{
sys_tell(user,"COMMANDS");
sys_tell(user," /Channel channel change channel");
sys_tell(user," /Exit leave the system");
sys_tell(user," /Help this list");
sys_tell(user," /Journal [limit,][string] list last logins");
sys_tell(user," /Nick nick change your nick name");
sys_tell(user," /Show show currently logged in users");
sys_tell(user," /Time show current time");
sys_tell(user," /Whisper user msg send secret message to user");
sys_tell(user,"KEYS");
sys_tell(user," ^A home, ^B back, ^E end of line, ^F forwards, ^H erase,");
sys_tell(user," ^P previous line, ^R redraw, ^U and ^X erase line.");
}
static void show(USER *user)
{
USER *walk;
char fmt_same[40],fmt_diff[40],msg[MAX_LINE];
sprintf(fmt_same,"%%-%ds %%%ds %%-%ds%%s",MAX_ID,MAX_ID+2,MAX_ID);
sprintf(fmt_diff,"%%-%ds (%%s)%%-%ds %%-%ds%%s",MAX_ID,MAX_ID,MAX_ID);
for (walk = users; walk; walk = walk->next) {
if (walk->nick == NULL || is(walk->nick,walk->first_nick))
sprintf(msg,fmt_same,walk->nick ? walk->nick : LOGIN,"",
walk->channel ? walk->channel : "",walk->dead ? " (dead)" : "");
else {
sprintf(fmt_diff,"%%-%ds (%%s)%%-%ds%%-%ds%%s",MAX_ID,MAX_ID+1-
strlen(walk->first_nick),MAX_ID);
sprintf(msg,fmt_diff,walk->nick,walk->first_nick,"",walk->channel,
walk->dead ? " (dead)" : "");
}
sys_tell(user,msg);
}
}
static void channel(USER *user,char *channel)
{
char msg[MAX_LINE];
if (!name_okay(user,channel)) return;
if (is(channel,user->channel)) return;
sprintf(msg,"%s has left this channel",user->nick);
sys_say(user->channel,msg,user);
leave_channel(user);
join_channel(user,channel);
sprintf(msg,"%s has joined this channel",user->nick);
sys_say(channel,msg,user);
sprintf(msg,"You're now on channel %s",channel);
sys_tell(user,msg);
}
static void nick(USER *user,char *nick)
{
char msg[MAX_LINE];
USER *walk;
if (!name_okay(user,nick)) return;
for (walk = users; walk; walk = walk->next)
if (walk->nick && is(walk->nick,nick)) {
sys_tell(user,"This nick is already in use");
return;
}
sprintf(msg,"%s is now %s",user->nick,nick);
if (user->nick != user->first_nick) free(user->nick);
if ((user->nick = malloc(strlen(nick)+1)) == NULL) crash("Out of memory");
strcpy(user->nick,nick);
sys_say(user->channel,msg,NULL);
}
static void whisper(USER *user,char *arg)
{
USER *walk;
char *msg,*fix;
if (arg == NULL) msg = fix = NULL;
else {
if (msg = fix = strchr(arg,' ')) {
*(fix = msg++) = 0;
while (*msg == ' ') msg++;
if (!*msg) msg = NULL;
}
}
if (msg == NULL) {
if (fix) *fix = ' ';
sys_tell(user,"Two arguments expected");
return;
}
for (walk = users; walk; walk = walk->next)
if (walk->nick && is(walk->nick,arg)) break;
*fix = ' ';
if (walk) tell(user,walk,msg);
else sys_tell(user,"No such user");
}
static void journal(USER *user,char *arg)
{
int items,count,limit = JOURNAL_DFL;
char fmt[40],buffer[MAX_LINE+1];
char *str,*here;
if (arg == NULL) str = "";
else {
if ((here = strchr(arg,',')) == NULL) str = arg;
else {
limit = atoi(arg);
if (limit <= 0 || limit > JOURNAL_MAX) {
sys_tell(user,"Invalid limit");
return;
}
for (str = here+1; *str && *str == ' '; str++);
}
}
if (!(items = journal_get(limit,str))) {
sys_tell(user,"No entries found");
return;
}
sprintf(fmt,"%%s, %%-%ds %%s",MAX_JOU_TYPE);
for (count = 0; count < items; count++) {
sprintf(buffer,fmt,result[count].date,result[count].type,
result[count].nick);
sys_tell(user,buffer);
}
}
static void c_time(USER *user)
{
time_t now;
char buffer[MAX_LINE+1];
char *here;
time(&now);
strcpy(buffer,ctime(&now));
if (here = strchr(buffer,'\n')) *here = 0;
sys_tell(user,buffer);
}
static void error(USER *user)
{
sys_tell(user,"Unknown command. Enter /Help for a list of commands.");
}
static void action(USER *user, char *arg)
{
char buffer[MAX_LINE+1];
if(arg == (char *)0) {
sprintf(buffer, "%s erweist sich als FAYCA-Frischling.", user->nick);
} else {
sprintf(buffer, "%s %s", user->nick, arg);
}
send_channel(user->channel, "***", buffer, (USER *)0);
}
static void interpret(USER *user,char *line)
{
char cmd,*arg;
if (!*line) return;
if (*line != '/') say(user,line);
else {
cmd = *(line+1);
if (islower(cmd)) cmd = toupper(cmd);
if (arg = strchr(line,' ')) {
while (*arg == ' ') arg++;
if (!*arg) arg = NULL;
}
switch (cmd) {
case '?':
case 'H': help(user);
break;
case 'S': show(user);
break;
case 'C': channel(user,arg);
break;
case 'N': nick(user,arg);
break;
case 'W': whisper(user,arg);
break;
case 'J': journal(user,arg);
break;
case 'T': c_time(user);
break;
case 'E': signoff(user,0);
break;
case 'A': action(user, arg);
break;
default: error(user);
}
}
}
static void process(USER *user,char *line)
{
USER *walk;
char msg[MAX_LINE];
if (user->nick) interpret(user,line);
else {
if (*line == '/') {
if (line[1] == 's' || line[1] == 'S') {
show(user);
return;
}
if (line[1] == 'e' || line[1] == 'E') {
signoff(user,0);
return;
}
}
if (!name_okay(user,line)) return;
for (walk = users; walk; walk = walk->next)
if (walk->nick && is(walk->nick,line)) {
sys_tell(user,"This nick is already in use");
return;
}
if ((user->nick = user->first_nick = malloc(strlen(line)+1)) == NULL)
crash("Out of memory");
strcpy(user->nick,line);
if (motd) output(user,motd);
join_channel(user,ENTRY_CHANNEL);
sprintf(msg,"%s has entered the %s system on channel %s",line,
SYS_NAME,ENTRY_CHANNEL);
sys_say(NULL,msg,NULL);
journal_add(JOU_SIGNON,line);
}
}
static void cleanup(void)
{
USER *walk,*next;
for (walk = users; walk; walk = next) {
next = walk->next;
if (walk->dead) remove_user(walk);
}
}
static void accept_new(void)
{
USER *user;
int size,socket;
char echo[7];
size = 0;
if ((socket = accept(port,NULL,&size)) < 0) perror("accept");
#ifndef linux
if (fcntl(socket,F_SETFL,FNDELAY) < 0) perror("fcntl");
#else
if (fcntl(socket,F_SETFL,O_NONBLOCK) < 0) perror("fcntl");
#endif
if (user_count == MAX_USERS || reject) {
write(socket,reject ? reject : REJECT,strlen(reject ? reject : REJECT));
write(socket,"\r\n",2);
close(socket);
return;
}
user_count++;
if ((user = malloc(sizeof(USER))) == NULL) crash("Out of memory");
user->nick = user->channel = NULL;
user->socket = socket;
user->dead = 0;
user->state = s_normal;
user->eol = user->cursor = user->buffer;
*user->prev = 0;
user->next = users;
users = user;
echo[0] = IAC;
echo[1] = WILL;
echo[2] = TELOPT_ECHO;
echo[3] = IAC;
echo[4] = WILL;
echo[5] = TELOPT_SGA;
echo[6] = 0;
output(user,echo);
output(user,announce);
}
static void crsr_back(USER *user)
{
if (user->cursor == user->buffer) return;
user->cursor--;
output(user,"\b");
}
static void crsr_fwd(USER *user)
{
char c[2];
if (user->cursor >= user->eol) return;
c[0] = *user->cursor++;
c[1] = 0;
output(user,c);
}
static void crsr_up(USER *user)
{
char temp[MAX_LINE+MAX_LINE+1];
int slack;
if (!*user->prev) return;
output(user,"\r");
output(user,user->prev);
if ((slack = user->eol-user->buffer-strlen(user->prev)) > 0) {
memset(temp,' ',slack);
memset(temp+slack,8,slack);
*(temp+slack+slack) = 0;
output(user,temp);
}
user->eol = user->cursor = strchr(strcpy(user->buffer,user->prev),0);
}
static void special(USER *user,unsigned char ch)
{
switch (user->state) {
case s_iac: switch (ch) {
case WONT: user->state = s_wont;
break;
case WILL: user->state = s_will;
break;
case DO: user->state = s_do;
break;
case DONT: user->state = s_dont;
break;
default: user->state = s_normal;
}
break;
case s_wont:
case s_will:
case s_do:
case s_dont:user->state = s_normal;
break;
case s_esc: if (ch == '[') user->state = s_csi;
else user->state = s_normal;
break;
case s_csi: switch (ch) {
case 'D': crsr_back(user);
break;
case 'C': crsr_fwd(user);
break;
case 'A': crsr_up(user);
}
user->state = s_normal;
break;
default: crash("Unknown terminal state");
}
}
static void get_input(USER *user)
{
char input[MAX_LINE+1],echo[2],temp[MAX_LINE*3];
char *walk,*move;
int size,dist;
echo[1] = 0;
if ((size = read(user->socket,input,MAX_LINE)) <= 0) {
signoff(user,1);
return;
}
for (walk = input; size--; walk++) {
if (user->state != s_normal) special(user,*walk);
else {
switch((unsigned char) *walk) {
#ifdef linux
case '\n':
#endif
case '\r': *user->eol = 0;
user->eol = user->cursor = user->buffer;
output(user,"\r\n");
if (*user->buffer)
process(user,strcpy(user->prev,user->buffer));
break;
case 8:
case 127: if (user->buffer != user->cursor) {
user->cursor--;
*user->eol-- = 0;
if (user->cursor == user->eol)
output(user,"\b \b");
else {
output(user,"\b");
output(user,user->cursor+1);
for (move = user->cursor+1; *move; move++)
*(move-1) = *move;
temp[0] = ' ';
memset(temp+1,8,dist = user->eol-user->
cursor+1);
temp[dist+1] = 0;
output(user,temp);
}
}
break;
case 1: user->cursor = user->buffer;
output(user,"\r");
break;
case 5: if (user->cursor != user->eol) {
*user->eol = 0;
output(user,user->cursor);
user->cursor = user->eol;
}
break;
case 27: user->state = s_esc;
break;
case IAC: user->state = s_iac;
break;
case 2: crsr_back(user);
break;
case 6: crsr_fwd(user);
break;
case 16: crsr_up(user);
break;
case 18: output(user,"\r");
*user->eol = 0;
output(user,user->buffer);
if (dist = user->eol-user->cursor) {
memset(temp,8,dist);
temp[dist] = 0;
output(user,temp);
}
break;
case 21:
case 24: if (dist = user->eol-user->buffer) {
output(user,"\r");
memset(temp,' ',dist);
temp[dist] = 0;
output(user,temp);
output(user,"\r");
user->eol = user->cursor = user->buffer;
}
break;
default: if (*walk >= ' ' && *walk <= '~') {
if (user->eol-user->buffer == MAX_LINE)
output(user,"\7");
else {
echo[0] = *walk;
output(user,echo);
if (user->cursor == user->eol) {
*user->cursor = *walk;
user->eol = ++user->cursor;
}
else {
*user->eol++ = 0;
output(user,user->cursor);
for (move = user->eol; move > user->
cursor; move--) *move = *(move-1);
*user->cursor++ = *walk;
memset(temp,8,dist = user->eol-user->
cursor);
temp[dist] = 0;
output(user,temp);
}
}
}
}
}
}
}
static void poll(void)
{
USER *walk;
fd_set flags;
int max;
FD_ZERO(&flags);
FD_SET(port,&flags);
max = port;
for (walk = users; walk; walk = walk->next)
if (!walk->dead) {
FD_SET(walk->socket,&flags);
if (walk->socket > max) max = walk->socket;
}
select(max+1,&flags,NULL,NULL,NULL);
if (FD_ISSET(port,&flags)) accept_new();
for (walk = users; walk; walk = walk->next)
if (FD_ISSET(walk->socket,&flags)) get_input(walk);
}
static void die(char *msg)
{
perror(msg);
exit(1);
}
static char *get_path(char *name,char *buffer)
{
char *path;
sprintf(buffer,"%s/%s",(path = getenv("FAYCA")) ? path : ".",name);
}
static char *get_msg(char *name)
{
char full_name[PATH_MAX+1];
char input[READ_CHUNK],cvt[READ_CHUNK*2];
char *path,*msg,*new,*from,*to;
int file,total,size,count;
(void) get_path(name,full_name);
if ((file = open(full_name,O_RDONLY)) < 0) return NULL;
msg = NULL;
total = 0;
while ((size = read(file,input,READ_CHUNK)) > 0) {
from = input;
to = cvt;
for (count = size; count > 0; count--) {
if (*from == '\n') {
*to++ = '\r';
size++;
}
*to++ = *from++;
}
if (msg == NULL || (new = realloc(msg,total+size+1)) == NULL) {
if ((new = malloc(total+size+1)) == NULL) crash("Out of memory");
if (msg) {
memcpy(new,msg,total);
free(msg);
}
}
memcpy(new+total,cvt,size);
(msg = new)[(total += size)+1] = 0;
}
(void) close(file);
return msg;
}
static void setup(void)
{
char full_name[PATH_MAX+1];
if ((announce = get_msg("announce")) == NULL) announce =
"Welcome to FAYCA (For All You Chat Addicts)\r\n\
~~~~~~~~~~~~~~~~~~\\ Version 0.10 ALPHA\r\n\n\
Please enter your nick name (or /Show or /Exit): ";
motd = get_msg("motd");
get_path("journal",full_name);
/* if ((jou_file = open(full_name,O_RDWR)) < 0) */ jou_file = 0;
}
int main(int argc,char **argv)
{
struct sockaddr_in name;
int option,tmp,nr = PORT;
FILE *file;
if (argc == 3 && !strcmp(argv[1],"-t"))
return kill(atoi(argv[2]),0) < 0 ? 1 : 0;
setup();
if ((port = socket(AF_INET,SOCK_STREAM,0)) < 0) die("socket");
option = 1;
if (setsockopt(port,SOL_SOCKET,SO_REUSEADDR,(char *) &option,
sizeof(option)) < 0) die("setsockopt");
bzero(&name,sizeof(name));
name.sin_family = AF_INET;
while (argc-- > 1) {
if (atoi(argv[1])) nr = atoi(argv[1]);
else reject = argv[1];
argv++;
}
name.sin_port = htons(nr);
name.sin_addr.s_addr = INADDR_ANY;
if (bind(port,(struct sockaddr *) &name,sizeof(name)) < 0) die("bind");
if (listen(port,5) < 0) die("listen");
if ((file = fopen("fayca.pid","w")) == NULL) die("fopen");
if (fprintf(file,"%d\n",getpid()) < 0) die("fprintf");
if (fclose(file) < 0) die("fclose");
fprintf(stderr,"Ready at port %d\n",ntohs(name.sin_port));
while (1) {
poll();
cleanup();
}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.