
/**********************************************************************/
/*                                                                    */
/* Copyright (c) 2001 by Sun Microsystems, Inc.                       */
/* All rights reserved.                                               */
/*                                                                    */
/**********************************************************************/


/* $Date:   19 Sep 2001 16:47:48  $ */
/* $Modtime:   18 Sep 2001 16:42:42  $ */

#ifndef lint
#ifdef __STDC__
const
#endif
static char sccsid[] = "@(#) $Workfile:   recordout.c  $ $Revision:   1.0  $";
#endif

/*
 * $Log:   /unikix/source2/SunMTP7.2.0/unikixsrc/user/record/PVCS/recordout.c_v  $
 * 
 *    Rev 1.0   19 Sep 2001 16:47:48   unikix
 * Initial 7.2
 * 
 *    Rev 1.0   30 Jan 2000 11:47:58   unikix
 * Initial 7.0
 * 
 *    Rev 1.0   15 Mar 1999 20:00:02   unikix
 * Initial 6.0
 * 
 *    Rev 1.0   05/22/97 17:33:56   unikix
 * Initial 5.1
 * 
 *    Rev 1.0   04/10/96 14:14:08   unikix
 * Initial 5.0
 * 
 *    Rev 1.0   12/28/94 15:18:42   unikix
 * Initial revision (from V410ad)
 * 
 *    Rev 1.0.1.0   11/18/93 16:36:56   unikix
 * UniKix 4.1 baseline (from V400m)
 * 
 *    Rev 1.0   06/10/93 11:59:52   unikix
 * UniKix 3.1.2 version
 * 
 *    Rev 1.0   05/21/93 16:14:38   unikix
 * UniKix 3.1.2 version
 */

/*
** Name:            RECORD.out
**                  writes a fixed length record to a sequential file.
**
**                    1.0      (90/12/17)
**
** Parameters:      1: name of this program
**                  2: name of file to be written
**                  3: logical record length "99999"
**                  4: "F" for fixed or "V" for variable length file.
**
** Return:          The return codes and data is returned thru standard
**                  back.  The data is sent via standard output. The lenght
**                  is placed in the first 6 bytes (5 bytes for the
**                  number and a trailing null), followed by the data.
**                  End of file is indicated by a zero record length.
**                  The pipe is oneway so an error can not be reported
**                  back to the parent procedure.  If there is a error the
**                  procedure will abort and the parent will time out.
**
** External:        <ERRNO.H> list of errors for file operations.
**                  open UNIX close function.
**
*/

/*
recordout.c exported routines:
        main
recordout.c has no exported variables
recordout.c imports:
        atoi
        close
        creat
        errno
        exit
        fprintf
        free
         malloc
        memcpy
        read
        write
*/

/* ------------- unix includes ------------- */

#include <sys/types.h>
#ifdef __STDC__
#include <stdlib.h>
#include <unistd.h>
#endif
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#ifndef DPX
#include <malloc.h>
#include <memory.h>
#endif

/* ------------- local defines ------------- */

#define TRUE       1
#define OKCD       0
#define OPNOK      0
#define STDOUTDES  1
#define STDINDES   0
#define ERRSZ      6
#define MEMERR    -1
#define OPNERR    -2
#define RDERR     -3
#define BLKSIZE    4096


main (/* ARGSUSED */argc,argv)
int argc;
char *argv[];
{
int      lrecl;                            /*logical record length*/
char     lsrecl[6];                      /*logical record length*/
char     lrecfmt;                          /*record format F=fixed V=var.*/
char     lseq_fileid[129];               /*file id of seq file to be read*/
char    *lrecbuff;                         /*pointer to record buffer      */
int      lfildes;                          /*output file descriptor*/
int      lindes;                           /*standard input  file descriptor*/
int      lcurr_len;                        /*current record length          */
unsigned lbufl;                            /*number of bytes in buffer */
int      lnread;                           /*number of bytes actually read   */
int      li;                               /*total number of bytes read in   */
int      lj;                               /*first time flag                 */


    /* Get parameters for argv. */
    memcpy(lseq_fileid, argv[1], 129);
    lrecl = atoi(argv[2]);
    memcpy((char *)&lrecfmt,argv[3], 1);

    lindes = STDINDES;    /* Set file descriptor to standard input. */

    /* Create memory for buffer. Size = logical record length + 6.  */
    lbufl = (unsigned)lrecl + 6;
    if((lrecbuff = malloc(lbufl)) == 0)
        {
        exit(errno); /* Abort with systen error number.   */
        }

    /* Open output file in create mode (delete if exist).          */
    if((lfildes = creat(lseq_fileid, 0644)) < 0)
        {
         exit(errno); /* Abort with systen error number.   */
        }

    /* Read pipe until error, no more data, or record size = zero. */
    /* CONSTCOND */
    while(TRUE)
        {
        li = 0;
        while ((lnread = read(lindes,lrecbuff+li,(unsigned)(6 - li))) != (6 - li))
            {
	    if (lnread < 1)
		{
		/* This is a read error.                               */
		if (errno == 0)
		  {
		  errno = RDERR;
		  }
		exit(errno); /* Abort with systen error number.   */
		}
            li += lnread;
            }

        /* The first 6 bytes contain the record size format = "99999\0" */
        memcpy(lsrecl,lrecbuff,6);

        /* If record size is less then one this is EOF.                 */
        if((lcurr_len = atoi(lsrecl)) < 1)
            {
            break;
            }

        /* The pipe can only transfer 4096 bytes at a time.  So if the  */
        /*     record is larger we must loop until the complete record  */
        /*     has been read in.                                        */

        lj = 0;

        while(lcurr_len > 0)
            {
            lj = (lj == 0) ? BLKSIZE - 6 : BLKSIZE;
            li = (lcurr_len < lj) ? lcurr_len : lj;
            lnread = read(lindes,lrecbuff,(unsigned)(li));
            if (lnread < 1)   /* Check for read error.                 */
                {
                if (errno == 0) /* No data in pipe.                    */
                  {
                  errno = RDERR;
                  }
                exit(errno); /* Abort with systen error number.   */
                }
            /* Now write the output file and check for errors.    */
            if(write(lfildes,lrecbuff,(unsigned)lnread) < 0)
                {
                exit(errno); /* Abort with systen error number.   */
                }
            lcurr_len -= lnread;
            }
        }

    close(lfildes); /* Close output file                                    */
    free(lrecbuff); /* Free buffer memory                                   */

    exit(0);
    /* NOTREACHED */
}
