1327Sjkh/* 2327Sjkh * 3228990Suqs * FreeBSD install - a package for the installation and maintenance 4327Sjkh * of non-core utilities. 5327Sjkh * 6327Sjkh * Redistribution and use in source and binary forms, with or without 7327Sjkh * modification, are permitted provided that the following conditions 8327Sjkh * are met: 9327Sjkh * 1. Redistributions of source code must retain the above copyright 10327Sjkh * notice, this list of conditions and the following disclaimer. 11327Sjkh * 2. Redistributions in binary form must reproduce the above copyright 12327Sjkh * notice, this list of conditions and the following disclaimer in the 13327Sjkh * documentation and/or other materials provided with the distribution. 14327Sjkh * 15327Sjkh * Jordan K. Hubbard 16327Sjkh * 18 July 1993 17327Sjkh * 18327Sjkh * This is the delete module. 19327Sjkh * 20327Sjkh */ 21327Sjkh 2293520Sobrien#include <sys/cdefs.h> 2393520Sobrien__FBSDID("$FreeBSD$"); 2493520Sobrien 2560499Shoek#include <sys/types.h> 2660499Shoek#include <sys/stat.h> 27179433Sflz#include <getopt.h> 2830221Scharnier#include <err.h> 29179433Sflz 30222035Sflz#include "lib.h" 31327Sjkh#include "delete.h" 32327Sjkh 33327Sjkhchar *Prefix = NULL; 3473134SsobomaxBoolean CleanDirs = FALSE; 3573134SsobomaxBoolean Interactive = FALSE; 36327SjkhBoolean NoDeInstall = FALSE; 3783663SsobomaxBoolean Recursive = FALSE; 3873134Ssobomaxmatch_t MatchType = MATCH_GLOB; 39327Sjkh 40173412Skevlostatic void usage(void); 4130221Scharnier 42179433Sflzstatic char opts[] = "adDfGhinp:rvxX"; 43179433Sflzstatic struct option longopts[] = { 44179433Sflz { "all", no_argument, NULL, 'a' }, 45179433Sflz { "clean-dirs", no_argument, NULL, 'd' }, 46179433Sflz { "dry-run", no_argument, NULL, 'n' }, 47179433Sflz { "extended", no_argument, NULL, 'X' }, 48179433Sflz { "force", no_argument, NULL, 'f' }, 49179433Sflz { "help", no_argument, NULL, 'h' }, 50179433Sflz { "interactive",no_argument, NULL, 'i' }, 51179433Sflz { "prefix", required_argument, NULL, 'p' }, 52179433Sflz { "recursive", no_argument, NULL, 'r' }, 53179433Sflz { "regex", no_argument, NULL, 'x' }, 54179433Sflz { "no-glob", no_argument, NULL, 'G' }, 55179433Sflz { "no-script", no_argument, NULL, 'D' }, 56179433Sflz { "no-scripts", no_argument, NULL, 'D' }, 57179433Sflz { "verbose", no_argument, NULL, 'v' }, 58179433Sflz { NULL, 0, NULL, 0 }, 59179433Sflz}; 60179433Sflz 61327Sjkhint 62327Sjkhmain(int argc, char **argv) 63327Sjkh{ 644996Sjkh int ch, error; 65327Sjkh char **pkgs, **start; 6656001Sdan char *pkgs_split; 6784745Ssobomax const char *tmp; 6860499Shoek struct stat stat_s; 69327Sjkh 70241830Seadler warnpkgng(); 71327Sjkh pkgs = start = argv; 72179433Sflz while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) 73327Sjkh switch(ch) { 74327Sjkh case 'v': 75159554Sobrien Verbose++; 76327Sjkh break; 77327Sjkh 784996Sjkh case 'f': 794996Sjkh Force = TRUE; 804996Sjkh break; 814996Sjkh 82327Sjkh case 'p': 83327Sjkh Prefix = optarg; 84327Sjkh break; 85327Sjkh 86327Sjkh case 'D': 87327Sjkh NoDeInstall = TRUE; 88327Sjkh break; 89327Sjkh 904996Sjkh case 'd': 914996Sjkh CleanDirs = TRUE; 924996Sjkh break; 934996Sjkh 94327Sjkh case 'n': 95327Sjkh Fake = TRUE; 96327Sjkh Verbose = TRUE; 97327Sjkh break; 98327Sjkh 9973134Ssobomax case 'a': 10073134Ssobomax MatchType = MATCH_ALL; 10173134Ssobomax break; 10273134Ssobomax 10373134Ssobomax case 'G': 10473134Ssobomax MatchType = MATCH_EXACT; 10573134Ssobomax break; 10673134Ssobomax 10773134Ssobomax case 'x': 10873134Ssobomax MatchType = MATCH_REGEX; 10973134Ssobomax break; 11073134Ssobomax 111131275Seik case 'X': 112131275Seik MatchType = MATCH_EREGEX; 113131275Seik break; 114131275Seik 11573134Ssobomax case 'i': 11673134Ssobomax Interactive = TRUE; 11773134Ssobomax break; 11873134Ssobomax 11983663Ssobomax case 'r': 12083663Ssobomax Recursive = TRUE; 12183663Ssobomax break; 12283663Ssobomax 123327Sjkh case 'h': 124327Sjkh default: 12530221Scharnier usage(); 126327Sjkh break; 127327Sjkh } 128327Sjkh 1298857Srgrimes argc -= optind; 130327Sjkh argv += optind; 131327Sjkh 132327Sjkh /* Get all the remaining package names, if any */ 13357311Sjkh while (*argv) { 13473134Ssobomax /* Don't try to apply heuristics if arguments are regexs */ 13573134Ssobomax if (MatchType != MATCH_REGEX) 13673134Ssobomax while ((pkgs_split = strrchr(*argv, (int)'/')) != NULL) { 13773134Ssobomax *pkgs_split++ = '\0'; 13873134Ssobomax /* 13973134Ssobomax * If character after the '/' is alphanumeric, then we've found the 14073134Ssobomax * package name. Otherwise we've come across a trailing '/' and 14173134Ssobomax * need to continue our quest. 14273134Ssobomax */ 143151188Skrion if (isalnum(*pkgs_split) || ((MatchType == MATCH_GLOB) && \ 14473134Ssobomax strpbrk(pkgs_split, "*?[]") != NULL)) { 14573134Ssobomax *argv = pkgs_split; 14673134Ssobomax break; 14773134Ssobomax } 14860563Ssteve } 14960563Ssteve *pkgs++ = *argv++; 15056001Sdan } 151327Sjkh 152327Sjkh /* If no packages, yelp */ 15373134Ssobomax if (pkgs == start && MatchType != MATCH_ALL) 15430221Scharnier warnx("missing package name(s)"), usage(); 155327Sjkh *pkgs = NULL; 15681049Ssobomax tmp = LOG_DIR; 15760499Shoek (void) stat(tmp, &stat_s); 15860499Shoek if (!Fake && getuid() && geteuid() != stat_s.st_uid) { 15960499Shoek if (!Force) 16060499Shoek errx(1, "you do not own %s, use -f to force", tmp); 16160499Shoek else 16260499Shoek warnx("you do not own %s (proceeding anyways)", tmp); 16360499Shoek } 16429574Sphk if ((error = pkg_perform(start)) != 0) { 165327Sjkh if (Verbose) 16630221Scharnier warnx("%d package deletion(s) failed", error); 1674996Sjkh return error; 168327Sjkh } 169327Sjkh else 170327Sjkh return 0; 171327Sjkh} 172327Sjkh 17330221Scharnierstatic void 174201226Sedusage(void) 175327Sjkh{ 17673134Ssobomax fprintf(stderr, "%s\n%s\n", 177131275Seik "usage: pkg_delete [-dDfGinrvxX] [-p prefix] pkg-name ...", 17873134Ssobomax " pkg_delete -a [flags]"); 179327Sjkh exit(1); 180327Sjkh} 181