/*-------------------------------------------------------------------+
| Copyright (c) 1996, SAS Institute Inc. |
| Unpublished - All Rights Reserved |
| S A S / C S A M P L E |
| |
| NAME: DESCRIBE |
| LANGUAGE: C |
| PURPOSE: This program demonstrates the use of the SAS/C FSSL. |
| Specifically, this routine allows a dataset name to |
| be entered. Upon entry it will provide misc infor- |
| mation on the dataset. At the user request it will |
| also allow a detailed description about the dataset |
| to be entered. The description is stored in a |
| master "DSINFO" file. When the dataset name is |
| entered this file is searched for an old description.|
| SYSTEM NOTES: This routine will run on either CMS or TSO |
| |
| MVS - |
| COMPILE/LINK: SUBMIT prefix.SAMPLE.AUX(DESCRIBE) |
| where "prefix" is the installation defined high-level|
| qualifier for the SAS/C product. |
| EXECUTE: execute under TSO, see below |
| TSO - |
| COMPILE: LC370 CLIST |
| LINK: CLK370 CLIST |
| EXECUTE: CALL your.load.lib(DESCRIBE) |
| At compile time the decision is made (by preprocessor|
| control) whether to generate OS or CMS specific code.|
| CMS - |
| COMPILE: GLOBAL MACLIB LC370 L$FSSL |
| LC370 DESCRIBE |
| LINK: GLOBAL TXTLIB LC370BAS LC370STD L$FSSL |
| CLINK DESCRIBE (GENMOD |
| EXECUTE: DESCRIBE |
| |
| MISC NOTES: SAS/C FSSL must be installed. |
| If running in OS, dataset names must be entered in |
| fully qualified format. |
| ---> The master "DSINFO" file must be preallocated. The |
| only requirement is that the RECFM=FBS. |
| |
+-------------------------------------------------------------------*/
#include <lcio.h>
#if defined(OSVS) /* choose OS or CMS */
#include <os.h>
#elif defined(CMS)
#include <cmsstat.h>
#endif
#include <time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <l$fappl.h>
#define TRUE 1
#define FALSE 0
#define MAX_DSN 45
#define DSN 1000
#define DSCRNO 1001
struct FS_TERMATTR * scr_attr;
struct FS_READPAN input;
struct FS_READSCR screen;
FILE * dsnfp;
char * info = "panel1";
char errmsg(|132|);
char xline(|80|);
char status(|51|);
long oldpos;
int fldno = 10000;
int dsnattr, xlen, row, col;
/* dataset description structure */
struct dscrp {
char dsn(|MAX_DSN+2|);
char lrecl(|6|);
char blksize(|6|);
char recfm(|6|);
char descript(|10|)(|61|);
time_t time;
char userid(|L_cuserid+1|);
} dsinfo;
/*-------------------------------------------------------------------+
| The main will request that the screen definitions are set up, |
| display the screen and wait for input. When input has been |
| entered, it will decide what to do. Possible decisions are: |
| (1) terminate program, or |
| (2) edit dataset description, or |
| (3) enter dataset name |
+-------------------------------------------------------------------*/
main()
{
int rc;
/* make the screen ready */
define_screen();
/* open dataset description file */
save_descrp(0);
/* continue while user wants to... */
/* after each input check the user's response; */
/* this response can be either PFkeys or data (enter key) */
while (TRUE) {
/* display panel */
strcpy(status, "PF 3/15 - END, PF 12/24 - Edit Description");
rc = fsdspn(info, 0, 1, 1, DSN, 1, FS_FORCE);
if (rc != FS_OK && rc != FS_DFLTVIEW) {
fsterm();
printf("ERROR: panel display failure\n");
exit(EXIT_FAILURE);
}
/* wait for input from user */
screen = fsrdsc();
/* check for 'the end' */
if ( (screen.aid == PF_3) || (screen.aid == PF_15) ) {
fsterm();
fclose(dsnfp);
return(0);
}
/* check for request of dataset description entry */
else if ( (screen.aid == PF_12) || (screen.aid == PF_24) ) {
if (dsn_dscrp())
save_descrp(1);
continue;
}
/* not a PF key...read fields */
input = fsrdpn(info);
/* get dataset characteristics and old description */
if (dsn_info())
save_descrp(-1);
}
}
/*-------------------------------------------------------------------+
| This routine will obtain the characteristics about the dataset |
| name entered by the user. The name must be in its fully qualified|
| format. |
+-------------------------------------------------------------------*/
dsn_info()
{
#if defined(CMS) /* used only in CMS */
struct cmsstat cmsinfo;
#elif defined(OSVS) /* used only in OS */
char alloc(|80|);
#endif
int rc, i, lreclp, blkszp;
char recfmp;
/* did user modify any field? */
if (input.count) {
/* check for null entry */
/* if so then tell user of the error */
if (strlen(dsinfo.dsn) == 0) {
strcpy(status, "INVALID ENTRY - REENTER");
fsuppn(info, 0, 1, 1, DSN, 1, FS_FORCE);
sleep(5);
return(FALSE);
}
/* TSO? */
/* compile OS dependent code iff in OS environment */
#if defined(OSVS)
/* allow no embedded blanks in dataset name */
for (i=0; iprim_row - 14;
/* tell user what this half of the screen is for */
attr2 = PROTECTED;
color = RED;
col = 20;
fsdffd(info, n++, row, col, 25, "Enter Dataset Description",
&attr2, color, BLANK);
row += 2;
/* get modifier user's id */
color = GREEN;
cuserid(dsinfo.userid);
col = 5;
fsdffd(info, n++, row, col, L_cuserid, dsinfo.userid,
&attr2, color, BLANK);
/* get modifier user's time */
time(&dsinfo.time);
col += L_cuserid + 10;
fsdffd(info, n++, row, col, 25, ctime(&dsinfo.time),
&attr2, color, BLANK);
/* display all description entries */
row++;
col = 10;
attr = REVERSE_VIDEO | BRIGHT | AUTOREAD | MUST_ENTER;
color = GREEN;
for (i=0; i<10; i++) {
row++;
fsdffd(info, n++, row, col, 60, dsinfo.descript(|i|),
&attr, color, BLANK);
}
/* give the user some info */
color = YELLOW;
row++;
col = 20;
fsdffd(info, n++, row, col, 26, "Any PF key terminates edit",
&attr2, color, BLANK);
/* display new screen */
fsdspn(info, 0, 1, 1, DSN, 1, FS_FORCE);
/* allow input */
screen = fsrdsc();
/* store input */
input = fsrdpn(info);
/* check for no mod */
if (screen.aid == ENTER_KEY) rc = TRUE;
else rc = FALSE; /* no mod if any PFkey pressed */
/* ok...restore screen */
fsrmfd(info, DSN);
dsnattr = BRIGHT | AUTOREAD | MUST_ENTER;
color = BLUE;
fsdffd(info, DSN, 3, 25, MAX_DSN, dsinfo.dsn,
&dsnattr, color, NULL);
/* remove description fields */
n = DSCRNO;
for (i=0; i<14; i++) {
fsrmfd(info, n++);
}
return(rc);
}
/*-------------------------------------------------------------------+
| This routine creates the full screen image. It sets up the full |
| screen environment, defines the panel, defines all the fields, |
| and other misc fs needs. |
+-------------------------------------------------------------------*/
define_screen()
{
int rc;
static int color, color2, attr;
/* get FS mode up */
if ((rc = fsinit(errmsg)) != FS_OK) {
fsterm();
printf("ERROR: initialization failure\n");
exit(EXIT_FAILURE);
}
/* get screen attribute capability */
if ((int)(scr_attr = fsrttm()) == FS_INITERR) {
fsterm();
printf("ERROR: terminal read failure\n");
exit(EXIT_FAILURE);
}
/* set line separator */
memset(xline, '-', scr_attr->prim_col-1);
xline(|scr_attr->prim_col|) = '\0';
xlen = strlen(xline);
/* define panel size */
if ((rc = fsdfpn(info, scr_attr->prim_row, scr_attr->prim_col))
!= FS_OK) {
fsterm();
printf("ERROR: panel definition failure\n");
exit(EXIT_FAILURE);
}
/* display title */
row = 1;
title(info, "Dataset Description", row);
/* allow users to enter dataset name */
row += 2;
col = 5;
attr = BRIGHT | PROTECTED;
color = WHITE;
fsdffd(info, fldno++, row, col, 19, "Enter Dataset Name:",
&attr, color, BLANK);
col += 20;
dsnattr = BRIGHT | AUTOREAD | MUST_ENTER;
color = BLUE;
fsdffd(info, DSN, row, col, MAX_DSN, dsinfo.dsn,
&dsnattr, color, NULL);
/* create fields for dataset characteristics...recfm */
/* note: this field will be the internal hex value for the recfm */
row += 2;
col = 5;
color = WHITE;
fsdffd(info, fldno++, row, col, 6, "RECFM:",
&attr, color, BLANK);
col += 7;
color2 = GREEN;
fsdffd(info, fldno++, row, col, 2, dsinfo.recfm,
&attr, color2, BLANK);
/* ...lrecl */
col += 11;
fsdffd(info, fldno++, row, col, 6, "LRECL:",
&attr, color, BLANK);
col += 7;
fsdffd(info, fldno++, row, col, 5, dsinfo.lrecl,
&attr, color2, BLANK);
/* ...blksize */
col += 11;
fsdffd(info, fldno++, row, col, 8, "BLKSIZE:",
&attr, color, BLANK);
col += 9;
fsdffd(info, fldno++, row, col, 5, dsinfo.blksize,
&attr, color2, BLANK);
/* create field for messages */
row += 2;
col = 15;
attr = BRIGHT | PROTECTED;
color = YELLOW;
fsdffd(info, fldno++, row, col, 50, status,
&attr, color, BLANK);
/* separate screen...visible effect only */
row++;
color = RED;
fsdffd(info, fldno++, row, 2, xlen, xline, &attr, color, BLANK);
return(0);
}
/*-------------------------------------------------------------------+
| The title routine will create a title across the screen. |
+-------------------------------------------------------------------*/
title(panel, ttl, row)
char *panel;
char *ttl;
int row;
{
char *work;
int bg, len;
static int attr = PROTECTED | BRIGHT;
static int color = CYAN;
/* create the title as ----- title ----- */
work = malloc((scr_attr->prim_col+3));
memset(work, '-', scr_attr->prim_col);
*(work+scr_attr->prim_col) = '\0';
len = strlen(ttl);
bg = (scr_attr->prim_col / 2) - (len / 2);
memcpy(work+bg-2, " ", 2);
memcpy(work+bg, ttl, len);
memcpy(work+bg+len, " ", 2);
/* display title */
fsdffd(panel, fldno++, row, 2, scr_attr->prim_col-1, work,
&attr, color, BLANK);
return(0);
}
/*-------------------------------------------------------------------+
| This routine will handle all requests for I/O for the dataset |
| description info. Requests are: |
| -1 = read request |
| 0 = open request |
| 1 = write request |
| Note: The I/O method used is a simple brute force search and is |
| not intended to show good/effecient I/O. |
+-------------------------------------------------------------------*/
save_descrp(type)
int type;
{
struct dscrp oldinfo;
int rc, i;
/* open request */
if (type == 0) {
quiet(TRUE);
dsnfp = fopen("DSINFO", "rb+");
if (dsnfp == NULL) dsnfp = fopen("DSINFO", "wb+");
if (dsnfp == NULL) {
printf("ERROR: open failure on DSINFO\n");
exit(EXIT_FAILURE);
}
quiet(FALSE);
oldpos = -1;
}
/* read request */
else if (type == -1) {
/* start search...search in a straight brute force way */
rewind(dsnfp);
/* ok, search */
while (TRUE) {
oldpos = ftell(dsnfp);
quiet(TRUE);
rc = fread((char*)&oldinfo, sizeof(oldinfo), 1, dsnfp);
quiet(FALSE);
if (rc == 0) {
oldpos = -1;
clearerr(dsnfp);
return(FALSE);
}
/* check if dsn read is one requested */
if (!memcmp(oldinfo.dsn, dsinfo.dsn, strlen(dsinfo.dsn))) {
/* found it...copy description */
for (i=0; i<10; i++)
strcpy(dsinfo.descript(|i|), oldinfo.descript(|i|));
break;
}
}
}
/* write request */
else {
/* go directly to old position in dataset, or eof */
if (oldpos < 0)
fseek(dsnfp, 0, SEEK_END);
else
fseek(dsnfp, oldpos, SEEK_SET);
/* write */
fwrite((char*)&dsinfo, sizeof(dsinfo), 1, dsnfp);
}
return(TRUE);
}
|