home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / utility / text / emacsdif.lha / emacs-18.58 / src / amiga_processes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-26  |  7.8 KB  |  404 lines

  1. #include <exec/types.h>
  2. #include <exec/execbase.h>
  3. #include <dos/dos.h>
  4. #include <dos/dosextens.h>
  5. #include <dos/dostags.h>
  6. #include <proto/exec.h>
  7. #include <proto/dos.h>
  8. #include <signal.h>
  9. #undef signal
  10. #include <ios1.h>
  11. #include <string.h>
  12. #include <errno.h>
  13. #include <stdio.h>
  14.  
  15. #include "amiga.h"
  16.  
  17. #define OUR_PID 1
  18.  
  19. static int far next_pid = OUR_PID + 1;
  20. #if 0
  21. static struct MinList processes;
  22. #endif
  23.  
  24. static struct timerequest *far AlarmRequest;
  25. ULONG alarmsig;
  26. static int alarm_sent;
  27.  
  28. void *xmalloc(), *xrealloc();
  29.  
  30. int getpid(void) { return OUR_PID; }
  31.  
  32. struct process
  33. {
  34.     struct MinNode node;
  35.     struct Task *process;
  36.     int pid;
  37. };
  38.  
  39. static struct process *find_pid(int pid)
  40. {
  41. #if 0
  42.     struct process *entry;
  43.  
  44.     for (entry = (struct process *)processes.mlh_Head;
  45.      entry->node.mln_Succ; entry = (struct process *)entry->node.mln_Succ)
  46.     if (entry->pid == pid) return entry;
  47. #endif
  48.  
  49.     return NULL;
  50. }
  51.  
  52. static void (*sig_handlers[NB_SIGNALS])(int);
  53.  
  54. static void sas_sig_dispatch(int sig)
  55. /* Effect: Redispatch one of the SAS signals to the correct fn, then
  56.      reestablish the signal handler */
  57. {
  58.     sig_handlers[sig](sig);
  59.     signal(sig, sas_sig_dispatch);
  60. }
  61.  
  62. static void sig_dispatch(int sig)
  63. /* Effect: Do the action associated with signal sig
  64. */
  65. {
  66.     void (*fn)(int);
  67.  
  68.     if (sig == SIGKILL) exit(0);
  69.  
  70.     if (sig >= 0 && sig < NB_SIGNALS)
  71.     {
  72.     fn = sig_handlers[sig];
  73.  
  74.     if (fn == SIG_DFL)
  75.         switch (sig)
  76.         {
  77.         case SIGFPE: case SIGALRM: break;
  78.         default: exit(0);
  79.         }
  80.     else if (fn != SIG_IGN) sig_handlers[sig](sig);
  81.     }
  82. }
  83.  
  84. void (*emacs_signal(int sig,void (*fn)(int)))(int)
  85. {
  86.     void (*oldfn)(int);
  87.  
  88.     if (sig >= 0 && sig < NB_SIGNALS)
  89.     {
  90.     oldfn = sig_handlers[sig];
  91.     sig_handlers[sig] = fn;
  92.     }
  93.     else oldfn = 0;
  94.  
  95.     if (sig == SIGINT || sig == SIGFPE) /* SAS C signals */
  96.     if (fn == SIG_IGN || fn == SIG_DFL) signal(sig, fn);
  97.     else signal(sig, sas_sig_dispatch);
  98.  
  99.     return oldfn;
  100. }
  101.  
  102. void kill(int pid, int signal)
  103. {
  104.     if (pid == OUR_PID) sig_dispatch(signal);
  105.     else switch (signal)
  106.     {
  107.     case SIGKILL: case SIGINT: case SIGQUIT: {
  108.         struct process *entry;
  109.  
  110.         entry = find_pid(pid);
  111.         if (entry)
  112.         {
  113.         Signal(entry->process, SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D);
  114.         if (signal == SIGKILL)
  115.         {
  116.             Remove((struct Node *)entry);
  117.             free(entry);
  118.         }
  119.         }
  120.         break;
  121.     }
  122.     }
  123. }
  124.  
  125. void check_alarm(void)
  126. {
  127.     if (alarm_sent && CheckIO(AlarmRequest))
  128.     {
  129.     alarm_sent = FALSE;
  130.     sig_dispatch(SIGALRM);
  131.     }
  132. }
  133.  
  134. void alarm(int secs)
  135. /* Effect: Schedule a SIGALRM after secs seconds
  136. */
  137. {
  138.     if (alarm_sent)
  139.     {
  140.     AbortIO(AlarmRequest);
  141.     WaitIO(AlarmRequest);
  142.     }
  143.     if (secs)
  144.     {
  145.     AlarmRequest->tr_time.tv_secs = (ULONG) secs;
  146.     AlarmRequest->tr_time.tv_micro = 0L;
  147.     AlarmRequest->tr_node.io_Command = TR_ADDREQUEST;
  148.     SendIO(AlarmRequest);
  149.     alarm_sent = TRUE;
  150.     }
  151.     else alarm_sent = FALSE;
  152. }
  153.  
  154. #if 0
  155. int update_processes(void)
  156. /* Effect: Check Exec process lists to see if any of our processes has died.
  157.      Remove them from our process list.
  158.    Return: TRUE if any of our processes died.
  159. */
  160. {
  161.     struct process *p;
  162.     int death = FALSE;
  163.     extern struct ExecBase *SysBase;
  164.  
  165.     Forbid();
  166.     p = (struct process *)processes.mlh_Head;
  167.     while (p->node.mln_Succ)
  168.     {
  169.     struct process *next = (struct process *)p->node.mln_Succ;
  170.     struct Task *t;
  171.     int found = FALSE;
  172.     
  173.     /* Check the ready & waiting lists */
  174.     for (t = (struct Task *)SysBase->TaskWait.lh_Head; t->tc_Node.ln_Succ;
  175.          t = (struct Task *)t->tc_Node.ln_Succ)
  176.         if (t == p->process)
  177.         {
  178.         found = TRUE;
  179.         break;
  180.         }
  181.     if (!found)
  182.     {
  183.         for (t = (struct Task *)SysBase->TaskReady.lh_Head; t->tc_Node.ln_Succ;
  184.          t = (struct Task *)t->tc_Node.ln_Succ)
  185.         if (t == p->process)
  186.         {
  187.             found = TRUE;
  188.             break;
  189.         }
  190.         if (!found)
  191.         {
  192.         Remove((struct Node *)p);
  193.         free(p);
  194.         death = TRUE;
  195.         }
  196.     }
  197.     p = next;
  198.     }
  199.     Permit();
  200.  
  201.     return death;
  202. }
  203. #endif
  204.  
  205. int wait_for_termination(int pid)
  206. {
  207. #if 0
  208.     do
  209.     {
  210.     struct process *entry;
  211.  
  212.     update_processes();
  213.     entry = find_pid(pid);
  214.     if (!entry) return 0;
  215.     Delay(25);        /* Try again a bit later */
  216.     } while (1);
  217. #endif
  218. }
  219.  
  220. int wait_without_blocking(void)
  221. {
  222. #if 0
  223.     if (!processes.mlh_Head->mln_Succ)
  224.     while (update_processes()) Delay(25);
  225. #endif
  226. }
  227.  
  228. static BPTR pseudo_close(int fd)
  229. /* Effect: Closes fd from the C compilers point of view, but keeps the
  230.      AmigaDOS file open.
  231.    Returns: The AmigaDOS filehandle associated with fd.
  232.      If fd wasn't a valid file, returns a file handle on NIL:
  233. */
  234. {
  235.     BPTR dummy_file = Open("NIL:", MODE_READWRITE);
  236.     BPTR old_file;
  237.     struct UFB *ufb = chkufb(fd);
  238.  
  239.     if (!ufb) return dummy_file;
  240.     old_file = ufb->ufbfh;
  241.     ufb->ufbfh = dummy_file;
  242.     close(fd);
  243.  
  244.     return old_file;
  245. }
  246.  
  247. int exec(char *program, char **argv, int input, int output, char *dir)
  248. {
  249.     int index, pid, ioerr, comsize, dlen;
  250.     char *combuf, *bp;
  251.     BPTR in, out, dirlock;
  252. #if 0
  253.     struct process *entry = xmalloc(sizeof(struct process));
  254. #endif
  255.  
  256.     in = pseudo_close(input);
  257.     out = pseudo_close(output);
  258.  
  259.     combuf = xmalloc(256);
  260.     comsize = 256;
  261.  
  262.     bp = combuf;
  263.     for (index = 0; argv[index] != 0; index++)
  264.     {
  265.     char *s = argv[index];
  266.     int len;
  267.  
  268.     len = 3;
  269.     while (*s) len += 1 + 2 * (*s++ == '"');
  270.     if (bp + len + 1 >= combuf + comsize)
  271.     {
  272.         char *newbuf;
  273.  
  274.         comsize = 2 * comsize + len;
  275.         newbuf = xrealloc(combuf, comsize);
  276.         bp = newbuf + (bp - combuf);
  277.         combuf = newbuf;
  278.     }
  279.     *bp++ = ' ';
  280.     *bp++ = '"';
  281.     s = argv[index];
  282.     while (*s)
  283.     {
  284.         if (*s == '"' || *s == '*') *bp++ = '*';
  285.         *bp++ = *s++;
  286.     }
  287.     *bp++ = '"';
  288.     }
  289.     *bp = '\0';
  290.     /*dlen = strlen(dir);
  291.     if (dlen > 0 && dir[dlen - 1] == '/') dir[dlen - 1] = '\0';*/
  292.     if (dir) dirlock = Lock(dir, SHARED_LOCK);
  293.     else
  294.     {
  295.     BPTR cd = CurrentDir(0);
  296.  
  297.     dirlock = DupLock(cd);
  298.     CurrentDir(cd);
  299.     }
  300.     if (dirlock &&
  301.     SystemTags(combuf,
  302.            SYS_Asynch, TRUE,
  303.            SYS_Input, in, SYS_Output, out,
  304.            NP_StackSize, 10000L,
  305.            NP_CurrentDir, dirlock,
  306.            TAG_END) != -1)
  307.     {
  308.     pid = next_pid++;
  309.  
  310. #if 0
  311.     entry->process = 0;    /* No way to find process, alas */
  312.     entry->pid = pid;
  313.     AddHead((struct List *)&processes, (struct Node *)entry);
  314. #endif
  315.     return pid;
  316.     }
  317.     ioerr = IoErr();
  318.     errno = convert_oserr(ioerr);
  319.     free(combuf);
  320. #if 0
  321.     free(entry);
  322. #endif
  323.     Close(in); Close(out);
  324.     if (dirlock) UnLock(dirlock);
  325.     return -1;
  326. }
  327.  
  328. char *amiga_path(void)
  329. {
  330.     char *path, *pp, name[128];
  331.     int pathsize;
  332.     struct CommandLineInterface *cli;
  333.     struct Process *p;
  334.     BPTR lock;
  335.     long l, *lp, nlen;
  336.  
  337.     pathsize = 128;
  338.     path = xmalloc(pathsize);
  339.  
  340.     strcpy(path, ".,");
  341.     pp = path + 2;
  342.  
  343.     p = (struct Process *)FindTask(0);
  344.     if (!(cli = (struct CommandLineInterface *)((long)p->pr_CLI << 2)))
  345.         return path;
  346.  
  347.     l = (long)cli->cli_CommandDir;
  348.     while (l) {
  349.         l <<= 2;
  350.         lp = (long *)l;
  351.         lock = (BPTR)*(lp + 1);
  352.     NameFromLock(lock, name, 128);
  353.     nlen = strlen(name);
  354.     if (pp + nlen + 5 >= path + pathsize)
  355.     {
  356.         char *newpath;
  357.  
  358.         pathsize = 2 * pathsize + nlen;
  359.         newpath = xrealloc(path);
  360.         pp = newpath + (pp - path);
  361.         path = newpath;
  362.     }
  363.     memcpy(pp, name, nlen);
  364.     pp += nlen;
  365.     *pp++ = ',';
  366.         l = *lp;
  367.     }
  368.     /* Use of +5 above guarantees that there is enough space for c: */
  369.     strcpy(pp, "c:");
  370.  
  371.     return path;
  372. }
  373.  
  374. int init_amiga_processes(void)
  375. {
  376.     int i;
  377.  
  378.     for (i = 0; i < NB_SIGNALS; i++) sig_handlers[i] = SIG_DFL;
  379.     if (!(AlarmRequest = (struct timerequest *)
  380.       device_open("timer.device", 0L, 0L, 0L, 0, sizeof(struct timerequest))))
  381.     {
  382.     fprintf(stderr, "Timer will not open\n");
  383.     return FALSE;
  384.     }
  385.     alarmsig = 1L << AlarmRequest->tr_node.io_Message.mn_ReplyPort->mp_SigBit;
  386.     alarm_sent = FALSE;
  387.  
  388. #if 0
  389.     NewList((struct List *)&processes);
  390. #endif
  391.  
  392.     return TRUE;
  393. }
  394.  
  395. void cleanup_amiga_processes(void)
  396. {
  397.     if (alarm_sent)
  398.     {
  399.     AbortIO(AlarmRequest);
  400.     WaitIO(AlarmRequest);
  401.     }
  402.     device_close(AlarmRequest);
  403. }
  404.