Subversion Repositories SvarDOS

Rev

Rev 472 | Rev 475 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 472 Rev 474
Line 161... Line 161...
161
 
161
 
162
  }
162
  }
163
}
163
}
164
 
164
 
165
 
165
 
-
 
166
/* builds the prompt string and displays it. buff is filled with a zero-terminated copy of the prompt. */
166
static void buildprompt(char *s, unsigned short envseg) {
167
static void build_and_display_prompt(char *buff, unsigned short envseg) {
-
 
168
  char *s = buff;
167
  /* locate the prompt variable or use the default pattern */
169
  /* locate the prompt variable or use the default pattern */
168
  const char far *fmt = env_lookup_val(envseg, "PROMPT");
170
  const char far *fmt = env_lookup_val(envseg, "PROMPT");
169
  if ((fmt == NULL) || (*fmt == 0)) fmt = "$p$g"; /* fallback to default if empty */
171
  if ((fmt == NULL) || (*fmt == 0)) fmt = "$p$g"; /* fallback to default if empty */
170
  /* build the prompt string based on pattern */
172
  /* build the prompt string based on pattern */
171
  for (; *fmt != 0; fmt++) {
173
  for (; *fmt != 0; fmt++) {
Line 262... Line 264...
262
        *s = '\n';
264
        *s = '\n';
263
        s++;
265
        s++;
264
        break;
266
        break;
265
    }
267
    }
266
  }
268
  }
267
  *s = '$';
269
  *s = 0;
-
 
270
  output(buff);
268
}
271
}
269
 
272
 
270
 
273
 
271
/* tries locating executable fname in path and fille res with result. returns 0 on success,
274
/* tries locating executable fname in path and fille res with result. returns 0 on success,
272
 * -1 on failed match and -2 on failed match + "don't even try with other paths"
275
 * -1 on failed match and -2 on failed match + "don't even try with other paths"
Line 414... Line 417...
414
    rmod->batfile[i] = 0;
417
    rmod->batfile[i] = 0;
415
    /* copy args of the bat file to rmod buff */
418
    /* copy args of the bat file to rmod buff */
416
    for (i = 0; cmdtail[i] != 0; i++) rmod->batargs[i] = cmdtail[i];
419
    for (i = 0; cmdtail[i] != 0; i++) rmod->batargs[i] = cmdtail[i];
417
    /* reset the 'next line to execute' counter */
420
    /* reset the 'next line to execute' counter */
418
    rmod->batnextline = 0;
421
    rmod->batnextline = 0;
-
 
422
    /* remember the echo flag (in case bat file disables echo) */
-
 
423
    rmod->flags &= ~FLAG_ECHO_BEFORE_BAT;
-
 
424
    if (rmod->echoflag) rmod->flags |= FLAG_ECHO_BEFORE_BAT;
419
    return;
425
    return;
420
  }
426
  }
421
 
427
 
422
  /* copy full filename to execute */
428
  /* copy full filename to execute */
423
  for (i = 0; cmdfile[i] != 0; i++) rmod_execprog[i] = cmdfile[i];
429
  for (i = 0; cmdfile[i] != 0; i++) rmod_execprog[i] = cmdfile[i];
Line 517... Line 523...
517
  }
523
  }
518
}
524
}
519
 
525
 
520
 
526
 
521
/* fetches a line from batch file and write it to buff, increments
527
/* fetches a line from batch file and write it to buff, increments
522
 * rmod counter on success. returns NULL on failure.
528
 * rmod counter on success. returns 0 on success.
523
 * buff must start with a length byte but the returned pointer must
529
 * buff starts with a length byte and is NULL-terminated */
524
 * skip it. */
-
 
