/*
 * this file is a part of yabbs - yet another bulletin board system.
 * Copyright (C) 1993, 1994 Alex Wetmore.  
 * email: alex@phred.org
 * address: 6 rech ave
 *          oreland pa 19075
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#define FALSE 0
#define TRUE 1
#define GFILDEPTH 100                   /* maximum levels deep for gfile    */
                                        /* indexs                           */
#define YABBSPORT 4225                  /* the port for the server          */
                                        /* (other port can be specified on  */
                                        /* command line)                    */
#define MAXCMD 512                      /* maximum length of a command      */
#define MAXCMDKEY 20                    /* maximum length of a key          */

#include "patchlevel.h"

/* function prototypes for all of the functions to handle various messages.
 * they should take the client number as the first parameter, and their
 * parameter list as the second one.
 */
void s_help(int n, char **argv);        /* no parameters                    */
void s_login(int n, char **argv);       /* name, password                   */
void s_logout(int n, char **argv);      /* no parameters                    */
void s_who(int n, char **argv);         /* no parameters                    */
void s_channels(int n, char **argv);    /* no parameters                    */
void s_talk(int n, char **argv);        /* toname (PUBLIC), line, message   */
void s_page(int n, char **argv);        /* toname                           */
void s_getmsg(int n, char **argv);      /* msgbase, msgnum                  */
void s_getmsghdrs(int n, char **argv);  /* msgbase, minmsgnum, maxmsgnum    */
void s_getmsgnum(int n, char **argv);   /* msgbase                          */
void s_addmsg(int n, char **argv);      /* see documentation                */
void s_deletemsg(int n, char **argv);   /* msgbase, msgnum                  */
void s_getbases(int n, char **argv);    /* no parameters                    */
void s_getopts(int n, char **argv);     /* no parameters                    */
void s_setopts(int n, char **argv);     /* scrlen, options, subs            */
void s_getlastmsg(int n, char **argv);  /* baseid                           */
void s_setlastmsg(int n, char **argv);  /* baseid, msgnum                   */
void s_setpasswd(int n, char **argv);   /* new passwd                       */
void s_finduser(int n, char **argv);    /* partial name                     */
void s_newuser(int n, char **argv);     /* user name, passwd                */
void s_userexist(int n, char **argv);   /* users name                       */
void s_gettxtfile(int n, char **argv);  /* file name                        */
void s_getplanfile(int n, char **argv); /* user name                        */
void s_putplanfile(int n, char **argv); /* see docs                         */
void s_gfileindex(int n, char **argv);  /* keys to menu file (see docs)     */
void s_getgfile(int n, char **argv);    /* keys to text file (see docs)     */
void s_startlog(int n, char **argv);    /* no parameters                    */
void s_stoplog(int n, char **argv);     /* no parameters                    */
void s_gnuinfo(int n, char **argv);     /* no parameters                    */
void s_shutdown(int n, char **argv);    /* really shutdown, message         */
void s_onfrom(int n, char **argv);      /* location connect from            */
void s_request(int n, char **argv);     /* type of request, paramter        */

struct ctype {
    char cname[16];                     /* command name                     */
    int  minargs;                       /* number of args required          */
    int  fork;                          /* O_NOFORK or O_FORK               */
    int  login;                         /* O_NOLOGIN or O_LOGIN             */
    void (*f)(int cli, char **argv);    /* function to call                 */
};

#define O_NOFORK 0                      /* don't fork operation             */
#define O_FORK 1                        /* fork operation                   */
#define O_NOLOGIN 0                     /* user doesnt have to be logged in */
#define O_LOGIN 1                       /* user must be logged in           */
#define S_CNUM 32
/*
 * warning: the only operations that can be forked are operations that don't
 * change any of the public (global) variables in the server, because otherwise
 * the changes will get lost.  someday this should be done with a real
 * threads package, but for now this works.
 */
