©2004 by Marc J. Rochkind. All rights reserved. Portions marked "Open Source" may be copied under license.

 

Main Page   Modules   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

c3/aupls.c

Go to the documentation of this file.
00001 /*
00002     ls command
00003     AUP2, Sec. 3.5, 3.6.5
00004 
00005     Copyright 2003 by Marc J. Rochkind. All rights reserved.
00006     May be copied only for purposes and under conditions described
00007     on the Web page www.basepath.com/aup/copyright.htm.
00008 
00009     The Example Files are provided "as is," without any warranty;
00010     without even the implied warranty of merchantability or fitness
00011     for a particular purpose. The author and his publisher are not
00012     responsible for any damages, direct or incidental, resulting
00013     from the use or non-use of these Example Files.
00014 
00015     The Example Files may contain defects, and some contain deliberate
00016     coding mistakes that were included for educational reasons.
00017     You are responsible for determining if and how the Example Files
00018     are to be used.
00019 
00020 */
00021 #define WANT_LSDIR_FIXEDx
00022 #define AUPLS_FULL
00023 
00024 #include "defs.h"
00025 #include <dirent.h>
00026 #include <pwd.h>
00027 #include <grp.h>
00028 /*[aupls-top1]*/
00029 #define USAGE "Usage: aupls [-Rd] [dir]\n"
00030 
00031 static long total_entries = 0, total_dirs = 0;
00032 /*[aupls-top2]*/
00033 typedef enum {SHOW_PATH, SHOW_INFO} SHOW_OP;
00034 
00035 struct traverse_info {
00036     bool ti_recursive;                               /* -R option? */
00037     char *ti_name;                                   /* current entry */
00038     struct stat ti_stat;                             /* stat for ti_name */
00039     bool (*ti_fcn)(struct traverse_info *, SHOW_OP); /* callback fcn */
00040 };
00041 /*[print_mode]*/
00042 #define TYPE(b) ((statp->st_mode & (S_IFMT)) == (b))
00043 #define MODE(b) ((statp->st_mode & (b)) == (b))
00044 
00045 static void print_mode(const struct stat *statp)
00046 {
00047     if (TYPE(S_IFBLK))
00048         putchar('b');
00049     else if (TYPE(S_IFCHR))
00050         putchar('c');
00051     else if (TYPE(S_IFDIR))
00052         putchar('d');
00053     else if (TYPE(S_IFIFO)) /* sic */
00054         putchar('p');
00055     else if (TYPE(S_IFREG))
00056         putchar('-');
00057     else if (TYPE(S_IFLNK))
00058         putchar('l');
00059     else if (TYPE(S_IFSOCK))
00060         putchar('s');
00061     else
00062         putchar('?');
00063     putchar(MODE(S_IRUSR) ? 'r' : '-');
00064     putchar(MODE(S_IWUSR) ? 'w' : '-');
00065     if (MODE(S_ISUID)) {
00066         if (MODE(S_IXUSR))
00067             putchar('s');
00068         else
00069             putchar('S');
00070     }
00071     else if (MODE(S_IXUSR))
00072         putchar('x');
00073     else
00074         putchar('-');
00075     putchar(MODE(S_IRGRP) ? 'r' : '-');
00076     putchar(MODE(S_IWGRP) ? 'w' : '-');
00077     if (MODE(S_ISGID)) {
00078         if (MODE(S_IXGRP))
00079             putchar('s');
00080         else
00081             putchar('S');
00082     }
00083     else if (MODE(S_IXGRP))
00084         putchar('x');
00085     else
00086         putchar('-');
00087     putchar(MODE(S_IROTH) ? 'r' : '-');
00088     putchar(MODE(S_IWOTH) ? 'w' : '-');
00089     if (MODE(S_IFDIR) && MODE(S_ISVTX)) {
00090         if (MODE(S_IXOTH))
00091             putchar('t');
00092         else
00093             putchar('T');
00094     }
00095     else if (MODE(S_IXOTH))
00096         putchar('x');
00097     else
00098         putchar('-');
00099 }
00100 /*[]*/
00101 
00102 #undef TYPE
00103 #undef MODE
00104 
00105 /*[print_numlinks]*/
00106 static void print_numlinks(const struct stat *statp)
00107 {
00108     printf("%5ld", (long)statp->st_nlink);
00109 }
00110 /*[print_owner]*/
00111 static void print_owner(const struct stat *statp)
00112 {
00113     struct passwd *pwd = getpwuid(statp->st_uid);
00114 
00115     if (pwd == NULL)
00116         printf(" %-8ld", (long)statp->st_uid);
00117     else
00118         printf(" %-8s", pwd->pw_name);
00119 }
00120 /*[print_group]*/
00121 static void print_group(const struct stat *statp)
00122 {
00123     struct group *grp = getgrgid(statp->st_gid);
00124 
00125     if (grp == NULL)
00126         printf(" %-8ld", (long)statp->st_gid);
00127     else
00128         printf(" %-8s", grp->gr_name);
00129 }
00130 /*[print_size]*/
00131 static void print_size(const struct stat *statp)
00132 {
00133     switch (statp->st_mode & S_IFMT) {
00134     case S_IFCHR:
00135     case S_IFBLK:
00136         printf("%4u,%4u", (unsigned)(statp->st_rdev >> 8),
00137           (unsigned)(statp->st_rdev & 0xFF));
00138         break;
00139     default:
00140         printf("%9lu", (unsigned long)statp->st_size);
00141     }
00142 }
00143 /*[print_date]*/
00144 static void print_date(const struct stat *statp)
00145 {
00146     time_t now;
00147     double diff;
00148     char buf[100], *fmt;
00149 
00150     if (time(&now) == -1) {
00151         printf(" ????????????");
00152         return;
00153     }
00154     diff = difftime(now, statp->st_mtime);
00155     if (diff < 0 || diff > 60 * 60 * 24 * 182.5) /* roughly 6 months */
00156         fmt = "%b %e  %Y";
00157     else
00158         fmt = "%b %e %H:%M";
00159     strftime(buf, sizeof(buf), fmt, localtime(&statp->st_mtime));
00160     printf(" %s", buf);
00161 }
00162 /*
00163     In code below, the "not supposed to happen" test modified to include EINVAL, which Darwin
00164     returned for paths like /dev and /dev/fd.
00165 */
00166 /*[get_max_pathname]*/
00167 static long get_max_pathname(const char *path)
00168 {
00169     long max_path;
00170 
00171     errno = 0;
00172     max_path = pathconf(path, _PC_PATH_MAX);
00173     if (max_path == -1) {
00174         if (errno == 0 || errno == EINVAL) /* not supposed to happen */
00175             max_path = 4096;
00176         else
00177             EC_FAIL
00178     }
00179     return max_path + 1;
00180 
00181 EC_CLEANUP_BGN
00182     return -1;
00183 EC_CLEANUP_END
00184 }
00185 /*[]*/
00186 /*[print_name]*/
00187 static void print_name(const struct stat *statp, const char *name)
00188 {
00189     if (S_ISLNK(statp->st_mode)) {
00190         char *contents = malloc(statp->st_size + 1);
00191         ssize_t n;
00192 
00193         if (contents != NULL && (n = readlink(name, contents,
00194           statp->st_size)) != -1) {
00195             contents[n] = '\0'; /* can't assume NUL-terminated */
00196             printf(" %s -> %s", name, contents);
00197         }
00198         else
00199             printf(" %s -> [can't read link]", name);
00200         free(contents);
00201     }
00202     else
00203         printf(" %s", name);
00204 }
00205 /*[ls_long-a]*/
00206 static void ls_long(const struct stat *statp, const char *name)
00207 {
00208     print_mode(statp);
00209     print_numlinks(statp);
00210     print_owner(statp);
00211     print_group(statp);
00212     print_size(statp);
00213     print_date(statp);
00214     print_name(statp, name);
00215     putchar('\n');
00216 }
00217 /*[]*/
00218 #ifdef WANT_LSLONG
00219 /*[ls_long-b]*/
00220 int main(int argc, char *argv[])
00221 {
00222     int i;
00223     struct stat statbuf;
00224 
00225     for (i = 1; i < argc; i++) {
00226         ec_neg1( lstat(argv[i], &statbuf) )
00227         ls_long(&statbuf, argv[i]);
00228     }
00229     exit(EXIT_SUCCESS);
00230 
00231 EC_CLEANUP_BGN
00232     exit(EXIT_FAILURE);
00233 EC_CLEANUP_END
00234 }
00235 /*[]*/
00236 #endif
00237 /*[get_cwd]*/
00238 static char *get_cwd(bool cleanup)
00239 {
00240     static char *cwd = NULL;
00241     static long max_path;
00242 
00243     if (cleanup) {
00244         free(cwd);
00245         cwd = NULL;
00246     }
00247     else {
00248         if (cwd == NULL) {
00249             ec_neg1( max_path = get_max_pathname(".") )
00250             ec_null( cwd = malloc((size_t)max_path) )
00251         }
00252         ec_null( getcwd(cwd, max_path) )
00253         return cwd;
00254     }
00255     return NULL;
00256 
00257 EC_CLEANUP_BGN
00258     return NULL;
00259 EC_CLEANUP_END
00260 }
00261 /*[aupls-print_cwd]*/
00262 static bool print_cwd(bool cleanup)
00263 {
00264     char *cwd;
00265 
00266     if (cleanup)
00267         (void)get_cwd(true);
00268     else {
00269         ec_null( cwd = get_cwd(false) )
00270         printf("\n%s:\n", cwd);
00271     }
00272     return true;
00273 
00274 EC_CLEANUP_BGN
00275     return false;
00276 EC_CLEANUP_END
00277 }
00278 /*[aupls-show_stat]*/
00279 static bool show_stat(struct traverse_info *p, SHOW_OP op)
00280 {
00281     switch (op) {
00282     case SHOW_PATH:
00283         ec_false( print_cwd(false) )
00284         break;
00285     case SHOW_INFO:
00286         ls_long(&p->ti_stat, p->ti_name);
00287     }
00288     return true;
00289 
00290 EC_CLEANUP_BGN
00291     return false;
00292 EC_CLEANUP_END
00293 }
00294 /*[aupls-check_parent]*/
00295 static bool check_parent(int dirfd, const char *name)
00296 {
00297     struct stat statbuf1, statbuf2;
00298 
00299     if (name[0] != '/') {
00300         ec_neg1( fstat(dirfd, &statbuf1) )
00301         ec_neg1( lstat("..", &statbuf2) )
00302         if (statbuf1.st_dev != statbuf2.st_dev ||
00303           statbuf1.st_ino != statbuf2.st_ino) {
00304             print_cwd(false);
00305             fprintf(stderr, "Doubly-linked directory encountered (%s).\n",
00306               name);
00307             errno = 0;
00308             EC_FAIL
00309         }
00310     }
00311     return true;
00312 
00313 EC_CLEANUP_BGN
00314     return false;
00315 EC_CLEANUP_END
00316 }
00317 /*[]*/
00318 
00319 static bool do_entry(struct traverse_info *p, bool stat_only);
00320 
00321 /*[aupls-do_dir1]*/
00322 static bool do_dir(struct traverse_info *p)
00323 {
00324     DIR *sp = NULL;
00325     struct dirent *dp;
00326     int dirfd = -1;
00327     bool result = false;
00328 
00329     /*
00330         Entry could be changed from directory to symlink between
00331         lstat() and here, in which case opendir would follow it,
00332         possibly resulting in double-visiting or even a loop.
00333     */
00334     ec_neg1(  dirfd = open(".", O_RDONLY) )
00335     /*
00336         [Not in book.]
00337         On Darwin, fails on directory /dev/fd. Problem is that it thinks that some of
00338         the file descriptors there are directories, and opendir fails on them with a bus
00339         error. Skipping the entire /dev directory is a good idea. The shortcut is to skip
00340         directories whose name is "dev", which isn't really correct, because they may not
00341         be at the root. Fix is left to the reader...
00342     */
00343     if (strcmp(p->ti_name, "dev") == 0 || strncmp(p->ti_name, "/dev", 4) == 0) {
00344         printf("Skipping directory \"dev\" (even if it's not /dev).\n");
00345         result = true;
00346         EC_CLEANUP
00347     }
00348     /* [End of stuff not in book.] */
00349     if ((sp = opendir(p->ti_name)) == NULL || chdir(p->ti_name) == -1) {
00350         if (errno == EACCES) {
00351             fprintf(stderr, "%s: Permission denied.\n", p->ti_name);
00352             result = true;
00353             EC_CLEANUP
00354         }
00355         /* Book showed just EC_FAIL here. Change so we can keep going. */
00356         else {
00357             syserr_print("do_dir()");
00358             result = true; /* repeat of above, but want to keep book's logic */
00359             EC_CLEANUP
00360         }
00361         /* EC_FAIL -- don't want this line anymore */
00362     }
00363 /*[]*/
00364     /*
00365         Following is a good idea, but left out of book for space reasons.
00366     */
00367     if (strcmp(p->ti_name, ".") != 0)
00368         ec_false( check_parent(dirfd, p->ti_name) )
00369 /*[aupls-do_dir2]*/
00370     if (p->ti_recursive)
00371         ec_false( (p->ti_fcn)(p, SHOW_PATH) )
00372     while (errno = 0, ((dp = readdir(sp)) != NULL)) {
00373         if (strcmp(dp->d_name, ".") == 0 ||
00374           strcmp(dp->d_name, "..") == 0)
00375             continue;
00376         p->ti_name = dp->d_name;
00377         ec_false( do_entry(p, true) )
00378     }
00379     if (errno != 0)
00380         syserr_print("Reading directory (Pass 1)");
00381     if (p->ti_recursive) {
00382         rewinddir(sp);
00383         while (errno = 0, ((dp = readdir(sp)) != NULL)) {
00384             if (strcmp(dp->d_name, ".") == 0 ||
00385               strcmp(dp->d_name, "..") == 0)
00386                 continue;
00387             p->ti_name = dp->d_name;
00388             ec_false( do_entry(p, false) )
00389         }
00390         if (errno != 0)
00391             syserr_print("Reading directory (Pass 2)");
00392     }
00393     result = true;
00394     EC_CLEANUP
00395 
00396 EC_CLEANUP_BGN
00397     if (dirfd != -1) {
00398         (void)fchdir(dirfd);
00399         (void)close(dirfd);
00400     }
00401     if (sp != NULL)
00402         (void)closedir(sp);
00403     return result;
00404 EC_CLEANUP_END
00405 }
00406 /*[aupls-do_entry]*/
00407 static bool do_entry(struct traverse_info *p, bool stat_only)
00408 {
00409     bool is_dir;
00410 
00411     ec_neg1( lstat(p->ti_name, &p->ti_stat) )
00412     is_dir = S_ISDIR(p->ti_stat.st_mode);
00413     if (stat_only/* || !is_dir*/) { /* Bug fix: 24-March-2004 */
00414         total_entries++;
00415         if (is_dir)
00416             total_dirs++;
00417         ec_false( (p->ti_fcn)(p, SHOW_INFO) )
00418     }
00419     else if (is_dir)
00420         ec_false( do_dir(p) )
00421     return true;
00422 
00423 EC_CLEANUP_BGN
00424     return false;
00425 EC_CLEANUP_END
00426 }
00427 /*[]*/
00428 #ifdef WANT_LSDIR_BUGGY
00429 /*[ls_dir]*/
00430 int main(int argc, char *argv[]) /* has a bug */
00431 {
00432     bool ok = false;
00433     int i;
00434     DIR *dir = NULL;
00435     struct dirent *entry;
00436     struct stat statbuf;
00437 
00438     for (i = 1; i < argc; i++) {
00439         ec_neg1( lstat(argv[i], &statbuf) )
00440         if (!S_ISDIR(statbuf.st_mode)) {
00441             ls_long(&statbuf, argv[i]);
00442             ok = true;
00443             EC_CLEANUP
00444         }
00445         ec_null( dir = opendir(argv[i]) )
00446         while (errno = 0, ((entry = readdir(dir)) != NULL)) {
00447             ec_neg1( lstat(entry->d_name, &statbuf) )
00448             ls_long(&statbuf, entry->d_name);
00449         }
00450         ec_nzero( errno )
00451     }
00452     ok = true;
00453     EC_CLEANUP
00454 
00455 EC_CLEANUP_BGN
00456     if (dir != NULL)
00457         (void)closedir(dir);
00458     exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
00459 EC_CLEANUP_END
00460 }
00461 /*[]*/
00462 #endif /* WANT_LSDIR_BUGGY */
00463 #ifdef WANT_LSDIR_FIXED
00464 int main(int argc, char *argv[])
00465 {
00466     bool ok = false;
00467     int i, fd;
00468     DIR *dir = NULL;
00469     struct dirent *entry;
00470     struct stat statbuf;
00471 
00472     for (i = 1; i < argc; i++) {
00473         ec_neg1( lstat(argv[i], &statbuf) )
00474         if (!S_ISDIR(statbuf.st_mode)) {
00475             ls_long(&statbuf, argv[i]);
00476             ok = true;
00477             EC_CLEANUP
00478         }
00479 /*[ls_dir_fixed]*/
00480         ec_null( dir = opendir(argv[i]) )
00481         ec_neg1( fd = open(".", O_RDONLY) )
00482         ec_neg1( chdir(argv[i]) )
00483         while (errno = 0, ((entry = readdir(dir)) != NULL)) {
00484             ec_neg1( lstat(entry->d_name, &statbuf) )
00485             ls_long(&statbuf, entry->d_name);
00486         }
00487         ec_nzero( errno )
00488         ec_neg1( fchdir(fd) )
00489 /*[]*/
00490     }
00491     ok = true;
00492     EC_CLEANUP
00493 
00494 EC_CLEANUP_BGN
00495     if (dir != NULL)
00496         (void)closedir(dir);
00497     exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
00498 EC_CLEANUP_END
00499 }
00500 #endif /* WANT_LSDIR_FIXED */
00501 #ifdef WANT_LSDIR_ALTERNATIVE
00502 int main(int argc, char *argv[])
00503 {
00504     bool ok = false;
00505     int i, fd, lstat_result, errno_save;
00506     DIR *dir = NULL;
00507     struct dirent *entry;
00508     struct stat statbuf;
00509 
00510     for (i = 1; i < argc; i++) {
00511         ec_neg1( lstat(argv[i], &statbuf) )
00512         if (!S_ISDIR(statbuf.st_mode)) {
00513             ls_long(&statbuf, argv[i]);
00514             ok = true;
00515             EC_CLEANUP
00516         }
00517 /*[ls_dir_fixed2]*/
00518         ec_null( dir = opendir(argv[i]) )
00519         ec_neg1( fd = open(".", O_RDONLY) )
00520         ec_neg1( chdir(argv[i]) ) /* no jumps allowed until fchdir! */
00521         while (errno = 0, ((entry = readdir(dir)) != NULL)) {
00522             if ((lstat_result = lstat(entry->d_name, &statbuf)) == -1)
00523                 break;
00524             ls_long(&statbuf, entry->d_name);
00525         }
00526         errno_save = errno;
00527         ec_neg1( fchdir(fd) )
00528         errno = errno_save;
00529         ec_neg1( lstat_result )
00530         ec_nzero( errno )
00531 /*[]*/
00532     }
00533     ok = true;
00534     EC_CLEANUP
00535 
00536 EC_CLEANUP_BGN
00537     if (dir != NULL)
00538         (void)closedir(dir);
00539     exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
00540 EC_CLEANUP_END
00541 }
00542 #endif /* WANT_LSDIR_ALTERNATIVE */
00543 
00544 static bool ls_one(const char *name)
00545 {
00546     struct stat statbuf;
00547 
00548     ec_neg1( lstat(name, &statbuf) )
00549     ls_long(&statbuf, name);
00550     return true;
00551 
00552 EC_CLEANUP_BGN
00553     return false;
00554 EC_CLEANUP_END
00555 }
00556 
00557 static char *big_cwd = NULL;
00558 static char big_name[FILENAME_MAX + 1];
00559 static off_t big_size = 0;
00560 
00561 static bool biggest(struct traverse_info *p, SHOW_OP op)
00562 {
00563     char *cwd;
00564 
00565     if (p->ti_stat.st_size > big_size && S_ISREG(p->ti_stat.st_mode)) {
00566         ec_null( cwd = get_cwd(false) )
00567         free(big_cwd);
00568         ec_null( big_cwd = malloc(strlen(cwd) + 1) )
00569         strcpy(big_cwd, cwd);
00570         strncpy(big_name, p->ti_name, sizeof(big_name));
00571         big_name[sizeof(big_name) - 1] = '\0';
00572         big_size = p->ti_stat.st_size;
00573     }
00574     return true;
00575 
00576 EC_CLEANUP_BGN
00577     return false;
00578 EC_CLEANUP_END
00579 }
00580 
00581 static void biggest_file(void)
00582 {
00583     struct traverse_info ti = {0};
00584 
00585     ti.ti_fcn = biggest;
00586     ti.ti_recursive = true;
00587     ti.ti_name = "/";
00588     ec_false( do_entry(&ti, false) )
00589     printf("Biggest file:\n%s\n%s\n%lu\n", big_cwd, big_name,
00590       (unsigned long)big_size);
00591     return;
00592 
00593 EC_CLEANUP_BGN
00594     EC_FLUSH("biggest_file");
00595 EC_CLEANUP_END
00596 }
00597 
00598 static bool runtest(char testtype, const char *name)
00599 {
00600     struct stat statbuf;
00601 
00602     ec_neg1( lstat(name, &statbuf) )
00603     switch (testtype) {
00604     case 'a':
00605         printf("get_max_pathname = %ld\n", get_max_pathname("."));
00606         printf("get_max_pathname = %ld\n", get_max_pathname("/aup"));
00607         /* Following line failed on DARWIN */
00608         printf("get_max_pathname = %ld\n", get_max_pathname("/dev/fd"));
00609         break;
00610     case 'b':
00611         biggest_file();
00612         break;
00613     case 'y':
00614         ec_false( ls_one(name) )
00615         break;
00616     case 'c':
00617     {
00618 /*[test_get_cwd]*/
00619 char *cwd;
00620 
00621 ec_null( cwd = get_cwd(false) )
00622 printf("%s\n", cwd);
00623 (void) get_cwd(true);
00624 /*[]*/
00625 ec_null( cwd = get_cwd(false) )
00626 printf("%s\n", cwd);
00627 (void) get_cwd(true);
00628 ec_null( cwd = get_cwd(false) )
00629 printf("%s\n", cwd);
00630 (void) get_cwd(true);
00631 ec_null( cwd = get_cwd(false) )
00632 printf("%s\n", cwd);
00633 (void) get_cwd(true);
00634     }
00635         break;
00636     case 'M':
00637 {
00638 /*[test_print_mode]*/
00639 struct stat statbuf;
00640 
00641 ec_neg1( lstat("fifo", &statbuf) )
00642 print_mode(&statbuf);
00643 putchar('\n');
00644 ec_neg1( system("ls -l fifo") )
00645 /*[]*/
00646 }
00647         break;
00648     case 'm':
00649         print_mode(&statbuf);
00650         break;
00651     case 'l':
00652         print_numlinks(&statbuf);
00653         break;
00654     case 'o':
00655         print_owner(&statbuf);
00656         break;
00657     case 'g':
00658         print_group(&statbuf);
00659         break;
00660     case 's':
00661         print_size(&statbuf);
00662         break;
00663     case 'd':
00664         print_date(&statbuf);
00665         break;
00666     case 'n':
00667         print_name(&statbuf, name);
00668         break;
00669     default:
00670         fprintf(stderr, "Unknown test letter: %c\n", testtype);
00671         errno = 0;
00672         EC_FAIL
00673     }
00674     printf("\n");
00675     return true;
00676 
00677 EC_CLEANUP_BGN
00678     return false;
00679 EC_CLEANUP_END
00680 }
00681 #ifdef AUPLS_FULL
00682 /*[aupls-main1]*/
00683 int main(int argc, char *argv[])
00684 {
00685     struct traverse_info ti = {0};
00686     int c, status = EXIT_FAILURE;
00687     bool stat_only = false;
00688 /*[]*/
00689     char testtype = '\0';
00690 /*[aupls-main2]*/
00691 
00692     ti.ti_fcn = show_stat;
00693     while ((c = getopt(argc, argv, "dRt:")) != -1)
00694         switch(c) {
00695         case 'd':
00696             stat_only = true;
00697             break;
00698         case 'R':
00699             ti.ti_recursive = true;
00700             break;
00701 /*[]*/
00702         case 't':
00703             testtype = *optarg;
00704             break;
00705 /*[aupls-main3]*/
00706         default:
00707             fprintf(stderr, USAGE);
00708             EC_CLEANUP
00709         }
00710     switch (argc - optind) {
00711     case 0:
00712         ti.ti_name = ".";
00713         break;
00714     case 1:
00715         ti.ti_name = argv[optind];
00716         break;
00717     default:
00718         fprintf(stderr, USAGE);
00719         EC_CLEANUP
00720     }
00721 /*[]*/
00722     if (testtype != '\0')
00723         ec_false( runtest(testtype, ti.ti_name) )
00724     else {
00725 /*[aupls-main4]*/
00726     ec_false( do_entry(&ti, stat_only) )
00727     printf("\nTotal entries: %ld; directories = %ld\n", total_entries,
00728       total_dirs);
00729 /*[]*/
00730     }
00731 /*[aupls-main5]*/
00732     status = EXIT_SUCCESS;
00733     EC_CLEANUP
00734 
00735 EC_CLEANUP_BGN
00736     print_cwd(true);
00737     exit(status);
00738 EC_CLEANUP_END
00739 }
00740 /*[]*/
00741 #endif

Generated on Fri Apr 23 10:56:55 2004 for AUP2 Example Source by doxygen 1.3.1