home *** CD-ROM | disk | FTP | other *** search
/ MACD 4 / MACD4.iso / Emulatory / AROS / filesys / emul_handler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1978-03-06  |  17.2 KB  |  737 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: emul_handler.c,v 1.15 1996/10/24 15:51:01 aros Exp $
  4.     $Log: emul_handler.c,v $
  5.     Revision 1.15  1996/10/24 15:51:01  aros
  6.     Use the official AROS macros over the __AROS versions.
  7.  
  8.     Revision 1.14  1996/10/23 14:21:32  aros
  9.     Renamed a few macros from XYZ to AROS_XYZ so we know which if from AROS and
  10.     which not.
  11.  
  12.     Revision 1.13  1996/10/21 20:57:50    aros
  13.     ADE doesn't need to have the patch for timeval.
  14.  
  15.     Revision 1.12  1996/10/14 02:38:39    iaint
  16.     FreeBSD patch no longer needed.
  17.  
  18.     Revision 1.11  1996/10/10 13:23:55    digulla
  19.     Make handler work with timer (Fleischer)
  20.  
  21.     Revision 1.10  1996/09/13 17:57:07    digulla
  22.     Use IPTR
  23.  
  24.     Revision 1.9  1996/09/13 04:23:23  aros
  25.     Define FreeBSD should have been __FreeBSD__ (sorry my fault).
  26.  
  27.     Revision 1.8  1996/09/11 16:54:24  digulla
  28.     Always use AROS_SLIB_ENTRY() to access shared external symbols, because
  29.     some systems name an external symbol "x" as "_x" and others as "x".
  30.     (The problem arises with assembler symbols which might differ)
  31.  
  32.     Revision 1.7  1996/09/11 14:40:10  digulla
  33.     Integrated patch by I. Templeton: Under FreeBSD, there is a clash with
  34.     struct timeval
  35.  
  36.     Revision 1.6  1996/09/11 13:05:34  digulla
  37.     Own function to open a file (M. Fleischer)
  38.  
  39.     Revision 1.5  1996/08/31 12:58:11  aros
  40.     Merged in/modified for FreeBSD.
  41.  
  42.     Revision 1.4  1996/08/30 17:02:06  digulla
  43.     Fixed a bug which caused the shell to exit if the timer sent a signal. This
  44.     fix is a very bad hack :(
  45.  
  46.     Revision 1.3  1996/08/13 15:35:07  digulla
  47.     Replaced AROS_LA by AROS_LHA
  48.  
  49.     Revision 1.2  1996/08/01 17:41:22  digulla
  50.     Added standard header for all files
  51.  
  52.     Desc:
  53.     Lang:
  54. */
  55. #include <aros/system.h>
  56. #ifndef _AMIGA    /* ADE <sys/time.h> has provisions for this */
  57. #define DEVICES_TIMER_H /* avoid redefinition of struct timeval */
  58. #endif /* _AMIGA */
  59. #include <exec/resident.h>
  60. #include <exec/memory.h>
  61. #include <clib/exec_protos.h>
  62. #include <utility/tagitem.h>
  63. #include <dos/dosextens.h>
  64. #include <dos/filesystem.h>
  65. #include <dos/exall.h>
  66. #include <dos/dosasl.h>
  67. #include <clib/dos_protos.h>
  68. #include <aros/libcall.h>
  69. #include <unistd.h>
  70. #include <fcntl.h>
  71. #include <dirent.h>
  72. #include <string.h>
  73. #include <stdlib.h>
  74. #include <stddef.h>
  75. #include <errno.h>
  76. #include <sys/stat.h>
  77. #include <sys/time.h>
  78. #ifdef __GNUC__
  79.     #include "emul_handler_gcc.h"
  80. #endif
  81.  
  82. static const char name[];
  83. static const char version[];
  84. static const APTR inittabl[4];
  85. static void *const functable[];
  86. static const UBYTE datatable;
  87.  
  88. struct emulbase * AROS_SLIB_ENTRY(init,emul_handler) ();
  89. void AROS_SLIB_ENTRY(open,emul_handler) ();
  90. BPTR AROS_SLIB_ENTRY(close,emul_handler) ();
  91. BPTR AROS_SLIB_ENTRY(expunge,emul_handler) ();
  92. int AROS_SLIB_ENTRY(null,emul_handler) ();
  93. void AROS_SLIB_ENTRY(beginio,emul_handler) ();
  94. LONG AROS_SLIB_ENTRY(abortio,emul_handler) ();
  95.  
  96. static const char end;
  97.  
  98. struct filehandle
  99. {
  100.     char *name;
  101.     int type;
  102.     long fd;
  103. };
  104. #define FHD_FILE    0
  105. #define FHD_DIRECTORY    1
  106.  
  107. int emul_handler_entry(void)
  108. {
  109.     /* If the device was executed by accident return error code. */
  110.     return -1;
  111. }
  112.  
  113. const struct Resident emul_handler_resident=
  114. {
  115.     RTC_MATCHWORD,
  116.     (struct Resident *)&emul_handler_resident,
  117.     (APTR)&end,
  118.     RTF_AUTOINIT,
  119.     1,
  120.     NT_LIBRARY,
  121.     0,
  122.     (char *)name,
  123.     (char *)&version[6],
  124.     (ULONG *)inittabl
  125. };
  126.  
  127. static const char name[]="emul.handler";
  128.  
  129. static const char version[]="$VER: emul_handler 1.0 (28.3.96)\n\015";
  130.  
  131. static const APTR inittabl[4]=
  132. {
  133.     (APTR)sizeof(struct emulbase),
  134.     (APTR)functable,
  135.     (APTR)&datatable,
  136.     &AROS_SLIB_ENTRY(init,emul_handler)
  137. };
  138.  
  139. static void *const functable[]=
  140. {
  141.     &AROS_SLIB_ENTRY(open,emul_handler),
  142.     &AROS_SLIB_ENTRY(close,emul_handler),
  143.     &AROS_SLIB_ENTRY(expunge,emul_handler),
  144.     &AROS_SLIB_ENTRY(null,emul_handler),
  145.     &AROS_SLIB_ENTRY(beginio,emul_handler),
  146.     &AROS_SLIB_ENTRY(abortio,emul_handler),
  147.     (void *)-1
  148. };
  149.  
  150. static const UBYTE datatable=0;
  151.  
  152. LONG u2a[][2]=
  153. {
  154.   { ENOMEM, ERROR_NO_FREE_STORE },
  155.   { ENOENT, ERROR_OBJECT_NOT_FOUND },
  156.   { 0, 0 }
  157. };
  158.  
  159. LONG err_u2a(void)
  160. {
  161.     ULONG i;
  162.     for(i=0;i<sizeof(u2a)/sizeof(u2a[0]);i++)
  163.     if(u2a[i][0]==errno)
  164.         break;
  165.     return u2a[i][1];
  166. }
  167.  
  168. static void shrink(char *filename)
  169. {
  170.     char *s1,*s2;
  171.     unsigned long len;
  172.     for(;;)
  173.     {
  174.     while(*filename=='/')
  175.         memmove(filename,filename+1,strlen(filename));
  176.     s1=strstr(filename,"//");
  177.     if(s1==NULL)
  178.         break;
  179.     s2=s1;
  180.     while(s2>filename&&*--s2!='/')
  181.         ;
  182.     memmove(s2,s1+2,strlen(s1+1));
  183.     }
  184.     len=strlen(filename);
  185.     if(len&&filename[len-1]=='/')
  186.     filename[len-1]=0;
  187. }
  188.  
  189. static LONG open_(struct filehandle **handle,STRPTR name,LONG mode)
  190. {
  191.     LONG ret=ERROR_NO_FREE_STORE;
  192.     struct filehandle *fh;
  193.     struct stat st;
  194.     long flags;
  195.     fh=(struct filehandle *)malloc(sizeof(struct filehandle));
  196.     if(fh!=NULL)
  197.     {
  198.     if(!*name&&(*handle)->type==FHD_FILE&&((*handle)->fd==STDIN_FILENO||
  199.        (*handle)->fd==STDOUT_FILENO||(*handle)->fd==STDERR_FILENO))
  200.     {
  201.         fh->type=FHD_FILE;
  202.         fh->fd=(*handle)->fd;
  203.         fh->name="";
  204.         *handle=fh;
  205.         return 0;
  206.     }
  207.     fh->name=(char *)malloc(strlen((*handle)->name)+strlen(name)+2);
  208.     if(fh->name!=NULL)
  209.     {
  210.         strcpy(fh->name,(*handle)->name);
  211.         strcat(fh->name,"/");
  212.         strcat(fh->name,name);
  213.         shrink(fh->name);
  214.         if(!stat(*fh->name?fh->name:".",&st))
  215.         {
  216.         if(S_ISREG(st.st_mode))
  217.         {
  218.             fh->type=FHD_FILE;
  219.             flags=(mode&FMF_CREATE?O_CREAT:0)|
  220.               (mode&FMF_CLEAR?O_TRUNC:0);
  221.             if(mode&FMF_WRITE)
  222.             flags|=mode&FMF_READ?O_RDWR:O_WRONLY;
  223.             else
  224.             flags|=O_RDONLY;
  225.             fh->fd=open(*fh->name?fh->name:".",flags,0770);
  226.             if(fh->fd>=0)
  227.             {
  228.             *handle=fh;
  229.             return 0;
  230.             }
  231.         }else if(S_ISDIR(st.st_mode))
  232.         {
  233.             fh->type=FHD_DIRECTORY;
  234.             fh->fd=(long)opendir(*fh->name?fh->name:".");
  235.             if(fh->fd)
  236.             {
  237.             *handle=fh;
  238.             return 0;
  239.             }
  240.         }else
  241.             errno=ENOENT;
  242.         }
  243.         ret=err_u2a();
  244.         free(fh->name);
  245.     }
  246.     free(fh);
  247.     }
  248.     return ret;
  249. }
  250.  
  251. static LONG open_file(struct filehandle **handle,STRPTR name,LONG mode,LONG protect)
  252. {
  253.     LONG ret=ERROR_NO_FREE_STORE;
  254.     struct filehandle *fh;
  255.     long flags;
  256.     fh=(struct filehandle *)malloc(sizeof(struct filehandle));
  257.     if(fh!=NULL)
  258.     {
  259.     if(!*name&&(*handle)->type==FHD_FILE&&((*handle)->fd==STDIN_FILENO||
  260.        (*handle)->fd==STDOUT_FILENO||(*handle)->fd==STDERR_FILENO))
  261.     {
  262.         fh->type=FHD_FILE;
  263.         fh->fd=(*handle)->fd;
  264.         fh->name="";
  265.         *handle=fh;
  266.         return 0;
  267.     }
  268.     fh->name=(char *)malloc(strlen((*handle)->name)+strlen(name)+2);
  269.     if(fh->name!=NULL)
  270.     {
  271.         strcpy(fh->name,(*handle)->name);
  272.         strcat(fh->name,"/");
  273.         strcat(fh->name,name);
  274.         shrink(fh->name);
  275.         fh->type=FHD_FILE;
  276.         flags=(mode&FMF_CREATE?O_CREAT:0)|
  277.           (mode&FMF_CLEAR?O_TRUNC:0);
  278.         if(mode&FMF_WRITE)
  279.         flags|=mode&FMF_READ?O_RDWR:O_WRONLY;
  280.         else
  281.         flags|=O_RDONLY;
  282.         fh->fd=open(fh->name,flags,0770);
  283.         if(fh->fd>=0)
  284.         {
  285.         *handle=fh;
  286.         return 0;
  287.         }
  288.         ret=err_u2a();
  289.         free(fh->name);
  290.     }
  291.     free(fh);
  292.     }
  293.     return ret;
  294. }
  295.  
  296. static LONG free_lock(struct filehandle *current)
  297. {
  298.     switch(current->type)
  299.     {
  300.     case FHD_FILE:
  301.         if(current->fd!=STDIN_FILENO&¤t->fd!=STDOUT_FILENO&&
  302.            current->fd!=STDERR_FILENO)
  303.         {
  304.         close(current->fd);
  305.         free(current->name);
  306.         }
  307.         break;
  308.     case FHD_DIRECTORY:
  309.         closedir((DIR *)current->fd);
  310.         free(current->name);
  311.         break;
  312.     }
  313.     free(current);
  314.     return 0;
  315. }
  316.  
  317. static LONG startup(struct emulbase *emulbase)
  318. {
  319.     struct filehandle *fhi, *fho, *fhe, *fhv, *fhc, *fhs;
  320.     struct DosList *dlv, *dlc;
  321.     static struct filehandle sys={ "", FHD_DIRECTORY, 0 };
  322.     LONG ret=ERROR_NO_FREE_STORE;
  323.  
  324.     fhi=(struct filehandle *)malloc(sizeof(struct filehandle));
  325.     if(fhi!=NULL)
  326.     {
  327.     fho=(struct filehandle *)malloc(sizeof(struct filehandle));
  328.     if(fho!=NULL)
  329.     {
  330.         fhe=(struct filehandle *)malloc(sizeof(struct filehandle));
  331.         if(fhe!=NULL)
  332.         {
  333.         fhv=&sys;
  334.         ret=open_(&fhv,"",0);
  335.         if(!ret)
  336.         {
  337.             fhc=&sys;
  338.             ret=open_(&fhc,"",0);
  339.             if(!ret)
  340.             {
  341.             fhs=&sys;
  342.             ret=open_(&fhs,"",0);
  343.             if(!ret)
  344.             {
  345.                 ret=ERROR_NO_FREE_STORE;
  346.                 dlv=MakeDosEntry("Workbench",DLT_VOLUME);
  347.                 if(dlv!=NULL)
  348.                 {
  349.                 dlc=MakeDosEntry("SYS",DLT_DEVICE);
  350.                 if(dlc!=NULL)
  351.                 {
  352.                     ret=ERROR_OBJECT_EXISTS;
  353.                     dlv->dol_Unit  =(struct Unit *)fhv;
  354.                     dlv->dol_Device=&emulbase->device;
  355.                     dlc->dol_Unit  =(struct Unit *)fhc;
  356.                     dlc->dol_Device=&emulbase->device;
  357.                     fhi->type=FHD_FILE;
  358.                     fhi->fd=STDIN_FILENO;
  359.                     fhi->name="";
  360.                     emulbase->stdin=(struct Unit *)fhi;
  361.                     fho->type=FHD_FILE;
  362.                     fho->fd=STDOUT_FILENO;
  363.                     fho->name="";
  364.                     emulbase->stdout=(struct Unit *)fho;
  365.                     fhe->type=FHD_FILE;
  366.                     fhe->fd=STDERR_FILENO;
  367.                     fhe->name="";
  368.                     emulbase->stderr=(struct Unit *)fhe;
  369.                     if(AddDosEntry(dlv))
  370.                     {
  371.                     if(AddDosEntry(dlc))
  372.                     {
  373.                         DOSBase->dl_NulHandler=&emulbase->device;
  374.                         DOSBase->dl_NulLock   =(struct Unit *)fhs;
  375.                         return 0;
  376.                     }
  377.                     RemDosEntry(dlv);
  378.                     }
  379.                     FreeDosEntry(dlc);
  380.                 }
  381.                 FreeDosEntry(dlv);
  382.                 }
  383.                 free_lock(fhs);
  384.             }
  385.             free_lock(fhc);
  386.             }
  387.             free_lock(fhv);
  388.         }
  389.         free(fhe);
  390.         }
  391.         free(fho);
  392.     }
  393.     free(fhi);
  394.     }
  395.     return ret;
  396. }
  397.  
  398. static const ULONG sizes[]=
  399. { 0, offsetof(struct ExAllData,ed_Type), offsetof(struct ExAllData,ed_Size),
  400.   offsetof(struct ExAllData,ed_Prot), offsetof(struct ExAllData,ed_Days),
  401.   offsetof(struct ExAllData,ed_Comment), offsetof(struct ExAllData,ed_OwnerUID),
  402.   sizeof(struct ExAllData) };
  403.  
  404. static LONG examine(struct filehandle *fh,struct ExAllData *ead,ULONG size,ULONG type)
  405. {
  406.     STRPTR next, end, last, name;
  407.     struct stat st;
  408.     if(type>ED_OWNER)
  409.     return ERROR_BAD_NUMBER;
  410.     next=(STRPTR)ead+sizes[type];
  411.     end =(STRPTR)ead+size;
  412.     if(next>=end)
  413.     return ERROR_BUFFER_OVERFLOW;
  414.     if(lstat(*fh->name?fh->name:".",&st))
  415.     return err_u2a();
  416.     switch(type)
  417.     {
  418.     default:
  419.     case ED_OWNER:
  420.         ead->ed_OwnerUID=st.st_uid;
  421.         ead->ed_OwnerGID=st.st_gid;
  422.     case ED_COMMENT:
  423.         ead->ed_Comment=NULL;
  424.     case ED_DATE:
  425.         ead->ed_Days=st.st_ctime/(60*60*24)-(6*365+2*366);
  426.         ead->ed_Mins=(st.st_ctime/60)%(60*24);
  427.         ead->ed_Ticks=(st.st_ctime%60)*TICKS_PER_SECOND;
  428.     case ED_PROTECTION:
  429.         ead->ed_Prot=(st.st_mode&S_IRUSR?FIBF_READ:0)|
  430.              (st.st_mode&S_IWUSR?FIBF_WRITE:0)|
  431.              (st.st_mode&S_IXUSR?FIBF_EXECUTE:0)|
  432.              FIBF_SCRIPT|FIBF_DELETE;
  433.     case ED_SIZE:
  434.         ead->ed_Size=st.st_size;
  435.     case ED_TYPE:
  436.         ead->ed_Type=S_ISREG(st.st_mode)?ST_FILE:
  437.              S_ISDIR(st.st_mode)?(*fh->name?ST_USERDIR:ST_ROOT):0;
  438.     case ED_NAME:
  439.         ead->ed_Name=next;
  440.         last=name=*fh->name?fh->name:"Workbench";
  441.         while(*name)
  442.         if(*name++=='/')
  443.             last=name;
  444.         for(;;)
  445.         {
  446.         if(next>=end)
  447.             return ERROR_BUFFER_OVERFLOW;
  448.         if(!(*next++=*last++))
  449.             break;
  450.         }
  451.     case 0:
  452.         ead->ed_Next=(struct ExAllData *)(((IPTR)next+AROS_PTRALIGN-1)&~(AROS_PTRALIGN-1));
  453.         return 0;
  454.     }
  455. }
  456.  
  457. static LONG examine_all(struct filehandle *fh,struct ExAllData *ead,ULONG size,ULONG type)
  458. {
  459.     struct ExAllData *last=NULL;
  460.     STRPTR end=(STRPTR)ead+size, name, old;
  461.     off_t oldpos;
  462.     struct dirent *dir;
  463.     LONG error;
  464.     if(fh->type!=FHD_DIRECTORY)
  465.     return ERROR_OBJECT_WRONG_TYPE;
  466.     for(;;)
  467.     {
  468.     oldpos=telldir((DIR *)fh->fd);
  469.     errno=0;
  470.     dir=readdir((DIR *)fh->fd);
  471.     if(dir==NULL)
  472.     {
  473.         error=err_u2a();
  474.         break;
  475.     }
  476.     if(dir->d_name[0]=='.'&&(!dir->d_name[1]||(dir->d_name[1]=='.'&&!dir->d_name[2])))
  477.         continue;
  478.     name=(STRPTR)malloc(strlen(fh->name)+strlen(dir->d_name)+2);
  479.     if(name==NULL)
  480.     {
  481.         error=ERROR_NO_FREE_STORE;
  482.         break;
  483.     }
  484.     strcpy(name,fh->name);
  485.     if(*name)
  486.         strcat(name,"/");
  487.     strcat(name,dir->d_name);
  488.     old=fh->name;
  489.     fh->name=name;
  490.     error=examine(fh,ead,end-(STRPTR)ead,type);
  491.     fh->name=old;
  492.     free(name);
  493.     if(error)
  494.         break;
  495.     last=ead;
  496.     ead=ead->ed_Next;
  497.     }
  498.     if((!error||error==ERROR_BUFFER_OVERFLOW)&&last!=NULL)
  499.     {
  500.     last->ed_Next=NULL;
  501.     seekdir((DIR *)fh->fd,oldpos);
  502.     return 0;
  503.     }
  504.     if(!error)
  505.     error=ERROR_NO_MORE_ENTRIES;
  506.     rewinddir((DIR *)fh->fd);
  507.     return error;
  508. }
  509.  
  510. AROS_LH2(struct emulbase *, init,
  511.  AROS_LHA(struct emulbase *, emulbase, D0),
  512.  AROS_LHA(BPTR,              segList,   A0),
  513.        struct ExecBase *, sysBase, 0, emul_handler)
  514. {
  515.     AROS_LIBFUNC_INIT
  516.  
  517.     /* Store arguments */
  518.     emulbase->sysbase=sysBase;
  519.     emulbase->seglist=segList;
  520.     emulbase->device.dd_Library.lib_OpenCnt=1;
  521.     emulbase->dosbase=(struct DosLibrary *)OpenLibrary("dos.library",39);
  522.     if(emulbase->dosbase!=NULL)
  523.     {
  524.     if(AttemptLockDosList(LDF_ALL|LDF_WRITE))
  525.     {
  526.         if(!startup(emulbase))
  527.         {
  528.         UnLockDosList(LDF_ALL|LDF_WRITE);
  529.         return emulbase;
  530.         }
  531.         UnLockDosList(LDF_ALL|LDF_WRITE);
  532.     }
  533.     CloseLibrary((struct Library *)emulbase->dosbase);
  534.     }
  535.  
  536.     return NULL;
  537.     AROS_LIBFUNC_EXIT
  538. }
  539.  
  540. AROS_LH3(void, open,
  541.  AROS_LHA(struct IOFileSys *, iofs, A1),
  542.  AROS_LHA(ULONG,              unitnum, D0),
  543.  AROS_LHA(ULONG,              flags, D0),
  544.        struct emulbase *, emulbase, 1, emul_handler)
  545. {
  546.     AROS_LIBFUNC_INIT
  547.  
  548.     /* Keep compiler happy */
  549.     unitnum=0;
  550.     flags=0;
  551.  
  552.     /* I have one more opener. */
  553.     emulbase->device.dd_Library.lib_Flags&=~LIBF_DELEXP;
  554.  
  555.     /* Set returncode */
  556.     iofs->IOFS.io_Error=0;
  557.  
  558.     /* Mark Message as recently used. */
  559.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_REPLYMSG;
  560.     AROS_LIBFUNC_EXIT
  561. }
  562.  
  563. AROS_LH1(BPTR, close,
  564.  AROS_LHA(struct IOFileSys *, iofs, A1),
  565.        struct emulbase *, emulbase, 2, emul_handler)
  566. {
  567.     AROS_LIBFUNC_INIT
  568.  
  569.     /* Let any following attemps to use the device crash hard. */
  570.     iofs->IOFS.io_Device=(struct Device *)-1;
  571.     return 0;
  572.     AROS_LIBFUNC_EXIT
  573. }
  574.  
  575. AROS_LH0(BPTR, expunge, struct emulbase *, emulbase, 3, emul_handler)
  576. {
  577.     AROS_LIBFUNC_INIT
  578.  
  579.     /* Do not expunge the device. Set the delayed expunge flag and return. */
  580.     emulbase->device.dd_Library.lib_Flags|=LIBF_DELEXP;
  581.     return 0;
  582.     AROS_LIBFUNC_EXIT
  583. }
  584.  
  585. AROS_LH0I(int, null, struct emulbase *, emulbase, 4, emul_handler)
  586. {
  587.     AROS_LIBFUNC_INIT
  588.     return 0;
  589.     AROS_LIBFUNC_EXIT
  590. }
  591.  
  592. AROS_LH1(void, beginio,
  593.  AROS_LHA(struct IOFileSys *, iofs, A1),
  594.        struct emulbase *, emulbase, 5, emul_handler)
  595. {
  596.     AROS_LIBFUNC_INIT
  597.     LONG error=0;
  598.  
  599.     /* WaitIO will look into this */
  600.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_MESSAGE;
  601.  
  602.     Disable();
  603.  
  604.     /*
  605.     Do everything quick no matter what. This is possible
  606.     because I never need to Wait().
  607.     */
  608.     switch(iofs->IOFS.io_Command)
  609.     {
  610.     case FSA_OPEN:
  611.         error=open_((struct filehandle **)&iofs->IOFS.io_Unit,
  612.              (char *)iofs->io_Args[0],iofs->io_Args[1]);
  613.         break;
  614.  
  615.     case FSA_OPEN_FILE:
  616.         error=open_file((struct filehandle **)&iofs->IOFS.io_Unit,
  617.              (char *)iofs->io_Args[0],
  618.              iofs->io_Args[1],iofs->io_Args[2]);
  619.         break;
  620.  
  621.     case FSA_CLOSE:
  622.         error=free_lock((struct filehandle *)iofs->IOFS.io_Unit);
  623.         break;
  624.  
  625.     case FSA_IS_INTERACTIVE:
  626.     {
  627.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  628.         if(fh->type==FHD_FILE)
  629.         iofs->io_Args[0]=isatty(fh->fd);
  630.         else
  631.         iofs->io_Args[0]=0;
  632.         break;
  633.     }
  634.  
  635.     case FSA_READ:
  636.     {
  637.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  638.         if(fh->type==FHD_FILE)
  639.         {
  640.         if(fh->fd==STDOUT_FILENO)
  641.             fh->fd=STDIN_FILENO;
  642.         for(;;)
  643.         {
  644.             fd_set rfds;
  645.             struct timeval tv;
  646.             FD_ZERO(&rfds);
  647.             FD_SET(fh->fd,&rfds);
  648.             tv.tv_sec=0;
  649.             tv.tv_usec=100000;
  650.             if(select(fh->fd+1,&rfds,NULL,NULL,&tv))
  651.             break;
  652.             SysBase->ThisTask->tc_State=TS_READY;
  653.             AddTail(&SysBase->TaskReady,&SysBase->ThisTask->tc_Node);
  654.             Switch();
  655.         }
  656.  
  657.         iofs->io_Args[1]=read(fh->fd,(APTR)iofs->io_Args[0],iofs->io_Args[1]);
  658.         if(iofs->io_Args[1]<0)
  659.             error=err_u2a();
  660.         }else
  661.         error=ERROR_OBJECT_WRONG_TYPE;
  662.         break;
  663.     }
  664.  
  665.     case FSA_WRITE:
  666.     {
  667.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  668.         if(fh->type==FHD_FILE)
  669.         {
  670.         if(fh->fd==STDIN_FILENO)
  671.             fh->fd=STDOUT_FILENO;
  672.         iofs->io_Args[1]=write(fh->fd,(APTR)iofs->io_Args[0],iofs->io_Args[1]);
  673.         if(iofs->io_Args[1]<0)
  674.             error=err_u2a();
  675.         }else
  676.         error=ERROR_OBJECT_WRONG_TYPE;
  677.         break;
  678.     }
  679.  
  680.     case FSA_SEEK:
  681.     {
  682.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  683.         LONG mode=iofs->io_Args[2];
  684.         LONG oldpos;
  685.         if(fh->type==FHD_FILE)
  686.         {
  687.         oldpos=lseek(fh->fd,0,SEEK_CUR);
  688.         if(lseek(fh->fd,iofs->io_Args[1],mode==OFFSET_BEGINNING?SEEK_SET:mode==OFFSET_CURRENT?SEEK_CUR:SEEK_END)<0)
  689.             error=err_u2a();
  690.         iofs->io_Args[0]=0;
  691.         iofs->io_Args[1]=oldpos;
  692.         }else
  693.         error=ERROR_OBJECT_WRONG_TYPE;
  694.         break;
  695.     }
  696.  
  697.     case FSA_EXAMINE:
  698.         error=examine((struct filehandle *)iofs->IOFS.io_Unit,
  699.               (struct ExAllData *)iofs->io_Args[0],
  700.               iofs->io_Args[1],iofs->io_Args[2]);
  701.         break;
  702.  
  703.     case FSA_EXAMINE_ALL:
  704.         error=examine_all((struct filehandle *)iofs->IOFS.io_Unit,
  705.               (struct ExAllData *)iofs->io_Args[0],
  706.               iofs->io_Args[1],iofs->io_Args[2]);
  707.         break;
  708.  
  709.     default:
  710.         error=ERROR_NOT_IMPLEMENTED;
  711.         break;
  712.     }
  713.  
  714.     Enable();
  715.  
  716.     /* Set error code */
  717.     iofs->io_DosError=error;
  718.  
  719.     /* If the quick bit is not set send the message to the port */
  720.     if(!(iofs->IOFS.io_Flags&IOF_QUICK))
  721.     ReplyMsg(&iofs->IOFS.io_Message);
  722.  
  723.     AROS_LIBFUNC_EXIT
  724. }
  725.  
  726. AROS_LH1(LONG, abortio,
  727.  AROS_LHA(struct IOFileSys *, iofs, A1),
  728.        struct emulbase *, emulbase, 6, emul_handler)
  729. {
  730.     AROS_LIBFUNC_INIT
  731.     /* Everything already done. */
  732.     return 0;
  733.     AROS_LIBFUNC_EXIT
  734. }
  735.  
  736. static const char end=0;
  737.