summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/setenvar.c
blob: e2271d5272e5341460abbeddfb82b169506cf0d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
**  SETENVAR.C - Program which sets the DOS master environment upon exit
**
**  Original Copyright 1988-1991 by Bob Stout as part of
**  the MicroFirm Function Library (MFL)
**
**  This subset version is functionally identical to the
**  version originally published by the author in Tech Specialist
**  magazine and is hereby donated to the public domain.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>

#if !defined(__ZTC__) && !defined(__TURBOC__)
 #define MK_FP(seg,offset) \
        ((void far *)(((unsigned long)(seg)<<16) | (unsigned)(offset)))
 #define peek(s,o) (*((unsigned far *)(MK_FP(s,o))))
 #define poke(s,o,w) (*((unsigned far *)(MK_FP(s,o)))=(w))
#endif

#define SUCCESS 0
#define ERROR -1

static unsigned head, tail, start, end;
static int idx = 0;
static unsigned keystack[16][2];

/*
**  ungetkey()
**
**  Stuffs characters into the keyboard buffer.
**
**  Parameters: 1 - Extended character to stuff
**
**  Returns: SUCCESS or EOF
**
**  Note: This function assumes that the keyboard buffer is in
**        the normal (for IBM) location of 40:1E.
**
*/

int ungetkey(unsigned key)
{
        int count;

#ifdef __ZTC__
        peek(0x40, 0x1a, &head, sizeof(unsigned));
        peek(0x40, 0x1c, &tail, sizeof(unsigned));
        peek(0x40, 0x80, &start, sizeof(unsigned));
        peek(0x40, 0x82, &end, sizeof(unsigned));
#else
        head  = peek(0x40, 0x1a);
        tail  = peek(0x40, 0x1c);
        start = peek(0x40, 0x80);
        end   = peek(0x40, 0x82);
#endif
        count = tail - head;
        if (0 > count)
                count += (16 * sizeof(unsigned));
        count >>= 1;

        if (15 > count)
        {
#ifdef __ZTC__
                peek(0x40, tail, &keystack[idx][0], sizeof(unsigned));
#else
                keystack[idx][0] = peek(0x40, tail);
#endif
                keystack[idx][1] = tail;
#ifdef __ZTC__
                poke(0x40, tail, &key, sizeof(unsigned));
#else
                poke(0x40, tail, key);
#endif
                tail += sizeof(unsigned);
                if (end <= tail)
                        tail = start;
#ifdef __ZTC__
                poke(0x40, 0x1c, &tail, sizeof(unsigned));
#else
                poke(0x40, 0x1c, tail);
#endif
                return key;
        }
        return EOF;
}

/*
**  KB_stuff()
**
**  Stuffs strings into the keyboard buffer.
**
**  Parameters: 1 - String to stuff
**
**  Returns: SUCCESS if successful
**           ERROR   in case of error, plus beyboard buffer is
**                   restored
**
**  Note: This function assumes that the keyboard buffer is in
**        the normal (for IBM) location of 40:1E.
*/

int KB_stuff(char *str)
{
        int ercode = SUCCESS;

        idx = 0;
        while (*str)
        {
                if (EOF == ungetkey((unsigned)(*str++)))
                {
                        while (0 <= --idx)
                        {
                                tail = keystack[idx][1];
#ifdef __ZTC__
                                poke(0x40, tail, &keystack[idx][0],
                                        sizeof(unsigned));
#else
                                poke(0x40, tail, keystack[idx][0]);
#endif
                        }
#ifdef __ZTC__
                        poke(0x40, 0x1c, &tail, sizeof(unsigned));
#else
                        poke(0x40, 0x1c, tail);
#endif
                        ercode = ERROR;
                        break;
                }
                else    ++idx;
        }
        idx = 0;
        return ercode;
}

void main(int argc, char *argv[])
{
        FILE *bfile;

        if (3 > argc)
        {
                puts("\aUsage: SETENVAR envar datum");
                abort();
        }
        bfile = fopen("$TMP$.BAT", "w");
        fprintf(bfile, "SET %s=%s\ndel $tmp$.bat\x1a", argv[1], argv[2]);
        fclose(bfile);
        while (kbhit())
                getch();
        KB_stuff("$tmp$\r");
}