525
static char far *getbatcmd(char *buff, struct rmod_props far *rmod) {
530
static int getbatcmd(char *buff, struct rmod_props far *rmod) {
526
  unsigned short i;
531
  unsigned short i;
-
 
532
  unsigned short batname_seg = FP_SEG(rmod->batfile);
-
 
533
  unsigned short batname_off = FP_OFF(rmod->batfile);
-
 
534
  unsigned short filepos_cx = rmod->batnextline >> 16;
-
 
535
  unsigned short filepos_dx = rmod->batnextline & 0xffff;
-
 
536
  unsigned char blen = 0;
-
 
537
 
527
  buff++; /* make room for the len byte */
538
  buff++; /* make room for the len byte prefix */
-
 
539
 
-
 
540
  /* open file, jump to offset filpos, and read data into buff.
528
  /* TODO temporary hack to display a dummy message */
541
   * result in blen (unchanged if EOF or failure). */
-
 
542
  _asm {
-
 
543
    push ax
-
 
544
    push bx
-
 
545
    push cx
-
 
546
    push dx
-
 
547
 
529
  if (rmod->batnextline == 0) {
548
    /* open file (read-only) */
-
 
549
    mov dx, batname_off
-
 
550
    mov ax, batname_seg
-
 
551
    push ds     /* save DS */
-
 
552
    mov ds, ax
-
 
553
    mov ax, 0x3d00
530
    char *msg = "ECHO batch files not supported yet";
554
    int 0x21    /* handle in ax on success */
-
 
555
    pop ds      /* restore DS */
-
 
556
    jc DONE
531
    for (i = 0; msg[i] != 0; i++) buff[i] = msg[i];
557
    mov bx, ax  /* save handle to bx */
-
 
558
 
-
 
559
    /* jump to file offset CX:DX */
532
    buff[i] = 0;
560
    mov ax, 0x4200
-
 
561
    mov cx, filepos_cx
-
 
562
    mov dx, filepos_dx
-
 
563
    int 0x21  /* CF clear on success, DX:AX set to cur pos */
-
 
564
    jc CLOSEANDQUIT
-
 
565
 
-
 
566
    /* read the line into buff */
533
    buff[-1] = i;
567
    mov ah, 0x3f
534
  } else {
568
    mov cx, 255
-
 
569
    mov dx, buff
-
 
570
    int 0x21 /* CF clear on success, AX=number of bytes read */
-
 
571
    jc CLOSEANDQUIT
535
    rmod->batfile[0] = 0;
572
    mov blen, al
-
 
573
 
536
    return(NULL);
574
    CLOSEANDQUIT:
-
 
575
    /* close file (handle in bx) */
-
 
576
    mov ah, 0x3e
-
 
577
    int 0x21
-
 
578
 
-
 
579
    DONE:
-
 
580
    pop dx
-
 
581
    pop cx
-
 
582
    pop bx
-
 
583
    pop ax
537
  }
584
  }
538
  /* open file */
-
 
539
  /* read until awaiting line */
-
 
540
  /* copy line to buff */
-
 
541
  /* close file */
-
 
542
  /* */
-
 
543
  rmod->batnextline++;
-
 
544
  if (rmod->batnextline == 0) rmod->batfile[0] = 0; /* max line count reached */
-
 
545
 
585
 
-
 
586
  /* printf("blen=%u filepos_cx=%u filepos_dx=%u\r\n", blen, filepos_cx, filepos_dx); */
-
 
587
 
546
  /* output command on screen if echo on */
588
  /* on EOF - abort processing the bat file */
547
  if (rmod->echoflag != 0) outputnl(buff);
589
  if (blen == 0) goto OOPS;
548
 
590
 
-
 
591
  /* find nearest \n to inc batch offset and replace \r by NULL terminator
-
 
592
   * I support all CR/LF, CR- and LF-terminated batch files */
-
 
593
  for (i = 0; i < blen; i++) {
-
 
594
    if ((buff[i] == '\r') || (buff[i] == '\n')) {
-
 
595
      if ((buff[i] == '\r') && ((i+1) < blen) && (buff[i+1] == '\n')) rmod->batnextline += 1;
-
 
596
      break;
-
 
597
    }
-
 
598
  }
-
 
599
  buff[i] = 0;
-
 
600
  buff[-1] = i;
-
 
601
  rmod->batnextline += i + 1;
-
 
602
 
-
 
603
  return(0);
-
 
604
 
-
 
605
  OOPS:
-
 
606
  rmod->batfile[0] = 0;
-
 
607
  rmod->batnextline = 0;
549
  return(buff);
608
  return(-1);
550
}
609
}
551
 
