/* * pipe(2) system call. * Create a pipe by connecting two streams together. Associate * each end of the pipe with a vnode, a file descriptor and * one of the streams. */ longlong_t pipe() { vnode_t *vp1, *vp2; struct file *fp1, *fp2; int error = 0; int fd1, fd2; rval_t r; /* * Allocate and initialize two vnodes. */ makepipe(&vp1, &vp2); /* * Allocate and initialize two file table entries and two * file pointers. Each file pointer is open for read and * write. */ if (error = falloc(vp1, FWRITE|FREAD, &fp1, &fd1)) { VN_RELE(vp1); VN_RELE(vp2); return ((longlong_t)set_errno(error)); } if (error = falloc(vp2, FWRITE|FREAD, &fp2, &fd2)) goto out2; /* * Create two stream heads and attach to each vnode. */ if (error = fifo_stropen(&vp1, FWRITE|FREAD, fp1->f_cred, 0, 0)) goto out; if (error = fifo_stropen(&vp2, FWRITE|FREAD, fp2->f_cred, 0, 0)) { (void) VOP_CLOSE(vp1, FWRITE|FREAD, 1, (offset_t)0, fp1->f_cred); goto out; } strmate(vp1, vp2); VTOF(vp1)->fn_ino = VTOF(vp2)->fn_ino = fifogetid(); /* * Now fill in the entries that falloc reserved */ mutex_exit(&fp1->f_tlock); mutex_exit(&fp2->f_tlock); setf(fd1, fp1); setf(fd2, fp2); /* * Return the file descriptors to the user. They now * point to two different vnodes which have different * stream heads. */ r.r_val1 = fd1; r.r_val2 = fd2; return (r.r_vals); out: unfalloc(fp2); setf(fd2, NULL); out2: unfalloc(fp1); setf(fd1, NULL); VN_RELE(vp1); VN_RELE(vp2); return ((longlong_t)set_errno(error)); }
int main(int argc, char *argv[]) { speed_t baud = B57600; // default baudrate stdinfd = fileno(stdin); stdoutfd = fileno(stdout); serialfd = -1; erlpipefd = -1; struct termios oldserial, oldstdin; //saveterminal(stdinfd,oldstdin); // check(tcgetattr(stdinfd,&oldstdin) == 0, "Failed to backup stdin"); // if erlang mode is set then redirect stderr to erlerr.txt //read command line arguments check(parsecmdargs(argc, argv) != -1,"Command Line Argument Failure"); if(erlang == TRUE) { freopen("erlerr.txt", "w", stderr); } debug("pid is %d", getpid()); //setup pipe if require doesn't work yet if(pipedebug == 1) // { check(makepipe(ERLPIPE) == 0, "Pipe creation or opening failed for: "); debug("Pipe created:"); debug("Process %d opening erlpipe", getpid()); erlpipefd = open(ERLPIPE, O_WRONLY|O_NONBLOCK); check(erlpipefd > 0, "Erlpipe failed to open pipe: %s\nSetup reader in second terminal\n tail -f erlpipe",ERLPIPE); debug("Erlpipe opened"); /* check(makepipe(ERLPIPEIN) == 0, "Erlpipein creation or opening failed for: "); debug("Pipe created:"); debug("Process %d opening erlpipein", getpid()); erlpipeinfd = open(ERLPIPEIN); check(erlpipeinfd > 0, "Erlpipein: Failed to open pipe: %s\nSetup reader in second terminal\n tail -f erlpipe",ERLPIPEIN); debug("Erlpipe opened"); */ } // save terminal settings //get baud rate from command line arguments baud = getbaud(baudrate); check(baud != B0, "Illegal baud rate"); if(serial == TRUE){ //open serial port serialfd = open(serialport, O_RDWR); check(serialfd > 0,"Can't open serial port\n Try dmesg | grep tty from shell \n"); debug("Opened serial port: %s",serialport); //set serial port to raw mode check(makeraw(serialfd)==0,"Failed to set serial port raw mode"); //set baudrate serial check(setspeed(serialfd,baud)==0,"Failed to set baud rate"); debug("Baud rate set to: %d", baudrate); } //set stdin to raw mode // check(makeraw(stdinfd)==0, "Failed to set stdin to raw mode"); // debug("Not Entered raw mode:"); //send acknowledge to erlang??? /* Watch stdinfd and serialfd if input is available process then output Serial -> Erlang Erlang -> Serial */ /* int numbytes; while(1){ numbytes = read_erlang(erlmesg.mesg); check(numbytes > 0, "Read error from erlang"); debug("Read %d bytes from Erlang", numbytes); write_serial(numbytes, erlmesg.mesg); debug("Wrote %d bytes to serial:", numbytes); } //main loop */ { fd_set readfds; int maxfd; int is, numbytes; FD_ZERO(&readfds); maxfd = (stdinfd > serialfd) ? stdinfd : serialfd; maxfd = (maxfd > erlpipeinfd) ? maxfd : erlpipeinfd; while(1){ if(serial){ FD_SET(serialfd, &readfds); } if(pipedebug){ FD_SET(erlpipeinfd, &readfds); } FD_SET(stdinfd, &readfds); is = select(maxfd+1, &readfds, NULLFDS, NULLFDS, NULLTV); check(is>0,"Select error -"); if (serial && FD_ISSET(serialfd,&readfds)){ // Serial porth ready to read FD_CLR(serialfd,&readfds); numbytes = read(serialfd, erlmesg.mesg, MAXMESG); check(numbytes > 0, "Read error from serial port"); write_erlang(numbytes, erlmesg.mesg); } if (FD_ISSET(stdinfd,&readfds)){ //Stdin-Erlang ready to read FD_CLR(stdinfd, &readfds); numbytes = read_erlang(erlmesg.mesg); check(numbytes > 0, "Read error from erlang"); debug("Read %d bytes from Erlang", numbytes); write_serial(numbytes, erlmesg.mesg); debug("Wrote %d bytes to serial:", numbytes); } // input pipe /* if (pipedebug && (FD_ISSET(erlpipeinfd,&readfds)){ FD_CLR(erlpipeinfd, &readfds); } */ } } //hanldle input from erlang //handle input from serial port // restoreterminal(stdinfd,&oldstdin); // tcsetattr(stdinfd,TCSANOW,&oldstdin); return 0; error: //restoreterminal(stdinfd,&oldstdin); // tcsetattr(stdinfd,TCSANOW,&oldstdin);; debug("Restored terminal"); exit(1); }
/* * Note: This routine is single threaded * Protected by FIFOOPEN flag (i.e. flk_lock is not held) * Upon successful completion, the original fifo is unlocked * and FIFOOPEN is cleared for the original vpp. * The new fifo returned has FIFOOPEN set. */ static int fifo_connld(struct vnode **vpp, int flag, cred_t *crp) { struct vnode *vp1; struct vnode *vp2; struct fifonode *oldfnp; struct fifonode *fn_dest; int error; struct file *filep; struct fifolock *fn_lock; cred_t *c; /* * Get two vnodes that will represent the pipe ends for the new pipe. */ makepipe(&vp1, &vp2); /* * Allocate a file descriptor and file pointer for one of the pipe * ends. The file descriptor will be used to send that pipe end to * the process on the other end of this stream. Note that we get * the file structure only, there is no file list entry allocated. */ if (error = falloc(vp1, FWRITE|FREAD, &filep, NULL)) { VN_RELE(vp1); VN_RELE(vp2); return (error); } mutex_exit(&filep->f_tlock); oldfnp = VTOF(*vpp); fn_lock = oldfnp->fn_lock; fn_dest = oldfnp->fn_dest; /* * Create two new stream heads and attach them to the two vnodes for * the new pipe. */ if ((error = fifo_stropen(&vp1, FREAD|FWRITE, filep->f_cred, 0, 0)) != 0 || (error = fifo_stropen(&vp2, flag, filep->f_cred, 0, 0)) != 0) { #if DEBUG cmn_err(CE_NOTE, "fifo stropen failed error 0x%x", error); #endif /* * this will call fifo_close and VN_RELE on vp1 */ (void) closef(filep); VN_RELE(vp2); return (error); } /* * twist the ends of the pipe together */ strmate(vp1, vp2); /* * Set our end to busy in open * Note: Don't need lock around this because we're the only * one who knows about it */ VTOF(vp2)->fn_flag |= FIFOOPEN; mutex_enter(&fn_lock->flk_lock); fn_dest->fn_flag |= FIFOSEND; /* * check to make sure neither end of pipe has gone away */ if (!(fn_dest->fn_flag & FIFOISOPEN)) { error = ENXIO; fn_dest->fn_flag &= ~FIFOSEND; mutex_exit(&fn_lock->flk_lock); /* * this will call fifo_close and VN_RELE on vp1 */ goto out; } mutex_exit(&fn_lock->flk_lock); /* * Tag the sender's credential on the pipe descriptor. */ crhold(VTOF(vp1)->fn_pcredp = crp); VTOF(vp1)->fn_cpid = curproc->p_pid; /* * send the file descriptor to other end of pipe */ if (error = do_sendfp((*vpp)->v_stream, filep, crp)) { mutex_enter(&fn_lock->flk_lock); fn_dest->fn_flag &= ~FIFOSEND; mutex_exit(&fn_lock->flk_lock); /* * this will call fifo_close and VN_RELE on vp1 */ goto out; } mutex_enter(&fn_lock->flk_lock); /* * Wait for other end to receive file descriptor * FIFOCLOSE indicates that one or both sides of the pipe * have gone away. */ while ((fn_dest->fn_flag & (FIFOCLOSE | FIFOSEND)) == FIFOSEND) { if (!cv_wait_sig(&oldfnp->fn_wait_cv, &fn_lock->flk_lock)) { error = EINTR; fn_dest->fn_flag &= ~FIFOSEND; mutex_exit(&fn_lock->flk_lock); goto out; } } /* * If either end of pipe has gone away and the other end did not * receive pipe, reject the connld open */ if ((fn_dest->fn_flag & FIFOSEND)) { error = ENXIO; fn_dest->fn_flag &= ~FIFOSEND; mutex_exit(&fn_lock->flk_lock); goto out; } oldfnp->fn_flag &= ~FIFOOPEN; cv_broadcast(&oldfnp->fn_wait_cv); mutex_exit(&fn_lock->flk_lock); VN_RELE(*vpp); *vpp = vp2; (void) closef(filep); return (0); out: c = filep->f_cred; crhold(c); (void) closef(filep); VTOF(vp2)->fn_flag &= ~FIFOOPEN; (void) fifo_close(vp2, flag, 1, (offset_t)0, c, NULL); crfree(c); VN_RELE(vp2); return (error); }