perform.c revision 72174
1327Sjkh#ifndef lint 230221Scharnierstatic const char rcsid[] = 350479Speter "$FreeBSD: head/usr.sbin/pkg_install/info/perform.c 72174 2001-02-08 17:44:00Z sobomax $"; 4327Sjkh#endif 5327Sjkh 6327Sjkh/* 7327Sjkh * FreeBSD install - a package for the installation and maintainance 8327Sjkh * of non-core utilities. 9327Sjkh * 10327Sjkh * Redistribution and use in source and binary forms, with or without 11327Sjkh * modification, are permitted provided that the following conditions 12327Sjkh * are met: 13327Sjkh * 1. Redistributions of source code must retain the above copyright 14327Sjkh * notice, this list of conditions and the following disclaimer. 15327Sjkh * 2. Redistributions in binary form must reproduce the above copyright 16327Sjkh * notice, this list of conditions and the following disclaimer in the 17327Sjkh * documentation and/or other materials provided with the distribution. 18327Sjkh * 19327Sjkh * Jordan K. Hubbard 20327Sjkh * 23 Aug 1993 21327Sjkh * 22327Sjkh * This is the main body of the info module. 23327Sjkh * 24327Sjkh */ 25327Sjkh 26327Sjkh#include "lib.h" 27327Sjkh#include "info.h" 28327Sjkh 2972174Ssobomax#include <sys/types.h> 3072174Ssobomax#include <err.h> 3172174Ssobomax#include <glob.h> 3249300Sjdp#include <fts.h> 3372174Ssobomax#include <regex.h> 34327Sjkh#include <signal.h> 35327Sjkh 3649300Sjdpstatic int fname_cmp(const FTSENT **, const FTSENT **); 37327Sjkhstatic int pkg_do(char *); 3872174Ssobomaxstatic int rexs_match(char **, char *); 39327Sjkh 40327Sjkhint 41327Sjkhpkg_perform(char **pkgs) 42327Sjkh{ 43327Sjkh int i, err_cnt = 0; 447937Sjkh char *tmp; 45327Sjkh 46327Sjkh signal(SIGINT, cleanup); 47327Sjkh 487937Sjkh tmp = getenv(PKG_DBDIR); 497937Sjkh if (!tmp) 507937Sjkh tmp = DEF_LOG_DIR; 51327Sjkh /* Overriding action? */ 5216404Sjkh if (CheckPkg) { 5316404Sjkh char buf[FILENAME_MAX]; 54327Sjkh 5516404Sjkh snprintf(buf, FILENAME_MAX, "%s/%s", tmp, CheckPkg); 5616404Sjkh return abs(access(buf, R_OK)); 5772174Ssobomax /* Not reached */ 5816404Sjkh } 598857Srgrimes 6072174Ssobomax switch (MatchType) { 6172174Ssobomax case MATCH_ALL: 6272174Ssobomax case MATCH_REGEX: 6372174Ssobomax { 6472174Ssobomax FTS *ftsp; 6572174Ssobomax FTSENT *f; 6672174Ssobomax char *paths[2]; 6772174Ssobomax int errcode; 6872174Ssobomax 6972174Ssobomax if (!isdir(tmp)) 7072174Ssobomax return 1; 7172174Ssobomax paths[0] = tmp; 7272174Ssobomax paths[1] = NULL; 7372174Ssobomax ftsp = fts_open(paths, FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT, 7472174Ssobomax fname_cmp); 7572174Ssobomax if (ftsp != NULL) { 7672174Ssobomax while ((f = fts_read(ftsp)) != NULL) { 7772174Ssobomax if (f->fts_info == FTS_D && f->fts_level == 1) { 7872174Ssobomax fts_set(ftsp, f, FTS_SKIP); 7972174Ssobomax if (MatchType == MATCH_REGEX) { 8072174Ssobomax errcode = rexs_match(pkgs, f->fts_name); 8172174Ssobomax if (errcode == -1) { 8272174Ssobomax err_cnt += 1; 8372174Ssobomax break; 8472174Ssobomax } 8572174Ssobomax else if (errcode == 0) 8672174Ssobomax continue; 8772174Ssobomax } 8872174Ssobomax err_cnt += pkg_do(f->fts_name); 8972174Ssobomax } 9049300Sjdp } 9172174Ssobomax fts_close(ftsp); 9249300Sjdp } 9316404Sjkh } 9472174Ssobomax break; 9572174Ssobomax case MATCH_GLOB: 9672174Ssobomax { 9772174Ssobomax glob_t g; 9872174Ssobomax char *gexpr; 9972174Ssobomax char *cp; 10072174Ssobomax int gflags; 10172174Ssobomax int prev_matchc; 10272174Ssobomax 10372174Ssobomax gflags = GLOB_ERR; 10472174Ssobomax prev_matchc = 0; 10572174Ssobomax for (i = 0; pkgs[i]; i++) { 10672174Ssobomax asprintf(&gexpr, "%s/%s", tmp, pkgs[i]); 10772174Ssobomax 10872174Ssobomax if (glob(gexpr, gflags, NULL, &g) != 0) { 10972174Ssobomax warn("%s: error encountered when matching glob", pkgs[i]); 11072174Ssobomax return 1; 11172174Ssobomax } 11272174Ssobomax 11372174Ssobomax /* 11472174Ssobomax * If glob doesn't match try to use pkgs[i] directly - it 11572174Ssobomax * could be name of the tarball. 11672174Ssobomax */ 11772174Ssobomax if (g.gl_matchc == prev_matchc) 11872174Ssobomax err_cnt += pkg_do(pkgs[i]); 11972174Ssobomax 12072174Ssobomax prev_matchc = g.gl_matchc; 12172174Ssobomax gflags |= GLOB_APPEND; 12272174Ssobomax free(gexpr); 12372174Ssobomax } 12472174Ssobomax 12572174Ssobomax for (i = 0; i < g.gl_matchc; i++) { 12672174Ssobomax cp = strrchr(g.gl_pathv[i], '/'); 12772174Ssobomax if (cp == NULL) 12872174Ssobomax cp = g.gl_pathv[i]; 12972174Ssobomax else 13072174Ssobomax cp++; 13172174Ssobomax 13272174Ssobomax err_cnt += pkg_do(cp); 13372174Ssobomax } 13472174Ssobomax 13572174Ssobomax globfree(&g); 13672174Ssobomax } 13772174Ssobomax break; 13872174Ssobomax default: 13916404Sjkh for (i = 0; pkgs[i]; i++) 14016404Sjkh err_cnt += pkg_do(pkgs[i]); 14172174Ssobomax break; 14272174Ssobomax } 14372174Ssobomax 144327Sjkh return err_cnt; 145327Sjkh} 146327Sjkh 14711780Sjkhstatic char *Home; 14811780Sjkh 149327Sjkhstatic int 150327Sjkhpkg_do(char *pkg) 151327Sjkh{ 1528086Sjkh Boolean installed = FALSE, isTMP = FALSE; 153327Sjkh char log_dir[FILENAME_MAX]; 1548086Sjkh char fname[FILENAME_MAX]; 155327Sjkh Package plist; 156327Sjkh FILE *fp; 1578086Sjkh struct stat sb; 1588142Sjkh char *cp = NULL; 1598086Sjkh int code = 0; 160327Sjkh 1618086Sjkh if (isURL(pkg)) { 16211780Sjkh if ((cp = fileGetURL(NULL, pkg)) != NULL) { 1638086Sjkh strcpy(fname, cp); 1648086Sjkh isTMP = TRUE; 1658086Sjkh } 1668086Sjkh } 1679782Sache else if (fexists(pkg) && isfile(pkg)) { 1688086Sjkh int len; 169327Sjkh 1708423Sjkh if (*pkg != '/') { 1718423Sjkh if (!getcwd(fname, FILENAME_MAX)) 1728423Sjkh upchuck("getcwd"); 1738423Sjkh len = strlen(fname); 1748423Sjkh snprintf(&fname[len], FILENAME_MAX - len, "/%s", pkg); 1758423Sjkh } 1768423Sjkh else 1778423Sjkh strcpy(fname, pkg); 1788086Sjkh cp = fname; 1798086Sjkh } 1808086Sjkh else { 18111780Sjkh if ((cp = fileFindByPath(NULL, pkg)) != NULL) 1828086Sjkh strncpy(fname, cp, FILENAME_MAX); 1838086Sjkh } 1848086Sjkh if (cp) { 1853364Sjkh /* 1863364Sjkh * Apply a crude heuristic to see how much space the package will 1873364Sjkh * take up once it's unpacked. I've noticed that most packages 1883577Sjkh * compress an average of 75%, but we're only unpacking the + files so 1893577Sjkh * be very optimistic. 1903364Sjkh */ 1913364Sjkh if (stat(fname, &sb) == FAIL) { 19230221Scharnier warnx("can't stat package file '%s'", fname); 1938086Sjkh code = 1; 1948086Sjkh goto bail; 1953364Sjkh } 19611780Sjkh Home = make_playpen(PlayPen, sb.st_size / 2); 197327Sjkh if (unpack(fname, "+*")) { 19830221Scharnier warnx("error during unpacking, no info for '%s' available", pkg); 1998086Sjkh code = 1; 2008086Sjkh goto bail; 201327Sjkh } 202327Sjkh } 2038086Sjkh /* It's not an ininstalled package, try and find it among the installed */ 204327Sjkh else { 2057937Sjkh char *tmp; 2067937Sjkh 2077937Sjkh sprintf(log_dir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, 2087937Sjkh pkg); 209327Sjkh if (!fexists(log_dir)) { 21030221Scharnier warnx("can't find package `%s' installed or in a file!", pkg); 211327Sjkh return 1; 212327Sjkh } 213327Sjkh if (chdir(log_dir) == FAIL) { 21430221Scharnier warnx("can't change directory to '%s'!", log_dir); 215327Sjkh return 1; 216327Sjkh } 217327Sjkh installed = TRUE; 218327Sjkh } 219327Sjkh 220327Sjkh /* Suck in the contents list */ 221327Sjkh plist.head = plist.tail = NULL; 222327Sjkh fp = fopen(CONTENTS_FNAME, "r"); 223327Sjkh if (!fp) { 22430221Scharnier warnx("unable to open %s file", CONTENTS_FNAME); 2258086Sjkh code = 1; 2268086Sjkh goto bail; 227327Sjkh } 228327Sjkh /* If we have a prefix, add it now */ 229327Sjkh read_plist(&plist, fp); 230327Sjkh fclose(fp); 231327Sjkh 232327Sjkh /* 233327Sjkh * Index is special info type that has to override all others to make 234327Sjkh * any sense. 235327Sjkh */ 236327Sjkh if (Flags & SHOW_INDEX) { 2378086Sjkh char tmp[FILENAME_MAX]; 238327Sjkh 2398086Sjkh snprintf(tmp, FILENAME_MAX, "%-19s ", pkg); 2408086Sjkh show_index(tmp, COMMENT_FNAME); 241327Sjkh } 242327Sjkh else { 243327Sjkh /* Start showing the package contents */ 244411Sjkh if (!Quiet) 245411Sjkh printf("%sInformation for %s:\n\n", InfoPrefix, pkg); 246327Sjkh if (Flags & SHOW_COMMENT) 247379Sjkh show_file("Comment:\n", COMMENT_FNAME); 24866339Smarko if (Flags & SHOW_REQUIRE) 24966339Smarko show_plist("Depends on:\n", &plist, PLIST_PKGDEP); 2504996Sjkh if ((Flags & SHOW_REQBY) && !isemptyfile(REQUIRED_BY_FNAME)) 2514996Sjkh show_file("Required by:\n", REQUIRED_BY_FNAME); 252327Sjkh if (Flags & SHOW_DESC) 253379Sjkh show_file("Description:\n", DESC_FNAME); 2544996Sjkh if ((Flags & SHOW_DISPLAY) && fexists(DISPLAY_FNAME)) 2554996Sjkh show_file("Install notice:\n", DISPLAY_FNAME); 256327Sjkh if (Flags & SHOW_PLIST) 257379Sjkh show_plist("Packing list:\n", &plist, (plist_t)-1); 258327Sjkh if ((Flags & SHOW_INSTALL) && fexists(INSTALL_FNAME)) 259379Sjkh show_file("Install script:\n", INSTALL_FNAME); 26041866Sjkh if ((Flags & SHOW_INSTALL) && fexists(POST_INSTALL_FNAME)) 26141866Sjkh show_file("Post-Install script:\n", POST_INSTALL_FNAME); 262327Sjkh if ((Flags & SHOW_DEINSTALL) && fexists(DEINSTALL_FNAME)) 263379Sjkh show_file("De-Install script:\n", DEINSTALL_FNAME); 26441866Sjkh if ((Flags & SHOW_DEINSTALL) && fexists(POST_DEINSTALL_FNAME)) 26541866Sjkh show_file("Post-DeInstall script:\n", POST_DEINSTALL_FNAME); 2664996Sjkh if ((Flags & SHOW_MTREE) && fexists(MTREE_FNAME)) 2674996Sjkh show_file("mtree file:\n", MTREE_FNAME); 268327Sjkh if (Flags & SHOW_PREFIX) 269379Sjkh show_plist("Prefix(s):\n", &plist, PLIST_CWD); 270411Sjkh if (Flags & SHOW_FILES) 271411Sjkh show_files("Files:\n", &plist); 27262775Ssobomax if ((Flags & SHOW_SIZE) && installed) 27362775Ssobomax show_size("Package Size:\n", &plist); 27471965Sjkh if ((Flags & SHOW_CKSUM) && installed) 27571965Sjkh show_cksum("Mismatched Checksums:\n", &plist); 27667454Ssobomax if (Flags & SHOW_ORIGIN) 27767454Ssobomax show_origin("Origin:\n", &plist); 278411Sjkh if (!Quiet) 279411Sjkh puts(InfoPrefix); 280327Sjkh } 281327Sjkh free_plist(&plist); 2828086Sjkh bail: 28333427Sjkh leave_playpen(); 2848086Sjkh if (isTMP) 2858086Sjkh unlink(fname); 2868086Sjkh return code; 287327Sjkh} 288327Sjkh 289327Sjkhvoid 290327Sjkhcleanup(int sig) 291327Sjkh{ 29233427Sjkh static int in_cleanup = 0; 29333427Sjkh 29433427Sjkh if (!in_cleanup) { 29533427Sjkh in_cleanup = 1; 29672174Ssobomax leave_playpen(); 29733427Sjkh } 29839068Sjkh if (sig) 29939068Sjkh exit(1); 300327Sjkh} 30149300Sjdp 30249300Sjdpstatic int 30349300Sjdpfname_cmp(const FTSENT **a, const FTSENT **b) 30449300Sjdp{ 30549300Sjdp return strcmp((*a)->fts_name, (*b)->fts_name); 30649300Sjdp} 30772174Ssobomax 30872174Ssobomax/* 30972174Ssobomax * Returns 1 if specified pkgname matches at least one 31072174Ssobomax * of the RE from patterns. Otherwise return 0 if no 31172174Ssobomax * matches were found or -1 if RE engine reported an 31272174Ssobomax * error (usually invalid syntax). 31372174Ssobomax */ 31472174Ssobomaxstatic int 31572174Ssobomaxrexs_match(char **patterns, char *pkgname) 31672174Ssobomax{ 31772174Ssobomax Boolean matched; 31872174Ssobomax char errbuf[128]; 31972174Ssobomax int i; 32072174Ssobomax int errcode; 32172174Ssobomax int retval; 32272174Ssobomax regex_t rex; 32372174Ssobomax 32472174Ssobomax errcode = 0; 32572174Ssobomax retval = 0; 32672174Ssobomax matched = FALSE; 32772174Ssobomax for (i = 0; patterns[i]; i++) { 32872174Ssobomax errcode = regcomp(&rex, patterns[i], REG_BASIC | REG_NOSUB); 32972174Ssobomax if (errcode != 0) 33072174Ssobomax break; 33172174Ssobomax 33272174Ssobomax errcode = regexec(&rex, pkgname, 0, NULL, 0); 33372174Ssobomax if (errcode == 0) { 33472174Ssobomax matched = TRUE; 33572174Ssobomax retval = 1; 33672174Ssobomax break; 33772174Ssobomax } 33872174Ssobomax else if (errcode != REG_NOMATCH) 33972174Ssobomax break; 34072174Ssobomax 34172174Ssobomax regfree(&rex); 34272174Ssobomax errcode = 0; 34372174Ssobomax } 34472174Ssobomax 34572174Ssobomax if (errcode != 0) { 34672174Ssobomax regerror(errcode, &rex, errbuf, sizeof(errbuf)); 34772174Ssobomax warnx("%s: %s", patterns[i], errbuf); 34872174Ssobomax retval = -1; 34972174Ssobomax } 35072174Ssobomax 35172174Ssobomax if ((errcode != 0) || (matched == TRUE)) 35272174Ssobomax regfree(&rex); 35372174Ssobomax 35472174Ssobomax return retval; 35572174Ssobomax} 356