Subversion Repositories SvarDOS

Rev

Rev 519 | Rev 538 | 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
 
517 mateuszvis 25
#include <string.h> /* memset() */
26
 
402 mateuszvis 27
#include "doserr.h"
28
#include "helpers.h"
517 mateuszvis 29
#include "rmodinit.h"
402 mateuszvis 30
 
31
#include "redir.h"
32
 
33
static unsigned short oldstdout = 0xffff;
34
 
517 mateuszvis 35
 
402 mateuszvis 36
/* parse commandline and performs necessary redirections. cmdline is
517 mateuszvis 37
 * modified so all redirections are cut out. */
38
void redir_parsecmd(struct redir_data *d, char *cmdline) {
402 mateuszvis 39
  unsigned short i;
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
 
517 mateuszvis 56
  /* clear out the redir_data struct */
57
  memset(d, 0, sizeof(*d));
58
 
59
  /* parse the command line and fill struct with pointers */
402 mateuszvis 60
  for (i = 0;; i++) {
61
    if (cmdline[i] == '>') {
62
      cmdline[i] = 0;
517 mateuszvis 63
      if (cmdline[i + 1] == '>') {
64
        i++;
65
        d->stdout_openflag = 0x11;  /* used during int 21h,AH=6C */
66
      } else {
67
        d->stdout_openflag = 0x12;
68
      }
69
      d->stdoutfile = cmdline + i + 1;
70
      while (d->stdoutfile[0] == ' ') d->stdoutfile++;
402 mateuszvis 71
    } else if (cmdline[i] == '<') {
72
      cmdline[i] = 0;
517 mateuszvis 73
      d->stdinfile = cmdline + i + 1;
74
      while (d->stdinfile[0] == ' ') d->stdinfile++;
402 mateuszvis 75
    } else if (cmdline[i] == '|') {
76
      cmdline[i] = 0;
517 mateuszvis 77
      if (pipescount < REDIR_MAX_PIPES) {
78
        d->pipes[pipescount++] = cmdline + i + 1;
79
        while (d->pipes[pipescount][0] == ' ') d->pipes[pipescount]++;
80
      }
402 mateuszvis 81
    } else if (cmdline[i] == 0) {
82
      break;
83
    }
84
  }
517 mateuszvis 85
}
402 mateuszvis 86
 
517 mateuszvis 87
 
88
/* apply stdin/stdout redirections defined in redir_data, returns 0 on success */
89
int redir_apply(const struct redir_data *d) {
90
  if (d->stdinfile != NULL) {
402 mateuszvis 91
    outputnl("ERROR: stdin redirection is not supported yet");
92
    return(-1);
93
  }
94
 
517 mateuszvis 95
  if (d->stdoutfile != NULL) {
96
    unsigned short openflag = d->stdout_openflag;
402 mateuszvis 97
    unsigned short errcode = 0;
98
    unsigned short handle = 0;
517 mateuszvis 99
    const char *myptr = d->stdoutfile;
402 mateuszvis 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)*/
517 mateuszvis 112
      mov si, myptr      /* ASCIIZ filename */
402 mateuszvis 113
      int 0x21           /* AX=handle on success (CF clear), otherwise dos err */
520 mateuszvis 114
      mov handle, ax     /* save the file handler */
115
      jnc JMPEOF
116
      mov errcode, ax
402 mateuszvis 117
      jmp DONE
520 mateuszvis 118
 
119
      JMPEOF:
120
      cmp openflag, word ptr 0x11
121
      jne DUPSTDOUT
122
      /* jump to the end of the file (required for >> redirections) */
123
      mov ax, 0x4202     /* jump to position EOF - CX:DX in handle BX */
124
      mov bx, handle
125
      xor cx, cx
126
      xor dx, dx
127
      int 0x21
128
 
129
      /* save (duplicate) current stdout so I can revert it later */
402 mateuszvis 130
      DUPSTDOUT:
131
      mov ah, 0x45       /* duplicate file handle */
132
      mov bx, 1          /* handle to dup (1=stdout) */
133
      int 0x21           /* ax = new file handle */
520 mateuszvis 134
      mov oldstdout, ax
402 mateuszvis 135
      /* redirect the stdout handle */
520 mateuszvis 136
      mov bx, handle     /* dst handle */
402 mateuszvis 137
      mov cx, 1          /* src handle (1=stdout) */
138
      mov ah, 0x46       /* redirect a handle */
139
      int 0x21
140
      /* close the original file handle (no longer needed) */
141
      mov ah, 0x3e       /* close a file handle (handle in BX) */
142
      int 0x21
143
      DONE:
144
      pop si
145
      pop dx
146
      pop cx
147
      pop bx
148
      pop ax
149
    }
150
    if (errcode != 0) {
151
      outputnl(doserr(errcode));
152
      return(-1);
153
    }
154
  }
155
 
156
  return(0);
157
}
158
 
159
 
160
/* restores previous stdout/stdin handlers if they have been redirected */
161
void redir_revert(void) {
162
  _asm {
163
    /* if oldstdout is 0xffff then not redirected */
164
    cmp word ptr [oldstdout], 0xffff
165
    je DONE
166
    /* redirect the stdout handle */
167
    mov bx, [oldstdout] /* dst handle */
168
    mov cx, 1           /* src handle (1=stdout) */
169
    mov ah, 0x46        /* redirect a handle */
170
    int 0x21
519 mateuszvis 171
    /* close old handle (in bx already) */
172
    mov ah, 0x3e
173
    int 0x21
402 mateuszvis 174
    mov [oldstdout], 0xffff
175
    DONE:
176
  }
177
}