xref: /onnv-gate/usr/src/lib/libcmd/common/rmdir.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1992-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                                                                      *
204887Schin ***********************************************************************/
214887Schin #pragma prototyped
224887Schin /*
234887Schin  * Glenn Fowler
244887Schin  * AT&T Research
254887Schin  *
264887Schin  * rmdir
274887Schin  */
284887Schin 
294887Schin static const char usage[] =
304887Schin "[-?\n@(#)$Id: rmdir (AT&T Research) 2006-08-24 $\n]"
314887Schin USAGE_LICENSE
324887Schin "[+NAME?rmdir - remove empty directories]"
334887Schin "[+DESCRIPTION?\brmdir\b deletes each given directory.  The directory "
344887Schin 	"must be empty; containing no entries other than \b.\b or \b..\b.  "
354887Schin 	"If a directory and a subdirectory of that directory are specified "
364887Schin 	"as operands, the subdirectory must be specified before the parent "
374887Schin 	"so that the parent directory will be empty when \brmdir\b attempts "
384887Schin 	"to remove it.]"
394887Schin "[e:ignore-fail-on-non-empty?Ignore each non-empty directory failure.]"
404887Schin "[p:parents?Remove each explicit \adirectory\a argument directory that "
414887Schin 	"becomes empty after its child directories are removed.]"
424887Schin "[s:suppress?Suppress the message printed on the standard error when "
434887Schin 	"\b-p\b is in effect.]"
444887Schin "\n"
454887Schin "\ndirectory ...\n"
464887Schin "\n"
474887Schin "[+EXIT STATUS?]{"
484887Schin         "[+0?All directories deleted successfully.]"
494887Schin         "[+>0?One or more directories could not be deleted.]"
504887Schin "}"
514887Schin "[+SEE ALSO?\bmkdir\b(1), \brm\b(1), \brmdir\b(2), \bunlink\b(2)]"
524887Schin ;
534887Schin 
544887Schin #include <cmd.h>
554887Schin 
564887Schin int
b_rmdir(int argc,char ** argv,void * context)574887Schin b_rmdir(int argc, char** argv, void* context)
584887Schin {
594887Schin 	register char*	dir;
604887Schin 	register char*	end;
614887Schin 	register int	n;
624887Schin 	int		eflag = 0;
634887Schin 	int		pflag = 0;
644887Schin 	int		sflag = 0;
654887Schin 
664887Schin 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
674887Schin 	while (n = optget(argv, usage)) switch (n)
684887Schin 	{
694887Schin 	case 'e':
704887Schin 		eflag = 1;
714887Schin 		break;
724887Schin 	case 'p':
734887Schin 		pflag = 1;
744887Schin 		break;
754887Schin 	case 's':
764887Schin 		sflag = 1;
774887Schin 		break;
784887Schin 	case ':':
794887Schin 		error(2, "%s", opt_info.arg);
804887Schin 		break;
814887Schin 	case '?':
824887Schin 		error(ERROR_usage(2), "%s", opt_info.arg);
834887Schin 		break;
844887Schin 	}
854887Schin 	argv += opt_info.index;
864887Schin 	if (error_info.errors || !*argv)
874887Schin 		error(ERROR_usage(2), "%s", optusage(NiL));
884887Schin 	if (!pflag)
894887Schin 		sflag = 0;
904887Schin 	while (dir = *argv++)
914887Schin 	{
924887Schin 		end = dir;
934887Schin 		if (pflag) end += strlen(dir);
944887Schin 		n = 0;
954887Schin 		for (;;)
964887Schin 		{
974887Schin 			if (rmdir(dir) < 0)
984887Schin 			{
994887Schin 				if (!eflag || errno != EEXIST
1004887Schin #ifdef ENOTEMPTY
1014887Schin 				    && errno != ENOTEMPTY
1024887Schin #endif
1034887Schin 				    )
1044887Schin 				{
1054887Schin 					if (sflag)
1064887Schin 						error_info.errors++;
1074887Schin 					else
1084887Schin 						error(ERROR_system(0), "%s: cannot remove", dir);
1094887Schin 				}
1104887Schin 				break;
1114887Schin 			}
1124887Schin 			if (n) *end = '/';
1134887Schin 			else n = 1;
1144887Schin 			do if (end <= dir) goto next; while (*--end != '/');
1154887Schin 			do if (end <= dir) goto next; while (*(end - 1) == '/' && end--);
1164887Schin 			*end = 0;
1174887Schin 		}
1184887Schin 	next:	;
1194887Schin 	}
1204887Schin 	return(error_info.errors != 0);
1214887Schin }
1224887Schin 
123