1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1992-2011 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 29static const char usage[] = 30"[-?\n@(#)$Id: rmdir (AT&T Research) 2006-08-24 $\n]" 31USAGE_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 56int 57b_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 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