summaryrefslogtreecommitdiffstats
path: root/contrib/romid/setenvs.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/romid/setenvs.c')
-rw-r--r--contrib/romid/setenvs.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/contrib/romid/setenvs.c b/contrib/romid/setenvs.c
new file mode 100644
index 00000000..e18e399e
--- /dev/null
+++ b/contrib/romid/setenvs.c
@@ -0,0 +1,200 @@
+/* subroutine to put a value string into an environment symbol.
+ Uses the controling command.com environment, not the programs.
+ This means that the env variable is set so other routines in
+ a .BAT file may use it.
+
+ call: settheenv (char * symbol, char * val);
+ symbol is an asciiz string containing the env variable name,
+ val is an asciiz string containing the value to assign to this vbl.
+
+ returns: 0 = OK,
+ 1 = failure.
+ failure is not unlikely. The env block may be full. Or on some
+ systems the env block might not be found
+
+ SETENVS.C was written by Richard Marks <rmarks@KSP.unisys.COM>.
+*/
+
+
+#include <stdio.h>
+#include <dos.h>
+#include <string.h>
+#include <stdlib.h>
+
+typedef struct {
+ char fill1[0x0A];
+ int *prev_term_handler;
+ int *prev_ctrl_c;
+ int *prev_crit_error;
+ char fill2[0x16];
+ int envir_seg;
+} psp;
+
+typedef struct {
+ char type;
+ int psp_segment;
+ int num_segments;
+ char fill[11];
+ char arena_data;
+} arena;
+
+
+#define NORMAL_ATYPE 0x4D
+#define LAST_ATYPE 0x5A
+
+
+static arena * get_next_arena (arena * ap) {
+ return( MK_FP( FP_SEG(ap)+1+ap->num_segments, 0) );
+}
+
+/* returns 0 if passed pointer is to an arena, else returns 1 */
+static int is_valid_arena (arena * ap) {
+ arena * ap1;
+ if (ap->type == NORMAL_ATYPE &&
+ (ap1=get_next_arena(ap))->type == NORMAL_ATYPE &&
+ ( (ap1=get_next_arena(ap1))->type == NORMAL_ATYPE ||
+ ap1->type == LAST_ATYPE) )
+ return(0);
+ return (1);
+}
+
+
+static arena * get_first_arena () {
+/* return pointer to the first arena.
+ * scan memory for a 0x4D on a segment start,
+ * see if this points to another two levels of arena
+ */
+ arena * ap, * ap1;
+ int * temp;
+ int segment;
+
+ for (segment=0; segment<_CS; segment++) {
+ ap = MK_FP(segment, 0);
+ if ( is_valid_arena (ap) == 0) return (ap);
+ }
+ return(NULL);
+} /* end get_first_arena */
+
+
+static int is_valid_env (char * ad, int num_segs) {
+ char * base_ad;
+ base_ad = ad;
+ while ( (*ad) && (((ad-base_ad)>>4) < num_segs) ) {
+ if (strnicmp(ad, "COMSPEC=", 8)==0) return(0);
+ ad += strlen(ad) + 1;
+ }
+ return (1);
+}
+
+
+static arena * get_arena_of_environment () {
+/* to get the arena of first environment block:
+ First get segment of COMMAND.COM from segment of previous critical err code.
+ Then scan all the arenas for an environment block with a matching PSP
+ segment */
+
+arena * ap;
+psp * pspp, * pspc;
+unsigned int i, ccseg;
+
+/* set pspp to psp of this program */
+pspp = MK_FP(_psp,0);
+
+#ifdef DEBUG
+printf("prog psp=%p\n",pspp);
+#endif
+
+/* set pspc to psp of COMMAND.COM, back up a bit to get it if needed */
+ccseg = FP_SEG (pspp->prev_crit_error);
+if ( (i=ccseg-32) < 60) i=60;
+
+while (ccseg>i) {
+ pspc = MK_FP (ccseg, 0);
+ if ( is_valid_arena((arena *) pspc) == 0) goto L1;
+ ccseg--;
+}
+return (NULL);
+
+L1: pspc = MK_FP (++ccseg, 0);
+#ifdef DEBUG
+printf("comm.com=%p\n",pspc);
+#endif
+
+/* first see if env seg in command.com points to valid env block
+ if env seg is in a valid arena, then arena must point to this command.com
+ else assume env block is fabricated like for 4DOS, use 128 bytes */
+
+ap = MK_FP (pspc->envir_seg-1, 0);
+i = ap->num_segments;
+
+if (is_valid_arena (ap) == 0) {
+ if (ap->psp_segment != FP_SEG(pspc)) goto L2;
+} else {
+ i = 9;
+}
+
+if ( is_valid_env (&ap->arena_data, i) == 0 )
+ return (ap);
+
+/* command.com did not so point, search thru all env blocks */
+
+L2:
+if ( (ap=get_first_arena()) != NULL ) {
+ while (ap->type != LAST_ATYPE) {
+#ifdef DEBUG
+ printf("%p\n",ap);
+#endif
+ if (ap->psp_segment == FP_SEG(pspc) &&
+ is_valid_env (&ap->arena_data, ap->num_segments)==0 )
+ return (ap);
+
+ ap = get_next_arena(ap);
+ }
+} return(NULL);
+} /* end get_arena_of_environment */
+
+/*****************************************************************************/
+
+int settheenv(char * symbol, char * val) {
+int total_size,
+ needed_size=0,
+ strlength;
+char * sp, *op, *envir;
+char symb_len=strlen(symbol);
+char found=0;
+arena * ap;
+
+strupr(symbol);
+
+/* first, can COMMAND.COM's envir block be found ? */
+if ( (ap=get_arena_of_environment()) == NULL)
+ return(1);
+
+/* search to end of the envir block, get sizes */
+total_size = 16 * ap->num_segments;
+envir = &ap->arena_data;
+op=sp=envir;
+while (*sp) {
+ strlength = strlen(sp)+1;
+ if ( *(sp+symb_len)=='=' &&
+ strnicmp(sp,symbol,symb_len)==0 )
+ found=1;
+ else {
+ needed_size += strlength;
+ if (found) strcpy(op,sp);
+ op = &op[strlength];
+ }
+ sp += strlength;
+}
+*op=0;
+if (strlen(val) > 0) {
+ needed_size += 3 + strlen(symbol) + strlen(val);
+ if (needed_size > total_size)
+ return(1); /* could mess with environment expansion here */
+
+ strcpy(op, symbol); strcat(op, "="); strcat(op, val);
+ op += strlen(op)+1;
+ *op = 0;
+}
+return(0);
+} /* end setheenv subroutine */