home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / c / input.c < prev    next >
C/C++ Source or Header  |  1994-03-04  |  6KB  |  241 lines

  1.  4-May-86 13:56:29-PDT,5916;000000000001
  2. Return-Path: <pwu@unix.macc.wisc.edu>
  3. Received: FROM UNIX.MACC.WISC.EDU BY USC-ISIB.ARPA WITH TCP ; 4 May 86 13:51:39 PDT
  4. Received: by unix.macc.wisc.edu (4.12/6.0.GT)
  5.           id AA09143; Sun, 4 May 86 15:49:46 cdt
  6. Date: Sun, 4 May 86 15:49:46 cdt
  7. From: Peter Wu <pwu@unix.macc.wisc.edu>
  8. Message-Id: <8605042049.AA09143@unix.macc.wisc.edu>
  9. To: info-ibmpc-request@mosis
  10. Subject: input.c
  11.  
  12. /* INPUT version 1.0 by Peter Wu  5/86
  13. ** Send comments to
  14. ** uucp:   ..{ihnp4|seismo|ucbvax|harvard|allegra}!uwvax!uwmacc!pwu
  15. ** arpa:   uwmacc!pwu@uwvax.ARPA
  16. **
  17. ** compile with IBMC using "cc input /ze"
  18. ** link with "clink input /stack:4000"
  19. **
  20. ** Usage:
  21. ** Read a string from console into a DOS environment variable
  22. ** e.g. In a batch file:
  23. **
  24. **    echo off
  25. **    input "Who are you? " name
  26. **    if %name%.==God. goto greet
  27. **       .   \
  28. **       .    \-- (Note: %name% is an undocumented feature in Dos 3.1)
  29. **    :greet
  30. **    echo Your honor, why am I teleported here?
  31. **
  32. ** This program relies on a number of undocumented features in DOS 3.1 to work
  33. ** properly. If you are not using DOS 3.1 on a real IBMPC, this program
  34. ** might not work. It's been tested with DOS 3.1 on IBM PC AT and IBM PC XT.
  35. **
  36. ** See external document for more examples.
  37. */
  38.  
  39. #include <dos.h>
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include <ctype.h>
  43. #include <conio.h>
  44.  
  45. #define VLEN 80
  46. #define BUFLEN 1000
  47.  
  48. #define argprompt argv[1]
  49. #define argname argv[2]
  50.  
  51. unsigned int _psp;
  52. unsigned short peekw();
  53. unsigned char peekb();
  54. void pokeb();
  55.  
  56. main(argc,argv)
  57. int argc;
  58. char *argv[];
  59. {
  60.   unsigned short x, p, y, envsize, free;
  61.   int found;
  62.   char    c, var[VLEN+BUFSIZ+1], buf[BUFLEN];
  63.   int i, varlen;
  64.  
  65.   if (argc != 3) {
  66.     cputs("Usage: input <prompt> <variable name>\n\015");
  67.     cputs("Input string will always be converted to lower case\n\015");
  68.     cputs("E.g.  INPUT \"How are you? \" answer\n\015");
  69.     cputs("      if %answer%.==fine. goto fine\n\015");
  70.     exit(0);
  71.   };
  72.  
  73.   varlen = strlen(argname);  /* var. name */
  74.   if (varlen > VLEN) {
  75.     cputs("Variable name too long\n");
  76.     exit(1);
  77.   };
  78.  
  79.   for (i=0; i <= varlen; i++) {  /* convert to upper case */
  80.     var[i] = toupper(argname[i]);
  81.   };
  82.  
  83.   strcat(var,"=");
  84.   varlen++;
  85.  
  86.   p = _psp;
  87.  
  88.   do {    /* find DOS's segment */
  89.     x = p;
  90.     p = peekw(x,0xc);  /* terminate segment address */
  91.   } while (p != x);
  92.  
  93.   if (peekb(x-1,0) != 0x4d) {
  94.     cputs("Oops! Wrong DOS segment - something is wrong\n\015");
  95.     exit(2);
  96.   }
  97.  
  98.   /* found DOS segment at x */
  99.  
  100.   p = peekw(x-1,3) + x + 1;  /* DOS's env. space */
  101.   envsize = peekw(p-1, 3) << 4;  /* size of env. space in bytes */
  102.  
  103. #ifdef DEBUG
  104.   printf("Your env. size has total of %d bytes\n", envsize);
  105. #endif
  106.  
  107.  
  108.   /* The following code looks for an environment variable with the same
  109.   ** name supplied by the user. If such a variable is found, it will be
  110.   ** deleted (by copying the next variables over it)
  111.   */
  112.   x = 0;
  113.   found = 0;
  114.   do {    /* find environment var with the same name */
  115.  
  116.     if (mystrncmp(p,x,var,varlen) == 0) {  /* found same name */
  117.       y = x;
  118.       found = 1;
  119.     };
  120.  
  121.     while (c=peekb(p,x)) {
  122.  
  123. #ifdef DEBUG
  124.       putchar(c);
  125. #endif
  126.       if (found == 2) {
  127.     pokeb(p,y,c);
  128.     y++;
  129.       };
  130.  
  131.       x++;
  132.     };
  133.  
  134.     switch (found) {
  135.       case 1: found=2; break;
  136.       case 2: pokeb(p,y,c); y++; break;
  137.     };
  138.  
  139. #ifdef DEBUG
  140.     putchar('\n');
  141. #endif
  142.  
  143.   } while (peekb(p,++x));
  144.  
  145.   if (found) {
  146.     pokeb(p,y,'\0');
  147.     x = y;
  148.   };
  149.  
  150.   /* Ok. Now we have gotten rid of identical variable name. All that's
  151.   ** left to be done is to make sure there's room to copy the new
  152.   ** variable and input string into the environment space
  153.   */
  154.  
  155.   /* now p:x points to the 0 at the end of current environment */
  156.  
  157.   /* calculate free env. space */
  158.   free = envsize - x - 1;
  159.  
  160. #ifdef DEBUG
  161.   printf("You have %d bytes left in your env.\n", free);
  162. #endif
  163.  
  164.   cputs(argprompt);  /* prompt */
  165.   buf[0] = BUFLEN - 3;
  166.   cgets(buf);
  167.   cputs("\n\015");  /* line feed on console after user entered string */
  168.  
  169.   /* now convert the input string to lower case */
  170.   for (i=2; i < strlen(buf+2) + 2; i++) {  /* convert to lower case */
  171.     buf[i] = tolower(buf[i]);
  172.   };
  173.  
  174.   strcat(var,buf+2);  /* first two bytes of buf is not the string */
  175.  
  176.   /* check to see if things will fit */
  177.   y = strlen(var);
  178.   if (y+1 > free) {  /* Oops, won't fit! */
  179.     cputs("Sorry, your environment space is full, program abort.\n\015");
  180.     cputs("Try \"shell=c:\command.com /p /e:62\" in config.sys to\n\015");
  181.     cputs("increase your environment space to 992 bytes\n\015");
  182.     exit(3);
  183.   };
  184.  
  185.   /* now copy the NAME=string to the end of environment space */
  186.   for (i=0; i <= y; i++) {  /* poke the '\0' also, that's why I use <= */
  187.     pokeb(p, x++, var[i]);
  188.   };
  189.  
  190.   pokeb(p, x, 0);  /* terminate environment space */
  191. }
  192.  
  193. /* strncmp with one string in a different segment */
  194. mystrncmp(seg,offset,source,n)
  195. short seg,offset;
  196. int n;
  197. char *source;
  198. {
  199.   int i, dif;
  200.  
  201.   for (i=0; i < n; i++) {
  202.     dif = peekb(seg,offset+i) - source[i];
  203.     if (dif) return dif;
  204.   };
  205.   return 0;
  206. }
  207.  
  208. unsigned char peekb(seg,offset)
  209. short seg,offset;
  210. {
  211.   char far *fptr;  /* far pointer (segment + offset) to character */
  212.   /* if you forgot to use /ze option when you compile you'll get an
  213.   ** error here about the '*'
  214.   */
  215.  
  216.   FP_SEG(fptr) = seg;
  217.   FP_OFF(fptr) = offset;
  218.   return *fptr;
  219. }
  220.  
  221. void pokeb(seg,offset,what)
  222. short seg,offset;
  223. char what;
  224. {
  225.   char far *fptr;  /* far pointer (segment + offset) to character */
  226.  
  227.   FP_SEG(fptr) = seg;
  228.   FP_OFF(fptr) = offset;
  229.   *fptr = what;
  230. }
  231.  
  232. unsigned short peekw(seg,offset)
  233. short seg,offset;
  234. {
  235.   unsigned far *fptr;  /* far pointer (segment + offset) to short */
  236.  
  237.   FP_SEG(fptr) = seg;
  238.   FP_OFF(fptr) = offset;
  239.   return *fptr;
  240. }
  241.