MAIN() { char buf[1024], *s; Sfio_t* f; f = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND,-1,SF_WRITE|SF_STRING); sfsetbuf(sfstdout,buf,sizeof(buf)); sfsetbuf(sfstderr,buf,sizeof(buf)); sfset(sfstdout,SF_SHARE,0); sfset(sfstderr,SF_SHARE,0); if(!sfpool(sfstdout,f,SF_SHARE) || !sfpool(sfstderr,f,SF_SHARE) ) terror("Pooling\n"); if(sfputr(sfstdout,"01234",-1) != 5) terror("Writing to stderr\n"); if(sfputr(sfstderr,"56789",-1) != 5) terror("Writing to stdout\n"); if(sfputc(f,'\0') < 0) terror("Writing to string stream\n"); sfseek(f,(Sfoff_t)0,0); if(!(s = sfreserve(f,SF_UNBOUND,1)) ) terror("Peeking\n"); sfwrite(f,s,0); if(strcmp(s,"0123456789") != 0) terror("Data is wrong\n"); TSTEXIT(0); }
int b_print(int argc, char *argv[], Shbltin_t *context) { register Sfio_t *outfile; register int exitval=0,n, fd = 1; register Shell_t *shp = context->shp; const char *options, *msg = e_file+4; char *format = 0, *fmttype=0; int sflag = 0, nflag=0, rflag=0, vflag=0; Namval_t *vname=0; Optdisc_t disc; disc.version = OPT_VERSION; disc.infof = infof; opt_info.disc = &disc; if(argc>0) { options = sh_optprint; nflag = rflag = 0; format = 0; } else { struct print *pp = (struct print*)context; shp = pp->sh; options = pp->options; if(argc==0) { nflag = pp->echon; rflag = pp->raw; argv++; goto skip; } } while((n = optget(argv,options))) switch(n) { case 'n': nflag++; break; case 'p': fd = shp->coutpipe; msg = e_query; break; case 'f': format = opt_info.arg; break; case 's': /* print to history file */ if(!sh_histinit((void*)shp)) errormsg(SH_DICT,ERROR_system(1),e_history); fd = sffileno(shp->gd->hist_ptr->histfp); sh_onstate(shp,SH_HISTORY); sflag++; break; case 'e': rflag = 0; break; case 'r': rflag = 1; break; case 'u': if(opt_info.arg[0]=='p' && opt_info.arg[1]==0) { fd = shp->coutpipe; msg = e_query; break; } fd = (int)strtol(opt_info.arg,&opt_info.arg,10); if(*opt_info.arg) fd = -1; else if(!sh_iovalidfd(shp,fd)) fd = -1; else if(!(shp->inuse_bits&(1<<fd)) && (sh_inuse(shp,fd) || (shp->gd->hist_ptr && fd==sffileno(shp->gd->hist_ptr->histfp)))) fd = -1; break; case 'j': fmttype = "json"; case 'v': if(argc < 0) { if(!(vname = nv_open(opt_info.arg, shp->var_tree,NV_VARNAME|NV_NOARRAY))) errormsg(SH_DICT,2, "Cannot create variable %s", opt_info.arg); } else vflag='v'; break; case 'C': vflag='C'; break; case ':': /* The following is for backward compatibility */ #if OPT_VERSION >= 19990123 if(strcmp(opt_info.name,"-R")==0) #else if(strcmp(opt_info.option,"-R")==0) #endif { rflag = 1; if(error_info.errors==0) { argv += opt_info.index+1; /* special case test for -Rn */ if(strchr(argv[-1],'n')) nflag++; if(*argv && strcmp(*argv,"-n")==0) { nflag++; argv++; } goto skip2; } } else errormsg(SH_DICT,2, "%s", opt_info.arg); break; case '?': errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); break; } argv += opt_info.index; if(error_info.errors || (argc<0 && !(format = *argv++))) errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); if(vflag && format) errormsg(SH_DICT,ERROR_usage(2),"-%c and -f are mutually exclusive",vflag); skip: if(format) format = genformat(shp,format); /* handle special case of '-' operand for print */ if(argc>0 && *argv && strcmp(*argv,"-")==0 && strcmp(argv[-1],"--")) argv++; if(vname) { if(!shp->strbuf2) shp->strbuf2 = sfstropen(); outfile = shp->strbuf2; goto printv; } skip2: if(fd < 0) { errno = EBADF; n = 0; } else if(!(n=shp->fdstatus[fd])) n = sh_iocheckfd(shp,fd,fd); if(!(n&IOWRITE)) { /* don't print error message for stdout for compatibility */ if(fd==1) return(1); errormsg(SH_DICT,ERROR_system(1),msg); } if(!(outfile=shp->sftable[fd])) { sh_onstate(shp,SH_NOTRACK); n = SF_WRITE|((n&IOREAD)?SF_READ:0); shp->sftable[fd] = outfile = sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fd,n); sh_offstate(shp,SH_NOTRACK); sfpool(outfile,shp->outpool,SF_WRITE); }
/* * This routine will turn the sftmp() file into a real /tmp file or pipe */ void sh_subtmpfile(int pflag) { Shell_t *shp = &sh; int fds[2]; Sfoff_t off; register struct checkpt *pp = (struct checkpt*)shp->jmplist; register struct subshell *sp = subshell_data->pipe; if(sfset(sfstdout,0,0)&SF_STRING) { register int fd; /* save file descriptor 1 if open */ if((sp->tmpfd = fd = fcntl(1,F_DUPFD,10)) >= 0) { fcntl(fd,F_SETFD,FD_CLOEXEC); shp->fdstatus[fd] = shp->fdstatus[1]|IOCLEX; close(1); shp->fdstatus[1] = IOCLOSE; } else if(errno!=EBADF) { ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT; shp->toomany = 1; errormsg(SH_DICT,ERROR_system(1),e_toomany); } if(shp->subshare || !pflag) { sfdisc(sfstdout,SF_POPDISC); if((fd=sffileno(sfstdout))>=0) { shp->fdstatus[fd] = IOREAD|IOWRITE; sfsync(sfstdout); if(fd==1) fcntl(1,F_SETFD,0); else { sfsetfd(sfstdout,1); shp->fdstatus[1] = shp->fdstatus[fd]; shp->fdstatus[fd] = IOCLOSE; } goto skip; } } } if(sp && (shp->fdstatus[1]==IOCLOSE || (!shp->subshare && !(shp->fdstatus[1]&IONOSEEK)))) { struct stat statb,statx; int fd; sh_pipe(fds); sp->pipefd = fds[0]; sh_fcntl(sp->pipefd,F_SETFD,FD_CLOEXEC); /* write the data to the pipe */ if(off = sftell(sfstdout)) { write(fds[1],sfsetbuf(sfstdout,(Void_t*)sfstdout,0),(size_t)off); sfpurge(sfstdout); } if((sfset(sfstdout,0,0)&SF_STRING) || fstat(1,&statb)<0) statb.st_ino = 0; sfclose(sfstdout); if((sh_fcntl(fds[1],F_DUPFD, 1)) != 1) errormsg(SH_DICT,ERROR_system(1),e_redirect); sh_close(fds[1]); if(statb.st_ino) for(fd=0; fd < 10; fd++) { if(fd==1 || ((shp->fdstatus[fd]&(IONOSEEK|IOSEEK|IOWRITE))!=(IOSEEK|IOWRITE)) || fstat(fd,&statx)<0) continue; if(statb.st_ino==statx.st_ino && statb.st_dev==statx.st_dev) { sh_close(fd); fcntl(1,F_DUPFD, fd); } } skip: sh_iostream(shp,1); sfset(sfstdout,SF_SHARE|SF_PUBLIC,1); sfpool(sfstdout,shp->outpool,SF_WRITE); if(pp && pp->olist && pp->olist->strm == sfstdout) pp->olist->strm = 0; } }