File: TURBOC.C

package info (click to toggle)
flip 1.20-4
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster
  • size: 196 kB
  • sloc: ansic: 1,186; cpp: 172; makefile: 124; sh: 61
file content (325 lines) | stat: -rw-r--r-- 10,549 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
/* ::[[ @(#) turboc.c 1.6 89/07/02 00:19:31 ]]:: */
#ifndef LINT
static char sccsid[]="::[[ @(#) turboc.c 1.6 89/07/02 00:19:31 ]]::";
#endif

/*
Copyright 1989 Rahul Dhesi, All rights reserved.

This file is used only for MS-DOS & Turbo C.
*/

/*
Checksum: 3933529970      (check or update this with "brik")
*/

/*
nextfile() is a general wildcard expansion function that may be used
with other programs.  Usage instructions are below.  It does not
simply expand wildcards in an entire argument list.  Instead, it is
called in a loop as described below, and returns one matching
filename each time it is called.

These functions are for the SMALL MEMORY MODEL ONLY.
*/

extern unsigned _stklen = 10000;

#include "assert.h"
#include "flip.h"

#define  FMAX  2        /* Number of different filename patterns */
#define  PATHSIZE 200   /* Size of MS-DOS pathname */
#define  NULL  0

#ifdef ANSIPROTO
char *strtcpy (char *, char *);
int strlen (char *);
char *strcpy (char *, char *);
#endif


/* Structure definitions for MS-DOS software interrupt intdos() */

struct WORD_REGISTERS {
   unsigned int ax, bx, cx, dx, si, di, carry, flags;
};

/* byte registers */

struct BYTE_REGISTERS {
   unsigned char al, ah, bl, bh, cl, ch, dl, dh;
};

union REGS {
   struct WORD_REGISTERS x;
   struct BYTE_REGISTERS h;
};

int intdos (union REGS *, union REGS *);

/*
format of disk transfer address after MS-DOS calls FindFirst and
FindNext
*/
struct dta_t {
   char junk[22];
   int time;
   int date;
   long size;
   char fname[13];
   char just_in_case[4];   /* in case MS-DOS writes too much */
};

void setdta (struct dta_t *);
void fcbpath (struct dta_t *, char *, char *);

/*******************/
/*
nextfile() returns the name of the next source file matching a filespec.

INPUT
   what: A flag specifying what to do.  If "what" is 0, nextfile()
      initializes itself.  If "what" is 1, nextfile() returns the next
      matching filename.
   filespec:  The filespec, usually containing wildcard characters, that
      specifies which files are needed.  If "what" is 0, filespec must be
      the filespec for which matching filenames are needed.  If "what" is 1,
      nextfile() does not use "filespec" and "filespec" should be NULL to
      avoid an assertion error during debugging.
   fileset:  nextfile() can keep track of more than one set of filespecs.
      The fileset specifies which filespec is being matched and therefore
      which set of files is being considered.  "fileset" can be in the
      range 0:FMAX.  Initialization of one fileset does not affect the
      other filesets.

OUTPUT
   IF what == 0 THEN
      return value is NULL
   ELSE IF what == 1 THEN
      IF a matching filename is found THEN
         return value is pointer to matching filename including supplied path
      ELSE
         IF at least one file matched previously but no more match THEN
            return value is NULL
         ELSE IF supplied filespec never matched any filename THEN
            IF this is the first call with what == 1 THEN
               return value is pointer to original filespec
            ELSE
               return value is NULL
            END IF
         END IF
      END IF
   END IF

NOTE

   Initialization done when "what"=0 is not dependent on the correctness
   of the supplied filespec but simply initializes internal variables
   and makes a local copy of the supplied filespec.  If the supplied
   filespec was illegal, the only effect is that the first time that
   nextfile() is called with "what"=1, it will return the original
   filespec instead of a matching filename.  That the filespec was
   illegal will become obvious when the caller attempts to open the
   returned filename for input/output and the open attempt fails.

USAGE HINTS

nextfile() can be used in the following manner:

      char *filespec;                  -- will point to filespec
      char *this_file;                 -- will point to matching filename
      filespec = parse_command_line(); -- may contain wildcards
      FILE *stream;

      nextfile (0, filespec, 0);          -- initialize fileset 0
      while ((this_file = nextfile(1, (char *) NULL, 0)) != NULL) {
         stream = fopen (this_file, "whatever");
         if (stream == NULL)
            printf ("could not open %s\n", this_file);
         else
            perform_operations (stream);
      }
*/

