[comp.os.vms] Using SYS$TRNLNM, plus other goodies

carl@CITHEX.CALTECH.EDU (02/16/88)

A while back, somebody wrote to this teleconference asking about  how  to  use
sys  system  service  $TRNLNM from C.  The closest thing I saw to an answer to
his question was somebody's response telling him how to  use  LIB$TRNLNM.   At
various  times,  others  have  written in asking how to do quadword arithmetic
(necessary if you're going to fool around with the various VMS time services).
Finally,  I've had several users who were amazed by the things you can do with
DECnet tasks.  Therefore, I offer, as a  programming  example,  the  following
program that involves all three:  It calculates the time the system's been up,
formats it into a delta time, and displays  it  to  SYS$NET:   if  it  exists,
otherwise to SYS$OUTPUT:.

/******************************************************************************\
 * UPTIME.C -- print out how long the system's been up                        *
\******************************************************************************/
/*	include standard system definitions                                   */
#include descrip                    
#include stdio
#include syidef

/*	define IO status block for $GETSYIW service                           */
struct IOSBLK {
	long sts, reserved;
};

/*	define item list structure for $GETSYI and $TRNLNM services           */
struct ITEM_LIST_3 {
	short buflen, itmcod;
	long *bufadr, *retadr;
};

main()
{	long boot_time[2], now[2], uptime[2];
	short retlen;
	struct IOSBLK iosb;
	long stat;
	char timstr[64], *buff, *trnlnm();
	FILE *fp;
	$DESCRIPTOR(timbuf, timstr);
/* declare and initialize itmlst for $GETSYI service                          */
	struct ITEM_LIST_3 itmlst[2] =
		{ 8, SYI$_BOOTTIME, boot_time, &retlen, 0, 0, 0, 0 };

/*	get system boot time                                                  */
	if ((((stat = SYS$GETSYI(0, 0, 0, &itmlst, &iosb, 0, 0)) & 7) != 1) ||
		(((stat = iosb.sts) & 7) != 1))
		exit(stat);
/*	get current time                                                      */
	if (((stat = SYS$GETTIM(now)) & 7) != 1)
		exit(stat);
/*	subtract current time from boot time to get uptime as a delta time    */
	if (((stat = LIB$SUBX(boot_time, now, uptime, 0)) & 7) != 1)
		exit(stat);
/*	convert uptime to ascii                                               */
	if (((stat = SYS$ASCTIM(&retlen, &timbuf, uptime, 0)) & 7) != 1)
		exit(stat);
	timstr[retlen] = '\0';
/*	find out what node we're on; default to node 0::                      */
	if ((buff = trnlnm("LNM$SYSTEM", "SYS$NODE")) == 0)
		buff = "0::";
	buff[strlen(buff)-1] = '\0';
/*	try to open SYS$NET: If unsuccessful, output to SYS$OUTPUT:           */
	if ((fp = fopen("SYS$NET:", "w")) == 0)
		fp = stdout;
	fprintf(fp, "Uptime for node %s\t%s\n", buff, timstr);
}

#include lnmdef

char *trnlnm(tabname, logname)
{	$DESCRIPTOR(tabnam, "");
	$DESCRIPTOR(lognam, "");
	long stat;
	static char buffer[256];
	short retadr;
/*	declare & initialize itmlst for SYS$TRNLNM service                    */
	struct ITEM_LIST_3 itmlst[2] =
		{ 255, LNM$_STRING, buffer, &retadr, 0, 0, 0, 0 };

/*	set up descriptors for logical and table names                        */
	tabnam.dsc$w_length = strlen(tabname);
	tabnam.dsc$a_pointer = tabname;
	lognam.dsc$w_length = strlen(logname);
	lognam.dsc$a_pointer = logname;
/*	try to translate the logical name                                     */
	if (((stat = SYS$TRNLNM(0, &tabnam, &lognam, 0, itmlst, 0)) & 7) != 1)
		return(0);
	buffer[retadr] = '\0';
	return(buffer);
}
/******************************************************************************\
 * End of file UPTIME.C                                                       *
\******************************************************************************/

To make it easy to use as a DECnet object, put the executable in a safe
place (on CITHEX, it's in the directory HEP$UTIL:), then use a command of
the form:
	$ MCR NCP DEFINE OBJECT UPTIME NUMBER 0 FILE hep$util:UPTIME.EXE
to enter it in the permanent DECnet database, and the command:
	$ MCR NCP SET OBJECT UPTIME ALL
to put it in the volatile database.  A command of the form:
	$ TYPE yournode::"0=UPTIME"
then displays how long the system's been up in the format:
	Uptime for node CITHEX:	   1 19:52:02.02