rmdir.c revision 1.18
1/* $NetBSD: rmdir.c,v 1.18 2003/08/04 22:31:25 jschauma Exp $ */
2
3/*-
4 * Copyright (c) 1992, 1993, 1994
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by the University of
18 *	California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include <sys/cdefs.h>
37#ifndef lint
38__COPYRIGHT("@(#) Copyright (c) 1992, 1993, 1994\n\
39	The Regents of the University of California.  All rights reserved.\n");
40#endif /* not lint */
41
42#ifndef lint
43#if 0
44static char sccsid[] = "@(#)rmdir.c	8.3 (Berkeley) 4/2/94";
45#else
46__RCSID("$NetBSD: rmdir.c,v 1.18 2003/08/04 22:31:25 jschauma Exp $");
47#endif
48#endif /* not lint */
49
50#include <sys/param.h>
51
52#include <err.h>
53#include <errno.h>
54#include <locale.h>
55#include <stdio.h>
56#include <stdlib.h>
57#include <string.h>
58#include <unistd.h>
59#include <vis.h>
60
61int	stdout_ok;			/* stdout connected to a terminal */
62
63int	rm_path(char *);
64void	usage(void);
65int	main(int, char *[]);
66char	*printescaped(const char *);
67
68int
69main(int argc, char *argv[])
70{
71	int ch, errors, pflag;
72
73	setprogname(argv[0]);
74	(void)setlocale(LC_ALL, "");
75
76	pflag = 0;
77	while ((ch = getopt(argc, argv, "p")) != -1)
78		switch(ch) {
79		case 'p':
80			pflag = 1;
81			break;
82		case '?':
83		default:
84			usage();
85		}
86	argc -= optind;
87	argv += optind;
88
89	if (argc == 0)
90		usage();
91
92	stdout_ok = isatty(STDIN_FILENO);
93
94	for (errors = 0; *argv; argv++) {
95		char *p;
96
97		/* Delete trailing slashes, per POSIX. */
98		p = *argv + strlen(*argv);
99		while (--p > *argv && *p == '/')
100			;
101		*++p = '\0';
102
103		if (rmdir(*argv) < 0) {
104			char *dn;
105			dn = printescaped(*argv);
106			warn("%s", dn);
107			free(dn);
108			errors = 1;
109		} else if (pflag)
110			errors |= rm_path(*argv);
111	}
112
113	exit(errors);
114	/* NOTREACHED */
115}
116
117int
118rm_path(char *path)
119{
120	char *p;
121
122	while ((p = strrchr(path, '/')) != NULL) {
123		/* Delete trailing slashes. */
124		while (--p > path && *p == '/')
125			;
126		*++p = '\0';
127
128		if (rmdir(path) < 0) {
129			char *pn;
130			pn = printescaped(path);
131			warn("%s", pn);
132			free(pn);
133			return (1);
134		}
135	}
136
137	return (0);
138}
139
140void
141usage(void)
142{
143	(void)fprintf(stderr, "usage: %s [-p] directory ...\n", getprogname());
144	exit(1);
145	/* NOTREACHED */
146}
147
148char *
149printescaped(const char *src)
150{
151	size_t len;
152	char *retval;
153
154	len = strlen(src);
155	if (len != 0 && SIZE_T_MAX/len <= 4) {
156		errx(EXIT_FAILURE, "%s: name too long", src);
157		/* NOTREACHED */
158	}
159
160	retval = (char *)malloc(4*len+1);
161	if (retval != NULL) {
162		if (stdout_ok)
163			(void)strvis(retval, src, VIS_NL | VIS_CSTYLE);
164		else
165			(void)strcpy(retval, src);
166		return retval;
167	} else
168		errx(EXIT_FAILURE, "out of memory!");
169		/* NOTREACHED */
170}
171