1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1992-2012 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 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, Shbltin_t* 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 for (;;) 68 { 69 switch (optget(argv, usage)) 70 { 71 case 'e': 72 eflag = 1; 73 continue; 74 case 'p': 75 pflag = 1; 76 continue; 77 case 's': 78 sflag = 1; 79 continue; 80 case ':': 81 error(2, "%s", opt_info.arg); 82 break; 83 case '?': 84 error(ERROR_usage(2), "%s", opt_info.arg); 85 break; 86 } 87 break; 88 } 89 argv += opt_info.index; 90 if (error_info.errors || !*argv) 91 error(ERROR_usage(2), "%s", optusage(NiL)); 92 if (!pflag) 93 sflag = 0; 94 while (dir = *argv++) 95 { 96 end = dir; 97 if (pflag) end += strlen(dir); 98 n = 0; 99 for (;;) 100 { 101 if (rmdir(dir) < 0) 102 { 103 if (!eflag || errno != EEXIST 104 #ifdef ENOTEMPTY 105 && errno != ENOTEMPTY 106 #endif 107 ) 108 { 109 if (sflag) 110 error_info.errors++; 111 else 112 error(ERROR_system(0), "%s: cannot remove", dir); 113 } 114 break; 115 } 116 if (n) *end = '/'; 117 else n = 1; 118 do if (end <= dir) goto next; while (*--end != '/'); 119 do if (end <= dir) goto next; while (*(end - 1) == '/' && end--); 120 *end = 0; 121 } 122 next: ; 123 } 124 return(error_info.errors != 0); 125 } 126 127