610
 
552
 
611
 
553
int main(void) {
612
int main(void) {
554
  static struct config cfg;
613
  static struct config cfg;
Line 590... Line 649...
590
    envsiz *= 16;
649
    envsiz *= 16;
591
    printf("rmod_inpbuff at %04X:%04X, env_seg at %04X:0000 (env_size = %u bytes)\r\n", rmod->rmodseg, RMOD_OFFSET_INPBUFF, *rmod_envseg, envsiz);
650
    printf("rmod_inpbuff at %04X:%04X, env_seg at %04X:0000 (env_size = %u bytes)\r\n", rmod->rmodseg, RMOD_OFFSET_INPBUFF, *rmod_envseg, envsiz);
592
  }*/
651
  }*/
593
 
652
 
594
  do {
653
  do {
-
 
654
    char far *cmdline;
-
 
655
 
-
 
656
    if (rmod->echoflag != 0) outputnl(""); /* terminate the previous command with a CR/LF */
-
 
657
 
-
 
658
    SKIP_NEWLINE:
-
 
659
 
-
 
660
    /* cancel any redirections that may have been set up before */
-
 
661
    redir_revert();
-
 
662
 
595
    char far *cmdline = rmod->inputbuf + 2;
663
    cmdline = rmod->inputbuf + 2;
596
 
664
 
597
    /* (re)load translation strings if needed */
665
    /* (re)load translation strings if needed */
598
    nls_langreload(BUFFER, *rmod_envseg);
666
    nls_langreload(BUFFER, *rmod_envseg);
599
 
667
 
600
    /* skip user input if I have a command to exec (/C or /K) */
668
    /* skip user input if I have a command to exec (/C or /K) */
Line 602... Line 670...
602
      cmdline = cfg.execcmd;
670
      cmdline = cfg.execcmd;
603
      cfg.execcmd = NULL;
671
      cfg.execcmd = NULL;
604
      goto EXEC_CMDLINE;
672
      goto EXEC_CMDLINE;
605
    }
673
    }
606
 
674
 
607
    if (rmod->echoflag != 0) outputnl(""); /* terminate the previous command with a CR/LF */
-
 
608
 
-
 
609
    SKIP_NEWLINE:
-
 
610
 
-
 
611
    /* print shell prompt (only if ECHO is enabled) */
-
 
612
    if (rmod->echoflag != 0) {
-
 
613
      char *promptptr = BUFFER;
-
 
614
      buildprompt(promptptr, *rmod_envseg);
-
 
615
      _asm {
-
 
616
        push ax
-
 
617
        push dx
-
 
618
        mov ah, 0x09
-
 
619
        mov dx, promptptr
-
 
620
        int 0x21
-
 
621
        pop dx
-
 
622
        pop ax
-
 
623
      }
-
 
624
    }
-
 
625
 
-
 
626
    /* revert input history terminator to \r */
-
 
627
    if (cmdline[-1] != 0) {
-
 
628
      cmdline[(unsigned short)(cmdline[-1])] = '\r';
-
 
629
    }
-
 
630
 
-
 
631
    /* if batch file is being executed -> fetch next line */
675
    /* if batch file is being executed -> fetch next line */
