setenvs.c 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /* subroutine to put a value string into an environment symbol.
  2. Uses the controling command.com environment, not the programs.
  3. This means that the env variable is set so other routines in
  4. a .BAT file may use it.
  5. call: settheenv (char * symbol, char * val);
  6. symbol is an asciiz string containing the env variable name,
  7. val is an asciiz string containing the value to assign to this vbl.
  8. returns: 0 = OK,
  9. 1 = failure.
  10. failure is not unlikely. The env block may be full. Or on some
  11. systems the env block might not be found
  12. SETENVS.C was written by Richard Marks <rmarks@KSP.unisys.COM>.
  13. */
  14. #include <stdio.h>
  15. #include <dos.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. typedef struct {
  19. char fill1[0x0A];
  20. int *prev_term_handler;
  21. int *prev_ctrl_c;
  22. int *prev_crit_error;
  23. char fill2[0x16];
  24. int envir_seg;
  25. } psp;
  26. typedef struct {
  27. char type;
  28. int psp_segment;
  29. int num_segments;
  30. char fill[11];
  31. char arena_data;
  32. } arena;
  33. #define NORMAL_ATYPE 0x4D
  34. #define LAST_ATYPE 0x5A
  35. static arena * get_next_arena (arena * ap) {
  36. return( MK_FP( FP_SEG(ap)+1+ap->num_segments, 0) );
  37. }
  38. /* returns 0 if passed pointer is to an arena, else returns 1 */
  39. static int is_valid_arena (arena * ap) {
  40. arena * ap1;
  41. if (ap->type == NORMAL_ATYPE &&
  42. (ap1=get_next_arena(ap))->type == NORMAL_ATYPE &&
  43. ( (ap1=get_next_arena(ap1))->type == NORMAL_ATYPE ||
  44. ap1->type == LAST_ATYPE) )
  45. return(0);
  46. return (1);
  47. }
  48. static arena * get_first_arena () {
  49. /* return pointer to the first arena.
  50. * scan memory for a 0x4D on a segment start,
  51. * see if this points to another two levels of arena
  52. */
  53. arena * ap, * ap1;
  54. int * temp;
  55. int segment;
  56. for (segment=0; segment<_CS; segment++) {
  57. ap = MK_FP(segment, 0);
  58. if ( is_valid_arena (ap) == 0) return (ap);
  59. }
  60. return(NULL);
  61. } /* end get_first_arena */
  62. static int is_valid_env (char * ad, int num_segs) {
  63. char * base_ad;
  64. base_ad = ad;
  65. while ( (*ad) && (((ad-base_ad)>>4) < num_segs) ) {
  66. if (strnicmp(ad, "COMSPEC=", 8)==0) return(0);
  67. ad += strlen(ad) + 1;
  68. }
  69. return (1);
  70. }
  71. static arena * get_arena_of_environment () {
  72. /* to get the arena of first environment block:
  73. First get segment of COMMAND.COM from segment of previous critical err code.
  74. Then scan all the arenas for an environment block with a matching PSP
  75. segment */
  76. arena * ap;
  77. psp * pspp, * pspc;
  78. unsigned int i, ccseg;
  79. /* set pspp to psp of this program */
  80. pspp = MK_FP(_psp,0);
  81. #ifdef DEBUG
  82. printf("prog psp=%p\n",pspp);
  83. #endif
  84. /* set pspc to psp of COMMAND.COM, back up a bit to get it if needed */
  85. ccseg = FP_SEG (pspp->prev_crit_error);
  86. if ( (i=ccseg-32) < 60) i=60;
  87. while (ccseg>i) {
  88. pspc = MK_FP (ccseg, 0);
  89. if ( is_valid_arena((arena *) pspc) == 0) goto L1;
  90. ccseg--;
  91. }
  92. return (NULL);
  93. L1: pspc = MK_FP (++ccseg, 0);
  94. #ifdef DEBUG
  95. printf("comm.com=%p\n",pspc);
  96. #endif
  97. /* first see if env seg in command.com points to valid env block
  98. if env seg is in a valid arena, then arena must point to this command.com
  99. else assume env block is fabricated like for 4DOS, use 128 bytes */
  100. ap = MK_FP (pspc->envir_seg-1, 0);
  101. i = ap->num_segments;
  102. if (is_valid_arena (ap) == 0) {
  103. if (ap->psp_segment != FP_SEG(pspc)) goto L2;
  104. } else {
  105. i = 9;
  106. }
  107. if ( is_valid_env (&ap->arena_data, i) == 0 )
  108. return (ap);
  109. /* command.com did not so point, search thru all env blocks */
  110. L2:
  111. if ( (ap=get_first_arena()) != NULL ) {
  112. while (ap->type != LAST_ATYPE) {
  113. #ifdef DEBUG
  114. printf("%p\n",ap);
  115. #endif
  116. if (ap->psp_segment == FP_SEG(pspc) &&
  117. is_valid_env (&ap->arena_data, ap->num_segments)==0 )
  118. return (ap);
  119. ap = get_next_arena(ap);
  120. }
  121. } return(NULL);
  122. } /* end get_arena_of_environment */
  123. /*****************************************************************************/
  124. int settheenv(char * symbol, char * val) {
  125. int total_size,
  126. needed_size=0,
  127. strlength;
  128. char * sp, *op, *envir;
  129. char symb_len=strlen(symbol);
  130. char found=0;
  131. arena * ap;
  132. strupr(symbol);
  133. /* first, can COMMAND.COM's envir block be found ? */
  134. if ( (ap=get_arena_of_environment()) == NULL)
  135. return(1);
  136. /* search to end of the envir block, get sizes */
  137. total_size = 16 * ap->num_segments;
  138. envir = &ap->arena_data;
  139. op=sp=envir;
  140. while (*sp) {
  141. strlength = strlen(sp)+1;
  142. if ( *(sp+symb_len)=='=' &&
  143. strnicmp(sp,symbol,symb_len)==0 )
  144. found=1;
  145. else {
  146. needed_size += strlength;
  147. if (found) strcpy(op,sp);
  148. op = &op[strlength];
  149. }
  150. sp += strlength;
  151. }
  152. *op=0;
  153. if (strlen(val) > 0) {
  154. needed_size += 3 + strlen(symbol) + strlen(val);
  155. if (needed_size > total_size)
  156. return(1); /* could mess with environment expansion here */
  157. strcpy(op, symbol); strcat(op, "="); strcat(op, val);
  158. op += strlen(op)+1;
  159. *op = 0;
  160. }
  161. return(0);
  162. } /* end setheenv subroutine */