Subversion Repositories SvarDOS

Rev

Rev 520 | Rev 543 | 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 "helpers.h"
517 mateuszvis 28
#include "rmodinit.h"
402 mateuszvis 29
 
30
#include "redir.h"
31
 
32
static unsigned short oldstdout = 0xffff;
33
 
517 mateuszvis 34
 
402 mateuszvis 35
/* parse commandline and performs necessary redirections. cmdline is
517 mateuszvis 36
 * modified so all redirections are cut out. */
37
void redir_parsecmd(struct redir_data *d, char *cmdline) {
402 mateuszvis 38
  unsigned short i;
39
  unsigned short pipescount = 0;
40
 
41
  /* NOTE:
42
   *
43
   * 1. while it is possible to type a command with multiple
44
   *    redirections, MSDOS executes only the last redirection.
45
   *
46
   * 2. the order in which >, < and | are provided on the command line does
47
   *    not seem to matter for MSDOS. piped commands are executed first (in
48
   *    the order they appear) and the result of the last one is redirected to
49
   *    whenever the last > points at.
50
   */
51
 
52
  /* preset oldstdout to 0xffff in case no redirection is required */
53
  oldstdout = 0xffff;
54
 
517 mateuszvis 55
  /* clear out the redir_data struct */
56
  memset(d, 0, sizeof(*d));
57
 
58
  /* parse the command line and fill struct with pointers */
402 mateuszvis 59
  for (i = 0;; i++) {
60
    if (cmdline[i] == '>') {
61
      cmdline[i] = 0;
517 mateuszvis 62
      if (cmdline[i + 1] == '>') {
63
        i++;
64
        d->stdout_openflag = 0x11;  /* used during int 21h,AH=6C */
65
      } else {
66
        d->stdout_openflag = 0x12;
67
      }
68
      d->stdoutfile = cmdline + i + 1;
69
      while (d->stdoutfile[0] == ' ') d->stdoutfile++;
402 mateuszvis 70
    } else if (cmdline[i] == '<') {
71
      cmdline[i] = 0;
517 mateuszvis 72
      d->stdinfile = cmdline + i + 1;
73
      while (d->stdinfile[0] == ' ') d->stdinfile++;
402 mateuszvis 74
    } else if (cmdline[i] == '|') {
75
      cmdline[i] = 0;
517 mateuszvis 76
      if (pipescount < REDIR_MAX_PIPES) {
77
        d->pipes[pipescount++] = cmdline + i + 1;
78
        while (d->pipes[pipescount][0] == ' ') d->pipes[pipescount]++;
79
      }
402 mateuszvis 80
    } else if (cmdline[i] == 0) {
81
      break;
82
    }
83
  }
517 mateuszvis 84
}
402 mateuszvis 85
 
517 mateuszvis 86
 
87
/* apply stdin/stdout redirections defined in redir_data, returns 0 on success */
88
int redir_apply(const struct redir_data *d) {
89
  if (d->stdinfile != NULL) {
402 mateuszvis 90
    outputnl("ERROR: stdin redirection is not supported yet");
91
    return(-1);
92
  }
93
 
517 mateuszvis 94
  if (d->stdoutfile != NULL) {
95
    unsigned short openflag = d->stdout_openflag;
402 mateuszvis 96
    unsigned short errcode = 0;
97
    unsigned short handle = 0;
517 mateuszvis 98
    const char *myptr = d->stdoutfile;
402 mateuszvis 99
 
100
    /* */
101
    _asm {
102
      push ax
103
      push bx
104
      push cx
105
      push dx
106
      push si
107
      mov ax, 0x6c00     /* Extended Open/Create */
108
      mov bx, 1          /* access mode (0=read, 1=write, 2=r+w */
109
      xor cx, cx         /* attributes when(if) creating the file (0=normal) */
110
      mov dx, [openflag] /* action if file exists (0x11=open, 0x12=truncate)*/
517 mateuszvis 111
      mov si, myptr      /* ASCIIZ filename */
402 mateuszvis 112
      int 0x21           /* AX=handle on success (CF clear), otherwise dos err */
520 mateuszvis 113
      mov handle, ax     /* save the file handler */
114
      jnc JMPEOF
115
      mov errcode, ax
402 mateuszvis 116
      jmp DONE
520 mateuszvis 117
 
118
      JMPEOF:
119
      cmp openflag, word ptr 0x11
120
      jne DUPSTDOUT
121
      /* jump to the end of the file (required for >> redirections) */
122
      mov ax, 0x4202     /* jump to position EOF - CX:DX in handle BX */
123
      mov bx, handle
124
      xor cx, cx
125
      xor dx, dx
126
      int 0x21
127
 
128
      /* save (duplicate) current stdout so I can revert it later */
402 mateuszvis 129
      DUPSTDOUT:
130
      mov ah, 0x45       /* duplicate file handle */
131
      mov bx, 1          /* handle to dup (1=stdout) */
132
      int 0x21           /* ax = new file handle */
520 mateuszvis 133
      mov oldstdout, ax
402 mateuszvis 134
      /* redirect the stdout handle */
520 mateuszvis 135
      mov bx, handle     /* dst handle */
402 mateuszvis 136
      mov cx, 1          /* src handle (1=stdout) */
137
      mov ah, 0x46       /* redirect a handle */
138
      int 0x21
139
      /* close the original file handle (no longer needed) */
140
      mov ah, 0x3e       /* close a file handle (handle in BX) */
141
      int 0x21
142
      DONE:
143
      pop si
144
      pop dx
145
      pop cx
146
      pop bx
147
      pop ax
148
    }
149
    if (errcode != 0) {
538 mateuszvis 150
      nls_outputnl_doserr(errcode);
402 mateuszvis 151
      return(-1);
152
    }
153
  }
154
 
155
  return(0);
156
}
157
 
158
 
159
/* restores previous stdout/stdin handlers if they have been redirected */
160
void redir_revert(void) {
161
  _asm {
162
    /* if oldstdout is 0xffff then not redirected */
163
    cmp word ptr [oldstdout], 0xffff
164
    je DONE
165
    /* redirect the stdout handle */
166
    mov bx, [oldstdout] /* dst handle */
167
    mov cx, 1           /* src handle (1=stdout) */
168
    mov ah, 0x46        /* redirect a handle */
169
    int 0x21
519 mateuszvis 170
    /* close old handle (in bx already) */
171
    mov ah, 0x3e
172
    int 0x21
402 mateuszvis 173
    mov [oldstdout], 0xffff
174
    DONE:
175
  }
176
}