home *** CD-ROM | disk | FTP | other *** search
- #include <exec/types.h>
- #include <exec/execbase.h>
- #include <dos/dos.h>
- #include <dos/dosextens.h>
- #include <dos/dostags.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <signal.h>
- #undef signal
- #include <ios1.h>
- #include <string.h>
- #include <errno.h>
- #include <stdio.h>
-
- #include "amiga.h"
-
- #define OUR_PID 1
-
- static int far next_pid = OUR_PID + 1;
- #if 0
- static struct MinList processes;
- #endif
-
- static struct timerequest *far AlarmRequest;
- ULONG alarmsig;
- static int alarm_sent;
-
- void *xmalloc(), *xrealloc();
-
- int getpid(void) { return OUR_PID; }
-
- struct process
- {
- struct MinNode node;
- struct Task *process;
- int pid;
- };
-
- static struct process *find_pid(int pid)
- {
- #if 0
- struct process *entry;
-
- for (entry = (struct process *)processes.mlh_Head;
- entry->node.mln_Succ; entry = (struct process *)entry->node.mln_Succ)
- if (entry->pid == pid) return entry;
- #endif
-
- return NULL;
- }
-
- static void (*sig_handlers[NB_SIGNALS])(int);
-
- static void sas_sig_dispatch(int sig)
- /* Effect: Redispatch one of the SAS signals to the correct fn, then
- reestablish the signal handler */
- {
- sig_handlers[sig](sig);
- signal(sig, sas_sig_dispatch);
- }
-
- static void sig_dispatch(int sig)
- /* Effect: Do the action associated with signal sig
- */
- {
- void (*fn)(int);
-
- if (sig == SIGKILL) exit(0);
-
- if (sig >= 0 && sig < NB_SIGNALS)
- {
- fn = sig_handlers[sig];
-
- if (fn == SIG_DFL)
- switch (sig)
- {
- case SIGFPE: case SIGALRM: break;
- default: exit(0);
- }
- else if (fn != SIG_IGN) sig_handlers[sig](sig);
- }
- }
-
- void (*emacs_signal(int sig,void (*fn)(int)))(int)
- {
- void (*oldfn)(int);
-
- if (sig >= 0 && sig < NB_SIGNALS)
- {
- oldfn = sig_handlers[sig];
- sig_handlers[sig] = fn;
- }
- else oldfn = 0;
-
- if (sig == SIGINT || sig == SIGFPE) /* SAS C signals */
- if (fn == SIG_IGN || fn == SIG_DFL) signal(sig, fn);
- else signal(sig, sas_sig_dispatch);
-
- return oldfn;
- }
-
- void kill(int pid, int signal)
- {
- if (pid == OUR_PID) sig_dispatch(signal);
- else switch (signal)
- {
- case SIGKILL: case SIGINT: case SIGQUIT: {
- struct process *entry;
-
- entry = find_pid(pid);
- if (entry)
- {
- Signal(entry->process, SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D);
- if (signal == SIGKILL)
- {
- Remove((struct Node *)entry);
- free(entry);
- }
- }
- break;
- }
- }
- }
-
- void check_alarm(void)
- {
- if (alarm_sent && CheckIO(AlarmRequest))
- {
- alarm_sent = FALSE;
- sig_dispatch(SIGALRM);
- }
- }
-
- void alarm(int secs)
- /* Effect: Schedule a SIGALRM after secs seconds
- */
- {
- if (alarm_sent)
- {
- AbortIO(AlarmRequest);
- WaitIO(AlarmRequest);
- }
- if (secs)
- {
- AlarmRequest->tr_time.tv_secs = (ULONG) secs;
- AlarmRequest->tr_time.tv_micro = 0L;
- AlarmRequest->tr_node.io_Command = TR_ADDREQUEST;
- SendIO(AlarmRequest);
- alarm_sent = TRUE;
- }
- else alarm_sent = FALSE;
- }
-
- #if 0
- int update_processes(void)
- /* Effect: Check Exec process lists to see if any of our processes has died.
- Remove them from our process list.
- Return: TRUE if any of our processes died.
- */
- {
- struct process *p;
- int death = FALSE;
- extern struct ExecBase *SysBase;
-
- Forbid();
- p = (struct process *)processes.mlh_Head;
- while (p->node.mln_Succ)
- {
- struct process *next = (struct process *)p->node.mln_Succ;
- struct Task *t;
- int found = FALSE;
-
- /* Check the ready & waiting lists */
- for (t = (struct Task *)SysBase->TaskWait.lh_Head; t->tc_Node.ln_Succ;
- t = (struct Task *)t->tc_Node.ln_Succ)
- if (t == p->process)
- {
- found = TRUE;
- break;
- }
- if (!found)
- {
- for (t = (struct Task *)SysBase->TaskReady.lh_Head; t->tc_Node.ln_Succ;
- t = (struct Task *)t->tc_Node.ln_Succ)
- if (t == p->process)
- {
- found = TRUE;
- break;
- }
- if (!found)
- {
- Remove((struct Node *)p);
- free(p);
- death = TRUE;
- }
- }
- p = next;
- }
- Permit();
-
- return death;
- }
- #endif
-
- int wait_for_termination(int pid)
- {
- #if 0
- do
- {
- struct process *entry;
-
- update_processes();
- entry = find_pid(pid);
- if (!entry) return 0;
- Delay(25); /* Try again a bit later */
- } while (1);
- #endif
- }
-
- int wait_without_blocking(void)
- {
- #if 0
- if (!processes.mlh_Head->mln_Succ)
- while (update_processes()) Delay(25);
- #endif
- }
-
- static BPTR pseudo_close(int fd)
- /* Effect: Closes fd from the C compilers point of view, but keeps the
- AmigaDOS file open.
- Returns: The AmigaDOS filehandle associated with fd.
- If fd wasn't a valid file, returns a file handle on NIL:
- */
- {
- BPTR dummy_file = Open("NIL:", MODE_READWRITE);
- BPTR old_file;
- struct UFB *ufb = chkufb(fd);
-
- if (!ufb) return dummy_file;
- old_file = ufb->ufbfh;
- ufb->ufbfh = dummy_file;
- close(fd);
-
- return old_file;
- }
-
- int exec(char *program, char **argv, int input, int output, char *dir)
- {
- int index, pid, ioerr, comsize, dlen;
- char *combuf, *bp;
- BPTR in, out, dirlock;
- #if 0
- struct process *entry = xmalloc(sizeof(struct process));
- #endif
-
- in = pseudo_close(input);
- out = pseudo_close(output);
-
- combuf = xmalloc(256);
- comsize = 256;
-
- bp = combuf;
- for (index = 0; argv[index] != 0; index++)
- {
- char *s = argv[index];
- int len;
-
- len = 3;
- while (*s) len += 1 + 2 * (*s++ == '"');
- if (bp + len + 1 >= combuf + comsize)
- {
- char *newbuf;
-
- comsize = 2 * comsize + len;
- newbuf = xrealloc(combuf, comsize);
- bp = newbuf + (bp - combuf);
- combuf = newbuf;
- }
- *bp++ = ' ';
- *bp++ = '"';
- s = argv[index];
- while (*s)
- {
- if (*s == '"' || *s == '*') *bp++ = '*';
- *bp++ = *s++;
- }
- *bp++ = '"';
- }
- *bp = '\0';
- /*dlen = strlen(dir);
- if (dlen > 0 && dir[dlen - 1] == '/') dir[dlen - 1] = '\0';*/
- if (dir) dirlock = Lock(dir, SHARED_LOCK);
- else
- {
- BPTR cd = CurrentDir(0);
-
- dirlock = DupLock(cd);
- CurrentDir(cd);
- }
- if (dirlock &&
- SystemTags(combuf,
- SYS_Asynch, TRUE,
- SYS_Input, in, SYS_Output, out,
- NP_StackSize, 10000L,
- NP_CurrentDir, dirlock,
- TAG_END) != -1)
- {
- pid = next_pid++;
-
- #if 0
- entry->process = 0; /* No way to find process, alas */
- entry->pid = pid;
- AddHead((struct List *)&processes, (struct Node *)entry);
- #endif
- return pid;
- }
- ioerr = IoErr();
- errno = convert_oserr(ioerr);
- free(combuf);
- #if 0
- free(entry);
- #endif
- Close(in); Close(out);
- if (dirlock) UnLock(dirlock);
- return -1;
- }
-
- char *amiga_path(void)
- {
- char *path, *pp, name[128];
- int pathsize;
- struct CommandLineInterface *cli;
- struct Process *p;
- BPTR lock;
- long l, *lp, nlen;
-
- pathsize = 128;
- path = xmalloc(pathsize);
-
- strcpy(path, ".,");
- pp = path + 2;
-
- p = (struct Process *)FindTask(0);
- if (!(cli = (struct CommandLineInterface *)((long)p->pr_CLI << 2)))
- return path;
-
- l = (long)cli->cli_CommandDir;
- while (l) {
- l <<= 2;
- lp = (long *)l;
- lock = (BPTR)*(lp + 1);
- NameFromLock(lock, name, 128);
- nlen = strlen(name);
- if (pp + nlen + 5 >= path + pathsize)
- {
- char *newpath;
-
- pathsize = 2 * pathsize + nlen;
- newpath = xrealloc(path);
- pp = newpath + (pp - path);
- path = newpath;
- }
- memcpy(pp, name, nlen);
- pp += nlen;
- *pp++ = ',';
- l = *lp;
- }
- /* Use of +5 above guarantees that there is enough space for c: */
- strcpy(pp, "c:");
-
- return path;
- }
-
- int init_amiga_processes(void)
- {
- int i;
-
- for (i = 0; i < NB_SIGNALS; i++) sig_handlers[i] = SIG_DFL;
- if (!(AlarmRequest = (struct timerequest *)
- device_open("timer.device", 0L, 0L, 0L, 0, sizeof(struct timerequest))))
- {
- fprintf(stderr, "Timer will not open\n");
- return FALSE;
- }
- alarmsig = 1L << AlarmRequest->tr_node.io_Message.mn_ReplyPort->mp_SigBit;
- alarm_sent = FALSE;
-
- #if 0
- NewList((struct List *)&processes);
- #endif
-
- return TRUE;
- }
-
- void cleanup_amiga_processes(void)
- {
- if (alarm_sent)
- {
- AbortIO(AlarmRequest);
- WaitIO(AlarmRequest);
- }
- device_close(AlarmRequest);
- }
-