home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1996 September
/
Simtel-MSDOS-Sep1996-CD2.iso
/
disc2
/
c
/
input.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-05-03
|
6KB
|
241 lines
4-May-86 13:56:29-PDT,5916;000000000001
Return-Path: <pwu@unix.macc.wisc.edu>
Received: FROM UNIX.MACC.WISC.EDU BY USC-ISIB.ARPA WITH TCP ; 4 May 86 13:51:39 PDT
Received: by unix.macc.wisc.edu (4.12/6.0.GT)
id AA09143; Sun, 4 May 86 15:49:46 cdt
Date: Sun, 4 May 86 15:49:46 cdt
From: Peter Wu <pwu@unix.macc.wisc.edu>
Message-Id: <8605042049.AA09143@unix.macc.wisc.edu>
To: info-ibmpc-request@mosis
Subject: input.c
/* INPUT version 1.0 by Peter Wu 5/86
** Send comments to
** uucp: ..{ihnp4|seismo|ucbvax|harvard|allegra}!uwvax!uwmacc!pwu
** arpa: uwmacc!pwu@uwvax.ARPA
**
** compile with IBMC using "cc input /ze"
** link with "clink input /stack:4000"
**
** Usage:
** Read a string from console into a DOS environment variable
** e.g. In a batch file:
**
** echo off
** input "Who are you? " name
** if %name%.==God. goto greet
** . \
** . \-- (Note: %name% is an undocumented feature in Dos 3.1)
** :greet
** echo Your honor, why am I teleported here?
**
** This program relies on a number of undocumented features in DOS 3.1 to work
** properly. If you are not using DOS 3.1 on a real IBMPC, this program
** might not work. It's been tested with DOS 3.1 on IBM PC AT and IBM PC XT.
**
** See external document for more examples.
*/
#include <dos.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
#define VLEN 80
#define BUFLEN 1000
#define argprompt argv[1]
#define argname argv[2]
unsigned int _psp;
unsigned short peekw();
unsigned char peekb();
void pokeb();
main(argc,argv)
int argc;
char *argv[];
{
unsigned short x, p, y, envsize, free;
int found;
char c, var[VLEN+BUFSIZ+1], buf[BUFLEN];
int i, varlen;
if (argc != 3) {
cputs("Usage: input <prompt> <variable name>\n\015");
cputs("Input string will always be converted to lower case\n\015");
cputs("E.g. INPUT \"How are you? \" answer\n\015");
cputs(" if %answer%.==fine. goto fine\n\015");
exit(0);
};
varlen = strlen(argname); /* var. name */
if (varlen > VLEN) {
cputs("Variable name too long\n");
exit(1);
};
for (i=0; i <= varlen; i++) { /* convert to upper case */
var[i] = toupper(argname[i]);
};
strcat(var,"=");
varlen++;
p = _psp;
do { /* find DOS's segment */
x = p;
p = peekw(x,0xc); /* terminate segment address */
} while (p != x);
if (peekb(x-1,0) != 0x4d) {
cputs("Oops! Wrong DOS segment - something is wrong\n\015");
exit(2);
}
/* found DOS segment at x */
p = peekw(x-1,3) + x + 1; /* DOS's env. space */
envsize = peekw(p-1, 3) << 4; /* size of env. space in bytes */
#ifdef DEBUG
printf("Your env. size has total of %d bytes\n", envsize);
#endif
/* The following code looks for an environment variable with the same
** name supplied by the user. If such a variable is found, it will be
** deleted (by copying the next variables over it)
*/
x = 0;
found = 0;
do { /* find environment var with the same name */
if (mystrncmp(p,x,var,varlen) == 0) { /* found same name */
y = x;
found = 1;
};
while (c=peekb(p,x)) {
#ifdef DEBUG
putchar(c);
#endif
if (found == 2) {
pokeb(p,y,c);
y++;
};
x++;
};
switch (found) {
case 1: found=2; break;
case 2: pokeb(p,y,c); y++; break;
};
#ifdef DEBUG
putchar('\n');
#endif
} while (peekb(p,++x));
if (found) {
pokeb(p,y,'\0');
x = y;
};
/* Ok. Now we have gotten rid of identical variable name. All that's
** left to be done is to make sure there's room to copy the new
** variable and input string into the environment space
*/
/* now p:x points to the 0 at the end of current environment */
/* calculate free env. space */
free = envsize - x - 1;
#ifdef DEBUG
printf("You have %d bytes left in your env.\n", free);
#endif
cputs(argprompt); /* prompt */
buf[0] = BUFLEN - 3;
cgets(buf);
cputs("\n\015"); /* line feed on console after user entered string */
/* now convert the input string to lower case */
for (i=2; i < strlen(buf+2) + 2; i++) { /* convert to lower case */
buf[i] = tolower(buf[i]);
};
strcat(var,buf+2); /* first two bytes of buf is not the string */
/* check to see if things will fit */
y = strlen(var);
if (y+1 > free) { /* Oops, won't fit! */
cputs("Sorry, your environment space is full, program abort.\n\015");
cputs("Try \"shell=c:\command.com /p /e:62\" in config.sys to\n\015");
cputs("increase your environment space to 992 bytes\n\015");
exit(3);
};
/* now copy the NAME=string to the end of environment space */
for (i=0; i <= y; i++) { /* poke the '\0' also, that's why I use <= */
pokeb(p, x++, var[i]);
};
pokeb(p, x, 0); /* terminate environment space */
}
/* strncmp with one string in a different segment */
mystrncmp(seg,offset,source,n)
short seg,offset;
int n;
char *source;
{
int i, dif;
for (i=0; i < n; i++) {
dif = peekb(seg,offset+i) - source[i];
if (dif) return dif;
};
return 0;
}
unsigned char peekb(seg,offset)
short seg,offset;
{
char far *fptr; /* far pointer (segment + offset) to character */
/* if you forgot to use /ze option when you compile you'll get an
** error here about the '*'
*/
FP_SEG(fptr) = seg;
FP_OFF(fptr) = offset;
return *fptr;
}
void pokeb(seg,offset,what)
short seg,offset;
char what;
{
char far *fptr; /* far pointer (segment + offset) to character */
FP_SEG(fptr) = seg;
FP_OFF(fptr) = offset;
*fptr = what;
}
unsigned short peekw(seg,offset)
short seg,offset;
{
unsigned far *fptr; /* far pointer (segment + offset) to short */
FP_SEG(fptr) = seg;
FP_OFF(fptr) = offset;
return *fptr;
}