|  |  | /*
 | 
						
						
						
							|  |  |  *  linux/kernel/sys.c
 | 
						
						
						
							|  |  |  *
 | 
						
						
						
							|  |  |  *  (C) 1991  Linus Torvalds
 | 
						
						
						
							|  |  |  */
 | 
						
						
						
							|  |  | #include <stdarg.h>
 | 
						
						
						
							|  |  |  
 | 
						
						
						
							|  |  | #include <linux/config.h>
 | 
						
						
						
							|  |  | #include <asm/system.h>
 | 
						
						
						
							|  |  | #include <asm/io.h>
 | 
						
						
						
							|  |  | #include <unistd.h>
 | 
						
						
						
							|  |  | #include <fcntl.h>
 | 
						
						
						
							|  |  | #include <string.h>
 | 
						
						
						
							|  |  | #include <sys/stat.h>
 | 
						
						
						
							|  |  | #include <errno.h>
 | 
						
						
						
							|  |  | #include <linux/sched.h>
 | 
						
						
						
							|  |  | #include <linux/tty.h>
 | 
						
						
						
							|  |  | #include <linux/kernel.h>
 | 
						
						
						
							|  |  | #include <asm/segment.h>
 | 
						
						
						
							|  |  | #include <sys/times.h>
 | 
						
						
						
							|  |  | #include <sys/utsname.h>
 | 
						
						
						
							|  |  | #include <stdarg.h>
 | 
						
						
						
							|  |  | #include <new.h>
 | 
						
						
						
							|  |  | #include <mm.h>
 | 
						
						
						
							|  |  | //ADD FOR getcwd    
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | long sys_getcwd(char *buf,size_t size)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	int block=current->pwd->i_zone[0];	
 | 
						
						
						
							|  |  | 	int idev=current->pwd->i_dev;
 | 
						
						
						
							|  |  | 	int flag=0;
 | 
						
						
						
							|  |  | 	struct buffer_head * bh;
 | 
						
						
						
							|  |  | 	struct dir_entry * de;
 | 
						
						
						
							|  |  | 	struct m_inode *dir=current->pwd,*rdir=current->root;
 | 
						
						
						
							|  |  | 	if(dir==rdir) 
 | 
						
						
						
							|  |  | 	{
 | 
						
						
						
							|  |  | 		flag=1;
 | 
						
						
						
							|  |  | 		goto mytag;
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 	unsigned short curinode,finode,tempfi;
 | 
						
						
						
							|  |  | 	char name[128],base[128];
 | 
						
						
						
							|  |  | 	int entries,i;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	if (!(block = current->pwd->i_zone[0]))
 | 
						
						
						
							|  |  | 		return NULL;
 | 
						
						
						
							|  |  | 	if (!(bh = bread(current->pwd->i_dev,block)))
 | 
						
						
						
							|  |  | 		return NULL;
 | 
						
						
						
							|  |  | 	de = (struct dir_entry *) bh->b_data;
 | 
						
						
						
							|  |  | 	curinode=de->inode;
 | 
						
						
						
							|  |  | 	de++;
 | 
						
						
						
							|  |  | 	finode=de->inode; 
 | 
						
						
						
							|  |  | 	while (rdir!=dir)
 | 
						
						
						
							|  |  | 	{
 | 
						
						
						
							|  |  | 		//update father
 | 
						
						
						
							|  |  | 		dir=iget(idev,finode); 
 | 
						
						
						
							|  |  | 		if (!(block = dir->i_zone[0]))
 | 
						
						
						
							|  |  | 			return NULL;
 | 
						
						
						
							|  |  | 		if (!(bh = bread(dir->i_dev,block)))
 | 
						
						
						
							|  |  | 			return NULL;
 | 
						
						
						
							|  |  | 		i = 0;
 | 
						
						
						
							|  |  | 		entries = dir->i_size / (sizeof (struct dir_entry));
 | 
						
						
						
							|  |  | 		de = (struct dir_entry *) bh->b_data;
 | 
						
						
						
							|  |  | 		tempfi=(de+1)->inode;
 | 
						
						
						
							|  |  | 		while (i < entries) {
 | 
						
						
						
							|  |  | 			if ((char *)de >= BLOCK_SIZE+bh->b_data) {
 | 
						
						
						
							|  |  | 				brelse(bh);
 | 
						
						
						
							|  |  | 				bh = NULL;
 | 
						
						
						
							|  |  | 				if (!(block = bmap(dir,i/DIR_ENTRIES_PER_BLOCK)) ||
 | 
						
						
						
							|  |  | 					!(bh = bread(dir->i_dev,block))) {
 | 
						
						
						
							|  |  | 					i += DIR_ENTRIES_PER_BLOCK;
 | 
						
						
						
							|  |  | 					continue;
 | 
						
						
						
							|  |  | 				}
 | 
						
						
						
							|  |  | 				de = (struct dir_entry *) bh->b_data;
 | 
						
						
						
							|  |  | 			}
 | 
						
						
						
							|  |  | 				if(de->inode==curinode)
 | 
						
						
						
							|  |  | 				{
 | 
						
						
						
							|  |  | 					memset(base,'\0',sizeof(base));
 | 
						
						
						
							|  |  | 					strcat(base,"/");
 | 
						
						
						
							|  |  | 					strcat(base,de->name);
 | 
						
						
						
							|  |  | 					strcat(base,name);
 | 
						
						
						
							|  |  | 					strcpy(name,base);
 | 
						
						
						
							|  |  | 					break;
 | 
						
						
						
							|  |  | 				}
 | 
						
						
						
							|  |  | 			de++;
 | 
						
						
						
							|  |  | 			i++;
 | 
						
						
						
							|  |  | 		}
 | 
						
						
						
							|  |  | 		curinode=finode;
 | 
						
						
						
							|  |  | 		finode=tempfi;
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | mytag:
 | 
						
						
						
							|  |  | 	if(flag) strcpy(name,"/");
 | 
						
						
						
							|  |  | 	size_t len=strlen(name);
 | 
						
						
						
							|  |  | 	if(size<len && buf!=NULL)
 | 
						
						
						
							|  |  | 	{
 | 
						
						
						
							|  |  | 		errno=ERANGE;
 | 
						
						
						
							|  |  | 		return NULL;
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 	if(!buf)
 | 
						
						
						
							|  |  | 		buf=(char*)malloc(len);
 | 
						
						
						
							|  |  | 	char *p1=buf;
 | 
						
						
						
							|  |  | 	char *p2=name;
 | 
						
						
						
							|  |  | 	while(len--)
 | 
						
						
						
							|  |  | 		put_fs_byte(*(p2++),p1++);
 | 
						
						
						
							|  |  | 	return buf;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | //THE END 
 | 
						
						
						
							|  |  | int sys_getdents(unsigned int fd,struct linux_dirent *dirp,unsigned int count)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	struct m_inode	*filenode =current->filp[fd]->f_inode;
 | 
						
						
						
							|  |  | 	int block,i,entries,sizdir=sizeof(struct dir_entry);
 | 
						
						
						
							|  |  | 	struct buffer_head * bh;
 | 
						
						
						
							|  |  | 	struct dir_entry * de;
 | 
						
						
						
							|  |  | 	struct linux_dirent *initmp,*temp;
 | 
						
						
						
							|  |  | 	if(!(temp=(struct linux_dirent *)malloc(count+64)))
 | 
						
						
						
							|  |  | 		return -1;
 | 
						
						
						
							|  |  | 	initmp=temp;
 | 
						
						
						
							|  |  | 	int size=sizeof(long)+sizeof(off_t)+sizeof(unsigned short);
 | 
						
						
						
							|  |  | 	
 | 
						
						
						
							|  |  | 	if (!(block = filenode->i_zone[0]))
 | 
						
						
						
							|  |  | 		return -1;
 | 
						
						
						
							|  |  | 	if (!(bh = bread(filenode->i_dev,block)))
 | 
						
						
						
							|  |  | 		return -1;
 | 
						
						
						
							|  |  | 	de = (struct dir_entry *) bh->b_data;
 | 
						
						
						
							|  |  | 	entries=filenode->i_size/(sizeof(struct dir_entry));
 | 
						
						
						
							|  |  | 	i=0;
 | 
						
						
						
							|  |  | 	int nread=0,pos=0;
 | 
						
						
						
							|  |  | 	while(i<entries)
 | 
						
						
						
							|  |  | 	{
 | 
						
						
						
							|  |  | 		if ((char *)de >= BLOCK_SIZE+bh->b_data) {
 | 
						
						
						
							|  |  | 				brelse(bh);
 | 
						
						
						
							|  |  | 				bh = NULL;
 | 
						
						
						
							|  |  | 				if (!(block = bmap(filenode,i/DIR_ENTRIES_PER_BLOCK)) ||
 | 
						
						
						
							|  |  | 					!(bh = bread(filenode->i_dev,block))) {
 | 
						
						
						
							|  |  | 					i += DIR_ENTRIES_PER_BLOCK;
 | 
						
						
						
							|  |  | 					continue;
 | 
						
						
						
							|  |  | 				}
 | 
						
						
						
							|  |  | 				pos+=((char*) bh->b_data-(char*)(de));
 | 
						
						
						
							|  |  | 				de = (struct dir_entry *) bh->b_data;
 | 
						
						
						
							|  |  | 			}
 | 
						
						
						
							|  |  | 		temp->d_ino=de->inode;
 | 
						
						
						
							|  |  | 		temp->d_off=pos;
 | 
						
						
						
							|  |  | 		strcpy(temp->d_name,de->name);
 | 
						
						
						
							|  |  | 		temp->d_reclen=sizeof(de);
 | 
						
						
						
							|  |  | 		nread+=temp->d_reclen;
 | 
						
						
						
							|  |  | 		temp=(struct linux_dirent*)((char*)temp+temp->d_reclen);
 | 
						
						
						
							|  |  | 		de++;
 | 
						
						
						
							|  |  | 		pos+=sizdir;
 | 
						
						
						
							|  |  | 		i++;
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 	if(count<nread)
 | 
						
						
						
							|  |  | 	{
 | 
						
						
						
							|  |  | 		errno=ERANGE;
 | 
						
						
						
							|  |  | 		return -1;
 | 
						
						
						
							|  |  | 	}//printk("%d",nread);
 | 
						
						
						
							|  |  | 	i=nread;
 | 
						
						
						
							|  |  | 	char *p1=dirp;
 | 
						
						
						
							|  |  | 	char *p2=initmp;
 | 
						
						
						
							|  |  | 	while(i--)
 | 
						
						
						
							|  |  | 		put_fs_byte(*(p2++),p1++);
 | 
						
						
						
							|  |  | 	free(initmp);
 | 
						
						
						
							|  |  | 	return nread;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | int sys_pipe2()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -1;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | unsigned int sys_sleep(unsigned int seconds)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	struct sigaction tmp;
 | 
						
						
						
							|  |  | 	tmp.sa_handler = (void (*)(int)) SIG_IGN;
 | 
						
						
						
							|  |  | 	tmp.sa_mask = 0;
 | 
						
						
						
							|  |  | 	tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
 | 
						
						
						
							|  |  | 	tmp.sa_restorer = (void (*)(void)) NULL;
 | 
						
						
						
							|  |  | 	current->sigaction[SIGALRM-1] = tmp;
 | 
						
						
						
							|  |  | 	current->alarm=(seconds>0)?(jiffies+HZ*seconds):0;
 | 
						
						
						
							|  |  | 	current->state=TASK_INTERRUPTIBLE;
 | 
						
						
						
							|  |  | 	current->counter=(current->counter>>1)+current->priority;
 | 
						
						
						
							|  |  | 	schedule();
 | 
						
						
						
							|  |  | 	return 0;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_clone()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	return -1;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_ftime()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_break()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_ptrace()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_stty()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_gtty()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_rename()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_prof()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_setregid(int rgid, int egid)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	if (rgid>0) {
 | 
						
						
						
							|  |  | 		if ((current->gid == rgid) || 
 | 
						
						
						
							|  |  | 		    suser())
 | 
						
						
						
							|  |  | 			current->gid = rgid;
 | 
						
						
						
							|  |  | 		else
 | 
						
						
						
							|  |  | 			return(-EPERM);
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 	if (egid>0) {
 | 
						
						
						
							|  |  | 		if ((current->gid == egid) ||
 | 
						
						
						
							|  |  | 		    (current->egid == egid) ||
 | 
						
						
						
							|  |  | 		    suser()) {
 | 
						
						
						
							|  |  | 			current->egid = egid;
 | 
						
						
						
							|  |  | 			current->sgid = egid;
 | 
						
						
						
							|  |  | 		} else
 | 
						
						
						
							|  |  | 			return(-EPERM);
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 	return 0;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_setgid(int gid)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | /*	return(sys_setregid(gid, gid)); */
 | 
						
						
						
							|  |  | 	if (suser())
 | 
						
						
						
							|  |  | 		current->gid = current->egid = current->sgid = gid;
 | 
						
						
						
							|  |  | 	else if ((gid == current->gid) || (gid == current->sgid))
 | 
						
						
						
							|  |  | 		current->egid = gid;
 | 
						
						
						
							|  |  | 	else
 | 
						
						
						
							|  |  | 		return -EPERM;
 | 
						
						
						
							|  |  | 	return 0;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_acct()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_phys()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_lock()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_mpx()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_ulimit()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_time(long * tloc)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	int i;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	i = CURRENT_TIME;
 | 
						
						
						
							|  |  | 	if (tloc) {
 | 
						
						
						
							|  |  | 		verify_area(tloc,4);
 | 
						
						
						
							|  |  | 		put_fs_long(i,(unsigned long *)tloc);
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 	return i;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | /*
 | 
						
						
						
							|  |  |  * Unprivileged users may change the real user id to the effective uid
 | 
						
						
						
							|  |  |  * or vice versa.
 | 
						
						
						
							|  |  |  */
 | 
						
						
						
							|  |  | int sys_setreuid(int ruid, int euid)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	int old_ruid = current->uid;
 | 
						
						
						
							|  |  | 	
 | 
						
						
						
							|  |  | 	if (ruid>0) {
 | 
						
						
						
							|  |  | 		if ((current->euid==ruid) ||
 | 
						
						
						
							|  |  |                     (old_ruid == ruid) ||
 | 
						
						
						
							|  |  | 		    suser())
 | 
						
						
						
							|  |  | 			current->uid = ruid;
 | 
						
						
						
							|  |  | 		else
 | 
						
						
						
							|  |  | 			return(-EPERM);
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 	if (euid>0) {
 | 
						
						
						
							|  |  | 		if ((old_ruid == euid) ||
 | 
						
						
						
							|  |  |                     (current->euid == euid) ||
 | 
						
						
						
							|  |  | 		    suser()) {
 | 
						
						
						
							|  |  | 			current->euid = euid;
 | 
						
						
						
							|  |  | 			current->suid = euid;
 | 
						
						
						
							|  |  | 		} else {
 | 
						
						
						
							|  |  | 			current->uid = old_ruid;
 | 
						
						
						
							|  |  | 			return(-EPERM);
 | 
						
						
						
							|  |  | 		}
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 	return 0;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_setuid(int uid)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | /*	return(sys_setreuid(uid, uid)); */
 | 
						
						
						
							|  |  | 	if (suser())
 | 
						
						
						
							|  |  | 		current->uid = current->euid = current->suid = uid;
 | 
						
						
						
							|  |  | 	else if ((uid == current->uid) || (uid == current->suid))
 | 
						
						
						
							|  |  | 		current->euid = uid;
 | 
						
						
						
							|  |  | 	else
 | 
						
						
						
							|  |  | 		return -EPERM;
 | 
						
						
						
							|  |  | 	return(0);
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_stime(long * tptr)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	if (!suser())
 | 
						
						
						
							|  |  | 		return -EPERM;
 | 
						
						
						
							|  |  | 	startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;
 | 
						
						
						
							|  |  | 	return 0;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_times(struct tms * tbuf)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	if (tbuf) {
 | 
						
						
						
							|  |  | 		verify_area(tbuf,sizeof *tbuf);
 | 
						
						
						
							|  |  | 		put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
 | 
						
						
						
							|  |  | 		put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
 | 
						
						
						
							|  |  | 		put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
 | 
						
						
						
							|  |  | 		put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 	return jiffies;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_brk(unsigned long end_data_seg)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	if (end_data_seg >= current->end_code &&
 | 
						
						
						
							|  |  | 	    end_data_seg < current->start_stack - 16384)
 | 
						
						
						
							|  |  | 		current->brk = end_data_seg;
 | 
						
						
						
							|  |  | 	return current->brk;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | /*
 | 
						
						
						
							|  |  |  * This needs some heave checking ...
 | 
						
						
						
							|  |  |  * I just haven't get the stomach for it. I also don't fully
 | 
						
						
						
							|  |  |  * understand sessions/pgrp etc. Let somebody who does explain it.
 | 
						
						
						
							|  |  |  */
 | 
						
						
						
							|  |  | int sys_setpgid(int pid, int pgid)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	int i;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	if (!pid)
 | 
						
						
						
							|  |  | 		pid = current->pid;
 | 
						
						
						
							|  |  | 	if (!pgid)
 | 
						
						
						
							|  |  | 		pgid = current->pid;
 | 
						
						
						
							|  |  | 	for (i=0 ; i<NR_TASKS ; i++)
 | 
						
						
						
							|  |  | 		if (task[i] && task[i]->pid==pid) {
 | 
						
						
						
							|  |  | 			if (task[i]->leader)
 | 
						
						
						
							|  |  | 				return -EPERM;
 | 
						
						
						
							|  |  | 			if (task[i]->session != current->session)
 | 
						
						
						
							|  |  | 				return -EPERM;
 | 
						
						
						
							|  |  | 			task[i]->pgrp = pgid;
 | 
						
						
						
							|  |  | 			return 0;
 | 
						
						
						
							|  |  | 		}
 | 
						
						
						
							|  |  | 	return -ESRCH;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_getpgrp(void)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return current->pgrp;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_setsid(void)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	if (current->leader && !suser())
 | 
						
						
						
							|  |  | 		return -EPERM;
 | 
						
						
						
							|  |  | 	current->leader = 1;
 | 
						
						
						
							|  |  | 	current->session = current->pgrp = current->pid;
 | 
						
						
						
							|  |  | 	current->tty = -1;
 | 
						
						
						
							|  |  | 	return current->pgrp;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_getgroups()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_setgroups()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_uname(struct utsname * name)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	static struct utsname thisname = {
 | 
						
						
						
							|  |  | 		"linux .0","nodename","release ","version ","machine "
 | 
						
						
						
							|  |  | 	};
 | 
						
						
						
							|  |  | 	int i;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	if (!name) return -ERROR;
 | 
						
						
						
							|  |  | 	verify_area(name,sizeof *name);
 | 
						
						
						
							|  |  | 	for(i=0;i<sizeof *name;i++)
 | 
						
						
						
							|  |  | 		put_fs_byte(((char *) &thisname)[i],i+(char *) name);
 | 
						
						
						
							|  |  | 	return 0;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_sethostname()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_getrlimit()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_setrlimit()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_getrusage()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_gettimeofday()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_settimeofday()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	return -ENOSYS;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | int sys_umask(int mask)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	int old = current->umask;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	current->umask = mask & 0777;
 | 
						
						
						
							|  |  | 	return (old);
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | static int my_share(unsigned long address, struct task_struct * p)
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	unsigned long from;
 | 
						
						
						
							|  |  | 	unsigned long to;
 | 
						
						
						
							|  |  | 	unsigned long from_page;
 | 
						
						
						
							|  |  | 	unsigned long to_page;
 | 
						
						
						
							|  |  | 	unsigned long phys_addr;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	from_page = to_page = ((address>>20) & 0xffc);
 | 
						
						
						
							|  |  | 	from_page += ((current->start_code>>20) & 0xffc);
 | 
						
						
						
							|  |  | 	to_page += ((p->start_code>>20) & 0xffc);
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	from = *(unsigned long *) from_page;
 | 
						
						
						
							|  |  | 	from &= 0xfffff000;
 | 
						
						
						
							|  |  | 	from_page = from + ((address>>10) & 0xffc);
 | 
						
						
						
							|  |  | 	phys_addr = *(unsigned long *) from_page;
 | 
						
						
						
							|  |  | 	to = *(unsigned long *) to_page;
 | 
						
						
						
							|  |  | 	if (!(to & 1))
 | 
						
						
						
							|  |  | 		if (to = get_free_page())
 | 
						
						
						
							|  |  | 			*(unsigned long *) to_page = to | 7;
 | 
						
						
						
							|  |  | 		else
 | 
						
						
						
							|  |  | 			return 0;
 | 
						
						
						
							|  |  | 	to &= 0xfffff000;
 | 
						
						
						
							|  |  | 	to_page = to + ((address>>10) & 0xffc);
 | 
						
						
						
							|  |  | 	if (1 & *(unsigned long *) to_page)
 | 
						
						
						
							|  |  | 		return 0;
 | 
						
						
						
							|  |  | 	/* share them: write-protect */
 | 
						
						
						
							|  |  | 	*(unsigned long *) to_page = *(unsigned long *) from_page;
 | 
						
						
						
							|  |  | 	phys_addr -= LOW_MEM;
 | 
						
						
						
							|  |  | 	phys_addr >>= 12;
 | 
						
						
						
							|  |  | 	mem_map[phys_addr]++;
 | 
						
						
						
							|  |  | 	return 1;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // rememeber to sync when munmap exit manual 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | long sys_mmap(void * start,size_t len,...)// int prot,int flags,int fd,off_t off
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 	printk("start mmaping\n");
 | 
						
						
						
							|  |  | 	/* va_list args;
 | 
						
						
						
							|  |  | 	va_start(args,len); */
 | 
						
						
						
							|  |  | 	int prot=3,flags=1,fd=3,off=0;
 | 
						
						
						
							|  |  | 	/* prot=va_arg(args,int);flags=va_arg(args,int);fd=va_arg(args,int);
 | 
						
						
						
							|  |  | 	off_t off=va_arg(args,off_t);
 | 
						
						
						
							|  |  | 	int *ll=&len;printk("%d,%d,%d,%d,%d\n",*ll,*(ll+1),*(ll+2),*(ll+3),*(ll+4));
 | 
						
						
						
							|  |  | 	va_end(args);
 | 
						
						
						
							|  |  | 	printk("%d,%d,%d,%ld\n",prot,flags,fd,off); */
 | 
						
						
						
							|  |  | 	
 | 
						
						
						
							|  |  | 	int block;
 | 
						
						
						
							|  |  | 	size_t l=len;
 | 
						
						
						
							|  |  | 	struct buffer_head * bh;
 | 
						
						
						
							|  |  | 	char *temp,*p1,*p2;
 | 
						
						
						
							|  |  | 	void * buf=start;
 | 
						
						
						
							|  |  | 	int tempprot=0;
 | 
						
						
						
							|  |  | 	
 | 
						
						
						
							|  |  | 	//因为new.h和namei.c定义不一样,要修改
 | 
						
						
						
							|  |  | 	if(prot &PROT_READ) tempprot |=4;
 | 
						
						
						
							|  |  | 	if(prot &PROT_EXEC) tempprot |=1;
 | 
						
						
						
							|  |  | 	if(prot &PROT_WRITE) tempprot |=2;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	//特殊量len>0 off%4096==0 prot至少有read权限
 | 
						
						
						
							|  |  | 	if(len<=0 ||  off<0 || (off%PAGE_SIZE)) 
 | 
						
						
						
							|  |  | 	{
 | 
						
						
						
							|  |  | 		if(len<=0) 
 | 
						
						
						
							|  |  | 			printk("the len of the wanting bytes must be positive");
 | 
						
						
						
							|  |  | 		else
 | 
						
						
						
							|  |  | 			printk("offset must be the mul of 4096");
 | 
						
						
						
							|  |  | 		return MAP_FAILED;
 | 
						
						
						
							|  |  | 	}	
 | 
						
						
						
							|  |  | 	if(!(prot& PROT_READ)) return MAP_FAILED;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	//permissions of the file ,搬运函数namei.c::permissions
 | 
						
						
						
							|  |  | 	printk("fd: %d\n",fd);
 | 
						
						
						
							|  |  | 	struct m_inode *inode=current->filp[fd]->f_inode;
 | 
						
						
						
							|  |  | 	printk("end of permissions\n");
 | 
						
						
						
							|  |  | 	int mode = inode->i_mode;
 | 
						
						
						
							|  |  | 	if (inode->i_dev && !inode->i_nlinks)
 | 
						
						
						
							|  |  | 		{printk("end of permissions1\n");return MAP_FAILED;}
 | 
						
						
						
							|  |  | 	else if (current->euid==inode->i_uid)
 | 
						
						
						
							|  |  | 		mode >>= 6;
 | 
						
						
						
							|  |  | 	else if (current->egid==inode->i_gid)
 | 
						
						
						
							|  |  | 		mode >>= 3;
 | 
						
						
						
							|  |  | 	if (!(((mode & tempprot & 0007) == tempprot) || suser()))
 | 
						
						
						
							|  |  | 	{
 | 
						
						
						
							|  |  | 		printk("error permission.");
 | 
						
						
						
							|  |  | 		return MAP_FAILED;
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 	//end of permission check
 | 
						
						
						
							|  |  | 	printk("end of permissions\n");
 | 
						
						
						
							|  |  | 	
 | 
						
						
						
							|  |  | 	//设置用户空间的虚拟地址,初始为32MB处,这样写在brk增长至32MB时会有bug,我们忽略
 | 
						
						
						
							|  |  | 	//同时,当栈向下增长到一定程度时,也会和当前地址冲突,我们忽略
 | 
						
						
						
							|  |  | 	if(start<=current->brk || start>=current->start_stack-0x8000 || start==NULL) 
 | 
						
						
						
							|  |  | 	{
 | 
						
						
						
							|  |  | 		if(!current->mmap_tail)
 | 
						
						
						
							|  |  | 			buf=0x2000000;
 | 
						
						
						
							|  |  | 		else
 | 
						
						
						
							|  |  | 			buf=current->mmap_tail->endaddr;
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 	//申请mmap
 | 
						
						
						
							|  |  | 	struct mmap_struct *mmap=(struct mmap_struct *)malloc(sizeof(struct mmap_struct));
 | 
						
						
						
							|  |  | 	mmap->address=buf;
 | 
						
						
						
							|  |  | 	mmap->size=len;
 | 
						
						
						
							|  |  | 	mmap->endaddr=(unsigned long)buf+(len + 0xfff)&0xfffff000;
 | 
						
						
						
							|  |  | 	mmap->rw=prot;
 | 
						
						
						
							|  |  | 	mmap->ps=flags;
 | 
						
						
						
							|  |  | 	mmap->next=NULL;
 | 
						
						
						
							|  |  | 	//加入current->mmap
 | 
						
						
						
							|  |  | 	if(!current->mmap) 
 | 
						
						
						
							|  |  | 		{current->mmap=current->mmap_tail=mmap;}
 | 
						
						
						
							|  |  | 	else 
 | 
						
						
						
							|  |  | 		current->mmap_tail->next=mmap;
 | 
						
						
						
							|  |  | 	printk("buf: %x\n",(unsigned long )buf);
 | 
						
						
						
							|  |  | 	
 | 
						
						
						
							|  |  | 	//分配物理页
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	unsigned long from;
 | 
						
						
						
							|  |  | 	unsigned long to;
 | 
						
						
						
							|  |  | 	unsigned long from_page;
 | 
						
						
						
							|  |  | 	unsigned long to_page;
 | 
						
						
						
							|  |  | 	unsigned long phys_addr;
 | 
						
						
						
							|  |  | 	unsigned long tpage;
 | 
						
						
						
							|  |  | 	unsigned long address=mmap->address;
 | 
						
						
						
							|  |  | 	while(address<mmap->endaddr)
 | 
						
						
						
							|  |  | 	{
 | 
						
						
						
							|  |  | 		from_page =  ((mmap->address>>20) & 0xffc);
 | 
						
						
						
							|  |  | 		from_page += ((current->start_code>>20) & 0xffc);//页目录
 | 
						
						
						
							|  |  | 		if(!(*(unsigned long *)from_page&1))  //页表项不存在,申请页面
 | 
						
						
						
							|  |  | 			if(!(tpage=get_free_page()))
 | 
						
						
						
							|  |  | 			{
 | 
						
						
						
							|  |  | 				printk("out of memory.\n");
 | 
						
						
						
							|  |  | 				return MAP_FAILED;
 | 
						
						
						
							|  |  | 			}
 | 
						
						
						
							|  |  | 			else
 | 
						
						
						
							|  |  | 				*(unsigned long *)from_page= tpage | 7;
 | 
						
						
						
							|  |  | 		from=*(unsigned long *)from_page;	//页表项
 | 
						
						
						
							|  |  | 		from &= 0xfffff000;
 | 
						
						
						
							|  |  | 		from_page = from + ((address>>10) & 0xffc);
 | 
						
						
						
							|  |  | 		if(!(*(unsigned long *)from_page & 1))	//物理页不存在
 | 
						
						
						
							|  |  | 			if(!(tpage=get_free_page()))
 | 
						
						
						
							|  |  | 			{
 | 
						
						
						
							|  |  | 				printk("out of memory.\n");
 | 
						
						
						
							|  |  | 				return MAP_FAILED;
 | 
						
						
						
							|  |  | 			}
 | 
						
						
						
							|  |  | 			else
 | 
						
						
						
							|  |  | 				*(unsigned long *)from_page= tpage | 7; 
 | 
						
						
						
							|  |  | 		*(unsigned long *)from_page &= (prot&PROT_WRITE); //分配读写权限
 | 
						
						
						
							|  |  | 		if(flags & MAP_SHARED)
 | 
						
						
						
							|  |  | 		{
 | 
						
						
						
							|  |  | 			struct task_struct ** p;
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 			for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
 | 
						
						
						
							|  |  | 				if (!*p)
 | 
						
						
						
							|  |  | 					continue;
 | 
						
						
						
							|  |  | 				if (current == *p)
 | 
						
						
						
							|  |  | 					continue;
 | 
						
						
						
							|  |  | 				if(!my_share(address,*p))
 | 
						
						
						
							|  |  | 					printk("share failed at task:pid=%d",(*p)->pid);
 | 
						
						
						
							|  |  | 			}
 | 
						
						
						
							|  |  | 		}
 | 
						
						
						
							|  |  | 		address+=PAGE_SIZE;
 | 
						
						
						
							|  |  | 	}
 | 
						
						
						
							|  |  | 		
 | 
						
						
						
							|  |  | 	//read and put in 
 | 
						
						
						
							|  |  | 	if (!(block = inode->i_zone[0]))
 | 
						
						
						
							|  |  | 		return NULL;
 | 
						
						
						
							|  |  | 	if (!(bh = bread(inode->i_dev,block)))
 | 
						
						
						
							|  |  | 		return NULL;
 | 
						
						
						
							|  |  | 	temp = (char *) bh->b_data;
 | 
						
						
						
							|  |  | 	p1=temp;p2=buf;
 | 
						
						
						
							|  |  | 	while(l--)
 | 
						
						
						
							|  |  | 		put_fs_byte(*(p1++),p2++);
 | 
						
						
						
							|  |  | 	printk("%s\n",temp);
 | 
						
						
						
							|  |  | 	return buf;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | int sys_munmap()
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 	return -1;
 | 
						
						
						
							|  |  | }
 |