/* Internet Finger server */
#include <stdio.h>
#include <string.h>
#include "global.h"
#include "files.h"
#include "mbuf.h"
#include "socket.h"
#include "session.h"
#include "proc.h"
#include "dirutil.h"
#include "commands.h"
#include "mailbox.h"
  
extern int ShowConfUsers(int s,int quick);
extern int ShowConfLinks(int s,int full);
extern int doipheard(int argc,char *argv[],void *p);
extern int Sconv;
  
static int Sfinger = -1;    /* Prototype socket for service */
static void fingerd __ARGS((int s,void *unused,void *p));
  
/* Start up finger service */
int
finstart(argc,argv,p)
int argc;
char *argv[];
void *p;
{
    struct sockaddr_in lsocket;
    int s;
  
    if(Sfinger != -1){
        return 0;
    }
    psignal(Curproc,0); /* Don't keep the parser waiting */
    chname(Curproc,"Finger listener");
  
    lsocket.sin_family = AF_INET;
    lsocket.sin_addr.s_addr = INADDR_ANY;
    if(argc < 2)
        lsocket.sin_port = IPPORT_FINGER;
    else
        lsocket.sin_port = atoi(argv[1]);
  
    Sfinger = socket(AF_INET,SOCK_STREAM,0);
    bind(Sfinger,(char *)&lsocket,sizeof(lsocket));
    listen(Sfinger,1);
    for(;;){
        if((s = accept(Sfinger,NULLCHAR,(int *)NULL)) == -1)
            break;  /* Service is shutting down */
  
        /* Spawn a server */
        if(newproc("fingerd",1024,fingerd,s,NULL,NULL,0) == NULLPROC)
            close_s(s);
    }
    return 0;
}
  
#define FLINE 128
  
struct finfo {
    char *name;
    int (*func) __ARGS((int argc,char *argv[],void *p));
};
  
struct finfo Finfo[] = {
    "iheard", doipheard,
    "mstat", dombmailstats,
    "info", doinfo,
    "ax25", doaxstat,
    "netrom", donrstatus,
    "tcpview", doview,
    "memstat", dostat,
    "socket", dosock,
#ifdef ASY
    "asystat",doasystat,
#endif
    "ifconfig", doifconfig,
#ifdef RIP
    "rip", doripstat,
#endif
    NULL,
};
  
  
static void
fingerd(s,unused,p)
int s;
void *unused;
void *p;
{
    char user[80];
    int ulen,found;
    struct finfo *fi;
    FILE *fp;
    char *file,*cp;
    char line[FLINE+1];
    int outsave;
#ifdef USERLOG
    char *newargv[2];
#endif
  
    sockmode(s,SOCK_ASCII);
    sockowner(s,Curproc);
    log(s,"open Finger");
    recvline(s,user,80);
    rip(user);
    ulen = strlen(user);
  
    if(ulen) {
#ifdef CONVERS
        if(!stricmp(user,"conf"))
            ShowConfUsers(s,0);
        else if(!stricmp(user,"links"))
            ShowConfLinks(s,1);
        else
#endif
            for(fi=Finfo;fi->name;fi++) {
                if(!stricmp(fi->name,user)) {
                    outsave = Curproc->output;
                    Curproc->output = s;
                    fi->func(1,NULL,NULL);
                    Curproc->output = outsave;
                    break;
                }
            }
    } else {
        if(ulen == 0){
            fp = dir(Fdir,0);
            if(fp == NULLFILE)
                usputs(s,"No finger information available\n");
            else
                usputs(s,"Known users on this system:\n");
        } else {
#ifdef USERLOG
            outsave = Curproc->output;
            Curproc->output = s;
            newargv[1] = user;
            dombuserinfo(0,newargv,NULL);
            Curproc->output = outsave;
#endif
            file = pathname(Fdir,user);
            cp = pathname(Fdir,"");
            /* Check for attempted security violation (e.g., somebody
             * might be trying to finger "../ftpusers"!)
             */
            if(strncmp(file,cp,strlen(cp)) != 0){
                fp = NULLFILE;
                usprintf(s,"Invalid user name %s\n",user);
            } else if((fp = fopen(file,READ_TEXT)) == NULLFILE) {
                /* Now search the finger database file for this user - WG7J */
                found = 0;
                if((fp = fopen(Fdbase,READ_TEXT)) != NULLFILE) {
                    while(fgets(line,FLINE,fp) != NULLCHAR)
                        if(!strncmp(line,user,ulen)) {
                            usputs(s,line);
                            found = 1;
                            break;
                        }
                    fclose(fp);
                    fp = NULLFILE;
                }
                if(!found)
                    usprintf(s,"No user info for %s\n",user);
            }
            free(cp);
            free(file);
        }
        if(fp != NULLFILE){
            sendfile(fp,s,ASCII_TYPE,0);
            fclose(fp);
        }
    }
    if(ulen == 0 && Listusers != NULL)
        (*Listusers)(s);
    close_s(s);
    log(s,"close Finger");
}
int
fin0(argc,argv,p)
int argc;
char *argv[];
void *p;
{
    close_s(Sfinger);
    Sfinger = -1;
    return 0;
}
