int cmd_ctty(char *param) { int f, attr, failed; if(!param || !*param) { displayString(TEXT_CMDHELP_CTTY); return 1; } #ifdef DEBUG devAttr(0); devAttr(1); devAttr(2); #endif if((f = devopen(param, O_RDWR)) < 0) { error_no_rw_device(param); return 1; } if(((attr = fdattr(f)) & 0x80) == 0 || write(f, "\r\n", 2) != 2) { /* need \r as in bin mode */ close(f); error_no_rw_device(param); return 1; } /* Now inform the system that this device is the new console now; STDIN and STDOUT flag are the most lowest two bits */ fdsetattr(f, (attr & 0xFF) | 0x03); fflush(stdin); /* prepare asynchroneous changes of internal fd's */ fflush(stdout); fflush(stderr); /* Now change the file descriptors: 0 := rdonly 1,2 := wronly if CTTY is called within a pipe or its I/O is redirected, oldinfd or oldoutfd is not equal to -1. In such case the old*fd is modified in order to effect the file descriptor after the redirections are restored. Otherwise a pipe or redirection would left CTTY in a half-made status. */ failed = dup2(f, 2); /* no redirection support */ if(oldinfd != -1) close(oldinfd); oldinfd = f; if(oldoutfd != -1) close(oldoutfd); if((oldoutfd = dup(f)) == -1) failed = 1; if(failed) error_ctty_dup(param); return failed; }
int cmd_cls (char * param) { (void)param; outc( '\xc' ); /* ^L Form feed */ /* Output stream is neither a file nor NUL nor CLOCK$ */ if(((fdattr(1) ^ 0x80) & (0x80 | 0x08 | 0x04)) == 0) { /* Now roll the screen */ IREGS r; r.r_ax = 0x0600; /* Scroll window up // entire window */ r.r_bx = 0x0700; /* Attribute to write */ r.r_cx = 0x0000; /* Upper left */ r.r_dx = ((SCREEN_ROWS - 1) << 8) | (SCREEN_COLS - 1); /* Lower right */ intrpt(0x10, &r); goxy(1, 1); /* home the cursor */ } return 0; }
static void devAttr(int fd) { int attr; if((attr = fdattr(fd)) == 0) { dprintf(("[Failed to read attributes of fd #%d]\n", fd)); } else { dbg_print("[fd #%d is", fd); if(attr & 0x80) { if(attr & 7) { if(attr & 1) dbg_outs(" STDIN"); if(attr & 2) dbg_outs(" STDOUT"); if(attr & 4) dbg_outs(" NUL"); } else dbg_outs(" a device"); } else dbg_outs(" a file"); dbg_outsn("]"); } }
/* * do the prompt/input/process loop * * If xflg is true, the function will not go interactive, but returns. * If commandline != NULL, this command is processed first. * * Return: 0: on success */ int process_input(int xflag, char *commandline) { /* Dimensionate parsedline that no sprintf() can overflow the buffer */ char parsedline[MAX_INTERNAL_COMMAND_SIZE + sizeof(errorlevel) * 8] , *readline; /* Return the maximum pointer into parsedline to add 'numbytes' bytes */ #define parsedMax(numbytes) \ (parsedline + MAX_INTERNAL_COMMAND_SIZE - 1 - (numbytes)) char *evar; char *tp; char *ip; char *cp; char forvar; int echothisline; int tracethisline; do { interactive_command = 0; /* not directly entered by user */ echothisline = tracethisline = 0; if(commandline) { ip = commandline; readline = commandline = NULL; } else { if ((readline = malloc(MAX_INTERNAL_COMMAND_SIZE + 1)) == NULL) { error_out_of_memory(); return 1; } if (NULL == (ip = readbatchline(&echothisline, readline, MAX_INTERNAL_COMMAND_SIZE))) { /* if no batch input then... */ if (xflag /* must not go interactive */ || (fdattr(0) & 0x84) == 0x84 /* input is NUL device */ || feof(stdin)) /* no further input */ { free(readline); break; } /* Go Interactive */ interactive_command = 1; /* directly entered by user */ readcommand(ip = readline, MAX_INTERNAL_COMMAND_SIZE); tracemode = 0; /* reset trace mode */ } } /* * The question mark '?' has a double meaning: * C:\> ? * ==> Display short help * * C:\> ? command arguments * ==> enable tracemode for just this line */ if(*(ip = trim(ip)) == '?') { ip = trim(ip + 1); if(!*ip) { /* is short help command */ #ifdef INCLUDE_CMD_QUESTION showcmds(ip); #endif free(readline); continue; } /* this-line-tracemode */ echothisline = 0; tracethisline = 1; } /* The FOR hack If the line matches /^\s*for\s+\%[a-z]\s/, the FOR hack becomes active, because FOR requires the sequence "%<ch>" in its input. When the percent (%) expansion is made later on, any sequence "%<ch>" is retained. */ cp = ip; if(matchtok(cp, "for") && *cp == '%' && isalpha(cp[1]) && isspace(cp[2])) /* activate FOR hack */ forvar = toupper(cp[1]); else forvar = 0; cp = parsedline; while (*ip) { /* Assume that at least one character is added, place the test here to simplify the switch() statement */ if(cp >= parsedMax(1)) { cp = NULL; /* error condition */ break; } if (*ip == '%') { switch (*++ip) { case '\0': /* FOR hack forvar == 0 if no FOR is active */ *cp++ = '%'; break; case '%': *cp++ = *ip++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (NULL != (tp = find_arg(*ip - '0'))) { if(cp >= parsedMax(strlen(tp))) { cp = NULL; goto intBufOver; } cp = stpcpy(cp, tp); ip++; } else *cp++ = '%'; /* Let the digit be copied in the cycle */ break; case '?': /* overflow check: parsedline has that many character "on reserve" */ cp += sprintf(cp, "%u", errorlevel); ip++; break; default: if(forvar == toupper(*ip)) { /* FOR hack */ *cp++ = '%'; /* let the var be copied in next cycle */ break; } if ((tp = strchr(ip, '%')) != NULL) { *tp = '\0'; if ((evar = getEnv(ip)) != NULL) { if(cp >= parsedMax(strlen(evar))) { cp = NULL; goto intBufOver; } cp = stpcpy(cp, evar); } ip = tp + 1; } break; } continue; } if (iscntrl(*ip)) *cp = ' '; else *cp++ = *ip++; } intBufOver: free(readline); if(!cp) { /* internal buffer overflow */ error_line_too_long(); continue; } *cp = '\0'; /* terminate copied string */ if (echothisline) /* Echo batch file line */ { printprompt(); puts(parsedline); } if (*parsedline) { if(tracethisline) ++tracemode; parsecommandline(parsedline); if(tracethisline) --tracemode; if (echothisline || echo) putchar('\n'); } } while (!canexit || !exitflag); return 0; }
int isadev(const int fd) { return (fdattr(fd) & 0x80) != 0; /* is character device */ }
/* * do the prompt/input/process loop * * If xflg is true, the function will not go interactive, but returns. * If commandline != NULL, this command is processed first. * * Return: 0: on success */ int process_input(int xflag, char *commandline) { /* Dimensionate parsedline that no sprintf() can overflow the buffer */ char parsedline[MAX_INTERNAL_COMMAND_SIZE + sizeof(errorlevel) * 8] , *readline; #if 0 /* Return the maximum pointer into parsedline to add 'numbytes' bytes */ #define parsedMax(numbytes) \ (parsedline + MAX_INTERNAL_COMMAND_SIZE - 1 - (numbytes)) char *evar; char *tp; char *cp; #endif char *ip; #if 0 char forvar; #endif int echothisline; int tracethisline; do { #ifdef FEATURE_LONG_FILENAMES if( toupper( *getEnv( "LFN" ) ) == 'N' ) __supportlfns = 0; else __supportlfns = 1; #endif interactive_command = 0; /* not directly entered by user */ echothisline = tracethisline = 0; if(commandline) { ip = commandline; readline = commandline = 0; } else { if ((readline = malloc(MAX_INTERNAL_COMMAND_SIZE + 1)) == 0) { error_out_of_memory(); return 1; } if (0 == (ip = readbatchline(&echothisline, readline, MAX_INTERNAL_COMMAND_SIZE))) { /* if no batch input then... */ if (xflag /* must not go interactive */ || (fdattr(0) & 0x84) == 0x84 /* input is NUL device */ || feof(stdin)) /* no further input */ { free(readline); break; } /* Go Interactive */ interactive_command = 1; /* directly entered by user */ /* Ensure the prompt starts at column #0 */ if(echo && (mywherex()>1)) outc('\n'); readcommand(ip = readline, MAX_INTERNAL_COMMAND_SIZE); tracemode = 0; /* reset trace mode */ } } /* Make sure there is no left-over from last run */ currCmdHelpScreen = 0; /* * The question mark '?' has a double meaning: * C:\> ? * ==> Display short help * * C:\> ? command arguments * ==> enable tracemode for just this line */ if(*(ip = ltrimcl(ip)) == '?') { ip = ltrimcl(ip + 1); if(!*ip) { /* is short help command */ #ifdef INCLUDE_CMD_QUESTION showcmds(ip); #endif free(readline); continue; } /* this-line-tracemode */ echothisline = 0; tracethisline = 1; } #if 0 /* The FOR hack If the line matches /^\s*for\s+\%[a-z]\s/, the FOR hack becomes active, because FOR requires the sequence "%<ch>" in its input. When the percent (%) expansion is made later on, any sequence "%<ch>" is retained. */ cp = ip; if(matchtok(cp, "for") && *cp == '%' && isalpha(cp[1]) && isargdelim(cp[2])) /* activate FOR hack */ forvar = toupper(cp[1]); else forvar = 0; #else if(cmd_for_hackery(ip)) { free(readline); continue; } #endif { int rc = expandEnvVars(ip, parsedline); free(readline); if(!rc) { error_line_too_long(); continue; } } if (echothisline) /* Echo batch file line */ { printprompt(); puts(parsedline); } if (*parsedline) { if(swapOnExec != ERROR) swapOnExec = defaultToSwap; if(tracethisline) ++tracemode; parsecommandline(parsedline, TRUE); if(tracethisline) --tracemode; } } while (!canexit || !exitflag); return 0; }