14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #include "sfdchdr.h"
234887Schin
244887Schin /* A discipline to tee the output to a stream to another stream.
254887Schin ** This is similar to what the "tee" program does. As implemented
264887Schin ** this discipline only works with file streams.
274887Schin **
284887Schin ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998.
294887Schin */
304887Schin
314887Schin /* the discipline structure for tee-ing */
324887Schin typedef struct _tee_s
334887Schin { Sfdisc_t disc; /* the sfio discipline structure */
344887Schin Sfio_t* tee; /* the stream to tee to */
354887Schin int status; /* if tee stream is still ok */
364887Schin } Tee_t;
374887Schin
384887Schin /* write to the teed stream. */
394887Schin #if __STD_C
teewrite(Sfio_t * f,const Void_t * buf,size_t size,Sfdisc_t * disc)404887Schin static ssize_t teewrite(Sfio_t* f, const Void_t* buf, size_t size, Sfdisc_t* disc)
414887Schin #else
424887Schin static ssize_t teewrite(f,buf,size,disc)
434887Schin Sfio_t* f; /* the stream being written to */
444887Schin Void_t* buf; /* the buffer of data being output */
454887Schin size_t size; /* the data size */
464887Schin Sfdisc_t* disc; /* the tee discipline */
474887Schin #endif
484887Schin {
494887Schin reg Tee_t* te = (Tee_t*)disc;
504887Schin
514887Schin /* tee data if still ok */
524887Schin if(te->status == 0 && sfwrite(te->tee,buf,size) != (ssize_t)size)
534887Schin te->status = -1;
544887Schin
554887Schin /* do the actual write */
564887Schin return sfwr(f,buf,size,disc);
574887Schin }
584887Schin
594887Schin /* on close, remove the discipline */
604887Schin #if __STD_C
teeexcept(Sfio_t * f,int type,Void_t * data,Sfdisc_t * disc)614887Schin static int teeexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
624887Schin #else
634887Schin static int teeexcept(f,type,data,disc)
644887Schin Sfio_t* f;
654887Schin int type;
664887Schin Void_t* data;
674887Schin Sfdisc_t* disc;
684887Schin #endif
694887Schin {
704887Schin if(type == SF_FINAL || type == SF_DPOP)
714887Schin free(disc);
724887Schin
734887Schin return 0;
744887Schin }
754887Schin
764887Schin #if __STD_C
sfdctee(Sfio_t * f,Sfio_t * tee)774887Schin int sfdctee(Sfio_t* f, Sfio_t* tee)
784887Schin #else
794887Schin int sfdctee(f, tee)
804887Schin Sfio_t* f; /* stream to tee from */
814887Schin Sfio_t* tee; /* stream to tee to */
824887Schin #endif
834887Schin {
844887Schin reg Tee_t* te;
854887Schin
864887Schin if(!(te = (Tee_t*)malloc(sizeof(Tee_t))) )
874887Schin return -1;
884887Schin
894887Schin te->disc.readf = NIL(Sfread_f);
904887Schin te->disc.seekf = NIL(Sfseek_f);
914887Schin te->disc.writef = teewrite;
924887Schin te->disc.exceptf = teeexcept;
934887Schin te->tee = tee;
944887Schin te->status = 0;
954887Schin
964887Schin if(sfdisc(f,(Sfdisc_t*)te) != (Sfdisc_t*)te)
974887Schin { free(te);
984887Schin return -1;
994887Schin }
1004887Schin
1014887Schin return 0;
1024887Schin }
103