| This utility is far more than you need, but it's a working example of using
sys$trnlnm.
In this utility you will find the code that starts LOGINOUT.EXE and
feeds it commands. This code was written for VMS 5.1/5.2 and is no
longer needed under VMS 5.3 but it does serve to illustrate the
technique. Its long, so don't bother reading unless you are interested.
In regards to 37.6, I do not understand your question. If you want to
determine if the current process has a CLI, I do not think that there is
a "official" method. If you try one of the LIB$GET_SYMBOL functions, I
believe that it returns an error if DCL is not your CLI. The locations
CTL$AG_CLIIMAGE and CTL$AG_CLITABLE contain pointers to the pages used
by a CLI but do not know what they would contain if there was no CLI.
If you are concerned about the subprocess, then you will know if you've
created the process with a CLI. Perhaps you should rephrase your
question.
This file contains everything, (I believe) that you need to create your own
DECTERM utility. The files are:
DECTERM.TXT -- notes and instructions.
DECTERM.C -- the code that does the work.
VMS.H -- various helpful VMS C macros.
DECTERM.OPT -- linker options file
DECTERM.MMS -- MMS makefile.
VUE_DECTERM.COM -- procedure that can be called from a FileView menu.
+-------------------------+-------------------------------------+
|M. Erik Husby | If you lie to the computer, |
|Senior Software Engineer | it will get you. |
+-------------------------+-------------------------------------+
|Access Technology, Inc. | Voice: (508)655-9191 |
|2 Natick Executive Park | FAX: (508)655-7772 |
|Natick, MA 01760 | EasyPlex: 70003,5200 |
| | Internet: [email protected] |
| | DECUServe: EISNER::HUSBY |
| | Pageswapper: US110737 |
+-------------------------+-------------------------------------+
--DECTERM.TXT-------------------------------------------------------------------
DECTERM is a utility to create a DECterm window with all options including the
specification of DECW$TERMINAL resources on the command line.
Command line options:
---------------------
$ DECTERM -display node::n.m
-parameters p
-setup setupfile
-define portname
-login
-display node::n.m -- Specifies the display on which terminal window is to
be created. The default is the current value of DECW$DISPLAY.
-parameter "param: value\nparam: value..." -- A quoted string of
DECW$TERMINAL resources, separated by \n. The default is no parameters.
-setup setupfile -- a file containing DECW$TERMINAL resources.
The default if -setup is not specified is
DECW$USER_DEFAULTS:DECW$TERMINAL_DEFAULTS.DAT.
-define portname -- Requests that a logical name for the resulting terminal
port be created. The default if portname not specified is DECTERM_PORT.
-login -- Causes a process to be logged in on the port using the current
username.
? -- Produces this message.
Setup.
------
Create a DCL symbol which defines DECTERM as a foreign command. For example, if
DECTERM.EXE resides in SYS$LOGIN:, then:
$ DECTERM == "$SYS$LOGIN:DECTERM"
Examples:
---------
Create a DECTerm window logged into the current username, similar to the
Session Manager's Create Terminal Window command.
$ decterm -login
Create a DECTerm window that can be used for the DEBUGger.
$ decterm -define DBG$INPUT
$ DEFINE DBG$OUTPUT DBG$INPUT:
$...run the program to be debugged.
$ DEASSIGN DBG$INPUT
$ DEASSIGN DBG$OUTPUT
Create a DECTerm window on node REMOTE, server 0, screen 0.
$ decterm -display REMOTE::0.0
Create a DECTerm window at screen coordinates (10,10).
$ decterm -parameters "DECW$TERMINAL.x: 10\nDECW$TERMINAL.y: 10"
Create a DECTerm window using the parameter file SYS$LOGIN:DECTERM_BLUE.DAT.
$ decterm -setup SYS$LOGIN:DECTERM_BLUE.DAT
Create a DECterm window that can be used for a spawned subprocess. Note: A
DECterm window will stay around as long as a channel is assigned to the device.
The SPAWN command assigns a channel to the window, then deassigns the channel,
then creates the subprocess. Thus to keep the window around, one needs to keep
a channel assigned to the window. One can keep a channel assigned by using the
DCL OPEN command. CLOSE the channel when the window is no longer needed.
$ decterm -define
$ open/read window DECTERM_PORT:
$ port = f$trnlnm("DECTERM_PORT")
$ spawn/nowait/input='port'/output='port'
$...wait a suitable amount of time...
$ close window
DECW$TERMINAL resources:
------------------------
Easiest way to determine names is to play with the options in the customize
menu, and save the changes to different files. Then examine the files to learn
the resource names and values.
----------------------DECTERM.C-------------------------------------------------
#module DECTerm v1.0
/*
** ++ FACILITY:
**
** DECTERM
**
** ABSTRACT:
**
** Creates a DECTerm port for the specified display allowing for
** specification of customization parameters and alternate setup files.
**
** Takes a command line of the form:
**
** $ DECTERM -display node::n.m -parameters p
** -setup setupfile -define portname
**
** -display node::n.m -- Specifies display on which terminal window is to
** be created. Default is current value of DECW$DISPLAY.
**
** -pararametersparameters -- A quoted string of DECW$TERMINAL resources,
** separated by \n. Default is none.
**
** -setup setupfile -- a file containing DECW$TERMINAL resources.
** Default is DECW$USER_DEFAULTS:DECW$TERMINAL_DEFAULTS.DAT
**
** -define portname -- A logical name to be given to the port.
** Default is DECTERM_PORT
**
** -login -- causes a process to be logined on the port.
**
** ? -- Produces this message
**
** AUTHORS:
**
** M. Erik Husby
**
**
** CREATION DATE: Monday 2-OCT-1989 11:26 AM
**
** MODIFICATION HISTORY: --
*/
/*
**
** INCLUDE FILES
**
*/
#include ssdef
#include descrip
#include lnmdef
#include dvidef
#include jpidef
#include prvdef
#include prcdef
#include iodef
#include chfdef
#include accdef
#include "vms.h"
#include <DwtAppl.h>
/* See the VMS 5.1-1 release notes for a description of the DECwTermPort bug */
static void
fix_DECwTermPort_bug_2( fix ) /*f:
**
** Avoids a bug in the DECwTermPort routine which is an unitialized stack
** variable.
*/
{
}
static void
fix_DECwTermPort_bug() /*f:
**
** Second part of the bug avoiding routine.
*/
{
int fix[258];
fix[0] = 0;
fix_DECwTermPort_bug_2( fix );
}
/* Some items used by decterm but which need to be visible to the condition */
/* handler and Termination Mailbox AST routine. */
static unsigned short wInputChannel; /* Channel number of the mailbox used */
/* to feed commands to the controller */
/* process. */
static unsigned short wTrmChannel; /* Channel number of the termination */
/* mailbox for the controller */
/* process. */
static unsigned long nInputFlag; /* Event flag used when writing to */
/* the input mailbox. */
static Boolean bDebug = False;
static void
TrmMbxAST( void ) /*f:
**
** An AST routine called if there is a termination message from the controller
** process.
**
*/
{
struct acc$record accbuf;
IOSB iosb;
/* Called if a termination message comes in on the termination mailbox. */
/* We can assume that this means that the controller process failed for */
/* some reason. So we cancel any outstanding IO on the Input mailbox. */
if (wInputChannel != 0) {
PERFORM( sys$cancel (
wInputChannel) );
}
/* Read the termination message and report its errors. */
PERFORM( sys$qiow (
0,
wTrmChannel,
IO$_READVBLK,
&iosb,
0,
0,
&accbuf,
sizeof(accbuf),
0,
0,
0,
0) );
PERFORM( iosb.status);
PERFORM( accbuf.acc$l_finalsts );
}
static unsigned long
unwind_on_errors( /*f:
**
** Condition handler called in advent of VMS errors. It causes the stack to be
** unwound to the caller of the establisher.
**
** Causes a function result of False to be returned.
**
** During Unwinding, releases any resources grabbed by decterm
**
**
*/
struct chf$signal_array *sigargs,
struct chf$mech_array *mechargs)
{
unsigned long result = SS$_CONTINUE;
if (sigargs->chf$l_sig_name == SS$_UNWIND) {
/* Unwinding, free up resources that we allocated.. */
if (nInputFlag != 0) {
lib$free_ef(&nInputFlag);
nInputFlag = 0;
}
if (wInputChannel != 0) {
sys$dassgn (
wInputChannel);
wInputChannel = 0;
}
if (wTrmChannel != 0) {
sys$dassgn (
wTrmChannel);
wTrmChannel = 0;
}
}
else {
/* Set return code to false and unwind the stack.. */
mechargs->chf$l_mch_savr0 = (long)False;
sys$unwind(0,0);
}
return result;
}
static Boolean
decterm( /*f:
**
** Called to create a DECW$TERMINAL terminal window on the specified display.
**
** Inputs:
** azDisplay -- the display name.
** azParams -- any parameters to be used to configure the terminal window.
** Null if no parameters specified.
** azSetup -- name of a parameter file. If null, the default of
** DECW$USER_DEFAULTS:DECW$TERMINAL_DEFAULT.DAT is used.
**
** Outputs:
** azPort -- returned as the address of a string containing the terminal name
** of the created terminal. Should be freed with XtFree when no longer needed.
**
*/
char *azDisplay,
char *azParams,
char *azSetup,
char **azPort )
{
DSC_BUFFERZ(dscMailbox, azMailbox, 255);
DSC_BUFFERZ(dscName, azName, 255);
ITEMLIST items[2];
ITEMLIST *pItems = &items[0];
DSC_CONST(dscLNMSYSTEM, azLNMSYSTEM, "LNM$SYSTEM");
DSC_BUFFERZ(dscResult, azResult, 63);
Boolean bResult = True;
unsigned long lStatus;
unsigned long bIsMailbox;
Boolean bExists;
/* First thing we do is see if the controller process is around. If it */
/* isn't we will have to try to create it. */
/* Build the controller mailbox logical name and translate it. */
sprintf(azMailbox, "DECW$DECTERM_MAILBOX_%s", azDisplay);
dscMailbox.dsc$w_length = strlen(azMailbox);
ITEM_RETURNED(pItems, LNM$_STRING, azName, dscName.dsc$w_length);pItems++;
END_OF_ITEMS(pItems);
lStatus = sys$trnlnm (
&(LNM$M_CASE_BLIND),
&dscLNMSYSTEM,
&dscMailbox,
0,
&items[0]);
/* If the name translates, then see if the resulting mailbox really */
/* does exist. */
if (lStatus == SS$_NORMAL) {
lStatus = lib$getdvi (
&(DVI$_MBX),
0,
&dscName,
&bIsMailbox,
0,
0);
bExists = (lStatus == SS$_NORMAL) && ( bIsMailbox);
} else if(lStatus == SS$_NOLOGNAM ) {
bExists = False;
} else {
lib$signal(lStatus);
bResult = False;
}
/* If the controller does not exist, then we need to create it. */
if (bResult && !bExists) {
void TrmMbxAST( void );
DSC_BUFFERZ(dscInput, azInput, 64);
DSC_CONST(dscLoginout, azLoginout, "Sys$System:Loginout.exe");
DSC_CONST(dscNull, azNull, "NL:");
static char *azRunDecterm = "$ Run Sys$System:Decw$Terminal";
DSC_BUFFERZ(dscController, azController, 15);
char azSetDisplay[100];
unsigned long qCurPrivs[2];
unsigned long nTrmUnit;
unsigned short iosb[4];
unsigned long nPriority;
unsigned long lPid;
#ifdef DECTERMDEBUG
DSC_CONST(dscLNMPROCESS,azLNMPROCESS, "LNM$PROCESS");
DSC_CONST(dscSysOutput, azSysOutput, "SYS$OUTPUT");
DSC_BUFFERZ(dscOutput, azOutput, 255);
pItems = &items[0];
ITEM_RETURNED(pItems, LNM$_STRING, azOutput, dscOutput.dsc$w_length);pItems++;
END_OF_ITEMS(pItems);
lStatus = sys$trnlnm (
&(LNM$M_CASE_BLIND),
&dscLNMPROCESS,
&dscSysOutput,
0,
&items[0]);
if (azOutput[0] == '\033') {
dscOutput.dsc$a_pointer += 4;
dscOutput.dsc$w_length -= 4;
}
#else
DSC_CONST(dscOutput, azOutput, "NL:");
#endif /* DECTERMDEBUG */
PERFORM( lib$get_ef(&nInputFlag ));
/* Create a mailbox to feed some DCL commands to the controller */
/* process. */
PERFORM( sys$crembx (
0,
&wInputChannel,
0,
0,
0,
0,
0));
/* Get the physical device name of the input mailbox. */
PERFORM( lib$getdvi (
&(DVI$_DEVNAM),
&wInputChannel,
0,
0,
&dscInput,
&dscInput.dsc$w_length) );
/* Create a mailbox to receive a termination msg if the controller */
/* process fails. */
PERFORM( sys$crembx (
0,
&wTrmChannel,
0,
0,
0,
0,
0) );
/* Need the unit number of the termination mailbox. */
PERFORM( lib$getdvi (
&(DVI$_UNIT),
&wTrmChannel,
0,
&nTrmUnit,
0,
0) );
/* Establish a write attention ast on the termination mailbox. */
PERFORM( sys$qio (
0,
wTrmChannel,
IO$_SETMODE | IO$M_WRTATTN,
0,
0,
0,
TrmMbxAST,
0,
0,
0,
0,
0) );
/* Get our base priority. */
PERFORM( lib$getjpi (
&(JPI$_PRIB),
0,
0,
&nPriority,
0,
0) );
/* Then create a process running Loginout which takes input from */
/* our mailbox. */
strcpy(azController, "TRM_");
strcat(azController, azDisplay);
dscController.dsc$w_length = strlen(azController);
PERFORM( sys$creprc (
&lPid,
&dscLoginout,
&dscInput,
&dscOutput,
&dscNull,
0,
0,
&dscController,
nPriority,
0,
nTrmUnit,
PRC$M_DETACH ));
if (bDebug) {
printf("Controller: %s -- %0lx\n", azController, lPid);
}
/* Now write our DCL commands into that mailbox. */
/* Create the display for the controller. */
strcpy(azSetDisplay, "$ Set Display/Create/Node=");
strcat(azSetDisplay, azDisplay);
PERFORM( sys$qiow (
nInputFlag,
wInputChannel,
IO$_WRITEVBLK,
&iosb,
0,
0,
&azSetDisplay[0],
strlen(azSetDisplay),
0,
0,
0,
0) );
/* Check status of the write. If it failed, then assume that the */
/* controller process failed to get going for some reason. */
if (iosb[0] != SS$_NORMAL){
bResult = False;
}
else {
/* First command succeeded, throw out the next one and hope for */
/* the best. */
PERFORM( sys$qiow (
nInputFlag,
wInputChannel,
IO$_WRITEVBLK,
&iosb,
0,
0,
azRunDecterm,
strlen(azRunDecterm),
0,
0,
0,
0) );
if(iosb[0] != SS$_NORMAL) {
bResult = False;
}
else {
/* Indicate the mailbox is closed just in case the run */
/* fails. */
PERFORM( sys$qio (
nInputFlag,
wInputChannel,
IO$_WRITEOF | IO$M_NOW,
0,
0,
0,
0,
0,
0,
0,
0,
0) );
}
}
/* Release our resources. */
PERFORM( lib$free_ef(&nInputFlag )); nInputFlag = 0;
PERFORM( sys$dassgn ( wInputChannel) ); wInputChannel = 0;
PERFORM( sys$dassgn ( wTrmChannel) ); wTrmChannel = 0;
}
/* If we have a controller process around, proceed with creating the */
/* terminal port. */
if(bResult) {
/* Create the terminal port -- Note the following bug fixes are from */
/* the VMS V5.1-1 release notes. */
fix_DECwTermPort_bug();
/* Signal any creation errors. */
PERFORM( DECwTermPort(azDisplay,
azSetup, azParams, &azResult, &dscResult.dsc$w_length) );
azResult[dscResult.dsc$w_length] = '\0';
/* Return a string containing the port. */
*azPort = XtNewString(azResult);
}
return bResult;
}
/*
**++
** FUNCTIONAL DESCRIPTION:
**
** TranslateEscapes -- copys a string translating escape sequences.
**
** FORMAL PARAMETERS:
**
** The source string and the destination string.
**
** IMPLICIT INPUTS:
**
** none
**
** IMPLICIT OUTPUTS:
**
** none
**
** FUNCTION VALUE:
**
** none
**
** SIDE EFFECTS:
**
** none
**
**--
**/
void TranslateEscapes(
char *pDst,
char *pSrc)
{
while (*pSrc) {
if (*pSrc == '\\') {
pSrc++;
if (*pSrc == 'n') {
*pDst = '\n';
}
else if (*pSrc == 't') {
*pDst = '\t';
}
else if (*pSrc == 'v') {
*pDst = '\v';
}
else if (*pSrc == 'b') {
*pDst = '\b';
}
else if (*pSrc == 'r') {
*pDst = '\r';
}
else if (*pSrc == 'f') {
*pDst = '\f';
}
else if (*pSrc == '\\') {
*pDst = '\\';
}
else if (*pSrc == '\'') {
*pDst = '\'';
}
else if (*pSrc == '"') {
*pDst = '\"';
}
else {
*pDst = *pSrc;
}
}
else {
*pDst = *pSrc;
}
pDst++;
pSrc++;
}
/* And finally the null byte */
*pDst = *pSrc;
}
/*
**++
** FUNCTIONAL DESCRIPTION:
**
** Prints a usage message.
**
** FORMAL PARAMETERS:
**
** none
**
** IMPLICIT INPUTS:
**
** none
**
** IMPLICIT OUTPUTS:
**
** none
**
** FUNCTION VALUE:
**
** none
**
** SIDE EFFECTS:
**
** none
**
**--
**/
static void usage(void)
{
static const char *azHelp[] = {
"Usage is: DECTERM -display node::n.m \n\
-parameters p \n\
-setup setupfile \n\
-define portname \n\
-login ",
" ",
"-display node::n.m -- Specifies display on which terminal window is to be ",
" created. Default is current value of DECW$DISPLAY. ",
" ",
"-parameter \"param: value\\nparam: value...\" -- A quoted string of ",
" DECW$TERMINAL resources, separated by \\n. Default is none. ",
" ",
"-setup setupfile -- a file containing DECW$TERMINAL resources. ",
" Default is DECW$USER_DEFAULTS:DECW$TERMINAL_DEFAULTS.DAT ",
" ",
"-define portname -- A logical name to be given to the port. ",
" Default is DECTERM_PORT ",
" ",
"-login -- Causes a process to be logged in on the port.",
" ",
"? -- Produces this message "
};
int n = 0;
while (n < XtNumber(azHelp)) {
puts(azHelp[n]);
n++;
}
}
/*
* The following is a hack until XrmParseCommand is ready. It determines
* whether or not the given string is an abbreviation of the arg.
*/
static Bool isabbreviation (arg, s, minslen)
char *arg;
char *s;
int minslen;
{
int arglen;
int slen;
/* exact match */
if (strcmp (arg, s) == 0) return (True);
arglen = strlen (arg);
slen = strlen (s);
/* too long or too short */
if (slen >= arglen || slen < minslen) return (False);
/* abbreviation */
if (strncmp (arg, s, slen) == 0) return (True);
/* bad */
return (False);
}
/* DECTERM -- Create a DECTERM window according to command line arguments. */
/* */
/* If necessary will create the DECTERM controller process for the */
/* particular display. */
main(argc, argv)
int argc;
char *argv[];
{
Display *dpy;
char *azDisplay = NULL;
char *azParams = NULL;
char *azPort = NULL;
char *azSetup = NULL;
DSC_CONST(dscLoginout, azLoginout, "Sys$System:Loginout.exe");
$DESCRIPTOR(dscPortLogical,"DECTERM_PORT");
DSC_STATIC(dscPort);
DSC_CONST(dscProcess, azProcess, "LNM$PROCESS");
Boolean bDefine = False;
Boolean bLogin = False;
unsigned long result;
int n = 1;
/* Determine if display and/or parameters specified. */
while (n < argc) {
if (isabbreviation("-display",argv[n], 2)) {
/* Next item better be the display name. */
n++;
azDisplay = argv[n];
}
else if (isabbreviation("-parameters",argv[n],2)) {
/* Next item better be a string of parameters. */
n++;
azParams = XtNewString(argv[n]);
/* Translate the \n to real \n's */
TranslateEscapes(azParams, argv[n]);
}
else if (isabbreviation("-setup",argv[n],2)) {
/* Next item better be a filename. */
n++;
azSetup = argv[n];
}
else if (isabbreviation("-define",argv[n],2)) {
/* Need to define a logical name. */
bDefine = True;
n++;
/* If there is none parameter item following, then that will be */
/* the logical name to be used. */
if((n < argc) && (*argv[n] != '-')) {
char *pSrc;
char *pTemp;
pSrc = XtNewString(argv[n]);
pTemp = pSrc;
while (*pSrc != '\0') {
*pSrc = (char)toupper(*pSrc);
pSrc++;
}
dscPortLogical.dsc$a_pointer = pTemp;
dscPortLogical.dsc$w_length = strlen(pTemp);
}
else {
n--;
};
}
else if (isabbreviation("-login",argv[n],2) ) {
/* They want a logged in process created. */
bLogin = True;
}
else if (isabbreviation("?",argv[n],2)) {
/* They want some help. */
usage();
exit(SS$_NORMAL);
}
else if (isabbreviation("-debug",argv[n],2)) {
bDebug = True;
}
else {
/* Something unrecognized, so give help and terminate. */
usage();
exit(SS$_BADPARAM);
}
n++;
}
/* If display was not specified, then take the default display. */
if(azDisplay == NULL) {
dpy = XOpenDisplay(0);
azDisplay = XtNewString(DisplayString(dpy));
XCloseDisplay(dpy);
}
/* If we have a display, then try to create the terminal port. */
if (azDisplay != NULL) {
if (bDebug) {
printf("Display is <%s>\n", azDisplay);
if (azParams != NULL) {
printf("Params are <%s>\n", azParams);
}
if (azSetup != NULL) {
printf("Setup is <%s>\n", azSetup);
}
}
if(decterm(azDisplay,azParams,azSetup, &azPort)) {
if(bDebug) {
printf("Port is <%s>\n",azPort);
}
dscPort.dsc$a_pointer = azPort;
dscPort.dsc$w_length = strlen(azPort);
/* Define the logical name if requested. */
if(bDefine) {
PERFORM( lib$set_logical (
&dscPortLogical,
&dscPort,
&dscProcess,
0,
0) );
}
result = SS$_NORMAL;
/* Activate LoginOut if requested. */
if (bLogin) {
unsigned long lPid;
unsigned long nPriority;
/* Get our base priority. */
PERFORM( lib$getjpi (
&(JPI$_PRIB),
0,
0,
&nPriority,
0,
0) );
result = sys$creprc (
&lPid,
&dscLoginout,
&dscPort,
&dscPort,
&dscPort,
0,
0,
&dscPort,
nPriority,
0,
0,
PRC$M_DETACH | PRC$M_INTER | PRC$M_NOPASSWORD);
if (bDebug) {
printf("Pid is %0lx\n", lPid);
}
}
}
else {
result = SS$_ABORT;
}
} else {
result = SS$_BADPARAM;
}
exit(result);
}
--------VMS.H-------------------------------------------------------------------
/*
**++
** FACILITY:
**
** Vms.H
**
** ABSTRACT:
**
** Various helpfull things for doing VMS programming from C.
**
** AUTHORS:
**
** M. Erik Husby
**
**
** CREATION DATE: Friday 10-MAR-1989 10:03 AM
**
** MODIFICATION HISTORY:
** M. Erik Husby on Thursday 15-JUN-1989 0:03 PM -- Many stuff lifted from Mike
** Mulligan.
** MEH on Monday 6-NOV-1989 1:44 PM -- Added Ctrl macro.
**
**
**--
**/
#ifndef VMS_H
#define VMS_H TRUE
/*
**
** MACRO DEFINITIONS
**
**/
/* Performs a system service and checks for a successful result. */
/* Non-successful results are signaled. */
#define PERFORM(a) \
{ \
unsigned long status = a; \
if ( !(status & 1)) \
lib$signal(status); \
}
/* An itemlist strucutre. */
typedef struct
{
short bufsiz; /* Target buffer size. */
short itmcod; /* Item code. */
void *bufadr; /* Targe buffer address. */
short *retlen; /* Address of word to receive buffer length. */
} ITEMLIST;
#define ITEM(list, code, buffer) \
(list)->bufsiz = sizeof buffer; \
(list)->itmcod = code; \
(list)->bufadr = (void *)&buffer; \
(list)->retlen = (short *)0;
#define ITEM_RETURNED(list, code, buffer, returned_length) \
(list)->bufsiz = sizeof buffer; \
(list)->itmcod = code; \
(list)->bufadr = (void *)&buffer; \
(list)->retlen = (short *)&returned_length;
#define END_OF_ITEMS(list) \
(list)->bufsiz = 0; \
(list)->itmcod = 0; \
(list)->bufadr = (void *)0; \
(list)->retlen = (short *)0;
/* Types and data structures found on VAX/VMS ... */
typedef struct quad { unsigned long low; long high; } quad;
#define PRCNAM_MAX 15
#define USERNAME_MAX 12
#define NODENAME_MAX 15
#define RESOURCENAME_MAX 31
#define DEVICENAME_MAX 15
#define TICKS_PER_SECOND (-10000000)
typedef quad SYSTEM_TIME;
typedef unsigned long PID;
typedef quad PRIVILEGES;
#define GETMSG_DEFAULT 0
#define GETMSG_TEXT 1
#define GETMSG_IDENT 2
#define GETMSG_SEVERITY 4
#define GETMSG_FACILITY 8
typedef unsigned short CHANNEL, UNIT;
typedef struct IOSB {
unsigned short status;
unsigned short io_length;
unsigned : 32;
} IOSB;
typedef struct LKSB { /* Lock status block */
unsigned short status;
unsigned : 16;
unsigned long lock_id;
} LKSB;
#define VALUE_BLOCK_SIZE 16
typedef struct LKSB_VB { /* Lock status block with value */
unsigned short status; /* block */
unsigned : 16;
unsigned long lock_id;
char value_block[VALUE_BLOCK_SIZE];
} LKSB_VB;
typedef struct LKI_RETLEN { /* special return length for */
unsigned short length; /* sys$getlki */
unsigned field_length : 15;
unsigned too_small : 1;
} LKI_RETLEN;
/* Get System Service Info, for getjpi, getsyi, getuai, getlki ... */
typedef struct GETSSI_ITEM {
short length;
short code;
char *buffer;
short *retlen;
} GETSSI_ITEM;
#define GETSSI_ITEMV(code, place) \
{ sizeof (place), code, &(place), NULL }
#define GETSSI_ITEMR(code, place, retlenadr) \
{ sizeof (place) - sizeof '\0', code, &(place), (retlenadr) }
#define GETSSI_ITEMZ(code) \
{ 0, code, NULL, NULL }
/*
* File Scan system service data ...
*/
typedef struct FSCN_ITEM {
unsigned short item_length;
unsigned short item_code;
char *item;
} FSCN_ITEM;
#define FSCN_ITEMZ(code) \
{ 0, code, 0 }
/*
* Use niftier (reentrant for use with ast's) versions of c rtl routines
*/
#define malloc VAXC$MALLOC_OPT
#define calloc VAXC$CALLOC_OPT
#define free VAXC$FREE_OPT
#define cfree VAXC$CFREE_OPT
#define realloc VAXC$REALLOC_OPT
#ifndef _DESCRIPX
#define _DESCRIPX '1'
/*
* Add a few more hooks to the standard DESCRIP.H
*/
#ifndef $DESCRIPTOR
#include <descrip>
#endif
typedef struct dsc$descriptor dsc_t;
#define DSC_LITERAL(dsc, private, string) \
static const char private[] = string; \
globaldef const dsc_t dsc = \
{ (sizeof private)-1, DSC$K_DTYPE_T, DSC$K_CLASS_S, private }
#define DSC_CONST(dsc, private, string) \
static const char private[] = string; \
static const dsc_t dsc = \
{ (sizeof private)-1, DSC$K_DTYPE_T, DSC$K_CLASS_S, private }
#define DSC_STATIC(dsc) \
dsc_t dsc = \
{ 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL }
#define DSC_DYNAMIC(dsc) \
dsc_t dsc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_D, NULL }
#define DSC_BUFFER(dsc, private, size) \
char private[size]; \
dsc_t dsc = \
{ sizeof private, DSC$K_DTYPE_T, DSC$K_CLASS_S, private }
#define DSC_BUFFERZ(dsc, private, size) \
char private[size + 1 /* for '\0' */ ]; \
dsc_t dsc = \
{ sizeof private - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, private }
#define DSC_RECORD(dsc, type_def, record) \
type_def record; \
dsc_t dsc = \
{ sizeof (record), DSC$K_DTYPE_T, DSC$K_CLASS_S, &(record) }
#define DSC_OF(dsc, variable) \
dsc_t dsc = \
{ sizeof (variable), DSC$K_DTYPE_T, DSC$K_CLASS_S, &(variable) }
#define DSC(dsc, length, pointer) \
dsc_t dsc = \
{ (length), DSC$K_DTYPE_T, DSC$K_CLASS_S, (pointer) }
#define DSC_ASCIZ(dsc, asciz) \
dsc_t dsc = \
{ strlen(asciz), DSC$K_DTYPE_T, DSC$K_CLASS_S, (asciz) }
#endif /* _DESCRIPX */
#define Ctrl(a) (char)('a' - 64)
#endif /* VMS_H */
---DECTERM.OPT-----------------------------------------------------------------
DECTERM,SYS$SHARE:DECW$TERMINALSHR/SHARE
---DECTERM.MMS------------------------------------------------------------------
!
! Dependency File For: Decterm.exe
!
! Author: M. Erik Husby
!
! Created On: Monday 2-OCT-1989 09:56 AM
!
! Modifications:
!
! Notes: {tbs}
!
.first
define vaxc$include sys$library:,decw$include:
decterm.exe : decterm.obj, decterm.opt
$(link) $(linkflags) decterm/opt
decterm.obj : decterm.c
--VUE_DECTERM.COM---------------------------------------------------------------
$ save_verify = 'f$verify(0)' ! Make the 1 a 0 when procedure debugged.
$ goto skip_header
$ !
$ ! Vue_DECTerm.com
$ !
$ ! Procedure to: Start a DECTerm window.
$ !
$ ! Author: M. Erik Husby, on Thursday 5-OCT-1989 4:49 PM
$ !
$ ! Modifications:
$ !
$ ! Calling sequence: @Vue_DECTerm <<parameters>>...
$ !
$ skip_header:
$ exit_status=1 ! SS$_NORMAL
$ !
$ VUE$SUPPRESS_OUTPUT_POPUP
$ self = f$environment("PROCEDURE")
$ decterm = "$" + f$parse(self,,,"DEVICE") + f$parse(self,,,"DIRECTORY") + "decterm"
$ decterm 'P1' 'P2' 'P3' 'P4' 'P5' 'P6' 'P7' 'P8'
$ !
$ ! all done:
$ !
$ exit_com:
$ exit 'exit_status' ! 'f$verify(save_verify)' Restore verify status
--End of file-------------------------------------------------------------------
|