#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/segment.h>
+#include <sys/user.h>
extern int sys_exit(int exit_code);
extern int sys_close(int fd);
struct file file;
unsigned short fs;
int has_dumped = 0;
+ register int dump_start, dump_size;
+ struct user dump;
if (!current->dumpable)
return 0;
current->dumpable = 0;
+/* See if we have enough room to write the upage. */
+ if(current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE/1024) return 0;
__asm__("mov %%fs,%0":"=r" (fs));
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
if (open_namei("core",O_CREAT | O_WRONLY | O_TRUNC,0600,&inode))
has_dumped = 1;
/* write and seek example: from kernel space */
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
- DUMP_WRITE("core-dump, regs=\n",17);
- DUMP_SEEK(64);
- DUMP_WRITE(regs,sizeof(*regs));
- if (current->used_math) {
+ dump.u_tsize = current->end_code / PAGE_SIZE;
+ dump.u_dsize = (current->brk - current->end_code) / PAGE_SIZE;
+ dump.u_ssize =((current->start_stack +(PAGE_SIZE-1)) / PAGE_SIZE) -
+ (regs->esp/ PAGE_SIZE);
+/* If the size of the dump file exceeds the rlimit, then see what would happen
+ if we wrote the stack, but not the data area. */
+ if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE/1024 >
+ current->rlim[RLIMIT_CORE].rlim_cur)
+ dump.u_dsize = 0;
+/* Make sure we have enough room to write the stack and data areas. */
+ if ((dump.u_ssize+1) * PAGE_SIZE / 1024 >
+ current->rlim[RLIMIT_CORE].rlim_cur)
+ dump.u_ssize = 0;
+ dump.u_comm = 0;
+ dump.u_ar0 = (struct pt_regs *)(((int)(&dump.regs)) -((int)(&dump)));
+ dump.signal = signr;
+ dump.regs = *regs;
+ dump.start_code = 0;
+ dump.start_stack = regs->esp & ~(PAGE_SIZE - 1);
+/* Flag indicating the math stuff is valid. */
+ if (dump.u_fpvalid = current->used_math) {
if (last_task_used_math == current)
- __asm__("clts ; fnsave %0"::"m" (current->tss.i387));
- DUMP_SEEK(1024);
- DUMP_WRITE("floating-point regs=\n",21);
- DUMP_SEEK(1088);
- DUMP_WRITE(¤t->tss.i387,sizeof(current->tss.i387));
- }
+ __asm__("clts ; fnsave %0"::"m" (dump.i387));
+ else
+ memcpy(&dump.i387,¤t->tss.i387,sizeof(dump.i387));
+ };
+ DUMP_WRITE(&dump,sizeof(dump));
+ DUMP_SEEK(sizeof(dump));
+ /* Dump the task struct. Not be used by gdb, but could be useful */
+ DUMP_WRITE(current,sizeof(*current));
+/* Now dump all of the user data. Include malloced stuff as well */
+ DUMP_SEEK(PAGE_SIZE);
/* now we start writing out the user space info */
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x17));
-/* the dummy dump-file contains the first block of user space... */
- DUMP_SEEK(2048);
- DUMP_WRITE(0,1024);
+/* Dump the data area */
+ if (dump.u_dsize != 0) {
+ dump_start = current->end_code;
+ dump_size = current->brk - current->end_code;
+ DUMP_WRITE(dump_start,dump_size);
+ };
+/* Now prepare to dump the stack area */
+ if (dump.u_ssize != 0) {
+ dump_start = regs->esp & ~(PAGE_SIZE - 1);
+ dump_size = dump.u_ssize * PAGE_SIZE;
+ DUMP_WRITE(dump_start,dump_size);
+ };
close_coredump:
if (file.f_op->release)
file.f_op->release(inode,&file);
printk("bread failed\n");
return NULL;
}
-/* *((struct minix_super_block *) s) =
- *((struct minix_super_block *) bh->b_data); */
ms = (struct minix_super_block *) bh->b_data;
s->s_ninodes = ms->s_ninodes;
s->s_nzones = ms->s_nzones;
return 0;
}
-int sys_mknod(const char * filename, int mode, int dev)
+int do_mknod(const char * filename, int mode, int dev)
{
const char * basename;
int namelen;
struct inode * dir;
- if (!suser())
- return -EPERM;
if (!(dir = dir_namei(filename,&namelen,&basename, NULL)))
return -ENOENT;
if (!namelen) {
return dir->i_op->mknod(dir,basename,namelen,mode,dev);
}
+int sys_mknod(const char * filename, int mode, int dev)
+{
+ if (suser())
+ return do_mknod(filename,mode,dev);
+ return -EPERM;
+}
+
int sys_mkdir(const char * pathname, int mode)
{
const char * basename;
{
int chars, size, written = 0;
+ if (inode->i_count != 2) { /* no readers */
+ send_sig(SIGPIPE,current,0);
+ return -EINTR;
+ }
while (count>0) {
while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) {
wake_up(& PIPE_READ_WAIT(*inode));
if (inode->i_count != 2) { /* no readers */
- current->signal |= (1<<(SIGPIPE-1));
+ send_sig(SIGPIPE,current,0);
return written?written:-EINTR;
}
if (current->signal & ~current->blocked)
#define MAJOR(a) (((unsigned)(a))>>8)
#define MINOR(a) ((a)&0xff)
-#define NR_OPEN 20
+#define NR_OPEN 32
#define NR_INODE 128
#define NR_FILE 64
#define NR_SUPER 8
int follow_links);
extern int open_namei(const char * pathname, int flag, int mode,
struct inode ** res_inode);
+extern int do_mknod(const char * filename, int mode, int dev);
extern void iput(struct inode * inode);
extern struct inode * iget(int dev,int nr);
extern struct inode * get_empty_inode(void);
long pid,pgrp,session,leader;
int groups[NGROUPS];
/*
- * pointers to parent process, youngest child, younger sibling,
+ * pointers to (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
* p->p_pptr->pid)
*/
- struct task_struct *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
+ struct task_struct *p_opptr,*p_pptr, *p_cptr, *p_ysptr, *p_osptr;
/*
* sleep makes a singly linked list with this.
*/
/* ec,brk... */ 0,0,0,0,0,0,0, \
/* pid etc.. */ 0,0,0,0, \
/* suppl grps*/ {NOGROUP,}, \
-/* proc links*/ &init_task.task,NULL,NULL,NULL,NULL, \
+/* proc links*/ &init_task.task,&init_task.task,NULL,NULL,NULL,NULL, \
/* uid etc */ 0,0,0,0,0,0, \
/* timeout */ 0,0,0,0,0,0,0,0,0,0,0,0, \
/* min_flt */ 0,0,0,0, \
return __limit+1;
}
+#define REMOVE_LINKS(p) \
+ if ((p)->p_osptr) \
+ (p)->p_osptr->p_ysptr = (p)->p_ysptr; \
+ if ((p)->p_ysptr) \
+ (p)->p_ysptr->p_osptr = (p)->p_osptr; \
+ else \
+ (p)->p_pptr->p_cptr = (p)->p_osptr
+
+#define SET_LINKS(p) \
+ (p)->p_ysptr = NULL; \
+ if ((p)->p_osptr = (p)->p_pptr->p_cptr) \
+ (p)->p_osptr->p_ysptr = p; \
+ (p)->p_pptr->p_cptr = p
+
#endif
#ifndef _SYS_PTRACE_H
#define _SYS_PTRACE_H
/* has the defines to get at the registers. */
+
+#define PTRACE_TRACEME 0
+#define PTRACE_PEEKTEXT 1
+#define PTRACE_PEEKDATA 2
+#define PTRACE_PEEKUSR 3
+#define PTRACE_POKETEXT 4
+#define PTRACE_POKEDATA 5
+#define PTRACE_POKEUSR 6
+#define PTRACE_CONT 7
+#define PTRACE_KILL 8
+#define PTRACE_SINGLESTEP 9
+
+#define PTRACE_ATTACH 0x10
+#define PTRACE_DETACH 0x11
+
/* use ptrace (3 or 6, pid, PT_EXCL, data); to read or write
the processes registers. */
--- /dev/null
+#include <sys/ptrace.h>
+/* Core file format: The core file is written in such a way that gdb
+ can understand it and provide useful information to the user (under
+ linux we use the 'trad-core' bfd). There are quite a number of
+ obstacles to being able to view the contents of the floating point
+ registers, and until these are solved you will not be able to view the
+ contents of them. Actually, you can read in the core file and look at
+ the contents of the user struct to find out what the floating point
+ registers contain.
+ The actual file contents are as follows:
+ UPAGE: 1 page consisting of a user struct that tells gdb what is present
+ in the file. Directly after this is a copy of the task_struct, which
+ is currently not used by gdb, but it may come in useful at some point.
+ All of the registers are stored as part of the upage. The upage should
+ always be only one page.
+ DATA: The data area is stored. We use current->end_text to
+ current->brk to pick up all of the user variables, plus any memory
+ that may have been malloced. No attempt is made to determine if a page
+ is demand-zero or if a page is totally unused, we just cover the entire
+ range. All of the addresses are rounded in such a way that an integral
+ number of pages is written.
+ STACK: We need the stack information in order to get a meaningful
+ backtrace. We need to write the data from (esp) to
+ current->start_stack, so we round each of these off in order to be able
+ to write an integer number of pages.
+ The minimum core file size is 3 pages, or 12288 bytes.
+*/
+
+struct user_i387_struct {
+ long cwd;
+ long swd;
+ long twd;
+ long fip;
+ long fcs;
+ long foo;
+ long fos;
+ long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
+};
+
+/* When the kernel dumps core, it starts by dumping the user struct -
+ this will be used by gdb to figure out where the data and stack segments
+ are within the file, and what virtual addresses to use. */
+struct user{
+/* We start with the registers, to mimic the way that "memory" is returned
+ from the ptrace(3,...) function. */
+ struct pt_regs regs; /* Where the registers are actually stored */
+/* ptrace does not yet supply these. Someday.... */
+ int u_fpvalid; /* True if math co-processor being used. */
+ /* for this mess. Not yet used. */
+ struct user_i387_struct i387; /* Math Co-processor registers. */
+/* The rest of this junk is to help gdb figure out what goes where */
+ unsigned long int u_tsize; /* Text segment size (pages). */
+ unsigned long int u_dsize; /* Data segment size (pages). */
+ unsigned long int u_ssize; /* Stack segment size (pages). */
+ unsigned long start_code; /* Starting virtual address of text. */
+ unsigned long start_stack; /* Starting virtual address of stack area.
+ This is actually the bottom of the stack,
+ the top of the stack is always found in the
+ esp register. */
+ long int signal; /* Signal that caused the core dump. */
+ char * u_comm; /* User command that was responsible */
+ struct pt_regs * u_ar0; /* Used by gdb to help find the values for */
+ /* the registers. */
+ struct user_i387_struct* u_fpstate; /* Math Co-processor pointer. */
+};
+#define NBPG 4096
+#define UPAGES 1
+#define HOST_TEXT_START_ADDR (u.start_code)
+#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
return tmp-buf;
}
+static int read_zero(struct inode *node,struct file *file,char *buf,int count)
+{
+ int left;
+
+ for (left = count; left > 0; left--) {
+ put_fs_byte(0,buf);
+ buf++;
+ }
+ return count;
+}
+
/*
* The memory devices use the full 32 bits of the offset, and so we cannot
* check against negative addresses: they are ok. The return value is weird,
return 0; /* /dev/null */
case 4:
return read_port(inode,file,buf,count);
+ case 5:
+ return read_zero(inode,file,buf,count);
default:
return -ENODEV;
}
return count; /* /dev/null */
case 4:
return write_port(inode,file,buf,count);
+ case 5:
+ return count; /* /dev/zero */
default:
return -ENODEV;
}
extern void IRQ3_interrupt(void);
extern void IRQ4_interrupt(void);
+#define PORT_UNKNOWN 0
+#define PORT_8250 1
+#define PORT_16450 2
+#define PORT_16550 3
+#define PORT_16550A 4
+
+int port_table[] = {
+ PORT_UNKNOWN,
+ PORT_UNKNOWN,
+ PORT_UNKNOWN,
+ PORT_UNKNOWN,
+ PORT_UNKNOWN
+};
+
+
static void modem_status_intr(unsigned line, unsigned port, struct tty_struct * tty)
{
unsigned char status = inb(port+6);
if ((status & 0x88) == 0x08 && tty->pgrp > 0)
kill_pg(tty->pgrp,SIGHUP,1);
+
+ if ((status & 0x10) == 0x10)
+ tty->stopped = 0;
+ else
+ tty->stopped = 1;
}
/*
*/
static void send_intr(unsigned line, unsigned port, struct tty_struct * tty)
{
- int c;
+ int c, i = 0;
#define TIMER ((SER1_TIMEOUT-1)+line)
timer_active &= ~(1 << TIMER);
- if ((c = GETCH(tty->write_q)) < 0)
- return;
- outb(c,port);
+ if (!tty->stopped) {
+ do {
+ if ((c = GETCH(tty->write_q)) < 0)
+ return;
+ outb(c,port);
+ i++;
+ } while ( port_table[line] == PORT_16550A && \
+ i < 14 && !EMPTY(tty->write_q) && \
+ !tty->stopped);
+ }
timer_table[TIMER].expires = jiffies + 10;
timer_active |= 1 << TIMER;
if (LEFT(tty->write_q) > WAKEUP_CHARS)
{
if (FULL(tty->read_q))
return;
- PUTCH(inb(port),tty->read_q);
+
+ outb_p((inb(port+4) & 0x0d), port+4);
+
+ do {
+ PUTCH(inb(port),tty->read_q);
+ } while ((inb(port+5) & 0x01 != 0) && !FULL(tty->read_q));
+
+ outb_p((inb(port+4) | 0x02), port+4);
+
timer_active |= (1<<(SER1_TIMER-1))<<line;
}
if (!(port = tty->read_q->data))
return;
while (1) {
- ident = inb(port+2);
+ ident = inb(port+2) & 7;
if (ident & 1)
return;
ident >>= 1;
do_rs_write(4,tty_table+67);
}
-static void init(int port)
+static void init(int port, int line)
{
+ unsigned char status1, status2, scratch;
+
+ if (inb(port+5) == 0xff) {
+ port_table[line] = PORT_UNKNOWN;
+ return;
+ }
+
+ scratch = inb(port+7);
+ outb_p(0xa5, port+7);
+ status1 = inb(port+7);
+ outb_p(0x5a, port+7);
+ status2 = inb(port+7);
+ if (status1 == 0xa5 && status2 == 0x5a) {
+ outb_p(scratch, port+7);
+ outb_p(0x01, port+2);
+ scratch = inb(port+2) >> 6;
+ switch (scratch) {
+ case 0: printk("serial port at 0x%04x is a 16450\n", port);
+ port_table[line] = PORT_16450;
+ break;
+ case 1: printk("serial port at 0x%04x is unknown\n", port);
+ port_table[line] = PORT_UNKNOWN;
+ break;
+ case 2: printk("serial port at 0x%04x is a 16550 (FIFO's disabled)\n", port);
+ port_table[line] = PORT_16550;
+ outb_p(0x00, port+2);
+ break;
+ case 3: printk("serial port at 0x%04x is a 16550a (FIFO's enabled)\n", port);
+ port_table[line] = PORT_16550A;
+ outb_p(0xc7, port+2);
+ break;
+ }
+ } else
+ printk("serial port at 0x%04x is a 8250\n", port);
+
outb_p(0x80,port+3); /* set DLAB of line control reg */
outb_p(0x30,port); /* LS of divisor (48 -> 2400 bps */
outb_p(0x00,port+1); /* MS of divisor */
timer_table[SER4_TIMEOUT].expires = 0;
set_intr_gate(0x23,IRQ3_interrupt);
set_intr_gate(0x24,IRQ4_interrupt);
- init(tty_table[64].read_q->data);
- init(tty_table[65].read_q->data);
- init(tty_table[66].read_q->data);
- init(tty_table[67].read_q->data);
+ init(tty_table[64].read_q->data, 1);
+ init(tty_table[65].read_q->data, 2);
+ init(tty_table[66].read_q->data, 3);
+ init(tty_table[67].read_q->data, 4);
outb(inb_p(0x21)&0xE7,0x21);
}
if (!p || (sig < 0) || (sig > 32))
return -EINVAL;
if (!priv && ((sig != SIGCONT) || (current->session != p->session)) &&
- (current->euid != p->euid) && !suser())
+ (current->euid != p->euid) && (current->uid != p->uid) && !suser())
return -EPERM;
if (!sig)
return 0;
/* save the signal number for wait. */
p->exit_code = sig;
- /* we have to make sure the parent is awake. */
+ /* we have to make sure the parent process is awake. */
if (p->p_pptr != NULL && p->p_pptr->state == TASK_INTERRUPTIBLE)
p->p_pptr->state = TASK_RUNNING;
for (i=1 ; i<NR_TASKS ; i++)
if (task[i] == p) {
task[i] = NULL;
- /* Update links */
- if (p->p_osptr)
- p->p_osptr->p_ysptr = p->p_ysptr;
- if (p->p_ysptr)
- p->p_ysptr->p_osptr = p->p_osptr;
- else
- p->p_pptr->p_cptr = p->p_osptr;
+ REMOVE_LINKS(p);
free_page((long) p);
return;
}
return(0);
}
+static void forget_original_parent(struct task_struct * father)
+{
+ struct task_struct ** p;
+
+ for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
+ if (*p && (*p)->p_opptr == father)
+ (*p)->p_opptr = task[1];
+}
+
volatile void do_exit(long code)
{
struct task_struct *p;
for (i=0 ; i<NR_OPEN ; i++)
if (current->filp[i])
sys_close(i);
+ forget_original_parent(current);
iput(current->pwd);
current->pwd = NULL;
iput(current->root);
* A. Make init inherit all the child processes
* B. Check to see if any process groups have become orphaned
* as a result of our exiting, and if they have any stopped
- * jons, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
+ * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
*/
while (p = current->p_cptr) {
current->p_cptr = p->p_osptr;
p->p_ysptr = NULL;
- p->flags &= ~PF_PTRACED;
+ p->flags &= ~PF_PTRACED;
p->p_pptr = task[1];
- p->p_osptr = task[1]->p_cptr;
- task[1]->p_cptr->p_ysptr = p;
- task[1]->p_cptr = p;
+ p->p_osptr = p->p_pptr->p_cptr;
+ p->p_osptr->p_ysptr = p;
+ p->p_pptr->p_cptr = p;
if (p->state == TASK_ZOMBIE)
- task[1]->signal |= (1<<(SIGCHLD-1));
+ p->p_pptr->signal |= (1<<(SIGCHLD-1));
/*
* process group orphan check
* Case ii: Our child is in a different pgrp
verify_area(stat_addr,4);
repeat:
flag=0;
- for (p = current->p_cptr ; p ; p = p->p_osptr) {
+ for (p = current->p_cptr ; p ; p = p->p_osptr) {
if (pid>0) {
if (p->pid != pid)
continue;
flag = p->pid;
if (stat_addr)
put_fs_long(p->exit_code, stat_addr);
- release(p);
+ if (p->p_opptr != p->p_pptr) {
+ REMOVE_LINKS(p);
+ p->p_pptr = p->p_opptr;
+ SET_LINKS(p);
+ send_sig(SIGCHLD,p->p_pptr,1);
+ } else
+ release(p);
#ifdef DEBUG_PROC_TREE
audit_ptree();
#endif
}
return -ECHILD;
}
-
-
task[nr] = p;
*p = *current; /* NOTE! this doesn't copy the supervisor stack */
p->state = TASK_UNINTERRUPTIBLE;
+ p->flags &= ~PF_PTRACED;
p->pid = last_pid;
- p->p_pptr = current;
+ p->p_pptr = p->p_opptr = current;
p->p_cptr = NULL;
- p->p_ysptr = NULL;
- if (p->p_osptr = current->p_cptr)
- p->p_osptr->p_ysptr = p;
- current->p_cptr = p;
+ SET_LINKS(p);
p->counter = p->priority;
p->signal = 0;
p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
__asm__("clts ; fnsave %0 ; frstor %0"::"m" (p->tss.i387));
if (copy_mem(nr,p)) {
task[nr] = NULL;
- if (p->p_pptr->p_cptr == p)
- p->p_pptr->p_cptr = p->p_osptr;
- if (p->p_osptr)
- p->p_osptr->p_ysptr = p->p_ysptr;
- if (p->p_ysptr)
- p->p_ysptr->p_osptr = p->p_osptr;
+ REMOVE_LINKS(p);
free_page((long) p);
return -EAGAIN;
}
static unsigned long tvtojiffies(struct timeval *value)
{
return((unsigned long )value->tv_sec * HZ +
- (unsigned long )value->tv_usec / (1000000 / HZ));
+ (unsigned long )(value->tv_usec + (1000000 / HZ - 1)) /
+ (1000000 / HZ));
}
static void jiffiestotv(unsigned long jiffies, struct timeval *value)
int k;
if (!value)
- return -EFAULT;
- memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
+ memset((char *) &set_buffer, 0, sizeof(set_buffer));
+ else
+ memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
k = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
if (k < 0 || !ovalue)
return k;
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
-#include <errno.h>
+
#include <asm/segment.h>
#include <asm/system.h>
+
+#include <errno.h>
#include <sys/ptrace.h>
/*
void write_verify(unsigned long);
/* change a pid into a task struct. */
-static inline int get_task(int pid)
+static inline struct task_struct * get_task(int pid)
{
int i;
for (i = 0; i < NR_TASKS; i++) {
if (task[i] != NULL && (task[i]->pid == pid))
- return i;
+ return task[i];
}
- return -1;
+ return NULL;
}
/*
int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
- int childno;
- if (request == 0) {
+ if (request == PTRACE_TRACEME) {
+ /* are we already being traced? */
+ if (current->flags & PF_PTRACED)
+ return -EPERM;
/* set the ptrace bit in the proccess flags. */
current->flags |= PF_PTRACED;
return 0;
}
-
- childno = get_task(pid);
-
- if (childno < 0)
+ if (!(child = get_task(pid)))
return -ESRCH;
- else
- child = task[childno];
-
- if (child->p_pptr != current || !(child->flags & PF_PTRACED) ||
- child->state != TASK_STOPPED)
+ if (request == PTRACE_ATTACH) {
+ long tmp;
+
+ if ((!current->dumpable || (current->uid != child->euid) ||
+ (current->gid != child->egid)) && !suser())
+ return -EPERM;
+ /* the same process cannot be attached many times */
+ if (child->flags & PF_PTRACED)
+ return -EPERM;
+ child->flags |= PF_PTRACED;
+ if (child->p_pptr != current) {
+ REMOVE_LINKS(child);
+ child->p_pptr = current;
+ SET_LINKS(child);
+ }
+ tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) | TRAP_FLAG;
+ put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
+ if (child->state == TASK_INTERRUPTIBLE ||
+ child->state == TASK_STOPPED)
+ child->state = TASK_RUNNING;
+ child->signal = 0;
+ return 0;
+ }
+ if (!(child->flags & PF_PTRACED) || child->state != TASK_STOPPED)
return -ESRCH;
switch (request) {
/* when I and D space are seperate, these will need to be fixed. */
- case 1: /* read word at location addr. */
- case 2: {
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA: {
int tmp,res;
- res = read_long(task[childno], addr, &tmp);
+ res = read_long(child, addr, &tmp);
if (res < 0)
return res;
verify_area((void *) data, 4);
}
/* read the word at location addr in the USER area. */
- case 3: {
+ case PTRACE_PEEKUSR: {
int tmp;
addr = addr >> 2; /* temporary hack. */
if (addr < 0 || addr >= 17)
}
/* when I and D space are seperate, this will have to be fixed. */
- case 4: /* write the word at location addr. */
- case 5:
- return write_long(task[childno],addr,data);
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ return write_long(child,addr,data);
- case 6: /* write the word at location addr in the USER area */
+ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
addr = addr >> 2; /* temproary hack. */
if (addr < 0 || addr >= 17)
return -EIO;
return -EIO;
return 0;
- case 7: { /* restart after signal. */
+ case PTRACE_CONT: { /* restart after signal. */
long tmp;
- child->signal=0;
+ child->signal = 0;
if (data > 0 && data <= NSIG)
child->signal = 1<<(data-1);
- child->state = 0;
+ child->state = TASK_RUNNING;
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
* perhaps it should be put in the status that it want's to
* exit.
*/
- case 8: {
+ case PTRACE_KILL: {
long tmp;
- child->state = 0;
+ child->state = TASK_RUNNING;
child->signal = 1 << (SIGKILL-1);
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
return 0;
}
- case 9: { /* set the trap flag. */
+ case PTRACE_SINGLESTEP: { /* set the trap flag. */
long tmp;
tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) | TRAP_FLAG;
put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
- child->state = 0;
+ child->state = TASK_RUNNING;
child->signal = 0;
- if (data > 0 && data <NSIG)
+ if (data > 0 && data <= NSIG)
child->signal= 1<<(data-1);
/* give it a chance to run. */
return 0;
}
+ case PTRACE_DETACH: { /* detach a process that was attached. */
+ long tmp;
+
+ child->flags &= ~PF_PTRACED;
+ child->signal=0;
+ child->state = 0;
+ /* make sure the single step bit is not set. */
+ tmp = get_stack_long(child, 4*EFL-MAGICNUMBER) & ~TRAP_FLAG;
+ put_stack_long(child, 4*EFL-MAGICNUMBER,tmp);
+ return 0;
+ }
+
default:
return -EIO;
}
#endif
if ((regs->orig_eax != -1) &&
((regs->eax == -ERESTARTSYS) || (regs->eax == -ERESTARTNOINTR))) {
- if ((regs->eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) ||
- signr < SIGCONT || signr > SIGTTOU))
+ if ((regs->eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT)))
regs->eax = -EINTR;
else {
regs->eax = regs->orig_eax;
current->exit_code = signr;
if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
- send_sig(SIGCHLD, current->p_pptr, 1);
-/* current->p_pptr->signal |= (1<<(SIGCHLD-1));*/
-
+ send_sig(SIGCHLD, current->p_pptr, 1);
return(1); /* Reschedule another event */
case SIGQUIT:
--- /dev/null
+/*
+ * linux/lib/itimer.c
+ *
+ * (C) 1992 Darren Senn
+ */
+
+#define __LIBRARY__
+#include <unistd.h>
+#include <sys/time.h>
+
+_syscall2(int,getitimer,int,which,struct itimerval *,value)
+_syscall3(int,setitimer,int,which,struct itimerval *,value,struct itimerval *,ovalue)
char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
int i;
unsigned long old_fs;
- unsigned short old_euid;
PRINTK("unix_proto_bind: socket 0x%x, len=%d\n", sock,
sockaddr_len);
return -EINVAL;
}
- /*
- * W A R N I N G
- * this is a terrible hack. i want to create a socket in the
- * filesystem and get its inode. sys_mknod() can create one for
- * me, but it needs superuser privs and doesn't give me the inode.
- * we fake suser here and get the file created... ugh.
- */
memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
old_fs = get_fs();
set_fs(get_ds());
- old_euid = current->euid;
- current->euid = 0;
- i = sys_mknod(fname, S_IFSOCK, 0);
- current->euid = old_euid;
+ i = do_mknod(fname, S_IFSOCK | 0777, 0);
if (i == 0)
i = open_namei(fname, 0, S_IFSOCK, &upd->inode);
set_fs(old_fs);