struct ctype s_ctable[] = { 
    { "HELP",           0,  O_NOFORK,   O_NOLOGIN,  s_help          },
    { "LOGIN",          2,  O_NOFORK,   O_NOLOGIN,  s_login         },
    { "LOGOUT",         0,  O_NOFORK,   O_NOLOGIN,  s_logout        },
    { "WHO",            0,  O_NOFORK,   O_NOLOGIN,  s_who           },
    { "CHANNELS",       0,  O_NOFORK,   O_NOLOGIN,  s_channels      },
    { "TALK",           2,  O_NOFORK,   O_LOGIN,    s_talk          },
    { "PAGE",           1,  O_NOFORK,   O_LOGIN,    s_page          },
    { "GETMSG",         2,  O_FORK,     O_LOGIN,    s_getmsg        },
    { "GETMSGHDRS",     3,  O_FORK,     O_LOGIN,    s_getmsghdrs    },
    { "GETMSGNUM",      1,  O_NOFORK,   O_LOGIN,    s_getmsgnum     },
    { "ADDMSG",         2,  O_NOFORK,   O_LOGIN,    s_addmsg        },
    { "DELETEMSG",      2,  O_NOFORK,   O_LOGIN,    s_deletemsg     },
    { "GETBASES",       0,  O_NOFORK,   O_LOGIN,    s_getbases      },
    { "GETOPTS",        0,  O_NOFORK,   O_LOGIN,    s_getopts       },
    { "SETOPTS",        3,  O_NOFORK,   O_LOGIN,    s_setopts       },
    { "GETLASTMSG",     1,  O_NOFORK,   O_LOGIN,    s_getlastmsg    },
    { "SETLASTMSG",     2,  O_NOFORK,   O_LOGIN,    s_setlastmsg    },
    { "SETPASSWD",      1,  O_NOFORK,   O_LOGIN,    s_setpasswd     },
    { "FINDUSER",       1,  O_FORK,     O_LOGIN,    s_finduser      },
    { "NEWUSER",        2,  O_NOFORK,   O_NOLOGIN,  s_newuser       },
    { "USEREXIST",      1,  O_NOFORK,   O_NOLOGIN,  s_userexist     },
    { "GETTXTFILE",     1,  O_FORK,     O_NOLOGIN,  s_gettxtfile    },
    { "GETPLANFILE",    1,  O_FORK,     O_NOLOGIN,  s_getplanfile   },
    { "PUTPLANFILE",    2,  O_NOFORK,   O_LOGIN,    s_putplanfile   },
    { "GFILEINDEX",     1,  O_FORK,     O_LOGIN,    s_gfileindex    },
    { "GETGFILE",       1,  O_FORK,     O_LOGIN,    s_getgfile      },
    { "STARTLOG",       0,  O_NOFORK,   O_LOGIN,    s_startlog      },
    { "STOPLOG",        0,  O_NOFORK,   O_LOGIN,    s_stoplog       },
    { "GNUINFO",        0,  O_FORK,     O_NOLOGIN,  s_gnuinfo       },
    { "SHUTDOWN",       2,  O_NOFORK,   O_LOGIN,    s_shutdown      },
    { "ONFROM",         1,  O_NOFORK,   O_NOLOGIN,  s_onfrom        },
    { "REQUEST",        2,  O_NOFORK,   O_NOLOGIN,  s_request       }
};

int junk;
#undef DEBUG
#ifdef DEBUG
#define dbg(x) x
#else
#define dbg(x)
#endif

struct chanrec {
    char        name[11];                       /* name of channel          */
    llist       people;                         /* people in the channel    */
    char        hidden;                         /* this channel is hidden   */
};

typedef struct chanrec *crec;

/* host access control information structure                                */
typedef struct accesscont_st {
    char        *hoststring;                    /* domain name or ip addr   */
    int         maxusers;                       /* max # of users from host */
    int         numusers;                       /* # of users on right now  */
} accesscont;

/* temporary user information structure                                     */
struct utmprec {
    char        cmdbuf[MAXCMD];                 /* command buffer           */
    int         cmdbuflen;                      /* current length of it     */
    char        name[9];                        /* name of user             */
    time_t      timeon;                         /* time they logged on      */
    time_t      timelast;                       /* time since last command  */
    char        addr[33];                       /* address of client        */
    char        term[33];                       /* terminal type            */
    char        valid;                          /* true if user is valid    */
    mrec        msg;                            /* message buffer for       */
                                                /*  incoming messages       */
    int         msgbase;                        /* message base id for      */
                                                /*  incoming messages       */
    int         unum;                           /* user number              */
    llist       channels;                       /* chat channel             */
    int         talkcommands;                   /* talk commands this sec   */
    accesscont  *hostaccess;                    /* point to accesscont      */
    int         announce;                       /* what they want announced */
};

/* announcement options, in a bitfield.  by default they are all off        */
#define AN_LOGIN        0x0001
#define AN_LOGOUT       0x0002
#define AN_NEWMSG       0x0004
#define AN_CHANJOIN     0x0008
#define AN_CHANLEAVE    0x0010
#define AN_CHANCREATE   0x0020
#define AN_CHANDESTROY  0x0040
#define AN_CHANNEWNAME  0x0080

typedef struct utmprec wrec;
