home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
ddjmag
/
ddj8609.arc
/
HOLUB.SEP
< prev
next >
Wrap
Text File
|
1986-09-30
|
20KB
|
524 lines
Listing 1 -- dtree.c
------------------------------------------------------------------------------
1 #include <stdio.h>
2 #include <ctype.h>
3 #include <process.h> /* needed by spawn() */
4 #include <mydir.h> /* needed by dir() */
5 #include <signal.h> /* needed by signal() */
6
7 /* -------------------------------------------------------------------
8 * WHEREIS and DTREE
9 *
10 * A general-purpose directory traversal program. If invoked with name
11 * "whereis" it searches for a file in the directory system. If invoked
12 * with "dtree" it does the above and can also print the directory tree or
13 * executes a program in each directory. See usage() and wusage() below
14 * for more details about the command-line syntax.
15 *
16 * (C) 1986 Allen I. Holub. All rights reserved.
17 */
18
19 extern DIRECTORY *mk_dir( int );
20 extern void del_dir( DIRECTORY* );
21 extern void dir( char*, DIRECTORY* );
22 extern char *strrchr( char*, int );
23
24 /* -------------------------------------------------------------------
25 * These IBM graphics (box drawing) characters are used only if the
26 * output stream is stdout and isatty() is true (it will be false if
27 * stdout is redirected).
28 *
29 * | | |
30 * ELL | T_RIGHT +---- VERT | (dash) -----
31 * \300 +---- \303 | \263 | \304
32 */
33
34 static char *Graph_chars[] = { "\263", "\300\304\304\304\304\304",
35 "\303\304\304\304\304\304" };
36
37 static char *Norm_chars[] = { "|", "+-----", "+-----" };
38 static char **Cset = Norm_chars;
39
40 #define VERT Cset[0]
41 #define ELL Cset[1]
42 #define T_RIGHT Cset[2]
43
44 /* -------------------------------------------------------------------- */
45
46 #define DSIZE 255
47 static char Startdir[DSIZE+1]; /* The cwd when the program started */
48 static char Map[ 64/8 ]; /* Bitmap for 64 bits. If the */
49 /* directory tree is deeper than */
50 /* this, we're in trouble. */
51
52 static char **Args = NULL; /* Thing to execute, pass to spawnv */
53 static int Short_pname = 0; /* Use short pathnames */
54 static int Draw = 0; /* Draw directory tree */
55 static char *Findfile = NULL; /* File for which we're searching */
56
57 /* -------------------------------------------------------------------
58 * bitmap routines:
59 * testbit(x) Evaluates TRUE if bit x is set.
60 * setbut (x,val) Set bit x if val is TRUE, else clear it.
61 */
62
63 #define testbit(x) ( Map[x >> 3] & (1 << (x & 0x07)) )
64
65 static setbit( c, val )
66 int c, val;
67 {
68 if( val )
69 Map[c >> 3] |= 1 << (c & 0x07) ;
70 else
71 Map[c >> 3] &= ~(1 << (c & 0x07)) ;
72 }
73
74 /* ------------------------------------------------------------------- */
75
76 pline( depth, terminate )
77 {
78 /* Print all the spaces and vertical bars in a graphic
79 * representation of a tree. Does nothing if Draw if FALSE.
80 */
81
82 int i;
83
84 if( !Draw )
85 return;
86
87 for(i = 0; i < depth-1 ; i++ )
88 printf(testbit(i) ? "%s " : " ", VERT );
89
90 if( terminate )
91 printf("\n");
92 }
93
94 /* ------------------------------------------------------------------- */
95
96 pname( dname )
97 char *dname;
98 {
99 /* Print a directory name with or without the full path
100 * spec (depending on whether Short_pname is set.
101 */
102
103 char *name;
104
105 if( !Short_pname || (dname[0] == '/' && !dname[1]) )
106 name = dname;
107
108 else if( name = strrchr(dname, '/') )
109 name++;
110 else
111 name = dname;
112
113 printf( "%s\n", name );
114 }
115
116 /* ------------------------------------------------------------------- */
117
118 execute( dname )
119 char *dname;
120 {
121 /* Execute the command specified on the command line from
122 * the directory we're now visiting. This routine changes
123 * the current directory but doesn't put it back.
124 * The Args vector must point at the command array.
125 */
126
127 if( Args )
128 {
129 chdir( dname );
130 if( spawnvp(P_WAIT, *Args, Args) == -1 )
131 perror(*Args);
132 }
133 }
134
135 /* ------------------------------------------------------------------- */
136
137 find( dname )
138 char *dname;
139 {
140 /* Look for the Findfile file in dname. If it's there, print
141 * the full path and file names and return 1, else return 0.
142 */
143
144 static char pathname[DSIZE];
145 char **vects;
146 int count;
147 int rval;
148 DIRECTORY *dp;
149
150 sprintf( pathname, "%s/%s", dname, Findfile );
151
152 if( !(dp = mk_dir( 64 )) )
153 {
154 printf("dtree: Out of memory\n");
155 return 0;
156 }
157
158 dp->files = 1; /* Get files only */
159 dp->sort = 1; /* sort the list */
160 dp->path = 1; /* and include the full path name */
161 dir( pathname, dp ); /* Fill the DIRECTORY structure */
162
163 vects = (char **) dp->dirv; /* ... and print it. */
164 count = rval = dp->nfiles;
165 while( --count >= 0 )
166 printf( "%s\n", *vects++ );
167
168 del_dir( dp );
169 return rval;
170 }
171
172 /* ------------------------------------------------------------------- */
173
174 static prnt( dname, others )
175 char *dname;
176 int others;
177 {
178 /* Does a recursive traversal of the directory tree rooted at
179 * dname. "others" is true if the calling routine has more
180 * subdirectories to print.
181 */
182
183 DIRECTORY *dp;
184 char **vects;
185 int count;
186 static int depth = -1;
187
188 if( ++depth && Draw )
189 {
190 pline( depth, 0 );
191 printf("%s", others ? T_RIGHT : ELL );
192 }
193
194 if( Findfile ) /* If -f was set don't */
195 { /* execute a -e command */
196 if( find( dname )) /* unless we've found the */
197 execute( dname ); /* file. find() prints the */
198 } /* filename if it exists. */
199 else
200 {
201 pname ( dname ); /* else print the directory */
202 execute( dname ); /* name and execute the cmd */
203 }
204
205 if( !(dp = mk_dir( 32 )) )
206 {
207 printf("dtree: Out of memory\n");
208 return;
209 }
210
211 dp->dirs = 1; /* Get subdirectories */
212 dp->sort = 1; /* and sort them. */
213 dp->exp = 1; /* expand subdirectories rather than */
214 /* printing their names. */
215 dp->path = 1; /* and include the full path name. */
216 dir( dname, dp );
217
218 vects = (char **) dp->dirv; /* pointer to list of subdirs */
219 count = dp->ndirs; /* number of subdirs. */
220
221 while( --count >= 0 ) /* visit the subdirs, one */
222 { /* at a time. the setbit */
223 setbit( depth, count ); /* call is used for */
224 prnt( *vects++, count ); /* printing the tree. */
225 }
226
227 if( !others ) /* If there aren't any */
228 pline( depth, 1 ); /* subdirs in the parent, */
229 /* output a blank line */
230 del_dir( dp );
231 --depth;
232 }
233
234 /* ------------------------------------------------------------------- */
235
236 char *dodot( str )
237 char *str;
238 {
239 /* If str has no dots in it, return str, else get the pathname
240 * refered to by str (ie. whatever name is indicated by
241 * . or .. or ../.. etc.) and return a pointer to that string.
242 */
243
244 static char root_name[ DSIZE ];
245 char *p;
246
247 if( !strchr( str, '.' ) )
248 return str;
249
250 if( chdir(str) || !getcwd(root_name, DSIZE) )
251 {
252 fprintf(stderr, "Can't find %s, aborting\n", str );
253 exit( 1 );
254 }
255
256 for( p = root_name; *p ; p++ ) /* Map the name from DOS */
257 { /* style to UNIX style by */
258 if( *p == '\\' ) /* mapping upper to lower */
259 *p = '/'; /* case and changing \ to */
260 else /* / */
261 *p = tolower( *p );
262 }
263
264 chdir( Startdir ); /* Restore the original */
265 return root_name ; /* working directory */
266 }
267
268 /* ------------------------------------------------------------------- */
269
270 doargs( argc, argv )
271 char **argv;
272 {
273 /* Does several things. First, it shifts all the arguments down
274 * one notch, overwriting the original argv[0]. Next, it
275 * puts a NULL into argv[argc-1], finally it processes (and
276 * removes from argv) all command line switches. Switch processing
277 * stops after a -e is encountered (but the compression continues).
278 * Argc, decremented to reflect all this stuff, is returned.
279 *
280 * We can't use getargs() in the program because -e is
281 * position dependant.
282 */
283
284 register int nargc;
285 register char **nargv;
286
287 #ifdef DEBUG
288 char **v = argv;
289 int c;
290 #endif
291
292 nargc = 0 ;
293 for( nargv = argv++; --argc > 0; argv++ )
294 {
295 if( **argv != '-' || Args )
296 {
297 *nargv++ = *argv ;
298 nargc++;
299 }
300 else
301 {
302 switch( argv[0][1] )
303 {
304 case 'e':
305 Args = nargv ;
306 *nargv++ = *++argv ;
307 nargc ++;
308 putenv("CMDLINE=") ;
309 break;
310
311 case 'f': Findfile = &argv[0][2]; break;
312 case 's': Short_pname = 1; break;
313 case 'd': Draw = 1; break;
314 default : usage();
315 }
316 }
317 }
318
319 *argv = NULL ; /* Add a NULL as the last entry */
320
321 #ifdef DEBUG
322 printf("New argv is:\n");
323
324 for( c = nargc; --c >= 0 ; v++)
325 printf("<%s> 0x%x\n", *v, *v );
326
327 printf("\nFindfile=<%s>, Short_pname=%d, Draw=%d, *Args=0x%x\n",
328 Findfile, Short_pname, Draw, *Args);
329 #endif
330
331 return nargc ;
332 }
333
334 /* ------------------------------------------------------------------- */
335
336 #define E(x) fprintf(stderr, "%s\n", x )
337 usage()
338 {
339 E( "\nUsage is: dtree root [-s] [-d] [-f<name>] [-e arg arg arg]\n");
340 E("-e Execute rest of cmd line from each directory" );
341 E("-f<name> Find file called <name>" );
342 E("-s Use short path names" );
343 E("-d Draw directory tree" );
344 E("\nEach switch must be in its own argument (-sd is illegal,");
345 E("you must say -s -d). If -f and -e are both specified, the command");
346 E("is only executed if the indicated file is found.");
347 exit(1);
348 }
349
350 wusage()
351 {
352 E( "\nUsage is: whereis <filename>\n");
353 E( "Only one file name is permitted, though wildcards are recognized");
354 E( "by whereis itself, so you must escape these from the shell as in:");
355 E( "\twhereis \"*.c\" or whereis \\*.c" );
356 exit(1);
357 }
358
359 /* ------------------------------------------------------------------- */
360
361 onintr()
362 {
363 /* Called when a ^C is encountered: */
364 chdir( Startdir ); /* Get back to starting directory */
365 exit(0); /* before exiting. */
366 }
367
368 /* ------------------------------------------------------------------- */
369
370 main( argc, argv )
371 char **argv;
372 {
373 /* If the program is invoked under the name "whereis" it
374 * treats the command line: whereis <fname>
375 * as if you had said: dtree / -f<fname>
376 */
377
378 reargv( &argc, &argv ); /* Redo arg list if running under shell */
379
380 if( !strcmp(*argv, "whereis") )
381 {
382 if( argc != 2 || argv[1][0] == '-' )
383 wusage();
384
385 Findfile = argv[1]; /* Search for a file. */
386 argc = 0; /* Force search to begin at / */
387 }
388 else
389 {
390 argc = doargs( argc, argv );
391 /* argv[0] [1] [2] ... */
392 if( Args && argc < 2 ) /* pathname cmd args ... */
393 usage();
394 }
395
396
397 Cset = isatty(fileno(stdout)) ? Graph_chars : Norm_chars ;
398
399 if( !getcwd(Startdir, DSIZE) )
400 {
401 fprintf(stderr, "Can't save current directory, aborting\n");
402 exit( 1 );
403 }
404
405 signal( SIGINT, onintr );
406 prnt( (argc < 1 || argv == Args) ? "/" : dodot(argv[0]), 0 );
407 chdir( Startdir );
408
409 exit(0);
410 }
Listing 2 -- fix.c
------------------------------------------------------------------------------
1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <types.h>
4 #include <stat.h>
5
6 extern char *strrchr();
7
8
9 #define BSIZE (10 * 1024) /* Buffer size */
10 #define CTL_Z 0x1a /* EOF marker */
11 #define SMODE (O_RDONLY | O_BINARY ) /* read & write modes */
12 #define DMODE (O_WRONLY | O_BINARY | O_TRUNC | O_CREAT )
13
14 /*----------------------------------------------------------------------*/
15
16 char *bak( name )
17 char *name;
18 {
19 /* Strips extension from name and adds .bak extension, returning */
20 /* a pointer to the modified name. The original name is untouched */
21
22 static char buf[128], *p;
23
24 strncpy( buf, name, 128-5 );
25
26 if( p = strrchr(buf, '.') )
27 strcpy( p+1, "bak" );
28 else
29 strcat( buf, ".bak" );
30
31 return buf;
32 }
33
34 /*----------------------------------------------------------------------*/
35
36 usage()
37 {
38 fprintf(stderr, "Usage: fix file [file...]\n\n");
39 fprintf(stderr, "Removes trailing ^Z's from files.\n");
40 exit( 1 );
41 }
42
43 /*----------------------------------------------------------------------*/
44
45 main(argc, argv)
46 char **argv;
47 {
48 static char buf[BSIZE];
49 static char *srcname;
50 char *p;
51 register int got; /* # bytes got from read */
52 register int src, dest; /* File handles */
53
54 ctlc(); /* Fix ^C Interrupt handling */
55 reargv( &argc, &argv ); /* Remake argv from CMDLINE */
56
57 if( argc < 2 || argv[1][0] == '-' )
58 usage();
59
60 for( ++argv, --argc; --argc >= 0; ++argv )
61 {
62 srcname = bak( *argv ); /* srcname = xxx.bak */
63 unlink( srcname ); /* delete xxx.bak */
64 rename( srcname, *argv ); /* rename xxx.yyy to xxx.bak */
65
66 printf("Fixing %-20s (creating %s)\n", *argv, srcname );
67
68 if( (src = open(srcname, SMODE)) == -1 )
69 {
70 perror( srcname );
71 continue;
72 }
73 if( (dest = open( *argv, DMODE, S_IWRITE | S_IREAD)) == -1 )
74 {
75 perror( *argv );
76 continue;
77 }
78
79 while( got = read(src, buf, BSIZE) )
80 {
81 if( got == -1 )
82 {
83 perror( srcname );
84 break;
85 }
86
87 for( p = buf; --got >= 0 && *p != CTL_Z ; p++ )
88 ;
89
90 got = p - buf ; /* got = distance to ^Z */
91
92
93 if( write(dest, buf, got) != got )
94 {
95 perror( *argv );
96 break;
97 }
98
99 if( *p == CTL_Z )
100 break;
101 }
102
103 close( src );
104 close( dest );
105 }
106
107 exit( 0 );
108 }