1327Sjkh/* 2228990Suqs * FreeBSD install - a package for the installation and maintenance 3327Sjkh * of non-core utilities. 4327Sjkh * 5327Sjkh * Redistribution and use in source and binary forms, with or without 6327Sjkh * modification, are permitted provided that the following conditions 7327Sjkh * are met: 8327Sjkh * 1. Redistributions of source code must retain the above copyright 9327Sjkh * notice, this list of conditions and the following disclaimer. 10327Sjkh * 2. Redistributions in binary form must reproduce the above copyright 11327Sjkh * notice, this list of conditions and the following disclaimer in the 12327Sjkh * documentation and/or other materials provided with the distribution. 13327Sjkh * 14327Sjkh * Jordan K. Hubbard 15327Sjkh * 23 Aug 1993 16327Sjkh * 17327Sjkh * Various display routines for the info module. 18327Sjkh * 19327Sjkh */ 20327Sjkh 2193520Sobrien#include <sys/cdefs.h> 2293520Sobrien__FBSDID("$FreeBSD$"); 2393520Sobrien 24222035Sflz#include "lib.h" 25327Sjkh#include "info.h" 2649637Sbillf#include <err.h> 2762775Ssobomax#include <stdlib.h> 2862775Ssobomax#include <sys/types.h> 2962775Ssobomax#include <sys/stat.h> 3071965Sjkh#include <md5.h> 3149637Sbillf 32327Sjkhvoid 3384745Ssobomaxshow_file(const char *title, const char *fname) 34327Sjkh{ 35327Sjkh FILE *fp; 36327Sjkh char line[1024]; 37327Sjkh int n; 38327Sjkh 39411Sjkh if (!Quiet) 40411Sjkh printf("%s%s", InfoPrefix, title); 41327Sjkh fp = fopen(fname, "r"); 42115324Slioux if (fp == (FILE *) NULL) 439781Sache printf("ERROR: show_file: Can't open '%s' for reading!\n", fname); 449781Sache else { 45115324Slioux int append_nl = 0; 4616549Sjkh while ((n = fread(line, 1, 1024, fp)) != 0) 479781Sache fwrite(line, 1, n, stdout); 489781Sache fclose(fp); 49115324Slioux append_nl = (line[n - 1] != '\n'); /* Do we have a trailing \n ? */ 50115324Slioux if (append_nl) 51115324Slioux printf("\n"); 52327Sjkh } 53327Sjkh printf("\n"); /* just in case */ 54327Sjkh} 55327Sjkh 565399Sswallacevoid 5784745Ssobomaxshow_index(const char *title, const char *fname) 585399Sswallace{ 595399Sswallace FILE *fp; 605399Sswallace char line[MAXINDEXSIZE+2]; 618857Srgrimes 62115324Slioux strlcpy(line, "???\n", sizeof(line)); 63115324Slioux 64240682Sbapt if (!Quiet) { 655399Sswallace printf("%s%s", InfoPrefix, title); 66240682Sbapt fflush(stdout); 67240682Sbapt } 685399Sswallace fp = fopen(fname, "r"); 69115324Slioux if (fp == (FILE *) NULL) { 7030221Scharnier warnx("show_file: can't open '%s' for reading", fname); 71115324Slioux } else { 72115324Slioux if(fgets(line, MAXINDEXSIZE + 1, fp)) { 73115324Slioux size_t line_length = strlen(line); 74115324Slioux 75115324Slioux if (line[line_length - 1] != '\n') { /* Do we have a trailing \n ? */ 76115324Slioux line[line_length] = '\n'; /* Add a trailing \n */ 77115324Slioux line[line_length + 1] = '\0'; /* Terminate string */ 78115324Slioux } 79115324Slioux } 80115324Slioux fclose(fp); 818857Srgrimes } 82115324Slioux fputs(line, stdout); 838857Srgrimes} 845399Sswallace 8584745Ssobomax/* Show a packing list item type. If showall is TRUE, show all */ 86327Sjkhvoid 8784745Ssobomaxshow_plist(const char *title, Package *plist, plist_t type, Boolean showall) 88327Sjkh{ 89327Sjkh PackingList p; 90327Sjkh Boolean ign = FALSE; 91154102Skrion char *prefix = NULL; 92327Sjkh 93240682Sbapt if (!Quiet) { 94411Sjkh printf("%s%s", InfoPrefix, title); 95240682Sbapt fflush(stdout); 96240682Sbapt } 97327Sjkh p = plist->head; 98327Sjkh while (p) { 9984745Ssobomax if (p->type != type && showall != TRUE) { 100327Sjkh p = p->next; 101327Sjkh continue; 102327Sjkh } 103327Sjkh switch(p->type) { 104327Sjkh case PLIST_FILE: 105327Sjkh if (ign) { 106411Sjkh printf(Quiet ? "%s\n" : "File: %s (ignored)\n", p->name); 107327Sjkh ign = FALSE; 108327Sjkh } 109327Sjkh else 110411Sjkh printf(Quiet ? "%s\n" : "File: %s\n", p->name); 111327Sjkh break; 1128857Srgrimes 113327Sjkh case PLIST_CWD: 114154102Skrion if (!prefix) 115154102Skrion prefix = p->name; 116154102Skrion printf(Quiet ? "@cwd %s\n" : "\tCWD to %s\n", (p->name == NULL) ? prefix : p->name); 117327Sjkh break; 118327Sjkh 1194996Sjkh case PLIST_SRC: 1204996Sjkh printf(Quiet ? "@srcdir %s\n" : "\tSRCDIR to %s\n", p->name); 1214996Sjkh break; 1224996Sjkh 123327Sjkh case PLIST_CMD: 124411Sjkh printf(Quiet ? "@exec %s\n" : "\tEXEC '%s'\n", p->name); 125327Sjkh break; 126327Sjkh 12730531Sjkh case PLIST_UNEXEC: 12830531Sjkh printf(Quiet ? "@unexec %s\n" : "\tUNEXEC '%s'\n", p->name); 12930531Sjkh break; 13030531Sjkh 131327Sjkh case PLIST_CHMOD: 132411Sjkh printf(Quiet ? "@chmod %s\n" : "\tCHMOD to %s\n", 133411Sjkh p->name ? p->name : "(clear default)"); 134327Sjkh break; 135327Sjkh 136327Sjkh case PLIST_CHOWN: 137411Sjkh printf(Quiet ? "@chown %s\n" : "\tCHOWN to %s\n", 138411Sjkh p->name ? p->name : "(clear default)"); 139327Sjkh break; 140327Sjkh 141327Sjkh case PLIST_CHGRP: 142411Sjkh printf(Quiet ? "@chgrp %s\n" : "\tCHGRP to %s\n", 143411Sjkh p->name ? p->name : "(clear default)"); 144327Sjkh break; 145327Sjkh 146327Sjkh case PLIST_COMMENT: 147411Sjkh printf(Quiet ? "@comment %s\n" : "\tComment: %s\n", p->name); 148327Sjkh break; 149327Sjkh 150147381Skrion case PLIST_NOINST: 151147381Skrion printf(Quiet ? "@noinst %s\n" : "\tNot installed: %s\n", p->name); 152147381Skrion break; 153147381Skrion 154327Sjkh case PLIST_IGNORE: 155327Sjkh ign = TRUE; 156327Sjkh break; 157327Sjkh 1584996Sjkh case PLIST_IGNORE_INST: 1594996Sjkh printf(Quiet ? "@ignore_inst ??? doesn't belong here.\n" : 1604996Sjkh "\tIgnore next file installation directive (doesn't belong)\n"); 1614996Sjkh ign = TRUE; 1624996Sjkh break; 1634996Sjkh 164327Sjkh case PLIST_NAME: 165411Sjkh printf(Quiet ? "@name %s\n" : "\tPackage name: %s\n", p->name); 166327Sjkh break; 167327Sjkh 1684996Sjkh case PLIST_DISPLAY: 1694996Sjkh printf(Quiet ? "@display %s\n" : "\tInstall message file: %s\n", p->name); 1704996Sjkh break; 1714996Sjkh 1724996Sjkh case PLIST_PKGDEP: 17396076Ssobomax printf(Quiet ? "@pkgdep %s\n" : "Dependency: %s\n", p->name); 1744996Sjkh break; 1754996Sjkh 17696076Ssobomax case PLIST_DEPORIGIN: 17796076Ssobomax printf(Quiet ? "@comment DEPORIGIN:%s\n" : 17896076Ssobomax "\tdependency origin: %s\n", p->name); 17996076Ssobomax break; 18096076Ssobomax 181113594Skris case PLIST_CONFLICTS: 182113594Skris printf(Quiet ? "@conflicts %s\n" : "Conflicts: %s\n", p->name); 183113594Skris break; 184113594Skris 1854996Sjkh case PLIST_MTREE: 1864996Sjkh printf(Quiet ? "@mtree %s\n" : "\tPackage mtree file: %s\n", p->name); 1874996Sjkh break; 1884996Sjkh 1894996Sjkh case PLIST_DIR_RM: 1904996Sjkh printf(Quiet ? "@dirrm %s\n" : "\tDeinstall directory remove: %s\n", p->name); 1914996Sjkh break; 1924996Sjkh 19381218Skris case PLIST_OPTION: 19481218Skris printf(Quiet ? "@option %s\n" : 19581218Skris "\tOption \"%s\" controlling package installation behaviour\n", 19681218Skris p->name); 19781218Skris break; 19881218Skris 19996065Ssobomax case PLIST_ORIGIN: 20096065Ssobomax printf(Quiet ? "@comment ORIGIN:%s\n" : 20196065Ssobomax "\tPackage origin: %s\n", p->name); 20296065Ssobomax break; 20396065Ssobomax 204327Sjkh default: 20530221Scharnier cleanup(0); 20696388Salfred errx(2, "%s: unknown command type %d (%s)", 20796392Salfred __func__, p->type, p->name); 208327Sjkh break; 209327Sjkh } 210327Sjkh p = p->next; 211327Sjkh } 212327Sjkh} 213327Sjkh 214226708Sdelphijstatic const char * 215226697Semasteelide_root(const char *dir) 216226697Semaste{ 217226697Semaste if (strcmp(dir, "/") == 0) 218226697Semaste return ""; 219226697Semaste return dir; 220226697Semaste} 221226697Semaste 222411Sjkh/* Show all files in the packing list (except ignored ones) */ 223411Sjkhvoid 22484745Ssobomaxshow_files(const char *title, Package *plist) 225411Sjkh{ 226411Sjkh PackingList p; 227411Sjkh Boolean ign = FALSE; 228166552Spav char *prefix = NULL; 22984745Ssobomax const char *dir = "."; 230411Sjkh 231411Sjkh if (!Quiet) 232411Sjkh printf("%s%s", InfoPrefix, title); 233411Sjkh p = plist->head; 234411Sjkh while (p) { 235411Sjkh switch(p->type) { 236411Sjkh case PLIST_FILE: 237411Sjkh if (!ign) 238226697Semaste printf("%s/%s\n", elide_root(dir), p->name); 239411Sjkh ign = FALSE; 240411Sjkh break; 2418857Srgrimes 242411Sjkh case PLIST_CWD: 243166552Spav if (!prefix) 244166552Spav prefix = p->name; 245166552Spav if (p->name == NULL) 246166552Spav dir = prefix; 247166552Spav else 248166552Spav dir = p->name; 249411Sjkh break; 250411Sjkh 251411Sjkh case PLIST_IGNORE: 252411Sjkh ign = TRUE; 253411Sjkh break; 25462775Ssobomax 25562775Ssobomax /* Silence GCC in the -Wall mode */ 25662775Ssobomax default: 25762775Ssobomax break; 258411Sjkh } 259411Sjkh p = p->next; 260411Sjkh } 261411Sjkh} 26262775Ssobomax 26362775Ssobomax/* Calculate and show size of all installed package files (except ignored ones) */ 26462775Ssobomaxvoid 26584745Ssobomaxshow_size(const char *title, Package *plist) 26662775Ssobomax{ 26762775Ssobomax PackingList p; 26862775Ssobomax Boolean ign = FALSE; 26984745Ssobomax const char *dir = "."; 27062775Ssobomax struct stat sb; 27162775Ssobomax char tmp[FILENAME_MAX]; 27262775Ssobomax unsigned long size = 0; 27362775Ssobomax long blksize; 274108455Smike int headerlen; 27562775Ssobomax char *descr; 276166552Spav char *prefix = NULL; 27762775Ssobomax 27862775Ssobomax descr = getbsize(&headerlen, &blksize); 279240682Sbapt if (!Quiet) { 28062775Ssobomax printf("%s%s", InfoPrefix, title); 281240682Sbapt fflush(stdout); 282240682Sbapt } 28362775Ssobomax for (p = plist->head; p != NULL; p = p->next) { 28462775Ssobomax switch (p->type) { 28562775Ssobomax case PLIST_FILE: 28662775Ssobomax if (!ign) { 287226697Semaste snprintf(tmp, FILENAME_MAX, "%s/%s", elide_root(dir), p->name); 28862775Ssobomax if (!lstat(tmp, &sb)) { 28962775Ssobomax size += sb.st_size; 29062775Ssobomax if (Verbose) 29162775Ssobomax printf("%lu\t%s\n", (unsigned long) howmany(sb.st_size, blksize), tmp); 29262775Ssobomax } 29362775Ssobomax } 29462775Ssobomax ign = FALSE; 29562775Ssobomax break; 29662775Ssobomax 29762775Ssobomax case PLIST_CWD: 298166552Spav if (!prefix) 299166552Spav prefix = p->name; 300166552Spav if (p->name == NULL) 301166552Spav dir = prefix; 302166552Spav else 303166552Spav dir = p->name; 30462775Ssobomax break; 30562775Ssobomax 30662775Ssobomax case PLIST_IGNORE: 30762775Ssobomax ign = TRUE; 30862775Ssobomax break; 30962775Ssobomax 31062775Ssobomax /* Silence GCC in the -Wall mode */ 31162775Ssobomax default: 31262775Ssobomax break; 31362775Ssobomax } 31462775Ssobomax } 31562775Ssobomax if (!Quiet) 31662775Ssobomax printf("%lu\t(%s)\n", howmany(size, blksize), descr); 31762775Ssobomax else 318112579Smdodd if (UseBlkSz) 319112579Smdodd printf("%lu\n", howmany(size, blksize)); 320112579Smdodd else 321112579Smdodd printf("%lu\n", size); 32262775Ssobomax} 32367454Ssobomax 32471965Sjkh/* Show files that don't match the recorded checksum */ 325240682Sbaptint 32684745Ssobomaxshow_cksum(const char *title, Package *plist) 32771965Sjkh{ 32871965Sjkh PackingList p; 32984745Ssobomax const char *dir = "."; 330166552Spav char *prefix = NULL; 33171965Sjkh char tmp[FILENAME_MAX]; 332240682Sbapt int errcode = 0; 33371965Sjkh 334240682Sbapt if (!Quiet) { 33571965Sjkh printf("%s%s", InfoPrefix, title); 336240682Sbapt fflush(stdout); 337240682Sbapt } 33871965Sjkh 33971965Sjkh for (p = plist->head; p != NULL; p = p->next) 340166552Spav if (p->type == PLIST_CWD) { 341166552Spav if (!prefix) 342166552Spav prefix = p->name; 343166552Spav if (p->name == NULL) 344166552Spav dir = prefix; 345166552Spav else 346166552Spav dir = p->name; 347166552Spav } else if (p->type == PLIST_FILE) { 348226697Semaste snprintf(tmp, FILENAME_MAX, "%s/%s", elide_root(dir), p->name); 349240682Sbapt if (!fexists(tmp)) { 350150522Skrion warnx("%s doesn't exist", tmp); 351240682Sbapt errcode = 1; 352240682Sbapt } else if (p->next && p->next->type == PLIST_COMMENT && 35395933Ssobomax (strncmp(p->next->name, "MD5:", 4) == 0)) { 35495933Ssobomax char *cp = NULL, buf[33]; 35595933Ssobomax 35695933Ssobomax /* 35795933Ssobomax * For packing lists whose version is 1.1 or greater, the md5 35895933Ssobomax * hash for a symlink is calculated on the string returned 35995933Ssobomax * by readlink(). 36095933Ssobomax */ 36195933Ssobomax if (issymlink(tmp) && verscmp(plist, 1, 0) > 0) { 36295933Ssobomax int len; 36395933Ssobomax char linkbuf[FILENAME_MAX]; 36495933Ssobomax 36595933Ssobomax if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0) 36695933Ssobomax cp = MD5Data((unsigned char *)linkbuf, len, buf); 36795933Ssobomax } else if (isfile(tmp) || verscmp(plist, 1, 1) < 0) 36895933Ssobomax cp = MD5File(tmp, buf); 36995933Ssobomax 37095933Ssobomax if (cp != NULL) { 37195933Ssobomax /* Mismatch? */ 37271965Sjkh if (strcmp(cp, p->next->name + 4)) 37371965Sjkh printf("%s fails the original MD5 checksum\n", tmp); 37471965Sjkh else if (Verbose) 37571965Sjkh printf("%s matched the original MD5 checksum\n", tmp); 37672034Ssobomax } 37771965Sjkh } 37871965Sjkh } 379240682Sbapt return (errcode); 38071965Sjkh} 38171965Sjkh 38267454Ssobomax/* Show an "origin" path (usually category/portname) */ 38367454Ssobomaxvoid 38484745Ssobomaxshow_origin(const char *title, Package *plist) 38567454Ssobomax{ 38667454Ssobomax 387240682Sbapt if (!Quiet) { 38867454Ssobomax printf("%s%s", InfoPrefix, title); 389240682Sbapt fflush(stdout); 390240682Sbapt } 39196030Ssobomax printf("%s\n", plist->origin != NULL ? plist->origin : ""); 39267454Ssobomax} 39384750Ssobomax 39484750Ssobomax/* Show revision number of the packing list */ 39584750Ssobomaxvoid 39684750Ssobomaxshow_fmtrev(const char *title, Package *plist) 39784750Ssobomax{ 39896030Ssobomax 399240682Sbapt if (!Quiet) { 40084750Ssobomax printf("%s%s", InfoPrefix, title); 401240682Sbapt fflush(stdout); 402240682Sbapt } 40384750Ssobomax printf("%d.%d\n", plist->fmtver_maj, plist->fmtver_mnr); 40484750Ssobomax} 405