main.c revision 256281
1250079Scarl/*- 2302484Smav * ---------------------------------------------------------------------------- 3250079Scarl * "THE BEER-WARE LICENSE" (Revision 42): 4289542Scem * <beat@chruetertee.ch> wrote this file. As long as you retain this notice you 5250079Scarl * can do whatever you want with this stuff. If we meet some day, and you think 6250079Scarl * this stuff is worth it, you can buy me a beer in return. Beat G��tzi 7250079Scarl * ---------------------------------------------------------------------------- 8250079Scarl */ 9250079Scarl 10250079Scarl#include <sys/cdefs.h> 11250079Scarl__FBSDID("$FreeBSD: stable/10/usr.sbin/pkg_install/updating/main.c 241830 2012-10-22 02:12:20Z eadler $"); 12250079Scarl 13250079Scarl 14250079Scarl#include <sys/param.h> 15250079Scarl#include <stdio.h> 16250079Scarl#include <errno.h> 17250079Scarl#include <fetch.h> 18250079Scarl#include <limits.h> 19250079Scarl#include <sysexits.h> 20250079Scarl#include <getopt.h> 21250079Scarl 22250079Scarl#include "lib.h" 23250079Scarl#include "pathnames.h" 24250079Scarl 25250079Scarltypedef struct installedport { 26250079Scarl struct installedport *next; /* List of installed ports. */ 27250079Scarl char name[LINE_MAX]; /* Name of the installed port. */ 28250079Scarl} INSTALLEDPORT; 29302484Smav 30302484Smavint usage(void); 31302484Smav 32302484Smavstatic char opts[] = "d:f:h"; 33302484Smavstatic struct option longopts[] = { 34302484Smav { "date", required_argument, NULL, 'd' }, 35302484Smav { "file", required_argument, NULL, 'f' }, 36302484Smav { "help", no_argument, NULL, 'h' }, 37302484Smav { NULL, 0, NULL, 0 }, 38302484Smav}; 39250079Scarl 40250079Scarl/* 41250079Scarl * Parse /usr/port/UPDATING for corresponding entries. If no argument is 42250079Scarl * passed to pkg_updating all entries for all installed ports are displayed. 43250079Scarl * If a list of portnames is passed to pkg_updating only entries for the 44250079Scarl * given portnames are displayed. Use the -d option to define that only newer 45250079Scarl * entries as this date are shown. 46289774Scem */ 47302493Smavint 48250079Scarlmain(int argc, char *argv[]) 49250079Scarl{ 50295618Scem /* Keyword for searching portname in UPDATING. */ 51295618Scem const char *affects = "AFFECTS"; 52250079Scarl /* Indicate a date -> end of a entry. Will fail on 2100-01-01... */ 53250079Scarl const char *end = "20"; 54289774Scem /* Keyword for searching origin portname of installed port. */ 55289207Scem const char *origin = "@comment ORIGIN:"; 56250079Scarl const char *pkgdbpath = LOG_DIR; /* Location of pkgdb */ 57250079Scarl const char *updatingfile = UPDATING; /* Location of UPDATING */ 58250079Scarl 59295618Scem char *date = NULL; /* Passed -d argument */ 60250079Scarl char *dateline = NULL; /* Saved date of an entry */ 61250079Scarl /* Tmp lines for parsing file */ 62250079Scarl char *tmpline1 = NULL; 63250079Scarl char *tmpline2 = NULL; 64323032Smav 65302484Smav char originline[LINE_MAX]; /* Line of +CONTENTS */ 66250079Scarl /* Temporary variable to create path to +CONTENTS for installed ports. */ 67289648Scem char tmp_file[MAXPATHLEN]; 68250079Scarl char updatingline[LINE_MAX]; /* Line of UPDATING */ 69289539Scem 70289648Scem int ch; /* Char used by getopt */ 71291032Scem int found = 0; /* Found an entry */ 72250079Scarl int linelength; /* Length of parsed line */ 73295618Scem int maxcharperline = LINE_MAX; /* Max chars per line */ 74295618Scem int dflag = 0; /* -d option set */ 75295618Scem /* If pflag = 0 UPDATING will be checked for all installed ports. */ 76295618Scem int pflag = 0; 77295618Scem 78295618Scem size_t n; /* Offset to create path */ 79295618Scem 80295618Scem struct dirent *pkgdbdir; /* pkgdb directory */ 81295618Scem struct stat attribute; /* attribute of pkgdb element */ 82295618Scem 83295618Scem /* Needed nodes for linked list with installed ports. */ 84295618Scem INSTALLEDPORT *head = (INSTALLEDPORT *) NULL; 85250079Scarl INSTALLEDPORT *curr = (INSTALLEDPORT *) NULL; 86250079Scarl 87289648Scem DIR *dir; 88250079Scarl FILE *fd; 89250079Scarl 90289610Scem warnpkgng(); 91289610Scem while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) { 92289610Scem switch (ch) { 93289610Scem case 'd': 94289610Scem dflag = 1; 95289610Scem date = optarg; 96289610Scem break; 97289610Scem case 'f': 98289610Scem updatingfile = optarg; 99289610Scem break; 100289610Scem case 'h': 101289610Scem default: 102289539Scem usage(); 103289539Scem } 104289539Scem } 105289539Scem argc -= optind; 106289539Scem argv += optind; 107289539Scem 108289539Scem /* Check if passed date has a correct format. */ 109289539Scem if (dflag == 1) { 110295618Scem linelength = strlen(date); 111295618Scem if (linelength != 8) 112295618Scem exit(EX_DATAERR); 113295618Scem if (strspn(date, "0123456789") != 8) { 114295618Scem fprintf(stderr, "unknown date format: %s\n", date); 115295618Scem exit(EX_DATAERR); 116295618Scem } 117295618Scem } 118295618Scem 119295618Scem /* Save the list of passed portnames. */ 120295618Scem if (argc != 0) { 121295618Scem pflag = 1; 122255274Scarl while (*argv) { 123302484Smav if ((curr = (INSTALLEDPORT *) 124302484Smav malloc(sizeof(INSTALLEDPORT))) == NULL) 125255274Scarl (void)exit(EXIT_FAILURE); 126250079Scarl strlcpy(curr->name, *argv, strlen(*argv) + 1); 127250079Scarl curr->next = head; 128255274Scarl head = curr; 129250079Scarl (void)*argv++; 130289397Scem } 131250079Scarl } 132250079Scarl 133250079Scarl /* 134250079Scarl * UPDATING will be parsed for all installed ports 135250079Scarl * if no portname is passed. 136250079Scarl */ 137250079Scarl if (pflag == 0) { 138250079Scarl /* Open /var/db/pkg and search for all installed ports. */ 139290679Scem if ((dir = opendir(pkgdbpath)) != NULL) { 140290679Scem while ((pkgdbdir = readdir(dir)) != NULL) { 141291280Scem if (strcmp(pkgdbdir->d_name, ".") != 0 && 142289543Scem strcmp(pkgdbdir->d_name, "..") != 0) { 143289543Scem 144289543Scem /* Create path to +CONTENTS file for each installed port */ 145289543Scem n = strlcpy(tmp_file, pkgdbpath, sizeof(tmp_file)); 146289543Scem n = strlcpy(tmp_file + n, "/", sizeof(tmp_file) - n); 147250079Scarl n = strlcat(tmp_file + n, pkgdbdir->d_name, 148250079Scarl sizeof(tmp_file) - n); 149250079Scarl if (stat(tmp_file, &attribute) == -1) { 150250079Scarl fprintf(stderr, "can't open %s: %s\n", 151250079Scarl tmp_file, strerror(errno)); 152250079Scarl return EXIT_FAILURE; 153250079Scarl } 154250079Scarl if (attribute.st_mode & S_IFREG) 155289546Scem continue; 156250079Scarl (void)strlcat(tmp_file + n, "/", 157289546Scem sizeof(tmp_file) - n); 158295618Scem (void)strlcat(tmp_file + n, CONTENTS_FNAME, 159250079Scarl sizeof(tmp_file) - n); 160250079Scarl 161289542Scem /* Open +CONTENT file */ 162289542Scem fd = fopen(tmp_file, "r"); 163289542Scem if (fd == NULL) { 164289542Scem fprintf(stderr, "warning: can't open %s: %s\n", 165289542Scem tmp_file, strerror(errno)); 166289542Scem continue; 167289542Scem } 168289542Scem 169289542Scem /* 170289542Scem * Parses +CONTENT for ORIGIN line and 171289542Scem * put element into linked list. 172289542Scem */ 173289542Scem while (fgets(originline, maxcharperline, fd) != NULL) { 174289542Scem tmpline1 = strstr(originline, origin); 175289546Scem if (tmpline1 != NULL) { 176289546Scem /* Tmp variable to store port name. */ 177289546Scem char *pname; 178289546Scem pname = strrchr(originline, (int)':'); 179289546Scem pname++; 180289546Scem if ((curr = (INSTALLEDPORT *) 181289546Scem malloc(sizeof(INSTALLEDPORT))) == NULL) 182289546Scem (void)exit(EXIT_FAILURE); 183289546Scem if (pname[strlen(pname) - 1] == '\n') 184289546Scem pname[strlen(pname) - 1] = '\0'; 185289546Scem strlcpy (curr->name, pname, sizeof(curr->name)); 186289546Scem curr->next = head; 187289542Scem head = curr; 188289542Scem } 189289542Scem } 190289542Scem 191289542Scem if (ferror(fd)) { 192289542Scem fprintf(stderr, "error reading input\n"); 193289542Scem exit(EX_IOERR); 194289542Scem } 195289542Scem 196289542Scem (void)fclose(fd); 197295618Scem } 198295618Scem } 199295618Scem closedir(dir); 200295618Scem } 201295618Scem } 202250079Scarl 203303429Smav /* Fetch UPDATING file if needed and open file */ 204303429Smav if (isURL(updatingfile)) { 205303429Smav if ((fd = fetchGetURL(updatingfile, "")) == NULL) { 206250079Scarl fprintf(stderr, "Error: Unable to get %s: %s\n", 207250079Scarl updatingfile, fetchLastErrString); 208289774Scem exit(EX_UNAVAILABLE); 209250079Scarl } 210250079Scarl } 211250079Scarl else { 212250079Scarl fd = fopen(updatingfile, "r"); 213250079Scarl } 214295618Scem if (fd == NULL) { 215295618Scem fprintf(stderr, "can't open %s: %s\n", 216295618Scem updatingfile, strerror(errno)); 217295618Scem exit(EX_UNAVAILABLE); 218295618Scem } 219295618Scem 220295618Scem /* Parse opened UPDATING file. */ 221250079Scarl while (fgets(updatingline, maxcharperline, fd) != NULL) { 222250079Scarl /* No entry is found so far */ 223250079Scarl if (found == 0) { 224289546Scem /* Search for AFFECTS line to parse the portname. */ 225250079Scarl tmpline1 = strstr(updatingline, affects); 226289610Scem 227289610Scem if (tmpline1 != NULL) { 228289610Scem curr = head; 229289539Scem while (curr != NULL) { 230289542Scem tmpline2 = strstr(updatingline, curr->name); 231289542Scem if (tmpline2 != NULL) 232289542Scem break; 233289543Scem curr = curr->next; 234289542Scem } 235301293Smav if (tmpline2 != NULL) { 236295618Scem /* If -d is set, check if entry is newer than the date. */ 237289542Scem if ((dflag == 1) && (strncmp(dateline, date, 8) < 0)) 238289539Scem continue; 239289539Scem printf("%s", dateline); 240289539Scem printf("%s", updatingline); 241289539Scem found = 1; 242289539Scem } 243289542Scem } 244289546Scem } 245289546Scem /* Search for the end of an entry, if not found print the line. */ 246289546Scem else { 247289546Scem tmpline1 = strstr(updatingline, end); 248289542Scem if (tmpline1 == NULL) 249289542Scem printf("%s", updatingline); 250290686Scem else { 251290686Scem linelength = strlen(updatingline); 252289542Scem if (linelength == 10) 253289542Scem found = 0; 254289542Scem else 255289546Scem printf("%s", updatingline); 256322980Smav } 257322980Smav } 258289542Scem /* Save the actual line, it could be a date. */ 259289542Scem dateline = strdup(updatingline); 260289542Scem } 261289542Scem 262289542Scem if (ferror(fd)) { 263289542Scem fprintf(stderr, "error reading input\n"); 264289542Scem exit(EX_IOERR); 265250079Scarl } 266250079Scarl (void)fclose(fd); 267289234Scem 268289234Scem exit(EX_OK); 269289234Scem} 270289234Scem 271289234Scemint 272289234Scemusage(void) 273289234Scem{ 274289234Scem fprintf(stderr, 275289234Scem "usage: pkg_updating [-h] [-d YYYYMMDD] [-f file] [portname ...]\n"); 276289234Scem exit(EX_USAGE); 277289234Scem} 278289234Scem 279289234Scemvoid 280289234Scemcleanup(int sig) 281289234Scem{ 282289234Scem if (sig) 283289234Scem exit(1); 284289234Scem} 285289234Scem