⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysirix.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * sysirix.c: IRIX system call emulation. * * Copyright (C) 1996 David S. Miller * Copyright (C) 1997 Miguel de Icaza * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/binfmts.h>#include <linux/capability.h>#include <linux/highuid.h>#include <linux/pagemap.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/slab.h>#include <linux/swap.h>#include <linux/errno.h>#include <linux/time.h>#include <linux/timex.h>#include <linux/times.h>#include <linux/elf.h>#include <linux/msg.h>#include <linux/shm.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/utsname.h>#include <linux/file.h>#include <linux/vfs.h>#include <linux/namei.h>#include <linux/socket.h>#include <linux/security.h>#include <linux/syscalls.h>#include <asm/ptrace.h>#include <asm/page.h>#include <asm/uaccess.h>#include <asm/inventory.h>/* 2,191 lines of complete and utter shit coming up... */extern int max_threads;/* The sysmp commands supported thus far. */#define MP_NPROCS       	1 /* # processor in complex */#define MP_NAPROCS      	2 /* # active processors in complex */#define MP_PGSIZE           	14 /* Return system page size in v1. */asmlinkage int irix_sysmp(struct pt_regs *regs){	unsigned long cmd;	int base = 0;	int error = 0;	if(regs->regs[2] == 1000)		base = 1;	cmd = regs->regs[base + 4];	switch(cmd) {	case MP_PGSIZE:		error = PAGE_SIZE;		break;	case MP_NPROCS:	case MP_NAPROCS:		error = num_online_cpus();		break;	default:		printk("SYSMP[%s:%d]: Unsupported opcode %d\n",		       current->comm, current->pid, (int)cmd);		error = -EINVAL;		break;	}	return error;}/* The prctl commands. */#define PR_MAXPROCS		 1 /* Tasks/user. */#define PR_ISBLOCKED		 2 /* If blocked, return 1. */#define PR_SETSTACKSIZE		 3 /* Set largest task stack size. */#define PR_GETSTACKSIZE		 4 /* Get largest task stack size. */#define PR_MAXPPROCS		 5 /* Num parallel tasks. */#define PR_UNBLKONEXEC		 6 /* When task exec/exit's, unblock. */#define PR_SETEXITSIG		 8 /* When task exit's, set signal. */#define PR_RESIDENT		 9 /* Make task unswappable. */#define PR_ATTACHADDR		10 /* (Re-)Connect a vma to a task. */#define PR_DETACHADDR		11 /* Disconnect a vma from a task. */#define PR_TERMCHILD		12 /* Kill child if the parent dies. */#define PR_GETSHMASK		13 /* Get the sproc() share mask. */#define PR_GETNSHARE		14 /* Number of share group members. */#define PR_COREPID		15 /* Add task pid to name when it core. */#define PR_ATTACHADDRPERM	16 /* (Re-)Connect vma, with specified prot. */#define PR_PTHREADEXIT		17 /* Kill a pthread, only for IRIX 6.[234] */asmlinkage int irix_prctl(unsigned option, ...){	va_list args;	int error = 0;	va_start(args, option);	switch (option) {	case PR_MAXPROCS:		printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",		       current->comm, current->pid);		error = max_threads;		break;	case PR_ISBLOCKED: {		struct task_struct *task;		printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n",		       current->comm, current->pid);		read_lock(&tasklist_lock);		task = find_task_by_pid(va_arg(args, pid_t));		error = -ESRCH;		if (error)			error = (task->run_list.next != NULL);		read_unlock(&tasklist_lock);		/* Can _your_ OS find this out that fast? */		break;	}	case PR_SETSTACKSIZE: {		long value = va_arg(args, long);		printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n",		       current->comm, current->pid, (unsigned long) value);		if (value > RLIM_INFINITY)			value = RLIM_INFINITY;		if (capable(CAP_SYS_ADMIN)) {			task_lock(current->group_leader);			current->signal->rlim[RLIMIT_STACK].rlim_max =				current->signal->rlim[RLIMIT_STACK].rlim_cur = value;			task_unlock(current->group_leader);			error = value;			break;		}		task_lock(current->group_leader);		if (value > current->signal->rlim[RLIMIT_STACK].rlim_max) {			error = -EINVAL;			task_unlock(current->group_leader);			break;		}		current->signal->rlim[RLIMIT_STACK].rlim_cur = value;		task_unlock(current->group_leader);		error = value;		break;	}	case PR_GETSTACKSIZE:		printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n",		       current->comm, current->pid);		error = current->signal->rlim[RLIMIT_STACK].rlim_cur;		break;	case PR_MAXPPROCS:		printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",		       current->comm, current->pid);		error = 1;		break;	case PR_UNBLKONEXEC:		printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n",		       current->comm, current->pid);		error = -EINVAL;		break;	case PR_SETEXITSIG:		printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n",		       current->comm, current->pid);		/* We can probably play some game where we set the task		 * exit_code to some non-zero value when this is requested,		 * and check whether exit_code is already set in do_exit().		 */		error = -EINVAL;		break;	case PR_RESIDENT:		printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n",		       current->comm, current->pid);		error = 0; /* Compatibility indeed. */		break;	case PR_ATTACHADDR:		printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n",		       current->comm, current->pid);		error = -EINVAL;		break;	case PR_DETACHADDR:		printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n",		       current->comm, current->pid);		error = -EINVAL;		break;	case PR_TERMCHILD:		printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n",		       current->comm, current->pid);		error = -EINVAL;		break;	case PR_GETSHMASK:		printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n",		       current->comm, current->pid);		error = -EINVAL; /* Until I have the sproc() stuff in. */		break;	case PR_GETNSHARE:		error = 0;       /* Until I have the sproc() stuff in. */		break;	case PR_COREPID:		printk("irix_prctl[%s:%d]: Wants PR_COREPID\n",		       current->comm, current->pid);		error = -EINVAL;		break;	case PR_ATTACHADDRPERM:		printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n",		       current->comm, current->pid);		error = -EINVAL;		break;	default:		printk("irix_prctl[%s:%d]: Non-existant opcode %d\n",		       current->comm, current->pid, option);		error = -EINVAL;		break;	}	va_end(args);	return error;}#undef DEBUG_PROCGRPSextern unsigned long irix_mapelf(int fd, struct elf_phdr __user *user_phdrp, int cnt);extern int getrusage(struct task_struct *p, int who, struct rusage __user *ru);extern char *prom_getenv(char *name);extern long prom_setenv(char *name, char *value);/* The syssgi commands supported thus far. */#define SGI_SYSID         1       /* Return unique per-machine identifier. */#define SGI_INVENT        5       /* Fetch inventory  */#   define SGI_INV_SIZEOF 1#   define SGI_INV_READ   2#define SGI_RDNAME        6       /* Return string name of a process. */#define SGI_SETNVRAM	  8	  /* Set PROM variable. */#define SGI_GETNVRAM	  9	  /* Get PROM variable. */#define SGI_SETPGID      21       /* Set process group id. */#define SGI_SYSCONF      22       /* POSIX sysconf garbage. */#define SGI_PATHCONF     24       /* POSIX sysconf garbage. */#define SGI_SETGROUPS    40       /* POSIX sysconf garbage. */#define SGI_GETGROUPS    41       /* POSIX sysconf garbage. */#define SGI_RUSAGE       56       /* BSD style rusage(). */#define SGI_SSYNC        62       /* Synchronous fs sync. */#define SGI_GETSID       65       /* SysVr4 get session id. */#define SGI_ELFMAP       68       /* Map an elf image. */#define SGI_TOSSTSAVE   108       /* Toss saved vma's. */#define SGI_FP_BCOPY    129       /* Should FPU bcopy be used on this machine? */#define SGI_PHYSP      1011       /* Translate virtual into physical page. */asmlinkage int irix_syssgi(struct pt_regs *regs){	unsigned long cmd;	int retval, base = 0;	if (regs->regs[2] == 1000)		base = 1;	cmd = regs->regs[base + 4];	switch(cmd) {	case SGI_SYSID: {		char __user *buf = (char __user *) regs->regs[base + 5];		/* XXX Use ethernet addr.... */		retval = clear_user(buf, 64) ? -EFAULT : 0;		break;	}#if 0	case SGI_RDNAME: {		int pid = (int) regs->regs[base + 5];		char __user *buf = (char __user *) regs->regs[base + 6];		struct task_struct *p;		char tcomm[sizeof(current->comm)];		read_lock(&tasklist_lock);		p = find_task_by_pid(pid);		if (!p) {			read_unlock(&tasklist_lock);			retval = -ESRCH;			break;		}		get_task_comm(tcomm, p);		read_unlock(&tasklist_lock);		/* XXX Need to check sizes. */		retval = copy_to_user(buf, tcomm, sizeof(tcomm)) ? -EFAULT : 0;		break;	}	case SGI_GETNVRAM: {		char __user *name = (char __user *) regs->regs[base+5];		char __user *buf = (char __user *) regs->regs[base+6];		char *value;		return -EINVAL;	/* til I fix it */		value = prom_getenv(name);	/* PROM lock?  */		if (!value) {			retval = -EINVAL;			break;		}		/* Do I strlen() for the length? */		retval = copy_to_user(buf, value, 128) ? -EFAULT : 0;		break;	}	case SGI_SETNVRAM: {		char __user *name = (char __user *) regs->regs[base+5];		char __user *value = (char __user *) regs->regs[base+6];		return -EINVAL;	/* til I fix it */		retval = prom_setenv(name, value);		/* XXX make sure retval conforms to syssgi(2) */		printk("[%s:%d] setnvram(\"%s\", \"%s\"): retval %d",		       current->comm, current->pid, name, value, retval);/*		if (retval == PROM_ENOENT)		  	retval = -ENOENT; */		break;	}#endif	case SGI_SETPGID: {#ifdef DEBUG_PROCGRPS		printk("[%s:%d] setpgid(%d, %d) ",		       current->comm, current->pid,		       (int) regs->regs[base + 5], (int)regs->regs[base + 6]);#endif		retval = sys_setpgid(regs->regs[base + 5], regs->regs[base + 6]);#ifdef DEBUG_PROCGRPS		printk("retval=%d\n", retval);#endif	}	case SGI_SYSCONF: {		switch(regs->regs[base + 5]) {		case 1:			retval = (MAX_ARG_PAGES >> 4); /* XXX estimate... */			goto out;		case 2:			retval = max_threads;			goto out;		case 3:			retval = HZ;			goto out;		case 4:			retval = NGROUPS_MAX;			goto out;		case 5:			retval = NR_OPEN;			goto out;		case 6:			retval = 1;			goto out;		case 7:			retval = 1;			goto out;		case 8:			retval = 199009;			goto out;		case 11:			retval = PAGE_SIZE;			goto out;		case 12:			retval = 4;			goto out;		case 25:		case 26:		case 27:		case 28:		case 29:		case 30:			retval = 0;			goto out;		case 31:			retval = 32;			goto out;		default:			retval = -EINVAL;			goto out;		};	}	case SGI_SETGROUPS:		retval = sys_setgroups((int) regs->regs[base + 5],		                       (gid_t __user *) regs->regs[base + 6]);		break;	case SGI_GETGROUPS:		retval = sys_getgroups((int) regs->regs[base + 5],		                       (gid_t __user *) regs->regs[base + 6]);		break;	case SGI_RUSAGE: {		struct rusage __user *ru = (struct rusage __user *) regs->regs[base + 6];		switch((int) regs->regs[base + 5]) {		case 0:			/* rusage self */			retval = getrusage(current, RUSAGE_SELF, ru);			goto out;		case -1:			/* rusage children */			retval = getrusage(current, RUSAGE_CHILDREN, ru);			goto out;		default:			retval = -EINVAL;			goto out;		};	}	case SGI_SSYNC:		sys_sync();		retval = 0;		break;	case SGI_GETSID:#ifdef DEBUG_PROCGRPS		printk("[%s:%d] getsid(%d) ", current->comm, current->pid,		       (int) regs->regs[base + 5]);#endif		retval = sys_getsid(regs->regs[base + 5]);#ifdef DEBUG_PROCGRPS		printk("retval=%d\n", retval);#endif		break;	case SGI_ELFMAP:		retval = irix_mapelf((int) regs->regs[base + 5],				     (struct elf_phdr __user *) regs->regs[base + 6],				     (int) regs->regs[base + 7]);		break;	case SGI_TOSSTSAVE:		/* XXX We don't need to do anything? */		retval = 0;		break;	case SGI_FP_BCOPY:		retval = 0;		break;	case SGI_PHYSP: {		unsigned long addr = regs->regs[base + 5];		int __user *pageno = (int __user *) (regs->regs[base + 6]);		struct mm_struct *mm = current->mm;		pgd_t *pgdp;		pud_t *pudp;		pmd_t *pmdp;		pte_t *ptep;		down_read(&mm->mmap_sem);		pgdp = pgd_offset(mm, addr);		pudp = pud_offset(pgdp, addr);		pmdp = pmd_offset(pudp, addr);		ptep = pte_offset(pmdp, addr);		retval = -EINVAL;		if (ptep) {			pte_t pte = *ptep;			if (pte_val(pte) & (_PAGE_VALID | _PAGE_PRESENT)) {				/* b0rked on 64-bit */				retval =  put_user((pte_val(pte) & PAGE_MASK) >>				                   PAGE_SHIFT, pageno);			}		}		up_read(&mm->mmap_sem);		break;	}	case SGI_INVENT: {		int  arg1    = (int)    regs->regs [base + 5];		void __user *buffer = (void __user *) regs->regs [base + 6];		int  count   = (int)    regs->regs [base + 7];		switch (arg1) {		case SGI_INV_SIZEOF:			retval = sizeof (inventory_t);			break;		case SGI_INV_READ:			retval = dump_inventory_to_user (buffer, count);			break;		default:			retval = -EINVAL;		}		break;	}	default:		printk("irix_syssgi: Unsupported command %d\n", (int)cmd);		retval = -EINVAL;		break;	};out:	return retval;}asmlinkage int irix_gtime(struct pt_regs *regs){	return get_seconds();}/* * IRIX is completely broken... it returns 0 on success, otherwise * ENOMEM. */asmlinkage int irix_brk(unsigned long brk){	unsigned long rlim;	unsigned long newbrk, oldbrk;	struct mm_struct *mm = current->mm;	int ret;	down_write(&mm->mmap_sem);	if (brk < mm->end_code) {		ret = -ENOMEM;		goto out;	}	newbrk = PAGE_ALIGN(brk);	oldbrk = PAGE_ALIGN(mm->brk);	if (oldbrk == newbrk) {		mm->brk = brk;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -