[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference hydra::axp-developer

Title:Alpha Developer Support
Notice:[email protected], 800-332-4786
Moderator:HYDRA::SYSTEM
Created:Mon Jun 06 1994
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:3722
Total number of notes:11359

3367.0. "PeerLogic" by HYDRA::VANORDEN () Thu Mar 20 1997 09:28

    Company Name :  PeerLogic
    Contact Name :  Jackie Wong
    Phone        :  
    Fax          :  
    Email        :  [email protected]
    Date/Time in :  20-MAR-1997 09:27:25
    Entered by   :  Donna Van Orden
    SPE center   :  MRO

    Category     :  VMS
    OS Version   :  
    System H/W   :  


    Brief Description of Problem:
    -----------------------------

From:	SMTP%"[email protected]" 19-MAR-1997 17:36:43.48
To:	[email protected]
CC:	[email protected]
Subj:	technical question

Return-Path: [email protected]
Received: by asimov.mro.dec.com (UCX V4.1-12, OpenVMS V6.2 VAX);
	Wed, 19 Mar 1997 17:36:41 -0500
Received: from pobox1.pa.dec.com by fluid.mro.dec.com (5.65v4.0/1.1.8.2/19Nov96-0448PM)
	id AA26908; Wed, 19 Mar 1997 17:36:54 -0500
Received: by pobox1.pa.dec.com; id AA10472; Wed, 19 Mar 97 14:36:54 -0800
Received: from ns1.cityselect.com by mail2.digital.com (5.65 EXP 4/12/95 for V3.2/1.0/WV)
	id AA31347; Wed, 19 Mar 1997 14:32:35 -0800
Received: by gatekeeper.peerlogic.com id AA12079
  (5.67b/IDA-1.5 for <[email protected]>); Wed, 19 Mar 1997 13:33:11 -0800
Received: from mailhost.peerlogic.com(204.31.26.89) by gatekeeper via smap (V1.3)
	id sma012070; Wed Mar 19 13:33:00 1997
Received: from nirvana.peerlogic.com. (nirvana.peerlogic.com) by internal-dns.peerlogic.com with SMTP id AA03884
  (5.67b/IDA-1.5 for <[email protected]>); Wed, 19 Mar 1997 14:30:28 -0800
Message-Id: <[email protected]>
Received: by nirvana.peerlogic.com
	(1.40.112.4/16.2) id AA255120580; Wed, 19 Mar 1997 14:29:40 -0800
Date: Wed, 19 Mar 1997 14:29:40 -0800
From: Jackie Wong <[email protected]>
To: [email protected]
Subject: technical question
Cc: [email protected]
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Md5: dFq2qT8dNFeOgFRQz6Cfdw==

Could you please direct me on how we can translate the logical names
in a C program.

There is are lexical functions (F$LOGICAL and F$TRNLNM) to translate logical
names in a "command procedure", but I need to find a way to translate
the logical name in a C program.

Thank you.

-jackie

T.RTitleUserPersonal
Name
DateLines
3367.1HYDRA::SCHAFERMark Schafer, SPE MROThu Mar 20 1997 10:021206
    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-------------------------------------------------------------------
    
3367.2HYDRA::VANORDENThu Mar 20 1997 11:4427
    
    I mailed the previous reply (thanks Mark!) to Jackie with the following
    introduction.  I'm going to assume this answers her question and close
    for now.  We can reopen if we hear from her again.
    
    Donna VO
    
    __________________________
    
    Jackie,
    
    
    The following response and code comes from the VMS Freeware CD and
    appears
    to be relevant to your question.  As with all freeware, the answer and
    code are "as is".
    
    If you have any further questions regarding this topic, please do not
    hesitiate
    to reply to this mail message and reference call number 1997-3367.
    
    Good Luck!
    
    Donna Van Orden
    Alpha Developer Support
    
    --------Attachment Below------------------------------------