From: Fred Kleinsorge [kleinsorge@star.enet.dec_nospam.com] Sent: Tuesday, August 10, 1999 12:23 PM To: Info-VAX@Mvb.Saic.Com Subject: Re: Setting SRM console variables from within OpenVMS ? Chris King wrote: > > Does anyone know if there is a VMS equivalent of the Tru64 "consvar" > command to set SRM console variables ? > > I'm trying to find a way of automating standalone system disk backups, > so I can perform them more regularly, and at times when users aren't on > the machine. > Enjoy... /* 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 bootdef_dev */ arglist [0] = 3; arglist [1] = HW 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; }