1106491Sobrien/* 2228990Suqs * FreeBSD install - a package for the installation and maintenance 3106491Sobrien * of non-core utilities. 4106491Sobrien * 5106491Sobrien * Redistribution and use in source and binary forms, with or without 6106491Sobrien * modification, are permitted provided that the following conditions 7106491Sobrien * are met: 8106491Sobrien * 1. Redistributions of source code must retain the above copyright 9106491Sobrien * notice, this list of conditions and the following disclaimer. 10106491Sobrien * 2. Redistributions in binary form must reproduce the above copyright 11106491Sobrien * notice, this list of conditions and the following disclaimer in the 12106491Sobrien * documentation and/or other materials provided with the distribution. 13106491Sobrien * 14106491Sobrien * Jordan K. Hubbard 15106491Sobrien * 18 July 1993 16106491Sobrien * 17106491Sobrien * URL file access utilities. 18106491Sobrien * 19106491Sobrien */ 20106491Sobrien 21106491Sobrien#include <sys/cdefs.h> 22106491Sobrien__FBSDID("$FreeBSD$"); 23106491Sobrien 24106491Sobrien#include "lib.h" 25106491Sobrien#include <err.h> 26106491Sobrien#include <fetch.h> 27154145Sflz#include <libgen.h> 28106491Sobrien#include <sys/wait.h> 29154145Sflz#include <stdio.h> 30106491Sobrien 31106491Sobrien/* 32106491Sobrien * Try and fetch a file by URL, returning the directory name for where 33106491Sobrien * it's unpacked, if successful. 34106491Sobrien */ 35194497Sbrianconst char * 36154145SflzfileGetURL(const char *base, const char *spec, int keep_package) 37106491Sobrien{ 38194497Sbrian const char *rp; 39194497Sbrian char *cp, *tmp; 40106491Sobrien char fname[FILENAME_MAX]; 41106491Sobrien char pen[FILENAME_MAX]; 42154145Sflz char pkg[FILENAME_MAX]; 43106491Sobrien char buf[8192]; 44106491Sobrien FILE *ftp; 45106491Sobrien pid_t tpid; 46131285Seik int pfd[2], pstat, r, w = 0; 47106491Sobrien char *hint; 48154145Sflz int fd, pkgfd = 0; 49106491Sobrien 50106491Sobrien rp = NULL; 51106491Sobrien /* Special tip that sysinstall left for us */ 52106491Sobrien hint = getenv("PKG_ADD_BASE"); 53106491Sobrien if (!isURL(spec)) { 54106491Sobrien if (!base && !hint) 55106491Sobrien return NULL; 56106491Sobrien /* 57106491Sobrien * We've been given an existing URL (that's known-good) and now we need 58106491Sobrien * to construct a composite one out of that and the basename we were 59106491Sobrien * handed as a dependency. 60106491Sobrien */ 61106491Sobrien if (base) { 62106491Sobrien strcpy(fname, base); 63106491Sobrien /* 64106491Sobrien * Advance back two slashes to get to the root of the package 65106491Sobrien * hierarchy 66106491Sobrien */ 67106491Sobrien cp = strrchr(fname, '/'); 68106491Sobrien if (cp) { 69106491Sobrien *cp = '\0'; /* chop name */ 70106491Sobrien cp = strrchr(fname, '/'); 71106491Sobrien } 72106491Sobrien if (cp) { 73106491Sobrien *(cp + 1) = '\0'; 74106491Sobrien strcat(cp, "All/"); 75106491Sobrien strcat(cp, spec); 76236333Sjpaetzel if (getenv("PACKAGESUFFIX")) 77236333Sjpaetzel strcat(cp, getenv("PACKAGESUFFIX")); 78236333Sjpaetzel else 79236333Sjpaetzel strcat(cp, ".tbz"); 80106491Sobrien } 81106491Sobrien else 82106491Sobrien return NULL; 83106491Sobrien } 84106491Sobrien else { 85106491Sobrien /* 86106491Sobrien * Otherwise, we've been given an environment variable hinting 87106491Sobrien * at the right location from sysinstall 88106491Sobrien */ 89106491Sobrien strcpy(fname, hint); 90106491Sobrien strcat(fname, spec); 91236333Sjpaetzel if (getenv("PACKAGESUFFIX")) 92236333Sjpaetzel strcat(fname, getenv("PACKAGESUFFIX")); 93236333Sjpaetzel else 94236333Sjpaetzel strcat(fname, ".tbz"); 95106491Sobrien } 96106491Sobrien } 97106491Sobrien else 98106491Sobrien strcpy(fname, spec); 99106491Sobrien 100161212Sdes if (keep_package) { 101167972Snjl tmp = getenv("PKGDIR"); 102154145Sflz strlcpy(pkg, tmp ? tmp : ".", sizeof(pkg)); 103154145Sflz tmp = basename(fname); 104154145Sflz strlcat(pkg, "/", sizeof(pkg)); 105154145Sflz strlcat(pkg, tmp, sizeof(pkg)); 106167972Snjl if ((pkgfd = open(pkg, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) { 107167972Snjl printf("Error: Unable to open %s\n", pkg); 108154145Sflz perror("open"); 109154145Sflz return NULL; 110154145Sflz } 111161212Sdes } 112154145Sflz 113160178Sdes fetchDebug = (Verbose > 0); 114113587Srwatson if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) { 115195212Sbrian printf("Error: Unable to get %s: %s\n", 116106491Sobrien fname, fetchLastErrString); 117206043Sflz /* If the fetch fails, yank the package. */ 118206043Sflz if (keep_package && unlink(pkg) < 0 && Verbose) { 119206043Sflz warnx("failed to remove partially fetched package: %s", pkg); 120206043Sflz } 121106491Sobrien return NULL; 122106491Sobrien } 123106491Sobrien 124106491Sobrien if (isatty(0) || Verbose) 125106491Sobrien printf("Fetching %s...", fname), fflush(stdout); 126106491Sobrien pen[0] = '\0'; 127106491Sobrien if ((rp = make_playpen(pen, 0)) == NULL) { 128106491Sobrien printf("Error: Unable to construct a new playpen for FTP!\n"); 129106491Sobrien fclose(ftp); 130106491Sobrien return NULL; 131106491Sobrien } 132106491Sobrien if (pipe(pfd) == -1) { 133106491Sobrien warn("pipe()"); 134106491Sobrien cleanup(0); 135106491Sobrien exit(2); 136106491Sobrien } 137106491Sobrien if ((tpid = fork()) == -1) { 138106491Sobrien warn("pipe()"); 139106491Sobrien cleanup(0); 140106491Sobrien exit(2); 141106491Sobrien } 142106491Sobrien if (!tpid) { 143106491Sobrien dup2(pfd[0], 0); 144106491Sobrien for (fd = getdtablesize() - 1; fd >= 3; --fd) 145106491Sobrien close(fd); 146131285Seik execl("/usr/bin/tar", "tar", 147167270Sru Verbose ? "-xpjvf" : "-xpjf", 148131285Seik "-", (char *)0); 149106491Sobrien _exit(2); 150106491Sobrien } 151106491Sobrien close(pfd[0]); 152106491Sobrien for (;;) { 153106491Sobrien if ((r = fread(buf, 1, sizeof buf, ftp)) < 1) 154106491Sobrien break; 155106491Sobrien if ((w = write(pfd[1], buf, r)) != r) 156106491Sobrien break; 157154145Sflz if (keep_package) { 158154145Sflz if ((w = write(pkgfd, buf, r)) != r) 159154145Sflz break; 160154145Sflz } 161106491Sobrien } 162106491Sobrien if (ferror(ftp)) 163106491Sobrien warn("warning: error reading from server"); 164106491Sobrien fclose(ftp); 165154145Sflz if (keep_package) { 166154145Sflz close(pkgfd); 167154145Sflz } 168106491Sobrien close(pfd[1]); 169106491Sobrien if (w == -1) 170106491Sobrien warn("warning: error writing to tar"); 171106491Sobrien tpid = waitpid(tpid, &pstat, 0); 172106491Sobrien if (Verbose) 173106491Sobrien printf("tar command returns %d status\n", WEXITSTATUS(pstat)); 174106491Sobrien if (rp && (isatty(0) || Verbose)) 175106491Sobrien printf(" Done.\n"); 176106491Sobrien return rp; 177106491Sobrien} 178