1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1992-2010 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * * 20 ***********************************************************************/ 21 #pragma prototyped 22 /* 23 * Glenn Fowler 24 * AT&T Research 25 * 26 * rmdir 27 */ 28 29 static const char usage[] = 30 "[-?\n@(#)$Id: rmdir (AT&T Research) 2006-08-24 $\n]" 31 USAGE_LICENSE 32 "[+NAME?rmdir - remove empty directories]" 33 "[+DESCRIPTION?\brmdir\b deletes each given directory. The directory " 34 "must be empty; containing no entries other than \b.\b or \b..\b. " 35 "If a directory and a subdirectory of that directory are specified " 36 "as operands, the subdirectory must be specified before the parent " 37 "so that the parent directory will be empty when \brmdir\b attempts " 38 "to remove it.]" 39 "[e:ignore-fail-on-non-empty?Ignore each non-empty directory failure.]" 40 "[p:parents?Remove each explicit \adirectory\a argument directory that " 41 "becomes empty after its child directories are removed.]" 42 "[s:suppress?Suppress the message printed on the standard error when " 43 "\b-p\b is in effect.]" 44 "\n" 45 "\ndirectory ...\n" 46 "\n" 47 "[+EXIT STATUS?]{" 48 "[+0?All directories deleted successfully.]" 49 "[+>0?One or more directories could not be deleted.]" 50 "}" 51 "[+SEE ALSO?\bmkdir\b(1), \brm\b(1), \brmdir\b(2), \bunlink\b(2)]" 52 ; 53 54 #include <cmd.h> 55 56 int 57 b_rmdir(int argc, char** argv, void* context) 58 { 59 register char* dir; 60 register char* end; 61 register int n; 62 int eflag = 0; 63 int pflag = 0; 64 int sflag = 0; 65 66 cmdinit(argc, argv, context, ERROR_CATALOG, 0); 67 while (n = optget(argv, usage)) switch (n) 68 { 69 case 'e': 70 eflag = 1; 71 break; 72 case 'p': 73 pflag = 1; 74 break; 75 case 's': 76 sflag = 1; 77 break; 78 case ':': 79 error(2, "%s", opt_info.arg); 80 break; 81 case '?': 82 error(ERROR_usage(2), "%s", opt_info.arg); 83 break; 84 } 85 argv += opt_info.index; 86 if (error_info.errors || !*argv) 87 error(ERROR_usage(2), "%s", optusage(NiL)); 88 if (!pflag) 89 sflag = 0; 90 while (dir = *argv++) 91 { 92 end = dir; 93 if (pflag) end += strlen(dir); 94 n = 0; 95 for (;;) 96 { 97 if (rmdir(dir) < 0) 98 { 99 if (!eflag || errno != EEXIST 100 #ifdef ENOTEMPTY 101 && errno != ENOTEMPTY 102 #endif 103 ) 104 { 105 if (sflag) 106 error_info.errors++; 107 else 108 error(ERROR_system(0), "%s: cannot remove", dir); 109 } 110 break; 111 } 112 if (n) *end = '/'; 113 else n = 1; 114 do if (end <= dir) goto next; while (*--end != '/'); 115 do if (end <= dir) goto next; while (*(end - 1) == '/' && end--); 116 *end = 0; 117 } 118 next: ; 119 } 120 return(error_info.errors != 0); 121 } 122 123