/***************************************************************************
 *                                                                         *
 *   CSMJRTLC.C                                                            *
 *                                                                         *
 *   Copyright (c) 1994-1997 Galacticomm, Inc.   All rights reserved.      *
 *                                                                         *
 *   Teleconference agent.                                                 *
 *                                                                         *
 *                                                - Bill Hyatt 10/4/94     *
 *                                                                         *
 ***************************************************************************/

#include "tlc.h"

#define HASAKY 0x01                /* user has tele agent access key       */
#define HASMKY 0x02                /* user has key to moderate channel     */
#define HASUKY 0x04                /* user has key for unlimited tele use  */
#define HASDKY 0x08                /* user has key to use drawing board    */
#define HASFKY 0x10                /* user has key to send files           */

static VOID tlcread(INT direction,struct saunam *dpknam);
static VOID tlcwrite(struct saunam *dpknam,USHORT length,VOID *value);
static VOID tlcxdone(VOID);
static VOID tlcabort(VOID);

static struct tlccinf *curcinf(VOID);
static VOID wt4rcvr(VOID);
static VOID tlcfin(VOID);
static VOID reg_dpk(VOID);

struct agent tlcagt={              /* agent information structure          */
     "GALTLC",                     /* appid                                */
     tlcread,                      /* read-dynapak function pointer        */
     tlcwrite,                     /* write-dynapak function pointer       */
     tlcxdone,                     /* file xfer-done function pointer      */
     tlcabort                      /* abort-request function pointer       */
};

INT cswto;                         /* alw C/S users to swt to Forum chans? */

static
CHAR *tlcakey,                     /* key req'd to read from tele agent    */
      *dbrdky;                     /* key req'd to use the drawing board   */

struct tlccfg {                    /* tele config info for client          */
     SHORT tlckys;                 /* keys held by a particular user       */
     SHORT npaymx;                 /* # times non-paying user can speak    */
     LONG maxfre;                  /* highest non-paying chan# allowed     */
     SHORT tinpsz;                 /* max length of tele input line        */
};

struct flddef tlccfgFDA[] = {
     {CVTFLD_SHORT,2,fldoff(tlccfg,tlckys),NULL},
     {CVTFLD_LONG ,1,fldoff(tlccfg,maxfre),NULL},
     {CVTFLD_SHORT,1,fldoff(tlccfg,tinpsz),NULL},
     {CVTFLD_END  ,0,0                    ,NULL}
};

struct tlccinf {                   /* current channel information          */
     LONG curchan;                 /*   current channel number             */
     CHAR moderator[UIDSIZ-1];     /*   moderator, if any                  */
     CHAR topic[CTPSIZ-1];         /*   topic, if any                      */
};

struct flddef tlccinfFDA[] = {
     {CVTFLD_LONG ,1                ,fldoff(tlccinf,curchan)  ,NULL},
     {CVTFLD_RTEXT,UIDSIZ-1+CTPSIZ-1,fldoff(tlccinf,moderator),NULL},
     {CVTFLD_END  ,0                ,0                        ,NULL}
};

#define VBFILSIZ (GCMAXFILE+GCMAXEXT+1)/* VB filename size (i.e. 12)           */

struct tlcfil {                    /* info on file being sent through tele */
     CHAR userid[UIDSIZ-1];        /*   other guy's User-ID                */
     CHAR name[VBFILSIZ];          /*   file name                          */
     DOUBLE tnd;                   /*   file time and date (VB double form)*/
     LONG size;                    /*   file size in bytes                 */
};

struct flddef tlcfilFDA[]={
     {CVTFLD_RTEXT ,UIDSIZ-1+VBFILSIZ,fldoff(tlcfil,userid),NULL},
     {CVTFLD_DOUBLE,1                ,fldoff(tlcfil,tnd)   ,NULL},
     {CVTFLD_LONG  ,1                ,fldoff(tlcfil,size)  ,NULL},
     {CVTFLD_END   ,0                ,0                    ,NULL}
};

