home *** CD-ROM | disk | FTP | other *** search
- 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 }
-