Example #1
0
int
main(int argc, char *argv[])
{
	int	opt;
	int	params = 3;
	int	ret;
	char	**handle_args;
	char	*progname;

	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);
	if (init_yes() < 0) {
		(void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
		    strerror(errno));
		exit(BC_ERROR);
	}

	/*
	 * retro-compatibility: installing the bootblock is the default
	 * and there is no switch for it.
	 */
	do_install = B_TRUE;

	while ((opt = getopt(argc, argv, "dVMFfmneiu:")) != EOF) {
		switch (opt) {
		case 'm':
			write_mbr = B_TRUE;
			break;
		case 'n':
			nowrite = B_TRUE;
			break;
		case 'f':
			force_mbr = B_TRUE;
			break;
		case 'i':
			do_getinfo = B_TRUE;
			do_install = B_FALSE;
			params = 1;
			break;
		case 'V':
			verbose_dump = B_TRUE;
			break;
		case 'd':
			boot_debug = B_TRUE;
			break;
		case 'F':
			force_update = B_TRUE;
			break;
		case 'e':
			strip = B_TRUE;
			break;
		case 'M':
			do_mirror_bblk = B_TRUE;
			do_install = B_FALSE;
			params = 2;
			break;
		case 'u':
			do_version = B_TRUE;

			update_str = malloc(strlen(optarg) + 1);
			if (update_str == NULL) {
				(void) fprintf(stderr, gettext("Unable to "
				    "allocate memory\n"));
				exit(BC_ERROR);
			}
			(void) strlcpy(update_str, optarg, strlen(optarg) + 1);
			break;
		default:
			/* fall through to process non-optional args */
			break;
		}
	}

	/* check arguments */
	if (argc != optind + params) {
		usage(argv[0]);
		exit(BC_ERROR);
	}

	/*
	 * clean up options (and bail out if an unrecoverable combination is
	 * requested.
	 */
	progname = argv[0];
	check_options(progname);
	handle_args = argv + optind;

	if (nowrite)
		(void) fprintf(stdout, DRY_RUN);

	if (do_getinfo) {
		ret = handle_getinfo(progname, handle_args);
	} else if (do_mirror_bblk) {
		ret = handle_mirror(progname, handle_args);
	} else {
		ret = handle_install(progname, handle_args);
	}
	return (ret);
}
Example #2
0
int
main(int argc, char **argv)
{
	int	c, r;
	int	rflag	= 0;
	int	lflag	= 0;
	int	gflag	= 0;
	int	eflag	= 0;
	int	errflg	= 0;
	char *pp;
	FILE *fp, *tmpfp;
	struct stat stbuf;
	struct passwd *pwp;
	time_t omodtime;
	char *editor;
	uid_t ruid;
	pid_t pid;
	int stat_loc;
	int ret;
	char real_login[UNAMESIZE];
	int tmpfd = -1;
	pam_handle_t *pamh;
	int pam_error;
	char *buf;
	size_t buflen;

	(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
#define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
#endif
	(void) textdomain(TEXT_DOMAIN);

	if (init_yes() < 0) {
		(void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
		    strerror(errno));
		exit(1);
	}

	while ((c = getopt(argc, argv, "eglr")) != EOF)
		switch (c) {
			case 'e':
				eflag++;
				break;
			case 'g':
				gflag++;
				break;
			case 'l':
				lflag++;
				break;
			case 'r':
				rflag++;
				break;
			case '?':
				errflg++;
				break;
		}

	if (eflag + lflag + rflag > 1)
		errflg++;

	if (gflag && !lflag)
		errflg++;

	argc -= optind;
	argv += optind;
	if (errflg || argc > 1)
		crabort(BADUSAGE);

	ruid = getuid();
	if ((pwp = getpwuid(ruid)) == NULL)
		crabort(INVALIDUSER);

	if (strlcpy(real_login, pwp->pw_name, sizeof (real_login))
	    >= sizeof (real_login))
		crabort(NAMETOOLONG);

	if ((eflag || lflag || rflag) && argc == 1) {
		if ((pwp = getpwnam(*argv)) == NULL)
			crabort(INVALIDUSER);

		if (!cron_admin(real_login)) {
			if (pwp->pw_uid != ruid)
				crabort(NOTROOT);
			else
				pp = getuser(ruid);
		} else
			pp = *argv++;
	} else {
		pp = getuser(ruid);
	}

	if (pp == NULL) {
		if (per_errno == 2)
			crabort(BADSHELL);
		else
			crabort(INVALIDUSER);
	}
	if (strlcpy(login, pp, sizeof (login)) >= sizeof (login))
		crabort(NAMETOOLONG);
	if (!allowed(login, CRONALLOW, CRONDENY))
		crabort(NOTALLOWED);

	/* Do account validation check */
	pam_error = pam_start("cron", pp, NULL, &pamh);
	if (pam_error != PAM_SUCCESS) {
		crabort((char *)pam_strerror(pamh, pam_error));
	}
	pam_error = pam_acct_mgmt(pamh, PAM_SILENT);
	if (pam_error != PAM_SUCCESS) {
		(void) fprintf(stderr, gettext("Warning - Invalid account: "
		    "'%s' not allowed to execute cronjobs\n"), pp);
	}
	(void) pam_end(pamh, PAM_SUCCESS);


	/* check for unaudited shell */
	if (audit_crontab_not_allowed(ruid, pp))
		crabort(AUDITREJECT);

	cf = xmalloc(strlen(CRONDIR)+strlen(login)+2);
	strcat(strcat(strcpy(cf, CRONDIR), "/"), login);

	if (rflag) {
		r = unlink(cf);
		cron_sendmsg(DELETE, login, login, CRON);
		audit_crontab_delete(cf, r);
		exit(0);
	}
	if (lflag) {
		char sysconf[PATH_MAX];

		if (gflag) {
			if (snprintf(sysconf, sizeof (sysconf), "%s/%s",
			    SYSCRONDIR, login) < sizeof (sysconf) &&
			    (fp = fopen(sysconf, "r")) != NULL) {
				while (fgets(line, CTLINESIZE, fp) != NULL)
					fputs(line, stdout);
				fclose(fp);
				exit(0);
			} else {
				crabort(BADOPEN);
			}
		} else {
			if ((fp = fopen(cf, "r")) == NULL)
				crabort(BADOPEN);
			while (fgets(line, CTLINESIZE, fp) != NULL)
				fputs(line, stdout);
			fclose(fp);
			exit(0);
		}
	}
	if (eflag) {
		if ((fp = fopen(cf, "r")) == NULL) {
			if (errno != ENOENT)
				crabort(BADOPEN);
		}
		(void) strcpy(edtemp, "/tmp/crontabXXXXXX");
		tmpfd = mkstemp(edtemp);
		if (fchown(tmpfd, ruid, -1) == -1) {
			(void) close(tmpfd);
			crabort("fchown of temporary file failed");
		}
		(void) close(tmpfd);
		/*
		 * Fork off a child with user's permissions,
		 * to edit the crontab file
		 */
		if ((pid = fork()) == (pid_t)-1)
			crabort("fork failed");
		if (pid == 0) {		/* child process */
			/* give up super-user privileges. */
			setuid(ruid);
			if ((tmpfp = fopen(edtemp, "w")) == NULL)
				crabort("can't create temporary file");
			if (fp != NULL) {
				/*
				 * Copy user's crontab file to temporary file.
				 */
				while (fgets(line, CTLINESIZE, fp) != NULL) {
					fputs(line, tmpfp);
					if (ferror(tmpfp)) {
						fclose(fp);
						fclose(tmpfp);
						crabort("write error on"
						    "temporary file");
					}
				}
				if (ferror(fp)) {
					fclose(fp);
					fclose(tmpfp);
					crabort(BADREAD);
				}
				fclose(fp);
			}
			if (fclose(tmpfp) == EOF)
				crabort("write error on temporary file");
			if (stat(edtemp, &stbuf) < 0)
				crabort("can't stat temporary file");
			omodtime = stbuf.st_mtime;
#ifdef _XPG_NOTDEFINED
			editor = getenv("VISUAL");
			if (editor == NULL) {
#endif
				editor = getenv("EDITOR");
				if (editor == NULL)
					editor = VIPATH;
#ifdef _XPG_NOTDEFINED
			}
#endif
			buflen = strlen(editor) + strlen(edtemp) + 2;
			buf = xmalloc(buflen);
			(void) snprintf(buf, buflen, "%s %s", editor, edtemp);

			sleep(1);

			while (1) {
				ret = system(buf);

				/* sanity checks */
				if ((tmpfp = fopen(edtemp, "r")) == NULL)
					crabort("can't open temporary file");
				if (fstat(fileno(tmpfp), &stbuf) < 0)
					crabort("can't stat temporary file");
				if (stbuf.st_size == 0)
					crabort("temporary file empty");
				if (omodtime == stbuf.st_mtime) {
					(void) unlink(edtemp);
					fprintf(stderr, gettext(
					    "The crontab file was not"
					    " changed.\n"));
					exit(1);
				}
				if ((ret) && (errno != EINTR)) {
					/*
					 * Some editors (like 'vi') can return
					 * a non-zero exit status even though
					 * everything is okay. Need to check.
					 */
					fprintf(stderr, gettext(ED_ERROR));
					fflush(stderr);
					if (isatty(fileno(stdin))) {
						/* Interactive */
						fprintf(stdout,
						    gettext(ED_PROMPT),
						    yesstr, nostr, nostr);
						fflush(stdout);

						if (yes()) {
							/* Edit again */
							continue;
						} else {
							/* Dump changes */
							(void) unlink(edtemp);
							exit(1);
						}
					} else {
						/*
						 * Non-interactive, dump changes
						 */
						(void) unlink(edtemp);
						exit(1);
					}
				}
				exit(0);
			} /* while (1) */
		}

		/* fix for 1125555 - ignore common signals while waiting */
		(void) signal(SIGINT, SIG_IGN);
		(void) signal(SIGHUP, SIG_IGN);
		(void) signal(SIGQUIT, SIG_IGN);
		(void) signal(SIGTERM, SIG_IGN);
		wait(&stat_loc);
		if ((stat_loc & 0xFF00) != 0)
			exit(1);

		/*
		 * unlink edtemp as 'ruid'. The file contents will be held
		 * since we open the file descriptor 'tmpfp' before calling
		 * unlink.
		 */
		if (((ret = seteuid(ruid)) < 0) ||
		    ((tmpfp = fopen(edtemp, "r")) == NULL) ||
		    (unlink(edtemp) == -1)) {
			fprintf(stderr, "crontab: %s: %s\n",
			    edtemp, errmsg(errno));
			if ((ret < 0) || (tmpfp == NULL))
				(void) unlink(edtemp);
			exit(1);
		} else
			seteuid(0);

		copycron(tmpfp);
	} else {
		if (argc == 0)
			copycron(stdin);
		else if (seteuid(getuid()) != 0 || (fp = fopen(argv[0], "r"))
		    == NULL)
			crabort(BADOPEN);
		else {
			seteuid(0);
			copycron(fp);
		}
	}
	cron_sendmsg(ADD, login, login, CRON);
/*
 *	if (per_errno == 2)
 *		fprintf(stderr, gettext(WARNSHELL));
 */
	return (0);
}
Example #3
0
int
main(int argc, char **argv)
{
	int	j;
	struct inserts *psave;
	int c;
	int	initsize;
	char	*cmdname, **initlist;
	char	*arg;
	char	*next;

	/* initialization */
	blank = wctype("blank");
	n_inserts = 0;
	psave = saveargv;
	(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D 		*/
#define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't 		*/
#endif
	(void) textdomain(TEXT_DOMAIN);
	if (init_yes() < 0) {
		ermsg(_(ERR_MSG_INIT_YES), strerror(errno));
		exit(1);
	}

	parseargs(argc, argv);

	/* handling all of xargs arguments:				*/
	while ((c = getopt(mac, mav, "0tpe:E:I:i:L:l:n:s:x")) != EOF) {
		switch (c) {
		case '0':
			ZERO = TRUE;
			break;

		case 't':	/* -t: turn trace mode on		*/
			TRACE = TRUE;
			break;

		case 'p':	/* -p: turn on prompt mode.		*/
			if ((PROMPT = open("/dev/tty", O_RDONLY)) == -1) {
				PERR("can't read from tty for -p");
			} else {
				TRACE = TRUE;
			}
			break;

		case 'e':
			/*
			 * -e[eofstr]: set/disable end-of-file.
			 * N.B. that an argument *isn't* required here; but
			 * parseargs forced an argument if not was given.  The
			 * forced argument is the default...
			 */
			LEOF = optarg; /* can be empty */
			break;

		case 'E':
			/*
			 * -E eofstr: change end-of-file string.
			 * eofstr *is* required here, but can be empty:
			 */
			LEOF = optarg;
			break;

		case 'I':
			/* -I replstr: Insert mode. replstr *is* required. */
			INSERT = PER_LINE = LEGAL = TRUE;
			N_ARGS = 0;
			INSPAT = optarg;
			if (*optarg == '\0') {
				ermsg(_("Option requires an argument: -%c\n"),
				    c);
			}
			break;

		case 'i':
			/*
			 * -i [replstr]: insert mode, with *optional* replstr.
			 * N.B. that an argument *isn't* required here; if
			 * it's not given, then the string INSPAT_STR will
			 * be assumed.
			 *
			 * Since getopts(3C) doesn't handle the case of an
			 * optional variable argument at all, we have to
			 * parse this by hand:
			 */

			INSERT = PER_LINE = LEGAL = TRUE;
			N_ARGS = 0;
			if ((optarg != NULL) && (*optarg != '\0')) {
				INSPAT = optarg;
			} else {
				/*
				 * here, there is no next argument. so
				 * we reset INSPAT to the INSPAT_STR.
				 * we *have* to do this, as -i/I may have
				 * been given previously, and XCU4 requires
				 * that only "the last one specified takes
				 * effect".
				 */
				INSPAT = INSPAT_STR;
			}
			break;

		case 'L':
			/*
			 * -L number: # of times cmd is executed
			 * number *is* required here:
			 */
			PER_LINE = TRUE;
			N_ARGS = 0;
			INSERT = FALSE;
			if ((PER_LINE = atoi(optarg)) <= 0) {
				ermsg(_("#lines must be positive int: %s\n"),
				    optarg);
			}
			break;

		case 'l':
			/*
			 * -l [number]: # of times cmd is executed
			 * N.B. that an argument *isn't* required here; if
			 * it's not given, then 1 is assumed.
			 *
			 * parseargs handles the optional arg processing.
			 */

			PER_LINE = LEGAL = TRUE;  /* initialization	*/
			N_ARGS = 0;
			INSERT = FALSE;

			if ((optarg != NULL) && (*optarg != '\0')) {
				if ((PER_LINE = atoi(optarg)) <= 0)
					PER_LINE = 1;
			}
			break;

		case 'n':	/* -n number: # stdin args		*/
			/*
			 * -n number: # stdin args.
			 * number *is* required here:
			 */
			if ((N_ARGS = atoi(optarg)) <= 0) {
				ermsg(_("#args must be positive int: %s\n"),
				    optarg);
			} else {
				LEGAL = DASHX || N_ARGS == 1;
				INSERT = PER_LINE = FALSE;
			}
			break;

		case 's':	/* -s size: set max size of each arg list */
			BUFLIM = atoi(optarg);
			if (BUFLIM > BUFSIZE || BUFLIM <= 0) {
				ermsg(_("0 < max-cmd-line-size <= %d: %s\n"),
				    BUFSIZE, optarg);
			}
			break;

		case 'x':	/* -x: terminate if args > size limit	*/
			DASHX = LEGAL = TRUE;
			break;

		default:
			/*
			 * bad argument. complain and get ready to die.
			 */
			usage();
			exit(2);
			break;
		}
	}

	/*
	 * if anything called ermsg(), something screwed up, so
	 * we exit early.
	 */
	if (OK == FALSE) {
		usage();
		exit(2);
	}

	/*
	 * we're finished handling xargs's options, so now pick up
	 * the command name (if any), and it's options.
	 */


	mac -= optind;	/* dec arg count by what we've processed 	*/
	mav += optind;	/* inc to current mav				*/

	if (mac <= 0) {	/* if there're no more args to process,	*/
		cmdname = "/usr/bin/echo";	/* our default command	*/
		*ARGV++ = addarg(cmdname);	/* use the default cmd.	*/
	} else {	/* otherwise keep parsing rest of the string.	*/
		/*
		 * note that we can't use getopts(3C), and *must* parse
		 * this by hand, as we don't know apriori what options the
		 * command will take.
		 */
		cmdname = *mav;	/* get the command name	*/


		/* pick up the remaining args from the command line:	*/
		while ((OK == TRUE) && (mac-- > 0)) {
			/*
			 * while we haven't crapped out, and there's
			 * work to do:
			 */
			if (INSERT && ! ERR) {
				if (strstr(*mav, INSPAT) != NULL) {
					if (++n_inserts > MAXINSERTS) {
						ermsg(_("too many args "
						    "with %s\n"), INSPAT);
						ERR = TRUE;
					}
					psave->p_ARGV = ARGV;
					(psave++)->p_skel = *mav;
				}
			}
			*ARGV++ = addarg(*mav++);
		}
	}

	/* pick up args from standard input */

	initlist = ARGV;
	initsize = linesize;
	lastarg[0] = '\0';

	while (OK) {
		N_args = 0;
		N_lines = 0;
		ARGV = initlist;
		linesize = initsize;
		next = argbuf;

		while (MORE || (lastarg[0] != '\0')) {
			int l;

			if (*lastarg != '\0') {
				arg = strcpy(next, lastarg);
				*lastarg = '\0';
			} else if ((arg = getarg(next)) == NULL) {
				break;
			}

			l = strlen(arg) + 1;
			linesize += l;
			next += l;

			/* Inserts are handled specially later. */
			if ((n_inserts == 0) && (linesize >= BUFLIM)) {
				/*
				 * Legal indicates hard fail if the list is
				 * truncated due to size.  So fail, or if we
				 * cannot create any list because it would be
				 * too big.
				 */
				if (LEGAL || N_args == 0) {
					EMSG(LIST2LONG);
					exit(2);
					/* NOTREACHED */
				}

				/*
				 * Otherwise just save argument for later.
				 */
				(void) strcpy(lastarg, arg);
				break;
			}

			*ARGV++ = arg;

			N_args++;

			if ((PER_LINE && N_lines >= PER_LINE) ||
			    (N_ARGS && (N_args) >= N_ARGS)) {
				break;
			}


			if ((ARGV - arglist) == MAXARGS) {
				break;
			}
		}

		*ARGV = NULL;
		if (N_args == 0) {
			/* Reached the end with no more work. */
			exit(exitstat);
		}

		/* insert arg if requested */

		if (!ERR && INSERT) {

			p_ibuf = ins_buf;
			ARGV--;
			j = ibufsize = 0;
			for (psave = saveargv; ++j <= n_inserts; ++psave) {
				addibuf(psave);
				if (ERR)
					break;
			}
		}
		*ARGV = NULL;

		if (n_inserts > 0) {
			/*
			 * if we've done any insertions, re-calculate the
			 * linesize. bomb out if we've exceeded our length.
			 */
			linesize = 0;
			for (ARGV = arglist; *ARGV != NULL; ARGV++) {
				linesize += strlen(*ARGV) + 1;
			}
			if (linesize >= BUFLIM) {
				EMSG(LIST2LONG);
				exit(2);
				/* NOTREACHED */
			}
		}

		/* exec command */

		if (!ERR) {
			if (!MORE &&
			    (PER_LINE && N_lines == 0 || N_ARGS && N_args == 0))
				exit(exitstat);
			OK = TRUE;
			j = TRACE ? echoargs() : TRUE;
			if (j) {
				/*
				 * for xcu4, all invocations of cmdname must
				 * return 0, in order for us to return 0.
				 * so if we have a non-zero status here,
				 * quit immediately.
				 */
				exitstat |= lcall(cmdname, arglist);
			}
		}
	}

	if (OK)
		return (exitstat);

	/*
	 * if exitstat was set, to match XCU4 complience,
	 * return that value, otherwise, return 1.
	 */
	return (exitstat ? exitstat : 1);
}