* Copyright (c) 1987 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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
"@(#) Copyright (c) 1987 Regents of the University of California.\n\
static char sccsid
[] = "@(#)xinstall.c 5.24 (Berkeley) 7/1/90";
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
)
if (!(set
= setmode(optarg
))) {
"install: invalid file mode.\n");
/* 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
, 0600)) < 0) {
if ((from_fd
= open(from_name
, O_RDONLY
, 0)) < 0) {
copy(from_fd
, from_name
, to_fd
, to_name
);
* set owner, group, mode for target; do the chown first,
* chown may lose the setuid bits.
fchown(to_fd
, owner
? pp
->pw_uid
: -1, group
? gp
->gr_gid
: -1) ||
if (!docopy
&& !devnull
&& unlink(from_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
) {
* use strip(1) to strip the target file
execl(_PATH_STRIP
, "strip", to_name
, (char *)NULL
);
if (wait(&status
) == -1 || status
)
* print out an error message
(void)fprintf(stderr
, "install: %s: %s\n", s
, strerror(errno
));
* remove created target and die
* print a usage message and die
"usage: install [-cs] [-g group] [-m mode] [-o owner] file1 file2;\n\tor file1 ... fileN directory\n");