Subversion Repositories SvarDOS

Rev

Rev 571 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 571 Rev 989
1
/* This file is part of the SvarCOM project and is published under the terms
1
/* This file is part of the SvarCOM project and is published under the terms
2
 * of the MIT license.
2
 * of the MIT license.
3
 *
3
 *
4
 * Copyright (C) 2021-2022 Mateusz Viste
4
 * Copyright (C) 2021-2022 Mateusz Viste
5
 *
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
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
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:
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
12
 *
13
 * The above copyright notice and this permission notice shall be included in
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
14
 * all copies or substantial portions of the Software.
15
 *
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
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,
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
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
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
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
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
22
 * DEALINGS IN THE SOFTWARE.
23
 */
23
 */
24
 
24
 
25
/*
25
/*
26
 * ln add linkname linkdir
26
 * ln add linkname linkdir
27
 * ln del linkname
27
 * ln del linkname
28
 * ln list [pattern]
28
 * ln list [pattern]
29
 */
29
 */
30
 
30
 
31
static enum cmd_result cmd_lnadd(char *BUFFER, const char *linkname, const char *targetdir, unsigned short env_seg) {
31
static enum cmd_result cmd_lnadd(char *BUFFER, const char *linkname, const char *targetdir, unsigned short env_seg) {
32
  const char *ext;
32
  const char *ext;
33
  char *realdirname = BUFFER;
33
  char *realdirname = BUFFER;
34
  unsigned short realdirnamelen;
34
  unsigned short realdirnamelen;
35
  char *buff = BUFFER + 256;
35
  char *buff = BUFFER + 256;
36
  unsigned short doserr;
36
  unsigned short doserr;
37
 
37
 
38
  /* convert dirname to realpath */
38
  /* convert dirname to realpath */
39
  doserr = file_truename(targetdir, realdirname);
39
  doserr = file_truename(targetdir, realdirname);
40
  if (doserr != 0) {
40
  if (doserr != 0) {
41
    nls_outputnl_doserr(doserr);
41
    nls_outputnl_doserr(doserr);
42
    return(CMD_FAIL);
42
    return(CMD_FAIL);
43
  }
43
  }
44
 
44
 
45
  /* does EXENAME in DIRECTORY exist? */
45
  /* does EXENAME in DIRECTORY exist? */
46
  if (lookup_cmd(buff, linkname, realdirname, &ext) != 0) {
46
  if (lookup_cmd(buff, linkname, realdirname, &ext) != 0) {
47
    outputnl("No matching executable found in given path.");
47
    nls_outputnl(29,4); /* "No matching executable found in given path." */
48
    return(CMD_FAIL);
48
    return(CMD_FAIL);
49
  }
49
  }
50
 
50
 
51
  /* open DOSDIR\CFG\LINKS.DB and write realdirname to */
51
  /* open DOSDIR\CFG\LINKS.DB and write realdirname to */
52
  if (link_computefname(buff, linkname, env_seg) != 0) return(CMD_FAIL);
52
  if (link_computefname(buff, linkname, env_seg) != 0) return(CMD_FAIL);
53
 
53
 
54
  realdirnamelen = strlen(realdirname);
54
  realdirnamelen = strlen(realdirname);
55
 
55
 
56
  /* open file *only if it does not exist yet* and write realdirname to it */
56
  /* open file *only if it does not exist yet* and write realdirname to it */
57
  _asm {
57
  _asm {
58
    push ax
58
    push ax
59
    push bx
59
    push bx
60
    push cx
60
    push cx
61
    push dx
61
    push dx
62
 
62
 
63
    mov ax, 0x6c00  /* extended OPEN */
63
    mov ax, 0x6c00  /* extended OPEN */
64
    mov bx, 1       /* open for WRITE */
64
    mov bx, 1       /* open for WRITE */
65
    xor cx, cx      /* create the file with no attributes */
65
    xor cx, cx      /* create the file with no attributes */
66
    mov dx, 0x0010  /* create file if it does not exists, otherwise fail */
66
    mov dx, 0x0010  /* create file if it does not exists, otherwise fail */
67
    mov si, buff    /* file name */
67
    mov si, buff    /* file name */
68
    int 0x21
68
    int 0x21
69
    jnc WRITE
69
    jnc WRITE
70
    mov doserr, ax
70
    mov doserr, ax
71
    jmp DONE
71
    jmp DONE
72
 
72
 
73
    WRITE:
73
    WRITE:
74
    mov bx, ax      /* file handle */
74
    mov bx, ax      /* file handle */
75
    mov ah, 0x40    /* write to file */
75
    mov ah, 0x40    /* write to file */
76
    mov cx, realdirnamelen
76
    mov cx, realdirnamelen
77
    mov dx, realdirname
77
    mov dx, realdirname
78
    int 0x21
78
    int 0x21
79
 
79
 
80
    mov ah, 0x3e    /* close file in BX */
80
    mov ah, 0x3e    /* close file in BX */
81
    int 0x21
81
    int 0x21
82
 
82
 
83
    DONE:
83
    DONE:
84
 
84
 
85
    pop dx
85
    pop dx
86
    pop cx
86
    pop cx
87
    pop bx
87
    pop bx
88
    pop ax
88
    pop ax
89
  }
89
  }
90
 
90
 
91
  if (doserr != 0) {
91
  if (doserr != 0) {
92
    nls_outputnl_doserr(doserr);
92
    nls_outputnl_doserr(doserr);
93
    return(CMD_FAIL);
93
    return(CMD_FAIL);
94
  }
94
  }
95
 
95
 
96
  return(CMD_OK);
96
  return(CMD_OK);
97
}
97
}
98
 
