Esempio n. 1
0
int
main(UNUSED(int argc), UNUSED(char *argv[]))
{
	int n, i;
	gid_t *list;
	gid_t gid = MY_GID();
	int gid_in_list = 0;

#ifdef HAVE_GETGROUPS
	if ((n = getgroups(0, NULL)) < 0) {
		perror("getgroups");
		return 1;
	}
#else
	n = 0;
#endif

	list = (gid_t*)malloc(sizeof (gid_t) * (n + 1));
	if (!list) {
		fprintf(stderr, "out of memory!\n");
		exit(1);
	}

#ifdef HAVE_GETGROUPS
	if (n > 0)
		n = getgroups(n, list);
#endif

	for (i = 0; i < n; i++)  {
		printf("%lu ", (unsigned long)list[i]);
		if (list[i] == gid)
			gid_in_list = 1;
	}
	/* The default gid might not be in the list on some systems. */
	if (!gid_in_list)
		printf("%lu", (unsigned long)gid);
	printf("\n");

	return 0;
}
Esempio n. 2
0
static void
edit_cmd(void) {
	char n[MAX_FNAME], q[MAX_TEMPSTR];
	const char *editor;
	FILE *f;
	int ch, t, x;
	sig_t oint, oabrt, oquit, ohup;
	struct stat statbuf;
	struct utimbuf utimebuf;
	long mtimensec;
	WAIT_T waiter;
	PID_T pid, xpid;

	log_it(RealUser, Pid, "BEGIN EDIT", User);
	if (!glue_strings(n, sizeof n, SPOOL_DIR, User, '/')) {
		errx(ERROR_EXIT, "path too long");
	}
	if (!(f = fopen(n, "r"))) {
		if (errno != ENOENT) {
			err(ERROR_EXIT, "cannot open `%s'", n);
		}
		warnx("no crontab for `%s' - using an empty one", User);
		if (!(f = fopen(_PATH_DEVNULL, "r"))) {
			err(ERROR_EXIT, "cannot open `%s'", _PATH_DEVNULL);
		}
	}

	if (fstat(fileno(f), &statbuf) < 0) {
		warn("cannot stat crontab file");
		goto fatal;
	}
	utimebuf.actime = statbuf.st_atime;
	utimebuf.modtime = statbuf.st_mtime;
	mtimensec = statbuf.st_mtimensec;

	/* Turn off signals. */
	ohup = signal(SIGHUP, SIG_IGN);
	oint = signal(SIGINT, SIG_IGN);
	oquit = signal(SIGQUIT, SIG_IGN);
	oabrt = signal(SIGABRT, SIG_IGN);

	if (!glue_strings(Filename, sizeof Filename, _PATH_TMP,
	    "crontab.XXXXXXXXXX", '/')) {
		warnx("path too long");
		goto fatal;
	}
	if (-1 == (t = mkstemp(Filename))) {
		warn("cannot create `%s'", Filename);
		goto fatal;
	}
#ifdef HAS_FCHOWN
	x = fchown(t, MY_UID(pw), MY_GID(pw));
#else
	x = chown(Filename, MY_UID(pw), MY_GID(pw));
#endif
	if (x < 0) {
		warn("cannot chown `%s'", Filename);
		goto fatal;
	}
	if (!(NewCrontab = fdopen(t, "r+"))) {
		warn("cannot open fd");
		goto fatal;
	}

	Set_LineNum(1);

	skip_header(&ch, f);

	/* copy the rest of the crontab (if any) to the temp file.
	 */
	for (; EOF != ch; ch = get_char(f))
		(void)putc(ch, NewCrontab);
	(void)fclose(f);
	if (fflush(NewCrontab) < OK) {
		err(ERROR_EXIT, "cannot flush output for `%s'", Filename);
	}
	(void)utime(Filename, &utimebuf);
 again:
	rewind(NewCrontab);
	if (ferror(NewCrontab)) {
		warn("error while writing new crontab to `%s'", Filename);
 fatal:
		(void)unlink(Filename);
		exit(ERROR_EXIT);
	}

	if (((editor = getenv("VISUAL")) == NULL || *editor == '\0') &&
	    ((editor = getenv("EDITOR")) == NULL || *editor == '\0')) {
		editor = EDITOR;
	}

	/* we still have the file open.  editors will generally rewrite the
	 * original file rather than renaming/unlinking it and starting a
	 * new one; even backup files are supposed to be made by copying
	 * rather than by renaming.  if some editor does not support this,
	 * then don't use it.  the security problems are more severe if we
	 * close and reopen the file around the edit.
	 */

	switch (pid = fork()) {
	case -1:
		warn("cannot fork");
		goto fatal;
	case 0:
		/* child */
		if (setgid(MY_GID(pw)) < 0) {
			err(ERROR_EXIT, "cannot setgid(getgid())");
		}
		if (setuid(MY_UID(pw)) < 0) {
			err(ERROR_EXIT, "cannot setuid(getuid())");
		}
		if (chdir(_PATH_TMP) < 0) {
			err(ERROR_EXIT, "cannot chdir to `%s'", _PATH_TMP);
		}
		if (!glue_strings(q, sizeof q, editor, Filename, ' ')) {
			errx(ERROR_EXIT, "editor command line too long");
		}
		(void)execlp(_PATH_BSHELL, _PATH_BSHELL, "-c", q, (char *)0);
		err(ERROR_EXIT, "cannot start `%s'", editor);
		/*NOTREACHED*/
	default:
		/* parent */
		break;
	}

	/* parent */
	for (;;) {
		xpid = waitpid(pid, &waiter, WUNTRACED);
		if (xpid == -1) {
			if (errno != EINTR)
				warn("waitpid() failed waiting for PID %ld "
				    "from `%s'", (long)pid, editor);
		} else if (xpid != pid) {
			warnx("wrong PID (%ld != %ld) from `%s'",
			    (long)xpid, (long)pid, editor);
			goto fatal;
		} else if (WIFSTOPPED(waiter)) {
			(void)kill(getpid(), WSTOPSIG(waiter));
		} else if (WIFEXITED(waiter) && WEXITSTATUS(waiter)) {
			warnx("`%s' exited with status %d\n",
			    editor, WEXITSTATUS(waiter));
			goto fatal;
		} else if (WIFSIGNALED(waiter)) {
			warnx("`%s' killed; signal %d (%score dumped)",
			    editor, WTERMSIG(waiter),
			    WCOREDUMP(waiter) ? "" : "no ");
			goto fatal;
		} else
			break;
	}
	(void)signal(SIGHUP, ohup);
	(void)signal(SIGINT, oint);
	(void)signal(SIGQUIT, oquit);
	(void)signal(SIGABRT, oabrt);

	if (fstat(t, &statbuf) < 0) {
		warn("cannot stat `%s'", Filename);
		goto fatal;
	}
	if (utimebuf.modtime == statbuf.st_mtime &&
	    mtimensec == statbuf.st_mtimensec) {
		warnx("no changes made to crontab");
		goto remove;
	}
	warnx("installing new crontab");
	switch (replace_cmd()) {
	case 0:
		break;
	case -1:
		for (;;) {
			(void)fpurge(stdin);
			(void)printf("Do you want to retry the same edit? ");
			(void)fflush(stdout);
			q[0] = '\0';
			(void) fgets(q, (int)sizeof(q), stdin);
			switch (q[0]) {
			case 'y':
			case 'Y':
				goto again;
			case 'n':
			case 'N':
				goto abandon;
			default:
				(void)printf("Enter Y or N\n");
			}
		}
		/*NOTREACHED*/
	case -2:
	abandon:
		warnx("edits left in `%s'", Filename);
		goto done;
	default:
		warnx("panic: bad switch() in replace_cmd()");
		goto fatal;
	}
 remove:
	(void)unlink(Filename);
 done:
	log_it(RealUser, Pid, "END EDIT", User);
}