main.c revision 81049
1129202Scognet#ifndef lint
2129202Scognetstatic const char rcsid[] =
3129202Scognet  "$FreeBSD: head/usr.sbin/pkg_install/delete/main.c 81049 2001-08-02 13:13:06Z sobomax $";
4129202Scognet#endif
5129202Scognet
6129202Scognet/*
7129202Scognet *
8129202Scognet * FreeBSD install - a package for the installation and maintainance
9129202Scognet * of non-core utilities.
10129202Scognet *
11129202Scognet * Redistribution and use in source and binary forms, with or without
12129202Scognet * modification, are permitted provided that the following conditions
13129202Scognet * are met:
14129202Scognet * 1. Redistributions of source code must retain the above copyright
15129202Scognet *    notice, this list of conditions and the following disclaimer.
16129202Scognet * 2. Redistributions in binary form must reproduce the above copyright
17129202Scognet *    notice, this list of conditions and the following disclaimer in the
18129202Scognet *    documentation and/or other materials provided with the distribution.
19129202Scognet *
20129202Scognet * Jordan K. Hubbard
21129202Scognet * 18 July 1993
22129202Scognet *
23129202Scognet * This is the delete module.
24129202Scognet *
25129202Scognet */
26129202Scognet
27129202Scognet#include <sys/types.h>
28129202Scognet#include <sys/stat.h>
29129202Scognet#include <err.h>
30129202Scognet#include "lib.h"
31129202Scognet#include "delete.h"
32129202Scognet
33129202Scognetstatic char Options[] = "adDfGhinp:vx";
34129202Scognet
35129202Scognetchar	*Prefix		= NULL;
36129202ScognetBoolean	CleanDirs	= FALSE;
37129202ScognetBoolean	Interactive	= FALSE;
38129202ScognetBoolean	NoDeInstall	= FALSE;
39129202Scognetmatch_t	MatchType	= MATCH_GLOB;
40129202Scognet
41129202Scognetstatic void usage __P((void));
42129202Scognet
43129202Scognetint
44129202Scognetmain(int argc, char **argv)
45129202Scognet{
46129202Scognet    int ch, error;
47129202Scognet    char **pkgs, **start;
48129202Scognet    char *pkgs_split;
49129202Scognet    char *tmp;
50129202Scognet    struct stat stat_s;
51129202Scognet
52129202Scognet    pkgs = start = argv;
53129202Scognet    while ((ch = getopt(argc, argv, Options)) != -1)
54129202Scognet	switch(ch) {
55271337Sian	case 'v':
56	    Verbose = TRUE;
57	    break;
58
59	case 'f':
60	    Force = TRUE;
61	    break;
62
63	case 'p':
64	    Prefix = optarg;
65	    break;
66
67	case 'D':
68	    NoDeInstall = TRUE;
69	    break;
70
71	case 'd':
72	    CleanDirs = TRUE;
73	    break;
74
75	case 'n':
76	    Fake = TRUE;
77	    Verbose = TRUE;
78	    break;
79
80	case 'a':
81	    MatchType = MATCH_ALL;
82	    break;
83
84	case 'G':
85	    MatchType = MATCH_EXACT;
86	    break;
87
88	case 'x':
89	    MatchType = MATCH_REGEX;
90	    break;
91
92	case 'i':
93	    Interactive = TRUE;
94	    break;
95
96	case 'h':
97	case '?':
98	default:
99	    usage();
100	    break;
101	}
102
103    argc -= optind;
104    argv += optind;
105
106    /* Get all the remaining package names, if any */
107    while (*argv) {
108	/* Don't try to apply heuristics if arguments are regexs */
109	if (MatchType != MATCH_REGEX)
110	    while ((pkgs_split = strrchr(*argv, (int)'/')) != NULL) {
111		*pkgs_split++ = '\0';
112		/*
113		 * If character after the '/' is alphanumeric, then we've found the
114		 * package name.  Otherwise we've come across a trailing '/' and
115		 * need to continue our quest.
116		 */
117		if (isalpha(*pkgs_split) || ((MatchType == MATCH_GLOB) && \
118		    strpbrk(pkgs_split, "*?[]") != NULL)) {
119		    *argv = pkgs_split;
120		    break;
121		}
122	    }
123	*pkgs++ = *argv++;
124    }
125
126    /* If no packages, yelp */
127    if (pkgs == start && MatchType != MATCH_ALL)
128	warnx("missing package name(s)"), usage();
129    *pkgs = NULL;
130    tmp = LOG_DIR;
131    (void) stat(tmp, &stat_s);
132    if (!Fake && getuid() && geteuid() != stat_s.st_uid) {
133	if (!Force)
134	    errx(1, "you do not own %s, use -f to force", tmp);
135	else
136	    warnx("you do not own %s (proceeding anyways)", tmp);
137    }
138    if ((error = pkg_perform(start)) != 0) {
139	if (Verbose)
140	    warnx("%d package deletion(s) failed", error);
141	return error;
142    }
143    else
144	return 0;
145}
146
147static void
148usage()
149{
150    fprintf(stderr, "%s\n%s\n",
151	"usage: pkg_delete [-dDfGinvx] [-p prefix] pkg-name ...",
152	"       pkg_delete -a [flags]");
153    exit(1);
154}
155