98
 
99
 
99
 
100
static enum cmd_result cmd_lndel(char *buff, const char *linkname, unsigned short env_seg) {
100
static enum cmd_result cmd_lndel(char *buff, const char *linkname, unsigned short env_seg) {
101
  unsigned short i;
101
  unsigned short i;
102
 
102
 
103
  /* is the argument valid? (must not contain any dot nor backslash) */
103
  /* is the argument valid? (must not contain any dot nor backslash) */
104
  for (i = 0; linkname[i] != 0; i++) {
104
  for (i = 0; linkname[i] != 0; i++) {
105
    if ((linkname[i] == '.') || (linkname[i] == '/') || (linkname[i] == '\\')) {
105
    if ((linkname[i] == '.') || (linkname[i] == '/') || (linkname[i] == '\\')) {
106
      outputnl("Bad link name");
106
      nls_outputnl(0,3); /* "Invalid parameter format" */
107
      return(CMD_OK);
107
      return(CMD_OK);
108
    }
108
    }
109
  }
109
  }
110
 
110
 
111
  /* prep link filename to look at */
111
  /* prep link filename to look at */
112
  if (link_computefname(buff, linkname, env_seg) != 0) return(CMD_FAIL);
112
  if (link_computefname(buff, linkname, env_seg) != 0) return(CMD_FAIL);
113
 
113
 
114
  /* try removing it */
114
  /* try removing it */
115
  i = 0;
115
  i = 0;
116
  _asm {
116
  _asm {
117
    push ax
117
    push ax
118
    push bx
118
    push bx
119
    push cx
119
    push cx
120
    push dx
120
    push dx
121
 
121
 
122
    mov ah, 0x41
122
    mov ah, 0x41
123
    mov dx, buff
123
    mov dx, buff
124
    int 0x21
124
    int 0x21
125
    jnc SUCCESS
125
    jnc SUCCESS
126
    mov i, ax
126
    mov i, ax
127
    SUCCESS:
127
    SUCCESS:
128
 
128
 
129
    pop dx
129
    pop dx
130
    pop cx
130
    pop cx
131
    pop bx
131
    pop bx
132
    pop ax
132
    pop ax
133
  }
133
  }
134
 
134
 
135
  if (i != 0) nls_outputnl_doserr(i);
135
  if (i != 0) nls_outputnl_doserr(i);
136
 
136
 
137
  return(CMD_OK);
137
  return(CMD_OK);
138
}
138
}
139
 
139
 
140
 
140
 
