home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / unix / src / exec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-17  |  4.3 KB  |  147 lines

  1. #include "amiga.h"
  2. #include "processes.h"
  3. #include <amiga/ioctl.h>
  4. #include <exec/memory.h>
  5. #include <dos/dosextens.h>
  6. #include <dos/dostags.h>
  7. #include <string.h>
  8.  
  9. /* Variables used by a child that is starting up */
  10. struct MemList *_child_entry;    /* Memory used for child's code */
  11. struct Message startup_message;
  12. struct exit_message *_child_exit;
  13. char *_child_command;
  14. int _child_command_len;
  15. char *_child_door_name;
  16. int _child_door_name_len;
  17. extern char far _child_startup, far _child_startup_end;
  18.  
  19. int exec(char *program, char **argv, int input, int output, char *dir, int stacksize)
  20. {
  21.   int index, comsize;
  22.   char *combuf, *bp;
  23.   BPTR in, out, dirlock;
  24.   struct process *entry = (struct process *)malloc(sizeof(struct process));
  25.   static struct MemList alloc_child = { { 0 }, 1 };
  26.   int _pseudo_close(int fd);
  27.   
  28.   /* in & out must be different fhs for CreateNewProc. But get_fh
  29.      is not guaranteed to return different fhs when called twice on
  30.      the same file :-( Luckily it does for socketpairs.
  31.      Don't try & pass the same AmigaDOS file for input & output */
  32.   if (input == -1) in = Input();
  33.   else if (ioctl(input, _AMIGA_GET_FH, &in) == -1) { in = 0; }
  34.   if (output == -1) out = Output();
  35.   else if (ioctl(output, _AMIGA_GET_FH, &out) == -1) { out = 0; }
  36.   if (input != -1) _pseudo_close(input);
  37.   if (output != -1 && input != output) _pseudo_close(output);
  38.  
  39.   comsize = 256;
  40.   combuf = AllocMem(comsize, 0);
  41.  
  42.   _child_exit = AllocMem(sizeof(struct exit_message), 0);
  43.   _child_door_name = AllocMem(DOOR_LEN, 0);
  44.  
  45.   alloc_child.ml_ME[0].me_Length = &_child_startup_end - &_child_startup;
  46.   _child_entry = AllocEntry(&alloc_child);
  47.  
  48.   if (entry && in && out && combuf && _child_exit && _child_door_name &&
  49.       (long)_child_entry > 0)
  50.     {
  51.       memcpy(_child_entry->ml_ME[0].me_Addr, &_child_startup,
  52.          _child_entry->ml_ME[0].me_Length);
  53.       strcpy(_child_door_name, _door_name);
  54.       _child_door_name_len = DOOR_LEN;
  55.  
  56.       bp = combuf;
  57.       for (index = 0; argv[index] != 0; index++)
  58.     {
  59.       char *s = argv[index];
  60.       int len;
  61.  
  62.       len = 3;
  63.       while (*s) len += 1 + 2 * (*s++ == '"');
  64.       if (bp + len + 1 >= combuf + comsize)
  65.         {
  66.           char *newbuf;
  67.           int new_comsize;
  68.  
  69.           new_comsize = 2 * comsize + len;
  70.           newbuf = AllocMem(new_comsize, 0);
  71.           if (!newbuf) { errno = ENOMEM; goto error; }
  72.           memcpy(newbuf, combuf, comsize);
  73.  
  74.           bp = newbuf + (bp - combuf);
  75.           combuf = newbuf;
  76.           comsize = new_comsize;
  77.         }
  78.       *bp++ = ' ';
  79.       *bp++ = '"';
  80.       s = argv[index];
  81.       while (*s)
  82.         {
  83.           if (*s == '"' || *s == '*') *bp++ = '*';
  84.           *bp++ = *s++;
  85.         }
  86.       *bp++ = '"';
  87.     }
  88.       *bp = '\0';
  89.       if (dir) dirlock = Lock(dir, SHARED_LOCK);
  90.       else
  91.     {
  92.       BPTR cd = CurrentDir(0);
  93.  
  94.       dirlock = DupLock(cd);
  95.       CurrentDir(cd);
  96.     }
  97.       if (dirlock)
  98.     {
  99.       entry->pid = _next_pid++;
  100.       entry->input = in;
  101.       _child_command = combuf;
  102.       _child_command_len = comsize;
  103.  
  104.       /* This message is sent by the child when it has started */
  105.       startup_message.mn_Length = sizeof(startup_message);
  106.       startup_message.mn_Node.ln_Type = NT_MESSAGE;
  107.  
  108.       /* This message is sent by the child when it exits */
  109.       _child_exit->m.mn_Length = sizeof(*_child_exit);
  110.       _child_exit->m.mn_Node.ln_Type = NT_MESSAGE;
  111.       _child_exit->pid = entry->pid;
  112.  
  113.       entry->process = CreateNewProcTags(NP_Entry, _child_entry->ml_ME[0].me_Addr,
  114.                          NP_Input, in,
  115.                          NP_CloseInput, input != -1,
  116.                          NP_Output, out,
  117.                          NP_CloseOutput, output != -1,
  118.                          NP_StackSize,
  119.                           stacksize > 0 ? stacksize : _stack_size,
  120.                          NP_CurrentDir, dirlock,
  121.                          NP_Cli, TRUE,
  122.                          TAG_END);
  123.       if (entry->process)
  124.         {
  125.           do WaitPort(_startup_port); while (!GetMsg(_startup_port));
  126.           entry->status = alive;
  127.           AddHead((struct List *)&_processes, (struct Node *)entry);
  128.           return entry->pid;
  129.         }
  130.     }
  131.       errno = convert_oserr(IoErr());
  132.       FreeMem(combuf, comsize);
  133.       free(entry);
  134.       if (dirlock) UnLock(dirlock);
  135.     }
  136.   else errno = ENOMEM;
  137.  
  138.  error:
  139.   if (in && input != -1) Close(in);
  140.   if (out && output != -1) Close(out);
  141.   if (combuf) FreeMem(combuf, comsize);
  142.   if (_child_exit) FreeMem(_child_exit, sizeof(struct exit_message));
  143.   if (_child_door_name) FreeMem(_child_door_name, DOOR_LEN);
  144.   if ((long)_child_entry > 0) FreeEntry(_child_entry);
  145.   return -1;
  146. }
  147.