Import NetBSD xinstall
Also, fix mk files for cross compilation.
This commit is contained in:
parent
d433a56288
commit
9d04c193d2
11 changed files with 1707 additions and 671 deletions
|
@ -13,7 +13,7 @@ SUBDIR= add_route arp ash at \
|
|||
eject elvis env expand factor fbdctl \
|
||||
find finger fingerd fix fold format fortune fsck.mfs \
|
||||
ftp101 gcore gcov-pull getty grep head hexdump host \
|
||||
hostaddr id ifconfig ifdef install \
|
||||
hostaddr id ifconfig ifdef \
|
||||
intr ipcrm ipcs irdpd isoread join kill last \
|
||||
less loadkeys loadramdisk logger look lp \
|
||||
lpd ls lspci mail MAKEDEV \
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
PROG= xinstall
|
||||
SRCS= install.c
|
||||
BINDIR= /bin
|
||||
BINMODE= 4755
|
||||
MAN=
|
||||
|
||||
PROGNAME=install
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -1,657 +0,0 @@
|
|||
/* install 1.11 - install files. Author: Kees J. Bot
|
||||
* 21 Feb 1993
|
||||
*/
|
||||
#define nil 0
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <a.out.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <utime.h>
|
||||
#include <signal.h>
|
||||
|
||||
/* First line used on a self-decompressing executable. */
|
||||
char ZCAT[]= "#!/usr/bin/zexec /usr/bin/zcat\n";
|
||||
char GZCAT[]= "#!/usr/bin/zexec /usr/bin/gzcat\n";
|
||||
|
||||
/* Compression filters. */
|
||||
char *COMPRESS[]= { "compress", nil };
|
||||
char *GZIP[]= { "gzip", "-#", nil };
|
||||
|
||||
int excode= 0; /* Exit code. */
|
||||
|
||||
void report(char *label)
|
||||
{
|
||||
if (label == nil || label[0] == 0)
|
||||
fprintf(stderr, "install: %s\n", strerror(errno));
|
||||
else
|
||||
fprintf(stderr, "install: %s: %s\n", label, strerror(errno));
|
||||
excode= 1;
|
||||
}
|
||||
|
||||
void fatal(char *label)
|
||||
{
|
||||
report(label);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *allocate(void *mem, size_t size)
|
||||
/* Safe malloc/realloc. */
|
||||
{
|
||||
mem= mem == nil ? malloc(size) : realloc(mem, size);
|
||||
|
||||
if (mem == nil) fatal(nil);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void deallocate(void *mem)
|
||||
{
|
||||
if (mem != nil) free(mem);
|
||||
}
|
||||
|
||||
int lflag= 0; /* Make a link if possible. */
|
||||
int cflag= 0; /* Copy if you can't link, otherwise symlink. */
|
||||
int dflag= 0; /* Create a directory. */
|
||||
int pflag= 0; /* Preserve timestamps. */
|
||||
int strip= 0; /* Strip the copy. */
|
||||
char **compress= nil; /* Compress utility to make a compressed executable. */
|
||||
char *zcat= nil; /* Line one to decompress. */
|
||||
|
||||
int make_hardlink = 0; /* Make a hard link */
|
||||
int make_symlink = 0; /* Make a symbolic link */
|
||||
|
||||
long stack= -1; /* Amount of heap + stack. */
|
||||
int wordpow= 1; /* Must be multiplied with wordsize ** wordpow */
|
||||
/* So 8kb for an 8086 and 16kb for the rest. */
|
||||
|
||||
pid_t filter(int fd, char **command)
|
||||
/* Let a command filter the output to fd. */
|
||||
{
|
||||
pid_t pid;
|
||||
int pfd[2];
|
||||
|
||||
if (pipe(pfd) < 0) {
|
||||
report("pipe()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch ((pid= fork())) {
|
||||
case -1:
|
||||
report("fork()");
|
||||
return -1;
|
||||
case 0:
|
||||
/* Run the filter. */
|
||||
dup2(pfd[0], 0);
|
||||
dup2(fd, 1);
|
||||
close(pfd[0]);
|
||||
close(pfd[1]);
|
||||
close(fd);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
execvp(command[0], command);
|
||||
fatal(command[0]);
|
||||
}
|
||||
/* Connect fd to the pipe. */
|
||||
dup2(pfd[1], fd);
|
||||
close(pfd[0]);
|
||||
close(pfd[1]);
|
||||
return pid;
|
||||
}
|
||||
|
||||
int mkdirp(char *dir, int mode, int owner, int group)
|
||||
/* mkdir -p dir */
|
||||
{
|
||||
int keep;
|
||||
char *sep, *pref;
|
||||
|
||||
sep= dir;
|
||||
while (*sep == '/') sep++;
|
||||
|
||||
if (*sep == 0) {
|
||||
errno= EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
while (*sep != '/' && *sep != 0) sep++;
|
||||
pref= sep;
|
||||
while (*sep == '/') sep++;
|
||||
|
||||
keep= *pref; *pref= 0;
|
||||
|
||||
if (strcmp(dir, ".") == 0 || strcmp(dir, "..") == 0) continue;
|
||||
|
||||
if (mkdir(dir, mode) < 0) {
|
||||
if (errno != EEXIST || *sep == 0) {
|
||||
/* On purpose not doing: *pref= keep; */
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (chown(dir, owner, group) < 0 && errno != EPERM)
|
||||
return -1;
|
||||
}
|
||||
} while (*pref= keep, *sep != 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void makedir(char *dir, int mode, int owner, int group)
|
||||
/* Install a directory, and set it's modes. */
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(dir, &st) < 0) {
|
||||
if (errno != ENOENT) { report(dir); return; }
|
||||
|
||||
/* The target doesn't exist, make it. */
|
||||
if (mode == -1) mode= 0755;
|
||||
if (owner == -1) owner= getuid();
|
||||
if (group == -1) group= getgid();
|
||||
|
||||
if (mkdirp(dir, mode, owner, group) < 0) {
|
||||
report(dir); return;
|
||||
}
|
||||
} else {
|
||||
/* The target does exist, change mode and ownership. */
|
||||
if (mode == -1) mode= (st.st_mode & 07777) | 0555;
|
||||
|
||||
if ((st.st_mode & 07777) != mode) {
|
||||
if (chmod(dir, mode) < 0) { report(dir); return; }
|
||||
}
|
||||
if (owner == -1) owner= st.st_uid;
|
||||
if (group == -1) group= st.st_gid;
|
||||
if (st.st_uid != owner || st.st_gid != group) {
|
||||
if (chown(dir, owner, group) < 0 && errno != EPERM) {
|
||||
report(dir); return;
|
||||
}
|
||||
/* Set the mode again, chown may have wrecked it. */
|
||||
(void) chmod(dir, mode);
|
||||
}
|
||||
|
||||
if (pflag) {
|
||||
struct utimbuf ubuf;
|
||||
|
||||
ubuf.actime= st.st_atime;
|
||||
ubuf.modtime= st.st_mtime;
|
||||
|
||||
if (utime(dir, &ubuf) < 0 && errno != EPERM) {
|
||||
report(dir); return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int setstack(struct exec *hdr)
|
||||
/* Set the stack size in a header. Return true if something changed. */
|
||||
{
|
||||
long total;
|
||||
|
||||
total= stack;
|
||||
while (wordpow > 0) {
|
||||
total *= hdr->a_cpu == A_I8086 ? 2 : 4;
|
||||
wordpow--;
|
||||
}
|
||||
total+= hdr->a_data + hdr->a_bss;
|
||||
|
||||
if (!(hdr->a_flags & A_SEP)) {
|
||||
total+= hdr->a_text;
|
||||
#ifdef A_PAL
|
||||
if (hdr->a_flags & A_PAL) total+= hdr->a_hdrlen;
|
||||
#endif
|
||||
}
|
||||
if (hdr->a_cpu == A_I8086 && total > 0x10000L)
|
||||
total= 0x10000L;
|
||||
|
||||
if (hdr->a_total != total) {
|
||||
/* Need to change stack allocation. */
|
||||
hdr->a_total= total;
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void copylink(char *source, char *dest, int mode, int owner, int group)
|
||||
{
|
||||
struct stat sst, dst;
|
||||
int sfd, dfd, n;
|
||||
int r, same= 0, change= 0, docopy= 1;
|
||||
char buf[4096];
|
||||
# define hdr ((struct exec *) buf)
|
||||
pid_t pid = 0;
|
||||
int status = 0;
|
||||
char *p;
|
||||
|
||||
/* Source must exist as a plain file, dest may exist as a plain file. */
|
||||
if (make_symlink && source[0] != '/'
|
||||
&& (p = strrchr(dest, '/')) != NULL ) {
|
||||
/* creating a relative symlink; compute real target */
|
||||
strlcpy(buf, dest, sizeof(buf));
|
||||
if (p - dest + 1 >= (int)sizeof(buf))
|
||||
p = dest + sizeof(buf) - 2;
|
||||
buf[p - dest + 1] = '\0';
|
||||
strlcat(buf, source, sizeof(buf));
|
||||
r = stat(buf, &sst);
|
||||
} else
|
||||
r = stat(source, &sst);
|
||||
if (r < 0) { report(source); return; }
|
||||
|
||||
if (mode == -1) {
|
||||
mode= sst.st_mode & 07777;
|
||||
if (!lflag || cflag) {
|
||||
mode|= 0444;
|
||||
if (mode & 0111) mode|= 0111;
|
||||
}
|
||||
}
|
||||
if (owner == -1) owner= sst.st_uid;
|
||||
if (group == -1) group= sst.st_gid;
|
||||
|
||||
if (!make_symlink && !S_ISREG(sst.st_mode)) {
|
||||
fprintf(stderr, "install: %s is not a regular file\n", source);
|
||||
excode= 1;
|
||||
return;
|
||||
}
|
||||
r= lstat(dest, &dst);
|
||||
if (r < 0) {
|
||||
if (errno != ENOENT) { report(dest); return; }
|
||||
} else {
|
||||
if (!make_symlink && !S_ISREG(dst.st_mode)) {
|
||||
fprintf(stderr, "install: %s is not a regular file\n",
|
||||
dest);
|
||||
excode= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Are the files the same? */
|
||||
if (sst.st_dev == dst.st_dev && sst.st_ino == dst.st_ino) {
|
||||
if (!lflag && cflag) {
|
||||
fprintf(stderr,
|
||||
"install: %s and %s are the same, can't copy\n",
|
||||
source, dest);
|
||||
excode= 1;
|
||||
return;
|
||||
}
|
||||
same= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (lflag) {
|
||||
/* Try to link the files. */
|
||||
|
||||
if (r >= 0 && unlink(dest) < 0) {
|
||||
report(dest); return;
|
||||
}
|
||||
|
||||
if (make_hardlink) {
|
||||
r = link(source, dest);
|
||||
}
|
||||
else if (make_symlink) {
|
||||
r = symlink(source, dest);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"install: must specify hardlink or symlink\n");
|
||||
}
|
||||
|
||||
if (r >= 0) {
|
||||
docopy= 0;
|
||||
} else {
|
||||
if (!cflag || errno != EXDEV) {
|
||||
fprintf(stderr,
|
||||
"install: can't link %s to %s: %s\n",
|
||||
source, dest, strerror(errno));
|
||||
excode= 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (docopy && !same) {
|
||||
/* Copy the files, stripping if necessary. */
|
||||
long count= LONG_MAX;
|
||||
int first= 1;
|
||||
|
||||
if ((sfd= open(source, O_RDONLY)) < 0) {
|
||||
report(source); return;
|
||||
}
|
||||
|
||||
/* Open for write is less simple, its mode may be 444. */
|
||||
dfd= open(dest, O_WRONLY|O_CREAT|O_TRUNC, mode | 0600);
|
||||
if (dfd < 0 && errno == EACCES) {
|
||||
(void) chmod(dest, mode | 0600);
|
||||
dfd= open(dest, O_WRONLY|O_TRUNC);
|
||||
}
|
||||
if (dfd < 0) {
|
||||
report(dest);
|
||||
close(sfd);
|
||||
return;
|
||||
}
|
||||
|
||||
pid= 0;
|
||||
while (count > 0 && (n= read(sfd, buf, sizeof(buf))) > 0) {
|
||||
if (first && n >= A_MINHDR && !BADMAG(*hdr)) {
|
||||
if (strip) {
|
||||
count= hdr->a_hdrlen
|
||||
+ hdr->a_text + hdr->a_data;
|
||||
#ifdef A_NSYM
|
||||
hdr->a_flags &= ~A_NSYM;
|
||||
#endif
|
||||
hdr->a_syms= 0;
|
||||
}
|
||||
if (stack != -1 && setstack(hdr)) change= 1;
|
||||
|
||||
if (compress != nil) {
|
||||
/* Write first #! line. */
|
||||
(void) write(dfd, zcat, strlen(zcat));
|
||||
|
||||
/* Put a compressor in between. */
|
||||
if ((pid= filter(dfd, compress)) < 0) {
|
||||
close(sfd);
|
||||
close(dfd);
|
||||
return;
|
||||
}
|
||||
change= 1;
|
||||
}
|
||||
}
|
||||
if (count < n) n= count;
|
||||
|
||||
if (write(dfd, buf, n) < 0) {
|
||||
report(dest);
|
||||
close(sfd);
|
||||
close(dfd);
|
||||
if (pid != 0) (void) waitpid(pid, nil, 0);
|
||||
return;
|
||||
}
|
||||
count-= n;
|
||||
first= 0;
|
||||
}
|
||||
if (n < 0) report(source);
|
||||
close(sfd);
|
||||
close(dfd);
|
||||
if (pid != 0 && waitpid(pid, &status, 0) < 0 || status != 0) {
|
||||
excode= 1;
|
||||
return;
|
||||
}
|
||||
if (n < 0) return;
|
||||
} else {
|
||||
if (stack != -1) {
|
||||
/* The file has been linked into place. Set the
|
||||
* stack size.
|
||||
*/
|
||||
if ((dfd= open(dest, O_RDWR)) < 0) {
|
||||
report(dest);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n= read(dfd, buf, sizeof(*hdr))) < 0) {
|
||||
report(dest); return;
|
||||
}
|
||||
|
||||
if (n >= A_MINHDR && !BADMAG(*hdr) && setstack(hdr)) {
|
||||
if (lseek(dfd, (off_t) 0, SEEK_SET) == -1
|
||||
|| write(dfd, buf, n) < 0
|
||||
) {
|
||||
report(dest);
|
||||
close(dfd);
|
||||
return;
|
||||
}
|
||||
change= 1;
|
||||
}
|
||||
close(dfd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't modify metadata if symlink target doesn't exist */
|
||||
if (make_symlink && stat(dest, &dst) < 0) return;
|
||||
|
||||
if (stat(dest, &dst) < 0) { report(dest); return; }
|
||||
|
||||
if ((dst.st_mode & 07777) != mode) {
|
||||
if (chmod(dest, mode) < 0) { report(dest); return; }
|
||||
}
|
||||
if (dst.st_uid != owner || dst.st_gid != group) {
|
||||
if (chown(dest, owner, group) < 0 && errno != EPERM) {
|
||||
report(dest); return;
|
||||
}
|
||||
/* Set the mode again, chown may have wrecked it. */
|
||||
(void) chmod(dest, mode);
|
||||
}
|
||||
if (!change || pflag) {
|
||||
struct utimbuf ubuf;
|
||||
|
||||
ubuf.actime= dst.st_atime;
|
||||
ubuf.modtime= sst.st_mtime;
|
||||
|
||||
if (utime(dest, &ubuf) < 0 && errno != EPERM) {
|
||||
report(dest); return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr, "\
|
||||
Usage:\n\
|
||||
install [-lcpsz#] [-o owner] [-g group] [-m mode] [-S stack] [file1] file2\n\
|
||||
install [-lcpsz#] [-o owner] [-g group] [-m mode] [-S stack] file ... dir\n\
|
||||
install [-c] -d [-o owner] [-g group] [-m mode] directory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i= 1;
|
||||
int mode= -1; /* Mode of target. */
|
||||
int owner= -1; /* Owner. */
|
||||
int group= -1; /* Group. */
|
||||
int super = 0;
|
||||
#if NGROUPS_MAX > 0
|
||||
gid_t groups[NGROUPS_MAX];
|
||||
int ngroups;
|
||||
int g;
|
||||
#endif
|
||||
|
||||
/* Only those in group 0 are allowed to set owner and group. */
|
||||
if (getgid() == 0) super = 1;
|
||||
#if NGROUPS_MAX > 0
|
||||
ngroups= getgroups(NGROUPS_MAX, groups);
|
||||
for (g= 0; g < ngroups; g++) if (groups[g] == 0) super= 1;
|
||||
#endif
|
||||
if (!super) {
|
||||
setgid(getgid());
|
||||
setuid(getuid());
|
||||
}
|
||||
|
||||
/* May use a filter. */
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
while (i < argc && argv[i][0] == '-') {
|
||||
char *p= argv[i++]+1;
|
||||
char *end;
|
||||
unsigned long num;
|
||||
int wp;
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
|
||||
if (strcmp(p, "-") == 0) break;
|
||||
|
||||
while (*p != 0) {
|
||||
switch (*p++) {
|
||||
case 'c': cflag= 1; break;
|
||||
case 's': strip= 1; break;
|
||||
case 'd': dflag= 1; break;
|
||||
case 'p': pflag= 1; break;
|
||||
case 'z':
|
||||
if (compress == nil) {
|
||||
compress= COMPRESS;
|
||||
zcat= ZCAT;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if (*p == 0) {
|
||||
if (i == argc) usage();
|
||||
p= argv[i++];
|
||||
if (*p == 0) usage();
|
||||
}
|
||||
num= strtoul(p, &end, 10);
|
||||
if (*end == 0) {
|
||||
if ((uid_t) num != num) usage();
|
||||
owner= num;
|
||||
} else {
|
||||
if ((pw= getpwnam(p)) == nil) {
|
||||
fprintf(stderr,
|
||||
"install: %s: unknown user\n",
|
||||
p);
|
||||
exit(1);
|
||||
}
|
||||
owner= pw->pw_uid;
|
||||
}
|
||||
p= "";
|
||||
break;
|
||||
case 'g':
|
||||
if (*p == 0) {
|
||||
if (i == argc) usage();
|
||||
p= argv[i++];
|
||||
if (*p == 0) usage();
|
||||
}
|
||||
num= strtoul(p, &end, 10);
|
||||
if (*end == 0) {
|
||||
if ((gid_t) num != num) usage();
|
||||
group= num;
|
||||
} else {
|
||||
if ((gr= getgrnam(p)) == nil) {
|
||||
fprintf(stderr,
|
||||
"install: %s: unknown group\n",
|
||||
p);
|
||||
exit(1);
|
||||
}
|
||||
group= gr->gr_gid;
|
||||
}
|
||||
p= "";
|
||||
break;
|
||||
case 'm':
|
||||
if (*p == 0) {
|
||||
if (i == argc) usage();
|
||||
p= argv[i++];
|
||||
if (*p == 0) usage();
|
||||
}
|
||||
num= strtoul(p, &end, 010);
|
||||
if (*end != 0 || (num & 07777) != num) usage();
|
||||
mode= num;
|
||||
if ((mode & S_ISUID) && super && owner == -1) {
|
||||
/* Setuid what? Root most likely. */
|
||||
owner= 0;
|
||||
}
|
||||
if ((mode & S_ISGID) && super && group == -1) {
|
||||
group= 0;
|
||||
}
|
||||
p= "";
|
||||
break;
|
||||
case 'l':
|
||||
lflag= 1;
|
||||
if (*p == 0) {
|
||||
if (i == argc) usage();
|
||||
p= argv[i++];
|
||||
if (*p == 0) usage();
|
||||
}
|
||||
switch(*p) {
|
||||
case 'h':
|
||||
make_hardlink = 1;
|
||||
break;
|
||||
case 's':
|
||||
make_symlink = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
p= "";
|
||||
break;
|
||||
case 'S':
|
||||
if (*p == 0) {
|
||||
if (i == argc) usage();
|
||||
p= argv[i++];
|
||||
if (*p == 0) usage();
|
||||
}
|
||||
stack= strtol(p, &end, 0);
|
||||
wp= 0;
|
||||
if (end == p || stack < 0) usage();
|
||||
p= end;
|
||||
while (*p != 0) {
|
||||
switch (*p++) {
|
||||
case 'm':
|
||||
case 'M': num= 1024 * 1024L; break;
|
||||
case 'k':
|
||||
case 'K': num= 1024; break;
|
||||
case 'w':
|
||||
case 'W': num= 4; wp++; break;
|
||||
case 'b':
|
||||
case 'B': num= 1; break;
|
||||
default: usage();
|
||||
}
|
||||
if (stack > LONG_MAX / num) usage();
|
||||
stack*= num;
|
||||
}
|
||||
wordpow= 0;
|
||||
while (wp > 0) { stack /= 4; wordpow++; wp--; }
|
||||
break;
|
||||
default:
|
||||
if ((unsigned) (p[-1] - '1') <= ('9' - '1')) {
|
||||
compress= GZIP;
|
||||
GZIP[1][1]= p[-1];
|
||||
zcat= GZCAT;
|
||||
break;
|
||||
}
|
||||
usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Some options don't mix. */
|
||||
if (dflag && (lflag || strip)) usage();
|
||||
|
||||
/* Don't let the user umask interfere. */
|
||||
umask(000);
|
||||
|
||||
if (dflag) {
|
||||
/* install directory */
|
||||
if ((argc - i) != 1) usage();
|
||||
|
||||
makedir(argv[i], mode, owner, group);
|
||||
} else {
|
||||
struct stat st;
|
||||
|
||||
if ((argc - i) < 1) usage();
|
||||
if ((lflag || cflag) && (argc - i) == 1) usage();
|
||||
|
||||
if (lstat(argv[argc-1], &st) >= 0 && S_ISDIR(st.st_mode)) {
|
||||
/* install file ... dir */
|
||||
char *target= nil;
|
||||
char *base;
|
||||
|
||||
if ((argc - i) == 1) usage();
|
||||
|
||||
while (i < argc-1) {
|
||||
if ((base= strrchr(argv[i], '/')) == nil)
|
||||
base= argv[i];
|
||||
else
|
||||
base++;
|
||||
target= allocate(target, strlen(argv[argc-1])
|
||||
+ 1 + strlen(base) + 1);
|
||||
strcpy(target, argv[argc-1]);
|
||||
strcat(target, "/");
|
||||
strcat(target, base);
|
||||
|
||||
copylink(argv[i++], target, mode, owner, group);
|
||||
}
|
||||
} else {
|
||||
/* install [file1] file2 */
|
||||
|
||||
copylink(argv[i], argv[argc-1], mode, owner, group);
|
||||
}
|
||||
}
|
||||
exit(excode);
|
||||
}
|
|
@ -1,3 +1,15 @@
|
|||
20120608:
|
||||
New install and mk files require the following steps:
|
||||
|
||||
# cp /usr/src/share/mk/*.mk /usr/share/mk
|
||||
# cd /usr/src
|
||||
# make -C usr.bin/xinstall all
|
||||
# cp usr.bin/xinstall/xinstall /usr/bin/install
|
||||
# rm /bin/install
|
||||
|
||||
then do
|
||||
# make clean world
|
||||
|
||||
20120510:
|
||||
WARNING: the shared libraries major revision set to 0 will break
|
||||
existing dynamically linked binaries if they exist.
|
||||
|
|
|
@ -56,6 +56,9 @@ TOOLCHAIN_MISSING?= no
|
|||
# default to GCC4
|
||||
.if !defined(HAVE_GCC) && !defined(HAVE_PCC)
|
||||
HAVE_GCC= 4
|
||||
.if !defined(_GCC_LIBGCCDIR)
|
||||
_GCC_LIBGCCDIR= ${DESTDIR}/usr/lib
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.if \
|
||||
|
@ -128,8 +131,10 @@ _SRC_TOP_OBJ_!= cd ${_SRC_TOP_} && ${PRINTOBJDIR}
|
|||
|
||||
.if (${_SRC_TOP_} != "") && \
|
||||
(${TOOLCHAIN_MISSING} == "no" || defined(EXTERNAL_TOOLCHAIN))
|
||||
.if (defined(BUILDSH))
|
||||
USETOOLS?= yes
|
||||
.endif
|
||||
.endif
|
||||
USETOOLS?= no
|
||||
|
||||
|
||||
|
@ -756,10 +761,11 @@ _MKVARS.no= \
|
|||
MKMANDOC MKMANZ MKOBJDIRS \
|
||||
MKPCC MKPCCCMDS \
|
||||
MKSOFTFLOAT MKSTRIPIDENT \
|
||||
MKUNPRIVED MKUPDATE MKX11 MKZFS MKBSDTAR
|
||||
MKUNPRIVED MKUPDATE MKX11 MKZFS MKBSDTAR \
|
||||
MKARZERO
|
||||
#MINIX-specific vars
|
||||
_MKVARS.no+= \
|
||||
MKIMAGEONLY MKSMALL MKBUILDEXT2RD
|
||||
MKIMAGEONLY MKSMALL MKBUILDEXT2RD USETOOLS
|
||||
.for var in ${_MKVARS.no}
|
||||
${var}?=no
|
||||
.endfor
|
||||
|
|
|
@ -6,7 +6,7 @@ unix?= We run MINIX.
|
|||
# This variable should be used to differentiate Minix builds in Makefiles.
|
||||
__MINIX= yes
|
||||
|
||||
.SUFFIXES: .a .o .ln .s .S .c .cc .cpp .cxx .C .f .F .r .p .l .y #.sh
|
||||
.SUFFIXES: .a .o .ln .s .S .c .cc .cpp .cxx .C .f .F .r .p .l .y .sh
|
||||
|
||||
.LIBS: .a
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# NetBSD imports
|
||||
SUBDIR= login indent m4 make mktemp stat tic sed mkdep uniq seq du man \
|
||||
apropos chpass newgrp passwd bzip2 bzip2recover gzip su genassym \
|
||||
ldd/elf32 .WAIT ldd
|
||||
xinstall ldd/elf32 .WAIT ldd
|
||||
|
||||
# Non-NetBSD imports
|
||||
SUBDIR+= ministat
|
||||
|
|
23
usr.bin/xinstall/Makefile
Normal file
23
usr.bin/xinstall/Makefile
Normal file
|
@ -0,0 +1,23 @@
|
|||
# $NetBSD: Makefile,v 1.22 2011/08/17 14:00:30 christos Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= xinstall
|
||||
SRCS= xinstall.c getid.c
|
||||
MAN= install.1
|
||||
|
||||
.PATH: ${NETBSDSRCDIR}/usr.sbin/mtree
|
||||
CPPFLAGS+= -I${NETBSDSRCDIR}/usr.sbin/mtree
|
||||
|
||||
.if (${HOSTPROG:U} == "")
|
||||
DPADD+= ${LIBUTIL}
|
||||
LDADD+= -lutil
|
||||
.endif
|
||||
|
||||
COPTS.xinstall.c += -Wno-format-nonliteral
|
||||
|
||||
|
||||
PROGNAME=install
|
||||
|
||||
.include <bsd.prog.mk>
|
338
usr.bin/xinstall/install.1
Normal file
338
usr.bin/xinstall/install.1
Normal file
|
@ -0,0 +1,338 @@
|
|||
.\" $NetBSD: install.1,v 1.47 2012/04/08 22:00:40 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1987, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)install.1 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd May 1, 2009
|
||||
.Dt INSTALL 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm install
|
||||
.Nd install binaries
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl bcprsU
|
||||
.Op Fl a Ar command
|
||||
.Op Fl B Ar suffix
|
||||
.Op Fl D Ar destdir
|
||||
.Op Fl f Ar flags
|
||||
.Op Fl g Ar group
|
||||
.Op Fl h Ar hash
|
||||
.Op Fl l Ar linkflags
|
||||
.Op Fl M Ar metalog
|
||||
.Op Fl m Ar mode
|
||||
.Op Fl N Ar dbdir
|
||||
.Op Fl o Ar owner
|
||||
.Op Fl S Ar stripflag
|
||||
.Op Fl T Ar tags
|
||||
.Ar file1 file2
|
||||
.Nm
|
||||
.Op Fl bcprsU
|
||||
.Op Fl a Ar command
|
||||
.Op Fl B Ar suffix
|
||||
.Op Fl D Ar destdir
|
||||
.Op Fl f Ar flags
|
||||
.Op Fl g Ar group
|
||||
.Op Fl h Ar hash
|
||||
.Op Fl l Ar linkflags
|
||||
.Op Fl M Ar metalog
|
||||
.Op Fl m Ar mode
|
||||
.Op Fl N Ar dbdir
|
||||
.Op Fl o Ar owner
|
||||
.Op Fl S Ar stripflag
|
||||
.Op Fl T Ar tags
|
||||
.Ar file1 ...\&
|
||||
.Ar fileN directory
|
||||
.Nm
|
||||
.Fl d
|
||||
.Op Fl pU
|
||||
.Op Fl a Ar command
|
||||
.Op Fl D Ar destdir
|
||||
.Op Fl g Ar group
|
||||
.Op Fl M Ar metalog
|
||||
.Op Fl m Ar mode
|
||||
.Op Fl N Ar dbdir
|
||||
.Op Fl o Ar owner
|
||||
.Op Fl T Ar tags
|
||||
.Ar directory ...\&
|
||||
.Sh DESCRIPTION
|
||||
The file(s) are copied
|
||||
(or linked if the
|
||||
.Fl l
|
||||
option is specified) to the target file or directory.
|
||||
If the destination is a directory, then the
|
||||
.Ar file
|
||||
is copied into
|
||||
.Ar directory
|
||||
with its original filename.
|
||||
If the target file already exists, it is
|
||||
either renamed to
|
||||
.Ar file.old
|
||||
if the
|
||||
.Fl b
|
||||
option is given
|
||||
or overwritten
|
||||
if permissions allow; an alternate backup suffix may be specified via the
|
||||
.Fl B
|
||||
option's argument.
|
||||
.Pp
|
||||
.Bl -tag -width XsXXstripflagsXX
|
||||
.It Fl a Ar command
|
||||
Run
|
||||
.Ar command
|
||||
on the target after installation and stripping
|
||||
.Pq Fl s ,
|
||||
but before
|
||||
ownership, permissions or timestamps are set and before renaming
|
||||
.Pq Fl r
|
||||
occurs.
|
||||
.Ar command
|
||||
is invoked via the
|
||||
.Xr sh 1
|
||||
shell, allowing a single
|
||||
.Fl a
|
||||
argument be to specified to
|
||||
.Nm
|
||||
which the shell can then tokenize.
|
||||
.It Fl B Ar suffix
|
||||
Use
|
||||
.Ar suffix
|
||||
as the backup suffix if
|
||||
.Fl b
|
||||
is given.
|
||||
If
|
||||
.Ar suffix
|
||||
contains a '%' sign, a numbered backup will be performed, and the
|
||||
%-pattern will be expanded using
|
||||
.Xr sprintf 3 ,
|
||||
given an integer counter as the backup number.
|
||||
The counter used starts from 0, and the first available name resulting
|
||||
from the expansion is used.
|
||||
.It Fl b
|
||||
Backup any existing files before overwriting them by renaming
|
||||
them to
|
||||
.Ar file.old . See
|
||||
.Fl B
|
||||
for specifying a different backup suffix.
|
||||
.It Fl c
|
||||
Copy the file.
|
||||
This is the default behavior; the flag is maintained for backwards
|
||||
compatibility only.
|
||||
.It Fl D Ar destdir
|
||||
Specify the
|
||||
.Ev DESTDIR
|
||||
(top of the file hierarchy) that the items are installed in to.
|
||||
If
|
||||
.Fl M Ar metalog
|
||||
is in use, a leading string of
|
||||
.Dq Ar destdir
|
||||
will be removed from the file names logged to the
|
||||
.Ar metalog .
|
||||
This option does not affect where the actual files are installed.
|
||||
.It Fl d
|
||||
Create directories.
|
||||
Missing parent directories are created as required.
|
||||
.It Fl f Ar flags
|
||||
Specify the target's file flags.
|
||||
(See
|
||||
.Xr chflags 1
|
||||
for a list of possible flags and their meanings.)
|
||||
.It Fl g Ar group
|
||||
Specify a group.
|
||||
.It Fl h Ar hash
|
||||
When copying, calculate the digest of the files with
|
||||
.Ar hash
|
||||
to store in the
|
||||
.Fl M Ar metalog .
|
||||
Supported digests:
|
||||
.Bl -tag -width rmd160 -offset indent
|
||||
.It Sy none
|
||||
No hash.
|
||||
This is the default.
|
||||
.It Sy md5
|
||||
The MD5 cryptographic message digest.
|
||||
.It Sy rmd160
|
||||
The RMD-160 cryptographic message digest.
|
||||
.It Sy sha1
|
||||
The SHA-1 cryptographic message digest.
|
||||
.It Sy sha256
|
||||
The 256-bits
|
||||
.Tn SHA-2
|
||||
cryptographic message digest of the file.
|
||||
.It Sy sha384
|
||||
The 384-bits
|
||||
.Tn SHA-2
|
||||
cryptographic message digest of the file.
|
||||
.It Sy sha512
|
||||
The 512-bits
|
||||
.Tn SHA-2
|
||||
cryptographic message digest of the file.
|
||||
.El
|
||||
.It Fl l Ar linkflags
|
||||
Instead of copying the file make a link to the source.
|
||||
The type of the link is determined by the
|
||||
.Ar linkflags
|
||||
argument.
|
||||
Valid
|
||||
.Ar linkflags
|
||||
are:
|
||||
.Ar a
|
||||
(absolute),
|
||||
.Ar r
|
||||
(relative),
|
||||
.Ar h
|
||||
(hard),
|
||||
.Ar s
|
||||
(symbolic),
|
||||
.Ar m
|
||||
(mixed).
|
||||
Absolute and relative have effect only for symbolic links.
|
||||
Mixed links
|
||||
are hard links for files on the same filesystem, symbolic otherwise.
|
||||
.It Fl M Ar metalog
|
||||
Write the metadata associated with each item installed to
|
||||
.Ar metalog
|
||||
in an
|
||||
.Xr mtree 8
|
||||
.Dq full path
|
||||
specification line.
|
||||
The metadata includes: the file name and file type, and depending upon
|
||||
other options, the owner, group, file flags, modification time, and tags.
|
||||
.It Fl m Ar mode
|
||||
Specify an alternative mode.
|
||||
The default mode is set to rwxr-xr-x (0755).
|
||||
The specified mode may be either an octal or symbolic value; see
|
||||
.Xr chmod 1
|
||||
for a description of possible mode values.
|
||||
.It Fl N Ar dbdir
|
||||
Use the user database text file
|
||||
.Pa master.passwd
|
||||
and group database text file
|
||||
.Pa group
|
||||
from
|
||||
.Ar dbdir ,
|
||||
rather than using the results from the system's
|
||||
.Xr getpwnam 3
|
||||
and
|
||||
.Xr getgrnam 3
|
||||
(and related) library calls.
|
||||
.It Fl o Ar owner
|
||||
Specify an owner.
|
||||
.It Fl p
|
||||
Preserve the source files access and modification times.
|
||||
.It Fl r
|
||||
Install to a temporary file and then rename the file to its final destination
|
||||
name.
|
||||
This can be used for precious files, to avoid truncation of the original
|
||||
when error conditions (filesystem full etc.) occur.
|
||||
.It Fl S Ar stripflags
|
||||
.Nm
|
||||
passes
|
||||
.Ar stripflags
|
||||
as option arguments to
|
||||
.Xr strip 1 .
|
||||
When
|
||||
.Fl S
|
||||
is used,
|
||||
.Xr strip 1
|
||||
is invoked via the
|
||||
.Xr sh 1
|
||||
shell, allowing a single
|
||||
.Fl S
|
||||
argument be to specified to
|
||||
.Nm
|
||||
which the shell can then tokenize.
|
||||
Normally,
|
||||
.Nm
|
||||
invokes
|
||||
.Xr strip 1
|
||||
directly.
|
||||
This flag implies
|
||||
.Fl s .
|
||||
.It Fl s
|
||||
.Nm
|
||||
exec's the command
|
||||
.Xr strip 1
|
||||
to strip binaries so that install can be portable over a large
|
||||
number of systems and binary types.
|
||||
If the environment variable
|
||||
.Ev STRIP
|
||||
is set, it is used as the
|
||||
.Xr strip 1
|
||||
program.
|
||||
.It Fl T Ar tags
|
||||
Specify the
|
||||
.Xr mtree 8
|
||||
tags to write out for the file when using
|
||||
.Fl M Ar metalog .
|
||||
.It Fl U
|
||||
Indicate that install is running unprivileged, and that it should not
|
||||
try to change the owner, the group, or the file flags of the destination.
|
||||
The information that would have been updated can be stored in a log
|
||||
file with
|
||||
.Fl M Ar metalog .
|
||||
.El
|
||||
.Pp
|
||||
By default,
|
||||
.Nm
|
||||
preserves all file flags, with the exception of the ``nodump'' flag.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility attempts to prevent copying a file onto itself.
|
||||
.Pp
|
||||
Installing
|
||||
.Pa /dev/null
|
||||
creates an empty file.
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width Fl
|
||||
.It Ev STRIP
|
||||
The program used to strip installed binaries when the
|
||||
.Fl s
|
||||
option is used.
|
||||
If unspecified,
|
||||
.Pa /usr/bin/strip
|
||||
is used.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr chflags 1 ,
|
||||
.Xr chgrp 1 ,
|
||||
.Xr chmod 1 ,
|
||||
.Xr cp 1 ,
|
||||
.Xr mv 1 ,
|
||||
.Xr strip 1 ,
|
||||
.Xr chown 8 ,
|
||||
.Xr mtree 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Bx 4.2 .
|
36
usr.bin/xinstall/pathnames.h
Normal file
36
usr.bin/xinstall/pathnames.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* $NetBSD: pathnames.h,v 1.6 2003/08/07 11:17:50 agc Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
#ifndef _PATH_STRIP
|
||||
#define _PATH_STRIP "/usr/bin/strip"
|
||||
#endif
|
1287
usr.bin/xinstall/xinstall.c
Normal file
1287
usr.bin/xinstall/xinstall.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue