You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

244 lines
4.5 KiB

/*
* linux/kernel/signal.c
*
* (C) 1991 Linus Torvalds
*/
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <errno.h>
#include <signal.h>
#include <new.h>
volatile void do_exit(int error_code);
int sys_sgetmask()
{
return current->blocked;
}
int sys_ssetmask(int newmask)
{
int old=current->blocked;
current->blocked = newmask & ~(1<<(SIGKILL-1));
return old;
}
int sys_sigpending()
{
return -ENOSYS;
}
int sys_sigsuspend()
{
return -ENOSYS;
}
static inline void save_old(char * from,char * to)
{
int i;
verify_area(to, sizeof(struct sigaction));
for (i=0 ; i< sizeof(struct sigaction) ; i++) {
put_fs_byte(*from,to);
from++;
to++;
}
}
static inline void get_new(char * from,char * to)
{
int i;
for (i=0 ; i< sizeof(struct sigaction) ; i++)
*(to++) = get_fs_byte(from++);
}
int sys_signal(int signum, long handler, long restorer)
{
struct sigaction tmp;
if (signum<1 || signum>32 || signum==SIGKILL)
return -1;
tmp.sa_handler = (void (*)(int)) handler;
tmp.sa_mask = 0;
tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
tmp.sa_restorer = (void (*)(void)) restorer;
handler = (long) current->sigaction[signum-1].sa_handler;
current->sigaction[signum-1] = tmp;
return handler;
}
int sys_sigaction(int signum, const struct sigaction * action,
struct sigaction * oldaction)
{
struct sigaction tmp;
if (signum<1 || signum>32 || signum==SIGKILL)
return -1;
tmp = current->sigaction[signum-1];
get_new((char *) action,
(char *) (signum-1+current->sigaction));
if (oldaction)
save_old((char *) &tmp,(char *) oldaction);
if (current->sigaction[signum-1].sa_flags & SA_NOMASK)
current->sigaction[signum-1].sa_mask = 0;
else
current->sigaction[signum-1].sa_mask |= (1<<(signum-1));
return 0;
}
void do_signal(long signr,long eax, long ebx, long ecx, long edx,
long fs, long es, long ds,
long eip, long cs, long eflags,
unsigned long * esp, long ss)
{
unsigned long sa_handler;
long old_eip=eip;
struct sigaction * sa = current->sigaction + signr - 1;
int longs;
unsigned long * tmp_esp;
sa_handler = (unsigned long) sa->sa_handler;
if (sa_handler==1)
return;
if (!sa_handler) {
if (signr==SIGCHLD)
return;
else
do_exit(1<<(signr-1));
}
if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
*(&eip) = sa_handler;
longs = (sa->sa_flags & SA_NOMASK)?7:8;
*(&esp) -= longs;
verify_area(esp,longs*4);
tmp_esp=esp;
put_fs_long((long) sa->sa_restorer,tmp_esp++);
put_fs_long(signr,tmp_esp++);
if (!(sa->sa_flags & SA_NOMASK))
put_fs_long(current->blocked,tmp_esp++);
put_fs_long(eax,tmp_esp++);
put_fs_long(ecx,tmp_esp++);
put_fs_long(edx,tmp_esp++);
put_fs_long(eflags,tmp_esp++);
put_fs_long(old_eip,tmp_esp++);
current->blocked |= sa->sa_mask;
}
unsigned int sys_sleep(unsigned int time)
{
sys_signal(SIGALRM,SIG_IGN,NULL);
sys_alarm(time);
sys_pause();
return 0;
}
extern void ld_imm(unsigned long s,unsigned e)
{
unsigned long address;
s &=0xfffff000;
e &=0xfffff000;
for(address = s;address<e;address+=4096)
{
do_no_page1(address+current->start_code);
}
}
int sys_getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count)
{
struct buffer_head* a;
struct dir_entry* b;
int i,j,k;
a=bread(current->filp[fd]->f_inode->i_dev,current->filp[fd]->f_inode->i_zone[0]);
j=0;
struct linux_dirent p;
b=(struct dir_entry*) a->b_data;
for (i=0;i<100;++i) {
if (b->inode==0 || i*24>(count-24)) break;
p.d_ino=b[i].inode;
k=14;
while(k) {
p.d_name[14-k]=b[i].name[14-k];
k--;
}
p.d_off=0;
p.d_reclen=24;
k=24;
while(k) {
put_fs_byte(((char*)&p)[24-k],((char*)dirp+j));
--k;
++j;
}
}
return j;
}
int sys_pipe2(int fd[2],int flags)
{
if(flags==0)
{
sys_pipe(fd);
return 0;
}
}
char* sys_getcwd(char *buf,size_t size)
{
int i,k;
int dev=current->root->i_dev;
char *subpath[20];
struct m_inode *in = current->pwd;
int ino=in->i_num;
struct buffer_head *bh =bread(dev,in->i_zone[0]);
struct dir_entry *de=(struct dir_entry*)bh->b_data;
int j=0;
while(ino!=1)
{
in=iget(dev,de[1].inode);
bh=bread(dev,in->i_zone[0]);
de=(struct dir_entry*)bh->b_data;
for(i=0;de[i].inode!=ino;i++);
ino=in->i_num;
subpath[j]=de[i].name;
j++;
}
j--;
for(i=0;j>=0;j--)
{
if(i>=size)break;
put_fs_byte('/',buf+i);
i++;
for(k=0;subpath[j][k]!='\0';k++)
{
if(i>=size)break;
put_fs_byte(subpath[j][k],buf+i);
i++;
}
}
return buf;
}
int sys_mmap()/*未实现*/
{
return 0;
}
int sys_munmap()/*未实现*/
{
return 0;
}
int sys_clone()/*未实现*/
{
return 0;
}