141
static enum cmd_result cmd_lnlist(char *buff, const char *linkname, unsigned short env_seg) {
141
static enum cmd_result cmd_lnlist(char *buff, const char *linkname, unsigned short env_seg) {
142
  unsigned short i, pathlen;
142
  unsigned short i, pathlen;
143
  struct DTA *dta = (void *)0x80;
143
  struct DTA *dta = (void *)0x80;
144
  char *buff128 = buff + 256;
144
  char *buff128 = buff + 256;
145
  char *buff16 = buff128 + 128;
145
  char *buff16 = buff128 + 128;
146
 
146
 
147
  if (linkname != NULL) {
147
  if (linkname != NULL) {
148
    /* make sure link pattern is valid (must not contain '.' or '\\' or '/') */
148
    /* make sure link pattern is valid (must not contain '.' or '\\' or '/') */
149
    for (i = 0; linkname[i] != 0; i++) {
149
    for (i = 0; linkname[i] != 0; i++) {
150
      switch (linkname[i]) {
150
      switch (linkname[i]) {
151
        case '.':
151
        case '.':
152
        case '/':
152
        case '/':
153
        case '\\':
153
        case '\\':
154
          outputnl("Invalid link pattern");
154
          nls_outputnl(0,3); /* "Invalid parameter format" */
155
          return(CMD_FAIL);
155
          return(CMD_FAIL);
156
      }
156
      }
157
    }
157
    }
158
  } else {
158
  } else {
159
    linkname = "*";
159
    linkname = "*";
160
  }
160
  }
161
 
161
 
162
  /* fetch %DOSDIR% */
162
  /* fetch %DOSDIR% */
163
  pathlen = env_lookup_valcopy(buff, 128, env_seg, "DOSDIR");
163
  pathlen = env_lookup_valcopy(buff, 128, env_seg, "DOSDIR");
164
  if (pathlen == 0) {
164
  if (pathlen == 0) {
165
    outputnl("%DOSDIR% not defined");
165
    nls_outputnl(29,5); /* "%DOSDIR% not defined" */
166
    return(CMD_FAIL);
166
    return(CMD_FAIL);
167
  }
167
  }
168
 
168
 
169
  /* prep DOSDIR\LINKS\pattern */
169
  /* prep DOSDIR\LINKS\pattern */
170
  if (buff[pathlen - 1] == '\\') pathlen--;
170
  if (buff[pathlen - 1] == '\\') pathlen--;
171
  pathlen += sprintf(buff + pathlen, "\\LINKS\\");
171
  pathlen += sprintf(buff + pathlen, "\\LINKS\\");
172
  sprintf(buff + pathlen, "%s.LNK", linkname);
172
  sprintf(buff + pathlen, "%s.LNK", linkname);
173
 
173
 
174
  if (findfirst(dta, buff, DOS_ATTR_RO | DOS_ATTR_ARC) != 0) return(CMD_OK);
174
  if (findfirst(dta, buff, DOS_ATTR_RO | DOS_ATTR_ARC) != 0) return(CMD_OK);
175
 
175
 
176
  do {
176
  do {
177
    /* print link file name (but trim ".lnk") */
177
    /* print link file name (but trim ".lnk") */
178
    for (i = 0; (dta->fname[i] != 0) && (dta->fname[i] != '.'); i++) buff16[i] = dta->fname[i];
178
    for (i = 0; (dta->fname[i] != 0) && (dta->fname[i] != '.'); i++) buff16[i] = dta->fname[i];
179
    if (i < 8) buff16[i++] = '\t';
179
    if (i < 8) buff16[i++] = '\t';
180
    buff16[i] = 0;
180
    buff16[i] = 0;
181
    output(buff16);
181
    output(buff16);
182
    output(" @ ");
182
    output(" @ ");
183
    /* prep full link filename */
183
    /* prep full link filename */
184
    strcpy(buff + pathlen, dta->fname);
184
    strcpy(buff + pathlen, dta->fname);
185
    /* read up to 128 bytes from link file to buff and display it */
185
    /* read up to 128 bytes from link file to buff and display it */
186
    i = 0;
186
    i = 0;
187
    _asm {
187
    _asm {
188
      push ax
188
      push ax
189
      push bx
189
      push bx
190
      push cx
190
      push cx
191
      push dx
191
      push dx
192
 
192
 
193
      /* open file */
193
      /* open file */
194
      mov ax, 0x3d00
194
      mov ax, 0x3d00
195
      mov dx, buff   /* filename */
195
      mov dx, buff   /* filename */
196
      int 0x21
196
      int 0x21
197
      jc FAIL_FOPEN
197
      jc FAIL_FOPEN
198
      /* read from file */
198
      /* read from file */
199
      mov bx, ax
199
      mov bx, ax
200
      mov ah, 0x3f
200
      mov ah, 0x3f
201
      mov cx, 128
201
      mov cx, 128
202
      mov dx, buff128
202
      mov dx, buff128
203
      int 0x21
203
      int 0x21
204
      jc FAIL_FREAD
204
      jc FAIL_FREAD
205
      mov i, ax
205
      mov i, ax
206
      /* close file */
206
      /* close file */
207
      FAIL_FREAD:
207
      FAIL_FREAD:
208
      mov ah, 0x3e
208
      mov ah, 0x3e
209
      int 0x21
209
      int 0x21
210
      FAIL_FOPEN:
210
      FAIL_FOPEN:
211
 
211
 
212
      pop dx
212
      pop dx
213
      pop cx
213
      pop cx
214
      pop bx
214
      pop bx
215
      pop ax
215
      pop ax
216
    }
216
    }
217
    buff128[i] = 0;
217
    buff128[i] = 0;
218
    /* make sure no cr or lf is present */
218
    /* make sure no cr or lf is present */
219
    for (i = 0; buff128[i] != 0; i++) {
219
    for (i = 0; buff128[i] != 0; i++) {
220
      if ((buff128[i] == '\r') || (buff128[i] == '\n')) {
220
      if ((buff128[i] == '\r') || (buff128[i] == '\n')) {
221
        buff128[i] = 0;
221
        buff128[i] = 0;
222
        break;
222
        break;
223
      }
223
      }
224
    }
224
    }
225
    outputnl(buff128);
225
    outputnl(buff128);
226
  } while (findnext(dta) == 0);
226
  } while (findnext(dta) == 0);
227
 
227
 
228
  return(CMD_OK);
228
  return(CMD_OK);
229
}
229
}
230
 
