main.c revision 229234
172847Sgshapiro/*- 250472Speter * ---------------------------------------------------------------------------- 372847Sgshapiro * "THE BEER-WARE LICENSE" (Revision 42): 472847Sgshapiro * <beat@chruetertee.ch> wrote this file. As long as you retain this notice you 572847Sgshapiro * can do whatever you want with this stuff. If we meet some day, and you think 672847Sgshapiro * this stuff is worth it, you can buy me a beer in return. Beat G�tzi 772847Sgshapiro * ---------------------------------------------------------------------------- 872847Sgshapiro */ 972847Sgshapiro 1072847Sgshapiro#include <sys/cdefs.h> 1172847Sgshapiro__FBSDID("$FreeBSD: stable/9/usr.sbin/pkg_install/updating/main.c 229234 2012-01-01 23:18:34Z dim $"); 1272847Sgshapiro 1372847Sgshapiro 1493315Sgshapiro#include <sys/param.h> 1593853Sgshapiro#include <stdio.h> 1693853Sgshapiro#include <errno.h> 1793853Sgshapiro#include <fetch.h> 1893853Sgshapiro#include <limits.h> 1993853Sgshapiro#include <sysexits.h> 2093853Sgshapiro#include <getopt.h> 2193853Sgshapiro 2293853Sgshapiro#include "lib.h" 2372847Sgshapiro#include "pathnames.h" 2493853Sgshapiro 2593853Sgshapirotypedef struct installedport { 2693853Sgshapiro struct installedport *next; /* List of installed ports. */ 2793853Sgshapiro char name[LINE_MAX]; /* Name of the installed port. */ 2893853Sgshapiro} INSTALLEDPORT; 2993853Sgshapiro 3093853Sgshapiroint usage(void); 3193315Sgshapiro 3293315Sgshapirostatic char opts[] = "d:f:h"; 3393315Sgshapirostatic struct option longopts[] = { 3493315Sgshapiro { "date", required_argument, NULL, 'd' }, 3593315Sgshapiro { "file", required_argument, NULL, 'f' }, 3672847Sgshapiro { "help", no_argument, NULL, 'h' }, 3772847Sgshapiro { NULL, 0, NULL, 0 }, 3872847Sgshapiro}; 3972847Sgshapiro 4072847Sgshapiro/* 4172847Sgshapiro * Parse /usr/port/UPDATING for corresponding entries. If no argument is 4272847Sgshapiro * passed to pkg_updating all entries for all installed ports are displayed. 4372847Sgshapiro * If a list of portnames is passed to pkg_updating only entries for the 4494676Sgshapiro * given portnames are displayed. Use the -d option to define that only newer 4594676Sgshapiro * entries as this date are shown. 4672847Sgshapiro */ 47117286Sgshapiroint 4872847Sgshapiromain(int argc, char *argv[]) 4976622Sgshapiro{ 5076622Sgshapiro /* Keyword for searching portname in UPDATING. */ 5194676Sgshapiro const char *affects = "AFFECTS"; 52117291Sgshapiro /* Indicate a date -> end of a entry. Will fail on 2100-01-01... */ 53117291Sgshapiro const char *end = "20"; 54117291Sgshapiro /* Keyword for searching origin portname of installed port. */ 5594676Sgshapiro const char *origin = "@comment ORIGIN:"; 56117286Sgshapiro const char *pkgdbpath = LOG_DIR; /* Location of pkgdb */ 57117291Sgshapiro const char *updatingfile = UPDATING; /* Location of UPDATING */ 58117291Sgshapiro 59117291Sgshapiro char *date = NULL; /* Passed -d argument */ 6072847Sgshapiro char *dateline = NULL; /* Saved date of an entry */ 6172847Sgshapiro /* Tmp lines for parsing file */ 6272847Sgshapiro char *tmpline1 = NULL; 6372847Sgshapiro char *tmpline2 = NULL; 6472847Sgshapiro 6572847Sgshapiro char originline[LINE_MAX]; /* Line of +CONTENTS */ 6639146Sbrian /* Temporary variable to create path to +CONTENTS for installed ports. */ 6776622Sgshapiro char tmp_file[MAXPATHLEN]; 6876622Sgshapiro char updatingline[LINE_MAX]; /* Line of UPDATING */ 6976622Sgshapiro 7076622Sgshapiro int ch; /* Char used by getopt */ 7184684Sgshapiro int found = 0; /* Found an entry */ 72277273Swill int linelength; /* Length of parsed line */ 7376622Sgshapiro int maxcharperline = LINE_MAX; /* Max chars per line */ 7476622Sgshapiro int dflag = 0; /* -d option set */ 75117291Sgshapiro /* If pflag = 0 UPDATING will be checked for all installed ports. */ 76117291Sgshapiro int pflag = 0; 77130157Sgshapiro 7894676Sgshapiro size_t n; /* Offset to create path */ 79117291Sgshapiro 80277273Swill struct dirent *pkgdbdir; /* pkgdb directory */ 81117291Sgshapiro struct stat attribute; /* attribute of pkgdb element */ 82117291Sgshapiro 8373209Sgshapiro /* Needed nodes for linked list with installed ports. */ 8430581Sjmb INSTALLEDPORT *head = (INSTALLEDPORT *) NULL; 8594676Sgshapiro INSTALLEDPORT *curr = (INSTALLEDPORT *) NULL; 8694676Sgshapiro 8794676Sgshapiro DIR *dir; 8894676Sgshapiro FILE *fd; 8972847Sgshapiro 9057947Srwatson while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) { 9172847Sgshapiro switch (ch) { 9272847Sgshapiro case 'd': 9372847Sgshapiro dflag = 1; 9472847Sgshapiro date = optarg; 9572847Sgshapiro break; 9672847Sgshapiro case 'f': 9793765Sru updatingfile = optarg; 9893765Sru break; 9972847Sgshapiro case 'h': 10057947Srwatson default: 10172847Sgshapiro usage(); 10293853Sgshapiro } 10372847Sgshapiro } 10493853Sgshapiro argc -= optind; 10557947Srwatson argv += optind; 10672847Sgshapiro 10772847Sgshapiro /* Check if passed date has a correct format. */ 10872847Sgshapiro if (dflag == 1) { 10972847Sgshapiro linelength = strlen(date); 11072847Sgshapiro if (linelength != 8) 11172847Sgshapiro exit(EX_DATAERR); 11264567Sgshapiro if (strspn(date, "0123456789") != 8) { 11397200Sgshapiro fprintf(stderr, "unknown date format: %s\n", date); 11497200Sgshapiro exit(EX_DATAERR); 11597200Sgshapiro } 11672847Sgshapiro } 117117286Sgshapiro 11857947Srwatson /* Save the list of passed portnames. */ 11972847Sgshapiro if (argc != 0) { 12072847Sgshapiro pflag = 1; 12172847Sgshapiro while (*argv) { 12272847Sgshapiro if ((curr = (INSTALLEDPORT *) 12372847Sgshapiro malloc(sizeof(INSTALLEDPORT))) == NULL) 12475074Sgshapiro (void)exit(EXIT_FAILURE); 12575074Sgshapiro strlcpy(curr->name, *argv, strlen(*argv) + 1); 12672847Sgshapiro curr->next = head; 12772847Sgshapiro head = curr; 12875073Sgshapiro (void)*argv++; 12972847Sgshapiro } 13075074Sgshapiro } 13157947Srwatson 13275073Sgshapiro /* 13372847Sgshapiro * UPDATING will be parsed for all installed ports 13472847Sgshapiro * if no portname is passed. 13572847Sgshapiro */ 13672847Sgshapiro if (pflag == 0) { 13757947Srwatson /* Open /var/db/pkg and search for all installed ports. */ 13872847Sgshapiro if ((dir = opendir(pkgdbpath)) != NULL) { 13972847Sgshapiro while ((pkgdbdir = readdir(dir)) != NULL) { 14072847Sgshapiro if (strcmp(pkgdbdir->d_name, ".") != 0 && 14172847Sgshapiro strcmp(pkgdbdir->d_name, "..") != 0) { 14272847Sgshapiro 143117286Sgshapiro /* Create path to +CONTENTS file for each installed port */ 14472847Sgshapiro n = strlcpy(tmp_file, pkgdbpath, sizeof(tmp_file)); 14572847Sgshapiro n = strlcpy(tmp_file + n, "/", sizeof(tmp_file) - n); 14672847Sgshapiro n = strlcat(tmp_file + n, pkgdbdir->d_name, 147117286Sgshapiro sizeof(tmp_file) - n); 14875074Sgshapiro if (stat(tmp_file, &attribute) == -1) { 14997200Sgshapiro fprintf(stderr, "can't open %s: %s\n", 15072847Sgshapiro tmp_file, strerror(errno)); 15172847Sgshapiro return EXIT_FAILURE; 152117286Sgshapiro } 15375073Sgshapiro if (attribute.st_mode & S_IFREG) 15497200Sgshapiro continue; 15575073Sgshapiro (void)strlcat(tmp_file + n, "/", 15675073Sgshapiro sizeof(tmp_file) - n); 15772847Sgshapiro (void)strlcat(tmp_file + n, CONTENTS_FNAME, 15872847Sgshapiro sizeof(tmp_file) - n); 15972847Sgshapiro 16072847Sgshapiro /* Open +CONTENT file */ 16172847Sgshapiro fd = fopen(tmp_file, "r"); 16272847Sgshapiro if (fd == NULL) { 16372847Sgshapiro fprintf(stderr, "warning: can't open %s: %s\n", 16472847Sgshapiro tmp_file, strerror(errno)); 165117286Sgshapiro continue; 16672847Sgshapiro } 167117286Sgshapiro 16880175Sgshapiro /* 169117286Sgshapiro * Parses +CONTENT for ORIGIN line and 17072847Sgshapiro * put element into linked list. 17172847Sgshapiro */ 17272847Sgshapiro while (fgets(originline, maxcharperline, fd) != NULL) { 17372847Sgshapiro tmpline1 = strstr(originline, origin); 17472847Sgshapiro if (tmpline1 != NULL) { 175110576Sgshapiro /* Tmp variable to store port name. */ 176117286Sgshapiro char *pname; 177110576Sgshapiro pname = strrchr(originline, (int)':'); 17897200Sgshapiro pname++; 179110576Sgshapiro if ((curr = (INSTALLEDPORT *) 18072847Sgshapiro malloc(sizeof(INSTALLEDPORT))) == NULL) 18172847Sgshapiro (void)exit(EXIT_FAILURE); 18272847Sgshapiro if (pname[strlen(pname) - 1] == '\n') 18372847Sgshapiro pname[strlen(pname) - 1] = '\0'; 18472847Sgshapiro strlcpy (curr->name, pname, sizeof(curr->name)); 185117286Sgshapiro curr->next = head; 18672847Sgshapiro head = curr; 18757947Srwatson } 18872847Sgshapiro } 18972847Sgshapiro 19072847Sgshapiro if (ferror(fd)) { 191117286Sgshapiro fprintf(stderr, "error reading input\n"); 19272847Sgshapiro exit(EX_IOERR); 19390806Sgshapiro } 19494676Sgshapiro 19594676Sgshapiro (void)fclose(fd); 19694676Sgshapiro } 19794676Sgshapiro } 19894676Sgshapiro closedir(dir); 199117286Sgshapiro } 20094676Sgshapiro } 201100872Sru 20294676Sgshapiro /* Fetch UPDATING file if needed and open file */ 20394676Sgshapiro if (isURL(updatingfile)) { 20494676Sgshapiro if ((fd = fetchGetURL(updatingfile, "")) == NULL) { 205117286Sgshapiro fprintf(stderr, "Error: Unable to get %s: %s\n", 20694676Sgshapiro updatingfile, fetchLastErrString); 20790806Sgshapiro exit(EX_UNAVAILABLE); 20890806Sgshapiro } 20990806Sgshapiro } 21090806Sgshapiro else { 21194676Sgshapiro fd = fopen(updatingfile, "r"); 21294676Sgshapiro } 213100872Sru if (fd == NULL) { 21490806Sgshapiro fprintf(stderr, "can't open %s: %s\n", 21594676Sgshapiro updatingfile, strerror(errno)); 21690806Sgshapiro exit(EX_UNAVAILABLE); 217117286Sgshapiro } 21872847Sgshapiro 219117286Sgshapiro /* Parse opened UPDATING file. */ 22072847Sgshapiro while (fgets(updatingline, maxcharperline, fd) != NULL) { 22193853Sgshapiro /* No entry is found so far */ 22293853Sgshapiro if (found == 0) { 22393853Sgshapiro /* Search for AFFECTS line to parse the portname. */ 22493853Sgshapiro tmpline1 = strstr(updatingline, affects); 22593853Sgshapiro 22693853Sgshapiro if (tmpline1 != NULL) { 22772847Sgshapiro curr = head; 22893853Sgshapiro while (curr != NULL) { 22993853Sgshapiro tmpline2 = strstr(updatingline, curr->name); 23093853Sgshapiro if (tmpline2 != NULL) 23193853Sgshapiro break; 23293853Sgshapiro curr = curr->next; 23393853Sgshapiro } 23472847Sgshapiro if (tmpline2 != NULL) { 23593853Sgshapiro /* If -d is set, check if entry is newer than the date. */ 23693853Sgshapiro if ((dflag == 1) && (strncmp(dateline, date, 8) < 0)) 23793853Sgshapiro continue; 23893853Sgshapiro printf("%s", dateline); 23993853Sgshapiro printf("%s", updatingline); 24093853Sgshapiro found = 1; 24176623Sgshapiro } 24276623Sgshapiro } 24376623Sgshapiro } 24476623Sgshapiro /* Search for the end of an entry, if not found print the line. */ 24576623Sgshapiro else { 24695317Sgshapiro tmpline1 = strstr(updatingline, end); 24795317Sgshapiro if (tmpline1 == NULL) 24895317Sgshapiro printf("%s", updatingline); 249 else { 250 linelength = strlen(updatingline); 251 if (linelength == 10) 252 found = 0; 253 else 254 printf("%s", updatingline); 255 } 256 } 257 /* Save the actual line, it could be a date. */ 258 dateline = strdup(updatingline); 259 } 260 261 if (ferror(fd)) { 262 fprintf(stderr, "error reading input\n"); 263 exit(EX_IOERR); 264 } 265 (void)fclose(fd); 266 267 exit(EX_OK); 268} 269 270int 271usage(void) 272{ 273 fprintf(stderr, 274 "usage: pkg_updating [-h] [-d YYYYMMDD] [-f file] [portname ...]\n"); 275 exit(EX_USAGE); 276} 277 278void 279cleanup(int sig) 280{ 281 if (sig) 282 exit(1); 283} 284