X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=slip.c;h=abfd922e0aa97ad39db6b0300083a0ee149dc93c;hb=7a9235c5504104c2446c294fb0a4b4dcd1e82cb3;hp=3f7935a008ad16e483a3aaee72af8795b033147a;hpb=d6ca258a8088d6c1779df1b7bf08eb8548275366;p=secnet.git diff --git a/slip.c b/slip.c index 3f7935a..abfd922 100644 --- a/slip.c +++ b/slip.c @@ -31,6 +31,27 @@ struct slip { /* Generic SLIP mangling code */ +static void slip_write(int fd, const uint8_t *p, size_t l) +{ + while (l) { + ssize_t written=write(fd,p,l); + if (written<0) { + if (errno==EINTR) { + continue; + } else if (iswouldblock(errno)) { + lg_perror(0,"slip",0,M_ERR,errno,"write() (packet(s) lost)"); + return; + } else { + fatal_perror("slip_stuff: write()"); + } + } + assert(written>0); + assert((size_t)written<=l); + p+=written; + l-=written; + } +} + static void slip_stuff(struct slip *st, struct buffer_if *buf, int fd) { uint8_t txbuf[DEFAULT_BUFSIZE]; @@ -56,16 +77,12 @@ static void slip_stuff(struct slip *st, struct buffer_if *buf, int fd) break; } if ((j+2)>DEFAULT_BUFSIZE) { - if (write(fd,txbuf,j)<0) { - fatal_perror("slip_stuff: write()"); - } + slip_write(fd,txbuf,j); j=0; } } txbuf[j++]=SLIP_END; - if (write(fd,txbuf,j)<0) { - fatal_perror("slip_stuff: write()"); - } + slip_write(fd,txbuf,j); BUF_FREE(buf); } @@ -195,7 +212,7 @@ static void userv_afterpoll(void *sst, struct pollfd *fds, int nfds) if (fds[1].revents&POLLIN) { l=read(st->rxfd,rxbuf,DEFAULT_BUFSIZE); if (l<0) { - if (errno!=EINTR) + if (errno!=EINTR && !iswouldblock(errno)) fatal_perror("%s: userv_afterpoll: read(rxfd)", st->slip.nl.name); } else if (l==0) { @@ -256,8 +273,6 @@ static void userv_entry(void *sst) dup2(st->out,1); setsid(); - /* XXX We really should strdup() all of argv[] but because we'll just - exit anyway if execvp() fails it doesn't seem worth bothering. */ execvp(st->path,(char *const*)st->argv); perror("userv-entry: execvp()"); exit(1); @@ -320,6 +335,8 @@ static void userv_invoke_userv(struct userv *st) pipe_cloexec(c_stdout); st->txfd=c_stdin[1]; st->rxfd=c_stdout[0]; + setnonblock(st->rxfd); + setnonblock(st->txfd); er->in=c_stdin[0]; er->out=c_stdout[1];