VOID
inicstlc(VOID)                     /* initialize teleconference agent      */
{
     register_agent(&tlcagt);
     tlcakey=stgopt(TLCAKEY);
     dbrdky=stgopt(DBRDKY);
     cswto=(tlcovr || ynopt(CSWTO));
     hook_disconnect(tlchup);
     hook_shutdown(tlcfin);
     reg_dpk();
}

static VOID
tlcread(                           /* read-dynapak handler                 */
INT direction,                     /*   read direction: 0=eq, 1=gt, -1=lt  */
struct saunam *dpknam)             /*   dynapak name to read               */
{
     CHAR *dpkstg,*curguy,*stp;
     struct tlccfg tlccfg;
     struct tlc *tp;

     (VOID)direction;
     if (stdchk(tlcakey)) {
          dpkstg=cnvs2d(dpknam);
          tlcptr=&tlclst[usrnum];
          setmbk(tlcmb);
          if (sameas(dpkstg,"sau:tlccfg")) {
               setmem(&tlccfg,sizeof(struct tlccfg),0);
               if (haskey(tlcakey)) {
                    tlccfg.tlckys|=HASAKY;
               }
               if (haskey(modkey)) {
                    tlccfg.tlckys|=HASMKY;
               }
               if (haskey(unlkey)) {
                    tlccfg.tlckys|=HASUKY;
               }
               if (haskey(dbrdky)) {
                    tlccfg.tlckys|=HASDKY;
               }
               if (hasmkey(FILKEY)) {
                    tlccfg.tlckys|=HASFKY;
               }
               tlccfg.npaymx=npaymx;
               tlccfg.maxfre=(LONG)maxfre;
               tlccfg.tinpsz=tinpsz;
               rsp2read(dpknam,sizeof(struct tlccfg),&tlccfg,tlccfgFDA);
               return;
          }
          if (tlcptr->flags&TLCGCS) {
               if (sameas(dpkstg,"sau:chnlst")) {
                    rsptmp[0]='\0';
                    initls();
                    while ((curguy=tlsrui(LSTSCH)) != NULL) {
                         strcat(rsptmp,curguy);
                         onsys(curguy);
                         strcat(rsptmp,spr("%s\t",flgbyt(othusn)));
                    }
                    rsp2read(dpknam,STGLEN,rsptmp,rtextFDA);
                    return;
               }
               if (sameas(dpkstg,"sau:rchlst")) {
                    rsptmp[0]='\0';
                    initls();
                    while ((curguy=tlsrui(LSTALL)) != NULL) {
                         strcat(rsptmp,spr("%s\t",curguy));
                    }
                    rsp2read(dpknam,STGLEN,rsptmp,rtextFDA);
                    return;
               }
               if (sameas(dpkstg,"sau:crqlst")) {
                    rsptmp[0]='\0';
                    initls();
                    while ((curguy=tlsrui(LSTCRQ)) != NULL) {
                         strcat(rsptmp,spr("%s\t",curguy));
                    }
                    rsp2read(dpknam,STGLEN,rsptmp,rtextFDA);
                    return;
               }
               if (sameas(dpkstg,"sau:scan")) {
                    rsptmp[0]='\0';
                    for (tp=tlclst,othusn=0 ; othusn < nterms ; tp++,othusn++) {
                         if (inscan(othusn,tp)) {
                              strcat(rsptmp,spr("%s\t",uacoff(othusn)->userid));
                              strcat(rsptmp,scnchn(othusn,tp));
                              if (tp->channel != 0 && (stp=scntpc(tp)) != NULL) {
                                   strcat(rsptmp,spr("\t%s",stp));
                              }
                              strcat(rsptmp,";");
                         }
                    }
                    rsp2read(dpknam,STGLEN,rsptmp,rtextFDA);
                    return;
               }
               if (sameas(dpkstg,"sau:curcinf")) {
                    rsp2read(dpknam,sizeof(struct tlccinf),curcinf(),tlccinfFDA);
                    return;
               }
          }
     }
     rejectreq();
}

