Example #1
0
static void
startpr(int enable)
{
	struct stat stbuf;

	if (cgetstr(bp, "sd", &SD) == -1)
		SD = _PATH_DEFSPOOL;
	if (cgetstr(bp, "lo", &LO) == -1)
		LO = DEFLOCK;
	(void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
	printf("%s:\n", printer);

	/*
	 * Turn off the owner execute bit of the lock file to enable printing.
	 * If we are marking the printer "up" also turn off group execute bit.
	 */
	PRIV_START;
	if (enable && stat(line, &stbuf) >= 0) {
		if (enable == 2)
			stbuf.st_mode &= ~(S_IXUSR|S_IXGRP);
		else
			stbuf.st_mode &= ~S_IXUSR;
		if (chmod(line, stbuf.st_mode & 0777) < 0)
			printf("\tcannot enable printing\n");
		else
			printf("\tprinting enabled\n");
	}
	PRIV_END;
	if (!startdaemon(printer))
		printf("\tcouldn't start daemon\n");
	else
		printf("\tdaemon started\n");
}
Example #2
0
/*ARGSUSED*/
int openmem(int trystart)
{
    initpkey();
    shmid = shmget(pkey, SHMFLAG, 0);
    if (shmid < 0) {            /* Could not find the shared memory */
  if (errno != ENOENT) {  /* Error other not created yet */
      perror("shmget");
      exit(1);
  }
  if (trystart==1){          /* Create the memory */
    startdaemon();
  }
  else if (trystart < 0){    /* Just checking if it exists */
    return 0;
  }
  else {                     /* Wanted to use it, but...   */
    fprintf(stderr,"Warning: Daemon not running!\n");
    exit(1);
  }
  shmid = shmget(pkey, SHMFLAG, 0);
  if (shmid < 0) {  /* This is a bummer of an error */
      ERROR(1, ("Daemon not running (err:%d)\n",errno));
      exit(1);
  }
    }
    sharedMemory = (struct memory *) shmat(shmid, 0, 0);
    if (sharedMemory == (struct memory *) -1) {
  printf("Error number: %d\n",errno);
  perror("shared memory");
  exit(1);
    }
    setup_memory(sharedMemory);
    opensem();
    return 1;
}
Example #3
0
void
rmjob(const char *printer)
{
	register int i, nitems;
	int assassinated = 0;
	struct dirent **files;
	char *cp;
	struct printer myprinter, *pp = &myprinter;

	init_printer(pp);
	if ((i = getprintcap(printer, pp)) < 0)
		fatal(pp, "getprintcap: %s", pcaperr(i));
	if ((cp = checkremote(pp))) {
		printf("Warning: %s\n", cp);
		free(cp);
	}

	/*
	 * If the format was `lprm -' and the user isn't the super-user,
	 *  then fake things to look like he said `lprm user'.
	 */
	if (users < 0) {
		if (getuid() == 0)
			all = 1;	/* all files in local queue */
		else {
			user[0] = person;
			users = 1;
		}
	}
	if (!strcmp(person, "-all")) {
		if (from_host == local_host)
			fatal(pp, "The login name \"-all\" is reserved");
		all = 1;	/* all those from 'from_host' */
		person = root;
	}

	seteuid(euid);
	if (chdir(pp->spool_dir) < 0)
		fatal(pp, "cannot chdir to spool directory");
	if ((nitems = scandir(".", &files, iscf, NULL)) < 0)
		fatal(pp, "cannot access spool directory");
	seteuid(uid);

	if (nitems) {
		/*
		 * Check for an active printer daemon (in which case we
		 *  kill it if it is reading our file) then remove stuff
		 *  (after which we have to restart the daemon).
		 */
		if (lockchk(pp, pp->lock_file) && chk(current)) {
			seteuid(euid);
			assassinated = kill(cur_daemon, SIGINT) == 0;
			seteuid(uid);
			if (!assassinated)
				fatal(pp, "cannot kill printer daemon");
		}
		/*
		 * process the files
		 */
		for (i = 0; i < nitems; i++)
			process(pp, files[i]->d_name);
	}
	rmremote(pp);
	/*
	 * Restart the printer daemon if it was killed
	 */
	if (assassinated && !startdaemon(pp))
		fatal(pp, "cannot restart printer daemon\n");
	exit(0);
}
Example #4
0
int
main(int argc, char *argv[])
{
	struct passwd *pw;
	struct group *gptr;
	const char *arg, *cp, *printer;
	char *p;
	char buf[BUFSIZ];
	int c, i, f, errs;
	int	 ret, didlink;
	struct stat stb;
	struct stat statb1, statb2;
	struct printer myprinter, *pp = &myprinter;

	printer = NULL;
	euid = geteuid();
	uid = getuid();
	PRIV_END
	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
		signal(SIGHUP, cleanup);
	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
		signal(SIGINT, cleanup);
	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
		signal(SIGQUIT, cleanup);
	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
		signal(SIGTERM, cleanup);

	progname = argv[0];
	gethostname(local_host, sizeof(local_host));
	openlog("lpd", 0, LOG_LPR);

	errs = 0;
	while ((c = getopt(argc, argv,
			   ":#:1:2:3:4:C:J:L:P:T:U:Z:cdfghi:lnmprstvw:"))
	       != -1)
		switch (c) {
		case '#':		/* n copies */
			i = strtol(optarg, &p, 10);
			if (*p)
				errx(1, "Bad argument to -#, number expected");
			if (i > 0)
				ncopies = i;
			break;

		case '1':		/* troff fonts */
		case '2':
		case '3':
		case '4':
			fonts[optopt - '1'] = optarg;
			break;

		case 'C':		/* classification spec */
			hdr++;
			class = optarg;
			break;

		case 'J':		/* job name */
			hdr++;
			jobname = optarg;
			break;

		case 'P':		/* specifiy printer name */
			printer = optarg;
			break;

		case 'L':               /* pr's locale */
			locale = optarg;
			break;

		case 'T':		/* pr's title line */
			title = optarg;
			break;

		case 'U':		/* user name */
			hdr++;
			Uflag = optarg;
			break;

		case 'Z':
			Zflag = optarg;
			break;

		case 'c':		/* print cifplot output */
		case 'd':		/* print tex output (dvi files) */
		case 'g':		/* print graph(1G) output */
		case 'l':		/* literal output */
		case 'n':		/* print ditroff output */
		case 't':		/* print troff output (cat files) */
		case 'p':		/* print using ``pr'' */
		case 'v':		/* print vplot output */
			format = optopt;
			break;

		case 'f':		/* print fortran output */
			format = 'r';
			break;

		case 'h':		/* nulifiy header page */
			hdr = 0;
			break;

		case 'i':		/* indent output */
			iflag++;
			indent = strtol(optarg, &p, 10);
			if (*p)
				errx(1, "Bad argument to -i, number expected");
			break;

		case 'm':		/* send mail when done */
			mailflg++;
			break;

		case 'q':		/* just queue job */
			qflag++;
			break;

		case 'r':		/* remove file when done */
			rflag++;
			break;

		case 's':		/* try to link files */
			sflag++;
			break;

		case 'w':		/* versatec page width */
			width = optarg;
			break;

		case ':':		/* catch "missing argument" error */
			if (optopt == 'i') {
				iflag++; /* -i without args is valid */
				indent = 8;
			} else
				errs++;
			break;

		default:
			errs++;
		}
	argc -= optind;
	argv += optind;
	if (errs)
		usage();
	if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
		printer = DEFLP;
	chkprinter(printer, pp);
	if (pp->no_copies && ncopies > 1)
		errx(1, "multiple copies are not allowed");
	if (pp->max_copies > 0 && ncopies > pp->max_copies)
		errx(1, "only %ld copies are allowed", pp->max_copies);
	/*
	 * Get the identity of the person doing the lpr using the same
	 * algorithm as lprm.  Actually, not quite -- lprm will override
	 * the login name with "root" if the user is running as root;
	 * the daemon actually checks for the string "root" in its
	 * permission checking.  Sigh.
	 */
	userid = getuid();
	if (Uflag) {
		if (userid != 0 && userid != pp->daemon_user)
			errx(1, "only privileged users may use the `-U' flag");
		lpr_username = Uflag;		/* -U person doing 'lpr' */
	} else {
		lpr_username = getlogin();	/* person doing 'lpr' */
		if (userid != pp->daemon_user || lpr_username == 0) {
			if ((pw = getpwuid(userid)) == NULL)
				errx(1, "Who are you?");
			lpr_username = pw->pw_name;
		}
	}

	/*
	 * Check for restricted group access.
	 */
	if (pp->restrict_grp != NULL && userid != pp->daemon_user) {
		if ((gptr = getgrnam(pp->restrict_grp)) == NULL)
			errx(1, "Restricted group specified incorrectly");
		if (gptr->gr_gid != getgid()) {
			while (*gptr->gr_mem != NULL) {
				if ((strcmp(lpr_username, *gptr->gr_mem)) == 0)
					break;
				gptr->gr_mem++;
			}
			if (*gptr->gr_mem == NULL)
				errx(1, "Not a member of the restricted group");
		}
	}
	/*
	 * Check to make sure queuing is enabled if userid is not root.
	 */
	lock_file_name(pp, buf, sizeof buf);
	if (userid && stat(buf, &stb) == 0 && (stb.st_mode & LFM_QUEUE_DIS))
		errx(1, "Printer queue is disabled");
	/*
	 * Initialize the control file.
	 */
	mktemps(pp);
	tfd = nfile(tfname);
	PRIV_START
	(void) fchown(tfd, pp->daemon_user, -1);
	/* owned by daemon for protection */
	PRIV_END
	card('H', local_host);
	card('P', lpr_username);
	card('C', class);
	if (hdr && !pp->no_header) {
		if (jobname == NULL) {
			if (argc == 0)
				jobname = "stdin";
			else
				jobname = ((arg = strrchr(argv[0], '/'))
					   ? arg + 1 : argv[0]);
		}
		card('J', jobname);
		card('L', lpr_username);
	}
	if (format != 'p' && Zflag != 0)
		card('Z', Zflag);
	if (iflag)
		card('I', itoa(indent));
	if (mailflg)
		card('M', lpr_username);
	if (format == 't' || format == 'n' || format == 'd')
		for (i = 0; i < 4; i++)
			if (fonts[i] != NULL)
				card('1'+i, fonts[i]);
	if (width != NULL)
		card('W', width);
	/*
	 * XXX
	 * Our use of `Z' here is incompatible with LPRng's
	 * use.  We assume that the only use of our existing
	 * `Z' card is as shown for `p' format (pr) files.
	 */
	if (format == 'p') {
		char *s;

		if (locale)
			card('Z', locale);
		else if ((s = setlocale(LC_TIME, "")) != NULL)
			card('Z', s);
	}

	/*
	 * Read the files and spool them.
	 */
	if (argc == 0)
		copy(pp, 0, " ");
	else while (argc--) {
		if (argv[0][0] == '-' && argv[0][1] == '\0') {
			/* use stdin */
			copy(pp, 0, " ");
			argv++;
			continue;
		}
		if ((f = test(arg = *argv++)) < 0)
			continue;	/* file unreasonable */

		if (sflag && (cp = linked(arg)) != NULL) {
			(void)snprintf(buf, sizeof(buf), "%ju %ju",
			    (uintmax_t)statb.st_dev, (uintmax_t)statb.st_ino);
			card('S', buf);
			if (format == 'p')
				card('T', title ? title : arg);
			for (i = 0; i < ncopies; i++)
				card(format, &dfname[inchar-2]);
			card('U', &dfname[inchar-2]);
			if (f)
				card('U', cp);
			card('N', arg);
			dfname[inchar]++;
			nact++;
			continue;
		}
		if (sflag)
			printf("%s: %s: not linked, copying instead\n",
			    progname, arg);

		if (f) {
			/*
			 * The user wants the file removed after it is copied
			 * to the spool area, so see if the file can be moved
			 * instead of copy/unlink'ed.  This is much faster and
			 * uses less spool space than copying the file.  This
			 * can be very significant when running services like
			 * samba, pcnfs, CAP, et al.
			 */
			PRIV_START
			didlink = 0;
			/*
			 * There are several things to check to avoid any
			 * security issues.  Some of these are redundant
			 * under BSD's, but are necessary when lpr is built
			 * under some other OS's (which I do do...)
			 */
			if (lstat(arg, &statb1) < 0)
				goto nohardlink;
			if (S_ISLNK(statb1.st_mode))
				goto nohardlink;
			if (link(arg, dfname) != 0)
				goto nohardlink;
			didlink = 1;
			/*
			 * Make sure the user hasn't tried to trick us via
			 * any race conditions
			 */
			if (lstat(dfname, &statb2) < 0)
				goto nohardlink;
			if (statb1.st_dev != statb2.st_dev)
				goto nohardlink;
			if (statb1.st_ino != statb2.st_ino)
				goto nohardlink;
			/*
			 * Skip if the file already had multiple hard links,
			 * because changing the owner and access-bits would
			 * change ALL versions of the file
			 */
			if (statb2.st_nlink > 2)
				goto nohardlink;
			/*
			 * If we can access and remove the original file
			 * without special setuid-ness then this method is
			 * safe.  Otherwise, abandon the move and fall back
			 * to the (usual) copy method.
			 */
			PRIV_END
			ret = access(dfname, R_OK);
			if (ret == 0)
				ret = unlink(arg);
			PRIV_START
			if (ret != 0)
				goto nohardlink;
			/*
			 * Unlink of user file was successful.  Change the
			 * owner and permissions, add entries to the control
			 * file, and skip the file copying step.
			 */
			chown(dfname, pp->daemon_user, getegid());
			chmod(dfname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
			PRIV_END
			if (format == 'p')
				card('T', title ? title : arg);
			for (i = 0; i < ncopies; i++)
				card(format, &dfname[inchar-2]);
			card('U', &dfname[inchar-2]);
			card('N', arg);
			nact++;
			continue;
		nohardlink:
			if (didlink)
				unlink(dfname);
			PRIV_END           /* restore old uid */
		} /* end: if (f) */

		if ((i = open(arg, O_RDONLY)) < 0) {
			printf("%s: cannot open %s\n", progname, arg);
		} else {
			copy(pp, i, arg);
			(void) close(i);
			if (f && unlink(arg) < 0)
				printf("%s: %s: not removed\n", progname, arg);
		}
	}

	if (nact) {
		(void) close(tfd);
		tfname[inchar]--;
		/*
		 * Touch the control file to fix position in the queue.
		 */
		PRIV_START
		if ((tfd = open(tfname, O_RDWR)) >= 0) {
			char touch_c;

			if (read(tfd, &touch_c, 1) == 1 &&
			    lseek(tfd, (off_t)0, 0) == 0 &&
			    write(tfd, &touch_c, 1) != 1) {
				printf("%s: cannot touch %s\n", progname,
				    tfname);
				tfname[inchar]++;
				cleanup(0);
			}
			(void) close(tfd);
		}
		if (link(tfname, cfname) < 0) {
			printf("%s: cannot rename %s\n", progname, cfname);
			tfname[inchar]++;
			cleanup(0);
		}
		unlink(tfname);
		PRIV_END
		if (qflag)		/* just q things up */
			exit(0);
		if (!startdaemon(pp))
			printf("jobs queued, but cannot start daemon.\n");
		exit(0);
	}
	cleanup(0);
	return (1);
	/* NOTREACHED */
}
Example #5
0
File: lpr.c Project: ryo/netbsd-src
int
main(int argc, char *argv[])
{
	struct passwd *pw;
	struct group *gptr;
	char *arg;
	const char *cp;
	char buf[MAXPATHLEN];
	int i, f, errs, c;
	struct stat stb;
	int oerrno;

	euid = geteuid();
	uid = getuid();
	seteuid(uid);

	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
		signal(SIGHUP, cleanup);
	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
		signal(SIGINT, cleanup);
	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
		signal(SIGQUIT, cleanup);
	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
		signal(SIGTERM, cleanup);

	setprogname(*argv);
	gethostname(host, sizeof (host));
	host[sizeof(host) - 1] = '\0';
	openlog("lpd", 0, LOG_LPR);

	errs = 0;
	while ((c = getopt(argc, argv,
	    ":#:1:2:3:4:C:J:P:RT:U:cdfghi:lmnopqrstvw:")) != -1) {
		switch (c) {

		case '#':		/* n copies */
			if (isdigit((unsigned char)*optarg)) {
				i = atoi(optarg);
				if (i > 0)
					ncopies = i;
			}
			break;

		case '4':		/* troff fonts */
		case '3':
		case '2':
		case '1':
			fonts[optopt - '1'] = optarg;
			break;

		case 'C':		/* classification spec */
			hdr++;
			class = optarg;
			break;

		case 'J':		/* job name */
			hdr++;
			jobname = optarg;
			break;

		case 'P':		/* specifiy printer name */
			printer = optarg;
			break;

		case 'R':		/* print request id */
			Rflag++;
			break;
			
		case 'T':		/* pr's title line */
			title = optarg;
			break;

		case 'U':		/* user name */
			hdr++;
			person = optarg;
			break;

		case 'c':		/* print cifplot output */
		case 'd':		/* print tex output (dvi files) */
		case 'g':		/* print graph(1G) output */
		case 'l':		/* literal output */
		case 'o':		/* print postscript output */
		case 'n':		/* print ditroff output */
		case 'p':		/* print using ``pr'' */
		case 't':		/* print troff output (cat files) */
		case 'v':		/* print vplot output */
			format = optopt;
			break;

		case 'f':		/* print fortran output */
			format = 'r';
			break;

		case 'h':		/* toggle want of header page */
			hdr = !hdr;
			break;

		case 'i':		/* indent output */
			iflag++;
			indent = atoi(optarg);
			if (indent < 0)
				indent = 8;
			break;

		case 'm':		/* send mail when done */
			mailflg++;
			break;

		case 'q':		/* just q job */
			qflag++;
			break;

		case 'r':		/* remove file when done */
			rflag++;
			break;

		case 's':		/* try to link files */
			sflag++;
			break;

		case 'w':		/* versatec page width */
			width = optarg;
			break;

		case ':':               /* catch "missing argument" error */
			if (optopt == 'i') {
				iflag++; /* -i without args is valid */
				indent = 8;
			} else
				errs++;
			break;

		default:
			errs++;
		}
	}
	argc -= optind;
	argv += optind;
	if (errs)
		usage();
	if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
		printer = DEFLP;
	chkprinter(printer);
	if (SC && ncopies > 1)
		errx(EXIT_FAILURE, "multiple copies are not allowed");
	if (MC > 0 && ncopies > MC)
		errx(EXIT_FAILURE, "only %ld copies are allowed", MC);
	/*
	 * Get the identity of the person doing the lpr using the same
	 * algorithm as lprm. 
	 */
	userid = getuid();
	if (userid != DU || person == 0) {
		if ((pw = getpwuid(userid)) == NULL)
			errx(EXIT_FAILURE, "Who are you?");
		person = pw->pw_name;
	}
	/*
	 * Check for restricted group access.
	 */
	if (RG != NULL && userid != DU) {
		if ((gptr = getgrnam(RG)) == NULL)
			errx(EXIT_FAILURE,
			     "Restricted group specified incorrectly");
		if (gptr->gr_gid != getgid()) {
			while (*gptr->gr_mem != NULL) {
				if ((strcmp(person, *gptr->gr_mem)) == 0)
					break;
				gptr->gr_mem++;
			}
			if (*gptr->gr_mem == NULL)
				errx(EXIT_FAILURE,
				     "Not a member of the restricted group");
		}
	}
	/*
	 * Check to make sure queuing is enabled if userid is not root.
	 */
	(void)snprintf(buf, sizeof buf, "%s/%s", SD, LO);
	if (userid && stat(buf, &stb) == 0 && (stb.st_mode & S_IXGRP))
		errx(EXIT_FAILURE, "Printer queue is disabled");
	/*
	 * Initialize the control file.
	 */
	mktemps();
	tfd = nfile(tfname);
	seteuid(euid);
	(void)fchown(tfd, DU, -1);	/* owned by daemon for protection */
	seteuid(uid);
	card('H', host);
	card('P', person);
	if (hdr && !SH) {
		if (jobname == NULL) {
			if (argc == 0)
				jobname = "stdin";
			else
				jobname = (arg = strrchr(argv[0], '/')) ?
				    arg+1 : argv[0];
		}
		card('J', jobname);
		card('C', class);
		card('L', person);
	}
	if (iflag)
		card('I', itoa(indent));
	if (mailflg)
		card('M', person);
	if (format == 't' || format == 'n' || format == 'd')
		for (i = 0; i < 4; i++)
			if (fonts[i] != NULL)
				card('1'+i, fonts[i]);
	if (width != NULL)
		card('W', width);

	/*
	 * Read the files and spool them.
	 */
	if (argc == 0)
		copy(0, " ");
	else while (argc--) {
		if (argv[0][0] == '-' && argv[0][1] == '\0') {
			/* use stdin */
			copy(0, " ");
			argv++;
			continue;
		}
		if ((f = test(arg = *argv++)) < 0)
			continue;	/* file unreasonable */

		if (sflag && (cp = linked(arg)) != NULL) {
			(void)snprintf(buf, sizeof buf,
			    "%llu %llu",
			    (unsigned long long)statb.st_dev,
			    (unsigned long long)statb.st_ino);
			card('S', buf);
			if (format == 'p')
				card('T', title ? title : arg);
			for (i = 0; i < ncopies; i++)
				card(format, &dfname[inchar-2]);
			card('U', &dfname[inchar-2]);
			if (f)
				card('U', cp);
			card('N', arg);
			dfname[inchar]++;
			nact++;
			continue;
		}
		if (sflag)
			warnx("%s: not linked, copying instead", arg);
		seteuid(uid);
		if ((i = open(arg, O_RDONLY)) < 0) {
			oerrno = errno;
			seteuid(uid);
			errno = oerrno;
			warn("cannot open %s", arg);
			continue;
		} else {
			copy(i, arg);
			(void)close(i);
			if (f && unlink(arg) < 0)
				warn("%s: not removed", arg);
		}
		seteuid(uid);
	}

	if (nact) {
		(void)close(tfd);
		tfname[inchar]--;
		/*
		 * Touch the control file to fix position in the queue.
		 */
		seteuid(euid);
		if ((tfd = open(tfname, O_RDWR)) >= 0) {
			char ch;

			if (read(tfd, &ch, 1) == 1 &&
			    lseek(tfd, (off_t)0, 0) == 0 &&
			    write(tfd, &ch, 1) != 1) {
				warn("cannot touch %s", tfname);
				tfname[inchar]++;
				cleanup(0);
			}
			(void)close(tfd);
		}
		if (link(tfname, cfname) < 0) {
			warn("cannot rename %s", cfname);
			tfname[inchar]++;
			cleanup(0);
		}
		unlink(tfname);
		seteuid(uid);
		if (Rflag)
			printf("request id is %d\n", reqid);
		if (qflag)		/* just queue things up */
			exit(0);
		if (!startdaemon(printer))
			printf("jobs queued, but cannot start daemon.\n");
		exit(0);
	}
	cleanup(0);
#ifdef __GNUC__
	return (0);
#endif
	/* NOTREACHED */
}
Example #6
0
void
rmjob(void)
{
	int i, nitems;
	int assassinated = 0;
	struct dirent **files;
	char *cp;

	if ((i = cgetent(&bp, printcapdb, printer)) == -2)
		fatal("can't open printer description file");
	else if (i == -1)
		fatal("unknown printer");
	else if (i == -3)
		fatal("potential reference loop detected in printcap file");
	if (cgetstr(bp, DEFLP, &LP) < 0)
		LP = _PATH_DEFDEVLP;
	if (cgetstr(bp, "rp", &RP) < 0)
		RP = DEFLP;
	if (cgetstr(bp, "sd", &SD) < 0)
		SD = _PATH_DEFSPOOL;
	if (cgetstr(bp,"lo", &LO) < 0)
		LO = DEFLOCK;
	cgetstr(bp, "rm", &RM);
	if ((cp = checkremote()) != NULL)
		printf("Warning: %s\n", cp);

	/*
	 * If the format was `lprm -' and the user isn't the super-user,
	 *  then fake things to look like he said `lprm user'.
	 */
	if (users < 0) {
		if (getuid() == 0)
			all = 1;	/* all files in local queue */
		else {
			user[0] = person;
			users = 1;
		}
	}
	if (!strcmp(person, "-all")) {
		if (from == host)
			fatal("The login name \"-all\" is reserved");
		all = 1;	/* all those from 'from' */
		person = root;
	}

	PRIV_START;
	if (chdir(SD) < 0)
		fatal("cannot chdir to spool directory");
	if ((nitems = scandir(".", &files, iscf, NULL)) < 0)
		fatal("cannot access spool directory");
	PRIV_END;

	if (nitems) {
		/*
		 * Check for an active printer daemon.  If one is running
		 * and it is reading our file, kill it, then remove stuff.
		 * Lastly, restart the daemon if it is not (or no longer)
		 * running.
		 */
		if (lockchk(LO) && chk(current)) {
			PRIV_START;
			assassinated = kill(cur_daemon, SIGINT) == 0;
			PRIV_END;
			if (!assassinated)
				fatal("cannot kill printer daemon");
		}
		/*
		 * process the files
		 */
		for (i = 0; i < nitems; i++)
			process(files[i]->d_name);
	}
	rmremote();
	/*
	 * Restart the printer daemon if it was killed
	 */
	if (assassinated && !startdaemon(printer))
		fatal("cannot restart printer daemon");
	exit(0);
}
void 
openmem(int code, int leagueflag)
{
    extern int errno;		/* to get error number */
    key_t   shmemKey = PKEY;	/* shared memory's key */
    struct memory *sharedMemory;/* to point to shared memory */
    char   *k;

    k = getenv("TREKSHMKEY");	/* grab shared mem id environment variable */
    if (k) {			/* if it's set... */
	int     i;
	if (sscanf(k, "%d", &i) > 0 && i > 0)	/* ...grab its value... */
	    shmemKey = i;	/* ...and use it */
    }

    errno = 0;			/* clear error number */
    shmid = shmget(shmemKey, 0, 0);	/* get id of shared mem */
    if (code == 2) {
	if (shmid >= 0) {
	    /* If we're in daemon mode and we opened the memory */
	    /* "There can be only one". */
	    fprintf(stderr, "Killing existing segment\n");
	    shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0);
	    /* create a new one */
	}
	shmid = shmget(shmemKey, sizeof(struct memory), IPC_CREAT | 0666);
    }
    if (shmid < 0) {		/* if shared mem does not exist */
	switch (code) {
	case 0:
	    if (errno != ENOENT) {	/* catastrophic, sell all your stock */
		perror("shmget");	/* and leave the country type of */
		exit(1);	/* error--suicide */
	    }
	    fprintf(stderr, "Daemon not running (err:%d)\n", errno);
	    exit(1);
	case 1:
	    if (errno != ENOENT) {	/* catastrophic, sell all your stock */
		perror("shmget");	/* and leave the country type of */
		exit(1);	/* error--suicide */
	    }
	    startdaemon(leagueflag, 0);	/* try to start the daemon */
	    sleep(2);		/* wait for a sec for deamon to start */
	    shmid = shmget(shmemKey, 0, 0);	/* try again to get shared
						   mem */
	    if (shmid < 0) {	/* failure again then get out of here */
		fprintf(stderr, "Daemon not running (err:%d)\n", errno);
		exit(1);
	    }
	    break;
	case 2:
	    perror("daemon: can't open shared memory");
	    exit(1);
	}
    }
    if (code == 2) {
	struct shmid_ds smbuf;

	shmctl(shmid, IPC_STAT, &smbuf);	/* Hose Ed's robots */
	smbuf.shm_perm.uid = geteuid();
	smbuf.shm_perm.mode = 0666;
	shmctl(shmid, IPC_SET, &smbuf);
    }
    sharedMemory = (struct memory *) shmat(shmid, (char *) 0, 0);
    if (sharedMemory == (struct memory *)(-1)) {
	perror("shared memory");
	exit(1);
    }
    if (code == 2) {
	/* set the magic number */
	sharedMemory->shmem_size = sizeof(struct memory);
    }
    else {
	if (sharedMemory->shmem_size != sizeof(struct memory)) {
	    fprintf(stderr, "shared memory segment magic number mismatch!\
 (%d != %ld)\n  aborting to prevent corruption of game data\n",
		    sharedMemory->shmem_size, (long) sizeof(struct memory));
	    exit(1);
	}
    }
Example #8
0
int
main(int argc, char **argv)
{
	struct passwd *pw;
	struct group *gptr;
	char *arg, *cp;
	char buf[MAXPATHLEN];
	int i, f, ch;
	struct stat stb;

	/*
	 * Simulate setuid daemon w/ PRIV_END called.
	 * We don't want lpr to actually be setuid daemon since that
	 * requires that the lpr binary be owned by user daemon, which
	 * is potentially unsafe.
	 */
	if ((pw = getpwuid(DEFUID)) == NULL)
		errx(1, "daemon uid (%u) not in password file", DEFUID);
	effective_uid = pw->pw_uid;
	real_uid = getuid();
	effective_gid = pw->pw_gid;
	real_gid = getgid();
	setresgid(real_gid, real_gid, effective_gid);
	setresuid(real_uid, real_uid, effective_uid);

	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
		signal(SIGHUP, cleanup);
	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
		signal(SIGINT, cleanup);
	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
		signal(SIGQUIT, cleanup);
	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
		signal(SIGTERM, cleanup);

	gethostname(host, sizeof (host));
	openlog("lpr", 0, LOG_LPR);

	while ((ch = getopt(argc, argv,
	    ":#:1:2:3:4:C:J:P:T:U:cdfghi:lmnpqrstvw:")) != -1) {
		switch (ch) {

		case '#':		/* n copies */
			if (isdigit((unsigned char)*optarg)) {
				i = atoi(optarg);
				if (i > 0)
					ncopies = i;
			}
			break;

		case '4':		/* troff fonts */
		case '3':
		case '2':
		case '1':
			fonts[ch - '1'] = optarg;
			break;

		case 'C':		/* classification spec */
			hdr++;
			class = optarg;
			break;

		case 'J':		/* job name */
			hdr++;
			jobname = optarg;
			break;

		case 'P':		/* specifiy printer name */
			printer = optarg;
			break;

		case 'T':		/* pr's title line */
			title = optarg;
			break;

		case 'U':		/* user name */
			hdr++;
			person = optarg;
			break;

		case 'c':		/* print cifplot output */
		case 'd':		/* print tex output (dvi files) */
		case 'g':		/* print graph(1G) output */
		case 'l':		/* literal output */
		case 'n':		/* print ditroff output */
		case 'p':		/* print using ``pr'' */
		case 't':		/* print troff output (cat files) */
		case 'v':		/* print vplot output */
			format = ch;
			break;

		case 'f':		/* print fortran output */
			format = 'r';
			break;

		case 'h':		/* toggle want of header page */
			hdr = !hdr;
			break;

		case 'i':		/* indent output */
			iflag++;
			indent = atoi(optarg);
			if (indent < 0)
				indent = 8;
			break;

		case 'm':		/* send mail when done */
			mailflg++;
			break;

		case 'q':		/* just q job */
			qflag++;
			break;

		case 'r':		/* remove file when done */
			rflag++;
			break;

		case 's':		/* try to link files */
			sflag++;
			break;

		case 'w':		/* versatec page width */
			width = optarg;
			break;

		case ':':               /* catch "missing argument" error */
			if (optopt == 'i') {
				iflag++; /* -i without args is valid */
				indent = 8;
			} else
				usage();
			break;

		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
		printer = DEFLP;
	chkprinter(printer);
	if (SC && ncopies > 1)
		errx(1, "multiple copies are not allowed");
	if (MC > 0 && ncopies > MC)
		errx(1, "only %ld copies are allowed", MC);
	/*
	 * Get the identity of the person doing the lpr using the same
	 * algorithm as lprm. 
	 */
	if (real_uid != DU || person == NULL) {
		if ((pw = getpwuid(real_uid)) == NULL)
			errx(1, "Who are you?");
		if ((person = strdup(pw->pw_name)) == NULL)
			err(1, NULL);
	}
	/*
	 * Check for restricted group access.
	 */
	if (RG != NULL && real_uid != DU) {
		if ((gptr = getgrnam(RG)) == NULL)
			errx(1, "Restricted group specified incorrectly");
		if (gptr->gr_gid != getgid()) {
			while (*gptr->gr_mem != NULL) {
				if ((strcmp(person, *gptr->gr_mem)) == 0)
					break;
				gptr->gr_mem++;
			}
			if (*gptr->gr_mem == NULL)
				errx(1, "Not a member of the restricted group");
		}
	}
	/*
	 * Check to make sure queuing is enabled if real_uid is not root.
	 */
	(void)snprintf(buf, sizeof(buf), "%s/%s", SD, LO);
	if (real_uid && stat(buf, &stb) == 0 && (stb.st_mode & 010))
		errx(1, "Printer queue is disabled");
	/*
	 * Initialize the control file.
	 */
	mktemps();
	tfd = nfile(tfname);
	card('H', host);
	card('P', person);
	if (hdr) {
		if (jobname == NULL) {
			if (argc == 0)
				jobname = "stdin";
			else
				jobname = (arg = strrchr(argv[0], '/')) ?
				    arg + 1 : argv[0];
		}
		card('J', jobname);
		card('C', class);
		if (!SH)
			card('L', person);
	}
	if (iflag)
		card('I', itoa(indent));
	if (mailflg)
		card('M', person);
	if (format == 't' || format == 'n' || format == 'd')
		for (i = 0; i < 4; i++)
			if (fonts[i] != NULL)
				card('1'+i, fonts[i]);
	if (width != NULL)
		card('W', width);

	/*
	 * Read the files and spool them.
	 */
	if (argc == 0)
		copy(0, " ");
	else while (argc--) {
		if (argv[0][0] == '-' && argv[0][1] == '\0') {
			/* use stdin */
			copy(0, " ");
			argv++;
			continue;
		}
		if ((f = test(arg = *argv++)) < 0)
			continue;	/* file unreasonable */

		if (sflag && (cp = linked(arg)) != NULL) {
			(void)snprintf(buf, sizeof(buf), "%d %llu",
			    statb.st_dev, (unsigned long long)statb.st_ino);
			card('S', buf);
			if (format == 'p')
				card('T', title ? title : arg);
			for (i = 0; i < ncopies; i++)
				card(format, &dfname[inchar-2]);
			card('U', &dfname[inchar-2]);
			if (f)
				card('U', cp);
			card('N', arg);
			dfname[inchar]++;
			nact++;
			continue;
		}
		if (sflag)
			warnx("%s: not linked, copying instead", arg);
		if ((i = safe_open(arg, O_RDONLY, 0)) < 0)
			warn("%s", arg);
		else {
			copy(i, arg);
			(void)close(i);
			if (f && unlink(arg) < 0)
				warnx("%s: not removed", arg);
		}
	}

	if (nact) {
		(void)close(tfd);
		tfname[inchar]--;
		/*
		 * Touch the control file to fix position in the queue.
		 */
		PRIV_START;
		if ((tfd = safe_open(tfname, O_RDWR|O_NOFOLLOW, 0)) >= 0) {
			char c;

			if (read(tfd, &c, 1) == 1 &&
			    lseek(tfd, (off_t)0, SEEK_SET) == 0 &&
			    write(tfd, &c, 1) != 1) {
				warn("%s", tfname);
				tfname[inchar]++;
				cleanup(0);
			}
			(void)close(tfd);
		}
		if (link(tfname, cfname) < 0) {
			warn("cannot rename %s", cfname);
			tfname[inchar]++;
			cleanup(0);
		}
		unlink(tfname);
		PRIV_END;
		if (qflag)		/* just q things up */
			exit(0);
		if (!startdaemon(printer))
			printf("jobs queued, but cannot start daemon.\n");
		exit(0);
	}
	cleanup(0);
	return (1);
	/* NOTREACHED */
}