home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / amix / AmigaDOS-Emu.zoo / dos.c < prev    next >
C/C++ Source or Header  |  1992-01-14  |  10KB  |  490 lines

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <time.h>
  4. #include <termio.h>
  5. #include <fcntl.h>
  6. #include <osfcn.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #pragma pack(2)
  11. #include <exec/types.h>
  12. #include <exec/nodes.h>
  13. #include <exec/lists.h>
  14. #include <exec/ports.h>
  15. #include <exec/libraries.h>
  16. #include <exec/tasks.h>
  17. #include <exec/execbase.h>
  18. #include <libraries/dos.h>
  19. #include <libraries/dosextens.h>
  20. #pragma pack()
  21.  
  22. #include "arun.h"
  23.  
  24. #define TIME_OFFSET 252460800 /* Where AmigaDOS starts its times */
  25.  
  26.  
  27. #define NFUNCS 400
  28. struct doslib {
  29.     struct func vectors[NFUNCS];
  30.     struct DosLibrary lib;
  31. } doslib;
  32. struct DosLibrary *const DOSBase = &doslib.lib;
  33.  
  34. struct Process CurrentProcess;
  35. struct CommandLineInterface CLI;
  36.  
  37. extern void SDOSBase_Execute(void);
  38. extern void SDOSBase_Examine(void);
  39. extern void SDOSBase_Lock(void);
  40. extern void SDOSBase_UnLock(void);
  41. extern void SDOSBase_Open(void);
  42. extern void SDOSBase_Close(void);
  43. extern void SDOSBase_Read(void);
  44. extern void SDOSBase_Write(void);
  45. extern void SDOSBase_Seek(void);
  46. extern void SDOSBase_Input(void);
  47. extern void SDOSBase_Output(void);
  48. extern void SDOSBase_CurrentDir(void);
  49. extern void SDOSBase_DeleteFile(void);
  50. extern void SDOSBase_IoErr(void);
  51. extern void SDOSBase_IsInteractive(void);
  52. extern void SDOSBase_DateStamp(void);
  53. static struct libinit { void (*func)(); int offset; } libinit[] =
  54. {
  55.     { SDOSBase_Execute, -0xde, },
  56.     { SDOSBase_Examine, -0x66, },
  57.     { SDOSBase_Lock, -0x54, },
  58.     { SDOSBase_UnLock, -0x5a, },
  59.     { SDOSBase_Open, -0x1e, },
  60.     { SDOSBase_Close, -0x24, },
  61.     { SDOSBase_Read, -0x2a, },
  62.     { SDOSBase_Write, -0x30, },
  63.     { SDOSBase_Seek, -0x42, },
  64.     { SDOSBase_Input, -0x36, },
  65.     { SDOSBase_Output, -0x3c, },
  66.     { SDOSBase_CurrentDir, -0x7e, },
  67.     { SDOSBase_DeleteFile, -0x48, },
  68.     { SDOSBase_IoErr, -0x84, },
  69.     { SDOSBase_IsInteractive, -0xd8, },
  70.     { SDOSBase_DateStamp, -0xc0, },
  71.     { 0, 0, },
  72. };
  73.  
  74. struct RootNode RootNode;
  75. struct DosInfo DosInfo;
  76. struct FileHandle standardinputH, standardoutputH, erroroutputH;
  77. struct FileLock erroroutputL, initialdirL;
  78. ULONG CurrentDir;
  79.  
  80. void dos_init(void)
  81. {
  82.     struct libinit *p2;
  83.     struct func *p;
  84.     int i;
  85.  
  86.     DOSBase->dl_lib.lib_Node.ln_Name = DOSNAME;
  87.     DOSBase->dl_Root = (APTR)&RootNode;
  88.     RootNode.rn_Info = CTOB(&DosInfo);
  89.  
  90.     standardinputH.fh_Arg1 = 0;
  91.     standardinputH.fh_Arg2 = 1;
  92.     standardoutputH.fh_Arg1 = 1;
  93.     standardoutputH.fh_Arg2 = 1;
  94.     erroroutputH.fh_Arg1 = 2;
  95.     erroroutputH.fh_Arg2 = 1;
  96.     erroroutputL.fl_Key = 2;
  97.     initialdirL.fl_Key = open(".", O_RDONLY);
  98.     CurrentDir = CTOB(&initialdirL);
  99.  
  100.     /* First, fill all vectors with "unsupp" calls */
  101.     p = (struct func *)DOSBase;
  102.     for ( i=0 ; i<NFUNCS ; ++i )
  103.     {
  104.     --p;
  105.     p->opcode = 0x4eb9;    /* jsr N.l */
  106.     p->addr = unsupp;
  107.     }
  108.  
  109.     /* Now, fill in the supported vectors with the real jumps */
  110.     for ( p2=libinit ; p2->func ; ++p2 )
  111.     {
  112.     p = (struct func *)((char *)DOSBase + p2->offset);
  113.     p->opcode = 0x4ef9;    /* jmp N.l */
  114.     p->addr = p2->func;
  115.     }
  116.  
  117.     CurrentProcess.pr_Result2 = 1;    /* IoErr -- yuck */
  118.  
  119.     verbose("DOSBase = 0x%x", DOSBase);
  120.  
  121.     CurrentProcess.pr_Task.tc_Node.ln_Name = "FakeProcess";
  122.     CurrentProcess.pr_CLI = CTOB(&CLI);
  123.     ExecBase->ThisTask = &CurrentProcess.pr_Task;
  124.     verbose("&CurrentProcess = 0x%x (&MsgPort=0x%x)",
  125.         &CurrentProcess, &CurrentProcess.pr_MsgPort);
  126.     verbose("&CurrentProcess.pr_CLI = 0x%x (offset 0x%x)",
  127.         &CurrentProcess.pr_CLI,
  128.         (char *)&CurrentProcess.pr_CLI - (char *)&CurrentProcess);
  129. }
  130.  
  131.  
  132. #ifdef INTERNAL_EXECUTE
  133. static char *pathcat(const char *dir, const char *file)
  134. {
  135.     char *p;
  136.     static char *buf;
  137.     static unsigned int buflen;
  138.  
  139.     while (strlen(dir)+strlen(file)+2 > buflen)
  140.     buf = buf ? realloc(buf, buflen+=50) : malloc(buflen+=50);
  141.  
  142.     if (buf)
  143.     {
  144.     p=buf;
  145.     while (*p++ = *dir++)
  146.         ;
  147.     --p;
  148.     if (p>buf && p[-1] != '/')
  149.         *p++ = '/';
  150.     strcpy(p, file);
  151.     }
  152.  
  153.     return buf;
  154. }
  155.  
  156. static FILE *pathopen(const char *file)
  157. {
  158.     FILE *fp;
  159.     char *p, *path;
  160.  
  161.     if (fp = fopen(file, "r"))
  162.     return fp;
  163.  
  164.     if (!(path = getenv("PATH")))
  165.     return 0;
  166.     if (!(path = strdup(path)))
  167.     return 0;
  168.  
  169.     for ( p=strtok(path, ":") ; p ; p=strtok((char *)0, ":") )
  170.     {
  171.     char *name = pathcat(p, file);
  172.     if (name && (fp=fopen(name, "r")))
  173.     {
  174.         free(path);
  175.         return fp;
  176.     }
  177.     }
  178.  
  179.     free(path);
  180.     return 0;
  181. }
  182. #endif
  183.  
  184.  
  185. ULONG DOSBase_Execute(char *command, ULONG input, ULONG output)
  186. {
  187. #ifdef INTERNAL_EXECUTE
  188.     unsigned char *p;
  189.     int n;
  190.     ULONG savecmd;
  191.     ULONG *seg;
  192.     FILE *fp;
  193.  
  194.     n = strcspn(command, " \t");
  195.     p = malloc(n + 2);
  196.     if (!p)
  197.     return -1;
  198.     p[0] = n;
  199.     strncpy((char *)p+1, command, n);
  200.     p[n+1] = 0;
  201.  
  202.     if ((fp = pathopen((char *)p+1)) &&
  203.     (seg = adosload(fp, (char *)p+1, 0)))
  204.     {
  205.     (void)fclose(fp);
  206.     savecmd = CLI.cli_CommandName;
  207.     CLI.cli_CommandName = CTOB(p);
  208.  
  209.     verbose("Execute(%s) (internal)", command);
  210.     runseg(seg, (unsigned char *)command+n, strlen(command+n));
  211.  
  212.     CLI.cli_CommandName = savecmd;
  213.     }
  214.     else
  215.     {
  216.     verbose("Execute(%s) (external)", command);
  217.     system(command);
  218.     }
  219.  
  220.     free(p);
  221. #else
  222.     verbose("Execute(%s)", command);
  223.     system(command);
  224. #endif
  225. }
  226.  
  227.  
  228. static void stat_to_fib(struct FileInfoBlock *fibp, struct stat *statp)
  229. {
  230.     long temp;
  231.     struct tm *tp;
  232.  
  233.     memset(fibp, 0, sizeof *fibp);
  234.     fibp->fib_DiskKey = statp->st_ino;
  235.     fibp->fib_DirEntryType = ((statp->st_mode&S_IFMT)==S_IFDIR) ? 1 : -1;
  236.     fibp->fib_FileName[0] = '.';
  237.     if (!(statp->st_mode&S_IREAD))
  238.     fibp->fib_Protection |= FIBF_READ;
  239.     if (!(statp->st_mode&S_IWRITE))
  240.     fibp->fib_Protection |= FIBF_WRITE;
  241.     if (!(statp->st_mode&S_IEXEC))
  242.     fibp->fib_Protection |= FIBF_EXECUTE;
  243.     fibp->fib_Protection |= (statp->st_uid&0xff)<<24;
  244.     fibp->fib_Protection |= (statp->st_gid&0xff)<<16;
  245.     fibp->fib_Size = statp->st_size;
  246.     fibp->fib_NumBlocks = statp->st_blocks;
  247.  
  248.     temp = statp->st_mtime;
  249.     tp = localtime(&temp);
  250.     if (tp->tm_isdst)
  251.     temp += 60*60;
  252.     temp -= TIME_OFFSET;
  253.     temp -= timezone;
  254.  
  255.     fibp->fib_Date.ds_Days = temp / (60*60*24);
  256.     temp %= (60*60*24);
  257.     fibp->fib_Date.ds_Minute = temp / 60;
  258.     fibp->fib_Date.ds_Tick = (temp%60) * TICKS_PER_SECOND;
  259. }
  260.  
  261.  
  262. ULONG DOSBase_Examine(ULONG lock, struct FileInfoBlock *fibp)
  263. {
  264.     struct stat Stat;
  265.     struct FileLock *lp;
  266.  
  267.     verbose("Examine(0x%x, 0x%x)", lock);
  268.     lp = (struct FileLock *)BTOC(lock);
  269.     if (fstat(lp->fl_Key, &Stat))
  270.     return 0;
  271.  
  272.     stat_to_fib(fibp, &Stat);
  273.     return 1;
  274. }
  275.  
  276.  
  277. ULONG DOSBase_Lock(char *fn, ULONG mode)
  278. {
  279.     int fd;
  280.     struct FileLock *lp;
  281.  
  282.     verbose("Lock(%s, 0x%x)", fn, mode);
  283.     if (!strcmp(fn, "*"))
  284.     return CTOB(&erroroutputL);
  285.     if (!fn[0])
  286.     fn = ".";
  287.  
  288.     if ((fd=open(fn, O_RDONLY)) < 0)
  289.     return 0;
  290.  
  291.     lp = malloc(sizeof *lp);
  292.     if (!lp)
  293.     {
  294.     close(fd);
  295.     return 0;
  296.     }
  297.  
  298.     lp->fl_Link = lp->fl_Access = lp->fl_Volume = 0;
  299.     lp->fl_Task = (struct MsgPort *)0;
  300.     lp->fl_Key = fd;
  301.  
  302.     return CTOB(lp);
  303. }
  304.  
  305. void DOSBase_UnLock(ULONG fl)
  306. {
  307.     struct FileLock *lp;
  308.  
  309.     verbose("UnLock(%8x)", fl);
  310.     if (fl)
  311.     {
  312.     lp = (struct FileLock *)BTOC(fl);
  313.     close(lp->fl_Key);
  314.     free(lp);
  315.     }
  316. }
  317.  
  318. ULONG DOSBase_Open(char *fn, ULONG mode)
  319. {
  320.     int fd, umode;
  321.     struct FileHandle *fp;
  322.  
  323.     verbose("Open(%s, 0x%x)", fn, mode);
  324.     if (!strcmp(fn, "*"))
  325.     return CTOB(&erroroutputH);
  326.     if (!fn[0])
  327.     fn = ".";
  328.  
  329.     switch (mode)
  330.     {
  331.     case MODE_OLDFILE:
  332.     umode = O_RDWR;
  333.     break;
  334.     case MODE_NEWFILE:
  335.     umode = O_RDWR|O_CREAT|O_TRUNC;
  336.     break;
  337.     default:
  338.     return 0;
  339.     }
  340.  
  341.     if ((fd=open(fn, umode, 0666)) < 0)
  342.     return 0;
  343.  
  344.     fp = malloc(sizeof *fp);
  345.     if (!fp)
  346.     {
  347.     close(fd);
  348.     return 0;
  349.     }
  350.  
  351.     fp->fh_Buf = fp->fh_Pos = fp->fh_End = 0;
  352.     fp->fh_Func1 = fp->fh_Func2 = fp->fh_Func3 = 0;
  353.     fp->fh_Arg1 = fd;
  354.     fp->fh_Arg2 = 0;
  355.  
  356.     return CTOB(fp);
  357. }
  358.  
  359. void DOSBase_Close(ULONG fh)
  360. {
  361.     struct FileHandle *fp;
  362.  
  363.     verbose("Close(0x%x)", fh);
  364.     fp = (struct FileHandle *)BTOC(fh);
  365.     if (!fp->fh_Arg2)
  366.     {
  367.     close(fp->fh_Arg1);
  368.     free(fp);
  369.     }
  370. }
  371.  
  372. ULONG DOSBase_Read(ULONG fh, void *buf, ULONG nbytes)
  373. {
  374.     struct FileHandle *fp;
  375.  
  376.     fp = (struct FileHandle *)BTOC(fh);
  377.     verbose("Read(0x%x, 0x%x, 0x%x)", fh, buf, nbytes);
  378.     return read(fp->fh_Arg1, buf, nbytes);
  379. }
  380.  
  381. ULONG DOSBase_Write(ULONG fh, void *buf, ULONG nbytes)
  382. {
  383.     struct FileHandle *fp;
  384.  
  385.     fp = (struct FileHandle *)BTOC(fh);
  386.     verbose("Write(0x%x, 0x%x, 0x%x)", fh, buf, nbytes);
  387.     return write(fp->fh_Arg1, buf, nbytes);
  388. }
  389.  
  390. ULONG DOSBase_Seek(ULONG fh, LONG pos, ULONG mode)
  391. {
  392.     struct FileHandle *fp;
  393.     ULONG oldpos;
  394.  
  395.     fp = (struct FileHandle *)BTOC(fh);
  396.     verbose("Seek(0x%x, 0x%x, 0x%x)", fh, pos, mode);
  397.     switch (mode)
  398.     {
  399.     case OFFSET_BEGINNING:
  400.     oldpos = lseek(fp->fh_Arg1, 0L, 1);
  401.     if (oldpos != -1L)
  402.         if (lseek(fp->fh_Arg1, pos, 0) == -1L)
  403.         return -1L;
  404.     return oldpos;
  405.     case OFFSET_CURRENT:
  406.     oldpos = lseek(fp->fh_Arg1, pos, 1);
  407.     if (oldpos != -1L)
  408.         oldpos -= pos;
  409.     return oldpos;
  410.     case OFFSET_END:
  411.     oldpos = lseek(fp->fh_Arg1, 0L, 1);
  412.     if (oldpos != -1L)
  413.         if (lseek(fp->fh_Arg1, pos, 2) == -1L)
  414.         return -1L;
  415.     return oldpos;
  416.     default:
  417.     return -1;
  418.     }
  419. }
  420.  
  421. ULONG DOSBase_Input(void)
  422. {
  423.     verbose("Input()");
  424.     return CTOB(&standardinputH);
  425. }
  426.  
  427. ULONG DOSBase_Output(void)
  428. {
  429.     verbose("Output()");
  430.     return CTOB(&standardoutputH);
  431. }
  432.  
  433. ULONG DOSBase_CurrentDir(ULONG lock)
  434. {
  435.     struct FileLock *lp;
  436.     ULONG prev;
  437.  
  438.     verbose("CurrentDir(0x%x)", lock);
  439.     lp = (struct FileLock *)BTOC(lock);
  440.     if (fchdir(lock?lp->fl_Key:initialdirL.fl_Key))
  441.     panic("fchdir failed");
  442.     prev = CurrentDir;
  443.     CurrentDir = lock;
  444.     return prev;
  445. }
  446.  
  447. ULONG DOSBase_DeleteFile(char *fn)
  448. {
  449.     verbose("DeleteFile(%s)", fn);
  450.     return unlink(fn) == 0;
  451. }
  452.  
  453. ULONG DOSBase_IoErr(void)
  454. {
  455.     verbose("IoErr()");
  456.     return CurrentProcess.pr_Result2;
  457. }
  458.  
  459. ULONG DOSBase_IsInteractive(ULONG fh)
  460. {
  461.     struct FileHandle *fp;
  462.     struct termio termio;
  463.  
  464.     fp = (struct FileHandle *)BTOC(fh);
  465.     verbose("IsInteractive(%8x)", fh);
  466.     return ioctl(fp->fh_Arg1, TCGETA, &termio) == 0;
  467. }
  468.  
  469. ULONG *DOSBase_DateStamp(ULONG *v)
  470. {
  471.     extern long time(long *);
  472.     long temp;
  473.     struct tm *tp;
  474.  
  475.     verbose("DateStamp(0x%x)", v);
  476.     (void)time(&temp);
  477.     tp = localtime(&temp);
  478.     if (tp->tm_isdst)
  479.     temp += 60*60;
  480.     temp -= TIME_OFFSET;
  481.     temp -= timezone;
  482.  
  483.     v[0] = temp / (60*60*24);
  484.     temp %= (60*60*24);
  485.     v[1] = temp / 60;
  486.     v[2] = (temp%60) * TICKS_PER_SECOND;
  487.  
  488.     return v;
  489. }
  490.