1/* 2 * 3 * FreeBSD install - a package for the installation and maintenance 4 * of non-core utilities. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * Jordan K. Hubbard 16 * 18 July 1993 17 * 18 * This is the delete module. 19 * 20 */ 21 22#include <sys/cdefs.h> 23__FBSDID("$FreeBSD$"); 24 25#include <sys/types.h> 26#include <sys/stat.h> 27#include <getopt.h> 28#include <err.h> 29 30#include "lib.h" 31#include "delete.h" 32 33char *Prefix = NULL; 34Boolean CleanDirs = FALSE; 35Boolean Interactive = FALSE; 36Boolean NoDeInstall = FALSE; 37Boolean Recursive = FALSE; 38match_t MatchType = MATCH_GLOB; 39 40static void usage(void); 41 42static char opts[] = "adDfGhinp:rvxX"; 43static struct option longopts[] = { 44 { "all", no_argument, NULL, 'a' }, 45 { "clean-dirs", no_argument, NULL, 'd' }, 46 { "dry-run", no_argument, NULL, 'n' }, 47 { "extended", no_argument, NULL, 'X' }, 48 { "force", no_argument, NULL, 'f' }, 49 { "help", no_argument, NULL, 'h' }, 50 { "interactive",no_argument, NULL, 'i' }, 51 { "prefix", required_argument, NULL, 'p' }, 52 { "recursive", no_argument, NULL, 'r' }, 53 { "regex", no_argument, NULL, 'x' }, 54 { "no-glob", no_argument, NULL, 'G' }, 55 { "no-script", no_argument, NULL, 'D' }, 56 { "no-scripts", no_argument, NULL, 'D' }, 57 { "verbose", no_argument, NULL, 'v' }, 58 { NULL, 0, NULL, 0 }, 59}; 60 61int 62main(int argc, char **argv) 63{ 64 int ch, error; 65 char **pkgs, **start; 66 char *pkgs_split; 67 const char *tmp; 68 struct stat stat_s; 69 70 warnpkgng(); 71 pkgs = start = argv; 72 while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) 73 switch(ch) { 74 case 'v': 75 Verbose++; 76 break; 77 78 case 'f': 79 Force = TRUE; 80 break; 81 82 case 'p': 83 Prefix = optarg; 84 break; 85 86 case 'D': 87 NoDeInstall = TRUE; 88 break; 89 90 case 'd': 91 CleanDirs = TRUE; 92 break; 93 94 case 'n': 95 Fake = TRUE; 96 Verbose = TRUE; 97 break; 98 99 case 'a': 100 MatchType = MATCH_ALL; 101 break; 102 103 case 'G': 104 MatchType = MATCH_EXACT; 105 break; 106 107 case 'x': 108 MatchType = MATCH_REGEX; 109 break; 110 111 case 'X': 112 MatchType = MATCH_EREGEX; 113 break; 114 115 case 'i': 116 Interactive = TRUE; 117 break; 118 119 case 'r': 120 Recursive = TRUE; 121 break; 122 123 case 'h': 124 default: 125 usage(); 126 break; 127 } 128 129 argc -= optind; 130 argv += optind; 131 132 /* Get all the remaining package names, if any */ 133 while (*argv) { 134 /* Don't try to apply heuristics if arguments are regexs */ 135 if (MatchType != MATCH_REGEX) 136 while ((pkgs_split = strrchr(*argv, (int)'/')) != NULL) { 137 *pkgs_split++ = '\0'; 138 /* 139 * If character after the '/' is alphanumeric, then we've found the 140 * package name. Otherwise we've come across a trailing '/' and 141 * need to continue our quest. 142 */ 143 if (isalnum(*pkgs_split) || ((MatchType == MATCH_GLOB) && \ 144 strpbrk(pkgs_split, "*?[]") != NULL)) { 145 *argv = pkgs_split; 146 break; 147 } 148 } 149 *pkgs++ = *argv++; 150 } 151 152 /* If no packages, yelp */ 153 if (pkgs == start && MatchType != MATCH_ALL) 154 warnx("missing package name(s)"), usage(); 155 *pkgs = NULL; 156 tmp = LOG_DIR; 157 (void) stat(tmp, &stat_s); 158 if (!Fake && getuid() && geteuid() != stat_s.st_uid) { 159 if (!Force) 160 errx(1, "you do not own %s, use -f to force", tmp); 161 else 162 warnx("you do not own %s (proceeding anyways)", tmp); 163 } 164 if ((error = pkg_perform(start)) != 0) { 165 if (Verbose) 166 warnx("%d package deletion(s) failed", error); 167 return error; 168 } 169 else 170 return 0; 171} 172 173static void 174usage(void) 175{ 176 fprintf(stderr, "%s\n%s\n", 177 "usage: pkg_delete [-dDfGinrvxX] [-p prefix] pkg-name ...", 178 " pkg_delete -a [flags]"); 179 exit(1); 180} 181