From: hoffman@xdelta.zko.dec.nospam Sent: Monday, August 02, 1999 6:15 PM To: Info-VAX@Mvb.Saic.Com Subject: Re: Setting SRM console variables from within OpenVMS ? In article , Chris King writes: :Does anyone know if there is a VMS equivalent of the Tru64 "consvar" :command to set SRM console variables ? Ayup. You can use the (now documented) sys$getenv call to read the console environment variables. This call has been around for years, but is now documented with OpenVMS Alpha V7.2. To set the console environment variables you could: o poke around and look for an (undocumented) sys$setenv call that might just happen to exist. :-) If you should find this routine, the API might be structured and might work just like the sys$getenv() call, and it might even explain the "ST" prefix on all those sys$getenv() symbol definitions. :-) I'd expect that any sys$setenv call found would probably require the caller to have CMKRNL privilege. :-) o you could use something akin to attached get_env() and set_env() routines in the example program attached below. The attached example C code does not use documented or supported interfaces, and -- like any other kernel code -- it might just crash your OpenVMS system, and it might require a rebuild after an ECO or upgrade. CMKRNL privilege is required. --------------------------- pure personal opinion --------------------------- Hoff (Stephen) Hoffman OpenVMS Engineering hoffman#xdelta.zko.dec.com /* * DEFAULT_BOOT -- reads environment variable bootdef_dev and * writes its value to environment variable boot_dev * * This program is designed to emulate VAX style shutdown/reboot * behaviour on Alpha machines. On VAX, on a shutdown/reboot invoked * from VMS, the reboot occurs from the default boot device. On Alpha, * the reboot occurs from the device from which you last successfully * booted. This program copies environment variable BOOTDEF_DEV * (default boot device list) to BOOT_DEV (device list used by the last * bootstrap attempt), which effectively causes the reboot to occur from * the device(s) specified in BOOTDEF_DEV. * * This program is useful, for example, if you occasionally boot an * alternate system disk and you want the reboot to occur from your * usual system disk. In this case you may do something like: * * $ run default_boot * $ reboot * * The default_boot program will copy BOOTDEF_DEV to BOOT_DEV, and * the reboot will occur using the device list in BOOTDEF_DEV. * * You must have CMKRNL priviledge to run this program. It is * recommended that only one copy of this program runs at any one time. * */ #pragma module default_boot #include #include #include #include #include #include /* Local definitions */ #define BUF$K_LENGTH 132 /* External global variables */ extern HWRPB *exe$gpq_hwrpb; /* External routines */ extern int sys$cmkrnl (); extern void exit (); extern int strlen (); /* Routines defined in this module */ uint64 get_env (); uint64 set_env (); /* * Global array to associate environment variable numbers with * strings. Though it does not say so in the SRM, some of the * environment variables can be returned in different forms. For * example, if you say ...get_env ("bootdef_dev") you get the * name of the boot device in the form dka0.0.2.6.0. But if * you say ...get_env (3) you get the full path of the boot * device SCSI 0 0 2 6 0 -- very different. So, here I am * making a table which can be indexed by environment variable * number. The entries point to strings corresponding to the * environment variable number. See page 2-27 in the console * chapter of the SRM. */ static char *env_strings [] = { "reserved", "auto_action", "boot_dev", "bootdef_dev", "booted_dev", "boot_file", "booted_file", "boot_osflags", "booted_osflags", "boot_reset", "dump_dev", "enable_audit", "license", "char_set", "language", "tty_dev" }; main (argc, argv) int argc; char *argv []; { int status; int i; int num_bytes; int arglist [6]; char bootdef_dev [BUF$K_LENGTH]; char boot_dev [BUF$K_LENGTH]; uint64 callback_status; /* Initialize character buffers with zeros */ for (i=0; i++; i < BUF$K_LENGTH) { bootdef_dev [i] = (char) 0; boot_dev [i] = (char) 0; } /* Call kernel routine to read environment variable */ for (i=0; i++; i < BUF$K_LENGTH) { bootdef_dev [i] = (char) 0; boot_dev [i] = (char) 0; } /* Call kernel routine to read environment variable bootdef_dev */ arglist [0] = 3; arglist [1] = HWRPB_CRB$K_BOOTCMD_DEV, arglist [2] = (int) bootdef_dev; arglist [3] = (int) &callback_status; status = sys$cmkrnl (get_env, arglist); if (!(status & 1)) exit (status); /* * Console callbacks return status in bits 63:61. For get_env, * if the status is success, the number of bytes returned is * in the lower longword of the status quadword. So, break the * status into two longwords and look it over. */ status = callback_status >> 61; num_bytes = callback_status; /* * The callback status is as follows (now in bits 2:0) * 000 = success * 001 = success, byte stream truncated * 110 = environment variable not recognized */ switch (status) { case 0: /* Success */ break; case 1: { /* Success, but byte stream truncated. Display * what we got and exit. */ printf ("BOOTDEF_DEV partially read. %d bytes read\n", num_bytes); printf ("BOOTDEF_DEV : %s\n", bootdef_dev); printf ("BOOT_DEV not updated. Exiting...\n"); exit (0); } case 6: { printf ("Environment variable not recognized. Exiting...\n"); exit (0); } default: { printf ("Unknown status returned by get_env: %d\n", status); printf ("Exiting...\n"); exit (0); } } /* end switch (status) */ /* * We now have BOOTDEF_DEV. Use set_env to write BOOTDEF_DEV to * BOOT_DEV. */ arglist [0] = 3; arglist [1] = HWRPB_CRB$K_BOOT_DEV; /* EV to be written */ arglist [2] = (int) bootdef_dev; /* String to be written to EV */ arglist [3] = (int) &callback_status; status = sys$cmkrnl (set_env, arglist); if (!(status & 1)) exit (status); /* * Console callbacks return status in bits 63:61. For set_env, * if the status is success, everything is written. * Break the status into two longwords and look it over. */ status = callback_status >> 61; num_bytes = callback_status; /* * The set_env callback status is as follows (in bits 2:0) * 000 = success * 100 = fail, variable is read only * 110 = environment variable not recognized * 111 = fail, byte stream exceeds value length */ if (status != 0) { printf ("SET_ENV (boot_dev) failed. Callback status : %d\n", status); printf ("Exiting...\n"); exit (0); } exit (SS$_NORMAL); } uint64 get_env (int env_number, char *buffer, uint64 *callback_status) /* * Routine get_env -- performs get_env console callback to read * specified environment variable * * INPUTS * env_number Number of environment variable. * See SRM or HWRPBDEF.H * buffer pointer to an array of characters. * On success, the requested env. * variable is written to this array. * callback_status Pointer to a quadword. The status * of the get_env console callback * is returned in this quadword. * * OUTPUTS * SS$_NORMAL The callback executed, the actual * status of the callback returned * in callback_status. */ { uint64 status; HWRPB_CRB *crb; uint64 (* dispatch)(); crb = (HWRPB_CRB *) ((int)exe$gpq_hwrpb + exe$gpq_hwrpb->hwrpb$iq_crb_offset); dispatch = (uint64 (*)()) crb->hwrpb_crb$il_va_dispatch_pd_l; /* Execute get_env console callback to read bootdef_dev */ /* * status = (uint64) dispatch (HWRPB_CRB$K_GET_ENV, * env_number, * buffer, * BUF$K_LENGTH); */ status = (uint64) dispatch (HWRPB_CRB$K_GET_ENV, env_strings [env_number], buffer, BUF$K_LENGTH); *callback_status = status; return SS$_NORMAL; } uint64 set_env (int env_number, char *buffer, uint64 *callback_status) /* * Routine set_env -- performs set_env console callback * to write specified environment variable * * INPUTS * env_number environment variable to be written * buffer pointer to an array of characters. * On success, this string is written * to the specified EV. * callback_status Pointer to a quadword. The status * of the get_env console callback * is returned in this quadword. * * OUTPUTS * SS$_NORMAL The callback executed, the actual * status of the callback returned * in callback_status. */ { uint64 status; HWRPB_CRB *crb; uint64 (* dispatch)(); crb = (HWRPB_CRB *) ((int)exe$gpq_hwrpb + exe$gpq_hwrpb->hwrpb$iq_crb_offset); dispatch = (uint64 (*)()) crb->hwrpb_crb$il_va_dispatch_pd_l; status = (uint64) dispatch (HWRPB_CRB$K_SET_ENV, env_strings [env_number], buffer, strlen (buffer)); *callback_status = status; return SS$_NORMAL; }