/* * The additional architecture-specific notes for Cell are various * context files in the spu context. * * This function iterates over all open file descriptors and sees * if they are a directory in spufs. In that case we use spufs * internal functionality to dump them without needing to actually * open the files. */ static struct spu_context *coredump_next_context(int *fd) { struct fdtable *fdt = files_fdtable(current->files); struct file *file; struct spu_context *ctx = NULL; for (; *fd < fdt->max_fds; (*fd)++) { if (!FD_ISSET(*fd, fdt->open_fds)) continue; file = fcheck(*fd); if (!file || file->f_op != &spufs_context_fops) continue; ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx; if (ctx->flags & SPU_CREATE_NOSCHED) continue; /* start searching the next fd next time we're called */ (*fd)++; break; } return ctx; }
static INT8S fs_init (void) { INT32U retv; retv = finit (); spi_hi_speed (__TRUE); if (retv == 0) { retv = fcheck ("S:"); } else { retv = fformat ("S:"); if (retv == 0) { return 0; } else { return -1; } } return 0; }
asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd) { int err = -EBADF; lock_kernel(); #ifdef FDSET_DEBUG printk (KERN_ERR __FUNCTION__ " 0: oldfd = %d, newfd = %d\n", oldfd, newfd); #endif if (!fcheck(oldfd)) goto out; if (newfd >= NR_OPEN) goto out; /* following POSIX.1 6.2.1 */ err = newfd; if (newfd == oldfd) goto out; /* We must be able to do the fd setting inside dupfd() without blocking after the sys_close(). */ if ((err = expand_files(current->files, newfd)) < 0) goto out; sys_close(newfd); err = dupfd(oldfd, newfd); out: #ifdef FDSET_DEBUG printk (KERN_ERR __FUNCTION__ ": return %d\n", err); #endif unlock_kernel(); return err; }
static void timod_error(int fd, int prim, int terr, int uerr) { struct file *fp; struct T_primsg *it; struct T_error_ack *err; #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_STREAMS, "TI: %u error prim=%d, TLI=%d, UNIX=%d\n", fd, prim, terr, uerr); #endif fp = fcheck(fd); it = timod_mkctl(sizeof(struct T_error_ack)); if (!it) return; err = (struct T_error_ack *)&it->type; err->PRIM_type = T_ERROR_ACK; err->ERROR_prim = prim; err->TLI_error = terr; err->UNIX_error = iABI_errors(uerr); it->pri = MSG_HIPRI; it->length = sizeof(struct T_error_ack); it->next = Priv(fp)->pfirst; Priv(fp)->pfirst = it; if (!Priv(fp)->plast) Priv(fp)->plast = it; timod_socket_wakeup(fp); }
static void timod_ok(int fd, int prim) { struct file *fp; struct T_primsg *it; struct T_ok_ack *ok; #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_STREAMS, "TI: %u ok ack prim=%d\n", fd, prim); #endif fp = fcheck(fd); it = timod_mkctl(sizeof(struct T_ok_ack)); if (!it) return; ok = (struct T_ok_ack *)&it->type; ok->PRIM_type = T_OK_ACK; ok->CORRECT_prim = prim; it->pri = MSG_HIPRI; it->length = sizeof(struct T_ok_ack); it->next = Priv(fp)->pfirst; Priv(fp)->pfirst = it; if (!Priv(fp)->plast) Priv(fp)->plast = it; timod_socket_wakeup(fp); }
static XLIST_PAGE_T *xlist_newchild(XLIST_T *Me, PAGECHECK fcheck) { if(Me==NULL) return NULL; XLIST_PAGE_T *pg = NULL; LONG_T i; if(fcheck == NULL) { if(Me->PageCount==0 || Me->Pages==NULL) { pg = xlist_newpage(Me); } else { pg = xlist_page_appendchild(Me->Pages[Me->PageCount-1]); } } else { for(i=0; i<Me->PageCount; i++) { if(fcheck(Me->Pages[i])) { pg = xlist_page_appendchild(Me->Pages[i]); break; } } } return pg; }
asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3) { struct file *filp; struct inode *ino; struct strbuf *ctlptr, *datptr; struct strbuf ctl, dat; int flags = (int) arg3; int error = -EBADF; SOLD("entry"); lock_kernel(); if(fd >= NR_OPEN) goto out; read_lock(¤t->files->file_lock); filp = fcheck(fd); read_unlock(¤t->files->file_lock); if(!filp) goto out; ino = filp->f_dentry->d_inode; if (!ino) goto out; if (!ino->i_sock && (MAJOR(ino->i_rdev) != 30 || MINOR(ino->i_rdev) != 1)) goto out; ctlptr = (struct strbuf *)A(arg1); datptr = (struct strbuf *)A(arg2); error = -EFAULT; if (ctlptr) { if (copy_from_user(&ctl,ctlptr,sizeof(ctl))) goto out; if (ctl.len < 0 && flags) { error = -EINVAL; goto out; } } else { ctl.len = 0; ctl.buf = 0; } if (datptr) { if (copy_from_user(&dat,datptr,sizeof(dat))) goto out; } else { dat.len = 0; dat.buf = 0; } error = timod_putmsg(fd,(char*)A(ctl.buf),ctl.len, (char*)A(dat.buf),dat.len,flags); out: unlock_kernel(); SOLD("done"); return error; }
/* * descriptor table is not shared, so files can't change or go away. */ static struct spu_context *coredump_next_context(int *fd) { struct file *file; int n = iterate_fd(current->files, *fd, match_context, NULL); if (!n) return NULL; *fd = n - 1; file = fcheck(*fd); return SPUFS_I(file->f_dentry->d_inode)->i_ctx; }
asmlinkage int px_sys_mmap2( unsigned long addr, unsigned long len, unsigned long prot, unsigned long flgs, unsigned long fd, unsigned long pgoff /* unsigned long lRegSP*/ ) { int ret = 0; int saved_r5; unsigned long lsc; struct file *file; INIT_STACK_FRAME; // here we must save r5 since it will be used by the OS sys_mmap2 code __asm__("str r5, %0\n\t":"=m"(saved_r5):); APPEND_STACK_FRAME; lsc = get_sample_count(); // restore r5 __asm__("ldr r5, %0\n\t"::"m"(saved_r5):"r5"); ret = px_original_sys_mmap2( addr, len, prot, flgs, fd, pgoff); CUTTAIL_STACK_FRAME; if (gb_enable_os_hooks && !IS_ERR((void *)ret) && (prot & PROT_EXEC) && !(flgs & MAP_ANONYMOUS)) { //rcu_read_lock(); if ((file = fcheck(fd))!= NULL) { char *pname; memset(name, 0, PATH_MAX * sizeof(char)); pname = px_d_path(file, name, PATH_MAX); if (pname) { unsigned long name_offset; name_offset = get_filename_offset(pname); module_load_notif(pname, name_offset, current->tgid, ret, len, 0, lsc); } } //rcu_read_unlock(); } return ret; }
struct file *e_fget_light(unsigned int fd, int *fput_needed) { struct file *file; struct files_struct *files = current->files; *fput_needed = 0; if (likely((atomic_read(&files->count) == 1))) { file = fcheck(fd); } else { spin_lock(&files->file_lock); file = fcheck(fd); if (file) { get_file(file); *fput_needed = 1; } spin_unlock(&files->file_lock); } return file; } /*********** fin get_light **********/
asmlinkage int px_sys_mmap(struct mmap_arg_struct *arg) { int ret = 0; struct mmap_arg_struct tmp; struct file *file; unsigned long long lsc; char * name = NULL; lsc = get_sample_count(); if (copy_from_user(&tmp, arg, sizeof(tmp)) != 0) { return -EFAULT; } ret = px_original_sys_mmap(arg); if (gb_enable_os_hooks && (!IS_ERR((void*)ret)) && (tmp.prot & PROT_EXEC) && !(tmp.flags & MAP_ANONYMOUS)) { //rcu_read_lock(); if ((file = fcheck(tmp.fd)) != NULL) { char *filename; //memset(name, 0, PATH_MAX * sizeof(char)); name = kzalloc(PATH_MAX, GFP_ATOMIC); if (name == NULL) { return ret; } filename = px_d_path(file, name, PATH_MAX); if (filename) { unsigned long name_offset; name_offset = get_filename_offset(filename); module_load_notif(filename, name_offset, current->tgid, ret, tmp.len, 0, lsc); } kfree(name); } //rcu_read_unlock(); } return ret; }
static struct tty_struct *get_tty(int fd) { struct file *filp; struct tty_struct *ttyp = NULL; spin_lock(¤t->files->file_lock); filp = fcheck(fd); if(filp && filp->private_data) { ttyp = (struct tty_struct *) filp->private_data; if(ttyp->magic != TTY_MAGIC) ttyp =NULL; } spin_unlock(¤t->files->file_lock); return ttyp; }
static struct tty_struct *get_tty(int fd) { struct file *filp; struct tty_struct *ttyp = NULL; rcu_read_lock(); filp = fcheck(fd); if(filp && filp->private_data) { ttyp = (struct tty_struct *) filp->private_data; if(ttyp->magic != TTY_MAGIC) ttyp =NULL; } rcu_read_unlock(); return ttyp; }
int fcorr(int fd, va_list p, char f) { int i; static t_form formats[] = {{'d', &my_fdeci}, {'x', &my_flhex}, {'i', &my_fdeci}, {'X', &my_fLhex}, {'p', &my_fhexp}, {'s', &my_fstrp}, {'u', &my_funsigned}, {'o', &my_foctal}, {'S', &my_fspec}, {'c', &my_fchar}, {'b', &my_fbin}, {0, NULL}}; i = fcheck(fd, p, formats, f); return (i); }
/* * The additional architecture-specific notes for Cell are various * context files in the spu context. * * This function iterates over all open file descriptors and sees * if they are a directory in spufs. In that case we use spufs * internal functionality to dump them without needing to actually * open the files. */ static struct spu_context *coredump_next_context(int *fd) { struct fdtable *fdt = files_fdtable(current->files); struct file *file; struct spu_context *ctx = NULL; for (; *fd < fdt->max_fds; (*fd)++) { if (!fd_is_open(*fd, fdt)) continue; file = fcheck(*fd); if (!file || file->f_op != &spufs_context_fops) continue; ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx; if (ctx->flags & SPU_CREATE_NOSCHED) continue; break; } return ctx; }
/* * XXX: this function is a _horrible_ mess. */ static int timod_optmgmt(int fd, struct pt_regs * regs, int flag, char * opt_buf, int opt_len, int do_ret) { struct file * fp = fcheck(fd); char *ret_buf, *ret_base; u_int old_esp, *tsp; int is_tli, error, failed; int ret_len, ret_space; error=0; if (opt_buf && opt_len > 0) { if (!access_ok(VERIFY_READ, opt_buf, opt_len)) return -EFAULT; } /* * FIXME: * We should be able to detect the difference between * TLI and XTI requests at run time? */ #ifdef CONFIG_ABI_TLI_OPTMGMT is_tli = 1; #else is_tli = 0; #endif if (!do_ret && (!opt_buf || opt_len <= 0)) return 0; /* * Grab some space on the user stack to work with. We need 6 longs * to build an argument frame for [gs]etsockopt calls. We also * need space to build the return buffer. This will be at least * as big as the given options buffer but the given options * buffer may not include space for option values so we allow two * longs for each option multiple of the option header size * and hope that big options will not exhaust our space and * trash the stack. */ ret_space = 1024 + opt_len + 2*sizeof(long)*(opt_len / (is_tli ? sizeof(struct opthdr) : sizeof(struct t_opthdr))); ret_buf = ret_base = (char *)(_SP(regs) - ret_space); ret_len = 0; old_esp = _SP(regs); _SP(regs) -= ret_space + 6*sizeof(long); tsp = (unsigned int *)_SP(regs); if (!access_ok(VERIFY_WRITE, tsp, 6*sizeof(long))) { _SP(regs) = old_esp; return -EFAULT; } failed = 0; #ifndef CONFIG_ABI_TLI_OPTMGMT if (is_tli) { printk(KERN_WARNING "%d iBCS: TLI optmgmt requested but not supported\n", current->pid); } #else if (is_tli) while (opt_len >= sizeof(struct opthdr)) { struct opthdr opt; #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_STREAMS, "TLI optmgmt opt_len=%d, " "ret_buf=0x%08lx, ret_len=%d, ret_space=%d\n", opt_len, (unsigned long)ret_buf, ret_len, ret_space); #endif if (copy_from_user(&opt, opt_buf, sizeof(struct opthdr))) return -EFAULT; /* Idiot check... */ if (opt.len > opt_len) { failed = TBADOPT; break; } #if defined(CONFIG_ABI_TRACE) if (abi_traced(ABI_TRACE_STREAMS)) { unsigned long v; get_user(v, (unsigned long *)(opt_buf+sizeof(struct opthdr))); __abi_trace("TLI optmgmt fd=%d, level=%ld, " "name=%ld, value=%ld\n", fd, opt.level, opt.name, v); } #endif /* Check writable space in the return buffer. */ if (!access_ok(VERIFY_WRITE, ret_buf, sizeof(struct opthdr))) { failed = TSYSERR; break; } /* Flag values: * T_NEGOTIATE means try and set it. * T_DEFAULT means get the default value. * (return the current for now) * T_CHECK means get the current value. */ error = 0; if (flag == T_NEGOTIATE) { put_user(fd, tsp); put_user(opt.level, tsp+1); put_user(opt.name, tsp+2); put_user((long)opt_buf+sizeof(struct opthdr), tsp+3); put_user(opt.len, tsp+4); error = abi_do_setsockopt(tsp); if (error) { #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_STREAMS, "setsockopt failed: %d\n", error); #endif failed = TBADOPT; break; } } if (!error) { int len; put_user(fd, tsp); put_user(opt.level, tsp+1); put_user(opt.name, tsp+2); put_user((long)ret_buf+sizeof(struct opthdr), tsp+3); put_user((long)(tsp+5), tsp+4); put_user(ret_space, tsp+5); error = abi_do_getsockopt(tsp); if (error) { #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_STREAMS, "getsockopt failed: %d\n", error); #endif failed = TBADOPT; break; } get_user(len, tsp+5); if (copy_to_user(ret_buf, &opt, sizeof(opt))) return -EFAULT; put_user(len, &((struct opthdr *)opt_buf)->len); ret_space -= sizeof(struct opthdr) + len; ret_len += sizeof(struct opthdr) + len; ret_buf += sizeof(struct opthdr) + len; } opt_len -= sizeof(struct opthdr) + opt.len; opt_buf += sizeof(struct opthdr) + opt.len; } #endif /* CONFIG_ABI_TLI_OPTMGMT */ #ifndef CONFIG_ABI_XTI_OPTMGMT else { printk(KERN_WARNING "%d iBCS: XTI optmgmt requested but not supported\n", current->pid); } #else else while (opt_len >= sizeof(struct t_opthdr)) {
int timod_getmsg(unsigned int fd, char *ctl_buf, int ctl_maxlen, s32 *ctl_len, char *data_buf, int data_maxlen, s32 *data_len, int *flags_p) { int error; int oldflags; struct file *filp; struct inode *ino; struct sol_socket_struct *sock; struct T_unitdata_ind udi; mm_segment_t old_fs = get_fs(); long args[6]; char *tmpbuf; int tmplen; int (*sys_socketcall)(int, unsigned long *) = (int (*)(int, unsigned long *))SYS(socketcall); int (*sys_recvfrom)(int, void *, size_t, unsigned, struct sockaddr *, int *); SOLD("entry"); SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p)); read_lock(¤t->files->file_lock); filp = fcheck(fd); read_unlock(¤t->files->file_lock); if (!filp) return -EBADF; ino = filp->f_dentry->d_inode; sock = (struct sol_socket_struct *)filp->private_data; SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL)); if ( ctl_maxlen > 0 && !sock->pfirst && ino->u.socket_i.type == SOCK_STREAM && sock->state == TS_IDLE) { SOLD("calling LISTEN"); args[0] = fd; args[1] = -1; set_fs(KERNEL_DS); sys_socketcall(SYS_LISTEN, args); set_fs(old_fs); SOLD("LISTEN done"); } if (!(filp->f_flags & O_NONBLOCK)) { poll_table wait_table, *wait; poll_initwait(&wait_table); wait = &wait_table; for(;;) { SOLD("loop"); set_current_state(TASK_INTERRUPTIBLE); /* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ /* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ /* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ /* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */ /* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */ /* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */ if (ctl_maxlen >= 0 && sock->pfirst && (*flags_p != MSG_HIPRI || sock->pfirst->pri == MSG_HIPRI)) break; SOLD("cond 1 passed"); if ( #if 1 *flags_p != MSG_HIPRI && #endif ((filp->f_op->poll(filp, wait) & POLLIN) || (filp->f_op->poll(filp, NULL) & POLLIN) || signal_pending(current)) ) { break; } if( *flags_p == MSG_HIPRI ) { SOLD("avoiding lockup"); break ; } if(wait_table.error) { SOLD("wait-table error"); poll_freewait(&wait_table); return wait_table.error; } SOLD("scheduling"); schedule(); } SOLD("loop done"); current->state = TASK_RUNNING; poll_freewait(&wait_table); if (signal_pending(current)) { SOLD("signal pending"); return -EINTR; } } if (ctl_maxlen >= 0 && sock->pfirst) { struct T_primsg *it = sock->pfirst; int l = min_t(int, ctl_maxlen, it->length); SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC); SOLD("purting ctl data"); if(copy_to_user(ctl_buf, (char*)&it->type + sock->offset, l)) return -EFAULT; SOLD("pur it"); if(put_user(l, ctl_len)) return -EFAULT; SOLD("set ctl_len"); *flags_p = it->pri; it->length -= l; if (it->length) { SOLD("more ctl"); sock->offset += l; return MORECTL; } else { SOLD("removing message"); sock->pfirst = it->next; if (!sock->pfirst) sock->plast = NULL; SOLDD(("getmsg kfree %016lx->%016lx\n", it, sock->pfirst)); mykfree(it); sock->offset = 0; SOLD("ctl done"); return 0; } } *flags_p = 0; if (ctl_maxlen >= 0) { SOLD("ACCEPT perhaps?"); if (ino->u.socket_i.type == SOCK_STREAM && sock->state == TS_IDLE) { struct T_conn_ind ind; char *buf = getpage(); int len = BUF_SIZE; SOLD("trying ACCEPT"); if (put_user(ctl_maxlen - sizeof(ind), ctl_len)) return -EFAULT; args[0] = fd; args[1] = (long)buf; args[2] = (long)&len; oldflags = filp->f_flags; filp->f_flags |= O_NONBLOCK; SOLD("calling ACCEPT"); set_fs(KERNEL_DS); error = sys_socketcall(SYS_ACCEPT, args); set_fs(old_fs); filp->f_flags = oldflags; if (error < 0) { SOLD("some error"); putpage(buf); return error; } if (error) { SOLD("connect"); putpage(buf); if (sizeof(ind) > ctl_maxlen) { SOLD("generating CONN_IND"); ind.PRIM_type = T_CONN_IND; ind.SRC_length = len; ind.SRC_offset = sizeof(ind); ind.OPT_length = ind.OPT_offset = 0; ind.SEQ_number = error; if(copy_to_user(ctl_buf, &ind, sizeof(ind))|| put_user(sizeof(ind)+ind.SRC_length,ctl_len)) return -EFAULT; SOLD("CONN_IND created"); } if (data_maxlen >= 0) put_user(0, data_len); SOLD("CONN_IND done"); return 0; } if (len>ctl_maxlen) { SOLD("data don't fit"); putpage(buf); return -EFAULT; /* XXX - is this ok ? */ } if(copy_to_user(ctl_buf,buf,len) || put_user(len,ctl_len)){ SOLD("can't copy data"); putpage(buf); return -EFAULT; } SOLD("ACCEPT done"); putpage(buf); } } SOLD("checking data req"); if (data_maxlen <= 0) { if (data_maxlen == 0) put_user(0, data_len); if (ctl_maxlen >= 0) put_user(0, ctl_len); return -EAGAIN; } SOLD("wants data"); if (ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) { SOLD("udi fits"); tmpbuf = ctl_buf + sizeof(udi); tmplen = ctl_maxlen - sizeof(udi); } else { SOLD("udi does not fit"); tmpbuf = NULL; tmplen = 0; } if (put_user(tmplen, ctl_len)) return -EFAULT; SOLD("set ctl_len"); oldflags = filp->f_flags; filp->f_flags |= O_NONBLOCK; SOLD("calling recvfrom"); sys_recvfrom = (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(recvfrom); error = sys_recvfrom(fd, data_buf, data_maxlen, 0, (struct sockaddr*)tmpbuf, ctl_len); filp->f_flags = oldflags; if (error < 0) return error; SOLD("error >= 0" ) ; if (error && ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) { SOLD("generating udi"); udi.PRIM_type = T_UNITDATA_IND; get_user(udi.SRC_length, ctl_len); udi.SRC_offset = sizeof(udi); udi.OPT_length = udi.OPT_offset = 0; copy_to_user(ctl_buf, &udi, sizeof(udi)); put_user(sizeof(udi)+udi.SRC_length, ctl_len); SOLD("udi done"); } else put_user(0, ctl_len); put_user(error, data_len); SOLD("done"); return 0; }
asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3) { struct file *filp; struct inode *ino; struct strbuf *ctlptr, *datptr; struct strbuf ctl, dat; int *flgptr; int flags; int error = -EBADF; SOLD("entry"); lock_kernel(); if(fd >= NR_OPEN) goto out; read_lock(¤t->files->file_lock); filp = fcheck(fd); read_unlock(¤t->files->file_lock); if(!filp) goto out; ino = filp->f_dentry->d_inode; if (!ino) goto out; if (!ino->i_sock) goto out; ctlptr = (struct strbuf *)A(arg1); datptr = (struct strbuf *)A(arg2); flgptr = (int *)A(arg3); error = -EFAULT; if (ctlptr) { if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) || put_user(-1,&ctlptr->len)) goto out; } else ctl.maxlen = -1; if (datptr) { if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) || put_user(-1,&datptr->len)) goto out; } else dat.maxlen = -1; if (get_user(flags,flgptr)) goto out; switch (flags) { case 0: case MSG_HIPRI: case MSG_ANY: case MSG_BAND: break; default: error = -EINVAL; goto out; } error = timod_getmsg(fd,(char*)A(ctl.buf),ctl.maxlen,&ctlptr->len, (char*)A(dat.buf),dat.maxlen,&datptr->len,&flags); if (!error && put_user(flags,flgptr)) error = -EFAULT; out: unlock_kernel(); SOLD("done"); return error; }
asmlinkage int sunos_ioctl (int fd, unsigned long cmd, unsigned long arg) { int ret = -EBADF; if (fd >= SUNOS_NR_OPEN || !fcheck(fd)) goto out; /* First handle an easy compat. case for tty ldisc. */ if (cmd == TIOCSETD) { int __user *p; int ntty = N_TTY, tmp; mm_segment_t oldfs; p = (int __user *) arg; ret = -EFAULT; if (get_user(tmp, p)) goto out; if (tmp == 2) { oldfs = get_fs(); set_fs(KERNEL_DS); ret = sys_ioctl(fd, cmd, (unsigned long) &ntty); set_fs(oldfs); ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); goto out; } } /* Binary compatibility is good American knowhow f****n' up. */ if (cmd == TIOCNOTTY) { ret = sys_setsid(); goto out; } /* SunOS networking ioctls. */ switch (cmd) { case _IOW('r', 10, struct rtentry): ret = sys_ioctl(fd, SIOCADDRT, arg); goto out; case _IOW('r', 11, struct rtentry): ret = sys_ioctl(fd, SIOCDELRT, arg); goto out; case _IOW('i', 12, struct ifreq): ret = sys_ioctl(fd, SIOCSIFADDR, arg); goto out; case _IOWR('i', 13, struct ifreq): ret = sys_ioctl(fd, SIOCGIFADDR, arg); goto out; case _IOW('i', 14, struct ifreq): ret = sys_ioctl(fd, SIOCSIFDSTADDR, arg); goto out; case _IOWR('i', 15, struct ifreq): ret = sys_ioctl(fd, SIOCGIFDSTADDR, arg); goto out; case _IOW('i', 16, struct ifreq): ret = sys_ioctl(fd, SIOCSIFFLAGS, arg); goto out; case _IOWR('i', 17, struct ifreq): ret = sys_ioctl(fd, SIOCGIFFLAGS, arg); goto out; case _IOW('i', 18, struct ifreq): ret = sys_ioctl(fd, SIOCSIFMEM, arg); goto out; case _IOWR('i', 19, struct ifreq): ret = sys_ioctl(fd, SIOCGIFMEM, arg); goto out; case _IOWR('i', 20, struct ifconf): ret = sys_ioctl(fd, SIOCGIFCONF, arg); goto out; case _IOW('i', 21, struct ifreq): /* SIOCSIFMTU */ ret = sys_ioctl(fd, SIOCSIFMTU, arg); goto out; case _IOWR('i', 22, struct ifreq): /* SIOCGIFMTU */ ret = sys_ioctl(fd, SIOCGIFMTU, arg); goto out; case _IOWR('i', 23, struct ifreq): ret = sys_ioctl(fd, SIOCGIFBRDADDR, arg); goto out; case _IOW('i', 24, struct ifreq): ret = sys_ioctl(fd, SIOCSIFBRDADDR, arg); goto out; case _IOWR('i', 25, struct ifreq): ret = sys_ioctl(fd, SIOCGIFNETMASK, arg); goto out; case _IOW('i', 26, struct ifreq): ret = sys_ioctl(fd, SIOCSIFNETMASK, arg); goto out; case _IOWR('i', 27, struct ifreq): ret = sys_ioctl(fd, SIOCGIFMETRIC, arg); goto out; case _IOW('i', 28, struct ifreq): ret = sys_ioctl(fd, SIOCSIFMETRIC, arg); goto out; case _IOW('i', 30, struct arpreq): ret = sys_ioctl(fd, SIOCSARP, arg); goto out; case _IOWR('i', 31, struct arpreq): ret = sys_ioctl(fd, SIOCGARP, arg); goto out; case _IOW('i', 32, struct arpreq): ret = sys_ioctl(fd, SIOCDARP, arg); goto out; case _IOW('i', 40, struct ifreq): /* SIOCUPPER */ case _IOW('i', 41, struct ifreq): /* SIOCLOWER */ case _IOW('i', 44, struct ifreq): /* SIOCSETSYNC */ case _IOW('i', 45, struct ifreq): /* SIOCGETSYNC */ case _IOW('i', 46, struct ifreq): /* SIOCSSDSTATS */ case _IOW('i', 47, struct ifreq): /* SIOCSSESTATS */ case _IOW('i', 48, struct ifreq): /* SIOCSPROMISC */ ret = -EOPNOTSUPP; goto out; case _IOW('i', 49, struct ifreq): ret = sys_ioctl(fd, SIOCADDMULTI, arg); goto out; case _IOW('i', 50, struct ifreq): ret = sys_ioctl(fd, SIOCDELMULTI, arg); goto out; /* FDDI interface ioctls, unsupported. */ case _IOW('i', 51, struct ifreq): /* SIOCFDRESET */ case _IOW('i', 52, struct ifreq): /* SIOCFDSLEEP */ case _IOW('i', 53, struct ifreq): /* SIOCSTRTFMWAR */ case _IOW('i', 54, struct ifreq): /* SIOCLDNSTRTFW */ case _IOW('i', 55, struct ifreq): /* SIOCGETFDSTAT */ case _IOW('i', 56, struct ifreq): /* SIOCFDNMIINT */ case _IOW('i', 57, struct ifreq): /* SIOCFDEXUSER */ case _IOW('i', 58, struct ifreq): /* SIOCFDGNETMAP */ case _IOW('i', 59, struct ifreq): /* SIOCFDGIOCTL */ printk("FDDI ioctl, returning EOPNOTSUPP\n"); ret = -EOPNOTSUPP; goto out; case _IOW('t', 125, int): /* More stupid tty sunos ioctls, just * say it worked. */ ret = 0; goto out; /* Non posix grp */ case _IOW('t', 118, int): { int oldval, newval, __user *ptr; cmd = TIOCSPGRP; ptr = (int __user *) arg; ret = -EFAULT; if (get_user(oldval, ptr)) goto out; ret = sys_ioctl(fd, cmd, arg); __get_user(newval, ptr); if (newval == -1) { __put_user(oldval, ptr); ret = -EIO; } if (ret == -ENOTTY) ret = -EIO; goto out; } case _IOR('t', 119, int): { int oldval, newval, __user *ptr; cmd = TIOCGPGRP; ptr = (int __user *) arg; ret = -EFAULT; if (get_user(oldval, ptr)) goto out; ret = sys_ioctl(fd, cmd, arg); __get_user(newval, ptr); if (newval == -1) { __put_user(oldval, ptr); ret = -EIO; } if (ret == -ENOTTY) ret = -EIO; goto out; } } #if 0 if ((cmd & 0xff00) == ('k' << 8)) { printk ("[[KBIO: %8.8x\n", (unsigned int) cmd); } #endif ret = sys_ioctl(fd, cmd, arg); /* so stupid... */ ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); out: return ret; }
int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) { struct dnotify_struct *dn; struct dnotify_struct *odn; struct dnotify_struct **prev; struct inode *inode; fl_owner_t id = current->files; struct file *f; int error = 0; if ((arg & ~DN_MULTISHOT) == 0) { dnotify_flush(filp, id); return 0; } if (!dir_notify_enable) return -EINVAL; inode = filp->f_dentry->d_inode; if (!S_ISDIR(inode->i_mode)) return -ENOTDIR; dn = kmem_cache_alloc(dn_cache, SLAB_KERNEL); if (dn == NULL) return -ENOMEM; spin_lock(&inode->i_lock); prev = &inode->i_dnotify; while ((odn = *prev) != NULL) { if ((odn->dn_owner == id) && (odn->dn_filp == filp)) { odn->dn_fd = fd; odn->dn_mask |= arg; inode->i_dnotify_mask |= arg & ~DN_MULTISHOT; goto out_free; } prev = &odn->dn_next; } rcu_read_lock(); f = fcheck(fd); rcu_read_unlock(); /* we'd lost the race with close(), sod off silently */ /* note that inode->i_lock prevents reordering problems * between accesses to descriptor table and ->i_dnotify */ if (f != filp) goto out_free; error = f_setown(filp, current->pid, 0); if (error) goto out_free; dn->dn_mask = arg; dn->dn_fd = fd; dn->dn_filp = filp; dn->dn_owner = id; inode->i_dnotify_mask |= arg & ~DN_MULTISHOT; dn->dn_next = inode->i_dnotify; inode->i_dnotify = dn; spin_unlock(&inode->i_lock); if (filp->f_op && filp->f_op->dir_notify) return filp->f_op->dir_notify(filp, arg); return 0; out_free: spin_unlock(&inode->i_lock); kmem_cache_free(dn_cache, dn); return error; }
int timod_putmsg(unsigned int fd, char *ctl_buf, int ctl_len, char *data_buf, int data_len, int flags) { int ret, error, terror; char *buf; struct file *filp; struct inode *ino; struct sol_socket_struct *sock; mm_segment_t old_fs = get_fs(); long args[6]; int (*sys_socketcall)(int, unsigned long *) = (int (*)(int, unsigned long *))SYS(socketcall); int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int) = (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int))SYS(sendto); read_lock(¤t->files->file_lock); filp = fcheck(fd); read_unlock(¤t->files->file_lock); if (!filp) return -EBADF; ino = filp->f_dentry->d_inode; sock = (struct sol_socket_struct *)filp->private_data; SOLD("entry"); if (get_user(ret, (int *)A(ctl_buf))) return -EFAULT; switch (ret) { case T_BIND_REQ: { struct T_bind_req req; SOLDD(("bind %016lx(%016lx)\n", sock, filp)); SOLD("T_BIND_REQ"); if (sock->state != TS_UNBND) { timod_error(fd, T_BIND_REQ, TOUTSTATE, 0); return 0; } SOLD("state ok"); if (copy_from_user(&req, ctl_buf, sizeof(req))) { timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); return 0; } SOLD("got ctl req"); if (req.ADDR_offset && req.ADDR_length) { if (req.ADDR_length > BUF_SIZE) { timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); return 0; } SOLD("req size ok"); buf = getpage(); if (copy_from_user(buf, ctl_buf + req.ADDR_offset, req.ADDR_length)) { timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); putpage(buf); return 0; } SOLD("got ctl data"); args[0] = fd; args[1] = (long)buf; args[2] = req.ADDR_length; SOLD("calling BIND"); set_fs(KERNEL_DS); error = sys_socketcall(SYS_BIND, args); set_fs(old_fs); putpage(buf); SOLD("BIND returned"); } else error = 0; if (!error) { struct T_primsg *it; if (req.CONIND_number) { args[0] = fd; args[1] = req.CONIND_number; SOLD("calling LISTEN"); set_fs(KERNEL_DS); error = sys_socketcall(SYS_LISTEN, args); set_fs(old_fs); SOLD("LISTEN done"); } it = timod_mkctl(sizeof(struct T_bind_ack)+sizeof(struct sockaddr)); if (it) { struct T_bind_ack *ack; ack = (struct T_bind_ack *)&it->type; ack->PRIM_type = T_BIND_ACK; ack->ADDR_offset = sizeof(*ack); ack->ADDR_length = sizeof(struct sockaddr); ack->CONIND_number = req.CONIND_number; args[0] = fd; args[1] = (long)(ack+sizeof(*ack)); args[2] = (long)&ack->ADDR_length; set_fs(KERNEL_DS); sys_socketcall(SYS_GETSOCKNAME,args); set_fs(old_fs); sock->state = TS_IDLE; timod_ok(fd, T_BIND_REQ); timod_queue_end(fd, it); SOLD("BIND done"); return 0; } } SOLD("some error"); switch (error) { case -EINVAL: terror = TOUTSTATE; error = 0; break; case -EACCES: terror = TACCES; error = 0; break; case -EADDRNOTAVAIL: case -EADDRINUSE: terror = TNOADDR; error = 0; break; default: terror = TSYSERR; break; } timod_error(fd, T_BIND_REQ, terror, -error); SOLD("BIND done"); return 0; } case T_CONN_REQ: { struct T_conn_req req; unsigned short oldflags; struct T_primsg *it; SOLD("T_CONN_REQ"); if (sock->state != TS_UNBND && sock->state != TS_IDLE) { timod_error(fd, T_CONN_REQ, TOUTSTATE, 0); return 0; } SOLD("state ok"); if (copy_from_user(&req, ctl_buf, sizeof(req))) { timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); return 0; } SOLD("got ctl req"); if (ctl_len > BUF_SIZE) { timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); return 0; } SOLD("req size ok"); buf = getpage(); if (copy_from_user(buf, ctl_buf, ctl_len)) { timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); putpage(buf); return 0; } #ifdef DEBUG_SOLARIS { char * ptr = buf; int len = ctl_len; printk("returned data (%d bytes): ",len); while( len-- ) { if (!(len & 7)) printk(" "); printk("%02x",(unsigned char)*ptr++); } printk("\n"); } #endif SOLD("got ctl data"); args[0] = fd; args[1] = (long)buf+req.DEST_offset; args[2] = req.DEST_length; oldflags = filp->f_flags; filp->f_flags &= ~O_NONBLOCK; SOLD("calling CONNECT"); set_fs(KERNEL_DS); error = sys_socketcall(SYS_CONNECT, args); set_fs(old_fs); filp->f_flags = oldflags; SOLD("CONNECT done"); if (!error) { struct T_conn_con *con; SOLD("no error"); it = timod_mkctl(ctl_len); if (!it) { putpage(buf); return -ENOMEM; } con = (struct T_conn_con *)&it->type; #ifdef DEBUG_SOLARIS { char * ptr = buf; int len = ctl_len; printk("returned data (%d bytes): ",len); while( len-- ) { if (!(len & 7)) printk(" "); printk("%02x",(unsigned char)*ptr++); } printk("\n"); } #endif memcpy(con, buf, ctl_len); SOLD("copied ctl_buf"); con->PRIM_type = T_CONN_CON; sock->state = TS_DATA_XFER; } else { struct T_discon_ind *dis; SOLD("some error"); it = timod_mkctl(sizeof(*dis)); if (!it) { putpage(buf); return -ENOMEM; } SOLD("got primsg"); dis = (struct T_discon_ind *)&it->type; dis->PRIM_type = T_DISCON_IND; dis->DISCON_reason = -error; /* FIXME: convert this as in iABI_errors() */ dis->SEQ_number = 0; } putpage(buf); timod_ok(fd, T_CONN_REQ); it->pri = 0; timod_queue_end(fd, it); SOLD("CONNECT done"); return 0; } case T_OPTMGMT_REQ: { struct T_optmgmt_req req; SOLD("OPTMGMT_REQ"); if (copy_from_user(&req, ctl_buf, sizeof(req))) return -EFAULT; SOLD("got req"); return timod_optmgmt(fd, req.MGMT_flags, req.OPT_offset > 0 ? ctl_buf + req.OPT_offset : NULL, req.OPT_length, 1); } case T_UNITDATA_REQ: { struct T_unitdata_req req; int err; SOLD("T_UNITDATA_REQ"); if (sock->state != TS_IDLE && sock->state != TS_DATA_XFER) { timod_error(fd, T_CONN_REQ, TOUTSTATE, 0); return 0; } SOLD("state ok"); if (copy_from_user(&req, ctl_buf, sizeof(req))) { timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); return 0; } SOLD("got ctl req"); #ifdef DEBUG_SOLARIS { char * ptr = ctl_buf+req.DEST_offset; int len = req.DEST_length; printk("socket address (%d bytes): ",len); while( len-- ) { char c; if (get_user(c,ptr)) printk("??"); else printk("%02x",(unsigned char)c); ptr++; } printk("\n"); } #endif err = sys_sendto(fd, data_buf, data_len, 0, req.DEST_length > 0 ? (struct sockaddr*)(ctl_buf+req.DEST_offset) : NULL, req.DEST_length); if (err == data_len) return 0; if(err >= 0) { printk("timod: sendto failed to send all the data\n"); return 0; } timod_error(fd, T_CONN_REQ, TSYSERR, -err); return 0; } default: printk(KERN_INFO "timod_putmsg: unsupported command %u.\n", ret); break; } return -EINVAL; }
asmlinkage int sunos_ioctl (int fd, u32 cmd, u32 arg) { int ret = -EBADF; if(fd >= SUNOS_NR_OPEN) goto out; if(!fcheck(fd)) goto out; if(cmd == TIOCSETD) { mm_segment_t old_fs = get_fs(); int __user *p; int ntty = N_TTY; int tmp; p = (int __user *) (unsigned long) arg; ret = -EFAULT; if(get_user(tmp, p)) goto out; if(tmp == 2) { set_fs(KERNEL_DS); ret = sys_ioctl(fd, cmd, (unsigned long) &ntty); set_fs(old_fs); ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); goto out; } } if(cmd == TIOCNOTTY) { ret = sys_setsid(); goto out; } switch(cmd) { case _IOW('r', 10, struct rtentry32): ret = compat_sys_ioctl(fd, SIOCADDRT, arg); goto out; case _IOW('r', 11, struct rtentry32): ret = compat_sys_ioctl(fd, SIOCDELRT, arg); goto out; case _IOW('i', 12, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCSIFADDR, arg); goto out; case _IOWR('i', 13, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCGIFADDR, arg); goto out; case _IOW('i', 14, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg); goto out; case _IOWR('i', 15, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg); goto out; case _IOW('i', 16, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCSIFFLAGS, arg); goto out; case _IOWR('i', 17, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCGIFFLAGS, arg); goto out; case _IOW('i', 18, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCSIFMEM, arg); goto out; case _IOWR('i', 19, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCGIFMEM, arg); goto out; case _IOWR('i', 20, struct ifconf32): ret = compat_sys_ioctl(fd, SIOCGIFCONF, arg); goto out; case _IOW('i', 21, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCSIFMTU, arg); goto out; case _IOWR('i', 22, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCGIFMTU, arg); goto out; case _IOWR('i', 23, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg); goto out; case _IOW('i', 24, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg); goto out; case _IOWR('i', 25, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCGIFNETMASK, arg); goto out; case _IOW('i', 26, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCSIFNETMASK, arg); goto out; case _IOWR('i', 27, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCGIFMETRIC, arg); goto out; case _IOW('i', 28, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCSIFMETRIC, arg); goto out; case _IOW('i', 30, struct arpreq): ret = compat_sys_ioctl(fd, SIOCSARP, arg); goto out; case _IOWR('i', 31, struct arpreq): ret = compat_sys_ioctl(fd, SIOCGARP, arg); goto out; case _IOW('i', 32, struct arpreq): ret = compat_sys_ioctl(fd, SIOCDARP, arg); goto out; case _IOW('i', 40, struct ifreq32): /* SIOCUPPER */ case _IOW('i', 41, struct ifreq32): /* SIOCLOWER */ case _IOW('i', 44, struct ifreq32): /* SIOCSETSYNC */ case _IOW('i', 45, struct ifreq32): /* SIOCGETSYNC */ case _IOW('i', 46, struct ifreq32): /* SIOCSSDSTATS */ case _IOW('i', 47, struct ifreq32): /* SIOCSSESTATS */ case _IOW('i', 48, struct ifreq32): /* SIOCSPROMISC */ ret = -EOPNOTSUPP; goto out; case _IOW('i', 49, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCADDMULTI, arg); goto out; case _IOW('i', 50, struct ifreq32): ret = compat_sys_ioctl(fd, SIOCDELMULTI, arg); goto out; /* FDDI interface ioctls, unsupported. */ case _IOW('i', 51, struct ifreq32): /* SIOCFDRESET */ case _IOW('i', 52, struct ifreq32): /* SIOCFDSLEEP */ case _IOW('i', 53, struct ifreq32): /* SIOCSTRTFMWAR */ case _IOW('i', 54, struct ifreq32): /* SIOCLDNSTRTFW */ case _IOW('i', 55, struct ifreq32): /* SIOCGETFDSTAT */ case _IOW('i', 56, struct ifreq32): /* SIOCFDNMIINT */ case _IOW('i', 57, struct ifreq32): /* SIOCFDEXUSER */ case _IOW('i', 58, struct ifreq32): /* SIOCFDGNETMAP */ case _IOW('i', 59, struct ifreq32): /* SIOCFDGIOCTL */ printk("FDDI ioctl, returning EOPNOTSUPP\n"); ret = -EOPNOTSUPP; goto out; case _IOW('t', 125, int): /* More stupid tty sunos ioctls, just * say it worked. */ ret = 0; goto out; /* Non posix grp */ case _IOW('t', 118, int): { int oldval, newval, __user *ptr; cmd = TIOCSPGRP; ptr = (int __user *) (unsigned long) arg; ret = -EFAULT; if(get_user(oldval, ptr)) goto out; ret = compat_sys_ioctl(fd, cmd, arg); __get_user(newval, ptr); if(newval == -1) { __put_user(oldval, ptr); ret = -EIO; } if(ret == -ENOTTY) ret = -EIO; goto out; } case _IOR('t', 119, int): { int oldval, newval, __user *ptr; cmd = TIOCGPGRP; ptr = (int __user *) (unsigned long) arg; ret = -EFAULT; if(get_user(oldval, ptr)) goto out; ret = compat_sys_ioctl(fd, cmd, arg); __get_user(newval, ptr); if(newval == -1) { __put_user(oldval, ptr); ret = -EIO; } if(ret == -ENOTTY) ret = -EIO; goto out; } }; ret = compat_sys_ioctl(fd, cmd, arg); /* so stupid... */ ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); out: return ret; }
int main(int argc, char **argv) { int i, retval = SUCCESS; #if defined (HAVE_WORKING_FORK) pid_t cpid; FILE *fscore; #endif #if defined (HAVE_ASSERT_H) && defined (SHORT_PASSWORDS) assert(MAX_PLAIN_SIZE < 16); #endif /* set the default values for `usr_opt' */ memset(&usr_opt, 0, sizeof(usr_opt)); usr_opt.verbose = 1; #if defined (DEV_RANDOM_SUPPORT) usr_opt.cryptopt.get_entropy = get_dev_entropy; #elif defined (EGD_SUPPORT) usr_opt.cryptopt.get_entropy = get_egd_entropy; #else usr_opt.cryptopt.get_entropy = get_sys_entropy; #endif opt_parse(argc, argv, &usr_opt); #if defined (HAVE_UMASK) /* set umask for security reasons */ umask(0077); #endif switch (usr_opt.action) { case crypt_ios: case crypt_pix: if (argc != optind + 1) tty_error(ERR_USAGE, "no string to crypt"); usr_opt.cryptopt.plain = (u_char *) str_alloc_copy(argv[optind]); retval = (usr_opt.action == crypt_ios) ? crypt_ios_fe(usr_opt.cryptopt.plain, usr_opt.cryptopt.salt) : crypt_pix_fe(usr_opt.cryptopt.plain); break; case decrypt_bf: case decrypt_wl: if (argc != optind + 1) tty_error(ERR_USAGE, "no password to decrypt"); usr_opt.decryptopt.cipher = (u_char *) str_alloc_copy(argv[optind]); /* no break here! */ case resume: /* if `decrypt_bf', `decrypt_wl', `resume_bf', `resume_wl', * create the restore file in case of an abort event */ save_session_if_signal_abort = true; if (usr_opt.action == resume) { if (argc != optind) tty_error(ERR_USAGE, "bad argument found `%s'", argv[optind]); session_load(usr_opt.decryptopt.restore_file); /* `usr_opt.decryptopt.regexpr' can be NULL, * so we must check `usr_opt.decryptopt.wordlist' */ usr_opt.action = usr_opt.decryptopt.wordlist ? resume_wl: resume_bf; } #if defined (HAVE_WORKING_FORK) if (usr_opt.daemonize) { cpid = fork(); if (cpid == (pid_t) 0) { /* child process */ /* checks the SCORE_FILE format */ fcheck(SCORE_FILE, HEAD_SCORE_TEXT); /* add the line `HEAD_SCORE_TEXT"\n"' at the begin, * if the file do not exists */ if (!(fscore = fopen(SCORE_FILE, "r"))) { fscore = fopen(SCORE_FILE, "w"); fprintf(fscore, HEAD_SCORE_TEXT"\n"); } fclose(fscore); tty_message ("%s -- running in daemon mode" #if defined (HAVE_GETPID) " [pid: %d]" #endif "...\n** WARNING: " "sensible data could be written in the file `%s'!\n", *argv, #if defined (HAVE_GETPID) (int) getpid(), #endif SCORE_FILE); /* point stdin/stdout/stderr to /dev/null */ for (i = 0; i < 3; i++) close(i); i = open(NULL_DEV, O_RDWR); if (i >= 0) { dup2(i, 0); dup2(i, 1); dup2(i, 2); if (i > 2) close(i); } retval = cisco_decrypt(); return retval; } else if (cpid < (pid_t) 0) tty_error(ERR_FORKING, "cannot run in daemon mode : %s", strerror(errno)); else return SUCCESS; /* parent process */ } else #endif retval = cisco_decrypt(); break; default: /* not enought paramethers entered */ tty_error(ERR_USAGE, "nothing to do (?)"); } mem_free_all(); return retval; }