static VOID
tlcwrite(                          /* write-dynapak handler                */
struct saunam *dpknam,             /*   dynapak name to write              */
USHORT length,                     /*   length of dynapak value            */
VOID *value)                       /*   dynapak value to write             */
{
     CHAR *dpkstg,uid[UIDSIZ],datbuf[TDBFSZ];
     INT ousn,chkres,cnt;
     struct user *ousp;
     LONG newchn;
     struct tlc *otptr;
     struct tlcfil tlcf,*finf;

     if (stdchk(tlcakey)) {
          dpkstg=cnvs2d(dpknam);
          tlcptr=&tlclst[usrnum];
          setmbk(tlcmb);
          if (sameas(dpkstg,"sau:enttlc")) {
               if (length == 0) {
                    tlcptr->flags|=(TLCGCS|LUISSU);
                    if (!(usrptr->flags&INVISB)) {
                         outtlc(ENTTLC,ALLU,usrnum,-1,usaptr->userid,
                                flgbyt(usrnum),NULL);
                    }
                    rsp2write(TRUE,sizeof(struct tlccinf),curcinf(),tlccinfFDA);
                    return;
               }
          }
          if (sameas(dpkstg,"sau:nmtalk") && tlcptr->flags&TLCGCS) {
               if (length > 0 && length <= tinpsz) {
                    setpfn(value);
                    if ((chkres=ck4pfn()) != NOPFN) {
                         if (chkres != HUNGUP) {
                              r2wprf(FALSE);
                         }
                         return;
                    }
                    if (tlcptr->flags&SQUCHD) {
                         prf("SQL");
                         prfmsg(TLKSQU);
                         r2wprf(FALSE);
                         return;
                    }
                    if (!haskey(unlkey) && (tlcptr->inpcnt)++ >= npaymx) {
                         prf("NPY");
                         prfmsg(NPAYXC,npaymx);
                         r2wprf(FALSE);
                         return;
                    }
                    if (urinv()) {
                         r2wprf(FALSE);
                         return;
                    }
                    outtlc(NMTALK,ALLU,usrnum,-1,usaptr->userid,value,NULL);
                    *namtmp=*dpknam;
                    rsp2write(TRUE,0,NULL,NULL);
                    stlcpy(namtmp->suffix,"local",SFXSIZ);
                    if (qroom(usrnum,NORMAL)) {
                         senddpk(usrnum,TLCAID,NORMAL,namtmp,length,value,
                                 rtextFDA);
                    }
                    return;
               }
          }
          if (sameto("sau:whisper",dpkstg)) {
               if (length <= tinpsz) {
                    setpfn(value);
                    if ((chkres=ck4pfn()) != NOPFN) {
                         if (chkres != HUNGUP) {
                              r2wprf(FALSE);
                         }
                         return;
                    }
                    if (tlcptr->flags&SQUCHD) {
                         prf("SQL");
                         prfmsg(TLKSQU);
                         r2wprf(FALSE);
                         return;
                    }
                    if (!haskey(unlkey) && (tlcptr->inpcnt)++ >= npaymx) {
                         prf("NPY");
                         prfmsg(NPAYXC,npaymx);
                         r2wprf(FALSE);
                         return;
                    }
                    if (urinv()) {
                         r2wprf(FALSE);
                         return;
                    }
                    stlcpy(uid,skpwht(skpwrd(dpknam->suffix)),UIDSIZ);
                    if ((cnt=howmny(uid,2,TRUE)) == 0) {
                         prf("NHR");
                         prfmsg(WHSNHR,uid);
                         r2wprf(FALSE);
                         return;
                    }
                    if (cnt != 1) {
                         prf("AMB");
                         prfmsg(AMBIG,uid,"whisper");
                         r2wprf(FALSE);
                         return;
                    }
                    if (length == 0) {
                         prf("FMT");
                         prfmsg(WHSFMT);
                         r2wprf(FALSE);
                         return;
                    }
                    sndwsp(value);
                    *namtmp=*dpknam;
                    rsp2write(TRUE,0,NULL,NULL);
                    stlcpy(namtmp->suffix,"lclwsp",SFXSIZ);
                    stlcpy(datbuf,spr("%s\t",othuap->userid),UIDSIZ);
                    strcat(datbuf,value);
                    if (qroom(usrnum,NORMAL)) {
                         senddpk(usrnum,TLCAID,NORMAL,namtmp,STGLEN,datbuf,
                                 rtextFDA);
                    }
                    return;
               }
          }
          if (sameas(dpkstg,"sau:channel")) {
               if (length == sizeof(LONG)) {
                    newchn=lngval(value);
                    if ((chkres=chkchn(newchn)) == CHANOK) {
                         swtchn(newchn);
                         rsp2write(TRUE,STGLEN,"COK",NULL);
                    }
                    else {
                         switch (chkres=chkchn(newchn)) {
                         case OUTORG:
                              prf("ORG");
                              prfmsg(OUTORG);
                              break;
                         case YOURCH:
                              prf("YCH");
                              prfmsg(YOURCH);
                              break;
                         case CANTGO:
                              prf("CGO");
                              prfmsg(CANTGOCS);
                              break;
                         case PRVLCH:
                              prf("PRV");
                              prfmsg(PRVLCH);
                              break;
                         case PAYONL:
                              prf("PAY");
                              prfmsg(PAYONL,maxfre);
                              howbuy();
                              break;
                         case NANNOY:
                              prf("NNY");
                              prfmsg(NANNOY);
                              break;
                         }
                         r2wprf(FALSE);
                    }
                    return;
               }
          }
          if (sameas(dpkstg,"sau:unlist")) {
               tlcptr->flags&=~SHWCHN;
               rsp2write(TRUE,0,NULL,NULL);
               return;
          }
          if (sameas(dpkstg,"sau:list")) {
               tlcptr->flags|=SHWCHN;
               rsp2write(TRUE,0,NULL,NULL);
               return;
          }
          if (sameas(dpkstg,"sau:moderate")) {
               if (length < CTPSIZ) {
                    if (!haskey(modkey)) {
                         prf("MLV");
                         prfmsg(MODLIV);
                         howbuy();
                         r2wprf(FALSE);
                         return;
                    }
                    if (urinv()) {
                         r2wprf(FALSE);
                         return;
                    }
                    if (length == 0) {
                         r2wprf(xfrmod(NULL));
                         return;
                    }
                    if (tlcptr->channel == 0) {
                         prf("NC1");
                         prfmsg(NOMCH1);
                         r2wprf(FALSE);
                         return;
                    }
                    if (fidxst(tlcptr->channel)) {
                         prf("NVR");
                         prfmsg(NOOVRS);
                         r2wprf(FALSE);
                         return;
                    }
                    if (ck4mod(usrnum)) {
                         prf("ANO");
                         prfmsg(ANOMOD,uacoff(othusn)->userid);
                         r2wprf(FALSE);
                         return;
                    }
                    ntfyres(tlcptr->channel);
                    stlcpy(tlcptr->topic,value,CTPSIZ);
                    tlcptr->modchn=tlcptr->channel;
                    outtlc(BGNCON,ALLU,usrnum,-1,usaptr->userid,tlcptr->topic,NULL);
                    prf("BMD");
                    prfmsg(BMODER,tlcptr->topic);
                    r2wprf(TRUE);
                    return;
               }
          }
          if (sameas(dpkstg,"sau:appoint")) {
               if (length > 0 && length < UIDSIZ) {
                    r2wprf(xfrmod(value));
                    return;
               }
          }
          if (sameas(dpkstg,"sau:squelch") || sameas(dpkstg,"sau:unsquelch")) {
               if (length > 0 && length < UIDSIZ) {
                    r2wprf(squsqu(value,sameas(dpkstg,"sau:squelch")));
                    return;
               }
          }
          if (sameas(dpkstg,"sau:dbrdup") && haskey(dbrdky)) {
               tlcptr->flags|=DBRDUP;
               if (!(tlcptr->flags&SQUCHD) && !(usrptr->flags&INVISB)) {
                    if (tlcptr->flags&TLCGCS) {
                         outtlc(DBRDUP,CS,usrnum,-1,usaptr->userid,
                                spr("%c",tlcsex(usaptr->sex)),NULL);
                    }
                    rsp2write(TRUE,0,NULL,NULL);
                    return;
               }
          }
          if ((sameas(dpkstg,"sau:dbxyout") || sameas(dpkstg,"sau:dbtxout"))
           && haskey(dbrdky)) {
               if (!(tlcptr->flags&SQUCHD) && !(usrptr->flags&INVISB)) {
                    *namtmp=*dpknam;
                    if (sameas(dpkstg,"sau:dbxyout")) {
                         stlcpy(namtmp->suffix,"dbxyin",SFXSIZ);
                    }
                    else {
                         stlcpy(namtmp->suffix,"dbtxin",SFXSIZ);
                    }
                    namtmp->usrid[0]='\0';
                    if (tlcptr->flags&TLCGCS) {
                         for (ousn=0 ; ousn < nterms ; ousn++) {
                              ousp=usroff(ousn);
                              if (ousn != usrnum
                               && (ousp->flags&ISGCSU)
                               && (tlclst[ousn].flags&TLCGCS)
                               && (tlclst[ousn].flags&DBRDUP)
                               && tlcptr->channel == tlclst[ousn].channel
                               && qroom(ousn,NORMAL)) {
                                   senddpk(ousn,TLCAID,NORMAL,namtmp,length,
                                           value,NULL);
                              }
                         }
                         rsp2write(TRUE,0,NULL,NULL);
                         return;
                    }
                    if (tlcptr->flags&TLCCHT
                     && usroff(tlcptr->chatch)->flags&ISGCSU
                     && qroom(tlcptr->chatch,NORMAL)) {
                         senddpk(tlcptr->chatch,TLCAID,NORMAL,namtmp,length,
                                 value,NULL);
                         rsp2write(TRUE,0,NULL,NULL);
                         return;
                    }
               }
          }
          if (sameas(dpkstg,"sau:dbrddn") && haskey(dbrdky)) {
               if (tlcptr->flags&JUSTDB) {
                    prf("NNY");
                    prfmsg(NANNOYDB);
                    r2wprf(FALSE);
                    return;
               }
               if (tlcptr->flags&TLCGCS) {
                    tlcptr->flags&=~DBRDUP;
                    if (!(tlcptr->flags&SQUCHD) && !(usrptr->flags&INVISB)) {
                         outtlc(DBRDDN,CS,usrnum,-1,usaptr->userid,
                                spr("%c",tlcsex(usaptr->sex)),NULL);
                    }
                    tlcptr->flags|=JUSTDB;
                    rsp2write(TRUE,0,NULL,NULL);
                    return;
               }
          }
          if (sameas(dpkstg,"sau:chat") && tlcptr->flags&TLCGCS) {
               if (length > 0 && length < UIDSIZ) {
                    switch (chkres=chkcht(value)) {
                    case URINVS:
                         break;
                    case WHSNHR:
                         prf("NHR");
                         prfmsg(WHSNHR,value);
                         break;
                    case AMBIG:
                         prf("AMB");
                         prfmsg(AMBIG,value,"chat");
                         break;
                    case NCHSLF:
                         prf("SLF");
                         prfmsg(NCHSLF);
                         break;
                    case NOCHAA2:
                         prf("CAA");
                         prfmsg(NOCHAA2,othuap->userid,tlcsxp(othuap->sex));
                         break;
                    case ENTCHA:
                         enttcht();
                         break;
                    case CHTOFF:
                         prf("POF");
                         prfmsg(CHTOFF,othuap->userid);
                         break;
                    case CHAL2M:
                         prf("C2M");
                         prfmsg(CHAL2M,othuap->userid,(reqint+30)/60);
                         break;
                    case CHAREQ:
                         reqcht();
                         break;
                    }
                    r2wprf(chkres == ENTCHA || chkres == CHAREQ);
                    return;
               }
          }
          if (sameas(dpkstg,"sau:chatdout")) {
               if (tlcptr->flags&TLCCHT) {
                    if (usroff(tlcptr->chatch)->flags&ISGCSU) {
                         if (qroom(tlcptr->chatch,NORMAL)) {
                              *namtmp=*dpknam;
                              stlcpy(namtmp->usrid,
                                     uacoff(tlcptr->chatch)->userid,UIDSIZ);
                              stlcpy(namtmp->suffix,"chatdin",SFXSIZ);
                              senddpk(tlcptr->chatch,TLCAID,NORMAL,namtmp,
                                      length,value,NULL);
                              rsp2write(TRUE,0,NULL,NULL);
                              return;
                         }
                    }
               }
          }
          if (sameas(dpkstg,"sau:xitcht")) {
               if (tlcptr->flags&TLCCHT) {
                    tlcptr->flags|=TLCGCS;
                    xitcht(0);
                    rsp2write(TRUE,0,NULL,NULL);
                    return;
               }
          }
          if (sameas(dpkstg,"sau:denxfr") && !(tlcptr->flags&TLCRCV)) {
               if (onsys(value)) {
                    otptr=&tlclst[othusn];
                    if (otptr->sndstt == WT4ROK && otptr->rcvchn == usrnum) {
                         otptr->sndstt=NOSEND;
                         cnvd2s(spr("sau=%s;:denxfr",othuap->userid),namtmp);
                         senddpk(othusn,TLCAID,NORMAL,namtmp,STGLEN,
                          usaptr->userid,NULL);
                         rsp2write(TRUE,0,NULL,NULL);
                         return;
                    }
               }
          }
          if (sameas(dpkstg,"sau:bgnxfr") && hasmkey(FILKEY)
           && length == sizeof(struct tlcfil) && tlcptr->sndstt == NOSEND) {
            movmem(value,&tlcf,length);
               finf=&tlcf;
               if (finf->size < 1L) {
                    prf("LN0");
                    prfmsg(SNDLN0);
                    r2wprf(FALSE);
                    return;
               }
               if (urinv()) {
                    r2wprf(FALSE);
                    return;
               }
               b2ccpy(uid,finf->userid,UIDSIZ);
               switch (howmny(uid,1,1)) {
               case 0:
                    prf("NHR");
                    prfmsg(SNDNHR,uid);
                    r2wprf(FALSE);
                    return;
               case 1:
                    if (othusn == usrnum) {
                         prf("SLF");
                         prfmsg(SNDSLF);
                         r2wprf(FALSE);
                         return;
                    }
                    if (!(othusp->flags&ISGCSU)) {
                         prf("NCS");
                         prfmsg(SNDNCS,uid);
                         r2wprf(FALSE);
                         return;
                    }
                    if (tlclst[othusn].flags&TLCRCV) {
                         prf("RCV");
                         prfmsg(SNDRCV,uid);
                         r2wprf(FALSE);
                         return;
                    }
                    cnvd2s(spr("sau=%s;:xfrreq",othuap->userid),namtmp);
                    c2bcpy(finf->userid,usaptr->userid,UIDSIZ-1);
                    senddpk(othusn,TLCAID,NORMAL,namtmp,length,finf,tlcfilFDA);
                    tlcptr->sndstt=WT4ROK;
                    tlcptr->rcvchn=othusn;
                    tlcptr->sndbyt=finf->size;
                    rsp2write(TRUE,STGLEN,othuap->userid,rtextFDA);
                    return;
               default:
                    prf("AMB");
                    prfmsg(AMBIG,uid,"send file");
                    r2wprf(FALSE);
                    return;
               }
          }
          if (sameas(dpkstg,"sau:ok2xfr") && !(tlcptr->flags&TLCRCV)) {
               if (onsys(value)) {
                    otptr=&tlclst[othusn];
                    if (otptr->sndstt == WT4ROK && otptr->rcvchn == usrnum) {
                         otptr->sndstt=WT4DAT;
                         cnvd2s(spr("sau=%s;:ok2xfr",othuap->userid),namtmp);
                         senddpk(othusn,TLCAID,NORMAL,namtmp,STGLEN,
                                 usaptr->userid,NULL);
                         tlcptr->flags|=TLCRCV;
                         tlcptr->sndchn=othusn;
                         tlcptr->rcvopc=0;
                         rsp2write(TRUE,0,NULL,NULL);
                         return;
                    }
               }
          }
          if (sameas(dpkstg,"sau:fildat") && tlcptr->sndstt == WT4DAT
           && length <= tlcptr->sndbyt) {
               cnvd2s(spr("sau=%s;:fildat",uacoff(tlcptr->rcvchn)->userid),
                      namtmp);
               senddpk(tlcptr->rcvchn,TLCAID,BACKGND,namtmp,length,value,NULL);
               otptr=&tlclst[tlcptr->rcvchn];
               if ((tlcptr->sndbyt-=length) == 0L) {
                    tlcptr->sndstt=NOSEND;
                    otptr->flags&=~TLCRCV;
                    rsp2write(FALSE,0,NULL,NULL);
               }
               else if (++otptr->rcvopc >= MAXOPC
               || !qroom(tlcptr->rcvchn,BACKGND)) {
                    tlcptr->sndstt=WT4RRM;
                    cycleme(wt4rcvr);
               }
               else {
                    rsp2write(TRUE,0,NULL,NULL);
               }
               return;
          }
          if (sameas(dpkstg,"sau:gotdat") && (tlcptr->flags&TLCRCV)
           && tlcptr->rcvopc > 0) {
               tlcptr->rcvopc--;
               rsp2write(TRUE,0,NULL,NULL);
               return;
          }
          if (sameas(dpkstg,"sau:abosnd") && tlcptr->sndstt != NOSEND) {
               abosnd();
               rsp2write(TRUE,0,NULL,NULL);
               return;
          }
          if (sameas(dpkstg,"sau:aborcv") && (tlcptr->flags&TLCRCV)) {
               aborcv(tlcptr->sndchn);
               rsp2write(TRUE,0,NULL,NULL);
               return;
          }
          if (sameas(dpkstg,"sau:lvitlc")) {
               if (length == 0) {
                    if (tlcptr->flags&JUSTEX) {
                         prf("NNY");
                         prfmsg(NANNOY);
                         r2wprf(FALSE);
                         return;
                    }
                    if (tlcptr->flags&TLCGCS) {
                         tlcptr->flags&=~TLCGCS;
                         if (!(usrptr->flags&INVISB)) {
                              outtlc(LVITLC,ALLU,usrnum,-1,usaptr->userid,NULL,
                                     NULL);
                         }
                         rmvcht(-1);
                         tlcptr->flags|=JUSTEX;
                         tlcptr->flags&=~DBRDUP;
                         rsp2write(TRUE,0,NULL,NULL);
                         return;
                    }
                    if (tlcptr->flags&TLCCHT) {
                         xitcht(0);
                         tlcptr->flags|=JUSTEX;
                         tlcptr->flags&=~DBRDUP;
                         rsp2write(TRUE,0,NULL,NULL);
                         return;
                    }
               }
          }
          if (sameas(dpkstg,"sau:xittlc")) {
               abosnd();
               aboarcvs();
               rsp2write(TRUE,0,NULL,NULL);
               return;
          }
     }
     rejectreq();
}

