Subversion Repositories SvarDOS

Rev

Rev 517 | Rev 520 | 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 */
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
519 mateuszvis 160
    /* close old handle (in bx already) */
161
    mov ah, 0x3e
162
    int 0x21
402 mateuszvis 163
    mov [oldstdout], 0xffff
164
    DONE:
165
  }
166
}