home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / networking / amitcp / amitcp_tnserv.lha / tnserv / TelnetGetty / TelnetGetty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-15  |  39.7 KB  |  1,602 lines

  1. #define CLIB_SOCKET_INLINES_H /* avoid that include file */
  2. #include <exec/types.h>
  3. #include <exec/memory.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <dos/dos.h>
  7. #include <dos/dosextens.h>
  8. #include <dos/dostags.h>
  9. #include <proto/dos.h>
  10. #include <proto/exec.h>
  11. #include <proto/utility.h>
  12. #include <errno.h>
  13. #include <sys/ioctl.h>
  14. #include <exec/errors.h>
  15. #include <devices/serial.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <inetd.h>
  20.  
  21. #include <fakesr.h>
  22. /*#include <libraries/multiuser.h>
  23. #include <proto/multiuser.h>
  24. */
  25. /* IMPORTANT: Do NOT link this module with the startup code */
  26.  
  27. struct InstData {
  28.     struct Library *DOSB;
  29.     struct Library *SocketB;
  30.     struct Library *UtilityB;
  31.     int Socket;
  32.     signed short RecvBuf[1024];
  33.     int RecvBufPos;
  34.     int RecvBufFlags;
  35. /* Defines for RecvBufFlags: */
  36. #define RBF_SUBNEGOTIATE (1<<0)
  37. };
  38.  
  39. #undef DEBUG
  40.  
  41. struct Library *SocketBase; /* Linker wants it. We don't use it */
  42. #ifndef USE_INETD
  43. struct Library *SysBase;
  44. #endif
  45.  
  46. const char *Signature="FAKEMSG--EXPUNGE";
  47.  
  48. #define DOSBase Inst->DOSB
  49. #define SocketBase Inst->SocketB
  50. #define UtilityBase Inst->UtilityB
  51. #define Socket Inst->Socket
  52.  
  53. /* telnet symbols */
  54. #define IAC 255
  55. #define WILL 251
  56. #define WONT 252
  57. #define DO 253
  58. #define DONT 254
  59. #define ECHO 1
  60. #define LINEMODE 34
  61. #define SE 240
  62. #define SB 250
  63. #define MODE 1
  64. #define EDIT 1
  65.  
  66. struct PasswdInfo {
  67.     char Login[50];
  68.     char Passwd[50];
  69.     char RealName[150];
  70.     char WorkDir[256];
  71.     char Command[512];
  72. };
  73.  
  74. void SockPuts(struct InstData *Inst,int Sock,char *Buf);
  75. void SockGets(struct InstData *Inst,int Sock,char *Buf,int BufSize);
  76. unsigned long GetInt(char *String,char **NewPtr);
  77. struct PasswdInfo *LookupPasswd(struct InstData *Inst,char *Login);
  78. int __asm SubSubProc(register __a0 char *ArgString,register __d0 long Length);
  79. struct DosPacket *PktFromMsg(struct Message *Msg);
  80. void MakeLongStr(char *StrBuf,unsigned long Num);
  81. void SockWrite(struct InstData *Inst,int Sock,char *Buf,int Len,int RawFlag);
  82. int RecvChar(struct InstData *Inst,int Sock,unsigned char *Loc,int RawMode);
  83. struct Process *MyCreateNewProcTags(struct InstData *,ULONG,...);
  84. void *MyAllocDosObjectTags(struct InstData *,ULONG,ULONG,...);
  85. void PktFPuts(struct InstData *Inst,BPTR File,char *String);
  86. void SockRawWrite(struct InstData *Inst,int Sock,char *Buf,int Len);
  87. void MySystemTags(struct Library *DSBse,char *Cmd,ULONG Tag0,...);
  88. void mystrcat(char *Dest,char *Cat);
  89. void MyFPrintf(struct InstData *Inst,BPTR File,char *Fmt,...);
  90.  
  91. ULONG FakeBeginIO(void *IORequest);
  92. ULONG FakeAbortIO(void *IORequest);
  93. ULONG FakeOpen(void *IORequest);
  94. ULONG FakeClose(void *IORequest);
  95. void mymovmem(char *From,char *To,int Len);
  96.  
  97. #define NewList(list) {(list)->lh_Head=(struct Node *)&(list)->lh_Tail;(list)->lh_Tail=NULL;(list)->lh_TailPred=(struct Node *)&(list)->lh_Head;}
  98. #define bzero(base,n) memset(base,0,n)
  99. #define bcopy(from,to,n) memcpy(to,from,n)
  100. #ifdef DEBUG
  101.   BPTR DebugFile;
  102. #endif
  103.  
  104. /* SubProcCode MUST be the first function in the file */
  105. #ifdef USE_INETD
  106. void main(void)
  107. #else
  108. int __asm SubProcCode(register __a0 char *ArgStr,register __d0 long Length)
  109. /* ArgString will look like: "[SocketID] [SigNum] [ParentTaskID]" */
  110. #endif
  111. {
  112.     int Cnt;
  113.     unsigned long SockID,SigID,TaskID;
  114.     char Buf[1000],LoginBuf[50];
  115.     BPTR BannerFile=NULL;
  116.     struct InstData *Inst=NULL;
  117.     struct PasswdInfo *Info=NULL;
  118.     struct FileHandle *FH;
  119.     struct Message *Msg,*GotMsg;
  120.     char NoEcho[7];
  121.     char Echo[14];
  122.     char *ArgString;
  123.     int OpenCount=0;
  124.     int AmntRead;
  125.     int HangupFlag=FALSE;
  126.     
  127.     ULONG SigMask;
  128.     long yes=TRUE;
  129.     fd_set RdSet;
  130.     fd_set WrSet;
  131.     struct List ReadWaitList;
  132.     struct DosPacket *Pkt;
  133.     int Err;
  134.     unsigned char Chr,NumBuf[30];
  135.     int RawMode=FALSE;
  136.     int NextChar=-1;
  137.     struct MsgPort *TimePort;
  138.     struct timerequest *TimeReq;
  139.     /*struct Library *muBase=NULL;*/
  140.     struct DaemonMessage *InetdStartup;
  141.     struct Process *Self;
  142.     
  143.     
  144. #ifndef USE_INETD
  145.     SysBase=*((struct Library **)0x00000004);
  146.     ArgString=ArgStr;
  147. #endif
  148. /*
  149.     Echo[0]=NoEcho[0]=IAC;
  150.     Echo[1]=WONT;
  151.     Echo[2]=ECHO;
  152.     NoEcho[1]=WILL;
  153.     NoEcho[2]=ECHO;
  154.     Echo[3]=NoEcho[3]='\0';
  155. */    
  156.     Echo[0]=NoEcho[0]=IAC;
  157.     Echo[1]=WONT;
  158.     Echo[2]=ECHO;
  159.     Echo[3]=IAC;
  160.     Echo[4]=DO;
  161.     Echo[5]=LINEMODE;
  162.     Echo[6]=IAC;
  163.     Echo[7]=SB;
  164.     Echo[8]=LINEMODE;
  165.     Echo[9]=MODE;
  166.     Echo[10]=EDIT;
  167.     Echo[11]=IAC;
  168.     Echo[12]=SE;
  169.     NoEcho[1]=WILL;
  170.     NoEcho[2]=ECHO;
  171.     NoEcho[3]=IAC;
  172.     NoEcho[4]=DONT;
  173.     NoEcho[5]=LINEMODE;
  174.     Echo[13]=NoEcho[6]='\0';
  175.  
  176. #ifndef USE_INETD
  177.     for (Cnt=0;Cnt < Length;Cnt++) {
  178.         if (ArgStr[Cnt]!=' ' && (ArgStr[Cnt] < '0' || ArgStr[Cnt] > '9')) 
  179.             return ERROR_FILE_NOT_OBJECT;
  180.     }
  181. #endif    
  182.     Inst=AllocMem(sizeof(struct InstData),MEMF_CLEAR);
  183.     if (!Inst) return 0;
  184.     DOSBase=OpenLibrary("dos.library",36);
  185.     UtilityBase=OpenLibrary("utility.library",36);
  186.     SocketBase=OpenLibrary("bsdsocket.library",2);
  187. /*    muBase=OpenLibrary("multiuser.library",39);*/
  188.     
  189.     
  190.     TimePort=CreateMsgPort();
  191.  
  192.     if (!DOSBase || !UtilityBase || !SocketBase || !TimePort) return 0;
  193. #ifdef DEBUG
  194.     DebugFile=Open("con:0/0/500/100/TelnetGetty DEBUG/WAIT/CLOSE",MODE_OLDFILE);
  195.     FPuts(DebugFile,"TelnetGetty starting\nArgString=");
  196.     FPuts(DebugFile,ArgString);
  197.     FPuts(DebugFile,"\n");
  198.     
  199. #endif
  200.  
  201. #ifdef USE_INETD
  202.     Self=FindTask(NULL);
  203.     InetdStartup=(struct DaemonMessage *)Self->pr_ExitData;
  204.     if (!InetdStartup) goto quit;
  205.     Socket=ObtainSocket(InetdStartup->dm_Id,InetdStartup->dm_Family,InetdStartup->dm_Type,0);
  206.     if (Socket < 0) goto quit;
  207.     
  208. #else
  209.     /* Get arguments */
  210.     NewList(&ReadWaitList);
  211.     SockID=GetInt(ArgString,&ArgString);
  212.     ArgString++; /* Skip over space */
  213.     SigID=GetInt(ArgString,&ArgString);
  214.     ArgString++; /* Skip over space */
  215.     TaskID=GetInt(ArgString,&ArgString);
  216.     /* After this call, the parameter string is no longer valid */
  217.     Signal((struct Task *)TaskID,1<<SigID);
  218. #ifdef DEBUG
  219.     FPuts(DebugFile,"Signaled parent\n");
  220. #endif
  221.     
  222.     /* We're on our own now */
  223.     Socket=ObtainSocket(SockID,AF_INET,SOCK_STREAM,0);
  224.     if (Socket < 0) goto quit;
  225.  
  226. #endif
  227.  
  228. #ifdef DEBUG
  229.     FPuts(DebugFile,"Got Socket\n");
  230. #endif
  231.     /* First, display banner, ask for password, etc */
  232.     BannerFile=Open("tnserv:banner",MODE_OLDFILE);
  233.     if (!BannerFile) goto quit;
  234. #ifdef DEBUG
  235.     FPuts(DebugFile,"Opened tnserv:banner\n");
  236. #endif
  237.     while (FGets(BannerFile,Buf,sizeof(Buf))) {
  238.         SockWrite(Inst,Socket,Buf,strlen(Buf),FALSE);
  239.     }
  240. #ifdef DEBUG
  241.     FPuts(DebugFile,"Wrote tnserv:banner to socket\n");
  242. #endif
  243.     /* Get login name */
  244.     SockPuts(Inst,Socket,"Login: ");
  245.     SockPuts(Inst,Socket,Echo);
  246.     SockGets(Inst,Socket,LoginBuf,sizeof(LoginBuf));
  247.     while (strlen(LoginBuf) && (LoginBuf[strlen(LoginBuf)-1]=='\n' || LoginBuf[strlen(LoginBuf)-1]=='\r'))
  248.         LoginBuf[strlen(LoginBuf)-1]='\0';
  249. #ifdef DEBUG
  250.     FPuts(DebugFile,"Got Login: ");
  251.     FPuts(DebugFile,LoginBuf);
  252.     FPuts(DebugFile,"\n");
  253. #endif
  254.     
  255.   Info=LookupPasswd(Inst,LoginBuf);
  256.   if (!Info || strcmp(Info->Passwd,"*")) {
  257.   
  258.       strcpy(Buf,"Password: ");
  259.       strcpy(Buf+strlen(Buf),NoEcho);
  260.       SockPuts(Inst,Socket,Buf);
  261.       SockGets(Inst,Socket,Buf,sizeof(Buf));
  262.       while (strlen(Buf) && (Buf[strlen(Buf)-1]=='\n' || Buf[strlen(Buf)-1]=='\r'))
  263.           Buf[strlen(Buf)-1]='\0';
  264.       SockPuts(Inst,Socket,Echo);
  265. #ifdef DEBUG
  266.       FPuts(DebugFile,"Got Password: ");
  267.       FPuts(DebugFile,Buf);
  268.       FPuts(DebugFile,"\n");
  269. #endif
  270.       if (strcmp(Buf,Info->Passwd)) {
  271.           SockPuts(Inst,Socket,"\nLogin incorrect.\nClosing connection\n");
  272.           CloseSocket(Socket);
  273.           goto quit;
  274.       }
  275.   }
  276.     
  277.   
  278. /*
  279.     if (muBase) {
  280.         struct TagItem tags[]={
  281.             {muT_Graphical,FALSE},
  282.             {muT_Task,NULL},
  283.             {muT_Global,FALSE},
  284.             /*{muT_Quiet,FALSE},*/
  285.             /* {muT_All,FALSE}, */
  286.             {muT_UserID,NULL},
  287.             {muT_Password,NULL},
  288.             {TAG_END,0}
  289.         };
  290.         tags[1].ti_Data=FindTask(NULL);
  291.         tags[5].ti_Data=LoginBuf;
  292.         tags[6].ti_Data=Buf;
  293.         muLoginA(tags);
  294.     }
  295.     */
  296.     SockPuts(Inst,Socket,"\n");
  297.     
  298.     if (Info->Command[0]=='*') {
  299.         /* Use stdin/stdout */
  300.         /* Make myself a filehandle */
  301. #ifdef DEBUG
  302.         FPuts(DebugFile,"Logged in OK\nMaking Filehandle\n");
  303. #endif
  304.         
  305.         FH=MyAllocDosObjectTags(Inst,DOS_FILEHANDLE,ADO_FH_Mode,MODE_OLDFILE,TAG_END);
  306.         if (!FH) goto quit;
  307.         FH->fh_Pos=FH->fh_End=-1;
  308.         FH->fh_Type=&((struct Process *)FindTask(NULL))->pr_MsgPort;
  309.         FH->fh_Args=(LONG)Info;
  310.         FH->fh_Port=FH->fh_Type; /* Is this right? */
  311.         FH=(struct FileHandle *)MKBADDR(FH);
  312.         OpenCount++;
  313.         
  314.         /* Run the subprocess */
  315.         MakeLongStr(Buf,(ULONG)FH);
  316.         strcpy(Buf+strlen(Buf)," ");
  317.         strcpy(Buf+strlen(Buf),Info->Command+1 /* ignore the leading '*' */);
  318. #ifdef DEBUG
  319.         FPuts(DebugFile,"Starting subprocess\nCmdLine=");
  320.         FPuts(DebugFile,Buf);
  321.         FPuts(DebugFile,"\n");
  322.         /*Close(DebugFile);*/
  323.         Flush(DebugFile);
  324.         
  325.         /*DebugFile=NULL;*/
  326. #endif
  327.     
  328.         /* NO more DOS calls allowed after this one */
  329.         /* We also can't use Buf after we make this call */
  330.     if (*(Info->Command+1)) {
  331.           MyCreateNewProcTags(Inst,NP_Entry,SubSubProc,
  332.               NP_Arguments,Buf,
  333.               NP_Name,"Telnet subprocess",
  334.               TAG_END);
  335.     }
  336.         FD_ZERO(&RdSet);
  337.         IoctlSocket(Socket,FIONBIO,(caddr_t)&yes);
  338. #ifdef DEBUG
  339.         PktFPuts(Inst,DebugFile,"Starting handler support\n");
  340. #endif
  341.         for (;;) {
  342.             if (ReadWaitList.lh_Head->ln_Succ && !HangupFlag) {
  343.                 if (NextChar != -1) {
  344.                     Pkt=PktFromMsg((struct Message *)ReadWaitList.lh_Head);
  345.                     *(((unsigned char *)Pkt->dp_Arg2)+Pkt->dp_Res1)=NextChar;
  346.                     Chr=NextChar;
  347.                     NextChar=-1;
  348.                     Err=1;
  349.                     Pkt->dp_Res1++;
  350.                     if (Pkt->dp_Res1==Pkt->dp_Arg3 || Chr=='\r' || Chr=='\n') {
  351.                         Remove(ReadWaitList.lh_Head);
  352.                         PutMsg(Pkt->dp_Port,Pkt->dp_Link); /* Send it back */
  353.                     }
  354.                 }
  355.             }    
  356.             if (ReadWaitList.lh_Head->ln_Succ && !HangupFlag) {
  357.                 FD_SET(Socket,&RdSet);
  358.             } else {    
  359.                 FD_CLR(Socket,&RdSet);
  360.             }
  361.             SigMask=(1<<((struct Process *)FindTask(NULL))->pr_MsgPort.mp_SigBit)|(1<<TimePort->mp_SigBit);
  362.             WaitSelect(Socket+1,&RdSet,NULL,NULL,NULL,&SigMask);
  363. #ifdef DEBUG
  364.             PktFPuts(Inst,DebugFile,"Wait ended \n");
  365. #endif
  366.     
  367.             if (FD_ISSET(Socket,&RdSet)) {
  368. #ifdef DEBUG
  369.                 PktFPuts(Inst,DebugFile,"Got read available from socket\n");
  370. #endif
  371.                 if (ReadWaitList.lh_Head->ln_Succ) {
  372.                     /* Someone is waiting to read */
  373.                     Pkt=PktFromMsg((struct Message *)ReadWaitList.lh_Head);
  374.                     if (Pkt && Pkt->dp_Type==ACTION_READ) {
  375. #ifdef DEBUG
  376.                         PktFPuts(Inst,DebugFile,"Performing delayed read\n");
  377. #endif
  378.                         while (Pkt->dp_Res1 < Pkt->dp_Arg3) {
  379.                             if (NextChar != -1) {
  380.                                 *(((unsigned char *)Pkt->dp_Arg2)+Pkt->dp_Res1)=NextChar;
  381.                                 Chr=NextChar;
  382.                                 NextChar=-1;
  383.                                 Err=1;
  384.                             } else {
  385.                                 Err=RecvChar(Inst,Socket,((char *)Pkt->dp_Arg2)+Pkt->dp_Res1,FALSE/*RawMode*/);
  386.                                 Chr=*(((char *)Pkt->dp_Arg2)+Pkt->dp_Res1);
  387.                             }
  388.                             if (Err==1) Pkt->dp_Res1++;
  389.                             else if (Err==0) {
  390.                                 /* Hangup */
  391.                                 HangupFlag=TRUE;
  392.                                 break;
  393.                             } else break;
  394. #ifdef DEBUG
  395.                             if (Chr==255) {
  396.                                 PktFPuts(Inst,DebugFile,"Received 255\n");
  397.                             }
  398. #endif
  399.                             if (Chr=='\r' || Chr=='\n') {
  400.                                 break;
  401.                             }
  402.                         }
  403.                         if (Err==1) {
  404.                             if (Pkt->dp_Res1==Pkt->dp_Arg3 || Chr=='\r' || Chr=='\n') {
  405.                                 Remove(ReadWaitList.lh_Head);
  406.                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link); /* Send it back */
  407.                             }
  408.                         }
  409.                     } else if (Pkt && Pkt->dp_Type==ACTION_WAIT_CHAR) {
  410. #ifdef DEBUG
  411.                         PktFPuts(Inst,DebugFile,"Processing WAIT_CHAR");
  412. #endif
  413.                         if (NextChar==-1) {
  414.                             Err=RecvChar(Inst,Socket,&Chr,FALSE);
  415.                             if (Err==1) {
  416.                                 Pkt->dp_Res1=DOSTRUE;
  417.                                 Remove(ReadWaitList.lh_Head);
  418. #ifdef DEBUG
  419.                                 PktFPuts(Inst,DebugFile,"char ready\n");
  420. #endif
  421.                                 AbortIO((struct IORequest *)Pkt->dp_Res2);
  422.                                 WaitIO((struct IORequest *)Pkt->dp_Res2);
  423.                                 CloseDevice((struct IORequest *)Pkt->dp_Res2);
  424.                                 DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  425.                                 Pkt->dp_Res2=0;
  426.                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  427.                                 NextChar=Chr;
  428.                             } else {
  429. #ifdef DEBUG
  430.                                 PktFPuts(Inst,DebugFile,"no char available\n");
  431. #endif
  432.                                 NextChar=-1;
  433.                             }
  434.                             if (Err==0) HangupFlag=TRUE;
  435.                         } else {
  436.                             Pkt->dp_Res1=DOSTRUE;
  437.                             Remove(ReadWaitList.lh_Head);
  438.                             AbortIO((struct IORequest *)Pkt->dp_Res2);
  439.                             WaitIO((struct IORequest *)Pkt->dp_Res2);
  440.                             CloseDevice((struct IORequest *)Pkt->dp_Res2);
  441.                             DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  442.                             Pkt->dp_Res2=0;
  443.                             PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  444. #ifdef DEBUG
  445.                             PktFPuts(Inst,DebugFile,"char ready\n");
  446. #endif
  447.                         }
  448.                     }
  449.                     else { /* Invalid message */
  450.                         Remove(ReadWaitList.lh_Head);
  451.                     }
  452.                 } else {
  453. #ifdef DEBUG
  454.                     PktFPuts(Inst,DebugFile,"Unexpected: got read ready, no request\n");
  455. #endif                
  456.                 }
  457.             }
  458.             while (TimeReq=(struct timerequest *)GetMsg(TimePort)) {
  459.                 Msg=(struct Message *)TimeReq->tr_node.io_Message.mn_Node.ln_Name;
  460.                 Pkt=PktFromMsg(Msg);
  461.                 CloseDevice(TimeReq);
  462.                 DeleteIORequest(TimeReq);
  463.                 Pkt->dp_Res1=DOSFALSE;
  464.                 Pkt->dp_Res2=0;
  465.                 Remove(Msg); /* Remove it from the read wait list */
  466.                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  467.                 
  468.                 
  469.             }
  470.             while (Msg=GetMsg(&((struct Process *)FindTask(NULL))->pr_MsgPort)) {
  471.                 Pkt=PktFromMsg(Msg);
  472. #ifdef DEBUG
  473.                 PktFPuts(Inst,DebugFile,"Got packet\n");
  474. #endif
  475.                 switch(Pkt->dp_Type) {
  476.                     case ACTION_FINDINPUT:
  477.                     case ACTION_FINDOUTPUT:
  478.                     case ACTION_FINDUPDATE:
  479.                         FH=(struct FileHandle *)BADDR((BPTR)Pkt->dp_Arg1);
  480.                         FH->fh_Pos=FH->fh_End=-1;
  481.                         FH->fh_Type=&((struct Process *)FindTask(NULL))->pr_MsgPort;
  482.                         FH->fh_Args=(LONG)Info;
  483.                         FH->fh_Port=FH->fh_Type; /* Is this right? */
  484.                         OpenCount++;
  485.                         Pkt->dp_Res1=DOSTRUE;
  486.                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);    
  487.                     break;
  488.                     
  489.                     case ACTION_READ:
  490.                     Pkt->dp_Res1=0;
  491. #ifdef DEBUG
  492.                     PktFPuts(Inst,DebugFile,"Got action_read\n");
  493. #endif
  494.                     AddTail(&ReadWaitList,Msg);
  495.                     break;
  496.                     
  497.                     case ACTION_WRITE:
  498. #ifdef DEBUG
  499.                     PktFPuts(Inst,DebugFile,"Got action_write\n");
  500. #endif
  501.                     SockWrite(Inst,Socket,(char *)Pkt->dp_Arg2,Pkt->dp_Arg3,FALSE/*RawMode*/);
  502.                     Pkt->dp_Res1=Pkt->dp_Arg3;
  503.                     PutMsg(Pkt->dp_Port,Pkt->dp_Link);    
  504.                     break;
  505.                     
  506.                     case ACTION_WAIT_CHAR:
  507. #ifdef DEBUG
  508.                         PktFPuts(Inst,DebugFile,"Got action_waitchar");
  509. #endif
  510.                         Pkt->dp_Res1=DOSFALSE;
  511.                         
  512.                         TimeReq=CreateIORequest(TimePort,sizeof(struct timerequest));
  513.                         if (!TimeReq || OpenDevice("timer.device",UNIT_MICROHZ,TimeReq,0)) {
  514.                             if (TimeReq) DeleteIORequest(TimeReq);
  515.                             Pkt->dp_Res2=ERROR_NO_FREE_STORE;
  516.                             PutMsg(Pkt->dp_Port,Pkt->dp_Link);                        
  517.                         }
  518.                         TimeReq->tr_node.io_Command=TR_ADDREQUEST;
  519.                         TimeReq->tr_time.tv_micro=Pkt->dp_Arg1;
  520.                         TimeReq->tr_time.tv_secs=0;
  521.                         TimeReq->tr_node.io_Message.mn_Node.ln_Name=Msg;
  522.                         SendIO(TimeReq);
  523.                         Pkt->dp_Res2=(ULONG)TimeReq;
  524.                         
  525.                         AddTail(&ReadWaitList,Msg);
  526.                     
  527.                     break;
  528.     
  529.     /*
  530.                     case ACTION_DISKINFO:
  531.                     
  532.                     break;
  533.                     */
  534.                     case ACTION_SCREEN_MODE:
  535. #ifdef DEBUG
  536.                     PktFPuts(Inst,DebugFile,"Got action_screen_mode\n");
  537. #endif
  538.                         if (Pkt->dp_Arg1) {
  539.                             /* Raw mode */
  540.                             SockPuts(Inst,Socket,NoEcho);
  541.                             RawMode=TRUE;
  542.                         } else {
  543.                             SockPuts(Inst,Socket,Echo);
  544.                             RawMode=FALSE;
  545.                         }
  546.                         Pkt->dp_Res1=DOSFALSE;
  547.                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  548.                     break;
  549.                     
  550.                     case ACTION_END:
  551. #ifdef DEBUG
  552.                     PktFPuts(Inst,DebugFile,"Got action_end\n");
  553. #endif
  554.                         Pkt->dp_Res1=0;
  555.                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  556.                         OpenCount--;
  557.                         if (!OpenCount) {
  558.                             for (GotMsg=ReadWaitList.lh_Head;GotMsg->mn_Node.ln_Succ;GotMsg=(struct Message *)GotMsg->mn_Node.ln_Succ) {
  559.                                 Pkt=PktFromMsg(GotMsg);
  560.                                 if (Pkt->dp_Type==ACTION_WAIT_CHAR) {
  561.                                     AbortIO((struct IORequest *)Pkt->dp_Res2);
  562.                                     WaitIO((struct IORequest *)Pkt->dp_Res2);
  563.                                     CloseDevice((struct IORequest *)Pkt->dp_Res2);
  564.                                     DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  565.                                     Pkt->dp_Res2=0;
  566.                                 }
  567.                             }
  568.                             
  569.                             goto quit;
  570.                         }
  571.                     break;
  572.                     
  573.                     case ACTION_SEEK:
  574. #ifdef DEBUG
  575.                     PktFPuts(Inst,DebugFile,"Got action_seek\n");
  576. #endif
  577.                     Pkt->dp_Res1=-1;
  578.                     Pkt->dp_Res2=ERROR_OBJECT_WRONG_TYPE;
  579.                     PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  580.                     
  581.                     break;
  582.                     
  583.                     
  584.                     default:
  585. #ifdef DEBUG
  586.                     PktFPuts(Inst,DebugFile,"Got action_not_known. Number");
  587.                     MakeLongStr(NumBuf,Pkt->dp_Type);
  588.                     PktFPuts(Inst,DebugFile,NumBuf);
  589.                     PktFPuts(Inst,DebugFile,"\n");
  590. #endif
  591.                     Pkt->dp_Res1=0;
  592.                     Pkt->dp_Res2=ERROR_ACTION_NOT_KNOWN;
  593.                     PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  594.                 }
  595.             }
  596.         }
  597.     } else {
  598.         /* Use fake serial */
  599.         struct IOStdReq *IOReq=NULL;
  600.         struct MsgPort *IOPort=NULL;
  601.         struct FSRUnit *SerUnit=NULL;
  602.         /* SerUnit->fsru_UserData[0]=CmdPort
  603.            SerUnit->fsru_UserData[1]=ReadQueue
  604.              SerUnit->fsru_UserData[2]=WriteQueue
  605.              SerUnit->fsru_UserData[3]=Open count 
  606.              SerUnit->fsru_UserData[4]=RBufLen */
  607.         struct MsgPort *CmdPort=NULL;
  608.         struct List *ReadQueue=NULL;
  609.         struct List *WriteQueue=NULL;
  610.         char *CmdPtr;
  611.         struct IOExtSer *GotReq=NULL,*OtrReq=NULL;
  612.         char *RBuf=NULL;
  613.         int RBufPos=0;
  614.         int SerUnitAdded=FALSE;
  615.         int Amnt;
  616.         int RecvRet;
  617.         int CD=TRUE; /* Carrier Detect */
  618.         long UnitNum=FSR_UNITNONE;
  619.         
  620.         /* We use IOExtSer.Status bit 0 as a flag to say whether this request has
  621.            been aborted */
  622.         
  623. #ifdef DEBUG
  624.         FPuts(DebugFile,"Creating ports...\n");
  625. #endif
  626.         IOPort=CreateMsgPort();
  627.         CmdPort=CreateMsgPort();
  628.         IOReq=CreateIORequest(IOPort,sizeof(struct IOStdReq));
  629.         if (!IOPort || !IOReq || !CmdPort) {
  630. #ifdef DEBUG
  631.             FPuts(DebugFile,"Unable to create message port/IORequest\nExiting\n");
  632. #endif
  633.             goto quitfakeser;
  634.         }
  635. #ifdef DEBUG
  636.         FPuts(DebugFile,"Opening fakesr.device...\n");
  637. #endif        
  638.         if (OpenDevice("fakesr.device",FSR_CTLUNIT,IOReq,0)) {
  639.             IOReq->io_Device=NULL;
  640. #ifdef DEBUG
  641.             FPuts(DebugFile,"Unable to open fakesr.device\nExiting\n");
  642. #endif
  643.             goto quitfakeser;
  644.         }
  645. #ifdef DEBUG
  646.         FPuts(DebugFile,"opened successfully\n");
  647. #endif
  648.         SerUnit=AllocMem(sizeof(struct FSRUnit),MEMF_CLEAR|MEMF_PUBLIC);
  649.         ReadQueue=AllocMem(sizeof(struct List),MEMF_PUBLIC);
  650.         if (ReadQueue) NewList(ReadQueue);
  651.         WriteQueue=AllocMem(sizeof(struct List),MEMF_PUBLIC);
  652.         if (WriteQueue) NewList(WriteQueue);
  653.         if (!SerUnit || !ReadQueue || !WriteQueue) {
  654. #ifdef DEBUG
  655.             FPuts(DebugFile,"Unable to allocate memory\nExiting\n");
  656. #endif            
  657.             goto quitfakeser;
  658.         }
  659.         
  660.         CmdPtr=Info->Command;
  661.         if (Info->Command[0]<='9' && Info->Command[0] >= '0') {
  662.             UnitNum=GetInt(Info->Command,&CmdPtr);
  663.         }
  664.         
  665.         SerUnit->fsru_Num=UnitNum;
  666.         SerUnit->fsru_BeginIO=FakeBeginIO;
  667.         SerUnit->fsru_AbortIO=FakeAbortIO;
  668.         SerUnit->fsru_Open=FakeOpen;
  669.         SerUnit->fsru_Close=FakeClose;
  670.         SerUnit->fsru_UserData[0]=CmdPort;
  671.         SerUnit->fsru_UserData[1]=ReadQueue;
  672.         SerUnit->fsru_UserData[2]=WriteQueue;
  673.         SerUnit->fsru_UserData[3]=0;
  674.         SerUnit->fsru_UserData[4]=(void *)1024;
  675.         
  676.         IOReq->io_Data=(APTR)SerUnit;
  677.         IOReq->io_Length=sizeof(*SerUnit);
  678.         IOReq->io_Command=FSRCMD_ADDUNIT;
  679.         IOReq->io_Error=0;
  680. #ifdef DEBUG
  681.         FPuts(DebugFile,"Adding FakeSr unit...");
  682. #endif
  683.  
  684.         DoIO(IOReq);
  685.         if (IOReq->io_Error) {
  686. #ifdef DEBUG
  687.             FPuts(DebugFile,"Error adding fakesr.device unit\nExiting\n");
  688. #endif                        
  689.             goto quitfakeser;
  690.         }
  691.  
  692.         SerUnitAdded=TRUE;
  693.  
  694. #ifdef DEBUG
  695.         FPuts(DebugFile,"Done\n");
  696. #endif
  697.  
  698.         RBuf=AllocMem((ULONG)SerUnit->fsru_UserData[4],MEMF_PUBLIC);
  699.         RBufPos=0;
  700.         if (!RBuf) {
  701. #ifdef DEBUG
  702.             FPuts(DebugFile,"Unable to allocate memory\nExiting\n");
  703. #endif                        
  704.             goto quitfakeser;
  705.         }
  706.         
  707.  
  708.         IoctlSocket(Socket,FIONBIO,(caddr_t)&yes);
  709.         {
  710.             BPTR NilInput,NilOutput;
  711. #ifdef DEBUG
  712.             FPuts(DebugFile,"Opening filehandles\n");
  713. #endif
  714.       if (*CmdPtr) {
  715.               NilInput=Open("NIL:",MODE_OLDFILE);
  716.               NilOutput=Open("NIL:",MODE_OLDFILE);
  717.  
  718.               /* sprintf(Buf,"%s -DEVICE fakesr.device -UNIT %ld",CmdPtr,SerUnit->fsru_Num); */
  719.               strcpy(Buf,CmdPtr);
  720.               mystrcat(Buf," -DEVICE fakesr.device -UNIT ");
  721.               MakeLongStr(LoginBuf,SerUnit->fsru_Num);
  722. #ifdef DEBUG
  723.               FPuts(DebugFile,"Got FakeSr unit: ");
  724.               FPuts(DebugFile,LoginBuf);
  725.               FPuts(DebugFile,"\n");
  726. #endif
  727.               SockPuts(Inst,Socket,NoEcho);
  728.  
  729.               mystrcat(Buf,LoginBuf);
  730. #ifdef DEBUG
  731.               FPuts(DebugFile,"Running command:");
  732.               FPuts(DebugFile,Buf);
  733.               FPuts(DebugFile,"\n");
  734. #endif
  735.               MySystemTags(DOSBase,Buf,SYS_Input,NilInput,SYS_Output,NilOutput,SYS_Asynch,TRUE,TAG_END);
  736.       }
  737.         }
  738.         
  739.         for (;;) {
  740.             FD_ZERO(&RdSet);
  741.             FD_ZERO(&WrSet);
  742.             if (CD)  {
  743.                 if (RBufPos < (((long)SerUnit->fsru_UserData[4])-1)) FD_SET(Socket,&RdSet);
  744.                 if (WriteQueue->lh_Head->ln_Succ) FD_SET(Socket,&WrSet);
  745.             }
  746.             SigMask=(1<<CmdPort->mp_SigBit)|SIGBREAKF_CTRL_C;
  747.             WaitSelect(Socket+1,&RdSet,&WrSet,NULL,NULL,&SigMask);
  748. #ifdef DEBUG
  749.             FPuts(DebugFile,"Wait ended...");
  750. #endif
  751.             
  752.             if (FD_ISSET(Socket,&RdSet)) {
  753.                 while ((RBufPos < (long)SerUnit->fsru_UserData[4]) && ((RecvRet=RecvChar(Inst,Socket,RBuf+RBufPos,TRUE))==1)) RBufPos++;
  754.                 Forbid();
  755.                 if ((GotReq=(struct IOExtSer *)ReadQueue->lh_Head)->IOSer.io_Message.mn_Node.ln_Succ) {
  756.                     Remove(GotReq);
  757.                     Permit();
  758.                     Amnt=min(RBufPos,GotReq->IOSer.io_Length);
  759.                     memcpy(((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,RBuf,Amnt);
  760.                     GotReq->IOSer.io_Actual+=Amnt;
  761.                     if (Amnt < RBufPos) mymovmem(RBuf+Amnt,RBuf,RBufPos-Amnt);
  762.                     RBufPos-=Amnt;
  763.                     
  764.                     if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  765.                         if (GotReq->io_Status & (1<<0)) {
  766.                             /* We got an AbortIO() */
  767.                             GotReq->IOSer.io_Error=IOERR_ABORTED;
  768.                             ReplyMsg(GotReq);
  769.                         } else {
  770.                             Forbid();
  771.                             AddTail(ReadQueue,GotReq);
  772.                             Permit();
  773.                         }
  774.                     }
  775.                     else ReplyMsg(GotReq);
  776.                     
  777.                 }
  778.                 else Permit();
  779.                 if (RecvRet==0) {
  780.                     /* Connection closed */
  781.                     CD=FALSE;
  782.                 }
  783.             }
  784.             if (FD_ISSET(Socket,&WrSet)) {
  785.                 Forbid();
  786.                 if ((GotReq=(struct IOExtSer *)WriteQueue->lh_Head)->IOSer.io_Message.mn_Node.ln_Succ) {
  787.                     Remove(GotReq);
  788.                     Permit();
  789.                     
  790. #ifdef DEBUG
  791.                     FPuts(DebugFile,"Writing to socket\n");
  792.                     MyFPrintf(Inst,DebugFile,"io_Actual=%ld,io_Length=%ld\n",(long)GotReq->IOSer.io_Actual,(long)GotReq->IOSer.io_Length);
  793. #endif
  794.                     SockWrite(Inst,Socket,((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,GotReq->IOSer.io_Length-GotReq->IOSer.io_Actual,TRUE);
  795. #ifdef DEBUG
  796.                     FPuts(DebugFile,"Write completed\n");
  797. #endif
  798.                     GotReq->IOSer.io_Actual=GotReq->IOSer.io_Length;
  799.                     
  800.                     
  801.                     if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  802.                         Forbid();
  803.                         if (GotReq->io_Status & (1<<0)) {
  804.                             Permit();
  805.                             /* We got an AbortIO() */
  806.                             GotReq->IOSer.io_Error=IOERR_ABORTED;
  807.                             ReplyMsg(GotReq);
  808.                         } else {
  809.                             AddTail(WriteQueue,GotReq);
  810.                             Permit();
  811.                         }
  812.                     } else {
  813. #ifdef DEBUG
  814.                         FPuts(DebugFile,"Replying write message\n");
  815. #endif                        
  816.                         ReplyMsg(GotReq);
  817.                     }
  818.                         
  819.                     
  820.                 } else {
  821.                     
  822.                     Permit();
  823.                 }
  824.             }
  825.             while (GotReq=(struct IOExtSer *)GetMsg(CmdPort)) {
  826.                 if (GotReq->IOSer.io_Message.mn_Node.ln_Name==Signature) {
  827.                     /* We just use the pointer as a signature */
  828.                     /* We just got an expunge request */
  829. #ifdef DEBUG
  830.                     FPuts(DebugFile,"Got expunge request\n");
  831. #endif
  832.  
  833.                     FreeMem(GotReq,sizeof(struct Message)); /* We free the expunge request instead of reply */
  834.                     
  835.                     Forbid();
  836.                     if (SerUnit->fsru_UserData[3]==0) {
  837.                         /* Open count==0 */
  838.                         if (SerUnitAdded) {
  839.                             IOReq->io_Command=FSRCMD_REMUNIT;
  840.                             IOReq->io_Data=(APTR)SerUnit;
  841.                             IOReq->io_Length=sizeof(*SerUnit);
  842.                             DoIO(IOReq);
  843.                             SerUnitAdded=FALSE;
  844.                         }
  845.                         if (SerUnit->fsru_UserData[3]==0) {
  846.                             /* If opencnt is still 0 */
  847.                             Permit();
  848.                             goto quitfakeser; /* exit */
  849.                         }
  850.                     }
  851.                     Permit();
  852.                 }
  853.                 else {
  854. #ifdef DEBUG
  855.                     FPuts(DebugFile,"Got cmd...");
  856. #endif
  857.                     
  858.                     switch(GotReq->IOSer.io_Command) {
  859.                         case CMD_CLEAR:
  860. #ifdef DEBUG
  861.                             FPuts(DebugFile,"Got CMD_CLEAR\n");
  862. #endif
  863.                             RBufPos=0;
  864.                             GotReq->IOSer.io_Error=0;
  865.                             ReplyMsg(GotReq);                        
  866.                         break;
  867.                         
  868.                         case CMD_FLUSH:
  869.                         case CMD_RESET:
  870. #ifdef DEBUG
  871.                             FPuts(DebugFile,"Got CMD_FLUSH/RESET\n");
  872. #endif
  873.  
  874.                             Forbid();
  875.                             while (OtrReq=(struct IOExtSer *)RemHead(ReadQueue)) {
  876.                                 OtrReq->IOSer.io_Error=IOERR_ABORTED;
  877.                                 ReplyMsg(OtrReq);
  878.                             }
  879.                             while (OtrReq=(struct IOExtSer *)RemHead(WriteQueue)) {
  880.                                 OtrReq->IOSer.io_Error=IOERR_ABORTED;
  881.                                 ReplyMsg(OtrReq);
  882.                             }
  883.                             Permit();
  884.                             GotReq->IOSer.io_Error=0;
  885.                             ReplyMsg(GotReq);
  886.                         break;
  887.                         
  888.                         case CMD_READ:
  889. #ifdef DEBUG
  890.                             FPuts(DebugFile,"Got CMD_READ\n");
  891. #endif
  892.                             
  893.                             GotReq->IOSer.io_Actual=0;
  894.                             GotReq->IOSer.io_Error=0;
  895.                             Amnt=min(RBufPos,GotReq->IOSer.io_Length);
  896.                             memcpy(((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,RBuf,Amnt);
  897.                             GotReq->IOSer.io_Actual+=Amnt;
  898.                             if (Amnt < RBufPos) mymovmem(RBuf+Amnt,RBuf,Amnt);
  899.                             RBufPos-=Amnt;
  900.                             
  901.                             if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  902.                                 Forbid();
  903.                                 AddTail(ReadQueue,GotReq);
  904.                                 Permit();
  905.                             }
  906.                             else ReplyMsg(GotReq);
  907.                         break;
  908.                         
  909.                         case CMD_START:
  910. #ifdef DEBUG
  911.                             FPuts(DebugFile,"Got CMD_START\n");
  912. #endif
  913.  
  914.                             GotReq->IOSer.io_Error=0;
  915.                             ReplyMsg(GotReq);                        
  916.                         break;
  917.                         
  918.                         case CMD_STOP:
  919. #ifdef DEBUG
  920.                             FPuts(DebugFile,"Got CMD_STOP\n");
  921. #endif
  922.  
  923.                             GotReq->IOSer.io_Error=0;
  924.                             ReplyMsg(GotReq);                        
  925.                         break;
  926.                         
  927.                         case CMD_WRITE:
  928. #ifdef DEBUG
  929.                             FPuts(DebugFile,"Got CMD_WRITE\n");
  930. #endif
  931.                             
  932.                             GotReq->IOSer.io_Actual=0;
  933.                             GotReq->IOSer.io_Error=0;
  934.                             Forbid();
  935.                             AddTail(WriteQueue,GotReq);
  936.                             Permit();
  937.                         break;
  938.                         
  939.                         case SDCMD_BREAK:
  940. #ifdef DEBUG
  941.                             FPuts(DebugFile,"Got SDCMD_BREAK\n");
  942. #endif
  943.  
  944.                             GotReq->IOSer.io_Error=0;
  945.                             ReplyMsg(GotReq);                            
  946.                         break;
  947.                         
  948.                         case SDCMD_QUERY:
  949. #ifdef DEBUG
  950.                             FPuts(DebugFile,"Got SDCMD_QUERY\n");
  951. #endif
  952.  
  953.                             GotReq->IOSer.io_Actual=RBufPos;
  954.                             GotReq->io_Status=0x0000 | ((CD) ? 0:(1<<5));
  955.                             GotReq->IOSer.io_Error=0;
  956.                             
  957.                             ReplyMsg(GotReq);
  958.                         break;
  959.                         
  960.                         case SDCMD_SETPARAMS:
  961. #ifdef DEBUG
  962.                             FPuts(DebugFile,"Got SDCMD_SETPARAMS\n");
  963. #endif
  964.  
  965.                             GotReq->IOSer.io_Error=0;
  966.                             ReplyMsg(GotReq);                            
  967.                         break;
  968.                         
  969.                         default:
  970. #ifdef DEBUG
  971.                             FPuts(DebugFile,"Got CMD_UNKNOWN\n");
  972. #endif
  973.                             GotReq->IOSer.io_Error=IOERR_NOCMD;
  974.                             ReplyMsg(GotReq);
  975.                             
  976.                     }
  977.                 }
  978.             }
  979.         }
  980.         
  981.         
  982.         quitfakeser:
  983.         
  984.         if (ReadQueue) {
  985.             Forbid();
  986.             while (GotReq=(struct IOExtSer *)RemHead(ReadQueue)) {
  987.                 GotReq->IOSer.io_Error=IOERR_ABORTED;
  988.                 GotReq->IOSer.io_Actual=0;
  989.                 ReplyMsg(GotReq);
  990.             }
  991.             Permit();
  992.             FreeMem(ReadQueue,sizeof(struct List));
  993.         }
  994.         if (WriteQueue) {
  995.             Forbid();
  996.             while (GotReq=(struct IOExtSer *)RemHead(WriteQueue)) {
  997.                 GotReq->IOSer.io_Error=IOERR_ABORTED;
  998.                 GotReq->IOSer.io_Actual=0;
  999.                 ReplyMsg(GotReq);
  1000.             }
  1001.             Permit();
  1002.             FreeMem(WriteQueue,sizeof(struct List));
  1003.         }
  1004.         if (RBuf && SerUnit) {
  1005.             FreeMem(RBuf,(long)SerUnit->fsru_UserData[4]);
  1006.         }
  1007.         if (SerUnit) {
  1008.             if (SerUnitAdded && IOReq) {
  1009.                 IOReq->io_Data=(APTR)SerUnit;
  1010.                 IOReq->io_Length=sizeof(*SerUnit);
  1011.                 IOReq->io_Command=FSRCMD_REMUNIT;
  1012.                 DoIO(IOReq);
  1013.             }
  1014.             FreeMem(SerUnit,sizeof(struct FSRUnit));
  1015.         }
  1016.         if (IOReq) {
  1017.             if (IOReq->io_Device) CloseDevice(IOReq);
  1018.             DeleteIORequest(IOReq);
  1019.         }
  1020.         if (IOPort) DeleteMsgPort(IOPort);
  1021.         if (CmdPort) DeleteMsgPort(CmdPort);
  1022.         goto quit;
  1023.     }
  1024.           
  1025.     quit:
  1026. #ifdef DEBUG
  1027.     if (DebugFile) Close(DebugFile);
  1028. #endif
  1029.     if (TimePort) DeleteMsgPort(TimePort);
  1030.     if (Info) FreeMem(Info,sizeof(struct PasswdInfo));
  1031.     if (BannerFile) Close(BannerFile);
  1032.     if (Inst) {
  1033.         if (SocketBase) CloseLibrary(SocketBase);
  1034.         if (UtilityBase) CloseLibrary(UtilityBase);
  1035.         if (DOSBase) CloseLibrary(DOSBase);
  1036.     }
  1037.     return 0;
  1038. }
  1039.  
  1040. void MyFPrintf(struct InstData *Inst,BPTR File,char *Fmt,...)
  1041. {
  1042.     VFPrintf(File,Fmt,(&Fmt)+1);
  1043. }
  1044.  
  1045. void mystrcat(char *Dest,char *Cat)
  1046. {
  1047.     memcpy(Dest+strlen(Dest),Cat,strlen(Cat)+1);
  1048. }
  1049.  
  1050. void mymovmem(char *From,char *To,int Len)
  1051. {
  1052.     int Cnt;
  1053.     if (From > To) {
  1054.         for (Cnt=0;Cnt < Len;Cnt++) {
  1055.             To[Cnt]=From[Cnt];
  1056.         }
  1057.     } else if (From < To) {
  1058.         for (Cnt=Len-1;Cnt >= 0;Cnt--) {
  1059.             To[Cnt]=From[Cnt];
  1060.         }        
  1061.     }
  1062. }
  1063.  
  1064. struct Node *FindNode(struct List *List,struct Node *Node)
  1065. /* returns Node if Node is a member of list, NULL otherwise */
  1066. {
  1067.     struct Node *ChkNode;
  1068.     
  1069.     for (ChkNode=List->lh_Head;ChkNode->ln_Succ;ChkNode=ChkNode->ln_Succ) {
  1070.         if (ChkNode==Node) return Node;
  1071.     }
  1072.     return NULL;
  1073. }
  1074.  
  1075. ULONG FakeBeginIO(void *IORequest)
  1076. {
  1077.     ((struct IORequest *)IORequest)->io_Flags &= ~IOF_QUICK; /* Quick IO not supported */
  1078.     ((struct IOExtSer *)IORequest)->io_Status &= ~(1<<0); /* clear abort bit */
  1079.     ((struct Node *)IORequest)->ln_Name=NULL; /* clear possible signature */
  1080.     PutMsg((struct MsgPort *)((struct FSRUnit *)((struct IORequest *)IORequest)->io_Unit)->fsru_UserData[0],IORequest);
  1081.     return 0;
  1082. }
  1083.  
  1084. ULONG FakeAbortIO(void *IORequest)
  1085. {
  1086.     struct IOExtSer *Ser;
  1087.     
  1088.     Ser=IORequest;
  1089.     Forbid();
  1090.         Ser->io_Status |= (1<<0); /* Flag the request as aborted */
  1091.         if (FindNode(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[1],Ser) ||
  1092.             FindNode(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[2],Ser)) {
  1093.                 /* This IORequest is waiting to be processed */
  1094.                 Remove(Ser);
  1095.                 Ser->IOSer.io_Error=IOERR_ABORTED;
  1096.                 Ser->IOSer.io_Actual=0;
  1097.                 ReplyMsg(Ser);
  1098.         }
  1099.         else {
  1100.             /* This IORequest is currently being processed -- send a break */
  1101.             Signal(((struct MsgPort *)((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[0])->mp_SigTask,SIGBREAKF_CTRL_C);
  1102.         }
  1103.     Permit();
  1104.     
  1105.     return 0;
  1106. }
  1107.  
  1108. ULONG FakeOpen(void *IORequest)
  1109. {
  1110.     struct IOExtSer *Ser;
  1111.     
  1112.     Ser=IORequest;
  1113.     Forbid();
  1114.     ((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3]=(void *) ((long)(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3])+1); /* Increment opencnt */
  1115.     Permit();
  1116.     Ser->IOSer.io_Error=0;
  1117.     Ser->io_CtlChar=SER_DEFAULT_CTLCHAR;
  1118.     Ser->io_RBufLen=(long)((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[4];
  1119.     Ser->io_ExtFlags=0;
  1120.     Ser->io_Baud=19200;
  1121.     Ser->io_BrkTime=250000;
  1122.     Ser->io_TermArray.TermArray0=0;
  1123.     Ser->io_TermArray.TermArray1=0;
  1124.     Ser->io_ReadLen=8;
  1125.     Ser->io_WriteLen=8;
  1126.     Ser->io_StopBits=1;
  1127.     Ser->io_Status=0;
  1128.     return 0;
  1129. }
  1130.  
  1131. ULONG FakeClose(void *IORequest)
  1132. {
  1133.     struct IOExtSer *Ser;
  1134.     struct Message *Msg;
  1135.     
  1136.     Ser=IORequest;
  1137.     Forbid();
  1138.     
  1139.     ((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3]=(void *) ((long)(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3])-1); /* Decrement opencnt */
  1140.     Msg=AllocMem(sizeof(struct Message),MEMF_PUBLIC|MEMF_CLEAR);
  1141.     Msg->mn_Node.ln_Name=Signature;
  1142.     PutMsg((struct MsgPort *)((struct FSRUnit *)((struct IORequest *)IORequest)->io_Unit)->fsru_UserData[0],Msg);
  1143.     
  1144.     Permit();
  1145.     return 0;
  1146. }
  1147.  
  1148.  
  1149. struct DosPacket *PktFromMsg(struct Message *Msg)
  1150. {
  1151.     return (struct DosPacket *)Msg->mn_Node.ln_Name;
  1152. }
  1153.  
  1154. void PktFPuts(struct InstData *Inst,BPTR File,char *String)
  1155. {
  1156.     struct MsgPort *ReplyPort;
  1157.     struct DosPacket *Pkt;
  1158.     
  1159.     ReplyPort=CreateMsgPort();
  1160.     Pkt=AllocDosObject(DOS_STDPKT,NULL);
  1161.     if (!Pkt || !ReplyPort) return;
  1162.     
  1163.     Pkt->dp_Type=ACTION_WRITE;
  1164.     Pkt->dp_Arg1=((struct FileHandle *)BADDR(File))->fh_Arg1;
  1165.     Pkt->dp_Arg2=String;
  1166.     Pkt->dp_Arg3=strlen(String);
  1167.     Pkt->dp_Port=ReplyPort;
  1168.     PutMsg(((struct FileHandle *)BADDR(File))->fh_Type,Pkt->dp_Link);
  1169.     WaitPort(ReplyPort);
  1170.     GetMsg(ReplyPort);
  1171.     DeleteMsgPort(ReplyPort);
  1172.     FreeDosObject(DOS_STDPKT,Pkt);
  1173. }
  1174.  
  1175. unsigned long GetInt(char *String,char **NewPtr)
  1176. {
  1177.     unsigned long Num=0;
  1178.     char *Junk;
  1179.     long Cnt;
  1180.     long BaseNum;
  1181.     
  1182.     if (!NewPtr) NewPtr=&Junk;
  1183.     
  1184.     for (*NewPtr=String;;(*NewPtr)++) {
  1185.         
  1186.         if (**NewPtr < '0' || **NewPtr > '9') return Num;
  1187.         
  1188.         /* AAARGH!! multiplication causes a lib call to be generated.
  1189.            We can't use the library. Therefore we have to add */
  1190.         /* Num=Num*10; */
  1191.         for (BaseNum=Num,Cnt=0;Cnt < 9;Cnt++,Num+=BaseNum);
  1192.         
  1193.         
  1194.         Num+=**NewPtr-'0';
  1195.     }
  1196.     
  1197. }
  1198.  
  1199.  
  1200. void SockPuts(struct InstData *Inst,int Sock,char *Buf)
  1201. {
  1202.     int BufPos=0;
  1203.     int BytesWritten;
  1204.     
  1205.     do {
  1206.         BytesWritten=send(Sock,Buf+BufPos,strlen(Buf+BufPos),0);
  1207.         if (BytesWritten > 0) BufPos+=BytesWritten;
  1208.     } while (Buf[BufPos]);
  1209. }
  1210.  
  1211. void SockRawWrite(struct InstData *Inst,int Sock,char *Buf,int Len)
  1212. {
  1213.     int BufPos=0;
  1214.     int BytesWritten;
  1215.     
  1216.     if (!Len) return;
  1217.     
  1218.     do {
  1219.         BytesWritten=send(Sock,Buf+BufPos,Len-BufPos,0);
  1220.         if (BytesWritten > 0) BufPos+=BytesWritten;
  1221.     } while (Len-BufPos);
  1222.  
  1223. }
  1224.  
  1225. void SockWrite(struct InstData *Inst,int Sock,char *Buf,int Len,int RawFlag)
  1226. {
  1227.     int Cnt;
  1228.     int BufPos=0;
  1229.     char iac2[2];
  1230.     char eol[2];
  1231.     char csi[2];
  1232.     iac2[0]=iac2[1]=IAC;
  1233.     eol[0]='\r';
  1234.     eol[1]='\n';
  1235.     csi[0]='\x1b';
  1236.     csi[1]='[';
  1237.     
  1238.     
  1239.     while (Len > BufPos) {
  1240.         for (Cnt=BufPos;Cnt < Len;Cnt++) {
  1241.             if (!RawFlag) 
  1242.                 if (Buf[Cnt]=='\r' || Buf[Cnt]=='\n') break;
  1243.                 if (Buf[Cnt]=='\x9b') break;
  1244.             if (Buf[Cnt]==IAC) {
  1245.                 break;
  1246.             }
  1247.         }
  1248.         SockRawWrite(Inst,Sock,Buf+BufPos,Cnt-BufPos);
  1249.         BufPos=Cnt;
  1250.         if (BufPos < Len && Buf[BufPos]==IAC) { /* If we got single IAC, send double IAC */
  1251.             BufPos++;
  1252.             SockRawWrite(Inst,Sock,iac2,2);
  1253.         }
  1254.         if (!RawFlag) {
  1255.             if (BufPos < Len && Buf[BufPos]=='\r') {
  1256.                 BufPos++;
  1257.             }
  1258.             if (BufPos < Len && Buf[BufPos]=='\n') {
  1259.                 BufPos++;
  1260.                 SockRawWrite(Inst,Sock,eol,2);
  1261.             }
  1262.             if (BufPos < Len && Buf[BufPos]=='\x9b') {
  1263.                 BufPos++;
  1264.                 SockRawWrite(Inst,Sock,csi,2);
  1265.             }
  1266.         }
  1267.     }
  1268. }
  1269.  
  1270. void ParseBuf3(struct InstData *Inst)
  1271. /* Parse 3 character remote request */
  1272. {
  1273.     
  1274. }
  1275.  
  1276. void ParseBuf2(struct InstData *Inst)
  1277. /* Parse 2 character remote-request */
  1278. {
  1279.     
  1280. }
  1281.  
  1282. void ParseBufSubNegotiate(struct InstData *Inst)
  1283. {
  1284.     
  1285. }
  1286.  
  1287. int RecvChar(struct InstData *Inst,int Sock,unsigned char *Loc,int RawMode)
  1288. {
  1289.     int GotLen;
  1290.     unsigned char Got,TrueGot;
  1291.     /*RawMode=TRUE;*/
  1292.     static unsigned char PrevChar;
  1293.     
  1294.     do {
  1295.         
  1296.         GotLen=recv(Sock,&Got,1,0); /* Wait for a character */
  1297.         if (GotLen==-1) {
  1298.             if (Errno()==EINTR) continue;
  1299.             else return -1;
  1300.         } else if (GotLen==0) return 0;
  1301.         
  1302.         TrueGot=Got;
  1303.         if (!Inst->RecvBufPos && GotLen==1 && Got==0) GotLen=-1; /* Read again */
  1304.         if (GotLen==1 && !RawMode && !Inst->RecvBufPos) {
  1305.             /* These next few lines ignore incoming newlines and convert
  1306.             incoming CRs into newlines   */
  1307.             if (Got=='\n' && PrevChar=='\r') GotLen=-1; /* Read again. */
  1308.             if (Got=='\r') Got='\n';
  1309.         }
  1310.     } while (GotLen != 1);
  1311. /*    *Loc=Got;
  1312.     return 1; */
  1313.     
  1314.     if (Inst->RecvBufPos) {
  1315.         Inst->RecvBuf[Inst->RecvBufPos]=Got;
  1316.         Inst->RecvBufPos++;
  1317.         switch (Inst->RecvBufPos) {
  1318.             case 2:
  1319.               switch(Inst->RecvBuf[1]) {
  1320.                     case IAC:
  1321.                       /* Just a single IAC */
  1322.                         *Loc=IAC;
  1323.                         return 1;
  1324.                     break;
  1325.                     
  1326.                     case SB:
  1327.                         Inst->RecvBufFlags|=RBF_SUBNEGOTIATE;
  1328.                         return RecvChar(Inst,Sock,Loc,RawMode);
  1329.                     break;
  1330.                     
  1331.                     case SE:
  1332.                     Inst->RecvBufPos=0;
  1333.                     Inst->RecvBufFlags &= ~RBF_SUBNEGOTIATE;
  1334.                     return RecvChar(Inst,Sock,Loc,RawMode);
  1335.                     
  1336.                     case WILL:
  1337.                     case WONT:
  1338.                     case DO:
  1339.                     case DONT:
  1340.                     return RecvChar(Inst,Sock,Loc,RawMode);
  1341.                     break;
  1342.                     
  1343.                     default:
  1344.                     ParseBuf2(Inst);
  1345.                     Inst->RecvBufPos=0;
  1346.                     return RecvChar(Inst,Sock,Loc,RawMode);
  1347.                 }
  1348.             break;
  1349.             
  1350.             default:
  1351.                 if (Inst->RecvBufFlags & RBF_SUBNEGOTIATE) {
  1352.                     if (Inst->RecvBufPos >= 2 && Inst->RecvBuf[Inst->RecvBufPos-2]==IAC && Inst->RecvBuf[Inst->RecvBufPos-1]!=IAC) {
  1353.                         /* End of subnegotiation */
  1354.                         Inst->RecvBuf[0]=IAC;
  1355.                         if ((Inst->RecvBuf[1]=Inst->RecvBuf[Inst->RecvBufPos-1])==SE) {
  1356.                             Inst->RecvBufFlags &= ~RBF_SUBNEGOTIATE;
  1357.                             Inst->RecvBufPos=0;
  1358.                             return RecvChar(Inst,Sock,Loc,RawMode);
  1359.                         }
  1360.                         Inst->RecvBufPos=2;
  1361.                         
  1362.                         ParseBufSubNegotiate(Inst);
  1363.                     }
  1364.                     
  1365.                     if (Inst->RecvBufPos >= 2 && Inst->RecvBuf[Inst->RecvBufPos-2]==IAC && Inst->RecvBuf[Inst->RecvBufPos-1]==IAC) {
  1366.                         /* We just got a double IAC in subnegotiation */
  1367.                         Inst->RecvBuf[Inst->RecvBufPos-2]=-1; /* We store IAC as a (int)-1 */
  1368.                         Inst->RecvBufPos--;
  1369.                     }
  1370.                     return RecvChar(Inst,Sock,Loc,RawMode);
  1371.                 } else {
  1372.                     if (Inst->RecvBuf[2]==IAC) {
  1373.                         /* Restart sequence */
  1374.                         Inst->RecvBuf[0]=IAC;
  1375.                         Inst->RecvBufPos=1;
  1376.                         return RecvChar(Inst,Sock,Loc,RawMode);
  1377.                     } else {
  1378.                       ParseBuf3(Inst);
  1379.                         Inst->RecvBufPos=0;
  1380.                         return RecvChar(Inst,Sock,Loc,RawMode);
  1381.                     }
  1382.                 }
  1383.             break;
  1384.         }
  1385.     }
  1386.     else {
  1387.         if (Got==IAC) {
  1388.             Inst->RecvBuf[0]=Got;
  1389.             Inst->RecvBufPos=1;
  1390.             return RecvChar(Inst,Sock,Loc,RawMode);
  1391.         } else {
  1392.             *Loc=Got;
  1393.             PrevChar=TrueGot;
  1394.             return 1;
  1395.         }
  1396.     }
  1397.     return 1;
  1398.     
  1399. }
  1400.  
  1401.  
  1402. void SockGets(struct InstData *Inst,int Sock,char *Buf,int BufSize)
  1403. /* This function gets the next string until a CR
  1404. on the specified socket, and places it in buf. It 
  1405. discards leading crs/lfs */
  1406. {
  1407.     int BufPos=0;
  1408.     int BytesRead;
  1409.     int FirstBytes=TRUE;
  1410.     Buf[0]='\0';
  1411.     
  1412.     do {
  1413.         BytesRead=RecvChar(Inst,Sock,Buf+BufPos,FALSE);
  1414.         if (BytesRead < 0) {
  1415.             if (Errno()!=EINTR) {
  1416.                 Buf[BufPos]='\0';
  1417.                 return;
  1418.             }
  1419.       }
  1420.         else if (BytesRead==0) {
  1421.             Buf[BufPos]='\0';
  1422.             return;
  1423.         }
  1424.         else {
  1425.             if ((Buf[BufPos]=='\r' || Buf[BufPos]=='\n') && FirstBytes) {
  1426.                 Buf[BufPos]='\0';
  1427.             } else {
  1428.                 FirstBytes=FALSE;
  1429.                 BufPos+=BytesRead;
  1430.             }
  1431.         }
  1432.     } while (Buf[BufPos-1] != '\r' && Buf[BufPos-1] != '\n' && BufPos < (BufSize-1));
  1433.     Buf[BufPos]='\0';
  1434. }
  1435.  
  1436. char *PullPasswdString(char **StringPtr)
  1437. {
  1438.     int Cnt;
  1439.     char *RetVal;
  1440.     char *CurPos;
  1441.     
  1442.     if (!StringPtr || !*StringPtr) return NULL;
  1443.     
  1444.     RetVal=*StringPtr;
  1445.     
  1446.     for (CurPos=RetVal;*CurPos != ',' && *CurPos != '\r' && *CurPos != '\n' && *CurPos;CurPos++);
  1447.     switch (*CurPos) {
  1448.         case ',':
  1449.         case '\r':
  1450.         case '\n':
  1451.             *CurPos='\0';
  1452.             CurPos++;
  1453.             *StringPtr=CurPos;
  1454.         return RetVal;
  1455.         
  1456.         case '\0':
  1457.         *StringPtr=CurPos;
  1458.         return RetVal;
  1459.     }
  1460. }
  1461.  
  1462. int mystrcmp(char *S1,char *S2) 
  1463. {
  1464.     int Cnt;
  1465.     for (Cnt=0;S1[Cnt] && S2[Cnt];Cnt++) {
  1466.         if (S1[Cnt] != S2[Cnt]) return !0;
  1467.     }
  1468.     if (S1[Cnt] != S2[Cnt]) return !0;
  1469.     return 0;
  1470. }
  1471.  
  1472. struct PasswdInfo *LookupPasswd(struct InstData *Inst,char *Login)
  1473. {
  1474.     BPTR File;
  1475.     char *LineBuf;
  1476.     char *BufPtr;
  1477.     char *PasswdPtr;
  1478.     char *LoginPtr;
  1479.     char *RealNamePtr;
  1480.     char *HomeDirPtr;
  1481.     char *CmdPtr;
  1482.     struct PasswdInfo *Info;
  1483.     /* int NoPasswd=FALSE; */
  1484.   
  1485.     LineBuf=AllocMem(1000,MEMF_PUBLIC);
  1486.     if (!LineBuf) return NULL;
  1487.     
  1488.     File=Open("tnserv:Passwd",MODE_OLDFILE);
  1489.     if (!File) return NULL;
  1490.     
  1491.     
  1492.     while (FGets(File,LineBuf,1000)) {
  1493.         if (LineBuf[0]=='#') continue;
  1494.         BufPtr=LineBuf;
  1495.         LoginPtr=PullPasswdString(&BufPtr);
  1496. #ifdef DEBUG
  1497.         FPuts(DebugFile,"Got username: ");
  1498.         FPuts(DebugFile,LoginPtr);
  1499.         FPuts(DebugFile,"\n");
  1500. #endif
  1501.         PasswdPtr=PullPasswdString(&BufPtr);
  1502. #ifdef DEBUG
  1503.         FPuts(DebugFile,"Got password: ");
  1504.         FPuts(DebugFile,PasswdPtr);
  1505.         FPuts(DebugFile,"\n");
  1506. #endif
  1507.         PullPasswdString(&BufPtr); /* throw away user id */
  1508.         PullPasswdString(&BufPtr); /* Throw away group id */
  1509.         RealNamePtr=PullPasswdString(&BufPtr);
  1510.         HomeDirPtr=PullPasswdString(&BufPtr);
  1511.         CmdPtr=PullPasswdString(&BufPtr);
  1512.         
  1513.         /* if (!mystrcmp(PasswdPtr,"*")) NoPasswd=TRUE;*//*strcpy(Passwd,PasswdPtr);*/
  1514.     /* else NoPasswd=FALSE; */
  1515.         if (!mystrcmp(Login,LoginPtr)) {
  1516. #ifdef DEBUG
  1517.             FPuts(DebugFile,"Password located\n");
  1518. #endif
  1519.             /* Password located and correct */
  1520.             /*if (CmdPtr[0]=='*') */ /* We only support stdin/out logins */
  1521.             Close(File);
  1522.             Info=AllocMem(sizeof(struct PasswdInfo),MEMF_PUBLIC);
  1523.             if (!Info) return NULL;
  1524.             strcpy(Info->Login,LoginPtr);
  1525.             strcpy(Info->Passwd,PasswdPtr);
  1526.             strcpy(Info->RealName,RealNamePtr);
  1527.             strcpy(Info->WorkDir,HomeDirPtr);
  1528.             strcpy(Info->Command,CmdPtr);
  1529.             FreeMem(LineBuf,1000);
  1530.             return Info;
  1531.         }
  1532.     }
  1533.     Close(File);
  1534.     FreeMem(LineBuf,1000);
  1535.     return NULL; /* Login failed */
  1536. }
  1537.  
  1538. void __asm PutMLSChar(register __d0 char Chr,register __a3 char **BufPtr)
  1539. {
  1540.     **BufPtr=Chr;
  1541.     (*BufPtr)++;
  1542. }
  1543.  
  1544. void MakeLongStr(char *StrBuf,unsigned long Num)
  1545. {
  1546.     RawDoFmt("%lu",&Num,PutMLSChar,&StrBuf);
  1547. }
  1548.  
  1549.  
  1550. struct Process *MyCreateNewProcTags(struct InstData *Inst,ULONG Tag1,...)
  1551. {
  1552.     return CreateNewProc((struct TagItem *)&Tag1);
  1553. }
  1554.  
  1555. void *MyAllocDosObjectTags(struct InstData *Inst,ULONG Type,ULONG Tag1,...)
  1556. {
  1557.     return AllocDosObject(Type,(struct TagItem *)&Tag1);
  1558. }
  1559. void MySystemTags(struct Library *DSBse,char *Cmd,ULONG Tag0,...)
  1560. {
  1561. #define DOSBase DSBse
  1562.     SystemTagList(Cmd,(struct TagItem *)&Tag0);
  1563. #undef DOSBase
  1564. }
  1565.  
  1566. #define DOSBase DSBse
  1567. int __asm SubSubProc(register __a0 char *ArgString,register __d0 long Length)
  1568. {
  1569.     char StringBuf[1000];
  1570.     char *StringPtr;
  1571.     BPTR FH;
  1572.     struct Library *DSBse;
  1573.     
  1574.     DSBse=OpenLibrary("dos.library",36);
  1575.     if (!DSBse) return 0;
  1576.     
  1577.     FH=(BPTR)GetInt(ArgString,&StringPtr);
  1578.  
  1579. /*    if (IsInteractive(FH)) {
  1580.         Write(FH,"Interactive\n",12);
  1581.     }*/
  1582.     strcpy(StringBuf,StringPtr);
  1583.     if (!StringBuf[0]) {
  1584.         MySystemTags(DSBse,"execute s:remote-startup",
  1585.             SYS_Input,FH,
  1586.             SYS_Output,FH,
  1587.             NP_ConsoleTask,((struct FileHandle *)BADDR(FH))->fh_Type,
  1588.             TAG_END);
  1589.     } else {
  1590.         MySystemTags(DSBse,StringBuf,
  1591.             SYS_Input,FH,
  1592.             SYS_Output,FH,
  1593.             NP_ConsoleTask,((struct FileHandle *)BADDR(FH))->fh_Type,
  1594.             TAG_END);
  1595.     }
  1596.  
  1597.     Forbid();
  1598.     Close(FH);
  1599.     return 0;
  1600. }
  1601. #undef DOSBase
  1602.