static struct tlccinf *
curcinf(VOID)                      /* get current channel information      */
{
     static struct tlccinf tlccinf;

     setmem(&tlccinf,sizeof(struct tlccinf),0);
     tlccinf.curchan=((LONG)tlcptr->channel)+1L;
     if (ck4mod(-1)) {
          c2bcpy(tlccinf.moderator,uacoff(othusn)->userid,UIDSIZ-1);
          c2bcpy(tlccinf.topic,tptr->topic,CTPSIZ-1);
     }
     else {
          c2bcpy(tlccinf.moderator,"<none>",UIDSIZ-1);
          c2bcpy(tlccinf.topic,"<none>",CTPSIZ-1);
     }
     return(&tlccinf);
}

static VOID
wt4rcvr(VOID)                      /* wait 4 receiver to be ready for more */
{
     tlcptr=&tlclst[usrnum];
     if (tlcptr->sndstt != WT4RRM) {
          rsp2write(FALSE,0,NULL,NULL);
     }
     else if (tlclst[tlcptr->rcvchn].rcvopc < MAXOPC
           && qroom(tlcptr->rcvchn,BACKGND)) {
          tlcptr->sndstt=WT4DAT;
          rsp2write(TRUE,0,NULL,NULL);
     }
}

VOID
abosnd(VOID)                       /* abort send of file                   */
{
     switch (tlcptr->sndstt) {
     case NOSEND:
          break;
     case WT4ROK:
     case WT4DAT:
     case WT4RRM:
          cnvd2s(spr("sa=%s;u=%s;:aborcv",TLCAID,
               uacoff(tlcptr->rcvchn)->userid),namtmp);
          senddpk(tlcptr->rcvchn,TLCAID,NORMAL,namtmp,STGLEN,usaptr->userid,NULL);
          if ((tlclst[tlcptr->rcvchn].flags&TLCRCV)
           && tlclst[tlcptr->rcvchn].sndchn == usrnum) {
               tlclst[tlcptr->rcvchn].flags&=~TLCRCV;
          }
          tlcptr->sndstt=NOSEND;
          break;
     }
}

