* 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.19 (Berkeley) %G%";
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
)
mode
= setmode(optarg
, (mode_t
)0, 0);
if (mode
== (mode_t
)-1) {
"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");