home *** CD-ROM | disk | FTP | other *** search
- Listing 6 -- skipto.c
- ------------------------------------------------------------------------------
- 1 char *skipto( c, p, esc )
- 2 register char *p ;
- 3 register int c, esc ;
- 4 {
- 5 /* Skip to c or to end of string. If c is preceeded by
- 6 * the esc character it is skipped over.
- 7 */
- 8
- 9 while( *p && *p != c )
- 10 {
- 11 if ( *p != esc )
- 12 p++ ;
- 13
- 14 else if ( *++p ) /* skip over escaped characters */
- 15 p++;
- 16 }
- 17
- 18 return(p);
- 19 }
- Listing 7 -- dir.h
- ------------------------------------------------------------------------------
- 1 /*
- 2 * DIR.H
- 3 * #defines and typedefs needed to talk to the routine dir().
- 4 * A pointer to the DIRECTORY structure is passed to dir().
- 5 * DIRECTORY structures are created by mk_dir() and deleted with
- 6 * del_dir().
- 7 *
- 8 * On entry:
- 9 * dirv is the first of an uninitialized array of character
- 10 * pointers.
- 11 * lastdir should be initialized to point at dirv.
- 12 * maxdirs is the size of the above
- 13 * nfiles
- 14 * ndirs
- 15 * nbytes is the total file count, the total directory count
- 16 * and the total byte count. These will be incremented
- 17 * as appropriate and are usually set to 0 before
- 18 * calling dir().
- 19 * width should be initialized to 0 before calling dir().
- 20 * vol_label is undefined on entry to dir().
- 21 * longf is 1 if entrys are to be printed in long format
- 22 * files is 1 if files are included in the list.
- 23 * dirs is 1 if directors are included in the list.
- 24 * graphics is 1 if directories are highlighted with boldface.
- 25 * hidden is 1 if hidden files are to be included in the list.
- 26 * path is 1 if the path name is to be included in the list.
- 27 * label is 1 if you want to get the volume label
- 28 * exp is 1 if you want the contents of a subdirectory to
- 29 * be listed rather than the directory name when. This
- 30 * is only looked at if no wild cards are present in
- 31 * the file spec.
- 32 * sort is 1 if you want the list sorted.
- 33 *
- 34 * all other fields are ignored. On exit the structure will have been
- 35 * updated as follows:
- 36 *
- 37 * lastdir will be incremented to point at the last entry added
- 38 * to the dirv table.
- 39 * maxdirs will be decremented to reflect the added entries.
- 40 * nfiles is the number of added entries which are files.
- 41 * ndirs is the number of added entries which are directories.
- 42 * Note that the equivalent of argc can be derrived by
- 43 * adding ndirs and nfiles together.
- 44 * nbytes will have the total size in bytes of all files added
- 45 * to dirv. This number is the number of bytes actually
- 46 * occupied by the file, ie. the size returned by DOS
- 47 * rounded up to the nearest multiple of the disk's
- 48 * cluster size.
- 49 * vol_label will hold the volume lable provided that "label" was
- 50 * set on entry.
- 51 * width will hold the length of the widest entry added to dirv
- 52 *
- 53 * all other fields will have the same values they had on entry.
- 54 */
- 55
- 56 typedef struct
- 57 {
- 58 char **lastdir ; /* Most recent addition to dirv */
- 59 int maxdirs ; /* # of free slots in dirv */
- 60 int nfiles ; /* # of used slots that are files */
- 61 int ndirs ; /* # of used slots that are directories */
- 62 long nbytes ; /* byte count of files */
- 63 char vol_label[12]; /* volume lable if requested */
- 64 unsigned width : 7 ; /* Width of widest element in dirv */
- 65
- 66 /* Various flags control how dir works: */
- 67 unsigned longf : 1 ; /* Use long format for entries */
- 68 unsigned files : 1 ; /* Include files in list */
- 69 unsigned dirs : 1 ; /* Include directories in list */
- 70 unsigned graphics : 1 ; /* Use graphics around directory names */
- 71 unsigned hidden : 1 ; /* List hidden files */
- 72 unsigned path : 1 ; /* List complete path if given */
- 73 unsigned label : 1 ; /* Load vol_label with volume label */
- 74 unsigned exp : 1 ; /* Expand sub-directories */
- 75 unsigned sort : 1 ; /* Sort added entries */
- 76
- 77 char dirv[1]; /* The first of the dirv entries */
- 78 }
- 79 DIRECTORY;
- Listing 8 -- dir.c
- ------------------------------------------------------------------------------
- 1 #include <stdio.h>
- 2 #include <getargs.h>
- 3 #include <mydos.h>
- 4 #include <dir.h>
- 5
- 6 /*----------------------------------------------------------------------+
- 7 * DIR.C: An MSDOS directory access function. |
- 8 * |
- 9 * (c) Copyright 1985, Allen I. Holub. All rights reserved. |
- 10 *----------------------------------------------------------------------+
- 11 * 11/22/85 Modified so that the total amount of disk space used |
- 12 * (ie. # of clusters) is put into the total, rather |
- 13 * than the file size. |
- 14 *----------------------------------------------------------------------+
- 15 */
- 16
- 17 /* ROUND(n,u): if n is an even multiple of u, evaluate to n, else
- 18 * round n up to the next even multiple of u.
- 19 */
- 20
- 21 #define ROUND(n,u) ( !((n) % (u)) ? (n) : (((n) / (u)) + 1) * (u))
- 22
- 23
- 24 #define BOLDFACE "\033[1m" /* Ansi esc sequence to turn bold face on */
- 25 #define ALL_OFF "\033[0m" /* " attributes off */
- 26
- 27 #define ATTRIBUTES (READONLY | DIRTY | SYSTEM | HIDDEN | SUBDIR)
- 28 #define iswhite(c) ((c) == ' ' || (c) == '\t')
- 29
- 30 /*----------------------------------------------------------------------*/
- 31
- 32 extern char *calloc (unsigned,unsigned); /* In standard library */
- 33 extern char *cptolower(char*,char*); /* In /src/tools/cptolow.c */
- 34 extern char *cpy (char*,char*); /* In /src/tools/cpy.c */
- 35 extern int dos (REGS *); /* In /src/tools/dos.asm */
- 36 extern void gregs (REGS *); /* In /src/tools/dos.asm */
- 37 extern char *malloc (unsigned); /* In standard library */
- 38 extern char *next (char**,int,int); /* In /src/tools/next.c */
- 39 extern void ssort (char*,int,int,int(*)());/*in /src/tools/ssort.c */
- 40 extern int strcmp (char*, char*); /* in standard library */
- 41
- 42 /*----------------------------------------------------------------------*/
- 43
- 44 static unsigned Longfmt = 0; /* True if we're using long format. This
- 45 * has to be global for the comparison
- 46 * routine used for sroting to work.
- 47 */
- 48
- 49 static unsigned Cluster_size; /* Number of bytes per cluster on
- 50 * requested disk.
- 51 */
- 52
- 53 /*----------------------------------------------------------------------*/
- 54 /* Do a DOS system call using the dos() routine */
- 55
- 56 #define DOSCALL(id,regs) { regs.h.ah = id ; dos( ®s ); }
- 57
- 58 /*----------------------------------------------------------------------*/
- 59
- 60 static int find_first( filespec, attributes, regp )
- 61 char *filespec ;
- 62 short attributes;
- 63 register REGS *regp;
- 64 {
- 65 /* Get directory information for the indicated file.
- 66 * Ambiguous file references are ok but you have to use
- 67 * find_next to get the rest of the file references.
- 68 * In this case, The regs structure used by find_first
- 69 * must be passed to find_next. 0 is returned on success,
- 70 * otherwise the DOS error code is returned.
- 71 */
- 72
- 73 regp->h.ah = (char) FINDFIRST ;
- 74 regp->x.dx = (short) filespec ;
- 75 regp->x.cx = attributes ;
- 76
- 77 return (int)( (dos(regp) & CARRY) ? regp->x.ax : 0 );
- 78 }
- 79
- 80 /*----------------------------------------------------------------------*/
- 81
- 82 static int find_next ( regp )
- 83 REGS *regp;
- 84 {
- 85 /* Get the next file in an ambiguous file reference. A
- 86 * call to this function must be preceded by a
- 87 * find_first call. The regp argument must be the
- 88 * same register image used by the find_first call.
- 89 * 0 is returned on success, otherwise the error code
- 90 * generated by DOS is returned.
- 91 */
- 92
- 93 regp->h.ah = FINDNEXT ;
- 94 return (int)( (dos(regp) & CARRY) ? regp->x.ax : 0 );
- 95 }
- 96
- 97 /*----------------------------------------------------------------------*/
- 98
- 99 int haswild(s)
- 100 register char *s;
- 101 {
- 102 /* Return true if s has a unix wild card in it. */
- 103
- 104 for( ; *s ; s++)
- 105 if( *s == '*' || *s == '?' )
- 106 return 1;
- 107 return 0;
- 108 }
- 109
- 110 /*----------------------------------------------------------------------*/
- 111
- 112 static int isrootdir( name )
- 113 register char *name;
- 114 {
- 115 /* return true if name is explicitly specifying the root
- 116 * directory (ie. is one of: d:/ d:\ / \ where
- 117 * 'd' can be any disk designator.
- 118 */
- 119
- 120 if( *name && name[1] == ':' )
- 121 name += 2;
- 122
- 123 return( (*name == '\\' || *name == '/') && !name[1] );
- 124 }
- 125
- 126 /*----------------------------------------------------------------------*/
- 127
- 128 has_only( str, inclusion_set )
- 129 register char *str;
- 130 char *inclusion_set;
- 131 {
- 132 /* Return true only if every character in str is also in
- 133 * inclusion_set. True is returned if str is empty.
- 134 */
- 135
- 136 register char *p;
- 137
- 138 for(; *str ; str++)
- 139 {
- 140 for( p = inclusion_set ; *p && *p != *str ; p++ )
- 141 ;
- 142
- 143 if( !*p )
- 144 return 0;
- 145 }
- 146
- 147 return 1;
- 148 }
- 149
- 150 /*----------------------------------------------------------------------*/
- 151
- 152 static char *fixup_name( name, regs, info )
- 153 register char *name;
- 154 REGS *regs;
- 155 FILE_INFO *info;
- 156 {
- 157 /* If the name specifies an implicit file (ie. it asks for
- 158 * the directory rather than the files in the directory),
- 159 * modify it to ask for files (eg. ".." becomes "..\*.*").
- 160 * If the name is actually modified, a pointer to a modified
- 161 * copy of the original name is returned. Otherwise the
- 162 * original buffer is returned.
- 163 */
- 164
- 165 static char buf[80] ; /* Place to put modified name */
- 166 register char *p = buf ; /* Always points into buf */
- 167 char *start_name = name; /* Remember start of name */
- 168
- 169 if( isrootdir(name) || (name[0] && name[1]==':' && !name[2]) )
- 170 {
- 171 /* Handle an explicitly requested root directory or
- 172 * the current directory on another disk.
- 173 */
- 174
- 175 sprintf(buf, "%s*.*", name );
- 176 }
- 177 else if( !find_first( name, ALL, regs) )
- 178 {
- 179 /* Look for the indicated name & see if it's a directory.
- 180 * If so, append slash-*.* to the requested name
- 181 */
- 182
- 183 if( !IS_SUBDIR(info) )
- 184 return name;
- 185 else
- 186 sprintf(buf, "%s/*.*", name );
- 187 }
- 188 else
- 189 {
- 190 /* If we get here then a non-existant file or directory
- 191 * was requested.
- 192 * If the name consists of nothing but the characters
- 193 * \ / . or a drive designator, assume that the root
- 194 * directory was requested and adjust the name
- 195 * accordingly.
- 196 */
- 197
- 198 if( *name && name[1] == ':') /* Copy drive designator if */
- 199 { /* one's present. */
- 200 *p++ = *name++ ;
- 201 *p++ = *name++ ;
- 202 }
- 203
- 204 if( has_only(name, ".\\/") )
- 205 strcpy( p, "/*.*" );
- 206 else
- 207 return( start_name );
- 208 }
- 209
- 210 return( buf );
- 211 }
- 212
- 213 /*----------------------------------------------------------------------*/
- 214
- 215 static int dirtoa( target, infop, graphics, pathname )
- 216 register char *target ;
- 217 char *pathname ;
- 218 register FILE_INFO *infop ;
- 219 unsigned graphics;
- 220 {
- 221 /* Convert directory entry held in infop to an ascii string
- 222 * in target. If Longfmt use a long format, if graphics then
- 223 * directory names are printed in bold face, else they're
- 224 * printed as "<name>." If pathname is true then the name
- 225 * will be preceeded with the full pathname.
- 226 */
- 227
- 228 char *startstr = target;
- 229 int i;
- 230
- 231 if( Longfmt )
- 232 {
- 233 *target++ = ( IS_READONLY(infop) ) ? 'r' : '.' ;
- 234 *target++ = ( IS_HIDDEN (infop) ) ? 'h' : '.' ;
- 235 *target++ = ( IS_SYSTEM (infop) ) ? 's' : '.' ;
- 236 *target++ = ( IS_SUBDIR (infop) ) ? 'd' : '.' ;
- 237 *target++ = ( IS_DIRTY (infop) ) ? 'm' : '.' ;
- 238
- 239 sprintf(target, " %6ld %2d/%02d/%02d %2d:%02d:%02d - ",
- 240 infop->fi_fsize,
- 241 C_MONTH(infop), C_DAY(infop), C_YEAR(infop)-1900,
- 242 C_HR(infop), C_MIN(infop), C_SEC(infop) );
- 243
- 244 while( *target )
- 245 target++;
- 246 }
- 247
- 248 if( IS_SUBDIR(infop) && graphics )
- 249 target = cpy( target, BOLDFACE );
- 250
- 251 target = cpy ( target, pathname );
- 252 target = cptolower( target, infop->fi_name );
- 253
- 254 if( IS_SUBDIR(infop) && graphics )
- 255 target = cpy( target, ALL_OFF );
- 256
- 257 return( target - startstr );
- 258 }
- 259
- 260 /*----------------------------------------------------------------------*/
- 261
- 262 static int add_entry( infop, dp, path )
- 263 FILE_INFO *infop ;
- 264 register DIRECTORY *dp ;
- 265 char *path ;
- 266 {
- 267 /* Add an entry to the DIRECTORY structure. Return 0 if
- 268 * it was added, one if it wasn't.
- 269 */
- 270
- 271 char buf[128] ;
- 272 register int len ;
- 273
- 274 /*
- 275 * If we're not printing hidden directories but the current
- 276 * directory is nonetheless hidden, return immediately.
- 277 * Similarly, return if the directory is full.
- 278 */
- 279
- 280 if( !dp->hidden && (IS_HIDDEN(infop) || *infop->fi_name == '.') )
- 281 return 1;
- 282
- 283 if( dp->maxdirs <= 0 ) /* No more room in dirv. return */
- 284 return 0; /* error status */
- 285
- 286 /*
- 287 * Update the directory count or the file count as appropriate
- 288 * return immeadialy if we're looking at a file and we aren't
- 289 * supposed to list file. The same with directories.
- 290 */
- 291
- 292 if( IS_SUBDIR(infop) )
- 293 {
- 294 if( dp->dirs )
- 295 dp->ndirs++ ;
- 296 else
- 297 return 1;
- 298 }
- 299 else
- 300 {
- 301 if( dp->files )
- 302 dp->nfiles++ ;
- 303 else
- 304 return 1;
- 305 }
- 306
- 307 /*
- 308 * Convert the FILE_INFO structure to an ascii string and put
- 309 * it into buf. Then malloc a chunk of memory the correct size,
- 310 * copy the ascii string there, and put the malloced memory
- 311 * into dirv at the correct place.
- 312 */
- 313
- 314 Longfmt = dp->longf;
- 315
- 316 len = dirtoa( buf, infop, dp->graphics, path );
- 317
- 318 if( len > dp->width )
- 319 dp->width = len ;
- 320
- 321 if( *dp->lastdir = malloc(len + 1) )
- 322 {
- 323 strcpy( *dp->lastdir++, buf ) ;
- 324
- 325 /* Add file size to total. Note that the actual amount
- 326 * of space (# of clusters) used by the file on the
- 327 * disk is used.
- 328 */
- 329
- 330 dp->nbytes += ROUND( infop->fi_fsize, Cluster_size );
- 331
- 332 --dp->maxdirs;
- 333 return 1;
- 334 }
- 335
- 336 fprintf(stderr,"Can't get memory for directory\n");
- 337 return 0;
- 338 }
- 339
- 340 /*----------------------------------------------------------------------*/
- 341
- 342
- 343 static void copy_path( dest, src )
- 344 char *dest, *src;
- 345 {
- 346 /* Copy only the pathname part of the file spec contained in
- 347 * src to dest. Path names longer than 64 characters are
- 348 * truncated so dest must be at least 64 characters long.
- 349 */
- 350
- 351 register char *p, *slash;
- 352
- 353 for( p = slash = src ; *p ; p++ )
- 354 if( *p == '/' || *p == '\\' || *p == ':' )
- 355 slash = p + 1;
- 356
- 357 for(p = src; p < slash && p - src < 64 ; *dest++ = *p++ )
- 358 ;
- 359
- 360 *dest = 0;
- 361 }
- 362
- 363 /*----------------------------------------------------------------------*/
- 364
- 365 static void clab( dest, src )
- 366 register char *dest, *src;
- 367 {
- 368 for(; *src ; src++, dest++ )
- 369 if( *src != '.')
- 370 *dest = *src ;
- 371 }
- 372
- 373 /*----------------------------------------------------------------------*/
- 374
- 375 static int cmp( pp1, pp2 )
- 376 char **pp1, **pp2;
- 377 {
- 378 /* Comparison routine needed for ssort() */
- 379
- 380 register char *p1 = *pp1;
- 381 register char *p2 = *pp2;
- 382
- 383 if( Longfmt )
- 384 {
- 385 /* Skip forward to the '-' that will preceede
- 386 * the filename.
- 387 */
- 388
- 389 while( *p1 && *p1 != '-' )
- 390 p1++;
- 391
- 392 while( *p2 && *p2 != '-' )
- 393 p2++;
- 394 }
- 395
- 396 return( strcmp(p1, p2) );
- 397 }
- 398
- 399 /*----------------------------------------------------------------------*/
- 400
- 401 DIRECTORY *mk_dir( size )
- 402 register unsigned size;
- 403 {
- 404 /* Make a DIRECTORY with the indicated number of dirv entries.
- 405 * Note that since one dirv entry is declared as part of the
- 406 * DIRECTORY header, we'll actually have size+1 entries
- 407 * available, though the last one is never used. We allocate
- 408 * it so that we can terminate the list with a null
- 409 * entry, even if the list is full.
- 410 */
- 411
- 412 register DIRECTORY *dp;
- 413
- 414
- 415
- 416
- 417 if( !( dp = (DIRECTORY *)calloc( (unsigned)1,
- 418 sizeof(DIRECTORY) + (size * sizeof(char *))) ))
- 419 return 0;
- 420
- 421 dp->maxdirs = size ;
- 422 dp->lastdir = (char **) dp->dirv;
- 423 return dp;
- 424 }
- 425
- 426 /*----------------------------------------------------------------------*/
- 427
- 428 del_dir( dp )
- 429 register DIRECTORY *dp;
- 430 {
- 431 /* Delete a directory made with a previous mk_dir call.
- 432 * Note that all the strings pointed to by dirv entries
- 433 * are assumed to have been gotten from malloc (this is
- 434 * always true if dir() is used to fill the strings.
- 435 */
- 436
- 437 register char **v;
- 438
- 439 for( v = (char **) dp->dirv; v < dp->lastdir ; free( *v++ ) )
- 440 ;
- 441
- 442 free( dp );
- 443 }
- 444
- 445 /*----------------------------------------------------------------------*/
- 446
- 447 dir( spec, dp )
- 448 char *spec;
- 449 DIRECTORY *dp;
- 450 {
- 451 /* Get a directory for the indicated spec. DOS wildcards are
- 452 * permitted. If the DIRECTORY pointed to by dp already has
- 453 * entries in it, new ones will be appended onto the existing
- 454 * ones. If *spec is null, no files will be gotten, this is
- 455 * useful if all you want is the volume label.
- 456 *
- 457 * Note that the DTA is not modified by this routine. It
- 458 * sets the DTA to its own address, but then restores the
- 459 * DTA before returning.
- 460 */
- 461
- 462 REGS regs ; /* Needed for DOS calls */
- 463 FILE_INFO info ; /* DOS puts dirs here */
- 464 char path[80] ; /* place to put path */
- 465 char **firstdir; /* Used for sorting */
- 466 short seg,off ; /* Segment and offset of */
- 467 /* original DTA */
- 468 unsigned sec_per_cluster, /* Used to compute number of */
- 469 bytes_per_sector, /* bytes in a cluster */
- 470 garbage;
- 471
- 472 gregs( ®s ); /* Get the original DTA */
- 473 DOSCALL( GETDTA, regs );
- 474
- 475 seg = regs.x.es ; /* remember it in set:off */
- 476 off = regs.x.bx ;
- 477
- 478 regs.x.dx = (word) &info; /* Change the Disk Transfer Addr */
- 479 DOSCALL( SETDTA, regs ); /* to point at info structure */
- 480
- 481
- 482 /* Find the number of bytes/cluster on the indicated
- 483 * disk drive (or on the current drive if none is
- 484 * specified.
- 485 */
- 486
- 487 if( !diskinfo( (!*spec||spec[1]!=':') ? 0 : (toupper(*spec)-'A')+1,
- 488 &sec_per_cluster, &bytes_per_sector, &garbage, &garbage))
- 489 fprintf(stderr,"dir: Can't access indicated disk\n");
- 490
- 491 Cluster_size = sec_per_cluster * bytes_per_sector ;
- 492
- 493
- 494 /* If a volume label is requested, get it and copy it into
- 495 * dp->vol_lab. Any imbedded '.'s are stripped by clab.
- 496 * If no volume label is present, the string is nulled.
- 497 */
- 498
- 499 if( dp->label )
- 500 {
- 501 *dp->vol_label = 0;
- 502
- 503 if( spec[1] != ':' )
- 504 strcpy( path, "/*.*" );
- 505 else
- 506 {
- 507 *path = *spec ;
- 508 strcpy( path+1, ":/*.*" );
- 509 }
- 510
- 511 if( !find_first(path, LABEL, ®s) )
- 512 clab( dp->vol_label, info.fi_name );
- 513 }
- 514
- 515 /*
- 516 * Now get the directories:
- 517 */
- 518
- 519 if( dp->exp && !haswild(spec) )
- 520 spec = fixup_name( spec, ®s, &info );
- 521
- 522 copy_path( path, dp->path ? spec : "" );
- 523
- 524 firstdir = dp->lastdir;
- 525
- 526 /* Now go look for the file:
- 527 */
- 528
- 529 if( !find_first(spec, ATTRIBUTES, ®s) )
- 530 if( !add_entry(&info, dp, path) )
- 531 goto abort;
- 532
- 533 if( haswild(spec) )
- 534 while( !find_next( ®s ) )
- 535 if( !add_entry(&info, dp, path) )
- 536 goto abort;
- 537
- 538 if( dp->sort )
- 539 ssort( (char *)firstdir, dp->lastdir - firstdir,
- 540 sizeof(char*), cmp);
- 541
- 542 abort:
- 543 regs.x.ds = seg ; /* Restore the original disk */
- 544 regs.x.dx = off ; /* transfer address. */
- 545 DOSCALL( SETDTA, regs );
- 546 }
- Listing 9 -- reargv.c
- ------------------------------------------------------------------------------
- 1 #include <stdio.h>
- 2 #include <ctype.h>
- 3
- 4 #define MAXARGC (unsigned)128
- 5 #define isquote(c) ((c)=='"' || (c)=='\'')
- 6
- 7 extern char *getenv( char* );
- 8 extern char *malloc( unsigned );
- 9
- 10 /*----------------------------------------------------------------------*/
- 11
- 12 static char *nextarg( pp )
- 13 char **pp;
- 14 {
- 15 register char *p;
- 16 char *start;
- 17 register int term;
- 18
- 19 if( !*(p = *pp) )
- 20 return (char *) 0;
- 21
- 22 while( isspace(*p) )
- 23 p++;
- 24
- 25 if( isquote(*p) ) /* Can't use a conditional because */
- 26 term = *p++; /* of order of evaluation problems */
- 27 else
- 28 term = ' ';
- 29
- 30 for( start = p; *p ; p++)
- 31 {
- 32 if( *p == term && *(p-1) != '\\' )
- 33 {
- 34 *p++ = '\0';
- 35 break;
- 36 }
- 37 }
- 38
- 39 *pp = p;
- 40
- 41 return start;
- 42 }
- 43
- 44 /*----------------------------------------------------------------------*/
- 45
- 46 int reargv( argcp, argvp )
- 47 char ***argvp;
- 48 int *argcp;
- 49 {
- 50 register int argc = 0 ;
- 51 register int maxc = MAXARGC ;
- 52 char **argv, **start_argv ;
- 53 char *env, *p ;
- 54
- 55 if( !(env = getenv("CMDLINE")) || !*env )
- 56 return 0;
- 57
- 58 if( !(p = malloc( strlen(env)+1 )))
- 59 return 0;
- 60
- 61 if( !(argv = (char **) malloc( MAXARGC * sizeof(char *)) ))
- 62 return 0;
- 63
- 64 strcpy(p, env);
- 65 start_argv = argv;
- 66 for( maxc=MAXARGC; --maxc >= 0 && (*argv++ = nextarg(&p)); argc++)
- 67 ;
- 68
- 69 if( maxc < 0 )
- 70 fprintf(stderr, "Command line truncated\n");
- 71
- 72 *argcp = argc;
- 73 *argvp = start_argv;
- 74 return 1;
- 75 }
- 76
- 77 /*----------------------------------------------------------------------*/
- 78
- 79 #ifdef DEBUG
- 80
- 81 main( argc, argv )
- 82 char **argv;
- 83 {
- 84 printf("Original command line is: |");
- 85 while( --argc >= 0 )
- 86 printf("%s|", *argv++ );
- 87
- 88 if( !reargv( &argc, &argv ) )
- 89 printf("\nCMDLINE not present\n");
- 90 else
- 91 {
- 92 printf("New argc = %d\n", argc );
- 93 printf("\nModified command line is: |");
- 94
- 95 while( --argc >= 0 )
- 96 printf("%s|", *argv++ );
- 97
- 98 printf("\n");
- 99 }
- 100 }
- 101
- 102 #endif
- Listing 10 -- ssort.c
- ------------------------------------------------------------------------------
-
- 1 /* SSORT.C Works just like qsort() except that a shell
- 2 * sort, rather than a quick sort, is used. This
- 3 * is more efficient than quicksort for small numbers of elements
- 4 * and it's not recursive so will use much less stack space.
- 5 *
- 6 * Copyright (C) 1985, Allen I. Holub. All rights reserved
- 7 */
- 8
- 9 void ssort( base, nel, width, cmp )
- 10 char *base;
- 11 int nel, width;
- 12 int (*cmp)();
- 13 {
- 14 register int i, j;
- 15 int gap, k, tmp ;
- 16 char *p1, *p2;
- 17
- 18 for( gap = nel >>1 ; gap > 0 ; gap >>=1 )
- 19 for( i = gap; i < nel; i++ )
- 20 for( j = i-gap; j >= 0 ; j -= gap )
- 21 {
- 22 p1 = base + ( j * width);
- 23 p2 = base + ((j+gap) * width);
- 24
- 25 if( (*cmp)( p1, p2 ) <= 0 )
- 26 break;
- 27
- 28 for( k = width; --k >= 0 ;)
- 29 {
- 30 tmp = *p1;
- 31 *p1++ = *p2;
- 32 *p2++ = tmp;
- 33 }
- 34 }
- 35 }