Subversion Repositories SvarDOS

Rev

Rev 421 | Rev 517 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
421 mateuszvis 1
/* This file is part of the SvarCOM project and is published under the terms
2
 * of the MIT license.
3
 *
4
 * Copyright (C) 2021 Mateusz Viste
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
23
 */
402 mateuszvis 24
 
25
#include "doserr.h"
26
#include "helpers.h"
27
 
28
#include "redir.h"
29
 
30
static unsigned short oldstdout = 0xffff;
31
 
32
/* parse commandline and performs necessary redirections. cmdline is
33
 * modified so all redirections are cut out.
34
 * returns 0 on success, non-zero otherwise */
479 mateuszvis 35
int redir_parsecmd(char *cmdline, char *BUFFER) {
402 mateuszvis 36
  unsigned short i;
37
  unsigned short rediroffset_stdin = 0;
38
  unsigned short rediroffset_stdout = 0;
39
  unsigned short pipesoffsets[16];
40
  unsigned short pipescount = 0;
41
 
42
  /* NOTE:
43
   *
44
   * 1. while it is possible to type a command with multiple
45
   *    redirections, MSDOS executes only the last redirection.
46
   *
47
   * 2. the order in which >, < and | are provided on the command line does
48
   *    not seem to matter for MSDOS. piped commands are executed first (in
49
   *    the order they appear) and the result of the last one is redirected to
50
   *    whenever the last > points at.
51
   */
52
 
53
  /* preset oldstdout to 0xffff in case no redirection is required */
54
  oldstdout = 0xffff;
55
 
56
  for (i = 0;; i++) {
57
    if (cmdline[i] == '>') {
58
      cmdline[i] = 0;
59
      rediroffset_stdout = i + 1;
60
    } else if (cmdline[i] == '<') {
61
      cmdline[i] = 0;
62
      rediroffset_stdin = i + 1;
63
    } else if (cmdline[i] == '|') {
64
      cmdline[i] = 0;
65
      pipesoffsets[pipescount++] = i + 1;
66
    } else if (cmdline[i] == 0) {
67
      break;
68
    }
69
  }
70
 
71
  if (rediroffset_stdin != 0) {
72
    outputnl("ERROR: stdin redirection is not supported yet");
73
    return(-1);
74
  }
75
 
76
  if (pipescount != 0) {
77
    outputnl("ERROR: pipe redirections are not supported yet");
78
    return(-1);
79
  }
80
 
81
  if (rediroffset_stdout != 0) {
82
    unsigned short openflag = 0x12;  /* used during the int 21h,ah=6c call */
83
    unsigned short errcode = 0;
84
    unsigned short handle = 0;
479 mateuszvis 85
    char *ptr;
402 mateuszvis 86
    /* append? */
87
    if (cmdline[rediroffset_stdout] == '>') {
88
      openflag = 0x11;
89
      rediroffset_stdout++;
90
    }
91
 
92
    /* copy dst file to BUFFER */
93
    ptr = cmdline + rediroffset_stdout;
94
    while (*ptr == ' ') ptr++; /* skip leading white spaces */
95
    for (i = 0;; i++) {
96
      BUFFER[i] = ptr[i];
97
      if ((BUFFER[i] == ' ') || (BUFFER[i] == 0)) break;
98
    }
99
    BUFFER[i] = 0;
100
 
101
    /* */
102
    _asm {
103
      push ax
104
      push bx
105
      push cx
106
      push dx
107
      push si
108
      mov ax, 0x6c00     /* Extended Open/Create */
109
      mov bx, 1          /* access mode (0=read, 1=write, 2=r+w */
110
      xor cx, cx         /* attributes when(if) creating the file (0=normal) */
111
      mov dx, [openflag] /* action if file exists (0x11=open, 0x12=truncate)*/
112
      mov si, BUFFER     /* ASCIIZ filename */
113
      int 0x21           /* AX=handle on success (CF clear), otherwise dos err */
114
      mov [handle], ax   /* save the file handler */
115
      jnc DUPSTDOUT
116
      mov [errcode], ax
117
      jmp DONE
118
      DUPSTDOUT:
119
      /* save (duplicate) current stdout so I can revert it later */
120
      mov ah, 0x45       /* duplicate file handle */
121
      mov bx, 1          /* handle to dup (1=stdout) */
122
      int 0x21           /* ax = new file handle */
123
      mov [oldstdout], ax
124
      /* redirect the stdout handle */
125
      mov bx, [handle]   /* dst handle */
126
      mov cx, 1          /* src handle (1=stdout) */
127
      mov ah, 0x46       /* redirect a handle */
128
      int 0x21
129
      /* close the original file handle (no longer needed) */
130
      mov ah, 0x3e       /* close a file handle (handle in BX) */
131
      int 0x21
132
      DONE:
133
      pop si
134
      pop dx
135
      pop cx
136
      pop bx
137
      pop ax
138
    }
139
    if (errcode != 0) {
140
      outputnl(doserr(errcode));
141
      return(-1);
142
    }
143
  }
144
 
145
  return(0);
146
}
147
 
148
 
149
/* restores previous stdout/stdin handlers if they have been redirected */
150
void redir_revert(void) {
151
  _asm {
152
    /* if oldstdout is 0xffff then not redirected */
153
    cmp word ptr [oldstdout], 0xffff
154
    je DONE
155
    /* redirect the stdout handle */
156
    mov bx, [oldstdout] /* dst handle */
157
    mov cx, 1           /* src handle (1=stdout) */
158
    mov ah, 0x46        /* redirect a handle */
159
    int 0x21
160
    mov [oldstdout], 0xffff
161
    DONE:
162
  }
163
}