632
    if (rmod->batfile[0] != 0) {
676
    if (rmod->batfile[0] != 0) {
633
      cmdline = getbatcmd(BUFFER + sizeof(BUFFER) - 130, rmod);
677
      char *tmpbuff = BUFFER + sizeof(BUFFER) - 256;
-
 
678
      if (getbatcmd(tmpbuff, rmod) != 0) { /* end of batch */
-
 
679
        redir_revert(); /* cancel redirections (if there were any) */
-
 
680
        /* restore echo flag as it was before running the bat file */
-
 
681
        rmod->echoflag = 0;
-
 
682
        if (rmod->flags & FLAG_ECHO_BEFORE_BAT) rmod->echoflag = 1;
-
 
683
        continue;
-
 
684
      }
-
 
685
      /* output prompt and command on screen if echo on and command is not
-
 
686
       * inhibiting it with the @ prefix */
-
 
687
      if ((rmod->echoflag != 0) && (tmpbuff[1] != '@')) {
-
 
688
        build_and_display_prompt(BUFFER, *rmod_envseg);
-
 
689
        outputnl(tmpbuff + 1);
-
 
690
      }
-
 
691
      /* strip the @ prefix if present, it is no longer useful */
-
 
692
      if (tmpbuff[1] == '@') {
-
 
693
        memmove(tmpbuff + 1, tmpbuff + 2, tmpbuff[0] + 1);
-
 
694
        tmpbuff[0] -= 1; /* update the length byte */
-
 
695
      }
634
      if (cmdline == NULL) continue;
696
      cmdline = tmpbuff + 1;
635
    } else {
697
    } else {
636
      /* interactive mode: wait for user command line */
698
      /* interactive mode: display prompt (if echo enabled) and wait for user
-
 
699
       * command line */
-
 
700
      if (rmod->echoflag != 0) build_and_display_prompt(BUFFER, *rmod_envseg);
-
 
701
      /* revert input history terminator to \r so DOS or DOSKEY are not confused */
-
 
702
      cmdline[(unsigned short)(cmdline[-1])] = '\r';
-
 
703
      /* collect user input */
637
      cmdline_getinput(FP_SEG(rmod->inputbuf), FP_OFF(rmod->inputbuf));
704
      cmdline_getinput(FP_SEG(rmod->inputbuf), FP_OFF(rmod->inputbuf));
-
 
705
      /* replace \r by a zero terminator */
-
 
706
      cmdline[(unsigned char)(cmdline[-1])] = 0;
638
    }
707
    }
639
 
708
 
640
    /* if nothing entered, loop again (but without appending an extra CR/LF) */
709
    /* if nothing entered, loop again (but without appending an extra CR/LF) */
641
    if (cmdline[-1] == 0) goto SKIP_NEWLINE;
710
    if (cmdline[-1] == 0) goto SKIP_NEWLINE;
642
 
711
 
643
    /* replace \r by a zero terminator */
-
 
644
    cmdline[(unsigned char)(cmdline[-1])] = 0;
-
 
645
 
-
 
646
    /* I jump here when I need to exec an initial command (/C or /K) */
712
    /* I jump here when I need to exec an initial command (/C or /K) */
647
    EXEC_CMDLINE:
713
    EXEC_CMDLINE:
648
 
714
 
649
    /* move pointer forward to skip over any leading spaces */
715
    /* move pointer forward to skip over any leading spaces */
650
    while (*cmdline == ' ') cmdline++;
716
    while (*cmdline == ' ') cmdline++;
Line 668... Line 734...
668
    /* if here, then this was not an internal command */
734
    /* if here, then this was not an internal command */
669
    run_as_external(BUFFER, cmdline, *rmod_envseg, rmod);
735
    run_as_external(BUFFER, cmdline, *rmod_envseg, rmod);
670
    /* perhaps this is a newly launched BAT file */
736
    /* perhaps this is a newly launched BAT file */
671
    if ((rmod->batfile[0] != 0) && (rmod->batnextline == 0)) goto SKIP_NEWLINE;
737
    if ((rmod->batfile[0] != 0) && (rmod->batnextline == 0)) goto SKIP_NEWLINE;
672
 
738
 
673
    /* revert stdout (in case it was redirected) */
739
    /* revert stdout (so the err msg is not redirected) */
674
    redir_revert();
740
    redir_revert();
675
 
741
 
676
    /* run_as_external() does not return on success, if I am still alive then
742
    /* run_as_external() does not return on success, if I am still alive then
677
     * external command failed to execute */
743
     * external command failed to execute */
678
    outputnl("Bad command or file name");
744
    outputnl("Bad command or file name");