/*-------------------------------------------------------------------+ | 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 #if defined(OSVS) /* choose OS or CMS */ #include #elif defined(CMS) #include #endif #include #include #include #include #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); }