230
 
231
 
231
 
232
static enum cmd_result cmd_ln(struct cmd_funcparam *p) {
232
static enum cmd_result cmd_ln(struct cmd_funcparam *p) {
233
  if (cmd_ishlp(p)) {
233
  if (cmd_ishlp(p)) {
234
    outputnl("Adds, deletes or displays executable links.");
234
    nls_outputnl(29,0); /* "Adds, deletes or displays executable links." */
235
    outputnl("");
235
    outputnl("");
236
    outputnl("LN ADD linkname targetdir");
236
    nls_outputnl(29,1); /* "LN ADD linkname targetdir" */
237
    outputnl("LN DEL linkname");
237
    nls_outputnl(29,2); /* "LN DEL linkname" */
238
    outputnl("LN LIST [pattern]");
238
    nls_outputnl(29,3); /* "LN LIST [pattern]" */
239
    return(CMD_OK);
239
    return(CMD_OK);
240
  }
240
  }
241
 
241
 
242
  if (p->argc == 0) {
242
  if (p->argc == 0) {
243
    outputnl("Not enough parameters");
243
    nls_outputnl(0,7); /* "Required parameter missing */
244
    return(CMD_OK);
244
    return(CMD_OK);
245
  }
245
  }
246
 
246
 
247
  /* detect what subfunction the user wants */
247
  /* detect what subfunction the user wants */
248
  if ((imatch(p->argv[0], "add")) && (p->argc == 3)) return(cmd_lnadd(p->BUFFER, p->argv[1], p->argv[2], p->env_seg));
248
  if ((imatch(p->argv[0], "add")) && (p->argc == 3)) return(cmd_lnadd(p->BUFFER, p->argv[1], p->argv[2], p->env_seg));
249
  if ((imatch(p->argv[0], "del")) && (p->argc == 2)) return(cmd_lndel(p->BUFFER, p->argv[1], p->env_seg));
249
  if ((imatch(p->argv[0], "del")) && (p->argc == 2)) return(cmd_lndel(p->BUFFER, p->argv[1], p->env_seg));
250
  if (imatch(p->argv[0], "list")) {
250
  if (imatch(p->argv[0], "list")) {
251
    if (p->argc == 1) return(cmd_lnlist(p->BUFFER, NULL, p->env_seg));
251
    if (p->argc == 1) return(cmd_lnlist(p->BUFFER, NULL, p->env_seg));
252
    if (p->argc == 2) return(cmd_lnlist(p->BUFFER, p->argv[1], p->env_seg));
252
    if (p->argc == 2) return(cmd_lnlist(p->BUFFER, p->argv[1], p->env_seg));
253
  }
253
  }
254
 
254
 
255
  outputnl("Invalid argument");
255
  nls_outputnl(0,6); /* "Invalid parameter" */
256
  return(CMD_FAIL);
256
  return(CMD_FAIL);
257
}
257
}
258
 
258