Example #1
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(load_main) (char *fname, RADR startloc)
{
int fd;
int len;
int rc = 0;
RADR pageaddr;
U32  pagesize;

    fd = HOPEN (fname, O_RDONLY|O_BINARY);
    if (fd < 0)
    {
        if(errno != ENOENT)
            WRMSG(HHC00600,"E",fname,"open()",strerror(errno));
        return fd;
    }

    pagesize = PAGEFRAME_PAGESIZE - (startloc & PAGEFRAME_BYTEMASK);
    pageaddr = startloc;

    for( ; ; ) {
        if (pageaddr >= sysblk.mainsize)
        {
            WRMSG(HHC00603, "W", fname);
            close(fd);
            return rc;
        }

        len = read(fd, sysblk.mainstor + pageaddr, pagesize);
        if (len > 0)
        {
            STORAGE_KEY(pageaddr, &sysblk) |= STORKEY_REF|STORKEY_CHANGE;
            rc += len;
        }

        if (len < (int)pagesize)
        {
            close(fd);
            return rc;
        }

        pageaddr += PAGEFRAME_PAGESIZE;
        pageaddr &= PAGEFRAME_PAGEMASK;
        pagesize  = PAGEFRAME_PAGESIZE;
    }

} /* end function load_main */
Example #2
0
static void http_download(WEBBLK *webblk, char *filename)
{
    char buffer[HTTP_PATH_LENGTH];
    char tbuf[80];
    int fd, length;
    char *filetype;
    char fullname[HTTP_PATH_LENGTH];
    struct stat st;
    MIMETAB *mime_type = mime_types;

    strlcpy( fullname, http_serv.httproot, sizeof(fullname) );
    strlcat( fullname, filename,        sizeof(fullname) );

    http_verify_path(webblk,fullname);

    if(stat(fullname,&st))
        http_error(webblk, "404 File Not Found","",
                           strerror(errno));

    if(!S_ISREG(st.st_mode))
        http_error(webblk, "404 File Not Found","",
                           "The requested file is not a regular file");

    fd = HOPEN(fullname,O_RDONLY|O_BINARY,0);
    if (fd == -1)
        http_error(webblk, "404 File Not Found","",
                           strerror(errno));

    hprintf(webblk->sock,"HTTP/1.0 200 OK\n");
    if ((filetype = strrchr(filename,'.')))
        for(mime_type++;mime_type->suffix
          && strcasecmp(mime_type->suffix,filetype + 1);
          mime_type++);
    if(mime_type->type)
        hprintf(webblk->sock,"Content-Type: %s\n", mime_type->type);

    hprintf(webblk->sock,"Expires: %s\n",
      http_timestring(tbuf,sizeof(tbuf),time(NULL)+HTML_STATIC_EXPIRY_TIME));

    hprintf(webblk->sock,"Content-Length: %d\n\n", (int)st.st_size);
    while ((length = read(fd, buffer, sizeof(buffer))) > 0)
            hwrite(webblk->sock,buffer, length);
    close(fd);
    http_exit(webblk);
}
Example #3
0
DLL_EXPORT void log_sethrdcpy(char *filename)
{
    FILE *temp_hrdcpy = logger_hrdcpy;
    FILE *new_hrdcpy;
    int   new_hrdcpyfd = -1;

    if(!filename)
    {
        memset(logger_filename, 0, sizeof(logger_filename));

        if(!logger_hrdcpy)
        {
            WRMSG(HHC02100, "E");
            return;
        }
        else
        {
            obtain_lock(&logger_lock);
            logger_hrdcpy = 0;
            logger_hrdcpyfd = 0;
            release_lock(&logger_lock);
            if ( sysblk.emsg & EMSG_TS )
            {
                struct timeval  now;
                time_t          tt;
                char            hhmmss[10];

                gettimeofday( &now, NULL );
                tt = now.tv_sec;
                strlcpy( hhmmss, ctime(&tt)+11, sizeof(hhmmss) );
                hhmmss[8] = '\0';
                fprintf(temp_hrdcpy, "%s ", hhmmss);
            }
            fprintf(temp_hrdcpy,MSG(HHC02101, "I"));
            fclose(temp_hrdcpy);
            WRMSG(HHC02101, "I");
            return;
        }
    }
    else
    {
        char pathname[MAX_PATH];
        hostpath(pathname, filename, sizeof(pathname));

        memset(logger_filename, 0, sizeof(logger_filename));

        new_hrdcpyfd = HOPEN(pathname,
                             O_WRONLY | O_CREAT | O_TRUNC /* O_SYNC */,
                             S_IRUSR  | S_IWUSR | S_IRGRP);
        if(new_hrdcpyfd < 0)
        {
            WRMSG(HHC02102, "E","open()",strerror(errno));
            return;
        }
        else
        {
            if(!(new_hrdcpy = fdopen(new_hrdcpyfd,"w")))
            {
                WRMSG(HHC02102,"E", "fdopen()", strerror(errno));
                return;
            }
            else
            {
                setvbuf(new_hrdcpy, NULL, _IONBF, 0);

                obtain_lock(&logger_lock);
                logger_hrdcpy = new_hrdcpy;
                logger_hrdcpyfd = new_hrdcpyfd;
                strlcpy(logger_filename, filename, sizeof(logger_filename));
                release_lock(&logger_lock);

                if(temp_hrdcpy)
                {
                    char buf[MAX_PATH+2];
                    char *pzbuf = buf;

                    if ( strchr(filename,SPACE) == NULL )
                        pzbuf = filename;
                    else
                        MSGBUF(buf,"'%s'",filename);

                    if ( sysblk.emsg & EMSG_TS )
                    {
                        struct timeval  now;
                        time_t          tt;
                        char            hhmmss[10];

                        gettimeofday( &now, NULL );
                        tt = now.tv_sec;
                        strlcpy( hhmmss, ctime(&tt)+11, sizeof(hhmmss) );
                        hhmmss[8] = '\0';
                        fprintf(temp_hrdcpy, "%s ", hhmmss);
                    }
                    fprintf(temp_hrdcpy, MSG(HHC02104, "I", pzbuf));
                    fclose(temp_hrdcpy);
                }
            }
        }
    }
}
Example #4
0
/*-------------------------------------------------------------------*/
static void
convert_ckd_file (IFD ifd, char *ifname, int itrklen, BYTE *itrkbuf,
                int repl, int quiet,
                char *ofname, int fseqn, U16 devtype, U32 heads,
                U32 trksize, BYTE *obuf, U32 start, U32 end,
                U32 volcyls, BYTE *volser)
{
int             rc;                     /* Return code               */
int             ofd;                    /* Output file descriptor    */
CKDDASD_DEVHDR  devhdr;                 /* Output device header      */
CKDDASD_TRKHDR *trkhdr;                 /* -> Output track header    */
CKDDASD_RECHDR *rechdr;                 /* -> Output record header   */
U32             cyl;                    /* Cylinder number           */
U32             head;                   /* Head number               */
int             fileseq;                /* CKD header sequence number*/
int             highcyl;                /* CKD header high cyl number*/
BYTE           *opos;                   /* -> Byte in output buffer  */
BYTE            klen;                   /* Key length                */
U16             dlen;                   /* Data length               */
BYTE            rec;                    /* Record number             */
BYTE           *iptr;                   /* -> Byte in input buffer   */
BYTE           *kptr;                   /* -> Key in input buffer    */
BYTE           *dptr;                   /* -> Data in input buffer   */
int             ilen;                   /* Bytes left in input buffer*/
H30CKD_TRKHDR  *ith;                    /* -> Input track header     */
U32             ihc, ihh;               /* Input trk header cyl,head */
U32             offset;                 /* Current input file offset */
char            pathname[MAX_PATH];     /* file path in host format  */

    UNREFERENCED(volser);

    /* Set file sequence number to zero if this is the only file */
    if (fseqn == 1 && end + 1 == volcyls)
        fileseq = 0;
    else
        fileseq = fseqn;

    /* Set high cylinder number to zero if this is the last file */
    if (end + 1 == volcyls)
        highcyl = 0;
    else
        highcyl = end;

    /* Create the AWSCKD image file */
    hostpath(pathname, (char *)ofname, sizeof(pathname));
    ofd = HOPEN (pathname,
                O_WRONLY | O_CREAT | O_BINARY | (repl ? 0 : O_EXCL),
                S_IRUSR | S_IWUSR | S_IRGRP);

    if (ofd < 0)
    {
        fprintf (stderr, MSG(HHC02412, "E", "open()", strerror(errno)));
        EXIT(8);
    }

    /* Create the device header */
    memset(&devhdr, 0, CKDDASD_DEVHDR_SIZE);
    memcpy(devhdr.devid, "CKD_P370", 8);
    devhdr.heads[3] = (heads >> 24) & 0xFF;
    devhdr.heads[2] = (heads >> 16) & 0xFF;
    devhdr.heads[1] = (heads >> 8) & 0xFF;
    devhdr.heads[0] = heads & 0xFF;
    devhdr.trksize[3] = (trksize >> 24) & 0xFF;
    devhdr.trksize[2] = (trksize >> 16) & 0xFF;
    devhdr.trksize[1] = (trksize >> 8) & 0xFF;
    devhdr.trksize[0] = trksize & 0xFF;
    devhdr.devtype = devtype & 0xFF;
    devhdr.fileseq = fileseq;
    devhdr.highcyl[1] = (highcyl >> 8) & 0xFF;
    devhdr.highcyl[0] = highcyl & 0xFF;

    /* Write the device header */
    rc = write (ofd, &devhdr, CKDDASD_DEVHDR_SIZE);
    if (rc < CKDDASD_DEVHDR_SIZE)
    {
        fprintf (stderr, MSG(HHC02412, "E", "write()", errno ? strerror(errno) : "incomplete"));
        EXIT(1);
    }

    /* Write each cylinder */
    for (cyl = start; cyl <= end; cyl++)
    {
        /* Display progress message every 10 cylinders */
        if ((cyl % 10) == 0)
        {
#ifdef EXTERNALGUI
            if (extgui)
                fprintf (stderr, "CYL=%u\n", cyl);
            else
#endif /*EXTERNALGUI*/
            if (quiet == 0)
                fprintf (stderr, "Writing cylinder %u\r", cyl);
        }

        for (head = 0; head < heads; head++)
        {
            /* Calculate the current offset in the file */
            offset = ((cyl*heads)+head)*itrklen;

            /* Read the input track image (except cyl 0 head 0
               already read by the open_input_image procedure) */
            if (cyl > 0 || head > 0)
            {
                read_input_data (ifd, ifname,
                                 itrkbuf, itrklen,
                                 offset);
            } /* end if(cyl>0||head>0) */

            /* Validate the track header */
            ith = (H30CKD_TRKHDR*)itrkbuf;
            FETCH_HW (ihc, ith->cyl);
            FETCH_HW (ihh, ith->head);
            if (ihc != cyl || ihh != head)
            {
                fprintf (stderr, MSG(HHC02417, "E", offset));
                fprintf (stderr, MSG(HHC02418, "E",
                        cyl, head, ihc, ihh));
                EXIT(8);
            }

            /* Clear the output track image to zeroes */
            memset (obuf, 0, trksize);

            /* Build the output track header */
            trkhdr = (CKDDASD_TRKHDR*)obuf;
            trkhdr->bin = 0;
            STORE_HW (trkhdr->cyl, cyl);
            STORE_HW (trkhdr->head, head);
            opos = obuf + CKDDASD_TRKHDR_SIZE;

            /* Copy each record from the input buffer */
            iptr = itrkbuf + H30CKD_TRKHDR_SIZE;
            ilen = itrklen - H30CKD_TRKHDR_SIZE;
            while (1)
            {
                /* Locate the next input record */
                rc = find_input_record (itrkbuf, &iptr, &ilen,
                        &klen, &kptr, &dlen, &dptr,
                        &ihc, &ihh, &rec);

                /* Exit at end of track */
                if (rc == 1) break;

                /* Error if invalid record header detected */
                if (rc > 1)
                {
                    fprintf (stderr, MSG(HHC02419, "E",
                            rc, (unsigned int)(iptr-itrkbuf), cyl, head,
                            offset, ifname));
                    EXIT(9);
                }

                /* Build AWSCKD record header in output buffer */
                rechdr = (CKDDASD_RECHDR*)opos;
                opos += CKDDASD_RECHDR_SIZE;
                STORE_HW (rechdr->cyl, ihc);
                STORE_HW (rechdr->head, ihh);
                rechdr->rec = rec;
                rechdr->klen = klen;
                STORE_HW (rechdr->dlen, dlen);

                /* Copy key and data to output buffer */
                if (klen != 0)
                {
                    memcpy (opos, kptr, klen);
                    opos += klen;
                }
                if (dlen != 0)
                {
                    memcpy (opos, dptr, dlen);
                    opos += dlen;
                }

            } /* end while */

            /* Build the end of track marker */
            memcpy (opos, eighthexFF, 8);

            /* Write the track to the file */
            rc = write (ofd, obuf, trksize);
            if (rc < 0 || (U32)rc < trksize)
            {
                fprintf (stderr, MSG(HHC02412, "E", "write()",
                        errno ? strerror(errno) : "incomplete"));
                EXIT(1);
            }

        } /* end for(head) */

    } /* end for(cyl) */

    /* Close the AWSCKD image file */
    rc = close (ofd);
    if (rc < 0)
    {
        fprintf (stderr, MSG(HHC02412, "E", "close()", strerror(errno)));
        EXIT(10);
    }

    /* Display completion message */
    fprintf (stderr, MSG(HHC02420, "I",
            cyl - start, ofname));

} /* end function convert_ckd_file */
Example #5
0
/*-------------------------------------------------------------------*/
static IFD
open_input_image (char *ifname, U16 *devt, U32 *vcyls,
                U32 *itrkl, BYTE **itrkb, BYTE *volser)
{
int             rc;                     /* Return code               */
H30CKD_TRKHDR   h30trkhdr;              /* Input track header        */
IFD             ifd;                    /* Input file descriptor     */
int             len;                    /* Length of input           */
U16             code;                   /* Device type code          */
U16             dt;                     /* Device type               */
U32             cyls;                   /* Device size (pri+alt cyls)*/
U32             alts;                   /* Number of alternate cyls  */
BYTE           *itrkbuf;                /* -> Input track buffer     */
U32             itrklen;                /* Input track length        */
BYTE           *pbuf;                   /* Current byte in input buf */
BYTE            klen;                   /* Key length                */
U16             dlen;                   /* Data length               */
BYTE           *kptr;                   /* -> Key in input buffer    */
BYTE           *dptr;                   /* -> Data in input buffer   */
U32             cyl;                    /* Cylinder number           */
U32             head;                   /* Head number               */
BYTE            rec;                    /* Record number             */
char            pathname[MAX_PATH];     /* file path in host format  */

    hostpath(pathname, (char *)ifname, sizeof(pathname));

    /* Open the HDR-30 CKD image file */
  #if defined(HAVE_LIBZ)
    if (strcmp(ifname, "-") == 0)
        ifd = gzdopen (STDIN_FILENO, "rb");
    else
        ifd = gzopen (pathname, "rb");

    if (ifd == NULL)
    {
        fprintf (stderr, MSG(HHC02412, "E", "gzopen()", strerror(errno)));
        EXIT(3);
    }
  #else /*!defined(HAVE_LIBZ)*/
    if (strcmp(ifname, "-") == 0)
        ifd = STDIN_FILENO;
    else
    {
        ifd = HOPEN (pathname, O_RDONLY | O_BINARY);

        if (ifd < 0)
        {
            fprintf (stderr, MSG(HHC02412, "E", "open()", strerror(errno)));
            EXIT(3);
        }
    }
  #endif /*!defined(HAVE_LIBZ)*/

    /* Read the first track header */
    read_input_data (ifd, ifname, (BYTE*)&h30trkhdr,
                    H30CKD_TRKHDR_SIZE, 0);

  #if !defined(HAVE_LIBZ)
    /* Reject input if compressed and we lack gzip support */
    if (memcmp(h30trkhdr.devcode, gz_magic_id, sizeof(gz_magic_id)) == 0)
    {
        fprintf (stderr, MSG(HHC02413, "E"));
        EXIT(3);
    }
  #endif /*!defined(HAVE_LIBZ)*/

    /* Reject input if it is already in CKD or CCKD format */
    if (memcmp((BYTE*)&h30trkhdr, ckd_ident, sizeof(ckd_ident)) == 0)
    {
        fprintf (stderr, MSG(HHC02414, "I"));
        EXIT(3);
    }

    /* Extract the device type code from the track header */
    FETCH_HW (code, h30trkhdr.devcode);

    /* Determine the input device type and size from the device code */
    switch (code) {
    case 0x01: dt=0x3330; cyls=411; alts=7; break;      /* 3330      */
    case 0x02: dt=0x3330; cyls=815; alts=7; break;      /* 3330-11   */
    case 0x03: dt=0x3340; cyls=351; alts=1; break;      /* 3340-35   */
    case 0x04: dt=0x3340; cyls=701; alts=1; break;      /* 3340-70   */
    case 0x05: dt=0x3350; cyls=562; alts=7; break;      /* 3350      */
    case 0x06: dt=0x3375; cyls=962; alts=3; break;      /* 3375      */
    case 0x08: dt=0x3380; cyls=888; alts=3; break;      /* 3380-A,D,J*/
    case 0x09: dt=0x3380; cyls=1774; alts=4; break;     /* 3380-E    */
    case 0x0A: dt=0x3380; cyls=2660; alts=5; break;     /* 3380-K    */
    case 0x0B: dt=0x3390; cyls=1117; alts=4; break;     /* 3390-1    */
    case 0x0C: dt=0x3390; cyls=2230; alts=4; break;     /* 3390-2    */
    case 0x0D: dt=0x3390; cyls=3343; alts=4; break;     /* 3390-3    */
    case 0x12: dt=0x2314; cyls=203; alts=3; break;      /* 2314      */
    case 0x13: dt=0x3390; cyls=10038; alts=21; break;   /* 3390-9    */
    case 0x14: dt=0x9345; cyls=1454; alts=14; break;    /* 9345-1    */
    case 0x15: dt=0x9345; cyls=2170; alts=14; break;    /* 9345-2    */
    default:
        fprintf (stderr, MSG(HHC02415, "E", code));
        EXIT(3);
    } /* end switch(code) */

    /* Use the device type to determine the input image track size */
    switch (dt) {
    case 0x2314: itrklen = 0x2000; break;
    case 0x3330: itrklen = 0x3400; break;
    case 0x3340: itrklen = 0x2400; break;
    case 0x3350: itrklen = 0x4C00; break;
    case 0x3375: itrklen = 0x9000; break;
    case 0x3380: itrklen = 0xBC00; break;
    case 0x3390: itrklen = 0xE400; break;
    case 0x9345: itrklen = 0xBC00; break;
    default:
        fprintf (stderr, MSG(HHC02416, "E", dt));
        EXIT(3);
    } /* end switch(dt) */

    /* Obtain the input track buffer */
    itrkbuf = malloc (itrklen);
    if (itrkbuf == NULL)
    {
        char buf[40];
        MSGBUF( buf, "malloc(%u)", itrklen);
        fprintf (stderr, MSG(HHC02412, "E", buf, strerror(errno)));
        EXIT(3);
    }

    /* Copy the first track header to the input track buffer */
    memcpy (itrkbuf, &h30trkhdr, H30CKD_TRKHDR_SIZE);

    /* Read the remainder of the first track into the buffer */
    read_input_data (ifd, ifname,
                     itrkbuf + H30CKD_TRKHDR_SIZE,
                     itrklen - H30CKD_TRKHDR_SIZE,
                     H30CKD_TRKHDR_SIZE);

    /* Initialize the volume serial number */
    strcpy ((char *)volser, "(NONE)");

    /* Search for volume label in record 3 of first track */
    pbuf = itrkbuf + H30CKD_TRKHDR_SIZE;
    len = itrklen - H30CKD_TRKHDR_SIZE;
    while (1)
    {
        /* Find next input record */
        rc = find_input_record (itrkbuf, &pbuf, &len,
                &klen, &kptr, &dlen, &dptr,
                &cyl, &head, &rec);

        /* Give up if error or end of track */
        if (rc != 0) break;

        /* Process when record 3 is found */
        if (cyl == 0 && head == 0 && rec == 3)
        {
            /* Extract volser if it is a volume label */
            if (klen == 4 && memcmp(kptr, ebcdicvol1, 4) == 0
            && dlen == 80 && memcmp(dptr, ebcdicvol1, 4) == 0)
                make_asciiz ((char *)volser, 7, dptr+4, 6);
            break;
        }
    } /* end while */

    /* Set output variables and return the input file descriptor */
    *devt = dt;
    *vcyls = cyls - alts;
    *itrkl = itrklen;
    *itrkb = itrkbuf;
    return ifd;

} /* end function open_input_image */
Example #6
0
/*-------------------------------------------------------------------*/
static int open_cardrdr ( DEVBLK *dev, BYTE *unitstat )
{
int     rc;                             /* Return code               */
int     i;                              /* Array subscript           */
int     len;                            /* Length of data            */
BYTE    buf[160];                       /* Auto-detection buffer     */

    *unitstat = 0;

    // Socket device?

    if (dev->bs)
    {
        // Intervention required if no one has connected yet

        if (dev->fd == -1)
        {
            if(dev->rdreof)
            {
                *unitstat=CSW_CE|CSW_DE|CSW_UX;
                return -1;
            }
            dev->sense[0] = SENSE_IR;
            dev->sense[1] = SENSE1_RDR_RAIC; /* Retry when IntReq Cleared */
            *unitstat = CSW_CE | CSW_DE | CSW_UC;
            return -1;
        }

        return 0;
    }

    /* Intervention required if device has no file name */
    if (dev->filename[0] == '\0' || ( strlen(dev->filename) == 1 && dev->filename[0] == '*') )
    {
        if(dev->rdreof)
        {
            *unitstat=CSW_CE|CSW_DE|CSW_UX;
            return -1;
        }
        dev->sense[0] = SENSE_IR;
        dev->sense[1] = SENSE1_RDR_RAIC; /* Retry when IntReq Cleared */
        *unitstat = CSW_CE | CSW_DE | CSW_UC;
        return -1;
    }

    /* Open the device file */
    rc = HOPEN (dev->filename, O_RDONLY | O_BINARY);
    if (rc < 0)
    {
        /* Handle open failure */
        WRMSG (HHC01200, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, "open()", strerror(errno));

        /* Set unit check with equipment check */
        dev->sense[0] = SENSE_EC;
        *unitstat = CSW_CE | CSW_DE | CSW_UC;
        return -1;
    }

    /* Save the file descriptor in the device block */
    dev->fd = rc;
    dev->fh = fdopen(dev->fd, "rb");

    /* If neither EBCDIC nor ASCII was specified, attempt to
       detect the format by inspecting the first 160 bytes */
    if (dev->ebcdic == 0 && dev->ascii == 0)
    {
        /* Read first 160 bytes of file into the buffer */
        len = (int)fread(buf, 1, sizeof(buf), dev->fh);
        if (len < 0)
        {
            /* Handle read error condition */
            WRMSG (HHC01200, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, "fread()", strerror(errno));

            /* Close the file */
            fclose(dev->fh);
            dev->fd = -1;
            dev->fh = NULL;

            /* Set unit check with equipment check */
            dev->sense[0] = SENSE_EC;
            *unitstat = CSW_CE | CSW_DE | CSW_UC;
            return -1;
        }

        /* Assume ASCII format if first 160 bytes contain only ASCII
           characters, carriage return, line feed, tab, or EOF */
        for (i = 0, dev->ascii = 1; i < len && buf[i] != '\x1A'; i++)
        {
            if ((buf[i] < 0x20 || buf[i] > 0x7F)
                && buf[i] != '\r' && buf[i] != '\n'
                && buf[i] != '\t')
            {
                dev->ascii = 0;
                dev->ebcdic = 1;
                break;
            }
        } /* end for(i) */

        /* Rewind to start of file */
        rc = fseek (dev->fh, 0, SEEK_SET);
        if (rc < 0)
        {
            /* Handle seek error condition */
            WRMSG (HHC01200, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, "fseek()", strerror(errno));

            /* Close the file */
            fclose (dev->fh);
            dev->fd = -1;
            dev->fh = NULL;

            /* Set unit check with equipment check */
            dev->sense[0] = SENSE_EC;
            *unitstat = CSW_CE | CSW_DE | CSW_UC;
            return -1;
        }

    } /* end if(auto-detect) */

    ASSERT(dev->fd != -1 && dev->fh);

    return 0;
} /* end function open_cardrdr */
Example #7
0
/*-------------------------------------------------------------------*/
static S64 ARCH_DEP(read_file)(char *fname, CREG sto, S64 seek, S64 size)
{
int fd, nread;
U64 totread = 0;

    fd = HOPEN (fname, O_RDONLY|O_BINARY);
    if (fd < 0)
    {
        if(errno != ENOENT)
            WRMSG (HHC00600, "E", fname, "open()", strerror(errno));
        return -1;
    }

    if(lseek(fd, (off_t)seek, SEEK_SET) == (off_t)seek)
    {
#if defined(FEATURE_ESAME)
        sto &= ASCE_TO;
#else /*!defined(FEATURE_ESAME)*/
        sto &= STD_STO;
#endif /*!defined(FEATURE_ESAME)*/

        for( ; size > 0 ; sto += sizeof(sto))
        {
#if defined(FEATURE_ESAME)
        DBLWRD *ste;
#else /*!defined(FEATURE_ESAME)*/
        FWORD *ste;
#endif /*!defined(FEATURE_ESAME)*/
        CREG pto, pti;

            /* Fetch segment table entry and calc Page Table Origin */
            if( sto >= sysblk.mainsize)
                goto eof;
#if defined(FEATURE_ESAME)
            ste = (DBLWRD*)(sysblk.mainstor + sto);
#else /*!defined(FEATURE_ESAME)*/
            ste = (FWORD*)(sysblk.mainstor + sto);
#endif /*!defined(FEATURE_ESAME)*/
            FETCH_W(pto, ste);
            STORAGE_KEY(sto, &sysblk) |= (STORKEY_REF);
            if( pto & SEGTAB_INVALID )
                goto eof;
#if defined(FEATURE_ESAME)
            pto &= ZSEGTAB_PTO;
#else /*!defined(FEATURE_ESAME)*/
            pto &= SEGTAB_PTO;
#endif /*!defined(FEATURE_ESAME)*/

            for(pti = 0; pti < 256 && size > 0; pti++, pto += sizeof(pto))
            {
#if defined(FEATURE_ESAME)
            DBLWRD *pte;
#else /*!defined(FEATURE_ESAME)*/
            FWORD *pte;
#endif /*!defined(FEATURE_ESAME)*/
            CREG pgo;
            BYTE *page;

                /* Fetch Page Table Entry to get page origin */
                if( pto >= sysblk.mainsize)
                    goto eof;
#if defined(FEATURE_ESAME)
                pte = (DBLWRD*)(sysblk.mainstor + pto);
#else /*!defined(FEATURE_ESAME)*/
                pte = (FWORD*)(sysblk.mainstor + pto);
#endif /*!defined(FEATURE_ESAME)*/
                FETCH_W(pgo, pte);
                STORAGE_KEY(pto, &sysblk) |= (STORKEY_REF);
                if( pgo & PAGETAB_INVALID )
                    goto eof;
#if defined(FEATURE_ESAME)
                pgo &= ZPGETAB_PFRA;
#else /*!defined(FEATURE_ESAME)*/
                pgo &= PAGETAB_PFRA;
#endif /*!defined(FEATURE_ESAME)*/

                /* Read page into main storage */
                if( pgo >= sysblk.mainsize)
                    goto eof;
                page = sysblk.mainstor + pgo;
                nread = read(fd, page, STORAGE_KEY_PAGESIZE);
                totread += nread;
                size -= nread;
                if( nread != STORAGE_KEY_PAGESIZE )
                    goto eof;
                STORAGE_KEY(pgo, &sysblk) |= (STORKEY_REF|STORKEY_CHANGE);
            }
        }
    }
eof:
    close(fd);
    return totread;
}
Example #8
0
/*-------------------------------------------------------------------*/
int open_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code)
{
int             rc = -1;                /* Return code               */
char            pathname[MAX_PATH];     /* file path in host format  */

    /* Check for no tape in drive */
    if (!strcmp (dev->filename, TAPE_UNLOADED))
    {
        build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
        return -1;
    }

    /* Open the AWSTAPE file */
    hostpath(pathname, dev->filename, sizeof(pathname));
    if(!dev->tdparms.logical_readonly)
    {
        rc = HOPEN (pathname, O_RDWR | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP );
        if ( rc < 0 && !sysblk.noautoinit )
        {
            rc = HOPEN( pathname, O_RDWR | O_BINARY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP );
            if ( rc >= 0 )
            {
                int tmp_fd = dev->fd;
                int ret_code = 0;

                dev->fd = rc;

                WRMSG( HHC00235, "I", SSID_TO_LCSS(dev->ssid),
                       dev->devnum, dev->filename, "aws" );
                ret_code = write_awsmark( dev, unitstat, code );
                if ( ret_code >= 0 )
                    ret_code = write_awsmark( dev, unitstat, code );
                if ( ret_code < 0 )
                {
                    dev->fd = tmp_fd;
                    rc = ret_code;
                }
            }
        }
    }

    /* If file is read-only, attempt to open again */
    if (dev->tdparms.logical_readonly || (rc < 0 && (EROFS == errno || EACCES == errno)))
    {
        dev->readonly = 1;
        rc = HOPEN (pathname, O_RDONLY | O_BINARY, S_IRUSR | S_IRGRP );
    }

    /* Check for successful open */
    if (rc < 0)
    {
        WRMSG (HHC00205, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "aws", "open()", strerror(errno));

        strlcpy( dev->filename, TAPE_UNLOADED, sizeof(dev->filename) );
        build_senseX(TAPE_BSENSE_TAPELOADFAIL,dev,unitstat,code);
        return -1;
    }

    /* Store the file descriptor in the device block */
    dev->fd = rc;
    rc=rewind_awstape(dev,unitstat,code);
    return rc;

} /* end function open_awstape */
Example #9
0
/*-------------------------------------------------------------------*/
static int
open_printer (DEVBLK *dev)
{
pid_t           pid;                    /* Child process identifier  */
int             open_flags;             /* File open flags           */
#if !defined( _MSVC_ )
int             pipefd[2];              /* Pipe descriptors          */
int             rc;                     /* Return code               */
#endif

    /* Regular open if 1st char of filename is not vertical bar */
    if (!dev->ispiped)
    {
        int fd;

        /* Socket printer? */
        if (dev->bs)
            return (dev->fd < 0 ? -1 : 0);

        /* Normal printer */
        open_flags = O_BINARY | O_WRONLY | O_CREAT /* | O_SYNC */;
        if (dev->notrunc != 1)
        {
            open_flags |= O_TRUNC;
        }
        fd = HOPEN (dev->filename, open_flags,
                    S_IRUSR | S_IWUSR | S_IRGRP);
        if (fd < 0)
        {
            WRMSG (HHC01105, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, "open()", strerror(errno));
            return -1;
        }

        /* Save file descriptor in device block and return */
        dev->fd = fd;
        return 0;
    }

    /* Filename is in format |xxx, set up pipe to program xxx */

#if defined( _MSVC_ )

    /* "Poor man's" fork... */
    pid = w32_poor_mans_fork ( dev->filename+1, &dev->fd );
    if (pid < 0)
    {
        WRMSG (HHC01105, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, "fork()", strerror(errno));
        return -1;
    }

    /* Log start of child process */
    WRMSG (HHC01106, "I", SSID_TO_LCSS(dev->ssid), dev->devnum, pid);
    dev->ptpcpid = pid;

#else /* !defined( _MSVC_ ) */

    /* Create a pipe */
    rc = create_pipe (pipefd);
    if (rc < 0)
    {
        WRMSG (HHC01105, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, "create_pipe()", strerror(errno));
        return -1;
    }

    /* Fork a child process to receive the pipe data */
    pid = fork();
    if (pid < 0)
    {
        WRMSG (HHC01005, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, "fork()", strerror(errno));
        close_pipe ( pipefd[0] );
        close_pipe ( pipefd[1] );
        return -1;
    }

    /* The child process executes the pipe receiver program... */
    if (pid == 0)
    {
        /* Log start of child process */
        WRMSG (HHC01106, "I", SSID_TO_LCSS(dev->ssid), dev->devnum, getpid());

        /* Close the write end of the pipe */
        close_pipe ( pipefd[1] );

        /* Duplicate the read end of the pipe onto STDIN */
        if (pipefd[0] != STDIN_FILENO)
        {
            rc = dup2 (pipefd[0], STDIN_FILENO);
            if (rc != STDIN_FILENO)
            {
                WRMSG (HHC01105, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, "dup2()", strerror(errno));
                close_pipe ( pipefd[0] );
                _exit(127);
            }
        } /* end if(pipefd[0] != STDIN_FILENO) */

        /* Close the original descriptor now duplicated to STDIN */
        close_pipe ( pipefd[0] );

        /* Redirect stderr (screen) to hercules log task */
        dup2(STDOUT_FILENO, STDERR_FILENO);

        /* Relinquish any ROOT authority before calling shell */
        SETMODE(TERM);

        /* Execute the specified pipe receiver program */
        rc = system (dev->filename+1);

        if (rc == 0)
        {
            /* Log end of child process */
            WRMSG (HHC01107, "I", SSID_TO_LCSS(dev->ssid), dev->devnum, getpid());
        }
        else
        {
            /* Log error */
            WRMSG (HHC01108, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename+1, strerror(errno));
        }

        /* The child process terminates using _exit instead of exit
           to avoid invoking the panel atexit cleanup routine */
        _exit(rc);

    } /* end if(pid==0) */

    /* The parent process continues as the pipe sender */

    /* Close the read end of the pipe */
    close_pipe ( pipefd[0] );

    /* Save pipe write descriptor in the device block */
    dev->fd = pipefd[1];
    dev->ptpcpid = pid;

#endif /* defined( _MSVC_ ) */

    return 0;

} /* end function open_printer */
Example #10
0
/*-------------------------------------------------------------------*/
int read_omadesc (DEVBLK *dev)
{
int             rc;                     /* Return code               */
int             i;                      /* Array subscript           */
size_t          pathlen;                /* Length of TDF path name   */
int             tdfsize;                /* Size of TDF file in bytes */
int             filecount;              /* Number of files           */
int             stmt;                   /* TDF file statement number */
int             fd;                     /* TDF file descriptor       */
struct stat     statbuf;                /* TDF file information      */
U32             blklen;                 /* Fixed block length        */
int             tdfpos;                 /* Position in TDF buffer    */
char           *tdfbuf;                 /* -> TDF file buffer        */
char           *tdfrec;                 /* -> TDF record             */
char           *tdffilenm;              /* -> Filename in TDF record */
char           *tdfformat;              /* -> Format in TDF record   */
char           *tdfreckwd;              /* -> Keyword in TDF record  */
char           *tdfblklen;              /* -> Length in TDF record   */
OMATAPE_DESC   *tdftab;                 /* -> Tape descriptor array  */
BYTE            c;                      /* Work area for sscanf      */
char            pathname[MAX_PATH];     /* file path in host format  */
char           *strtok_str = NULL;      /* last token position       */

    /* Isolate the base path name of the TDF file */
    for (pathlen = strlen(dev->filename); pathlen > 0; )
    {
        pathlen--;
        if (dev->filename[pathlen-1] == '/') break;

    }
#if 0
    // JCS thinks this is bad
    if (pathlen < 7
        || strncasecmp(dev->filename+pathlen-7, "/tapes/", 7) != 0)
    {
        WRITEMSG ("%1d:%04X TDF File '%s': invalid filename: TDF files must be in the TAPES subdirectory", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename+pathlen, "oma");
        return -1;
    }
    pathlen -= 7;
#endif

    /* Open the tape descriptor file */
    hostpath(pathname, dev->filename, sizeof(pathname));
    fd = HOPEN (pathname, O_RDONLY | O_BINARY);
    if (fd < 0)
    {
        WRMSG (HHC00205, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "oma", "open()", strerror(errno));
        return -1;
    }

    /* Determine the size of the tape descriptor file */
    rc = fstat (fd, &statbuf);
    if (rc < 0)
    {
        WRMSG (HHC00205, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "oma", "fstat()", strerror(errno));
        close (fd);
        return -1;
    }
    tdfsize = statbuf.st_size;

    /* Obtain a buffer for the tape descriptor file */
    tdfbuf = malloc (tdfsize);
    if (tdfbuf == NULL)
    {
        WRMSG (HHC00205, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "oma", "malloc()", strerror(errno));
        close (fd);
        return -1;
    }

    /* Read the tape descriptor file into the buffer */
    rc = read (fd, tdfbuf, tdfsize);
    if (rc < tdfsize)
    {
        WRMSG (HHC00205, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "oma", "read()", strerror(errno));
        free (tdfbuf);
        close (fd);
        return -1;
    }

    /* Close the tape descriptor file */
    close (fd); fd = -1;

    /* Check that the first record is a TDF header */
    if (memcmp(tdfbuf, "@TDF", 4) != 0)
    {
        WRMSG (HHC00206, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "oma");
        free (tdfbuf);
        return -1;
    }

    /* Count the number of linefeeds in the tape descriptor file
       to determine the size of the descriptor array required */
    for (i = 0, filecount = 0; i < tdfsize; i++)
    {
        if (tdfbuf[i] == '\n') filecount++;
    } /* end for(i) */
    /* ISW Add 1 to filecount to add an extra EOT marker */
    filecount++;

    /* Obtain storage for the tape descriptor array */
    tdftab = (OMATAPE_DESC*)malloc (filecount * sizeof(OMATAPE_DESC));
    if (tdftab == NULL)
    {
        WRMSG (HHC00205, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "oma", "malloc()", strerror(errno));
        free (tdfbuf);
        return -1;
    }

    /* Build the tape descriptor array */
    for (filecount = 0, tdfpos = 0, stmt = 1; ; filecount++)
    {
        /* Clear the tape descriptor array entry */
        memset (&(tdftab[filecount]), 0, sizeof(OMATAPE_DESC));

        /* Point past the next linefeed in the TDF file */
        while (tdfpos < tdfsize && tdfbuf[tdfpos++] != '\n');
        stmt++;

        /* Exit at end of TDF file */
        if (tdfpos >= tdfsize) break;

        /* Mark the end of the TDF record with a null terminator */
        tdfrec = tdfbuf + tdfpos;
        while (tdfpos < tdfsize && tdfbuf[tdfpos]!='\r'
            && tdfbuf[tdfpos]!='\n') tdfpos++;
        c = tdfbuf[tdfpos];
        if (tdfpos >= tdfsize) break;
        tdfbuf[tdfpos] = '\0';

        /* Exit if TM or EOT record */
        if (strcasecmp(tdfrec, "TM") == 0)
        {
            tdftab[filecount].format='X';
            tdfbuf[tdfpos] = c;
            continue;
        }
        if(strcasecmp(tdfrec, "EOT") == 0)
        {
            tdftab[filecount].format='E';
            break;
        }

        /* Parse the TDF record */
        tdffilenm = strtok_r (tdfrec, " \t", &strtok_str);
        tdfformat = strtok_r (NULL,   " \t", &strtok_str);
        tdfreckwd = strtok_r (NULL,   " \t", &strtok_str);
        tdfblklen = strtok_r (NULL,   " \t", &strtok_str);

        /* Check for missing fields */
        if (tdffilenm == NULL || tdfformat == NULL)
        {
            WRMSG (HHC00207, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "oma", stmt, "filename or format missing");
            free (tdftab);
            free (tdfbuf);
            return -1;
        }

        /* Check that the file name is not too long */
        if (pathlen + 1 + strlen(tdffilenm)
                > sizeof(tdftab[filecount].filename) - 1)
        {
            char buf[MAX_PATH+32];

            if ( strchr(tdffilenm, SPACE) == NULL)
                MSGBUF(buf, "filename %s too long", tdffilenm);
            else
                MSGBUF(buf, "filename '%s' too long", tdffilenm);

            WRMSG (HHC00207, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "oma", stmt, buf);
            free (tdftab);
            free (tdfbuf);
            return -1;
        }

        /* Convert the file name to Unix format */
        for (i = 0; i < (int)strlen(tdffilenm); i++)
        {
            if (tdffilenm[i] == '\\')
                tdffilenm[i] = '/';
/* JCS */
//            else
//                tdffilenm[i] = tolower(tdffilenm[i]);
        } /* end for(i) */

        /* Prefix the file name with the base path name and
           save it in the tape descriptor array */
        /* but only if the filename lacks a leading slash - JCS  */
/*
        strncpy (tdftab[filecount].filename, dev->filename, pathlen);
        if (tdffilenm[0] != '/')
            stlrcat ( tdftab[filecount].filename, "/", sizeof(tdftab[filecount].filename) );
        strlcat ( tdftab[filecount].filename, tdffilenm, sizeof(tdftab[filecount].filename) );
*/
        tdftab[filecount].filename[0] = 0;

        if ((tdffilenm[0] != '/') && (tdffilenm[1] != ':'))
        {
            strncpy (tdftab[filecount].filename, dev->filename, pathlen);
            strlcat (tdftab[filecount].filename, "/", sizeof(tdftab[filecount].filename) );
        }

        strlcat (tdftab[filecount].filename, tdffilenm, sizeof(tdftab[filecount].filename) );

        /* Check for valid file format code */
        if (strcasecmp(tdfformat, "HEADERS") == 0)
        {
            tdftab[filecount].format = 'H';
        }
        else if (strcasecmp(tdfformat, "TEXT") == 0)
        {
            tdftab[filecount].format = 'T';
        }
        else if (strcasecmp(tdfformat, "FIXED") == 0)
        {
            /* Check for RECSIZE keyword */
            if (tdfreckwd == NULL
                || strcasecmp(tdfreckwd, "RECSIZE") != 0)
            {
                WRMSG (HHC00207, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "oma", stmt, "keyword RECSIZE missing");
                free (tdftab);
                free (tdfbuf);
                return -1;
            }

            /* Check for valid fixed block length */
            if (tdfblklen == NULL
                || sscanf(tdfblklen, "%u%c", &blklen, &c) != 1
                || blklen < 1 || blklen > MAX_BLKLEN)
            {
                char buf[40];
                MSGBUF(buf, "invalid record size %s", tdfblklen);
                WRMSG (HHC00207, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "oma", stmt, buf);
                free (tdftab);
                free (tdfbuf);
                return -1;
            }

            /* Set format and block length in descriptor array */
            tdftab[filecount].format = 'F';
            tdftab[filecount].blklen = blklen;
        }
        else
        {
            char buf[40];
            MSGBUF(buf, "invalid record format '%s'", tdfformat);
            WRMSG (HHC00207, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename, "oma", stmt, buf);
            free (tdftab);
            free (tdfbuf);
            return -1;
        }
        tdfbuf[tdfpos] = c;
    } /* end for(filecount) */
    /* Force an EOT as last entry (filecount is correctly adjusted here) */
    tdftab[filecount].format='E';

    /* Save the file count and TDF array pointer in the device block */
    dev->omafiles = filecount+1;
    dev->omadesc = tdftab;

    /* Release the TDF file buffer and exit */
    free (tdfbuf);
    return 0;

} /* end function read_omadesc */
Example #11
0
/*-------------------------------------------------------------------*/
int open_omatape (DEVBLK *dev, BYTE *unitstat,BYTE code)
{
int             fd;                     /* File descriptor integer   */
int             rc;                     /* Return code               */
OMATAPE_DESC   *omadesc;                /* -> OMA descriptor entry   */
char            pathname[MAX_PATH];     /* file path in host format  */

     /* Check for no tape in drive */
     if (!strcmp (dev->filename, TAPE_UNLOADED))
     {
         build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
         return -1;
     }

    /* Read the OMA descriptor file if necessary */
    if (dev->omadesc == NULL)
    {
        rc = read_omadesc (dev);
        if (rc < 0)
        {
            build_senseX(TAPE_BSENSE_TAPELOADFAIL,dev,unitstat,code);
            return -1;
        }
        dev->blockid = 0;
    }

    dev->fenced = 0;

    /* Unit exception if beyond end of tape */
    /* ISW: CHANGED PROCESSING - RETURN UNDEFINITE Tape Marks  */
    /*       NOTE: The last entry in the TDF table is ALWAYS   */
    /*              an EOT Condition                           */
    /*              This is ensured by the TDF reading routine */
#if 0
    if (dev->curfilen >= dev->omafiles)
    {
        WRITEMSG (HHC00000E, SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename);

        build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
        return -1;
    }
#else
    if(dev->curfilen>dev->omafiles)
    {
        dev->curfilen=dev->omafiles;
        return(0);
    }
#endif

    /* Point to the current file entry in the OMA descriptor table */
    omadesc = (OMATAPE_DESC*)(dev->omadesc);
    omadesc += (dev->curfilen-1);
    if(omadesc->format=='X')
    {
        return 0;
    }
    if(omadesc->format=='E')
    {
        return 0;
    }

    /* Open the OMATAPE file */
    hostpath(pathname, omadesc->filename, sizeof(pathname));
    fd = HOPEN (pathname, O_RDONLY | O_BINARY);

    /* Check for successful open */
    if (fd < 0 || lseek (fd, 0, SEEK_END) > LONG_MAX)
    {
        if (fd >= 0)            /* (if open was successful, then it) */
            errno = EOVERFLOW;  /* (must have been a lseek overflow) */

        WRMSG (HHC00205, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, omadesc->filename, "oma", "open()", strerror(errno));

        if (fd >= 0)
            close(fd);          /* (close the file if it was opened) */

        build_senseX(TAPE_BSENSE_TAPELOADFAIL,dev,unitstat,code);
        return -1;
    }

    /* OMA tapes are always read-only */
    dev->readonly = 1;

    /* Store the file descriptor in the device block */
    dev->fd = fd;
    return 0;

} /* end function open_omatape */
Example #12
0
int main ( int argc, char *argv[])
{
char           *pgmname;                /* prog name in host format  */
char           *pgm;                    /* less any extension (.ext) */
char            msgbuf[512];            /* message build work area   */
CKDDASD_DEVHDR  devhdr;                 /* CKD device header         */
CCKDDASD_DEVHDR cdevhdr;                /* Compressed CKD device hdr */
int             level = 0;              /* Chkdsk level              */
int             force = 0;              /* 1=swap if OPENED bit on   */
int             rc;                     /* Return code               */
int             i;                      /* Index                     */
int             bigend;                 /* 1=big-endian file         */
DEVBLK          devblk;                 /* DEVBLK                    */
DEVBLK         *dev=&devblk;            /* -> DEVBLK                 */
char           *strtok_str = NULL;

    /* Set program name */
    if ( argc > 0 )
    {
        if ( strlen(argv[0]) == 0 )
        {
            pgmname = strdup( UTILITY_NAME );
        }
        else
        {
            char path[MAX_PATH];
#if defined( _MSVC_ )
            GetModuleFileName( NULL, path, MAX_PATH );
#else
            strncpy( path, argv[0], sizeof( path ) );
#endif
            pgmname = strdup(basename(path));
#if !defined( _MSVC_ )
            strncpy( path, argv[0], sizeof(path) );
#endif
        }
    }
    else
    {
        pgmname = strdup( UTILITY_NAME );
    }

    pgm = strtok_r( strdup(pgmname), ".", &strtok_str);
    INITIALIZE_UTILITY( pgmname );
    /* Display the program identification message */
    MSGBUF( msgbuf, MSG_C( HHC02499, "I", pgm, "Swap 'endianess' of a cckd file" ) );
    display_version (stderr, msgbuf+10, FALSE);

    /* parse the arguments */
    for (argc--, argv++ ; argc > 0 ; argc--, argv++)
    {
        if(**argv != '-') break;

        switch(argv[0][1])
        {
            case '0':
            case '1':
            case '2':
            case '3':  if (argv[0][2] != '\0') return syntax (pgm);
                       level = (argv[0][1] & 0xf);
                       break;
            case 'f':  if (argv[0][2] != '\0') return syntax (pgm);
                       force = 1;
                       break;
            case 'v':  if (argv[0][2] != '\0') return syntax (pgm);
                       return 0;
            default:   return syntax (pgm);
        }
    }

    if (argc < 1) return syntax (pgm);

    for (i = 0; i < argc; i++)
    {
        memset (dev, 0, sizeof (DEVBLK));
        dev->batch = 1;

        /* open the input file */
        hostpath(dev->filename, argv[i], sizeof(dev->filename));
        dev->fd = HOPEN (dev->filename, O_RDWR|O_BINARY);
        if (dev->fd < 0)
        {
            fprintf(stdout, MSG(HHC00354, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename,
                    "open()", strerror(errno)));
            continue;
        }

        /* read the CKD device header */
        if ((rc = read (dev->fd, &devhdr, CKDDASD_DEVHDR_SIZE)) < CKDDASD_DEVHDR_SIZE)
        {
            fprintf(stdout, MSG(HHC00355, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename,
                    "read()", (U64)0, rc < 0 ? strerror(errno) : "incomplete"));
            close (dev->fd);
            continue;
        }
        if (memcmp(devhdr.devid, "CKD_C370", 8) != 0
         && memcmp(devhdr.devid, "CKD_S370", 8) != 0
         && memcmp(devhdr.devid, "FBA_C370", 8) != 0
         && memcmp(devhdr.devid, "FBA_S370", 8) != 0)
        {
            fprintf(stdout, MSG(HHC00356, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename));
            close (dev->fd);
            continue;
        }

        /* read the compressed CKD device header */
        if ((rc = read (dev->fd, &cdevhdr, CCKD_DEVHDR_SIZE)) < CCKD_DEVHDR_SIZE)
        {
            fprintf(stdout, MSG(HHC00355, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename,
                    "read()", (U64)CCKD_DEVHDR_POS, rc < 0 ? strerror(errno) : "incomplete"));
            close (dev->fd);
            continue;
        }

        /* Check the OPENED bit */
        if (!force && (cdevhdr.options & CCKD_OPENED))
        {
            fprintf(stdout, MSG(HHC00352, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename));
            close (dev->fd);
            continue;
        }

        /* get the byte order of the file */
        bigend = (cdevhdr.options & CCKD_BIGENDIAN);

        /* call chkdsk */
        if (cckd_chkdsk (dev, level) < 0)
        {
            fprintf(stdout, MSG(HHC00353, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename));
            close (dev->fd);
            continue;
        }

        /* re-read the compressed CKD device header */
        if (lseek (dev->fd, CCKD_DEVHDR_POS, SEEK_SET) < 0)
        {
            fprintf(stdout, MSG(HHC00355, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename,
                    "lseek()", (U64)CCKD_DEVHDR_POS, strerror(errno)));
            close (dev->fd);
            continue;
        }
        if ((rc = read (dev->fd, &cdevhdr, CCKD_DEVHDR_SIZE)) < CCKD_DEVHDR_SIZE)
        {
            fprintf(stdout, MSG(HHC00355, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename,
                    "read()", (U64)CCKD_DEVHDR_POS, rc < 0 ? strerror(errno) : "incomplete"));
            close (dev->fd);
            continue;
        }

        /* swap the byte order of the file if chkdsk didn't do it for us */
        if (bigend == (cdevhdr.options & CCKD_BIGENDIAN))
        {
            fprintf(stdout, MSG(HHC00357, "I", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename,
                    cckd_endian() ? "big-endian" : "little-endian"));
            if (cckd_swapend (dev) < 0)
                fprintf(stdout, MSG(HHC00378, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->filename));

        }

        close (dev->fd);
    } /* for each arg */

    return 0;
} /* end main */
Example #13
0
/*-------------------------------------------------------------------*/
int main (int argc, char *argv[])
{
char           *pgm;                    /* less any extension (.ext) */
int             ckddasd=-1;             /* 1=CKD  0=FBA              */
int             rc;                     /* Return code               */
int             quiet=0;                /* 1=Don't display status    */
int             comp=255;               /* Compression algorithm     */
int             cyls=-1, blks=-1;       /* Size of output file       */
int             lfs=0;                  /* 1=Create 1 large file     */
int             alt=0;                  /* 1=Create alt cyls         */
int             r=0;                    /* 1=Replace output file     */
int             in=0, out=0;            /* Input/Output file types   */
int             fd;                     /* Input file descriptor     */
char           *ifile, *ofile;          /* -> Input/Output file names*/
char           *sfile=NULL;             /* -> Input shadow file name */
CIFBLK         *icif, *ocif;            /* -> Input/Output CIFBLK    */
DEVBLK         *idev, *odev;            /* -> Input/Output DEVBLK    */

CKDDEV         *ckd=NULL;               /* -> CKD device table entry */
FBADEV         *fba=NULL;               /* -> FBA device table entry */
int             i, n, max;              /* Loop index, limits        */
BYTE            unitstat;               /* Device unit status        */
size_t          fba_bytes_remaining=0;  /* FBA bytes to be copied    */
int             nullfmt = CKDDASD_NULLTRK_FMT0; /* Null track format */
char            pathname[MAX_PATH];     /* file path in host format  */

    INITIALIZE_UTILITY( UTILITY_NAME, "DASD copy/convert", &pgm );

    if (strcasecmp(pgm, "ckd2cckd") == 0)
    {
        in = CKD;
        out = CCKD;
    }
    else if (strcasecmp(pgm, "cckd2ckd") == 0)
    {
        in = CCKD;
        out = CKD;
    }
    else if (strcasecmp(pgm, "fba2cfba") == 0)
    {
        in = FBA;
        out = CFBA;
    }
    else if (strcasecmp(pgm, "cfba2fba") == 0)
    {
        in = CFBA;
        out = FBA;
    }

    /* Process the arguments */
    for (argc--, argv++ ; argc > 0 ; argc--, argv++)
    {
        if (argv[0][0] != '-') break;
        if (strcmp(argv[0], "-h") == 0)
        {
            syntax( pgm );
            return 0;
        }
        else if (strcmp(argv[0], "-q") == 0
              || strcmp(argv[0], "-quiet") == 0)
            quiet = 1;
        else if (strcmp(argv[0], "-r") == 0)
            r = 1;
#ifdef CCKD_COMPRESS_ZLIB
        else if (strcmp(argv[0], "-z") == 0)
            comp = CCKD_COMPRESS_ZLIB;
#endif
#ifdef CCKD_COMPRESS_BZIP2
        else if (strcmp(argv[0], "-bz2") == 0)
            comp = CCKD_COMPRESS_BZIP2;
#endif
        else if (strcmp(argv[0], "-0") == 0)
            comp = CCKD_COMPRESS_NONE;
        else if ((strcmp(argv[0], "-cyl") == 0
               || strcmp(argv[0], "-cyls") == 0) && cyls < 0)
        {
            if (argc < 2 || (cyls = atoi(argv[1])) < 0)
                return syntax( pgm );
            argc--; argv++;
        }
        else if ((strcmp(argv[0], "-blk") == 0
               || strcmp(argv[0], "-blks") == 0) && blks < 0)
        {
            if (argc < 2 || (blks = atoi(argv[1])) < 0)
                return syntax( pgm );
            argc--; argv++;
        }
        else if (strcmp(argv[0], "-a") == 0
              || strcmp(argv[0], "-alt") == 0
              || strcmp(argv[0], "-alts") == 0)
            alt = 1;
        else if (strcmp(argv[0], "-lfs") == 0)
            lfs = 1;
        else if (out == 0 && strcmp(argv[0], "-o") == 0)
        {
            if (argc < 2 || out != 0) return syntax( pgm );
            if (strcasecmp(argv[1], "ckd") == 0)
                out = CKD;
            else if (strcasecmp(argv[1], "cckd") == 0)
                out = CCKD;
            else if (strcasecmp(argv[1], "fba") == 0)
                out = FBA;
            else if (strcasecmp(argv[1], "cfba") == 0)
                out = CFBA;
            else
                return syntax( pgm );
            argc--; argv++;
        }
        else
            return syntax( pgm );
    }

    /* Get the file names:
       input-file [sf=shadow-file] output-file   */
    if (argc < 2 || argc > 3) return syntax( pgm );
    ifile = argv[0];
    if (argc < 3)
        ofile = argv[1];
    else
    {
        if (strlen(argv[1]) < 4 || memcmp(argv[1], "sf=", 3))
            return syntax( pgm );
        sfile = argv[1];
        ofile = argv[2];
    }

    /* If we don't know what the input file is then find out */
    if (in == 0)
    {
        BYTE buf[8];
        hostpath(pathname, ifile, sizeof(pathname));
        fd = HOPEN (pathname, O_RDONLY|O_BINARY);
        if (fd < 0)
        {
            // "Error in function %s: %s"
            FWRMSG( stderr, HHC02412, "E", "open()", strerror(errno) );
            return -1;
        }
        rc = read (fd, buf, 8);
        if (rc < 8)
        {
            // "Error in function %s: %s"
            FWRMSG( stderr, HHC02412, "E", "read()", strerror(errno) );
            return -1;
        }
        if (memcmp(buf, "CKD_P370", 8) == 0)
            in = CKD;
        else if (memcmp(buf, "CKD_C370", 8) == 0)
            in = CCKD;
        else if (memcmp(buf, "FBA_C370", 8) == 0)
            in = CFBA;
        else
            in = FBA;
        close (fd);
    }

    /* If we don't know what the output file type is
       then derive it from the input file type */
    if (out == 0)
    {
        switch (in) {
        case CKD:  if (!lfs) out = CCKD;
                   else out = CKD;
                   break;
        case CCKD: if (comp == 255) out = CKD;
                   else out = CCKD;
                   break;
        case FBA:  if (!lfs) out = CFBA;
                   else out = FBA;
                   break;
        case CFBA: if (comp == 255) out = FBA;
                   else out = CFBA;
                   break;
        }
    }

    /* Set default compression if out file is to be compressed */
    if (comp == 255 && (out & COMPMASK))
#ifdef CCKD_COMPRESS_ZLIB
        comp = CCKD_COMPRESS_ZLIB;
#else
        comp = CCKD_COMPRESS_NONE;
#endif

    /* Perform sanity checks on the options */
    if ((in & CKDMASK) && !(out & CKDMASK)) return syntax( pgm );
    if ((in & FBAMASK) && !(out & FBAMASK)) return syntax( pgm );
    if (sfile && !(in & COMPMASK))          return syntax( pgm );
    if (comp != 255 && !(out & COMPMASK))   return syntax( pgm );
    if (lfs && (out & COMPMASK))            return syntax( pgm );
    if (cyls >= 0 && !(in & CKDMASK))       return syntax( pgm );
    if (blks >= 0 && !(in & FBAMASK))       return syntax( pgm );
    if (!(in & CKDMASK) && alt)             return syntax( pgm );

    /* Set the type of processing (ckd or fba) */
    ckddasd = (in & CKDMASK);

    /* Open the input file */
    if (ckddasd)
        icif = open_ckd_image (ifile, sfile, O_RDONLY|O_BINARY, IMAGE_OPEN_NORMAL);
    else
        icif = open_fba_image (ifile, sfile, O_RDONLY|O_BINARY, IMAGE_OPEN_NORMAL);
    if (icif == NULL)
    {
        // "Failed opening %s"
        FWRMSG( stderr, HHC02403, "E", ifile );
        return -1;
    }
    idev = &icif->devblk;
    if (idev->oslinux) nullfmt = CKDDASD_NULLTRK_FMT2;

    /* Calculate the number of tracks or blocks to copy */
    if (ckddasd)
    {
        if (cyls < 0) cyls = idev->ckdcyls;
        else if (cyls == 0) cyls = (idev->hnd->used)(idev);
        ckd = dasd_lookup (DASD_CKDDEV, NULL, idev->devtype, 0);
        if (ckd == NULL)
        {
            // "CKD lookup failed: device type %04X cyls %d"
            FWRMSG( stderr, HHC02430, "E",
                     idev->devtype, cyls );
            close_image_file (icif);
            return -1;
        }
        if (cyls <= ckd->cyls && alt) cyls = ckd->cyls + ckd->altcyls;
        n = cyls * idev->ckdheads;
        max = idev->ckdtrks;
        if (max < n && out == CCKD) n = max;
    }
    else
    {
        fba_bytes_remaining = idev->fbanumblk * idev->fbablksiz;
        if (blks < 0) blks = idev->fbanumblk;
        else if (blks == 0) blks = (idev->hnd->used)(idev);
        fba = dasd_lookup (DASD_FBADEV, NULL, idev->devtype, 0);
        if (fba == NULL)
        {
            // "FBA lookup failed: blks %d"
            FWRMSG( stderr, HHC02431, "E", blks );
            close_image_file (icif);
            return -1;
        }
        n = blks;
        max = idev->fbanumblk;
        if (max < n && out == CFBA) n = max;
        n = (n + FBA_BLKS_PER_GRP - 1) / FBA_BLKS_PER_GRP;
        max = (max + FBA_BLKS_PER_GRP - 1) / FBA_BLKS_PER_GRP;
    }

    /* Create the output file */
    if (ckddasd)
        rc = create_ckd(ofile, idev->devtype, idev->ckdheads,
                        ckd->r1, cyls, "", comp, lfs, 1+r, nullfmt, 0,
                        1, 0);
    else
        rc = create_fba(ofile, idev->devtype, fba->size,
                        blks, "", comp, lfs, 1+r, 0);
    if (rc < 0)
    {
        // "Failed creating %s"
        FWRMSG( stderr, HHC02432, "E", ofile );
        close_image_file (icif);
        return -1;
    }

    /* Open the output file */
    if (ckddasd)
        ocif = open_ckd_image (ofile, NULL, O_RDWR|O_BINARY, IMAGE_OPEN_DASDCOPY);
    else
        ocif = open_fba_image (ofile, NULL, O_RDWR|O_BINARY, IMAGE_OPEN_DASDCOPY);
    if (ocif == NULL)
    {
        // "Failed opening %s"
        FWRMSG( stderr, HHC02403, "E", ofile );
        close_image_file (icif);
        return -1;
    }
    odev = &ocif->devblk;

    /* Notify GUI of total #of tracks or blocks being copied... */
    EXTGUIMSG( "TRKS=%d\n", n );

    /* Copy the files */

#if defined( EXTERNALGUI )
    if (!extgui)
#endif
        if (!quiet)
            printf ( "  %3d%% %7d of %d", 0, 0, n );

    for (i = 0; i < n; i++)
    {
        /* Read a track or block */
        if (ckddasd)
        {
            if (i < max)
                rc = (idev->hnd->read)(idev, i, &unitstat);
            else
            {
                memset (idev->buf, 0, idev->ckdtrksz);
                rc = nulltrk(idev->buf, i, idev->ckdheads, nullfmt);
            }
        }
        else
        {
            if (i < max)
                rc = (idev->hnd->read)(idev, i, &unitstat);
            else
                memset (idev->buf, 0, FBA_BLKGRP_SIZE);
                rc = 0;
        }
        if (rc < 0)
        {
            // "Read error on file %s: %s %d stat=%2.2X, null %s substituted"
            FWRMSG( stderr, HHC02433, "E",
                     ifile, ckddasd ? "track" : "block", i, unitstat,
                     ckddasd ? "track" : "block" );
            if (ckddasd)
                nulltrk(idev->buf, i, idev->ckdheads, nullfmt);
            else
                memset (idev->buf, 0, FBA_BLKGRP_SIZE);
            if (!quiet)
            {
#if defined( EXTERNALGUI )
                if (!extgui)
#endif
                    printf ( "  %3d%% %7d of %d", 0, 0, n );
                status (i, n);
            }
        }

        /* Write the track or block just read */
        if (ckddasd)
        {
            rc = (odev->hnd->write)(odev, i, 0, idev->buf,
                      idev->ckdtrksz, &unitstat);
        }
        else
        {
            if (fba_bytes_remaining >= (size_t)idev->buflen)
            {
                rc = (odev->hnd->write)(odev,  i, 0, idev->buf,
                          idev->buflen, &unitstat);
                fba_bytes_remaining -= (size_t)idev->buflen;
            }
            else
            {
                ASSERT(fba_bytes_remaining > 0 && (i+1) >= n);
                rc = (odev->hnd->write)(odev,  i, 0, idev->buf,
                          (int)fba_bytes_remaining, &unitstat);
                fba_bytes_remaining = 0;
            }
        }
        if (rc < 0)
        {
            // "Write error on file %s: %s %d stat=%2.2X"
            FWRMSG( stderr, HHC02434, "E",
                     ofile, ckddasd ? "track" : "block", i, unitstat );
            close_image_file(icif); close_image_file(ocif);
            return -1;
        }

        /* Update the status indicator */
        if (!quiet) status (i+1, n);
    }

    close_image_file(icif); close_image_file(ocif);

#if defined( EXTERNALGUI )
    if (!extgui)
#endif
        if (!quiet)
            printf (_("\r"));

    // "DASD operation completed"
    WRMSG( HHC02423, "I" );
    return 0;
}
Example #14
0
/*-------------------------------------------------------------------*/
DLL_EXPORT int impl(int argc, char *argv[])
{
char   *cfgfile;                        /* -> Configuration filename */
char    pathname[MAX_PATH];             /* work area for filenames   */
#if defined ( OPTION_LOCK_CONFIG_FILE )
int     fd_cfg = -1;                    /* fd for config file        */
#if !defined ( _MSVC_ )
struct  flock  fl_cfg;                  /* file lock for conf file   */
#endif
#endif
int     c;                              /* Work area for getopt      */
int     arg_error = 0;                  /* 1=Invalid arguments       */
char   *msgbuf;                         /*                           */
int     msgnum;                         /*                           */
int     msgcnt;                         /*                           */
TID     rctid;                          /* RC file thread identifier */
TID     logcbtid;                       /* RC file thread identifier */
int     rc;
#if defined(EXTERNALGUI)
int     e_gui = FALSE;                  /* EXTERNALGUI parm          */
#endif
#if defined(OPTION_DYNAMIC_LOAD)
#define MAX_DLL_TO_LOAD         50
char   *dll_load[MAX_DLL_TO_LOAD];      /* Pointers to modnames      */
int     dll_count;                      /* index into array          */
#endif

    /* Seed the pseudo-random number generator */
    srand( time(NULL) );

    /* Clear the system configuration block */
    memset( &sysblk, 0, sizeof( SYSBLK ) );

    VERIFY( MLOCK( &sysblk, sizeof( SYSBLK )) == 0);

#if defined (_MSVC_)
    _setmaxstdio(2048);
#endif

    /* Initialize EYE-CATCHERS for SYSBLK       */
    memset(&sysblk.blknam,SPACE,sizeof(sysblk.blknam));
    memset(&sysblk.blkver,SPACE,sizeof(sysblk.blkver));
    memset(&sysblk.blkend,SPACE,sizeof(sysblk.blkend));
    sysblk.blkloc = swap_byte_U64((U64)((uintptr_t)&sysblk));
    memcpy(sysblk.blknam,HDL_NAME_SYSBLK,strlen(HDL_NAME_SYSBLK));
    memcpy(sysblk.blkver,HDL_VERS_SYSBLK,strlen(HDL_VERS_SYSBLK));
    sysblk.blksiz = swap_byte_U32((U32)sizeof(SYSBLK));
    {
        char buf[32];
        MSGBUF( buf, "END%13.13s", HDL_NAME_SYSBLK );

        memcpy(sysblk.blkend, buf, sizeof(sysblk.blkend));
    }

    /* Initialize SETMODE and set user authority */
    SETMODE(INIT);

#if defined(OPTION_DYNAMIC_LOAD)
    for ( dll_count = 0; dll_count < MAX_DLL_TO_LOAD; dll_count++ )
        dll_load[dll_count] = NULL;
    dll_count = -1;
#endif

    SET_THREAD_NAME("impl");

    /* Initialize 'hostinfo' BEFORE display_version is called */
    init_hostinfo( &hostinfo );

#ifdef _MSVC_
    /* Initialize sockets package */
    VERIFY( socket_init() == 0 );
#endif

    /* Ensure hdl_shut is called in case of shutdown
       hdl_shut will ensure entries are only called once */
    atexit(hdl_shut);

    if ( argc > 0 )
    {
        int i,len;

        for (len = 0, i = 0; i < argc; i++ )
            len += (int)strlen( (char *)argv[i] ) + 1;

        sysblk.hercules_cmdline = (char *)malloc( len );

        strlcpy( sysblk.hercules_cmdline, argv[0], len );
        for ( i = 1; i < argc; i++ )
        {
            strlcat( sysblk.hercules_cmdline, " ", len );
            strlcat( sysblk.hercules_cmdline, argv[i], len );
        }
    }

    /* Set program name */
    if ( argc > 0 )
    {
        if ( strlen(argv[0]) == 0 )
        {
            sysblk.hercules_pgmname = strdup("hercules");
            sysblk.hercules_pgmpath = strdup("");
        }
        else
        {
            char path[MAX_PATH];
#if defined( _MSVC_ )
            GetModuleFileName( NULL, path, MAX_PATH );
#else
            strncpy(path,argv[0],sizeof(path)-1);
#endif
            sysblk.hercules_pgmname = strdup(basename(path));
#if !defined( _MSVC_ )
            strncpy(path,argv[0],sizeof(path)-1);
#endif
            sysblk.hercules_pgmpath = strdup(dirname(path));
        }
    }
    else
    {
            sysblk.hercules_pgmname = strdup("hercules");
            sysblk.hercules_pgmpath = strdup("");
    }

#if defined( OPTION_CONFIG_SYMBOLS )

    /* These were moved from console.c to make them available sooner */
    set_symbol( "VERSION", VERSION);
    set_symbol( "BDATE", __DATE__ );
    set_symbol( "BTIME", __TIME__ );

    {
        char num_procs[64];

        if ( hostinfo.num_packages     != 0 &&
             hostinfo.num_physical_cpu != 0 &&
             hostinfo.num_logical_cpu  != 0 )
        {
            MSGBUF( num_procs, "LP=%d, Cores=%d, CPUs=%d", hostinfo.num_logical_cpu,
                                hostinfo.num_physical_cpu, hostinfo.num_packages );
        }
        else
        {
            if ( hostinfo.num_procs > 1 )
                MSGBUF( num_procs, "MP=%d", hostinfo.num_procs );
            else if ( hostinfo.num_procs == 1 )
                strlcpy( num_procs, "UP", sizeof(num_procs) );
            else
                strlcpy( num_procs,   "",  sizeof(num_procs) );
        }

        set_symbol( "HOSTNAME", hostinfo.nodename );
        set_symbol( "HOSTOS", hostinfo.sysname );
        set_symbol( "HOSTOSREL", hostinfo.release );
        set_symbol( "HOSTOSVER", hostinfo.version );
        set_symbol( "HOSTARCH", hostinfo.machine );
        set_symbol( "HOSTNUMCPUS", num_procs );
    }

    set_symbol( "MODNAME", sysblk.hercules_pgmname );
    set_symbol( "MODPATH", sysblk.hercules_pgmpath );

#endif // defined( OPTION_CONFIG_SYMBOLS )

    sysblk.sysgroup = DEFAULT_SYSGROUP;
    sysblk.msglvl   = DEFAULT_MLVL;                 /* Defaults to TERSE and DEVICES */

    /* set default console port address */
    sysblk.cnslport = strdup("3270");

    /* set default tape autoinit value to OFF   */
    sysblk.noautoinit = TRUE;

    /* default for system dasd cache is on */
    sysblk.dasdcache = TRUE;

#if defined(OPTION_MSGCLR) || defined(OPTION_MSGHLD)
    /* set default error message display (emsg) */
    sysblk.emsg = EMSG_ON;
#endif

#if defined( OPTION_SHUTDOWN_CONFIRMATION )
    /* set default quit timeout value (also ssd) */
    sysblk.quitmout = QUITTIME_PERIOD;
#endif

    /* Default command separator to off (NULL) */
    sysblk.cmdsep = NULL;

#if defined(_FEATURE_SYSTEM_CONSOLE)
    /* set default for scpecho to TRUE */
    sysblk.scpecho = TRUE;

    /* set fault for scpimply to FALSE */
    sysblk.scpimply = FALSE;
#endif

    /* set default system state to reset */
    sysblk.sys_reset = TRUE;

    /* set default SHCMDOPT enabled     */
    sysblk.shcmdopt = SHCMDOPT_ENABLE + SHCMDOPT_DIAG8;

    /* Save process ID */
    sysblk.hercules_pid = getpid();

    /* Save thread ID of main program */
    sysblk.impltid = thread_id();

    /* Save TOD of when we were first IMPL'ed */
    time( &sysblk.impltime );

    /* Set to LPAR mode with LPAR 1, LPAR ID of 01, and CPUIDFMT 0   */
    sysblk.lparmode = 1;                /* LPARNUM 1    # LPAR ID 01 */
    sysblk.lparnum = 1;                 /* ...                       */
    sysblk.cpuidfmt = 0;                /* CPUIDFMT 0                */
    sysblk.operation_mode = om_mif;     /* Default to MIF operaitons */

    /* set default CPU identifier */
    sysblk.cpumodel = 0x0586;
    sysblk.cpuversion = 0xFD;
    sysblk.cpuserial = 0x000001;
    sysblk.cpuid = createCpuId(sysblk.cpumodel, sysblk.cpuversion,
                               sysblk.cpuserial, 0);

    /* set default Program Interrupt Trace to NONE */
    sysblk.pgminttr = OS_NONE;

    sysblk.timerint = DEF_TOD_UPDATE_USECS;

    /* set default thread priorities */
    sysblk.hercprio = DEFAULT_HERCPRIO;
    sysblk.todprio  = DEFAULT_TOD_PRIO;
    sysblk.cpuprio  = DEFAULT_CPU_PRIO;
    sysblk.devprio  = DEFAULT_DEV_PRIO;
    sysblk.srvprio  = DEFAULT_SRV_PRIO;

    /* Cap the default priorities at zero if setuid not available */
#if !defined( _MSVC_ )
  #if !defined(NO_SETUID)
    if (sysblk.suid)
  #endif
    {
        if (sysblk.hercprio < 0)
            sysblk.hercprio = 0;
        if (sysblk.todprio < 0)
            sysblk.todprio = 0;
        if (sysblk.cpuprio < 0)
            sysblk.cpuprio = 0;
        if (sysblk.devprio < 0)
            sysblk.devprio = 0;
        if (sysblk.srvprio < 0)
            sysblk.srvprio = 0;
    }
#endif

    /* set default console keep alive values */
    sysblk.kaidle = KEEPALIVE_IDLE_TIME;
    sysblk.kaintv = KEEPALIVE_PROBE_INTERVAL;
    sysblk.kacnt  = KEEPALIVE_PROBE_COUNT;

#if defined(_FEATURE_ECPSVM)
    sysblk.ecpsvm.available = 0;
    sysblk.ecpsvm.level = 20;
#endif

#ifdef PANEL_REFRESH_RATE
    sysblk.panrate = PANEL_REFRESH_RATE_SLOW;
#endif

#if defined( OPTION_SHUTDOWN_CONFIRMATION )
    /* Set the quitmout value */
    sysblk.quitmout = QUITTIME_PERIOD;     /* quit timeout value        */
#endif

#if defined(OPTION_SHARED_DEVICES)
    sysblk.shrdport = 0;
#endif

#ifdef OPTION_MSGHLD
    /* Set the default timeout value */
    sysblk.keep_timeout_secs = 120;
#endif

#if defined(OPTION_CONFIG_SYMBOLS) && defined(OPTION_BUILTIN_SYMBOLS)
    /* setup defaults for BUILTIN symbols  */
    {
        char buf[8];

        set_symbol("LPARNAME", str_lparname());
        set_symbol("LPARNUM", "1");
        set_symbol("CPUIDFMT", "0");

        MSGBUF( buf, "%06X", sysblk.cpuserial );
        set_symbol( "CPUSERIAL", buf );

        MSGBUF( buf, "%04X", sysblk.cpumodel );
        set_symbol( "CPUMODEL", buf );

    }
#endif /* defined(OPTION_CONFIG_SYMBOLS) && defined(OPTION_BUILTIN_SYMBOLS */

#if defined(_FEATURE_CMPSC_ENHANCEMENT_FACILITY)
    sysblk.zpbits  = DEF_CMPSC_ZP_BITS;
#endif

    /* Initialize locks, conditions, and attributes */
    initialize_lock (&sysblk.config);
    initialize_lock (&sysblk.todlock);
    initialize_lock (&sysblk.mainlock);
    sysblk.mainowner = LOCK_OWNER_NONE;
    initialize_lock (&sysblk.intlock);
    initialize_lock (&sysblk.iointqlk);
    sysblk.intowner = LOCK_OWNER_NONE;
    initialize_lock (&sysblk.sigplock);
    initialize_lock (&sysblk.mntlock);
    initialize_lock (&sysblk.scrlock);
    initialize_lock (&sysblk.crwlock);
    initialize_lock (&sysblk.ioqlock);
    initialize_condition (&sysblk.ioqcond);
#if defined(OPTION_CMDSER)
    initialize_lock      (&sysblk.cmdlock);
    initialize_condition (&sysblk.cmdcond);
#endif /*defined(OPTION_CMDSER)*/

#ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_3
    /* Initialize the wrapping key registers lock */
    initialize_rwlock(&sysblk.wklock);
#endif

    /* Initialize thread creation attributes so all of hercules
       can use them at any time when they need to create_thread
    */
    initialize_detach_attr (DETACHED);
    initialize_join_attr   (JOINABLE);

    initialize_condition (&sysblk.cpucond);
    {
        int i;
        for (i = 0; i < MAX_CPU_ENGINES; i++)
            initialize_lock (&sysblk.cpulock[i]);
    }
    initialize_condition (&sysblk.sync_cond);
    initialize_condition (&sysblk.sync_bc_cond);

    /* Copy length for regs */
    sysblk.regs_copy_len = (int)((uintptr_t)&sysblk.dummyregs.regs_copy_end
                               - (uintptr_t)&sysblk.dummyregs);

    /* Set the daemon_mode flag indicating whether we running in
       background/daemon mode or not (meaning both stdout/stderr
       are redirected to a non-tty device). Note that this flag
       needs to be set before logger_init gets called since the
       logger_logfile_write function relies on its setting.
    */
    sysblk.daemon_mode = !isatty(STDERR_FILENO) && !isatty(STDOUT_FILENO);

    /* Initialize the logmsg pipe and associated logger thread.
       This causes all subsequent logmsg's to be redirected to
       the logger facility for handling by virtue of stdout/stderr
       being redirected to the logger facility.
    */
    logger_init();

    /*
       Setup the initial codepage
    */
    set_codepage(NULL);

    /* Now display the version information again after logger_init
       has been called so that either the panel display thread or the
       external gui can see the version which was previously possibly
       only displayed to the actual physical screen the first time we
       did it further above (depending on whether we're running in
       daemon_mode (external gui mode) or not). This it the call that
       the panel thread or the one the external gui actually "sees".
       The first call further above wasn't seen by either since it
       was issued before logger_init was called and thus got written
       directly to the physical screen whereas this one will be inter-
       cepted and handled by the logger facility thereby allowing the
       panel thread or external gui to "see" it and thus display it.
    */
    display_version (stdout, "Hercules", TRUE);

#ifdef EXTERNALGUI
    if (argc >= 1 && strncmp(argv[argc-1],"EXTERNALGUI",11) == 0)
    {
        e_gui = TRUE;
        argc--;
    }
#endif

#if !defined(WIN32) && !defined(HAVE_STRERROR_R)
    strerror_r_init();
#endif

#if defined(OPTION_SCSI_TAPE)
    initialize_lock      ( &sysblk.stape_lock         );
    initialize_condition ( &sysblk.stape_getstat_cond );
    InitializeListHead   ( &sysblk.stape_mount_link   );
    InitializeListHead   ( &sysblk.stape_status_link  );
#endif /* defined(OPTION_SCSI_TAPE) */

    /* Get name of configuration file or default to hercules.cnf */
    if(!(cfgfile = getenv("HERCULES_CNF")))
        cfgfile = "hercules.cnf";

    /* Process the command line options */
    {
#define  HERCULES_BASE_OPTS     "hf:r:db:v"
#define  HERCULES_SYM_OPTS      ""
#define  HERCULES_HDL_OPTS      ""
#if defined(OPTION_CONFIG_SYMBOLS)
#undef   HERCULES_SYM_OPTS
#define  HERCULES_SYM_OPTS      "s:"
#endif
#if defined(OPTION_DYNAMIC_LOAD)
#undef   HERCULES_HDL_OPTS
#define  HERCULES_HDL_OPTS      "p:l:"
#endif
#define  HERCULES_OPTS_STRING   HERCULES_BASE_OPTS  HERCULES_SYM_OPTS  HERCULES_HDL_OPTS

#if defined(HAVE_GETOPT_LONG)
    static struct option longopts[] =
    {
        { "help",     no_argument,       NULL, 'h' },
        { "config",   required_argument, NULL, 'f' },
        { "rcfile",   required_argument, NULL, 'r' },
        { "daemon",   no_argument,       NULL, 'd' },
        { "herclogo", required_argument, NULL, 'b' },
        { "verbose",  no_argument,       NULL, 'v' },
#if defined(OPTION_CONFIG_SYMBOLS)
        { "defsym",   required_argument, NULL, 's' },
#endif
#if defined(OPTION_DYNAMIC_LOAD)
        { "modpath",  required_argument, NULL, 'p' },
        { "ldmod",    required_argument, NULL, 'l' },
#endif
        { NULL,       0,                 NULL,  0  }
    };
    while ((c = getopt_long( argc, argv, HERCULES_OPTS_STRING, longopts, NULL )) != EOF)
#else
    while ((c = getopt( argc, argv, HERCULES_OPTS_STRING )) != EOF)
#endif
    {
        switch (c) {
        case 'h':
            arg_error = 1;
            break;
        case 'f':
            cfgfile = optarg;
            break;
        case 'r':
            rcname = optarg;
            break;
#if defined(OPTION_CONFIG_SYMBOLS)
        case 's':
            {
            char *sym        = NULL;
            char *value      = NULL;
            char *strtok_str = NULL;
                if ( strlen( optarg ) >= 3 )
                {
                    sym   = strtok_r( optarg, "=", &strtok_str);
                    value = strtok_r( NULL,   "=", &strtok_str);
                    if ( sym != NULL && value != NULL )
                    {
                    int j;
                        for( j = 0; j < (int)strlen( sym ); j++ )
                            if ( islower( sym[j] ) )
                            {
                                sym[j] = toupper( sym[j] );
                            }
                        set_symbol(sym, value);
                    }
                    else
                        WRMSG(HHC01419, "E" );
                }
                else
                    WRMSG(HHC01419, "E");
            }
            break;
#endif /* defined(OPTION_CONFIG_SYMBOLS) */
#if defined(OPTION_DYNAMIC_LOAD)
        case 'p':
            if(optarg)
                hdl_setpath(strdup(optarg), FALSE);
            break;
        case 'l':
            {
            char *dllname, *strtok_str = NULL;
                for(dllname = strtok_r(optarg,", ",&strtok_str);
                    dllname;
                    dllname = strtok_r(NULL,", ",&strtok_str))
                {
                    if (dll_count < MAX_DLL_TO_LOAD - 1)
                        dll_load[++dll_count] = strdup(dllname);
                    else
                    {
                        WRMSG(HHC01406, "W", MAX_DLL_TO_LOAD);
                        break;
                    }
                }
            }
            break;
#endif /* defined(OPTION_DYNAMIC_LOAD) */
        case 'b':
            sysblk.logofile = optarg;
            break;
        case 'v':
            sysblk.msglvl |= MLVL_VERBOSE;
            break;
        case 'd':
            sysblk.daemon_mode = 1;
            break;
        default:
            arg_error = 1;

        } /* end switch(c) */
    } /* end while */
    } /* end Process the command line options */

    /* Treat filename None as special */
    if(!strcasecmp(cfgfile,"None"))
        cfgfile = NULL;

    if (optind < argc)
        arg_error = 1;

    /* Terminate if invalid arguments were detected */
    if (arg_error)
    {
        char pgm[MAX_PATH];
        char* strtok_str = NULL;
        strncpy(pgm, sysblk.hercules_pgmname, sizeof(pgm));

        /* Show them all of our command-line arguments... */

        WRMSG (HHC01414, "S", "");   // (blank line)
        WRMSG (HHC01414, "S", "");   // (blank line)

#if defined(OPTION_DYNAMIC_LOAD)
        // "Usage: %s [-f config-filename] [-d] [-b logo-filename] [-s sym=val]%s [> logfile]"
        WRMSG (HHC01407, "S", strtok_r(pgm,".",&strtok_str),
                             " [-p dyn-load-dir] [[-l dynmod-to-load]...]");
#else
        WRMSG (HHC01407, "S", strtok_r(pgm,".", &strtok_str), "");
#endif /* defined(OPTION_DYNAMIC_LOAD) */

        WRMSG (HHC01414, "S", "");   // (blank line)
        WRMSG (HHC01414, "S", "");   // (blank line)

        fflush(stderr);
        fflush(stdout);
        usleep(100000);
        return(1);
    }

    /* Initialize runtime opcode tables */
    init_opcode_tables();

#if defined(OPTION_DYNAMIC_LOAD)
    /* Initialize the hercules dynamic loader */
    hdl_main();

    /* Load modules requested at startup */
    if (dll_count >= 0)
    {
        int hl_err = FALSE;
        for ( dll_count = 0; dll_count < MAX_DLL_TO_LOAD; dll_count++ )
        {
            if (dll_load[dll_count] != NULL)
            {
                if (hdl_load(dll_load[dll_count], HDL_LOAD_DEFAULT) != 0)
                {
                    hl_err = TRUE;
                }
                free(dll_load[dll_count]);
            }
            else
                break;
        }

        if (hl_err)
        {
            usleep(10000);      // give logger time to issue error message
            WRMSG(HHC01408, "S");
            delayed_exit(-1);
            return(1);
        }

    }
#endif /* defined(OPTION_DYNAMIC_LOAD) */

#ifdef EXTERNALGUI
    /* Set GUI flag if specified as final argument */
    if (e_gui)
    {
#if defined(OPTION_DYNAMIC_LOAD)
        if (hdl_load("dyngui",HDL_LOAD_DEFAULT) != 0)
        {
            usleep(10000); /* (give logger thread time to issue
                               preceding HHC01516E message) */
            WRMSG(HHC01409, "S");
            delayed_exit(-1);
            return(1);
        }
#endif /* defined(OPTION_DYNAMIC_LOAD) */
    }
#endif /*EXTERNALGUI*/

    /* Register the SIGINT handler */
    if ( signal (SIGINT, sigint_handler) == SIG_ERR )
    {
        WRMSG(HHC01410, "S", "SIGINT", strerror(errno));
        delayed_exit(-1);
        return(1);
    }

    /* Register the SIGTERM handler */
    if ( signal (SIGTERM, sigterm_handler) == SIG_ERR )
    {
        WRMSG(HHC01410, "S", "SIGTERM", strerror(errno));
        delayed_exit(-1);
        return(1);
    }

#if defined( _MSVC_ )
    /* Register the Window console ctrl handlers */
    if (!IsDebuggerPresent())
    {
        if (!SetConsoleCtrlHandler( console_ctrl_handler, TRUE ))
        {
            WRMSG( HHC01410, "S", "Console-ctrl", strerror( errno ));
            delayed_exit(-1);
            return(1);
        }
    }
#endif

#if defined(HAVE_DECL_SIGPIPE) && HAVE_DECL_SIGPIPE
    /* Ignore the SIGPIPE signal, otherwise Hercules may terminate with
       Broken Pipe error if the printer driver writes to a closed pipe */
    if ( signal (SIGPIPE, SIG_IGN) == SIG_ERR )
    {
        WRMSG(HHC01411, "E", strerror(errno));
    }
#endif

    {
        int fds[2];
        initialize_lock(&sysblk.cnslpipe_lock);
        initialize_lock(&sysblk.sockpipe_lock);
        sysblk.cnslpipe_flag=0;
        sysblk.sockpipe_flag=0;
        VERIFY( create_pipe(fds) >= 0 );
        sysblk.cnslwpipe=fds[1];
        sysblk.cnslrpipe=fds[0];
        VERIFY( create_pipe(fds) >= 0 );
        sysblk.sockwpipe=fds[1];
        sysblk.sockrpipe=fds[0];
    }

#if !defined(NO_SIGABEND_HANDLER)
    {
    struct sigaction sa;
        sa.sa_sigaction = (void*)&sigabend_handler;
#ifdef SA_NODEFER
        sa.sa_flags = SA_NODEFER;
#else
        sa.sa_flags = 0;
#endif

        if( sigaction(SIGILL, &sa, NULL)
         || sigaction(SIGFPE, &sa, NULL)
         || sigaction(SIGSEGV, &sa, NULL)
         || sigaction(SIGBUS, &sa, NULL)
         || sigaction(SIGUSR1, &sa, NULL)
         || sigaction(SIGUSR2, &sa, NULL) )
        {
            WRMSG(HHC01410, "S", "SIGILL/FPE/SEGV/BUS/USR", strerror(errno));
            delayed_exit(-1);
            return(1);
        }
    }
#endif /*!defined(NO_SIGABEND_HANDLER)*/

    if(cfgfile)
    {
        /* attempt to get lock on config file */
        hostpath(pathname, cfgfile, sizeof(pathname));

#if defined( OPTION_LOCK_CONFIG_FILE )

        /* Test that we can get a read the file */

        if ( ( fd_cfg = HOPEN( pathname, O_RDONLY, S_IRUSR | S_IRGRP ) ) < 0 )
        {
            if ( errno == EACCES )
            {
                WRMSG( HHC01453, "S", cfgfile, strerror( errno ) );
                delayed_exit(-1);
                return(1);
            }
        }
        else
        {
            if ( lseek(fd_cfg, 0L, 2) < 0 )
            {
                if ( errno == EACCES )
                {
                    WRMSG( HHC01453, "S", cfgfile, strerror( errno ) );
                    delayed_exit(-1);
                    return(1);
                }
            }
            close( fd_cfg );
        }

        /* File was not lock, therefore we can proceed */
#endif // OPTION_LOCK_CONFIG_FILE
    }

    /* System initialisation time */
    sysblk.todstart = hw_clock() << 8;

#if !defined(NO_SIGABEND_HANDLER)
    /* Start the watchdog */
    rc = create_thread (&sysblk.wdtid, DETACHED,
                        watchdog_thread, NULL, "watchdog_thread");
    if (rc)
    {
        WRMSG(HHC00102, "E", strerror(rc));
        delayed_exit(-1);
        return(1);
    }
#endif /*!defined(NO_SIGABEND_HANDLER)*/

    if(log_callback)
    {
        // 'herclin' called us. IT'S in charge. Create its requested
        // logmsg intercept callback function and return back to it.
        rc = create_thread(&logcbtid,DETACHED,
                      log_do_callback,NULL,"log_do_callback");
        if (rc)
            WRMSG(HHC00102, "E", strerror(rc));
        return(0);
    }

    hdl_adsc("release_config", release_config, NULL);

    /* Build system configuration */
    if ( build_config (cfgfile) )
    {
        delayed_exit(-1);
        return(1);
    }

    /* Start up the RC file processing thread */
    rc = create_thread(&rctid,DETACHED,
                  process_rc_file,NULL,"process_rc_file");
    if (rc)
        WRMSG(HHC00102, "E", strerror(rc));


#if defined( OPTION_LOCK_CONFIG_FILE )
    if(cfgfile)
    {
        if ( ( fd_cfg = HOPEN( pathname, O_RDONLY, S_IRUSR | S_IRGRP ) ) < 0 )
        {
            WRMSG( HHC01432, "S", pathname, "open()", strerror( errno ) );
            delayed_exit(-1);
            return(1);
        }
        else
        {
#if defined( _MSVC_ )
            if( ( rc = _locking( fd_cfg, _LK_NBRLCK, 1L ) ) < 0 )
            {
                int rc = errno;
                WRMSG( HHC01454, "S", pathname, "_locking()", strerror( errno ) );
                delayed_exit(-1);
                return(1);
            }
#else
            fl_cfg.l_type = F_RDLCK;
            fl_cfg.l_whence = SEEK_SET;
            fl_cfg.l_start = 0;
            fl_cfg.l_len = 1;

            if ( fcntl(fd_cfg, F_SETLK, &fl_cfg) == -1 )
            {
                if (errno == EACCES || errno == EAGAIN)
                {
                    WRMSG( HHC01432, "S", pathname, "fcntl()", strerror( errno ) );
                    delayed_exit(-1);
                    return(1);
                }
            }
#endif
        }
    }
#endif // OPTION_LOCK_CONFIG_FILE

    //---------------------------------------------------------------
    // The below functions will not return until Hercules is shutdown
    //---------------------------------------------------------------

    /* Activate the control panel */
    if(!sysblk.daemon_mode)
        panel_display ();
    else
    {
#if defined(OPTION_DYNAMIC_LOAD)
        if(daemon_task)
            daemon_task ();
        else
#endif /* defined(OPTION_DYNAMIC_LOAD) */
        {
            /* Tell RC file and HAO threads they may now proceed */
            sysblk.panel_init = 1;

            /* Retrieve messages from logger and write to stderr */
            while (1)
                if((msgcnt = log_read(&msgbuf, &msgnum, LOG_BLOCK)))
                    if(isatty(STDERR_FILENO))
                        fwrite(msgbuf,msgcnt,1,stderr);
        }
    }

    //  -----------------------------------------------------
    //      *** Hercules has been shutdown (PAST tense) ***
    //  -----------------------------------------------------

#if defined( OPTION_LOCK_CONFIG_FILE )
    if(cfgfile)
        close( fd_cfg );            // release config file lock
#endif //    OPTION_LOCK_CONFIG_FILE

    ASSERT( sysblk.shutdown );  // (why else would we be here?!)

#ifdef _MSVC_
    SetConsoleCtrlHandler(console_ctrl_handler, FALSE);
    socket_deinit();
#endif
#if defined(OPTION_MSGCLR) || defined(OPTION_MSGHLD)
    if ( sysblk.emsg & EMSG_TEXT )
        fprintf(stdout, HHC01412 );
    else
#endif
        fprintf(stdout, MSG(HHC01412, "I"));
    fflush(stdout);
    usleep(10000);
    return 0;
} /* end function impl */
Example #15
0
/*-------------------------------------------------------------------*/
DLL_EXPORT int
fet_open ( FETB **fetb, char *filename, int flags )
{
int             rc = -1;                /* Return code               */
char            pathname[MAX_PATH];     /* file path in host format  */
FETB           *tfetb;
char           *omode;
int             oflags;


    /* Open the FAKETAPE file */
    *fetb = NULL;

    hostpath(pathname, filename, sizeof(pathname));

    /*
    || Allocate a new FETB
    */
    tfetb = calloc( 1, sizeof( FETB ) );
    if( tfetb == NULL )
    {
        return( FETE_NOMEM );
    }

    /* Initialize FETB */
    tfetb->fd = -1;

    /*
    || clear FETOPEN_CREATE if FETOPEN_READONLY is specified
    */
    if(flags & FETOPEN_READONLY)
    {
        flags&=~FETOPEN_CREATE;
    }
    /*
    || Translate HET create flag to filesystem flag
    */
    oflags = ( ( flags & FETOPEN_CREATE ) ? O_CREAT : 0 );

    omode = "r+b";
    if( !( flags & FETOPEN_READONLY ) )
    {
        tfetb->fd = HOPEN( pathname, O_RDWR | O_BINARY | oflags, S_IRUSR | S_IWUSR | S_IRGRP );
    }

    /* If file is read-only, attempt to open again */
    if ( ( flags & FETOPEN_READONLY ) || (tfetb->fd < 0 && (EROFS == errno || EACCES == errno)))
    {
        omode = "rb";
        tfetb->writeprotect = TRUE;
        tfetb->fd = HOPEN( pathname, O_RDONLY | O_BINARY, S_IRUSR | S_IRGRP );
    }

    /*
    || Error out if both opens failed
    */
    if( tfetb->fd == -1 )
    {
        free( tfetb );
        return( FETE_ERROR );
    }

    /*
    || Associate stream with file descriptor
    */
    tfetb->fh = fdopen( tfetb->fd, omode );

    if( tfetb->fh == NULL )
    {
        rc = errno;
        close( tfetb->fd );
        errno = rc;
        free( tfetb );
        return( FETE_ERROR );
    }

    /*
    || If uninitialized tape, write 2 tapemarks to make it a valid NL tape
    */
    rc = fet_read_header( tfetb, 0L, NULL, NULL );
    if( rc < 0 && rc != FETE_TAPEMARK )
    {
        if( rc != FETE_EOT )
        {
            return( rc );
        }

        rc = fet_tapemark( tfetb );
        if( rc < 0 )
        {
            return( rc );
        }

        rc = fet_tapemark( tfetb );
        if( rc < 0 )
        {
            return( rc );
        }

        tfetb->created = TRUE;
    }
    else
        tfetb->created = FALSE;

    /*
    || Reposition tape to load point
    */
    rc = fet_rewind( tfetb );
    if( rc < 0 )
    {
        return( rc );
    }

    /*
    || Give the caller the new FETB
    */
    *fetb = tfetb;

    return( 0 );

} /* end function fet_open */
Example #16
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(load_main) (char *fname, RADR startloc, int noisy)
{
U64 loaded;
RADR aaddr;
RADR pageaddr;
int fd;
size_t chunk;
int bytes;
time_t begtime, curtime;
char fmt_mem[8];

    fd = HOPEN (fname, O_RDONLY|O_BINARY);
    if (fd < 0)
    {
        if(errno != ENOENT)
            WRMSG(HHC00600,"E",fname,"open()",strerror(errno));
        return fd;
    }

    /* Calculate size of first chunk to reach page boundary */
    chunk = PAGEFRAME_PAGESIZE - (startloc & PAGEFRAME_BYTEMASK);
    aaddr = startloc;

    if (noisy)
    {
        loaded = 0;
        time( &begtime );
    }

    /* Read file into storage until end of file or end of storage */
    for( ; ; ) {

        bytes = read(fd, sysblk.mainstor + aaddr, chunk);

        /* Check for I/O error */
        if (bytes < 0)
        {
            // "SCE file %s: error in function %s: %s"
            WRMSG(HHC00600, "E", fname, "read()",strerror(errno));
            close(fd);
            return -1;
        }

        /* Check for end-of-file */
        if (bytes == 0)
        {
            close(fd);
            return 0;
        }

        /* Update the storage keys for all of the pages we just read */
        chunk = bytes;
        pageaddr = aaddr;

        for ( ; chunk > 0; chunk -= PAGEFRAME_PAGESIZE)
        {
            STORAGE_KEY(pageaddr, &sysblk) |= STORKEY_REF|STORKEY_CHANGE;
            pageaddr += PAGEFRAME_PAGESIZE;
        }

        aaddr += bytes;
        aaddr &= PAGEFRAME_PAGEMASK;

        /* Check if end of storge reached */
        if (aaddr >= sysblk.mainsize)
        {
            int rc;
            if (read(fd, &rc, 1) > 0)
            {
                rc = +1;
                if (noisy)
                {
                    // "SCE file %s: load main terminated at end of mainstor"
                    WRMSG(HHC00603, "W", fname);
                }
            }
            else /* ignore any error; we're at end of storage anyway */
                rc = 0;
            close(fd);
            return rc;
        }

        /* Issue periodic progress messages */
        if (noisy)
        {
            loaded += bytes;
            time( &curtime );

            if (difftime( curtime, begtime ) > 2.0)
            {
                begtime = curtime;
                // "%s bytes %s so far..."
                WRMSG( HHC02317, "I",
                    fmt_memsize_rounded( loaded, fmt_mem, sizeof( fmt_mem )),
                        "loaded" );
            }
        }

        chunk = (64 * 1024 * 1024);

        if (chunk > (sysblk.mainsize - aaddr))
            chunk = (sysblk.mainsize - aaddr);

    } /* end for( ; ; ) */

} /* end function load_main */
Example #17
0
/*-------------------------------------------------------------------*/
static S64 ARCH_DEP(write_file)(char *fname, int mode, CREG sto, S64 size)
{
int fd, nwrite;
U64 totwrite = 0;

    fd = HOPEN (fname, mode |O_WRONLY|O_BINARY,
            S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    if (fd < 0)
    {
        WRMSG (HHC00600, "E", fname, "open()", strerror(errno));
        return -1;
    }

#if defined(FEATURE_ESAME)
    sto &= ASCE_TO;
#else /*!defined(FEATURE_ESAME)*/
    sto &= STD_STO;
#endif /*!defined(FEATURE_ESAME)*/

    for( ; size > 0 ; sto += sizeof(sto))
    {
#if defined(FEATURE_ESAME)
    DBLWRD *ste;
#else /*!defined(FEATURE_ESAME)*/
    FWORD *ste;
#endif /*!defined(FEATURE_ESAME)*/
    CREG pto, pti;

        /* Fetch segment table entry and calc Page Table Origin */
        if( sto >= sysblk.mainsize)
            goto eof;
#if defined(FEATURE_ESAME)
        ste = (DBLWRD*)(sysblk.mainstor + sto);
#else /*!defined(FEATURE_ESAME)*/
        ste = (FWORD*)(sysblk.mainstor + sto);
#endif /*!defined(FEATURE_ESAME)*/
        FETCH_W(pto, ste);
        STORAGE_KEY(sto, &sysblk) |= (STORKEY_REF);
        if( pto & SEGTAB_INVALID )
            goto eof;
#if defined(FEATURE_ESAME)
        pto &= ZSEGTAB_PTO;
#else /*!defined(FEATURE_ESAME)*/
        pto &= SEGTAB_PTO;
#endif /*!defined(FEATURE_ESAME)*/

        for(pti = 0; pti < 256 && size > 0; pti++, pto += sizeof(pto))
        {
#if defined(FEATURE_ESAME)
        DBLWRD *pte;
#else /*!defined(FEATURE_ESAME)*/
        FWORD *pte;
#endif /*!defined(FEATURE_ESAME)*/
        CREG pgo;
        BYTE *page;

            /* Fetch Page Table Entry to get page origin */
            if( pto >= sysblk.mainsize)
                goto eof;

#if defined(FEATURE_ESAME)
            pte = (DBLWRD*)(sysblk.mainstor + pto);
#else /*!defined(FEATURE_ESAME)*/
            pte = (FWORD*)(sysblk.mainstor + pto);
#endif /*!defined(FEATURE_ESAME)*/
            FETCH_W(pgo, pte);
            STORAGE_KEY(pto, &sysblk) |= (STORKEY_REF);
            if( !(pgo & PAGETAB_INVALID) )
            {
#if defined(FEATURE_ESAME)
                pgo &= ZPGETAB_PFRA;
#else /*!defined(FEATURE_ESAME)*/
                pgo &= PAGETAB_PFRA;
#endif /*!defined(FEATURE_ESAME)*/

                /* Write page to SCE disk */
                if( pgo >= sysblk.mainsize)
                    goto eof;

                page = sysblk.mainstor + pgo;
                nwrite = write(fd, page, STORAGE_KEY_PAGESIZE);
                totwrite += nwrite;
                if( nwrite != STORAGE_KEY_PAGESIZE )
                    goto eof;

                STORAGE_KEY(pgo, &sysblk) |= (STORKEY_REF);
            }
            size -= STORAGE_KEY_PAGESIZE;
        }
    }
eof:
    close(fd);
    return totwrite;
}
Example #18
0
/*-------------------------------------------------------------------*/
int main (int argc, char *argv[])
{
char           *pgmname;                /* prog name in host format  */
char           *pgm;                    /* less any extension (.ext) */
char            msgbuf[512];            /* message build work area   */
int             cckd_diag_rc = 0;       /* Program return code       */
char           *fn;                     /* File name                 */

CKDDASD_DEVHDR  devhdr;                 /* [C]CKD device hdr         */
CCKDDASD_DEVHDR cdevhdr;                /* Compressed CKD device hdr */
CKDDEV         *ckd=0;                  /* CKD DASD table entry      */
FBADEV         *fba=0;                  /* FBA DASD table entry      */

int             cmd_devhdr = 0;         /* display DEVHDR            */
int             cmd_cdevhdr = 0;        /* display CDEVHDR           */
int             cmd_l1tab = 0;          /* display L1TAB             */
int             cmd_l2tab = 0;          /* display L2TAB             */
int             cmd_trkdata = 0;        /* display track data        */
int             cmd_hexdump = 0;        /* display track data (hex)  */

int             cmd_offset = 0;         /* 1 = display data at       */
int             op_offset = 0;          /* op_offset of length       */
int             op_length = 0;          /* op_length                 */

int             cmd_cchh = 0;           /* 1 = display CCHH data     */
int             op_cc = 0;              /* CC = cylinder             */
int             op_hh = 0;              /* HH = head                 */

int             cmd_tt = 0;             /* 1 = display TT data       */
int             op_tt = 0;              /* relative track #          */

int             swapend;                /* 1 = New endianess doesn't
                                             match machine endianess */
int             n, trk=0, l1ndx=0, l2ndx=0;
off_t           l2taboff=0;             /* offset to assoc. L2 table */
int             ckddasd;                /* 1=CKD dasd  0=FBA dasd    */
int             heads=0;                /* Heads per cylinder        */
off_t           trkhdroff=0;            /* offset to assoc. trk hdr  */
int             imglen=0;               /* track length              */
char            pathname[MAX_PATH];     /* file path in host format  */
char           *strtok_str = NULL;

    /* Set program name */
    if ( argc > 0 )
    {
        if ( strlen(argv[0]) == 0 )
        {
            pgmname = strdup( UTILITY_NAME );
        }
        else
        {
            char path[MAX_PATH];
#if defined( _MSVC_ )
            GetModuleFileName( NULL, path, MAX_PATH );
#else
            strncpy( path, argv[0], sizeof( path ) );
#endif
            pgmname = strdup(basename(path));
#if !defined( _MSVC_ )
            strncpy( path, argv[0], sizeof(path) );
#endif
        }
    }
    else
    {
        pgmname = strdup( UTILITY_NAME );
    }

    pgm = strtok_r( strdup(pgmname), ".", &strtok_str);
    INITIALIZE_UTILITY( pgmname );

    /* Display the program identification message */
    MSGBUF( msgbuf, MSG_C( HHC02499, "I", pgm, "CCKD diagnostic program" ) );
    display_version (stderr, msgbuf+10, FALSE);

    /* parse the arguments */
    argc--;
    argv++ ;
    while (argc > 0) {
        if(**argv != '-') break;

        switch(argv[0][1]) {
            case 'v':  if (argv[0][2] != '\0') return syntax (pgm);
                       return 0;
            case 'd':  if (argv[0][2] != '\0') return syntax (pgm);
                       cmd_devhdr = 1;
                       break;
            case 'c':  if (argv[0][2] != '\0') return syntax (pgm);
                       cmd_cdevhdr = 1;
                       break;
            case '1':  if (argv[0][2] != '\0') return syntax (pgm);
                       cmd_l1tab = 1;
                       break;
            case '2':  if (argv[0][2] != '\0') return syntax (pgm);
                       cmd_l2tab = 1;
                       break;
            case 'a':  if (argv[0][2] != '\0') return syntax (pgm);
                       cmd_cchh = 1;
                       argc--; argv++;
                       op_cc = offtify(*argv);
                       argc--; argv++;
                       op_hh = offtify(*argv);
                       break;
            case 'r':  if (argv[0][2] != '\0') return syntax (pgm);
                       cmd_tt = 1;
                       argc--; argv++;
                       op_tt = offtify(*argv);
                       break;
            case 'o':  if (argv[0][2] != '\0') return syntax (pgm);
                       cmd_offset = 1;
                       argc--;
                       argv++;
                       op_offset = offtify(*argv);
                       argc--;
                       argv++;
                       op_length = offtify(*argv);
                       break;
            case 't':  if (argv[0][2] != '\0') return syntax (pgm);
                       cmd_trkdata = 1;
                       break;
            case 'x':  if (argv[0][2] != '\0') return syntax (pgm);
                       cmd_hexdump = 1;
                       cmd_trkdata = 1;
                       break;
            case 'g':  if (argv[0][2] != '\0') return syntax (pgm);
                       debug = 1;
                       break;
            default:   return syntax (pgm);
        }
        argc--;
        argv++;
    }
    if (argc != 1) return syntax (pgm);
    fn = argv[0];

    /* open the file */
    hostpath(pathname, fn, sizeof(pathname));
    fd = HOPEN(pathname, O_RDONLY | O_BINARY);
    if (fd < 0) {
        fprintf(stderr,
                _("cckddiag: error opening file %s: %s\n"),
                fn, strerror(errno));
        return -1;
    }

    /*---------------------------------------------------------------*/
    /* display DEVHDR - first 512 bytes of dasd image                */
    /*---------------------------------------------------------------*/
    readpos(fd, &devhdr, 0, sizeof(devhdr));
    if (cmd_devhdr) {
        fprintf(stderr, "\nDEVHDR - %d (decimal) bytes:\n",
                (int)sizeof(devhdr));
        data_dump(&devhdr, sizeof(devhdr));
    }

    /*---------------------------------------------------------------*/
    /* Determine CKD or FBA device type                              */
    /*---------------------------------------------------------------*/
    if (memcmp(devhdr.devid, "CKD_C370", 8) == 0
       || memcmp(devhdr.devid, "CKD_S370", 8) == 0) {
        ckddasd = 1;
        ckd = dasd_lookup(DASD_CKDDEV, NULL, devhdr.devtype, 0);
        if (ckd == NULL) {
            fprintf(stderr,
                    "DASD table entry not found for devtype 0x%2.2X\n",
                    devhdr.devtype);
            clean();
            exit(5);
        }
    }
    else
        if (memcmp(devhdr.devid, "FBA_C370", 8) == 0
           || memcmp(devhdr.devid, "FBA_S370", 8) == 0) {
        ckddasd = 0;
        fba = dasd_lookup(DASD_FBADEV, NULL, devhdr.devtype, 0);
        if (fba == NULL) {
            fprintf(stderr,
                    "DASD table entry not found for "
                    "devtype 0x%2.2X\n",
                    DEFAULT_FBA_TYPE);
            clean();
            exit(6);
        }
    }
    else {
        fprintf(stderr, "incorrect header id\n");
        clean();
        return -1;
    }

    /*---------------------------------------------------------------*/
    /* Set up device characteristics                                 */
    /*---------------------------------------------------------------*/
    if (ckddasd) {
        heads = ((U32)(devhdr.heads[3]) << 24)
              | ((U32)(devhdr.heads[2]) << 16)
              | ((U32)(devhdr.heads[1]) << 8)
              | (U32)(devhdr.heads[0]);
        if (debug)
            fprintf(stderr,
                "\nHHC90000D DBG: %s device has %d heads/cylinder\n",
                ckd->name, heads);
    } 


    /*---------------------------------------------------------------*/
    /* display CDEVHDR - follows DEVHDR                              */
    /*---------------------------------------------------------------*/
    readpos(fd, &cdevhdr, CKDDASD_DEVHDR_SIZE, sizeof(cdevhdr));
    if (cmd_cdevhdr) {
        fprintf(stderr, "\nCDEVHDR - %d (decimal) bytes:\n",
                (int)sizeof(cdevhdr));
        data_dump(&cdevhdr, sizeof(cdevhdr));
    }

    /*---------------------------------------------------------------*/
    /* Find machine endian-ness                                      */
    /*---------------------------------------------------------------*/
    /* cckd_endian() returns 1 for big-endian machines               */
    swapend = (cckd_endian() !=
               ((cdevhdr.options & CCKD_BIGENDIAN) != 0));

    /*---------------------------------------------------------------*/
    /* display L1TAB - follows CDEVHDR                               */
    /*---------------------------------------------------------------*/
    /* swap numl1tab if needed */
    n = cdevhdr.numl1tab;
    if (swapend) cckd_swapend4((char *)&n);

    l1 = makbuf(n * CCKD_L1ENT_SIZE, "L1TAB");
    readpos(fd, l1, CCKD_L1TAB_POS, n * CCKD_L1ENT_SIZE);
    /* L1TAB itself is not adjusted for endian-ness                  */
    if (cmd_l1tab) {
        fprintf(stderr, "\nL1TAB - %d (0x%X) bytes:\n",
                (int)(n * CCKD_L1ENT_SIZE), (unsigned int)(n * CCKD_L1ENT_SIZE));
        data_dump(l1, n * CCKD_L1ENT_SIZE);
    }

    /*---------------------------------------------------------------*/
    /* display OFFSET, LENGTH data                                   */
    /*---------------------------------------------------------------*/
    if (cmd_offset) {
        bulk = makbuf(op_length, "BULK");
        readpos(fd, bulk, op_offset, op_length);
        fprintf(stderr,
            "\nIMAGE OFFSET %d (0x%8.8X) "
            "of length %d (0x%8.8X) bytes:\n",
            op_offset, op_offset, op_length, op_length);
        data_dump(bulk, op_length);
        free(bulk);
        bulk = NULL;
    }

    /*---------------------------------------------------------------*/
    /* FBA isn't supported here because I don't know much about FBA  */
    /*---------------------------------------------------------------*/
    if ( (!ckddasd) && ((cmd_cchh) || (cmd_tt)) ) {
        fprintf(stderr, "CCHH/reltrk not supported for FBA\n");
        clean();
        exit(3);
    }

    /*---------------------------------------------------------------*/
    /* Setup CCHH or relative track request                          */
    /*---------------------------------------------------------------*/
    if (ckddasd) {
        if (cmd_tt) {
            trk = op_tt;
            op_cc = trk / heads;
            op_hh = trk % heads;
        } else {
            trk = (op_cc * heads) + op_hh;
        }
        l1ndx = trk / cdevhdr.numl2tab;
        l2ndx = trk % cdevhdr.numl2tab;
        l2taboff = l1[l1ndx];
        if (swapend) cckd_swapend4((char *)&l2taboff);
    }

    /*---------------------------------------------------------------*/
    /* display CKD CCHH or relative track data                       */
    /*---------------------------------------------------------------*/
    if ((cmd_cchh) || (cmd_tt)) {
        fprintf(stderr,
                "CC %d HH %d = reltrk %d; "
                "L1 index = %d, L2 index = %d\n"
                "L1 index %d = L2TAB offset %d (0x%8.8X)\n",
                op_cc, op_hh, trk,
                l1ndx, l2ndx,
                l1ndx, (int)l2taboff, (int)l2taboff);
        l2 = makbuf(cdevhdr.numl2tab * sizeof(CCKD_L2ENT), "L2TAB");
        readpos(fd, l2, l2taboff,
                cdevhdr.numl2tab * sizeof(CCKD_L2ENT));
        if (cmd_l2tab) {
            fprintf(stderr,
                   "\nL2TAB - %d (decimal) bytes\n",
                   (int)(cdevhdr.numl2tab * sizeof(CCKD_L2ENT)));
            data_dump(l2, (cdevhdr.numl2tab * sizeof(CCKD_L2ENT)) );
        }
        fprintf(stderr, "\nL2 index %d = L2TAB entry %d bytes\n",
               l2ndx, (int)sizeof(CCKD_L2ENT) );
        data_dump(&l2[l2ndx], sizeof(CCKD_L2ENT) );
        trkhdroff = l2[l2ndx].pos;
        imglen = l2[l2ndx].len;
        if (swapend) {
            cckd_swapend4((char *)&trkhdroff);
            cckd_swapend4((char *)&imglen);
        }
        fprintf(stderr, "\nTRKHDR offset %d (0x%8.8X); "
                "length %d (0x%4.4X)\n",
                (int)trkhdroff, (int)trkhdroff, imglen, imglen);
        tbuf = makbuf(imglen, "TRKHDR+DATA");
        readpos(fd, tbuf, trkhdroff, imglen);
        fprintf(stderr, "\nTRKHDR track %d\n", trk);
        data_dump(tbuf, sizeof(CKDDASD_TRKHDR) );
        if (cmd_trkdata) showtrk(tbuf, imglen, trk, cmd_hexdump);
        free(l2); free(tbuf);
        l2 = NULL; tbuf = NULL;
    }

    /* Close file, exit */
    fprintf(stderr, "\n");
    clean();
    return cckd_diag_rc;
}
Example #19
0
int main( int argc, char *argv[] )
{
    U64 nxtpos;                         /* file position of next read */
    U64 altpos;                         /* file position of alternate track */
    U64 orgpos;                         /* alternate track's file position of original track */
    U32 numbad = 0;                     /* Counts defective tracks */
    U32 reclaimed = 0;                  /* Counts reclaimed tracks */
    U32 remaining;                      /* Counts number of tracks to process */
    U32 total;                          /* Total number of tracks to process */

    int infile  = -1;                   /* Input  file descriptor integer */
    int outfile = -1;                   /* output file descriptor integer */
    int cyl;                            /* Cylinder number */
    int head;                           /* Head number */
    int track;                          /* Track number */
    int rc;                             /* Return code */

    U8 trackbuf[TRACKSIZE];             /* Primary track buffer */
    U8 alttrack[TRACKSIZE];             /* Alternate track buffer */

    U8 altmark[6] = { BAD_TRACK_SIG };  /* Defective track signature */
    U8 reclaim = 0;                     /* false: map, true: reclaim */

    /*----------------*/
    /* Initialization */
    /*----------------*/

    if (argc < 3 || argc > 4)
        return error( EINVAL, "invalid number of arguments" );

    if (1
        && strcmp( argv[1], "MAP"     ) != 0
        && strcmp( argv[1], "map"     ) != 0
        && strcmp( argv[1], "RECLAIM" ) != 0
        && strcmp( argv[1], "reclaim" ) != 0
    )
        return error( EINVAL, "invalid 'action'" );

    reclaim = ((strcmp( argv[1], "RECLAIM" ) == 0) ||
               (strcmp( argv[1], "reclaim" ) == 0));

    if (reclaim && argc < 4)
        return error( EINVAL, "missing outfile argument" );

    printf( "Run option = %s\n", argv[1] );

    printf( "Opening input file \"%s\"...\n", argv[2] );

    if ((infile = HOPEN( argv[2], O_RDONLY | O_BINARY )) < 0)
        return error( errno, "could not open input file" );

    /*------------------------------*/
    /* Read and inspect file header */
    /*------------------------------*/

    if ((rc = read(infile, trackbuf, FILEHDRSIZE)) <= 0 || rc != FILEHDRSIZE)
        return error( EIO, "I/O error reading header from input file" );

    if (memcmp(trackbuf, "CKD_P370", 8) != 0)
        return error(EINTR, "input file is no CKD dasd image");

    if (trackbuf[16] != 0x90)
        return error(EINTR, "input file is no 3390 dasd image");

    FETCH_FW( head, &trackbuf[8] );
    FETCH_FW( track, &trackbuf[12] );
    FETCH_HW( cyl, &trackbuf[18] );

    if (bswap_32(track) != TRACKSIZE)
        return error(EINTR, "input file uses an unsupported track size");

    printf("3390 DASD image: %d heads, %d cylinders\n\n", bswap_32(head), bswap_16(cyl));

    remaining = total = TRACKSPERCYL * bswap_16(cyl);

    /*-----------------------------------------------------------*/
    /* Open output file and copy file header (only on "reclaim") */
    /*-----------------------------------------------------------*/

    if (reclaim)
    {
        printf( "Opening output file \"%s\"...\n", argv[3] );

        if ((outfile = HOPEN( argv[3], O_CREAT | O_EXCL | O_WRONLY | O_BINARY,
            S_IRUSR | S_IWUSR | S_IRGRP )) < 0)
            return error( errno, "could not open output file" );

        if ((rc = write( outfile, trackbuf, FILEHDRSIZE )) < 0 || rc != FILEHDRSIZE)
            return error( EIO, "I/O error writing output file" );
    }


c:  /*---------------------------*/
    /* Start of copy tracks loop */
    /*---------------------------*/

    track = total - remaining;
    cyl   = CYLNUM ( track );
    head  = HEADNUM( track );

    if (!head)
        printf( "Inspecting cylinder %d...\r", cyl );

    /* Read next track */

    if ((rc = read( infile, trackbuf, TRACKSIZE )) <= 0 || rc != TRACKSIZE)
        return error( errno, "I/O error reading input file" );

    /*------------------*/
    /* Defective track? */
    /*------------------*/

    if (memcmp( &trackbuf[TRACKSIZE-16], altmark, 6 ) == 0)
    {
        numbad++;     /* Count defective tracks */

        if (reclaim)
            printf( "Reclaiming track %6d = Cyl %4d (%4.4X), Head %2d (%2.2X)...\n",
                track, cyl, cyl, head, head );
        else
            printf( "Track %6d = Cyl %4d (%4.4X), Head %2d (%2.2X) is flagged\nas being defective and has an alternate track assigned.\n",
                track, cyl, cyl, head, head );

        FETCH_DW( altpos, &trackbuf[ TRACKSIZE-8 ] );   /* get alternate track position */
nxtpos= lseek( infile,   0,      SEEK_CUR  );           /* save current file position */
        lseek( infile, altpos,   SEEK_SET  );           /* position to alternate */
        read ( infile, alttrack, TRACKSIZE );           /* read alternate track */
        lseek( infile, nxtpos,   SEEK_SET  );           /* restore original file position */
        FETCH_DW( orgpos, &alttrack[ TRACKSIZE-8 ] );   /* get original track position */


        /*----------------------------------------------*/
#if (DEBUGOPT & DEBUG_POSITIONS)
        {
            int alttrk   = POS2TRACK( altpos );
            int altcyl   = CYLNUM ( alttrk );
            int althead  = HEADNUM( alttrk );

            int orgtrk   = POS2TRACK( orgpos );
            int orgcyl   = CYLNUM ( orgtrk );
            int orghead  = HEADNUM( orgtrk );

            printf("\n");

            printf( "\taltpos = %llx ==> track %6d = Cyl %4d (%4.4X), Head %2d (%2.2X)\n",
                altpos, alttrk, altcyl, altcyl, althead, althead );

            printf( "\torgpos = %llx ==> track %6d = Cyl %4d (%4.4X), Head %2d (%2.2X)\n",
                orgpos, orgtrk, orgcyl, orgcyl, orghead, orghead );
        }
#endif

#if (DEBUGOPT & DEBUG_TRACKDATA)
        {
            char *dump = NULL;

            printf("\n");

            hexdumpe( "\tPRI:  ", &dump, trackbuf, 0, TRACKSIZE, orgpos, 4, 4 );
            if (dump) printf( "%s\n", dump );

            hexdumpe( "\tALT:  ", &dump, alttrack, 0, TRACKSIZE, altpos, 4, 4 );
            if (dump) printf( "%s", dump );

            if (dump) free( dump );
        }
#endif

#if (DEBUGOPT & DEBUG_BOTH) /* if EITHER debug option */
        printf("\n");       /* if EITHER debug option */
#endif
        /*----------------------------------------------*/


        if (reclaim)
        {
            /* Reclaim the original track: the alternate tracks's
               position of the original defective track must match,
               and the track header containing the cylinder and track
               numbers must also match.
            */
            if (orgpos == (nxtpos-TRACKSIZE) &&
                memcmp( &alttrack[0], &trackbuf[0], 16 ) == 0)
            {
                /* copy alternate track data to original track */
                memcpy( trackbuf, alttrack, TRACKSIZE );

                /* indicate original track is no longer defective */
                memset( &trackbuf[TRACKSIZE-16], 0, 16 );

                reclaimed++;    /* Count reclaimed tracks */
            }
            else
                fprintf( stderr, "\t*** ERROR *** Reclaim failed!\n\n" );
        }
    }

    /*----------------------------*/
    /* Write track to output file */
    /*----------------------------*/

    if (reclaim)
        if ((rc = write( outfile, trackbuf, TRACKSIZE )) < 0 || rc != TRACKSIZE)
            return error( EIO, "I/O error writing output file" );

    /*------------------------------*/
    /* Loop until all tracks copied */
    /*------------------------------*/

    if (--remaining)
        goto c;

    /*-----------------------*/
    /* Print totals and exit */
    /*-----------------------*/

    if (infile  > 0) close( infile  );
    if (outfile > 0) close( outfile );

    printf( "%d tracks (%d cylinders) read.\n",    total, CYLNUM(total) );
    if (reclaim)
    printf( "%d tracks (%d cylinders) written.\n", total, CYLNUM(total) );

    if (!reclaim)
        printf( "Image currently has %d defective tracks assigned to an alternate.\n", numbad );
    else
    {
        printf( "Image had %d defective tracks assigned to an alternate.\n", numbad );
        printf( "A total of %d defective tracks were reclaimed from their assigned alternate.\n", reclaimed );
        printf( "Reclaim %s.\n", reclaimed >= numbad ? "was successful" : "function FAILED" );
    }

    PAUSEIFBEINGDEBUGGED();

    return (0);
}