⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 install.c

📁 minix软件源代码
💻 C
字号:
/*	install 1.9 - 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 hard link if possible. */int cflag= 0;		/* Copy if you can't link, otherwise symlink. */int dflag= 0;		/* Create a directory. */int strip= 0;		/* Strip the copy. */char **compress= nil;	/* Compress utility to make a compressed executable. */char *zcat= nil;	/* Line one to decompress. */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);		}	}}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;	int status;	/* Source must exist as a plain file, dest may exist as a plain file. */	if (stat(source, &sst) < 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 (!S_ISREG(sst.st_mode)) {		fprintf(stderr, "install: %s is not a regular file\n", source);		return;	}	r= stat(dest, &dst);	if (r < 0) {		if (errno != ENOENT) { report(dest); return; }	} else {		if (!S_ISREG(dst.st_mode)) {			fprintf(stderr, "install: %s is not a regular file\n",									dest);			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);				return;			}			same= 1;		}	}	if (lflag && !same) {		/* Try to link the files. */		if (r >= 0 && unlink(dest) < 0) {			report(dest); return;		}		if (link(source, dest) >= 0) {			docopy= 0;		} else {			if (!cflag || errno != EXDEV) {				fprintf(stderr,					"install: can't link %s to %s: %s\n",					source, dest, strerror(errno));				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);		}	}	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) {		struct utimbuf ubuf;		ubuf.actime= dst.st_atime;		ubuf.modtime= sst.st_mtime;		if (utime(dest, &ubuf) < 0) { report(dest); return; }	}}void usage(void){	fprintf(stderr, "\Usage:\n\  install [-lcsz#] [-o owner] [-g group] [-m mode] [-S stack] [file1] file2\n\  install [-lcsz#] [-o owner] [-g group] [-m mode] [-S stack] file ... dir\n\  install -d [-o owner] [-g group] [-m mode] directory\n");	exit(1);}void 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 'l':	lflag= 1;	break;			case 'c':	cflag= 1;	break;			case 's':	strip= 1;	break;			case 'd':	dflag= 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 user\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 '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 && (cflag || 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 (stat(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);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -