1327Sjkh/* 2327Sjkh * 3327Sjkh * FreeBSD install - a package for the installation and maintainance 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 70327Sjkh pkgs = start = argv; 71179433Sflz while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) 72327Sjkh switch(ch) { 73327Sjkh case 'v': 74159554Sobrien Verbose++; 75327Sjkh break; 76327Sjkh 774996Sjkh case 'f': 784996Sjkh Force = TRUE; 794996Sjkh break; 804996Sjkh 81327Sjkh case 'p': 82327Sjkh Prefix = optarg; 83327Sjkh break; 84327Sjkh 85327Sjkh case 'D': 86327Sjkh NoDeInstall = TRUE; 87327Sjkh break; 88327Sjkh 894996Sjkh case 'd': 904996Sjkh CleanDirs = TRUE; 914996Sjkh break; 924996Sjkh 93327Sjkh case 'n': 94327Sjkh Fake = TRUE; 95327Sjkh Verbose = TRUE; 96327Sjkh break; 97327Sjkh 9873134Ssobomax case 'a': 9973134Ssobomax MatchType = MATCH_ALL; 10073134Ssobomax break; 10173134Ssobomax 10273134Ssobomax case 'G': 10373134Ssobomax MatchType = MATCH_EXACT; 10473134Ssobomax break; 10573134Ssobomax 10673134Ssobomax case 'x': 10773134Ssobomax MatchType = MATCH_REGEX; 10873134Ssobomax break; 10973134Ssobomax 110131275Seik case 'X': 111131275Seik MatchType = MATCH_EREGEX; 112131275Seik break; 113131275Seik 11473134Ssobomax case 'i': 11573134Ssobomax Interactive = TRUE; 11673134Ssobomax break; 11773134Ssobomax 11883663Ssobomax case 'r': 11983663Ssobomax Recursive = TRUE; 12083663Ssobomax break; 12183663Ssobomax 122327Sjkh case 'h': 123327Sjkh default: 12430221Scharnier usage(); 125327Sjkh break; 126327Sjkh } 127327Sjkh 1288857Srgrimes argc -= optind; 129327Sjkh argv += optind; 130327Sjkh 131327Sjkh /* Get all the remaining package names, if any */ 13257311Sjkh while (*argv) { 13373134Ssobomax /* Don't try to apply heuristics if arguments are regexs */ 13473134Ssobomax if (MatchType != MATCH_REGEX) 13573134Ssobomax while ((pkgs_split = strrchr(*argv, (int)'/')) != NULL) { 13673134Ssobomax *pkgs_split++ = '\0'; 13773134Ssobomax /* 13873134Ssobomax * If character after the '/' is alphanumeric, then we've found the 13973134Ssobomax * package name. Otherwise we've come across a trailing '/' and 14073134Ssobomax * need to continue our quest. 14173134Ssobomax */ 142151188Skrion if (isalnum(*pkgs_split) || ((MatchType == MATCH_GLOB) && \ 14373134Ssobomax strpbrk(pkgs_split, "*?[]") != NULL)) { 14473134Ssobomax *argv = pkgs_split; 14573134Ssobomax break; 14673134Ssobomax } 14760563Ssteve } 14860563Ssteve *pkgs++ = *argv++; 14956001Sdan } 150327Sjkh 151327Sjkh /* If no packages, yelp */ 15273134Ssobomax if (pkgs == start && MatchType != MATCH_ALL) 15330221Scharnier warnx("missing package name(s)"), usage(); 154327Sjkh *pkgs = NULL; 15581049Ssobomax tmp = LOG_DIR; 15660499Shoek (void) stat(tmp, &stat_s); 15760499Shoek if (!Fake && getuid() && geteuid() != stat_s.st_uid) { 15860499Shoek if (!Force) 15960499Shoek errx(1, "you do not own %s, use -f to force", tmp); 16060499Shoek else 16160499Shoek warnx("you do not own %s (proceeding anyways)", tmp); 16260499Shoek } 16329574Sphk if ((error = pkg_perform(start)) != 0) { 164327Sjkh if (Verbose) 16530221Scharnier warnx("%d package deletion(s) failed", error); 1664996Sjkh return error; 167327Sjkh } 168327Sjkh else 169327Sjkh return 0; 170327Sjkh} 171327Sjkh 17230221Scharnierstatic void 173201226Sedusage(void) 174327Sjkh{ 17573134Ssobomax fprintf(stderr, "%s\n%s\n", 176131275Seik "usage: pkg_delete [-dDfGinrvxX] [-p prefix] pkg-name ...", 17773134Ssobomax " pkg_delete -a [flags]"); 178327Sjkh exit(1); 179327Sjkh} 180