X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=blobdiff_plain;f=slip.c;h=e555f471218b710b12ecbe35a075ec0660533cd1;hp=59978c98d87ea5a5704595d675532d4b87320d43;hb=22c77971bb13c37344fc73fe9b8d72ed96181df2;hpb=4ac7fd3ff73c98100d8a8546668d0212e4af3ffa diff --git a/slip.c b/slip.c index 59978c9..e555f47 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) { @@ -230,7 +247,9 @@ static void userv_userv_callback(void *sst, pid_t pid, int status) "(expected %d)\n",pid,st->pid); return; } - if (!st->expecting_userv_exit) { + if (!(st->expecting_userv_exit && + (!status || + (WIFSIGNALED(status) && WTERMSIG(status)==SIGTERM)))) { lg_exitstatus(0,st->slip.nl.name,0, st->expecting_userv_exit ? M_WARNING : M_FATAL, status,"userv"); @@ -254,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); @@ -364,6 +381,8 @@ static void userv_invoke_userv(struct userv *st) st->slip.nl.name,confirm); } } + setnonblock(st->txfd); + setnonblock(st->rxfd); } static void userv_kill_userv(struct userv *st)