char *nextfile (what, filespec, fileset)
int what;                        /* whether to initialize or match      */
register char *filespec;         /* filespec to match if initializing   */
register int fileset;            /* which set of files                  */
{
   static struct dta_t new_dta [FMAX+1];     /* our own private dta        */
   static int first_time [FMAX+1];
   static char pathholder [FMAX+1][PATHSIZE]; /* holds a pathname to return */
   static char saved_fspec [FMAX+1][PATHSIZE];/* our own copy of filespec   */
   union REGS regs;

   assert(fileset >= 0 && fileset <= FMAX);
   if (what == 0) {
      assert(filespec != NULL);
      strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
      first_time[fileset] = 1;
      return ((char *) NULL);
   }

   setdta (&new_dta[fileset]);   /* set new dta -- our very own */
   assert(what == 1);
   assert(filespec == NULL);
   assert(first_time[fileset] == 0 || first_time[fileset] == 1);

   if (first_time[fileset]) {             /* first time -- initialize etc. */
      /* find first matching file */
      regs.h.ah = 0x4e;                   /* FindFirst MS-DOS call    */
      regs.x.dx = (unsigned int) saved_fspec[fileset]; /* filespec to match */
      regs.x.cx = 0;                      /* search attributes       */
      intdos (&regs, &regs);
   } else {
      /* find next matching file */
      regs.h.ah = 0x4f;                   /* FindNext MS-DOS call     */
      intdos (&regs, &regs);
   }

   if (regs.x.carry != 0) {            /* if error status                  */
      if (first_time[fileset]) {       /*   if file never matched then     */
         first_time[fileset] = 0;
         return (saved_fspec[fileset]);/*      return original filespec    */
      } else {                         /*   else                           */
         first_time[fileset] = 0;      /*                                  */
         return ((char *) NULL);         /*      return (NULL) for no more   */
      }
   } else {                                        /* a file matched */
      first_time[fileset] = 0;
      /* add path info  */
      fcbpath (&new_dta[fileset], saved_fspec[fileset], pathholder[fileset]);
      return (pathholder[fileset]);                /* matching path  */
   }
} /* nextfile */

/*******************/
/* This function sets the dta to a new dta */
void setdta (dta)
struct dta_t *dta;
{
   union REGS regs;
   regs.h.ah = 0x1a;                /* SetDTA Call       */
   regs.x.dx = (unsigned int) dta;  /* new DTA address   */
   intdos (&regs, &regs);
}

/*******************/
/*
fcbpath() accepts a pointer to the Disk Transfer Area, a character
pointer to a pathname that may contain wildcards, and a character
pointer to a buffer.  It copies into the buffer the path prefix from
the pathname and the filename prefix from the DTA so that it forms a
complete path.
*/

void fcbpath (dta, old_path, new_path)
struct dta_t *dta;
char *old_path;
register char *new_path;
{
   register int i;
   int length, start_pos;

   strcpy(new_path, old_path);               /* copy the whole thing first */
   length = strlen(new_path);
   i = length - 1;                           /* i points to end of path */
   while (i >= 0 && new_path[i] != '/' && new_path[i] != '\\' && new_path[i] != ':')
      i--;
   /* either we found a "/", "\", or ":", or we reached the beginning of
      the name.  In any case, i points to the last character of the
      path part. */
   start_pos = i + 1;
   for (i = 0; i < 13; i++)
      new_path[start_pos+i] = dta->fname[i];
   new_path[start_pos+13] = '\0';
}
/* -- END OF nextfile() and related functions -- */

/*
For Turbo C, we implement MVFILE as a file copy to avoid wildcard
expansion finding the same file again after a direct rename.  To
avoid leaving a partially-written destination file, we trap ^C,
and if it occurs, delete the dest file and quickly do just a simple
rename to it.
*/

#define BLOCKSIZ  16384
#include <fcntl.h>
#include <sys/stat.h>
#include <io.h>
#include <signal.h>

void handler (int);        /* ^C handler */
char  *xsrc, *xdest;       /* global for handler() */
void (*oldsignal) (int);   /* global for handler() */
int infd, outfd;           /* global for handler() */
int brk_flag;              /* ms-dos break flag status */
int getcbrk (void);
int setcbrk (int);

int MVFILE (src, dest)
char *src;
char *dest;
{
   int retval;
   char buf[BLOCKSIZ];

   retval = -1;               /* default error return */
   xsrc = src;  xdest = dest; /* make visible to handler */

   oldsignal = signal (SIGINT, handler);
   outfd = open (dest, O_CREAT|O_TRUNC|O_BINARY, S_IREAD|S_IWRITE);
   if (outfd == -1)
      goto erret;
   infd = open (src, O_RDONLY|O_BINARY);
   if (infd == -1) {
      close (outfd);
      goto erret;
   }
   while ((retval = read (infd, buf, BLOCKSIZ)) > 0) {
      if (write (outfd, buf, retval) != retval) {
         retval = -1;
         goto done;
      }
   }
 done: /* retval is zero on normal exit from loop, else nonzero */
   close (infd); close (outfd);

   if (retval == 0) {
      signal (SIGINT, oldsignal);      /* avoid race condition */
      unlink (src);
      return (retval);
   }
erret:
   /* if error during read/write, do rename to avoid loss of dest file */
   unlink (dest);
   retval = rename (src, dest);
   signal (SIGINT, oldsignal);
   return (retval);
}

void handler (int sig)
{
   signal (sig, SIG_IGN);
   close (infd);  close (outfd);
   unlink (xdest);
   rename (xsrc, xdest);
   signal (sig, oldsignal);
   raise  (sig);                 /* original handler gets signal now */
}

#include <conio.h>
void brktst() { kbhit(); }      /* test for user interrupt */

void spec_init()
{
   brk_flag = getcbrk();
   setcbrk (0);
}

void spec_exit()
{
   setcbrk (brk_flag);
}