VOID
aborcv(                            /* abort receive/receive request        */
INT sndchn)                        /*   from this sender channel           */
{
     struct tlc *stptr;

     stptr=&tlclst[sndchn];
     switch (stptr->sndstt) {
     case NOSEND:
          break;
     case WT4ROK:
          cnvd2s(spr("sa=%s;u=%s;:abosnd",TLCAID,uacoff(sndchn)->userid),namtmp);
          senddpk(sndchn,TLCAID,NORMAL,namtmp,STGLEN,usaptr->userid,NULL);
     case WT4DAT:
     case WT4RRM:
          stptr->sndstt=NOSEND;
          break;
     }
     if ((tlcptr->flags&TLCRCV) && tlcptr->sndchn == sndchn) {
          tlcptr->flags&=~TLCRCV;
     }
}

VOID
aboarcvs(VOID)                     /* about all receives/receive requests  */
{
     INT i;

     for (i=0 ; i < nterms ; i++) {
          if (tlclst[i].sndstt != NOSEND && tlclst[i].rcvchn == usrnum) {
               aborcv(i);
          }
     }
}

static VOID
tlcxdone(VOID)                     /* file transfer-done handler           */
{
}

static VOID
tlcabort(VOID)                     /* abort-request handler                */
{
}

static VOID
tlcfin(VOID)                       /* system shutdown hook handler         */
{
}

static VOID
reg_dpk(VOID)                      /* register dynapaks                    */
{
     register_dpkfda("GALTLC","sau:channel",longFDA);
     register_dpkfda("GALTLC","sau:bgnxfr" ,tlcfilFDA);
     register_dpkfda("GALTLC","sau:nmtalk" ,rtextFDA);
     register_dpkfda("GALTLC","sau:whisper" ,rtextFDA);
}
