home *** CD-ROM | disk | FTP | other *** search
- 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;
- }
-