static int process(Sfio_t* mp, Sfio_t* lp, int delay, int timeout) { int i; int n; int t; ssize_t r; char* s; Sfio_t* ip; Sfio_t* sps[2]; struct stat dst; struct stat fst; ip = sfstdin; if (!fstat(sffileno(ip), &dst) && !stat("/dev/null", &fst) && dst.st_dev == fst.st_dev && dst.st_ino == fst.st_ino) ip = 0; do { i = 0; t = timeout; if (mp) sps[i++] = mp; if (ip) { sps[i++] = ip; t = -1; } if (!i) break; if ((n = sfpoll(sps, i, t)) <= 0) { if (n < 0) error(ERROR_SYSTEM|2, "poll failed"); break; } for (i = t = 0; i < n; i++) { if (!(sfvalue(sps[i]) & SF_READ)) /*skip*/; else if (sps[i] == mp) { t++; if (!(s = (char*)sfreserve(mp, SF_UNBOUND, -1))) { sfclose(mp); mp = 0; } else if ((r = sfvalue(mp)) > 0 && (sfwrite(sfstdout, s, r) != r || sfsync(sfstdout))) { error(ERROR_SYSTEM|2, "output write failed"); goto done; } } else { t++; if (!(s = sfgetr(ip, '\n', 1))) ip = 0; else if (sfputr(mp, s, '\r') < 0 || sfsync(mp)) { error(ERROR_SYSTEM|2, "write failed"); goto done; } } } } while (t); done: if (mp) sfclose(mp); return error_info.errors != 0; }
tmain() { Sfio_t *f, *g, *str, *fr, *fw, *sf[2]; int c; char *s; int fd[2]; if(argc > 1) { while((s = sfgetr(sfstdin, '\n', 1)) ) { sfputr(sfstdout, s, '\n'); sfsync(sfstdout); } texit(0); } if(!(str = sfopen(NIL(Sfio_t*),"abc","s")) ) terror("Opening string stream"); if(pipe(fd) < 0) terror("pipe failed"); if(!(fr = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND, fd[0],SF_READ)) ) terror("Opening read pipe stream"); if(!(fw = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND, fd[1],SF_WRITE)) ) terror("Opening write pipe stream"); sf[0] = fr; sf[1] = str; if((c = sfpoll(sf,2,0)) != 1 || sf[0] != str) terror("Only str should be available c=%d",c); sf[0] = fr; if(sfpoll(sf,1,0) != 0 ) terror("Pipe stream should not be ready"); sfputc(fw,'a'); sfsync(fw); sf[0] = fr; if(sfpoll(sf,1,0) != 1 ) terror("Pipe read should be ready"); if((c = sfgetc(fr)) != 'a') terror("Didn't get back right data"); sf[0] = fr; sf[1] = str; if(sfpoll(sf,2,0) != 1 || sf[0] != str) terror("Only str should be available2"); sf[0] = fw; sf[1] = str; if(sfpoll(sf,2,0) != 2) terror("Both str&pipe write should be available"); if(pipe(fd) < 0) terror("Can't create pipe"); if(!(fr = sfnew(fr,NIL(Void_t*),(size_t)SF_UNBOUND,fd[0],SF_READ)) ) terror("Can't create stream"); if(write(fd[1],"0123456789",10) != 10) terror("Can't write to pipe"); if(sfpoll(&fr,1,1000) != 1) terror("Data should be available"); s = sfprints("%s 1", argv[0]); if(!(f = sfpopen(0, s, "w+")) ) terror("Can't create read/write process"); /* this write does not flush yet */ if(sfwrite(f, "abc\n",4) != 4) terror("Writing to pipe"); if(sfpoll(&f, 1, 0) != 1) terror("Poll should succeed"); if(sfvalue(f)&SF_READ) /* data has not been flushed to the child yet */ terror("Read should not be ready"); if(!(sfvalue(f)&SF_WRITE) ) terror("Write should be ready"); if(sfsync(f) < 0) /* now flush data to the child process */ terror("Bad sync"); if(sfpoll(&f, 1, 1000) != 1) terror("Poll should succeed2"); if(!(sfvalue(f)&SF_READ) ) /* the child should have read and rewritten */ terror("Read should be ready"); if(!(sfvalue(f)&SF_WRITE) ) terror("Write should be ready"); if(!(s = sfgetr(f,'\n',1)) || strcmp(s, "abc") != 0) terror("Bad read"); #if _lib_socketpair if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0) terror("socketpair failed"); if(!(f = sfnew(0,NIL(Void_t*),(size_t)SF_UNBOUND,fd[0],SF_READ|SF_WRITE)) ) terror("Can't create stream with socket file descriptor"); if(!(g = sfnew(0,NIL(Void_t*),(size_t)SF_UNBOUND,fd[1],SF_READ|SF_WRITE)) ) terror("Can't create stream with socket file descriptor"); /* turn off write-capability for f */ sfset(f,SF_WRITE,0); sf[0] = f; sf[1] = g; if(sfpoll(sf,2,0) != 1) terror("Exactly one stream should be ready!"); if(sf[0] != g) terror("Stream g should be ready"); if(sfvalue(g)&SF_READ) terror("Read should not be ready for g"); if(!(sfvalue(g)&SF_WRITE) ) terror("Write should be ready for g"); if(sfwrite(g, "abc\n", 4) != 4 || sfsync(g) < 0) terror("Writing to g socket"); if(sfpoll(sf, 2, 0) != 2) terror("Poll should succeed with both streams"); if(!(sfvalue(f)&SF_READ) ) terror("Read should be ready for f"); if(sfgetc(f) != 'a' ) terror("sfgetc failed"); /* turn back on write-capability for f */ sfset(f,SF_WRITE,1); if(sfwrite(f,"def\n",4) != 4 || sfsync(f) < 0) terror("Writing to f socket"); if(sfpoll(sf, 2, 0) != 2) terror("Poll should succeed for both streams"); if(!sfvalue(f)&SF_READ) terror("Read should be ready for f"); if(!sfvalue(g)&SF_READ) terror("Read should be ready for g"); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"bc") != 0) terror("f gets wrong data"); if(!(s = sfgetr(g,'\n',1)) || strcmp(s,"def") != 0) terror("g gets wrong data"); if(sfpoll(sf, 2, 0) != 2) terror("Poll should succeed for both streams"); if(sfvalue(f)&SF_READ) terror("Read should not be ready for f"); if(sfvalue(g)&SF_READ) terror("Read should not be ready for g"); #endif texit(0); }