* Copyright (c) 1987 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
"@(#) Copyright (c) 1987 Regents of the University of California.\n\
static char sccsid
[] = "@(#)xinstall.c 5.14 (Berkeley) %G%";
#define PERROR(head, msg) { \
static struct passwd
*pp
;
static int docopy
, dostrip
, mode
= 0755;
static char *group
, *owner
, pathbuf
[MAXPATHLEN
];
struct stat from_sb
, to_sb
;
while ((ch
= getopt(argc
, argv
, "cg:m:o:s")) != EOF
)
/* get group and owner id's */
if (group
&& !(gp
= getgrnam(group
))) {
fprintf(stderr
, "install: unknown group %s.\n", group
);
if (owner
&& !(pp
= getpwnam(owner
))) {
fprintf(stderr
, "install: unknown user %s.\n", owner
);
no_target
= stat(to_name
= argv
[argc
- 1], &to_sb
);
if (!no_target
&& (to_sb
.st_mode
& S_IFMT
) == S_IFDIR
) {
for (; *argv
!= to_name
; ++argv
)
install(*argv
, to_name
, 1);
/* can't do file1 file2 directory/file */
if (stat(*argv
, &from_sb
)) {
fprintf(stderr
, "install: can't find %s.\n", *argv
);
if ((to_sb
.st_mode
& S_IFMT
) != S_IFREG
) {
fprintf(stderr
, "install: %s isn't a regular file.\n", to_name
);
if (to_sb
.st_dev
== from_sb
.st_dev
&& to_sb
.st_ino
== from_sb
.st_ino
) {
fprintf(stderr
, "install: %s and %s are the same file.\n", *argv
, to_name
);
/* unlink now... avoid ETXTBSY errors later */
install(*argv
, to_name
, 0);
* build a path name and install the file
install(from_name
, to_name
, isdir
)
char *from_name
, *to_name
;
int devnull
, from_fd
, to_fd
;
/* if try to install NULL file to a directory, fails */
if (isdir
|| strcmp(from_name
, _PATH_DEVNULL
)) {
if (stat(from_name
, &from_sb
)) {
fprintf(stderr
, "install: can't find %s.\n", from_name
);
if ((from_sb
.st_mode
& S_IFMT
) != S_IFREG
) {
fprintf(stderr
, "install: %s isn't a regular file.\n", from_name
);
/* build the target path */
(void)sprintf(pathbuf
, "%s/%s", to_name
, (C
= rindex(from_name
, '/')) ? ++C
: from_name
);
/* unlink now... avoid ETXTBSY errors later */
if ((to_fd
= open(to_name
, O_CREAT
|O_WRONLY
|O_TRUNC
, 0)) < 0) {
PERROR("install: ", to_name
);
if ((from_fd
= open(from_name
, O_RDONLY
, 0)) < 0) {
PERROR("install: open: ", from_name
);
strip(from_fd
, from_name
, to_fd
, to_name
);
copy(from_fd
, from_name
, to_fd
, to_name
);
/* set owner, group, mode for target */
if (fchmod(to_fd
, mode
)) {
PERROR("install: fchmod: ", to_name
);
if ((group
|| owner
) && fchown(to_fd
, owner
? pp
->pw_uid
: -1,
group
? gp
->gr_gid
: -1)) {
PERROR("install: fchown: ", to_name
);
* copy file, strip(1)'ing it at the same time
strip(from_fd
, from_name
, to_fd
, to_name
)
register int from_fd
, to_fd
;
char *from_name
, *to_name
;
typedef struct exec EXEC
;
if (read(from_fd
, (char *)&head
, sizeof(head
)) < 0 || N_BADMAG(head
)) {
fprintf(stderr
, "install: %s not in a.out format.\n", from_name
);
if (head
.a_syms
|| head
.a_trsize
|| head
.a_drsize
) {
size
= (long)head
.a_text
+ head
.a_data
;
head
.a_syms
= head
.a_trsize
= head
.a_drsize
= 0;
if (head
.a_magic
== ZMAGIC
)
size
+= getpagesize() - sizeof(EXEC
);
if (write(to_fd
, (char *)&head
, sizeof(EXEC
)) != sizeof(EXEC
)) {
PERROR("install: write: ", to_name
);
/* sizeof(buf) guaranteed to fit in an int */
if ((n
= read(from_fd
, buf
, (int)MIN(size
, sizeof(buf
)))) <= 0)
else if (write(to_fd
, buf
, n
) != n
) {
PERROR("install: write: ", to_name
);
fprintf(stderr
, "install: read: %s: premature EOF.\n", from_name
);
PERROR("install: read: ", from_name
);
(void)lseek(from_fd
, 0L, L_SET
);
copy(from_fd
, from_name
, to_fd
, to_name
);
* copy from one file to another
copy(from_fd
, from_name
, to_fd
, to_name
)
register int from_fd
, to_fd
;
char *from_name
, *to_name
;
while ((n
= read(from_fd
, buf
, sizeof(buf
))) > 0)
if (write(to_fd
, buf
, n
) != n
) {
PERROR("install: write: ", to_name
);
PERROR("install: read: ", from_name
);
for (val
= 0; isdigit(*str
); ++str
)
val
= val
* 8 + *str
- '0';
* remove created target and die
* print a usage message and die
fputs("usage: install [-cs] [-g group] [-m mode] [-o owner] file1 file2;\n\tor file1 ... fileN directory\n", stderr
);