/* This is part of ODS2 written by Paul Nankervis, * email address: Paulnank@au1.ibm.com * * ODS2 is distributed freely for all members of the * VMS community to use. However all derived works * must maintain comments in their source to acknowledge * the contributions of the original author and * subsequent contributors. This is free software; no * warranty is offered, and while we believe it to be useful, * you use it at your own risk. */ #if !defined( DEBUG ) && defined( DEBUG_CREATECMD ) #define DEBUG DEBUG_CREATECMD #else #ifndef DEBUG #define DEBUG 0 #endif #endif #include "cmddef.h" static vmscond_t create_directory( options_t options, int argc, char** argv ); static vmscond_t create_file( options_t options, int argc, char** argv ); /******************************************************************* docreate() */ #define create_log OPT_GENERIC_1 #define create_dir OPT_GENERIC_2 #define create_owner OPT_GENERIC_3 #define create_protect OPT_GENERIC_4 #define create_volume OPT_GENERIC_5 #define create_verlim OPT_GENERIC_6 #define create_recfmt (OPT_GENERIC_10|OPT_GENERIC_9|OPT_GENERIC_8) #define create_v_recfmt (OPT_V_GENERIC + 7) #define create_b4 (OPT_SHARED_2|OPT_SHARED_1) #define create_v_b4 0 #define create_after (OPT_SHARED_4|OPT_SHARED_3) #define create_v_after 2 #define create_prn_none 0 #define create_prn_nl 1 #define create_prn_c0 2 #define create_prn_vfu 3 #define create_prn OPT_SHARED_17 #define create_ftn OPT_SHARED_18 #define create_cr OPT_SHARED_19 #define create_span OPT_SHARED_20 static uint32_t b4n, aftn; static uint32_t vfclen; static uint32_t reclen; static uint32_t verlimit; static uint32_t volume; static uint32_t protection; static uint32_t ownuic; static qual_t prnb4[] = { {"none", create_prn_none << create_v_b4, create_b4, NV, "commands create qual_cc print b4 none"}, {"nl", create_prn_nl << create_v_b4, create_b4, DV(&b4n), "commands create qual_cc print b4 nl"}, {"ctl", create_prn_c0, create_b4, DV(&b4n), "commands create qual_cc print b4 ctl"}, {"vfu", create_prn_vfu << create_v_b4, create_b4, DV(&b4n), "commands create qual_cc print b4 vfu"}, {NULL, 0, 0, NV, NULL} }; static qual_t prnafter[] = { {"none", create_prn_none << create_v_after, create_after, NV, "commands create qual_cc print b4 none"}, {"nl", create_prn_nl << create_v_after, create_after, DV(&aftn), "commands create qual_cc print b4 nl"}, {"ctl", create_prn_c0, create_b4, DV(&aftn), "commands create qual_cc print b4 ctl"}, {"vfu", create_prn_vfu << create_v_after, create_after, DV(&aftn), "commands create qual_cc print b4 vfu"}, {NULL, 0, 0, NV, NULL} }; static qual_t prnkwds[] = { {"before", 0, create_b4, KV(prnb4), "commands create qual_cc print b4"}, {"after", 0, create_after, KV(prnafter), "commands create qual_cc print after"}, {NULL, OPT_NOSORT, 0, NV, NULL} }; static qual_t cckwds[] = { {"fortran", create_ftn, create_cr|create_prn, NV, "commands create qual_cc fortran"}, {"carriage_return", create_cr, create_ftn|create_prn, NV, "commands create qual_cc cr"}, {"print", create_prn|(FAB$C_VFC<> 16)) | (uint16_t)protection); } if( options & create_owner ) { pro.xab$l_uic = ownuic; } itm.xab$l_nxt = &fhc; directory = 1; itm.xab$b_mode = XAB$K_SETMODE; pro.xab$l_nxt = &itm; nfab.fab$l_xab = &pro; nam.nam$b_rss = sizeof( rsname ) -1; nam.nam$l_rsa = rsname; nfab.fab$l_nam = &nam; nfab.fab$b_fac = 0; nfab.fab$l_fop = FAB$M_OFP; nfab.fab$b_org = FAB$C_SEQ; nfab.fab$b_rat = FAB$M_BLK; nfab.fab$b_rfm = FAB$C_VAR; fhc.xab$w_lrl = nfab.fab$w_mrs = 512; nfab.fab$b_fns = fab.fab$b_fns; nfab.fab$l_fna = fab.fab$l_fna; sts = sys_create( &nfab ); rsname[nam.nam$b_rsl] = '\0'; if( $FAILED(sts) ) { printmsg( CREATE_CREDIRFAIL, 0, rsname ); sts = printmsg( sts, MSG_CONTINUE, CREATE_CREDIRFAIL ); } else { if( $FAILS(sts = sys_close(&nfab)) ) { printmsg(CREATE_CLOSEOUT, 0, rsname); sts = printmsg(sts, MSG_CONTINUE, CREATE_CLOSEOUT); } } nfab.fab$b_fns = nam.nam$b_ess = 0; nfab.fab$b_dns = 0; nam.nam$b_nop = NAM$M_SYNCHK; (void) sys_parse( &nfab ); if( $FAILED(sts) ) break; if( options & create_log ) sts = printmsg( CREATE_CREATED, 0, rsname ); } if( *p == ']' ) break; switch( level++ ) { case 0: break; case 1: memmove( tdir+devlen+1, tdir+devlen+tmplen, sfdlen ); tmplen = 1+ sfdlen +1; tdir[devlen+tmplen-1] = ']'; break; default: tdir[devlen+tmplen -1] = '.'; tmplen += 1 + sfdlen; tdir[devlen+tmplen -1] = ']'; break; } for( sfdlen = 0; *p != '.' && *p != ']'; sfdlen++ ) tdir[devlen+tmplen+sfdlen] = *p++; memcpy( tdir+devlen+tmplen+sfdlen, ".DIR;1", 6 ); if( *p == '.' ) ++p; } } while( 0 ); if( nam.nam$l_fnb & (NAM$M_EXP_NAME | NAM$M_EXP_TYPE | NAM$M_EXP_VER | NAM$M_WILDCARD) ) { sts = printmsg( RMS$_DIR, 0 ); } fab.fab$b_fns = nam.nam$b_ess = fab.fab$b_dns = 0; nam.nam$b_nop = NAM$M_SYNCHK; (void) sys_parse( &fab ); return sts; } /******************************************************************* create_file() */ static vmscond_t create_file( options_t options, int argc, char** argv ) { vmscond_t sts; char *buf = NULL; size_t bufsize = 80; char vfc[2], rsbuf[NAM$C_MAXRSS + 1]; struct NAM nam; struct FAB fab; struct RAB rab; struct XABPRO pro; UNUSED( argc ); nam = cc$rms_nam; fab = cc$rms_fab; rab = cc$rms_rab; pro = cc$rms_xabpro; nam.nam$l_esa = NULL; nam.nam$b_ess = 0; nam.nam$b_rss = sizeof( rsbuf ) -1; nam.nam$l_rsa = rsbuf; if( options & (create_protect|create_owner) ) { fab.fab$l_xab = &pro; if( options & create_protect ) { pro.xab$w_pro = (uint16_t) ((pro.xab$w_pro & ~(protection >> 16)) | (uint16_t)protection); } if( options & create_owner ) { pro.xab$l_uic = ownuic; } } fab.fab$l_nam = &nam; fab.fab$b_fac = FAB$M_PUT; fab.fab$l_fop = FAB$M_OFP | FAB$M_TEF; fab.fab$b_org = FAB$C_SEQ; if( !(options & create_recfmt) ) { options |= (FAB$C_VAR +1) << create_v_recfmt; if( !(options & (create_prn|create_ftn|create_cr)) ) options |= create_cr; } fab.fab$b_rfm = ((options & create_recfmt) >> create_v_recfmt) -1; switch( fab.fab$b_rfm ) { case FAB$C_STM: case FAB$C_STMLF: case FAB$C_STMCR: fab.fab$b_rat |= FAB$M_CR; break; case FAB$C_VFC: fab.fab$b_fsz = vfclen; break; } if( !(options & create_span) ) fab.fab$b_rat |= FAB$M_BLK; if( options & create_ftn ) fab.fab$b_rat |= FAB$M_FTN; if( options & create_cr ) fab.fab$b_rat |= FAB$M_CR; if( options & create_prn ) { fab.fab$b_rat |= FAB$M_PRN; fab.fab$b_fsz = 2; fab.fab$b_rfm = FAB$C_VFC; switch( (options & create_b4) >> create_v_b4 ) { case create_prn_none: vfc[0] = 0; break; case create_prn_nl: if( b4n < 1 || b4n > 127 ) return printmsg( CREATE_INVALIDNL, 0 ); vfc[0] = b4n & 0x7f; break; case create_prn_c0: if( b4n > 31 ) return printmsg( CREATE_INVALIDC0, 0 ); vfc[0] = 0x80 | b4n; break; case create_prn_vfu: if( b4n < 1 || b4n > 16 ) return printmsg( CREATE_INVALIDVFU, 0 ); vfc[0] = (0xC0 | (b4n -1)) & 0xff; } switch( (options & create_after) >> create_v_after ) { case create_prn_none: vfc[1] = 0; break; case create_prn_nl: if( aftn < 1 || aftn > 127 ) return printmsg( CREATE_INVALIDNL, 0 ); vfc[1] = aftn & 0x7f; break; case create_prn_c0: if( aftn > 31 ) return printmsg( CREATE_INVALIDC0, 0 ); vfc[1] = 0x80 | aftn; break; case create_prn_vfu: if( aftn < 1 || aftn > 16 ) return printmsg( CREATE_INVALIDVFU, 0 ); vfc[1] = (0xC0 | (aftn -1)) & 0xff; } } /* prn */ /* fab.fab$w_deq = 5; fab.fab$l_alq = 100; */ fab.fab$w_mrs = (uint16_t)reclen; fab.fab$l_fna = argv[1]; fab.fab$b_fns = (uint8_t)strlen(fab.fab$l_fna); do { char *input; sts = sys_create( &fab ); rsbuf[nam.nam$b_rsl] = '\0'; if( $FAILED(sts) ) break; rab.rab$l_fab = &fab; if( $FAILS(sts = sys_connect( &rab )) ) break; if( options & create_prn ) rab.rab$l_rhb = vfc; if( options & create_log ) { printmsg( CREATE_READY, 0, rsbuf ); printmsg( CREATE_TERMEOF, MSG_CONTINUE, CREATE_READY, #if defined( VMS ) || defined( _WIN32 ) "Control-Z" #ifdef _WIN32 " Enter" #endif #else "Control-D" #endif ); } while( (input = fgetline( stdin, FALSE, &buf, &bufsize )) != NULL ) { size_t len; len = strlen( input ); sts = SS$_NORMAL; #if 0 if( len && input[len -1] == '\r' ) len--; #endif rab.rab$l_rbf = input; switch( fab.fab$b_rfm ) { case FAB$C_FIX: if( len > (size_t)fab.fab$w_mrs ) len = fab.fab$w_mrs; else if( len < (size_t)fab.fab$w_mrs ) { char *p = input; if( bufsize < fab.fab$w_mrs ) { p = realloc( buf, fab.fab$w_mrs ); if( p == NULL ) { sts = SS$_INSFMEM; break; } bufsize = fab.fab$w_mrs; rab.rab$l_rbf = buf = input = p; } p += len; len = fab.fab$w_mrs - len; while( len-- ) *p++ = ' '; len = fab.fab$w_mrs; } break; case FAB$C_VFC: if( !(options & create_prn) ) { if( len < fab.fab$b_fsz ) { sts = RMS$_RFM; break; } rab.rab$l_rhb = input; rab.rab$l_rbf = input + fab.fab$b_fsz; len -= fab.fab$b_fsz; } break; } if( $SUCCESSFUL(sts) ) { rab.rab$w_rsz = (uint16_t)len; sts = sys_put(&rab); } if( $FAILED(sts) ) break; } break; } while( 0 ); if( buf != NULL ) free( buf ); if( $FAILED(sts) ) { vmscond_t rsts; int err; err = errno; rsts = printmsg( sts, 0, nam.nam$b_rsl? rsbuf: argv[1] ); if( err ) printmsg( ODS2_OSERROR, MSG_CONTINUE, sts, strerror( err ) ); sts = rsts; } sys_disconnect( &rab ); if( $SUCCESSFUL( sts ) ) { if( $FAILS(sts = sys_close( &fab )) ) { vmscond_t rsts; int err; err = errno; rsts = printmsg( CREATE_CLOSEOUT, 0, nam.nam$b_rsl? rsbuf: argv[1] ); printmsg( sts, MSG_CONTINUE, rsts, nam.nam$b_rsl? rsbuf: argv[1] ); if( err ) printmsg( ODS2_OSERROR, MSG_CONTINUE, sts, strerror( err ) ); sts = rsts; } } else { sys_close( &fab ); } if( $SUCCESSFUL( sts ) && (options & create_log) ) sts = printmsg( CREATE_CREATED, 0, rsbuf ); return sts; }