/* Internet Finger server */
#include "global.h"
#ifdef FINGERSERVER
#include "files.h"
#include "mbuf.h"
#include "socket.h"
#include "session.h"
#include "proc.h"
#include "smtp.h"
#include "dirutil.h"
#include "commands.h"
#include "mailbox.h"

#ifdef MAILFOR
extern int dombmailfor __ARGS((int argc,char *argv[],void *p));
#endif

static void fingerd __ARGS((int s,void *unused,void *p));
#if defined SAMCALLB || QRZCALLB
extern int cb_lookup __ARGS((int, char *, FILE *));
#endif


/* Start up finger service */
int
finstart(argc,argv,p)
int argc;
char *argv[];
void *p;
{
    int16 port;

    if(argc < 2)
        port = IPPORT_FINGER;
    else
        port = atoi(argv[1]);

    return start_tcp(port,"FINGER Server",fingerd,1024);
}

int
fin0(argc,argv,p)
int argc;
char *argv[];
void *p;
{
    int16 port;

    if(argc < 2)
        port = IPPORT_FINGER;
    else
        port = atoi(argv[1]);

    return stop_tcp(port);
}

#define FLINE 128

struct finfo {
    char *name;
    int (*func) __ARGS((int argc,char *argv[],void *p));
};

struct finfo Finfo[] = {
    "iheard",   doipheard,
#ifdef N2RJT_FINGERS
    "aheard",   doaxheard,
#endif /* N2RJT_FINGERS */
#ifdef MAILBOX
    "mstat",    dombmailstats,
#ifdef N2RJT_FINGERS
    "mpast", dombpast,
#endif /* N2RJT_FINGERS */
#endif
#ifdef ALLCMD
    "info",     doinfo,
#endif
#ifdef AX25
    "ax25",     doaxstat,
#ifdef MAILFOR
    "mailfor",  dombmailfor,
#endif // MAILFOR
#endif // AX25
#ifdef NETROM
    "netrom",   donrstatus,
#endif
    "memstat",  dostat,
    "socket",   dosock,
    "tcpview",  doview,
    "users",    dombstatus,
#ifdef ASY
    "asystat",  doasystat,
#endif
/* This gives a lot of info you might not want to be known - WG7J */
/*    "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;
    FILE *fp;
    char *file,*cp;
    struct finfo *fi;
    int outsave;
    char line[FLINE+1];

    sockmode(s,SOCK_ASCII);
    sockowner(s,Curproc);
    log(s,"open Finger");
    recvline(s,user,80);
    rip(user);
    ulen = strlen(user);

#ifdef CONVERS
    if(ulen && !strcmp(user,"conf"))
        ShowConfUsers(s,0,NULL);
    else if( ulen && !strcmp(user,"links"))
        ShowConfLinks(s,1);
    else {
#endif
        for(fi=Finfo;fi->name;fi++)
            if(!stricmp(fi->name,user))
                break;
        if(ulen && fi->name) {
            outsave = Curproc->output;
            Curproc->output = s;
            fi->func(1,NULL,NULL);
            Curproc->output = outsave;
        } 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
                char *newargv[2];

                outsave = Curproc->output;
                Curproc->output = s;
                newargv[1] = user;
                dombuserinfo(0,newargv,NULL);
                Curproc->output = outsave;
#endif
#if defined SAMCALLB || QRZCALLB
                cb_lookup (s, user, (FILE *) 0);
#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,NULL);
                fclose(fp);
            }
        }
#ifdef CONVERS
    }
#endif
    if(ulen == 0 && Listusers != NULL)
        (*Listusers)(s);
    close_s(s);
    log(s,"close Finger");
}

#endif /* FINGERSERVER */
