/*+++*
 *  title:	_install.c
 *  abstract:	minimal BSD 4.2 installation program.
 *  author:	T.R.Hageman, Groningen, The Netherlands.
 *  created:	october 1991
 *  modified:
 *  description:
 *---*/

#define NOT_JOVE

#include "tune.h"

RCS("$Id: _install.c,v 14.31 1993/02/15 02:01:44 tom Exp tom $")

#undef NULL
#include <stdio.h>
#if _I_FCNTL
#   include <fcntl.h>
#endif
#ifdef MSDOS
#   include <io.h>
#endif

#ifndef O_RDONLY
#   define O_RDONLY	0
#endif
#ifndef O_BINARY
#   define O_BINARY	0
#endif

int	strip_flag = 0;
int	chmod_flag = -1;
int	copy_flag = 0;

char	buf[31*1024];

void copy __(( const char *_(src), const char *_(dest) ));
void
copy(src, dest)
const char	*src,
		*dest;
{
#if !vms
#   if _I_SYS_STAT - -1
#	include <sys/stat.h>
#   else
#	if _I_STAT
#	    include <stat.h>
#	endif
#   endif

	struct stat	st;
	register int	sfd, dfd, n;

	if ((sfd = open(src, O_RDONLY|O_BINARY)) < 0) {
		fprintf(stderr, "cp: cannot open \"%s\"\n", src);
		exit(EXIT_FAILURE);
	}
	if ((dfd = creat(dest, chmod_flag >= 0 ? chmod_flag : 0666)) < 0) {
		fprintf(stderr, "cp: cannot create \"%s\"\n", dest);
		exit(EXIT_FAILURE);
	}
#ifdef MSDOS	/* sigh... */
	if (setmode(dfd, O_BINARY) < 0) {
		fprintf(stderr, "cp: setmode error \"%s\"\n", dest);
		exit(EXIT_FAILURE);
	}
#endif
	while ((n = read(sfd, buf, (int) sizeof buf)) != 0) {
		if (n < 0) {
			fprintf(stderr, "cp: read error \"%s\"\n", src);
			exit(EXIT_FAILURE);
		}
		if (write(dfd, buf, n) != n) {
			fprintf(stderr, "cp: write error \"%s\" (device full?)\n", dest);
			exit(EXIT_FAILURE);
		}
	}
	close(dfd);
	if (fstat(sfd, &st) == 0) {		/* preserve times */
		time_t	times[2];

		times[0] = st.st_atime;
		times[1] = st.st_mtime;
		utime(dest, times);
	}
	close(sfd);
#else
	/* VMS Strikes again! The code above does not work since the
	   original file types are lost.  So do it the hard way. */

	char	command[BUFSIZ];

	sprintf(command, "copy %s %s", src, dest);
	system(command);
#endif /* vms */
}

#ifndef RENAME
#   if unix
int rename  __(( const char *_(src), const char *_(dest) ));
int
rename(src, dest)
const char	*src,
		*dest;
{
	if (link(src, dest) < 0 || unlink(src) < 0)
		return -1;
	return 0;
}
#   endif
#endif

void move __(( const char *_(src), const char *_(dest) ));
void
move(src, dest)
const char	*src,
		*dest;
{
	unlink(dest);				/* just to be sure */
	if (rename(src, dest) < 0) {
		copy(src, dest);
		unlink(src);
	}
}

void strip __(( const char *_(filename) ));
void
strip(filename)
const char	*filename;
{
	char	command[BUFSIZ];

	sprintf(command, "strip %s", filename);
	system(command);
}

void usage __(( void ));
void
usage()
{
	fprintf(stderr,
		"Usage: install [-cs] [-m mode] [source-file] [destination]\n");
}

int ato8 __(( const char *_(arg) ));
int
ato8(arg)
register const char	*arg;
{
	register char	c;
	register int	n = 0;

	while ((unsigned)(c = *arg++ - '0') < 8)
		n = (n << 3) + c;
	if (c += '0')
		return -1;
	return n;
}

main(argc, argv)
int	argc;
char	*argv[];
{
	while (--argc && (*++argv)[0] == '-') {
		switch ((*argv)[1]) {
		case 's':
			strip_flag = 1;
			break;
		case 'c':
			copy_flag = 1;
			break;
		case 'm':
			if (--argc) {
				chmod_flag = ato8(*++argv);
				break;
			}
		default:
			usage();
			exit(EXIT_FAILURE);
		}
	}
	if (argc < 2) {
		usage();
		exit(EXIT_FAILURE);
	}
	if (copy_flag)
		copy(argv[0], argv[1]);
	else
		move(argv[0], argv[1]);
	if (strip_flag)
		strip(argv[1]);
	if (chmod_flag >= 0)
		chmod(argv[1], chmod_flag);
	exit(EXIT_SUCCESS);
}

/*======================================================================
 * $Log: _install.c,v $
 * Revision 14.31  1993/02/15  02:01:44  tom
 * remove (void) casts.
 *
 * Revision 14.30  1993/01/26  18:43:18  tom
 * cleanup whitespace.
 *
 * Revision 14.28  1992/10/23  17:15:59  tom
 * move some system-dependent stuff to header files (esp. tune.h/portdefs.h).
 *
 * Revision 14.26  1992/08/26  23:57:07  tom
 * add RCS directives.
 *
 */
