From bb771512fafa88cfc4e0a998b2d485cfcb4c3ea4 Mon Sep 17 00:00:00 2001 From: Packit Service Date: Dec 09 2020 07:51:31 +0000 Subject: Prepare for a new update Reverting patches so we can apply the latest update and changes can be seen in the spec file and sources. --- diff --git a/Makefile.in b/Makefile.in index 6e6ebdc..dd3c2f8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -68,13 +68,13 @@ LIST = Filelist Filelist.asc all: at atd atd.service atrun at: $(ATOBJECTS) - $(CC) $(LDFLAGS) -pie -o at $(ATOBJECTS) $(LIBS) $(LEXLIB) $(PAMLIB) + $(CC) $(LDFLAGS) -o at $(ATOBJECTS) $(LIBS) $(LEXLIB) rm -f $(CLONES) $(LN_S) -f at atq $(LN_S) -f at atrm atd: $(RUNOBJECTS) - $(CC) $(LDFLAGS) -pie -o atd $(RUNOBJECTS) $(LIBS) $(PAMLIB) $(SELINUXLIB) + $(CC) $(LDFLAGS) -o atd $(RUNOBJECTS) $(LIBS) $(PAMLIB) $(SELINUXLIB) y.tab.c y.tab.h: parsetime.y $(YACC) -d parsetime.y @@ -89,41 +89,38 @@ atrun: atrun.in configure .c.o: - $(CC) -c $(CFLAGS) -fPIE $(DEFS) $*.c + $(CC) -c $(CFLAGS) $(DEFS) $*.c install: all - $(INSTALL) -m 755 -d $(IROOT)$(etcdir) - $(INSTALL) -m 755 -d $(IROOT)$(bindir) - $(INSTALL) -m 755 -d $(IROOT)$(sbindir) - $(INSTALL) -m 755 -d $(IROOT)$(docdir) - $(INSTALL) -m 755 -d $(IROOT)$(atdocdir) - $(INSTALL) -m 755 -d $(IROOT)$(etcdir)/pam.d/ - $(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 755 -d $(IROOT)$(ATSPOOL_DIR) - chmod 700 $(IROOT)$(ATJOB_DIR) $(IROOT)$(ATSPOOL_DIR) - chown $(DAEMON_USERNAME):$(DAEMON_GROUPNAME) $(IROOT)$(ATJOB_DIR) $(IROOT)$(ATSPOOL_DIR) + $(INSTALL) -g root -o root -m 755 -d $(IROOT)$(etcdir) + $(INSTALL) -g root -o root -m 755 -d $(IROOT)$(bindir) + $(INSTALL) -g root -o root -m 755 -d $(IROOT)$(sbindir) + $(INSTALL) -g root -o root -m 755 -d $(IROOT)$(docdir) + $(INSTALL) -g root -o root -m 755 -d $(IROOT)$(atdocdir) + $(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 755 -d $(IROOT)$(ATSPOOL_DIR) $(IROOT)$(ATJOB_DIR) + chmod 1770 $(IROOT)$(ATSPOOL_DIR) $(IROOT)$(ATJOB_DIR) touch $(IROOT)$(LFILE) chmod 600 $(IROOT)$(LFILE) chown $(DAEMON_USERNAME):$(DAEMON_GROUPNAME) $(IROOT)$(LFILE) - test -f $(IROOT)$(etcdir)/at.allow || test -f $(IROOT)$(etcdir)/at.deny || $(INSTALL) -m 600 at.deny $(IROOT)$(etcdir)/ - $(INSTALL) -o $(INSTALL_ROOT_USER) -g $(DAEMON_GROUPNAME) pam_atd $(IROOT)$(etcdir)/pam.d/atd - $(INSTALL) -m 4755 at $(IROOT)$(bindir) + test -f $(IROOT)$(etcdir)/at.allow || test -f $(IROOT)$(etcdir)/at.deny || $(INSTALL) -o root -g $(DAEMON_GROUPNAME) -m 640 at.deny $(IROOT)$(etcdir)/ + $(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 6755 at $(IROOT)$(bindir) $(LN_S) -f at $(IROOT)$(bindir)/atq $(LN_S) -f at $(IROOT)$(bindir)/atrm - $(INSTALL) -m 755 batch $(IROOT)$(bindir) - $(INSTALL) -d -m 755 $(IROOT)$(man1dir) - $(INSTALL) -d -m 755 $(IROOT)$(man5dir) - $(INSTALL) -d -m 755 $(IROOT)$(man8dir) - $(INSTALL) -m 755 atd $(IROOT)$(sbindir) - $(INSTALL) -m 755 atrun $(IROOT)$(sbindir) - $(INSTALL) -m 644 at.1 $(IROOT)$(man1dir)/ + $(INSTALL) -g root -o root -m 755 batch $(IROOT)$(bindir) + $(INSTALL) -d -o root -g root -m 755 $(IROOT)$(man1dir) + $(INSTALL) -d -o root -g root -m 755 $(IROOT)$(man5dir) + $(INSTALL) -d -o root -g root -m 755 $(IROOT)$(man8dir) + $(INSTALL) -g root -o root -m 755 atd $(IROOT)$(sbindir) + $(INSTALL) -g root -o root -m 755 atrun $(IROOT)$(sbindir) + $(INSTALL) -g root -o root -m 644 at.1 $(IROOT)$(man1dir)/ cd $(IROOT)$(man1dir) && $(LN_S) -f at.1 atq.1 && $(LN_S) -f at.1 batch.1 && $(LN_S) -f at.1 atrm.1 - $(INSTALL) -m 644 atd.8 $(IROOT)$(man8dir)/ + $(INSTALL) -g root -o root -m 644 atd.8 $(IROOT)$(man8dir)/ sed "s,\$${exec_prefix},$(exec_prefix),g" tmpman - $(INSTALL) -m 644 tmpman $(IROOT)$(man8dir)/atrun.8 + $(INSTALL) -g root -o root -m 644 tmpman $(IROOT)$(man8dir)/atrun.8 rm -f tmpman - $(INSTALL) -m 644 at.allow.5 $(IROOT)$(man5dir)/ + $(INSTALL) -g root -o root -m 644 at.allow.5 $(IROOT)$(man5dir)/ cd $(IROOT)$(man5dir) && $(LN_S) -f at.allow.5 at.deny.5 - $(INSTALL) -m 644 $(DOCS) $(IROOT)$(atdocdir) + $(INSTALL) -g root -o root -m 644 $(DOCS) $(IROOT)$(atdocdir) rm -f $(IROOT)$(mandir)/cat1/at.1* $(IROOT)$(mandir)/cat1/batch.1* \ $(IROOT)$(mandir)/cat1/atq.1* rm -f $(IROOT)$(mandir)/cat1/atd.8* diff --git a/Makefile.in.make b/Makefile.in.make deleted file mode 100644 index dd3c2f8..0000000 --- a/Makefile.in.make +++ /dev/null @@ -1,174 +0,0 @@ -VERSION = @VERSION@ -srcdir = @srcdir@ -VPATH = $(srcdir) - -install_prefix = -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -sbindir = @sbindir@ -mandir = @mandir@ -libdir = @libdir@ -man1dir = $(mandir)/man1 -man5dir = $(mandir)/man5 -man8dir = $(mandir)/man8 -docdir = $(prefix)/doc -atdocdir = $(docdir)/at -etcdir = @ETCDIR@ -systemdsystemunitdir = @systemdsystemunitdir@ - -DAEMON_USERNAME = @DAEMON_USERNAME@ -DAEMON_GROUPNAME= @DAEMON_GROUPNAME@ -LOADAVG_MX = @LOADAVG_MX@ -ATJOB_DIR = @ATJBD@ -ATSPOOL_DIR = @ATSPD@ -LN_S = @LN_S@ -YACC = @YACC@ -LEX = @LEX@ -LEXLIB = @LEXLIB@ - -CC = @CC@ -CFLAGS = -I$(srcdir) @CFLAGS@ -LDFLAGS = @LDFLAGS@ -LFILE = $(ATJOB_DIR)/.SEQ -DEFS = @DEFS@ -DVERSION=\"$(VERSION)\" \ - -DETCDIR=\"$(etcdir)\" -DLOADAVG_MX=$(LOADAVG_MX) \ - -DDAEMON_USERNAME=\"$(DAEMON_USERNAME)\" \ - -DDAEMON_GROUPNAME=\"$(DAEMON_GROUPNAME)\" \ - -DLFILE=\"$(LFILE)\" -Wall -LIBS = @LIBS@ -LIBOBJS = @LIBOBJS@ -INSTALL = @INSTALL@ -PAMLIB = @PAMLIB@ -SELINUXLIB = @SELINUXLIB@ - -CLONES = atq atrm -ATOBJECTS = at.o panic.o perm.o posixtm.o y.tab.o lex.yy.o -RUNOBJECTS = atd.o daemon.o $(LIBOBJS) -CSRCS = at.c atd.c panic.c perm.c posixtm.c daemon.c getloadavg.c \ - y.tab.c y.tab.h lex.yy.c -HEADERS = at.h panic.h parsetime.h perm.h posixtm.h daemon.h \ - getloadavg.h privs.h - -OTHERS = parsetime.l parsetime.y parsetime.pl - -DOCS = Problems Copyright README ChangeLog timespec - -MISC = COPYING Makefile.in configure acconfig.h install-sh \ - README atrun.in at.1.in atrun.8.in atd.8.in at.allow.5.in \ - configure.in config.h.in config.guess config.sub batch.in at.deny \ - atd.service.in \ - $(DOCS) - -DIST = $(CSRCS) $(HEADERS) $(MISC) $(OTHERS) -LIST = Filelist Filelist.asc - -.PHONY: all install clean dist distclean - -all: at atd atd.service atrun - -at: $(ATOBJECTS) - $(CC) $(LDFLAGS) -o at $(ATOBJECTS) $(LIBS) $(LEXLIB) - rm -f $(CLONES) - $(LN_S) -f at atq - $(LN_S) -f at atrm - -atd: $(RUNOBJECTS) - $(CC) $(LDFLAGS) -o atd $(RUNOBJECTS) $(LIBS) $(PAMLIB) $(SELINUXLIB) - -y.tab.c y.tab.h: parsetime.y - $(YACC) -d parsetime.y - -lex.yy.c: parsetime.l - $(LEX) -i parsetime.l - -atd.service: atd.service.in - sed -e 's![@]sbindir[@]!$(sbindir)!g' < $< > $@ - -atrun: atrun.in - configure - -.c.o: - $(CC) -c $(CFLAGS) $(DEFS) $*.c - -install: all - $(INSTALL) -g root -o root -m 755 -d $(IROOT)$(etcdir) - $(INSTALL) -g root -o root -m 755 -d $(IROOT)$(bindir) - $(INSTALL) -g root -o root -m 755 -d $(IROOT)$(sbindir) - $(INSTALL) -g root -o root -m 755 -d $(IROOT)$(docdir) - $(INSTALL) -g root -o root -m 755 -d $(IROOT)$(atdocdir) - $(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 755 -d $(IROOT)$(ATSPOOL_DIR) $(IROOT)$(ATJOB_DIR) - chmod 1770 $(IROOT)$(ATSPOOL_DIR) $(IROOT)$(ATJOB_DIR) - touch $(IROOT)$(LFILE) - chmod 600 $(IROOT)$(LFILE) - chown $(DAEMON_USERNAME):$(DAEMON_GROUPNAME) $(IROOT)$(LFILE) - test -f $(IROOT)$(etcdir)/at.allow || test -f $(IROOT)$(etcdir)/at.deny || $(INSTALL) -o root -g $(DAEMON_GROUPNAME) -m 640 at.deny $(IROOT)$(etcdir)/ - $(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 6755 at $(IROOT)$(bindir) - $(LN_S) -f at $(IROOT)$(bindir)/atq - $(LN_S) -f at $(IROOT)$(bindir)/atrm - $(INSTALL) -g root -o root -m 755 batch $(IROOT)$(bindir) - $(INSTALL) -d -o root -g root -m 755 $(IROOT)$(man1dir) - $(INSTALL) -d -o root -g root -m 755 $(IROOT)$(man5dir) - $(INSTALL) -d -o root -g root -m 755 $(IROOT)$(man8dir) - $(INSTALL) -g root -o root -m 755 atd $(IROOT)$(sbindir) - $(INSTALL) -g root -o root -m 755 atrun $(IROOT)$(sbindir) - $(INSTALL) -g root -o root -m 644 at.1 $(IROOT)$(man1dir)/ - cd $(IROOT)$(man1dir) && $(LN_S) -f at.1 atq.1 && $(LN_S) -f at.1 batch.1 && $(LN_S) -f at.1 atrm.1 - $(INSTALL) -g root -o root -m 644 atd.8 $(IROOT)$(man8dir)/ - sed "s,\$${exec_prefix},$(exec_prefix),g" tmpman - $(INSTALL) -g root -o root -m 644 tmpman $(IROOT)$(man8dir)/atrun.8 - rm -f tmpman - $(INSTALL) -g root -o root -m 644 at.allow.5 $(IROOT)$(man5dir)/ - cd $(IROOT)$(man5dir) && $(LN_S) -f at.allow.5 at.deny.5 - $(INSTALL) -g root -o root -m 644 $(DOCS) $(IROOT)$(atdocdir) - rm -f $(IROOT)$(mandir)/cat1/at.1* $(IROOT)$(mandir)/cat1/batch.1* \ - $(IROOT)$(mandir)/cat1/atq.1* - rm -f $(IROOT)$(mandir)/cat1/atd.8* - if test x"$(systemdsystemunitdir)" != xno; then \ - $(INSTALL) -o root -g root -m 755 -d $(IROOT)$(systemdsystemunitdir); \ - $(INSTALL) -o root -g root -m 644 atd.service $(IROOT)$(systemdsystemunitdir); \ - fi - -dist: checkin $(DIST) $(LIST) Filelist.asc - (cd ..; tar cf - `for a in $(DIST) $(LIST); do echo at-$(VERSION)/$$a; done` |\ - gzip -9 > at-$(VERSION).tar.gz) - -pre: checkin $(DIST) $(LIST) - (cd ..; tar cf - `for a in $(DIST); do echo at-$(VERSION)/$$a; done` |\ - gzip -9 > at-$(VERSION).tar.gz) - mv ../at-$(VERSION).tar.gz ../at-$(VERSION)-`date +%Y%m%d`.tar.gz - -clean: - rm -f subs.sed *.o *.s at atd core a.out *~ $(CLONES) *.bak stamp-built - rm -f parsetest parsetime.c lex.yy.c y.tab.c y.tab.h - -distclean: clean - rm -rf at.1 at.allow.5 atd.8 atrun.8 config.cache atrun batch config.h \ - config.status Makefile config.log build atd.service - -checkin: $(DIST) - test -d RCS && for a in $(DIST); do ci -l $$a ; done - -Filelist: $(DIST) - md5sum $(DIST) > Filelist - -Filelist.asc: Filelist - pgp -sba Filelist - -parsetest: lex.yy.c y.tab.c - $(CC) -o parsetest $(CFLAGS) $(DEFS) -DTEST_PARSER -DNEED_YYWRAP lex.yy.c y.tab.c - -test: parsetest - prove parsetime.pl - -.depend: $(CSRCS) - gcc $(CFLAGS) $(DEFS) -MM $(CSRCS) > .depend - -at.o: at.c config.h at.h panic.h parsetime.h perm.h posixtm.h privs.h -atd.o: atd.c config.h privs.h daemon.h getloadavg.h -panic.o: panic.c config.h panic.h at.h -parsetime.o: parsetime.c config.h at.h panic.h -perm.o: perm.c config.h privs.h at.h -posixtm.o: posixtm.c posixtm.h -daemon.o: daemon.c config.h daemon.h privs.h -getloadavg.o: getloadavg.c config.h getloadavg.h diff --git a/Makefile.in.pam b/Makefile.in.pam deleted file mode 100644 index c613014..0000000 --- a/Makefile.in.pam +++ /dev/null @@ -1,177 +0,0 @@ -VERSION = @VERSION@ -srcdir = @srcdir@ -VPATH = $(srcdir) - -install_prefix = -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -sbindir = @sbindir@ -mandir = @mandir@ -libdir = @libdir@ -man1dir = $(mandir)/man1 -man5dir = $(mandir)/man5 -man8dir = $(mandir)/man8 -docdir = $(prefix)/doc -atdocdir = $(docdir)/at -etcdir = @ETCDIR@ -systemdsystemunitdir = @systemdsystemunitdir@ - -DAEMON_USERNAME = @DAEMON_USERNAME@ -DAEMON_GROUPNAME= @DAEMON_GROUPNAME@ -LOADAVG_MX = @LOADAVG_MX@ -ATJOB_DIR = @ATJBD@ -ATSPOOL_DIR = @ATSPD@ -LN_S = @LN_S@ -YACC = @YACC@ -LEX = @LEX@ -LEXLIB = @LEXLIB@ - -CC = @CC@ -CFLAGS = -I$(srcdir) @CFLAGS@ -LDFLAGS = @LDFLAGS@ -LFILE = $(ATJOB_DIR)/.SEQ -DEFS = @DEFS@ -DVERSION=\"$(VERSION)\" \ - -DETCDIR=\"$(etcdir)\" -DLOADAVG_MX=$(LOADAVG_MX) \ - -DDAEMON_USERNAME=\"$(DAEMON_USERNAME)\" \ - -DDAEMON_GROUPNAME=\"$(DAEMON_GROUPNAME)\" \ - -DLFILE=\"$(LFILE)\" -Wall -LIBS = @LIBS@ -LIBOBJS = @LIBOBJS@ -INSTALL = @INSTALL@ -PAMLIB = @PAMLIB@ -SELINUXLIB = @SELINUXLIB@ - -CLONES = atq atrm -ATOBJECTS = at.o panic.o perm.o posixtm.o y.tab.o lex.yy.o -RUNOBJECTS = atd.o daemon.o $(LIBOBJS) -CSRCS = at.c atd.c panic.c perm.c posixtm.c daemon.c getloadavg.c \ - y.tab.c y.tab.h lex.yy.c -HEADERS = at.h panic.h parsetime.h perm.h posixtm.h daemon.h \ - getloadavg.h privs.h - -OTHERS = parsetime.l parsetime.y parsetime.pl - -DOCS = Problems Copyright README ChangeLog timespec - -MISC = COPYING Makefile.in configure acconfig.h install-sh \ - README atrun.in at.1.in atrun.8.in atd.8.in at.allow.5.in \ - configure.in config.h.in config.guess config.sub batch.in at.deny \ - atd.service.in \ - $(DOCS) - -DIST = $(CSRCS) $(HEADERS) $(MISC) $(OTHERS) -LIST = Filelist Filelist.asc - -.PHONY: all install clean dist distclean - -all: at atd atd.service atrun - -at: $(ATOBJECTS) - $(CC) $(LDFLAGS) -pie -o at $(ATOBJECTS) $(LIBS) $(LEXLIB) - rm -f $(CLONES) - $(LN_S) -f at atq - $(LN_S) -f at atrm - -atd: $(RUNOBJECTS) - $(CC) $(LDFLAGS) -pie -o atd $(RUNOBJECTS) $(LIBS) $(PAMLIB) $(SELINUXLIB) - -y.tab.c y.tab.h: parsetime.y - $(YACC) -d parsetime.y - -lex.yy.c: parsetime.l - $(LEX) -i parsetime.l - -atd.service: atd.service.in - sed -e 's![@]sbindir[@]!$(sbindir)!g' < $< > $@ - -atrun: atrun.in - configure - -.c.o: - $(CC) -c $(CFLAGS) -fPIE $(DEFS) $*.c - -install: all - $(INSTALL) -m 755 -d $(IROOT)$(etcdir) - $(INSTALL) -m 755 -d $(IROOT)$(bindir) - $(INSTALL) -m 755 -d $(IROOT)$(sbindir) - $(INSTALL) -m 755 -d $(IROOT)$(docdir) - $(INSTALL) -m 755 -d $(IROOT)$(atdocdir) - $(INSTALL) -m 755 -d $(IROOT)$(etcdir)/pam.d/ - $(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 755 -d $(IROOT)$(ATSPOOL_DIR) - chmod 700 $(IROOT)$(ATJOB_DIR) $(IROOT)$(ATSPOOL_DIR) - chown $(DAEMON_USERNAME):$(DAEMON_GROUPNAME) $(IROOT)$(ATJOB_DIR) $(IROOT)$(ATSPOOL_DIR) - touch $(IROOT)$(LFILE) - chmod 600 $(IROOT)$(LFILE) - chown $(DAEMON_USERNAME):$(DAEMON_GROUPNAME) $(IROOT)$(LFILE) - test -f $(IROOT)$(etcdir)/at.allow || test -f $(IROOT)$(etcdir)/at.deny || $(INSTALL) -m 600 at.deny $(IROOT)$(etcdir)/ - $(INSTALL) -o $(INSTALL_ROOT_USER) -g $(DAEMON_GROUPNAME) pam_atd $(IROOT)$(etcdir)/pam.d/atd - $(INSTALL) -m 4755 at $(IROOT)$(bindir) - $(LN_S) -f at $(IROOT)$(bindir)/atq - $(LN_S) -f at $(IROOT)$(bindir)/atrm - $(INSTALL) -m 755 batch $(IROOT)$(bindir) - $(INSTALL) -d -m 755 $(IROOT)$(man1dir) - $(INSTALL) -d -m 755 $(IROOT)$(man5dir) - $(INSTALL) -d -m 755 $(IROOT)$(man8dir) - $(INSTALL) -m 755 atd $(IROOT)$(sbindir) - $(INSTALL) -m 755 atrun $(IROOT)$(sbindir) - $(INSTALL) -m 644 at.1 $(IROOT)$(man1dir)/ - cd $(IROOT)$(man1dir) && $(LN_S) -f at.1 atq.1 && $(LN_S) -f at.1 batch.1 && $(LN_S) -f at.1 atrm.1 - $(INSTALL) -m 644 atd.8 $(IROOT)$(man8dir)/ - sed "s,\$${exec_prefix},$(exec_prefix),g" tmpman - $(INSTALL) -m 644 tmpman $(IROOT)$(man8dir)/atrun.8 - rm -f tmpman - $(INSTALL) -m 644 at.allow.5 $(IROOT)$(man5dir)/ - cd $(IROOT)$(man5dir) && $(LN_S) -f at.allow.5 at.deny.5 - $(INSTALL) -m 644 $(DOCS) $(IROOT)$(atdocdir) - rm -f $(IROOT)$(mandir)/cat1/at.1* $(IROOT)$(mandir)/cat1/batch.1* \ - $(IROOT)$(mandir)/cat1/atq.1* - rm -f $(IROOT)$(mandir)/cat1/atd.8* - if test x"$(systemdsystemunitdir)" != xno; then \ - $(INSTALL) -o root -g root -m 755 -d $(IROOT)$(systemdsystemunitdir); \ - $(INSTALL) -o root -g root -m 644 atd.service $(IROOT)$(systemdsystemunitdir); \ - fi - -dist: checkin $(DIST) $(LIST) Filelist.asc - (cd ..; tar cf - `for a in $(DIST) $(LIST); do echo at-$(VERSION)/$$a; done` |\ - gzip -9 > at-$(VERSION).tar.gz) - -pre: checkin $(DIST) $(LIST) - (cd ..; tar cf - `for a in $(DIST); do echo at-$(VERSION)/$$a; done` |\ - gzip -9 > at-$(VERSION).tar.gz) - mv ../at-$(VERSION).tar.gz ../at-$(VERSION)-`date +%Y%m%d`.tar.gz - -clean: - rm -f subs.sed *.o *.s at atd core a.out *~ $(CLONES) *.bak stamp-built - rm -f parsetest parsetime.c lex.yy.c y.tab.c y.tab.h - -distclean: clean - rm -rf at.1 at.allow.5 atd.8 atrun.8 config.cache atrun batch config.h \ - config.status Makefile config.log build atd.service - -checkin: $(DIST) - test -d RCS && for a in $(DIST); do ci -l $$a ; done - -Filelist: $(DIST) - md5sum $(DIST) > Filelist - -Filelist.asc: Filelist - pgp -sba Filelist - -parsetest: lex.yy.c y.tab.c - $(CC) -o parsetest $(CFLAGS) $(DEFS) -DTEST_PARSER -DNEED_YYWRAP lex.yy.c y.tab.c - -test: parsetest - prove parsetime.pl - -.depend: $(CSRCS) - gcc $(CFLAGS) $(DEFS) -MM $(CSRCS) > .depend - -at.o: at.c config.h at.h panic.h parsetime.h perm.h posixtm.h privs.h -atd.o: atd.c config.h privs.h daemon.h getloadavg.h -panic.o: panic.c config.h panic.h at.h -parsetime.o: parsetime.c config.h at.h panic.h -perm.o: perm.c config.h privs.h at.h -posixtm.o: posixtm.c posixtm.h -daemon.o: daemon.c config.h daemon.h privs.h -getloadavg.o: getloadavg.c config.h getloadavg.h diff --git a/at.1.in b/at.1.in index 87577d6..5410bd4 100644 --- a/at.1.in +++ b/at.1.in @@ -210,7 +210,7 @@ queue for .BR batch . Queues with higher letters run with increased niceness. The special queue "=" is reserved for jobs which are currently running. - +.P If a job is submitted to a queue designated with an uppercase letter, the job is treated as if it were submitted to batch at the time of the job. Once the time is reached, the batch processing rules with respect to load diff --git a/at.1.in.nit b/at.1.in.nit deleted file mode 100644 index 5410bd4..0000000 --- a/at.1.in.nit +++ /dev/null @@ -1,310 +0,0 @@ -.TH AT 1 2009-11-14 -.SH NAME -at, batch, atq, atrm \- queue, examine or delete jobs for later execution -.SH SYNOPSIS -.B at -.RB [ -V ] -.RB [ -q -.IR queue ] -.RB [ -f -.IR file ] -.RB [ -mMlv ] -.IR timespec ... -.br -.B at -.RB [ -V ] -.RB [ -q -.IR queue ] -.RB [ -f -.IR file ] -.RB [ -mMkv ] -.RB [ -t -.IR time ] -.br -.B "at -c" -.I job -.RI [ job... ] -.br -.B atq -.RB [ -V ] -.RB [ -q -.IR queue ] -.br -.B at -.RB [ -rd ] -.I job -.RI [ job... ] -.br -.B atrm -.RB [ -V ] -.I job -.RI [ job... ] -.br -.B batch -.br -.B "at -b" -.SH DESCRIPTION -.B at -and -.B batch -read commands from standard input or a specified file which are to -be executed at a later time, using -.BR /bin/sh . -.TP 8 -.BR at -executes commands at a specified time. -.TP 8 -.BR atq -lists the user's pending jobs, unless the user is the superuser; in that -case, everybody's jobs are listed. The format of the output lines (one -for each job) is: Job number, date, hour, queue, and username. -.TP 8 -.BR atrm -deletes jobs, identified by their job number. -.TP 8 -.BR batch -executes commands when system load levels permit; in other words, when the load average -drops below @LOADAVG_MX@, or the value specified in the invocation of -.BR atd . -.PP -.B At -allows fairly complex time -specifications, extending the POSIX.2 standard. It accepts times -of the form -.B HH:MM -to run a job at a specific time of day. -(If that time is already past, the next day is assumed.) -You may also specify -.B midnight, -.B noon, -or -.B teatime -(4pm) -and you can have a time-of-day suffixed with -.B AM -or -.B PM -for running in the morning or the evening. -You can also say what day the job will be run, -by giving a date in the form -.B month-name -.B day -with an optional -.B year, -or giving a date of the form -.IR MMDD [ CC ] YY , -.IR MM / DD /[ CC ] YY , -.IR DD . MM .[ CC ] YY -or -.RI [ CC ] YY - MM - DD . -The specification of a date -.I must -follow the specification of the time of day. -You can also give times like -.B now -.B \+ -.I count -.I time-units, -where the time-units can be -.B minutes, -.B hours, -.B days, -or -.B weeks -and you can tell -.B at -to run the job today by suffixing the time with -.B today -and to run the job tomorrow by suffixing the time with -.B tomorrow. -.PP -For example, to run a job at 4pm three days from now, you would do -.B at 4pm + 3 days, -to run a job at 10:00am on July 31, you would do -.B at 10am Jul 31 -and to run a job at 1am tomorrow, you would do -.B at 1am tomorrow. -.PP -If you specify a job to absolutely run at a specific time and date in -the past, the job will run as soon as possible. For example, if it is -8pm and you do a -.B at 6pm today, -it will run more likely at 8:05pm. -.PP -The definition of the time specification can be found in -.IR @prefix@/share/doc/at/timespec . -.PP -For both -.BR at " and " batch , -commands are read from standard input or the file specified -with the -.B -f -option and executed. -The working directory, the environment (except for the variables -.BR BASH_VERSINFO , -.BR DISPLAY , -.BR EUID , -.BR GROUPS , -.BR SHELLOPTS , -.BR TERM , -.BR UID , -and -.BR _ ) -and the umask are retained from the time of invocation. - -As -.BR at -is currently implemented as a setuid program, other environment variables (e.g. -.BR LD_LIBRARY_PATH " or " LD_PRELOAD ) -are also not exported. This may change in the future. As a workaround, -set these variables explicitly in your job. - -An -.BR "at " \- -or -.BR "batch "\- -command invoked from a -.B su(1) -shell will retain the current userid. -The user will be mailed standard error and standard output from his -commands, if any. -Mail will be sent using the command -.BR @MAIL_CMD@ . -If -.B at -is executed from a -.B su(1) -shell, the owner of the login shell will receive the mail. -.PP -The superuser may use these commands in any case. -For other users, permission to use at is determined by the files -.I @ETCDIR@/at.allow -and -.IR @ETCDIR@/at.deny . -See -.BR at.allow (5) -for details. -.SH OPTIONS -.TP 8 -.B -V -prints the version number to standard error and exit successfully. -.TP 8 -.BI \-q " queue" -uses the specified queue. -A queue designation consists of a single letter; valid queue designations -range from -.B a -to -.BR z -and -.B A -to -.BR Z . -The -.B a -queue is the default for -.B at -and the -.B b -queue for -.BR batch . -Queues with higher letters run with increased niceness. The special -queue "=" is reserved for jobs which are currently running. -.P -If a job is submitted to a queue designated with an uppercase letter, the -job is treated as if it were submitted to batch at the time of the job. -Once the time is reached, the batch processing rules with respect to load -average apply. -If -.BR atq -is given a specific queue, it will only show jobs pending in that queue. -.TP 8 -.B \-m -Send mail to the user when the job has completed even if there was no -output. -.TP 8 -.B \-M -Never send mail to the user. -.TP 8 -.BI \-f " file" -Reads the job from -.I file -rather than standard input. -.TP 8 -.BI \-t " time" -run the job at -.IR time , -given in the format [[CC]YY]MMDDhhmm[.ss] -.TP 8 -.B \-l -Is an alias for -.B atq. -.TP -.B \-r -Is an alias for -.B atrm. -.TP -.B \-d -Is an alias for -.B atrm. -.TP -.B \-b -is an alias for -.BR batch . -.TP -.B \-v -Shows the time the job will be executed before reading the job. -.P -Times displayed will be in the format "Thu Feb 20 14:50:00 1997". -.TP -.B -\-c -cats the jobs listed on the command line to standard output. -.SH FILES -.I @ATJBD@ -.br -.I @ATSPD@ -.br -.I /proc/loadavg -.br -.I /var/run/utmp -.br -.I @ETCDIR@/at.allow -.br -.I @ETCDIR@/at.deny -.SH SEE ALSO -.BR at.allow (5), -.BR at.deny (5), -.BR atd (8), -.BR cron (1), -.BR nice (1), -.BR sh (1), -.BR umask (2). -.SH BUGS -The correct operation of -.B batch -for Linux depends on the presence of a -.IR proc - -type directory mounted on -.IR /proc . -.PP -If the file -.I /var/run/utmp -is not available or corrupted, or if the user is not logged on at the -time -.B at -is invoked, the mail is sent to the userid found -in the environment variable -.BR LOGNAME . -If that is undefined or empty, the current userid is assumed. -.PP -.B At -and -.B batch -as presently implemented are not suitable when users are competing for -resources. -If this is the case for your site, you might want to consider another -batch system, such as -.BR nqs . -.SH AUTHOR -At was mostly written by Thomas Koenig, ig25@rz.uni-karlsruhe.de. diff --git a/at.c b/at.c index 8ee9d28..2136e0b 100644 --- a/at.c +++ b/at.c @@ -62,8 +62,11 @@ #include #include +#ifdef TM_IN_SYS_TIME #include +#else #include +#endif #ifdef HAVE_UNISTD_H #include @@ -141,13 +144,18 @@ sigc(int signo) /* If the user presses ^C, remove the spool file and exit */ if (fcreated) { + /* PRIV_START - /* + We need the unprivileged uid here since the file is owned by the real (not effective) uid. */ - unlink(atfile); + setregid(real_gid, effective_gid); + unlink(atfile); + setregid(effective_gid, real_gid); + /* PRIV_END + */ } exit(EXIT_FAILURE); } @@ -209,11 +217,7 @@ nextjob() jobno = (1 + jobno) % 0xfffff; /* 2^20 jobs enough? */ fprintf(fid, "%05lx\n", jobno); - if (ferror(fid)) - jobno = EOF; - - if (fclose(fid) != 0) - jobno = EOF; + fclose(fid); return jobno; } @@ -240,12 +244,6 @@ writefile(time_t runtimer, char queue) int kill_errno; int rc; int mailsize = 128; - struct timeval tv; - struct timezone tz; - long int i; - - gettimeofday(&tv, &tz); - srandom(getpid()+tv.tv_usec); /* Install the signal handler for SIGINT; terminate after removing the * spool file if necessary @@ -317,19 +315,26 @@ writefile(time_t runtimer, char queue) * bit. Yes, this is a kluge. */ cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR); - if ((seteuid(effective_uid)) < 0) - perr("Error in seteuid: %s", errno); + seteuid(real_uid); if ((fd = open(atfile, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, S_IRUSR)) == -1) perr("Cannot create atjob file %.500s", atfile); + seteuid(effective_uid); if ((fd2 = dup(fd)) < 0) perr("Error in dup() of job file"); + /* if (fchown(fd2, real_uid, real_gid) != 0) - perr("Cannot give real_uid and real_gid the file"); + perr("Cannot give away file"); + */ PRIV_END + /* We no longer need suid root; now we just need to be able to write + * to the directory, if necessary. + */ + + REDUCE_PRIV(daemon_uid, daemon_gid) /* We've successfully created the file; let's set the flag so it * gets removed in case of an interrupt or error. */ @@ -408,9 +413,8 @@ writefile(time_t runtimer, char queue) unsigned int i; for (i = 0; i < sizeof(no_export) / sizeof(no_export[0]); i++) { export = export - && ((((size_t) (eqp - *atenv)) != strlen(no_export[i])) - ||(strncmp(*atenv, no_export[i],(size_t) (eqp - *atenv)) != 0) - ); + && (strncmp(*atenv, no_export[i], + (size_t) (eqp - *atenv)) != 0); } eqp++; } @@ -473,9 +477,6 @@ writefile(time_t runtimer, char queue) fprintf(fp, " || {\n\t echo 'Execution directory " "inaccessible' >&2\n\t exit 1\n}\n"); - i = random(); - fprintf(fp, "${SHELL:-/bin/sh} << \'marcinDELIMITER%08lx\'\n", i); - istty = isatty(fileno(stdin)); if (istty) { fprintf(stderr, "at> "); @@ -491,7 +492,7 @@ writefile(time_t runtimer, char queue) if (istty) { fprintf(stderr, "\n"); } - fprintf(fp, "marcinDELIMITER%08lx\n", i); + fprintf(fp, "\n"); if (ferror(fp)) panic("Output error"); fflush(fp); @@ -501,8 +502,7 @@ writefile(time_t runtimer, char queue) if (ferror(stdin)) panic("Input error"); - if (fclose(fp) != 0) - panic("Output error"); + fclose(fp); /* Set the x bit so that we're ready to start executing */ @@ -673,7 +673,7 @@ process_jobs(int argc, char **argv, int what) We need the unprivileged uid here since the file is owned by the real (not effective) uid. */ - PRIV_START + setregid(real_gid, effective_gid); if (queue == '=') { fprintf(stderr, "Warning: deleting running job\n"); @@ -682,8 +682,8 @@ process_jobs(int argc, char **argv, int what) perr("Cannot unlink %.500s", dirent->d_name); rc = EXIT_FAILURE; } - PRIV_END + setregid(effective_gid, real_gid); done = 1; break; @@ -693,7 +693,7 @@ process_jobs(int argc, char **argv, int what) FILE *fp; int ch; - PRIV_START + setregid(real_gid, effective_gid); fp = fopen(dirent->d_name, "r"); if (fp) { @@ -706,7 +706,7 @@ process_jobs(int argc, char **argv, int what) perr("Cannot open %.500s", dirent->d_name); rc = EXIT_FAILURE; } - PRIV_END + setregid(effective_gid, real_gid); } break; @@ -872,9 +872,10 @@ main(int argc, char **argv) */ if (disp_version) { - fprintf(stderr, "at version " VERSION "\n"); - if (argc == 2) - exit(EXIT_SUCCESS); + fprintf(stderr, "at version " VERSION "\n" + "Please report bugs to the Debian bug tracking system (http://bugs.debian.org/)\n" + "or contact the maintainers (at@packages.debian.org).\n"); + exit(EXIT_SUCCESS); } /* select our program diff --git a/at.c.export b/at.c.export deleted file mode 100644 index 104921a..0000000 --- a/at.c.export +++ /dev/null @@ -1,975 +0,0 @@ -/* - * at.c : Put file into atd queue - * Copyright (C) 1993, 1994, 1995, 1996, 1997 Thomas Koenig - * Copyright (C) 2002, 2005 Ryan Murray - * - * Atrun & Atq modifications - * Copyright (C) 1993 David Parsons - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif defined(HAVE_SYS_FCNTL_H) -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "at.h" -#include "panic.h" -#include "parsetime.h" -#include "perm.h" -#include "posixtm.h" -#include "privs.h" - -/* Macros */ - -#ifndef ATJOB_MX -#define ATJOB_MX 255 -#endif - -#define ALARMC 10 /* Number of seconds to wait for timeout */ - -#define SIZE 255 - -#define TIMEFORMAT_POSIX "%a %b %e %T %Y" -#define TIMESIZE 50 - -#define DEFAULT_QUEUE 'a' -#define BATCH_QUEUE 'b' - -enum { - ATQ, BATCH, ATRM, AT, CAT -}; /* what program we want to run */ - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -char *no_export[] = -{ - "TERM", "DISPLAY", "_", "SHELLOPTS", "BASH_VERSINFO", "EUID", "GROUPS", "PPID", "UID" -}; -static int send_mail = 0; - -/* External variables */ - -extern char **environ; -int fcreated; -char *namep; -char atfile[] = ATJOB_DIR "/12345678901234"; - -char *atinput = (char *) 0; /* where to get input from */ -char atqueue = 0; /* which queue to examine for jobs (atq) */ -char atverify = 0; /* verify time instead of queuing job */ - -/* Function declarations */ - -static void sigc(int signo); -static void alarmc(int signo); -static char *cwdname(void); -static void writefile(time_t runtimer, char queue); -static void list_jobs(void); - -/* Signal catching functions */ - -static RETSIGTYPE -sigc(int signo) -{ -/* If the user presses ^C, remove the spool file and exit - */ - if (fcreated) { - PRIV_START - /* - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ - unlink(atfile); - PRIV_END - } - exit(EXIT_FAILURE); -} - -static void -alarmc(int signo) -{ -/* Time out after some seconds - */ - panic("File locking timed out"); -} - -/* Local functions */ - -static char * -cwdname(void) -{ -/* Read in the current directory; the name will be overwritten on - * subsequent calls. - */ - static char *ptr = NULL; - static size_t size = SIZE; - - if (ptr == NULL) - ptr = (char *) mymalloc(size); - - while (1) { - if (ptr == NULL) - panic("Out of memory"); - - if (getcwd(ptr, size - 1) != NULL) - return ptr; - - if (errno != ERANGE) - perr("Cannot get current working directory"); - - free(ptr); - size += SIZE; - ptr = (char *) mymalloc(size); - } -} - -static long -nextjob() -{ - long jobno; - FILE *fid; - - jobno = 0; - fid = fopen(LFILE, "r+"); - if (fid != NULL) { - fscanf(fid, "%5lx", &jobno); - rewind(fid); - } else { - fid = fopen(LFILE, "w"); - if (fid == NULL) - return EOF; - } - jobno = (1 + jobno) % 0xfffff; /* 2^20 jobs enough? */ - fprintf(fid, "%05lx\n", jobno); - - fclose(fid); - return jobno; -} - -static void -writefile(time_t runtimer, char queue) -{ -/* This does most of the work if at or batch are invoked for writing a job. - */ - long jobno; - char *ap, *ppos, *mailname; - struct passwd *pass_entry; - struct stat statbuf; - int fd, lockdes, fd2; - FILE *fp, *fpin; - struct sigaction act; - char **atenv; - int ch; - mode_t cmask; - struct flock lock; - struct tm *runtime; - char timestr[TIMESIZE]; - pid_t pid; - int istty; - int kill_errno; - int rc; - int mailsize = 128; - struct timeval tv; - struct timezone tz; - long int i; - - gettimeofday(&tv, &tz); - srandom(getpid()+tv.tv_usec); - -/* Install the signal handler for SIGINT; terminate after removing the - * spool file if necessary - */ - memset(&act, 0, sizeof act); - act.sa_handler = sigc; - sigemptyset(&(act.sa_mask)); - act.sa_flags = 0; - - sigaction(SIGINT, &act, NULL); - - ppos = atfile + strlen(ATJOB_DIR) + 1; - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - /* Loop over all possible file names for running something at this - * particular time, see if a file is there; the first empty slot at any - * particular time is used. Lock the file LFILE first to make sure - * we're alone when doing this. - */ - - PRIV_START - - if ((lockdes = open(LFILE, O_WRONLY)) < 0) - perr("Cannot open lockfile " LFILE); - - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - - act.sa_handler = alarmc; - sigemptyset(&(act.sa_mask)); - act.sa_flags = 0; - - /* Set an alarm so a timeout occurs after ALARMC seconds, in case - * something is seriously broken. - */ - sigaction(SIGALRM, &act, NULL); - alarm(ALARMC); - fcntl(lockdes, F_SETLKW, &lock); - alarm(0); - - if ((jobno = nextjob()) == EOF) - perr("Cannot generate job number"); - - (void)snprintf(ppos, sizeof(atfile) - (ppos - atfile), - "%c%5lx%8lx", queue, jobno, (unsigned long) (runtimer / 60)); - - for (ap = ppos; *ap != '\0'; ap++) - if (*ap == ' ') - *ap = '0'; - - if (stat(atfile, &statbuf) != 0) - if (errno != ENOENT) - perr("Cannot access " ATJOB_DIR); - - /* Create the file. The x bit is only going to be set after it has - * been completely written out, to make sure it is not executed in the - * meantime. To make sure they do not get deleted, turn off their r - * bit. Yes, this is a kluge. - */ - cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR); - if ((seteuid(effective_uid)) < 0) - perr("Error in seteuid: %s", errno); - if ((fd = open(atfile, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, S_IRUSR)) == -1) - perr("Cannot create atjob file %.500s", atfile); - - if ((fd2 = dup(fd)) < 0) - perr("Error in dup() of job file"); - - if (fchown(fd2, real_uid, real_gid) != 0) - perr("Cannot give real_uid and real_gid the file"); - - PRIV_END - - /* We've successfully created the file; let's set the flag so it - * gets removed in case of an interrupt or error. - */ - fcreated = 1; - - /* Now we can release the lock, so other people can access it - */ - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - fcntl(lockdes, F_SETLKW, &lock); - close(lockdes); - - if ((fp = fdopen(fd, "w")) == NULL) - panic("Cannot reopen atjob file"); - - /* Get the userid to mail to, first by trying getlogin(), which reads - * /var/run/utmp, then from LOGNAME, finally from getpwuid(). - */ - mailname = getlogin(); - if (mailname == NULL) - mailname = getenv("LOGNAME"); - if (mailname == NULL || mailname[0] == '\0' || getpwnam(mailname) == NULL) { - pass_entry = getpwuid(real_uid); - if (pass_entry != NULL) - mailname = pass_entry->pw_name; - } - - if ((mailname == NULL) || (mailname[0] == '\0') - || (strlen(mailname) > mailsize) ) { - panic("Cannot find username to mail output to"); - } - if (atinput != (char *) NULL) { - fpin = freopen(atinput, "r", stdin); - if (fpin == NULL) - perr("Cannot open input file %.500s", atinput); - } - - fprintf(fp, "#!/bin/sh\n# atrun uid=%d gid=%d\n# mail %s %d\n", - real_uid, real_gid, mailname, send_mail); - - /* Write out the umask at the time of invocation - */ - fprintf(fp, "umask %lo\n", (unsigned long) cmask); - - /* Write out the environment. Anything that may look like a - * special character to the shell is quoted, except for \n, which is - * done with a pair of ""'s. Dont't export the no_export list (such - * as TERM or DISPLAY) because we don't want these. - */ - for (atenv = environ; *atenv != NULL; atenv++) { - int export = 1; - char *eqp; - - /* Only accept alphanumerics and underscore in variable names. - * Also require the name to not start with a digit. - * Some shells don't like other variable names. - */ - { - char *p = *atenv; - if (isdigit(*p)) - export = 0; - for (; *p != '=' && *p != '\0'; ++p) { - if (!isalnum(*p) && *p != '_') { - export = 0; - break; - } - } - } - - eqp = strchr(*atenv, '='); - if (ap == NULL) - eqp = *atenv; - else { - unsigned int i; - for (i = 0; i < sizeof(no_export) / sizeof(no_export[0]); i++) { - export = export - && (strncmp(*atenv, no_export[i], - (size_t) (eqp - *atenv)) != 0); - } - eqp++; - } - - if (export) { - fwrite(*atenv, sizeof(char), eqp - *atenv, fp); - for (ap = eqp; *ap != '\0'; ap++) { - if (*ap == '\n') - fprintf(fp, "\"\n\""); - else { - if (!isalnum(*ap)) { - switch (*ap) { - case '%': - case '/': - case '{': - case '[': - case ']': - case '=': - case '}': - case '@': - case '+': - case '#': - case ',': - case '.': - case ':': - case '-': - case '_': - break; - default: - fputc('\\', fp); - break; - } - } - fputc(*ap, fp); - } - } - fputs("; export ", fp); - fwrite(*atenv, sizeof(char), eqp - *atenv - 1, fp); - fputc('\n', fp); - - } - } - /* Cd to the directory at the time and write out all the - * commands the user supplies from stdin. - */ - fprintf(fp, "cd "); - for (ap = cwdname(); *ap != '\0'; ap++) { - if (*ap == '\n') - fprintf(fp, "\"\n\""); - else { - if (*ap != '/' && !isalnum(*ap)) - fputc('\\', fp); - - fputc(*ap, fp); - } - } - /* Test cd's exit status: die if the original directory has been - * removed, become unreadable or whatever - */ - fprintf(fp, " || {\n\t echo 'Execution directory " - "inaccessible' >&2\n\t exit 1\n}\n"); - - i = random(); - fprintf(fp, "${SHELL:-/bin/sh} << \'marcinDELIMITER%08lx\'\n", i); - - istty = isatty(fileno(stdin)); - if (istty) { - fprintf(stderr, "at> "); - fflush(stderr); - } - while ((ch = getchar()) != EOF) { - fputc(ch, fp); - if (ch == '\n' && istty) { - fprintf(stderr, "at> "); - fflush(stderr); - } - } - if (istty) { - fprintf(stderr, "\n"); - } - fprintf(fp, "marcinDELIMITER%08lx\n", i); - if (ferror(fp)) - panic("Output error"); - fflush(fp); - if (ferror(fp)) - panic("Output error"); - - if (ferror(stdin)) - panic("Input error"); - - fclose(fp); - - /* Set the x bit so that we're ready to start executing - */ - - if (fchmod(fd2, S_IRUSR | S_IWUSR | S_IXUSR) < 0) - perr("Cannot give away file"); - - close(fd2); - - runtime = localtime(&runtimer); - - strftime(timestr, TIMESIZE, TIMEFORMAT_POSIX, runtime); - fprintf(stderr, "job %ld at %s\n", jobno, timestr); - - /* Signal atd, if present. Usual precautions taken... */ - fd = open(PIDFILE, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "Can't open " PIDFILE " to signal atd. No atd running?\n"); - return; - } - - if (fstat(fd, &statbuf) == -1) - return; - if ((statbuf.st_uid != 0) || !S_ISREG(statbuf.st_mode) || - (statbuf.st_mode & (S_IWGRP | S_IWOTH))) - return; - - fp = fdopen(fd, "r"); - if (fp == NULL) - return; - if (fscanf(fp, "%d", &pid) != 1) - return; - - kill_errno = 0; - - PRIV_START - if (kill(pid, SIGHUP) == -1) - kill_errno = errno; - PRIV_END - - switch (kill_errno) { - case 0: - break; - - case EINVAL: - panic("kill returned EINVAL"); - break; - - case EPERM: - fprintf(stderr,"Can't signal atd (permission denied)\n"); - break; - - case ESRCH: - fprintf(stderr, "Warning: at daemon not running\n"); - break; - - default: - panic("kill returned impossible error number"); - break; - } - return; -} - -static void -list_jobs(void) -{ - /* List all a user's jobs in the queue, by looping through ATJOB_DIR, - * or everybody's if we are root - */ - DIR *spool; - struct dirent *dirent; - struct stat buf; - struct tm *runtime; - unsigned long ctm; - char queue; - long jobno; - time_t runtimer; - char timestr[TIMESIZE]; - struct passwd *pwd; - - PRIV_START - - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if ((spool = opendir(".")) == NULL) - perr("Cannot open " ATJOB_DIR); - - /* Loop over every file in the directory - */ - while ((dirent = readdir(spool)) != NULL) { - if (stat(dirent->d_name, &buf) != 0) - perr("Cannot stat in " ATJOB_DIR); - - /* See it's a regular file and is the user's */ - if (!S_ISREG(buf.st_mode) - || ((buf.st_uid != real_uid) && !(real_uid == 0)) - || atverify) - continue; - - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - if (atqueue && (queue != atqueue)) - continue; - - runtimer = 60 * (time_t) ctm; - runtime = localtime(&runtimer); - - strftime(timestr, TIMESIZE, TIMEFORMAT_POSIX, runtime); - - if ((pwd = getpwuid(buf.st_uid))) - printf("%ld\t%s %c %s\n", jobno, timestr, queue, pwd->pw_name); - else - printf("%ld\t%s %c\n", jobno, timestr, queue); - } - PRIV_END -} - -static int -process_jobs(int argc, char **argv, int what) -{ - /* Delete every argument (job - ID) given - */ - int i; - struct stat buf; - DIR *spool; - struct dirent *dirent; - unsigned long ctm; - char queue; - long jobno; - int rc = EXIT_SUCCESS; - int done; - - for (i = optind; i < argc; i++) { - done = 0; - PRIV_START - - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if ((spool = opendir(".")) == NULL) - perr("Cannot open " ATJOB_DIR); - - PRIV_END - - /* Loop over every file in the directory - */ - while ((dirent = readdir(spool)) != NULL) { - - PRIV_START - if (stat(dirent->d_name, &buf) != 0) - perr("Cannot stat in " ATJOB_DIR); - PRIV_END - - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - if (atoi(argv[i]) == jobno) { - if ((buf.st_uid != real_uid) && !(real_uid == 0)) { - fprintf(stderr, "%s: Not owner\n", argv[i]); - exit(EXIT_FAILURE); - } - switch (what) { - case ATRM: - - /* - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ - PRIV_START - - if (queue == '=') { - fprintf(stderr, "Warning: deleting running job\n"); - } - if (unlink(dirent->d_name) != 0) { - perr("Cannot unlink %.500s", dirent->d_name); - rc = EXIT_FAILURE; - } - PRIV_END - - done = 1; - - break; - - case CAT: - { - FILE *fp; - int ch; - - PRIV_START - fp = fopen(dirent->d_name, "r"); - - if (fp) { - while ((ch = getc(fp)) != EOF) { - putchar(ch); - } - done = 1; - } - else { - perr("Cannot open %.500s", dirent->d_name); - rc = EXIT_FAILURE; - } - PRIV_END - } - break; - - default: - fprintf(stderr, - "Internal error, process_jobs = %d\n", what); - exit(EXIT_FAILURE); - break; - } - } - } - closedir(spool); - if (done != 1) { - fprintf(stderr, "Cannot find jobid %s\n", argv[i] ); - rc = EXIT_FAILURE; - } - } - return rc; -} /* delete_jobs */ - -/* Global functions */ - -void * -mymalloc(size_t n) -{ - void *p; - if ((p = malloc(n)) == (void *) 0) { - fprintf(stderr, "Virtual memory exhausted\n"); - exit(EXIT_FAILURE); - } - return p; -} - -int -main(int argc, char **argv) -{ - int c; - char queue = DEFAULT_QUEUE; - char queue_set = 0; - char *pgm; - - int program = AT; /* our default program */ - char *options = "q:f:MmbvlrdhVct:"; /* default options for at */ - int disp_version = 0; - time_t timer = 0; - struct passwd *pwe; - struct group *ge; - - RELINQUISH_PRIVS - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - /* Eat any leading paths - */ - if ((pgm = strrchr(argv[0], '/')) == NULL) - pgm = argv[0]; - else - pgm++; - - namep = pgm; - - /* find out what this program is supposed to do - */ - if (strcmp(pgm, "atq") == 0) { - program = ATQ; - options = "hq:V"; - } else if (strcmp(pgm, "atrm") == 0) { - program = ATRM; - options = "hV"; - } - /* process whatever options we can process - */ - opterr = 1; - while ((c = getopt(argc, argv, options)) != EOF) - switch (c) { - case 'h': - usage(); - exit (0); - - case 'v': /* verify time settings */ - atverify = 1; - break; - - case 'm': /* send mail when job is complete */ - send_mail = 1; - break; - - case 'M': /* don't send mail, even when job failed */ - send_mail = -1; - break; - - case 'f': - atinput = optarg; - break; - - case 'q': /* specify queue */ - if (strlen(optarg) > 1) - usage(); - - atqueue = queue = *optarg; - if (!(islower(queue) || isupper(queue)) & (queue != '=')) - usage(); - - queue_set = 1; - break; - - case 'r': - case 'd': - if (program != AT) - usage(); - - program = ATRM; - options = "V"; - break; - - case 'l': - if (program != AT) - usage(); - - program = ATQ; - options = "q:V"; - break; - - case 'b': - if (program != AT) - usage(); - - program = BATCH; - options = ""; - break; - - case 'V': - disp_version = 1; - break; - - case 'c': - program = CAT; - options = ""; - break; - - case 't': - if (!posixtime(&timer, optarg, PDS_LEADING_YEAR | PDS_CENTURY | PDS_SECONDS)) { - fprintf(stderr, "invalid date format: %s\n", optarg); - exit(EXIT_FAILURE); - } - /* drop seconds */ - timer -= timer % 60; - break; - - default: - usage(); - break; - } - /* end of options eating - */ - - if (disp_version) { - fprintf(stderr, "at version " VERSION "\n"); - if (argc == 2) - exit(EXIT_SUCCESS); - } - - /* select our program - */ - if (!check_permission()) { - fprintf(stderr, "You do not have permission to use %.100s.\n", namep); - exit(EXIT_FAILURE); - } - switch (program) { - int i; - case ATQ: - - REDUCE_PRIV(daemon_uid, daemon_gid) - - list_jobs(); - break; - - case ATRM: - - REDUCE_PRIV(daemon_uid, daemon_gid) - if (argc > optind) { - for (i = optind; i < argc ; i++ ) - if (strspn(argv[i],"0123456789") != strlen(argv[i])) { - fprintf(stderr,"at: unknown jobid: %s\n", argv[i]); - exit(EXIT_FAILURE); - } - return process_jobs(argc, argv, ATRM); - } - else - usage(); - break; - - case CAT: - - if (argc > optind) { - for (i = optind; i < argc ; i++ ) - if (strspn(argv[i],"0123456789") != strlen(argv[i])) { - fprintf(stderr,"at: unknown jobid: %s", argv[i]); - exit(EXIT_FAILURE); - } - return process_jobs(argc, argv, CAT); - } - else - usage(); - break; - - case AT: - if (argc > optind) { - if (timer != 0) { - fprintf(stderr, "Cannot give time twice.\n"); - exit(EXIT_FAILURE); - } - timer = parsetime(time(0), argc - optind, argv + optind); - } - - if (timer == 0) { - fprintf(stderr, "Garbled time\n"); - exit(EXIT_FAILURE); - } - if (atverify) { - struct tm *tm = localtime(&timer); - fprintf(stderr, "%s\n", asctime(tm)); - } - - /* POSIX.2 allows the shell specified by the user's SHELL environment - variable, the login shell from the user's password database entry, - or /bin/sh to be the command interpreter that processes the at-job. - It also alows a warning diagnostic to be printed. Because of the - possible variance, we always output the diagnostic. */ - - fprintf(stderr, "warning: commands will be executed using /bin/sh\n"); - - writefile(timer, queue); - break; - - case BATCH: - if (queue_set) - queue = toupper(queue); - else - queue = BATCH_QUEUE; - - if (argc > optind) { - if (timer != 0) { - fprintf(stderr, "Cannot give time twice.\n"); - exit(EXIT_FAILURE); - } - timer = parsetime(time(0), argc, argv); - } else if (timer == 0) - timer = time(NULL); - - if (atverify) { - struct tm *tm = localtime(&timer); - fprintf(stderr, "%s\n", asctime(tm)); - } - writefile(timer, queue); - break; - - default: - panic("Internal error"); - break; - } - exit(EXIT_SUCCESS); -} - diff --git a/at.c.fclose b/at.c.fclose deleted file mode 100644 index 634795e..0000000 --- a/at.c.fclose +++ /dev/null @@ -1,976 +0,0 @@ -/* - * at.c : Put file into atd queue - * Copyright (C) 1993, 1994, 1995, 1996, 1997 Thomas Koenig - * Copyright (C) 2002, 2005 Ryan Murray - * - * Atrun & Atq modifications - * Copyright (C) 1993 David Parsons - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif defined(HAVE_SYS_FCNTL_H) -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "at.h" -#include "panic.h" -#include "parsetime.h" -#include "perm.h" -#include "posixtm.h" -#include "privs.h" - -/* Macros */ - -#ifndef ATJOB_MX -#define ATJOB_MX 255 -#endif - -#define ALARMC 10 /* Number of seconds to wait for timeout */ - -#define SIZE 255 - -#define TIMEFORMAT_POSIX "%a %b %e %T %Y" -#define TIMESIZE 50 - -#define DEFAULT_QUEUE 'a' -#define BATCH_QUEUE 'b' - -enum { - ATQ, BATCH, ATRM, AT, CAT -}; /* what program we want to run */ - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -char *no_export[] = -{ - "TERM", "DISPLAY", "_", "SHELLOPTS", "BASH_VERSINFO", "EUID", "GROUPS", "PPID", "UID" -}; -static int send_mail = 0; - -/* External variables */ - -extern char **environ; -int fcreated; -char *namep; -char atfile[] = ATJOB_DIR "/12345678901234"; - -char *atinput = (char *) 0; /* where to get input from */ -char atqueue = 0; /* which queue to examine for jobs (atq) */ -char atverify = 0; /* verify time instead of queuing job */ - -/* Function declarations */ - -static void sigc(int signo); -static void alarmc(int signo); -static char *cwdname(void); -static void writefile(time_t runtimer, char queue); -static void list_jobs(void); - -/* Signal catching functions */ - -static RETSIGTYPE -sigc(int signo) -{ -/* If the user presses ^C, remove the spool file and exit - */ - if (fcreated) { - PRIV_START - /* - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ - unlink(atfile); - PRIV_END - } - exit(EXIT_FAILURE); -} - -static void -alarmc(int signo) -{ -/* Time out after some seconds - */ - panic("File locking timed out"); -} - -/* Local functions */ - -static char * -cwdname(void) -{ -/* Read in the current directory; the name will be overwritten on - * subsequent calls. - */ - static char *ptr = NULL; - static size_t size = SIZE; - - if (ptr == NULL) - ptr = (char *) mymalloc(size); - - while (1) { - if (ptr == NULL) - panic("Out of memory"); - - if (getcwd(ptr, size - 1) != NULL) - return ptr; - - if (errno != ERANGE) - perr("Cannot get current working directory"); - - free(ptr); - size += SIZE; - ptr = (char *) mymalloc(size); - } -} - -static long -nextjob() -{ - long jobno; - FILE *fid; - - jobno = 0; - fid = fopen(LFILE, "r+"); - if (fid != NULL) { - fscanf(fid, "%5lx", &jobno); - rewind(fid); - } else { - fid = fopen(LFILE, "w"); - if (fid == NULL) - return EOF; - } - jobno = (1 + jobno) % 0xfffff; /* 2^20 jobs enough? */ - fprintf(fid, "%05lx\n", jobno); - - fclose(fid); - return jobno; -} - -static void -writefile(time_t runtimer, char queue) -{ -/* This does most of the work if at or batch are invoked for writing a job. - */ - long jobno; - char *ap, *ppos, *mailname; - struct passwd *pass_entry; - struct stat statbuf; - int fd, lockdes, fd2; - FILE *fp, *fpin; - struct sigaction act; - char **atenv; - int ch; - mode_t cmask; - struct flock lock; - struct tm *runtime; - char timestr[TIMESIZE]; - pid_t pid; - int istty; - int kill_errno; - int rc; - int mailsize = 128; - struct timeval tv; - struct timezone tz; - long int i; - - gettimeofday(&tv, &tz); - srandom(getpid()+tv.tv_usec); - -/* Install the signal handler for SIGINT; terminate after removing the - * spool file if necessary - */ - memset(&act, 0, sizeof act); - act.sa_handler = sigc; - sigemptyset(&(act.sa_mask)); - act.sa_flags = 0; - - sigaction(SIGINT, &act, NULL); - - ppos = atfile + strlen(ATJOB_DIR) + 1; - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - /* Loop over all possible file names for running something at this - * particular time, see if a file is there; the first empty slot at any - * particular time is used. Lock the file LFILE first to make sure - * we're alone when doing this. - */ - - PRIV_START - - if ((lockdes = open(LFILE, O_WRONLY)) < 0) - perr("Cannot open lockfile " LFILE); - - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - - act.sa_handler = alarmc; - sigemptyset(&(act.sa_mask)); - act.sa_flags = 0; - - /* Set an alarm so a timeout occurs after ALARMC seconds, in case - * something is seriously broken. - */ - sigaction(SIGALRM, &act, NULL); - alarm(ALARMC); - fcntl(lockdes, F_SETLKW, &lock); - alarm(0); - - if ((jobno = nextjob()) == EOF) - perr("Cannot generate job number"); - - (void)snprintf(ppos, sizeof(atfile) - (ppos - atfile), - "%c%5lx%8lx", queue, jobno, (unsigned long) (runtimer / 60)); - - for (ap = ppos; *ap != '\0'; ap++) - if (*ap == ' ') - *ap = '0'; - - if (stat(atfile, &statbuf) != 0) - if (errno != ENOENT) - perr("Cannot access " ATJOB_DIR); - - /* Create the file. The x bit is only going to be set after it has - * been completely written out, to make sure it is not executed in the - * meantime. To make sure they do not get deleted, turn off their r - * bit. Yes, this is a kluge. - */ - cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR); - if ((seteuid(effective_uid)) < 0) - perr("Error in seteuid: %s", errno); - if ((fd = open(atfile, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, S_IRUSR)) == -1) - perr("Cannot create atjob file %.500s", atfile); - - if ((fd2 = dup(fd)) < 0) - perr("Error in dup() of job file"); - - if (fchown(fd2, real_uid, real_gid) != 0) - perr("Cannot give real_uid and real_gid the file"); - - PRIV_END - - /* We've successfully created the file; let's set the flag so it - * gets removed in case of an interrupt or error. - */ - fcreated = 1; - - /* Now we can release the lock, so other people can access it - */ - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - fcntl(lockdes, F_SETLKW, &lock); - close(lockdes); - - if ((fp = fdopen(fd, "w")) == NULL) - panic("Cannot reopen atjob file"); - - /* Get the userid to mail to, first by trying getlogin(), which reads - * /var/run/utmp, then from LOGNAME, finally from getpwuid(). - */ - mailname = getlogin(); - if (mailname == NULL) - mailname = getenv("LOGNAME"); - if (mailname == NULL || mailname[0] == '\0' || getpwnam(mailname) == NULL) { - pass_entry = getpwuid(real_uid); - if (pass_entry != NULL) - mailname = pass_entry->pw_name; - } - - if ((mailname == NULL) || (mailname[0] == '\0') - || (strlen(mailname) > mailsize) ) { - panic("Cannot find username to mail output to"); - } - if (atinput != (char *) NULL) { - fpin = freopen(atinput, "r", stdin); - if (fpin == NULL) - perr("Cannot open input file %.500s", atinput); - } - - fprintf(fp, "#!/bin/sh\n# atrun uid=%d gid=%d\n# mail %s %d\n", - real_uid, real_gid, mailname, send_mail); - - /* Write out the umask at the time of invocation - */ - fprintf(fp, "umask %lo\n", (unsigned long) cmask); - - /* Write out the environment. Anything that may look like a - * special character to the shell is quoted, except for \n, which is - * done with a pair of ""'s. Dont't export the no_export list (such - * as TERM or DISPLAY) because we don't want these. - */ - for (atenv = environ; *atenv != NULL; atenv++) { - int export = 1; - char *eqp; - - /* Only accept alphanumerics and underscore in variable names. - * Also require the name to not start with a digit. - * Some shells don't like other variable names. - */ - { - char *p = *atenv; - if (isdigit(*p)) - export = 0; - for (; *p != '=' && *p != '\0'; ++p) { - if (!isalnum(*p) && *p != '_') { - export = 0; - break; - } - } - } - - eqp = strchr(*atenv, '='); - if (ap == NULL) - eqp = *atenv; - else { - unsigned int i; - for (i = 0; i < sizeof(no_export) / sizeof(no_export[0]); i++) { - export = export - && ((((size_t) (eqp - *atenv)) != strlen(no_export[i])) - ||(strncmp(*atenv, no_export[i],(size_t) (eqp - *atenv)) != 0) - ); - } - eqp++; - } - - if (export) { - fwrite(*atenv, sizeof(char), eqp - *atenv, fp); - for (ap = eqp; *ap != '\0'; ap++) { - if (*ap == '\n') - fprintf(fp, "\"\n\""); - else { - if (!isalnum(*ap)) { - switch (*ap) { - case '%': - case '/': - case '{': - case '[': - case ']': - case '=': - case '}': - case '@': - case '+': - case '#': - case ',': - case '.': - case ':': - case '-': - case '_': - break; - default: - fputc('\\', fp); - break; - } - } - fputc(*ap, fp); - } - } - fputs("; export ", fp); - fwrite(*atenv, sizeof(char), eqp - *atenv - 1, fp); - fputc('\n', fp); - - } - } - /* Cd to the directory at the time and write out all the - * commands the user supplies from stdin. - */ - fprintf(fp, "cd "); - for (ap = cwdname(); *ap != '\0'; ap++) { - if (*ap == '\n') - fprintf(fp, "\"\n\""); - else { - if (*ap != '/' && !isalnum(*ap)) - fputc('\\', fp); - - fputc(*ap, fp); - } - } - /* Test cd's exit status: die if the original directory has been - * removed, become unreadable or whatever - */ - fprintf(fp, " || {\n\t echo 'Execution directory " - "inaccessible' >&2\n\t exit 1\n}\n"); - - i = random(); - fprintf(fp, "${SHELL:-/bin/sh} << \'marcinDELIMITER%08lx\'\n", i); - - istty = isatty(fileno(stdin)); - if (istty) { - fprintf(stderr, "at> "); - fflush(stderr); - } - while ((ch = getchar()) != EOF) { - fputc(ch, fp); - if (ch == '\n' && istty) { - fprintf(stderr, "at> "); - fflush(stderr); - } - } - if (istty) { - fprintf(stderr, "\n"); - } - fprintf(fp, "marcinDELIMITER%08lx\n", i); - if (ferror(fp)) - panic("Output error"); - fflush(fp); - if (ferror(fp)) - panic("Output error"); - - if (ferror(stdin)) - panic("Input error"); - - fclose(fp); - - /* Set the x bit so that we're ready to start executing - */ - - if (fchmod(fd2, S_IRUSR | S_IWUSR | S_IXUSR) < 0) - perr("Cannot give away file"); - - close(fd2); - - runtime = localtime(&runtimer); - - strftime(timestr, TIMESIZE, TIMEFORMAT_POSIX, runtime); - fprintf(stderr, "job %ld at %s\n", jobno, timestr); - - /* Signal atd, if present. Usual precautions taken... */ - fd = open(PIDFILE, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "Can't open " PIDFILE " to signal atd. No atd running?\n"); - return; - } - - if (fstat(fd, &statbuf) == -1) - return; - if ((statbuf.st_uid != 0) || !S_ISREG(statbuf.st_mode) || - (statbuf.st_mode & (S_IWGRP | S_IWOTH))) - return; - - fp = fdopen(fd, "r"); - if (fp == NULL) - return; - if (fscanf(fp, "%d", &pid) != 1) - return; - - kill_errno = 0; - - PRIV_START - if (kill(pid, SIGHUP) == -1) - kill_errno = errno; - PRIV_END - - switch (kill_errno) { - case 0: - break; - - case EINVAL: - panic("kill returned EINVAL"); - break; - - case EPERM: - fprintf(stderr,"Can't signal atd (permission denied)\n"); - break; - - case ESRCH: - fprintf(stderr, "Warning: at daemon not running\n"); - break; - - default: - panic("kill returned impossible error number"); - break; - } - return; -} - -static void -list_jobs(void) -{ - /* List all a user's jobs in the queue, by looping through ATJOB_DIR, - * or everybody's if we are root - */ - DIR *spool; - struct dirent *dirent; - struct stat buf; - struct tm *runtime; - unsigned long ctm; - char queue; - long jobno; - time_t runtimer; - char timestr[TIMESIZE]; - struct passwd *pwd; - - PRIV_START - - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if ((spool = opendir(".")) == NULL) - perr("Cannot open " ATJOB_DIR); - - /* Loop over every file in the directory - */ - while ((dirent = readdir(spool)) != NULL) { - if (stat(dirent->d_name, &buf) != 0) - perr("Cannot stat in " ATJOB_DIR); - - /* See it's a regular file and is the user's */ - if (!S_ISREG(buf.st_mode) - || ((buf.st_uid != real_uid) && !(real_uid == 0)) - || atverify) - continue; - - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - if (atqueue && (queue != atqueue)) - continue; - - runtimer = 60 * (time_t) ctm; - runtime = localtime(&runtimer); - - strftime(timestr, TIMESIZE, TIMEFORMAT_POSIX, runtime); - - if ((pwd = getpwuid(buf.st_uid))) - printf("%ld\t%s %c %s\n", jobno, timestr, queue, pwd->pw_name); - else - printf("%ld\t%s %c\n", jobno, timestr, queue); - } - PRIV_END -} - -static int -process_jobs(int argc, char **argv, int what) -{ - /* Delete every argument (job - ID) given - */ - int i; - struct stat buf; - DIR *spool; - struct dirent *dirent; - unsigned long ctm; - char queue; - long jobno; - int rc = EXIT_SUCCESS; - int done; - - for (i = optind; i < argc; i++) { - done = 0; - PRIV_START - - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if ((spool = opendir(".")) == NULL) - perr("Cannot open " ATJOB_DIR); - - PRIV_END - - /* Loop over every file in the directory - */ - while ((dirent = readdir(spool)) != NULL) { - - PRIV_START - if (stat(dirent->d_name, &buf) != 0) - perr("Cannot stat in " ATJOB_DIR); - PRIV_END - - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - if (atoi(argv[i]) == jobno) { - if ((buf.st_uid != real_uid) && !(real_uid == 0)) { - fprintf(stderr, "%s: Not owner\n", argv[i]); - exit(EXIT_FAILURE); - } - switch (what) { - case ATRM: - - /* - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ - PRIV_START - - if (queue == '=') { - fprintf(stderr, "Warning: deleting running job\n"); - } - if (unlink(dirent->d_name) != 0) { - perr("Cannot unlink %.500s", dirent->d_name); - rc = EXIT_FAILURE; - } - PRIV_END - - done = 1; - - break; - - case CAT: - { - FILE *fp; - int ch; - - PRIV_START - fp = fopen(dirent->d_name, "r"); - - if (fp) { - while ((ch = getc(fp)) != EOF) { - putchar(ch); - } - done = 1; - } - else { - perr("Cannot open %.500s", dirent->d_name); - rc = EXIT_FAILURE; - } - PRIV_END - } - break; - - default: - fprintf(stderr, - "Internal error, process_jobs = %d\n", what); - exit(EXIT_FAILURE); - break; - } - } - } - closedir(spool); - if (done != 1) { - fprintf(stderr, "Cannot find jobid %s\n", argv[i] ); - rc = EXIT_FAILURE; - } - } - return rc; -} /* delete_jobs */ - -/* Global functions */ - -void * -mymalloc(size_t n) -{ - void *p; - if ((p = malloc(n)) == (void *) 0) { - fprintf(stderr, "Virtual memory exhausted\n"); - exit(EXIT_FAILURE); - } - return p; -} - -int -main(int argc, char **argv) -{ - int c; - char queue = DEFAULT_QUEUE; - char queue_set = 0; - char *pgm; - - int program = AT; /* our default program */ - char *options = "q:f:MmbvlrdhVct:"; /* default options for at */ - int disp_version = 0; - time_t timer = 0; - struct passwd *pwe; - struct group *ge; - - RELINQUISH_PRIVS - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - /* Eat any leading paths - */ - if ((pgm = strrchr(argv[0], '/')) == NULL) - pgm = argv[0]; - else - pgm++; - - namep = pgm; - - /* find out what this program is supposed to do - */ - if (strcmp(pgm, "atq") == 0) { - program = ATQ; - options = "hq:V"; - } else if (strcmp(pgm, "atrm") == 0) { - program = ATRM; - options = "hV"; - } - /* process whatever options we can process - */ - opterr = 1; - while ((c = getopt(argc, argv, options)) != EOF) - switch (c) { - case 'h': - usage(); - exit (0); - - case 'v': /* verify time settings */ - atverify = 1; - break; - - case 'm': /* send mail when job is complete */ - send_mail = 1; - break; - - case 'M': /* don't send mail, even when job failed */ - send_mail = -1; - break; - - case 'f': - atinput = optarg; - break; - - case 'q': /* specify queue */ - if (strlen(optarg) > 1) - usage(); - - atqueue = queue = *optarg; - if (!(islower(queue) || isupper(queue)) & (queue != '=')) - usage(); - - queue_set = 1; - break; - - case 'r': - case 'd': - if (program != AT) - usage(); - - program = ATRM; - options = "V"; - break; - - case 'l': - if (program != AT) - usage(); - - program = ATQ; - options = "q:V"; - break; - - case 'b': - if (program != AT) - usage(); - - program = BATCH; - options = ""; - break; - - case 'V': - disp_version = 1; - break; - - case 'c': - program = CAT; - options = ""; - break; - - case 't': - if (!posixtime(&timer, optarg, PDS_LEADING_YEAR | PDS_CENTURY | PDS_SECONDS)) { - fprintf(stderr, "invalid date format: %s\n", optarg); - exit(EXIT_FAILURE); - } - /* drop seconds */ - timer -= timer % 60; - break; - - default: - usage(); - break; - } - /* end of options eating - */ - - if (disp_version) { - fprintf(stderr, "at version " VERSION "\n"); - if (argc == 2) - exit(EXIT_SUCCESS); - } - - /* select our program - */ - if (!check_permission()) { - fprintf(stderr, "You do not have permission to use %.100s.\n", namep); - exit(EXIT_FAILURE); - } - switch (program) { - int i; - case ATQ: - - REDUCE_PRIV(daemon_uid, daemon_gid) - - list_jobs(); - break; - - case ATRM: - - REDUCE_PRIV(daemon_uid, daemon_gid) - if (argc > optind) { - for (i = optind; i < argc ; i++ ) - if (strspn(argv[i],"0123456789") != strlen(argv[i])) { - fprintf(stderr,"at: unknown jobid: %s\n", argv[i]); - exit(EXIT_FAILURE); - } - return process_jobs(argc, argv, ATRM); - } - else - usage(); - break; - - case CAT: - - if (argc > optind) { - for (i = optind; i < argc ; i++ ) - if (strspn(argv[i],"0123456789") != strlen(argv[i])) { - fprintf(stderr,"at: unknown jobid: %s", argv[i]); - exit(EXIT_FAILURE); - } - return process_jobs(argc, argv, CAT); - } - else - usage(); - break; - - case AT: - if (argc > optind) { - if (timer != 0) { - fprintf(stderr, "Cannot give time twice.\n"); - exit(EXIT_FAILURE); - } - timer = parsetime(time(0), argc - optind, argv + optind); - } - - if (timer == 0) { - fprintf(stderr, "Garbled time\n"); - exit(EXIT_FAILURE); - } - if (atverify) { - struct tm *tm = localtime(&timer); - fprintf(stderr, "%s\n", asctime(tm)); - } - - /* POSIX.2 allows the shell specified by the user's SHELL environment - variable, the login shell from the user's password database entry, - or /bin/sh to be the command interpreter that processes the at-job. - It also alows a warning diagnostic to be printed. Because of the - possible variance, we always output the diagnostic. */ - - fprintf(stderr, "warning: commands will be executed using /bin/sh\n"); - - writefile(timer, queue); - break; - - case BATCH: - if (queue_set) - queue = toupper(queue); - else - queue = BATCH_QUEUE; - - if (argc > optind) { - if (timer != 0) { - fprintf(stderr, "Cannot give time twice.\n"); - exit(EXIT_FAILURE); - } - timer = parsetime(time(0), argc, argv); - } else if (timer == 0) - timer = time(NULL); - - if (atverify) { - struct tm *tm = localtime(&timer); - fprintf(stderr, "%s\n", asctime(tm)); - } - writefile(timer, queue); - break; - - default: - panic("Internal error"); - break; - } - exit(EXIT_SUCCESS); -} - diff --git a/at.c.opt_V b/at.c.opt_V deleted file mode 100644 index 0d409ca..0000000 --- a/at.c.opt_V +++ /dev/null @@ -1,970 +0,0 @@ -/* - * at.c : Put file into atd queue - * Copyright (C) 1993, 1994, 1995, 1996, 1997 Thomas Koenig - * Copyright (C) 2002, 2005 Ryan Murray - * - * Atrun & Atq modifications - * Copyright (C) 1993 David Parsons - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif defined(HAVE_SYS_FCNTL_H) -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef TM_IN_SYS_TIME -#include -#else -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "at.h" -#include "panic.h" -#include "parsetime.h" -#include "perm.h" -#include "posixtm.h" -#include "privs.h" - -/* Macros */ - -#ifndef ATJOB_MX -#define ATJOB_MX 255 -#endif - -#define ALARMC 10 /* Number of seconds to wait for timeout */ - -#define SIZE 255 - -#define TIMEFORMAT_POSIX "%a %b %e %T %Y" -#define TIMESIZE 50 - -#define DEFAULT_QUEUE 'a' -#define BATCH_QUEUE 'b' - -enum { - ATQ, BATCH, ATRM, AT, CAT -}; /* what program we want to run */ - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -char *no_export[] = -{ - "TERM", "DISPLAY", "_", "SHELLOPTS", "BASH_VERSINFO", "EUID", "GROUPS", "PPID", "UID" -}; -static int send_mail = 0; - -/* External variables */ - -extern char **environ; -int fcreated; -char *namep; -char atfile[] = ATJOB_DIR "/12345678901234"; - -char *atinput = (char *) 0; /* where to get input from */ -char atqueue = 0; /* which queue to examine for jobs (atq) */ -char atverify = 0; /* verify time instead of queuing job */ - -/* Function declarations */ - -static void sigc(int signo); -static void alarmc(int signo); -static char *cwdname(void); -static void writefile(time_t runtimer, char queue); -static void list_jobs(void); - -/* Signal catching functions */ - -static RETSIGTYPE -sigc(int signo) -{ -/* If the user presses ^C, remove the spool file and exit - */ - if (fcreated) { - PRIV_START - /* - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ - unlink(atfile); - PRIV_END - } - exit(EXIT_FAILURE); -} - -static void -alarmc(int signo) -{ -/* Time out after some seconds - */ - panic("File locking timed out"); -} - -/* Local functions */ - -static char * -cwdname(void) -{ -/* Read in the current directory; the name will be overwritten on - * subsequent calls. - */ - static char *ptr = NULL; - static size_t size = SIZE; - - if (ptr == NULL) - ptr = (char *) mymalloc(size); - - while (1) { - if (ptr == NULL) - panic("Out of memory"); - - if (getcwd(ptr, size - 1) != NULL) - return ptr; - - if (errno != ERANGE) - perr("Cannot get current working directory"); - - free(ptr); - size += SIZE; - ptr = (char *) mymalloc(size); - } -} - -static long -nextjob() -{ - long jobno; - FILE *fid; - - jobno = 0; - fid = fopen(LFILE, "r+"); - if (fid != NULL) { - fscanf(fid, "%5lx", &jobno); - rewind(fid); - } else { - fid = fopen(LFILE, "w"); - if (fid == NULL) - return EOF; - } - jobno = (1 + jobno) % 0xfffff; /* 2^20 jobs enough? */ - fprintf(fid, "%05lx\n", jobno); - - fclose(fid); - return jobno; -} - -static void -writefile(time_t runtimer, char queue) -{ -/* This does most of the work if at or batch are invoked for writing a job. - */ - long jobno; - char *ap, *ppos, *mailname; - struct passwd *pass_entry; - struct stat statbuf; - int fd, lockdes, fd2; - FILE *fp, *fpin; - struct sigaction act; - char **atenv; - int ch; - mode_t cmask; - struct flock lock; - struct tm *runtime; - char timestr[TIMESIZE]; - pid_t pid; - int istty; - int kill_errno; - int rc; - int mailsize = 128; - -/* Install the signal handler for SIGINT; terminate after removing the - * spool file if necessary - */ - memset(&act, 0, sizeof act); - act.sa_handler = sigc; - sigemptyset(&(act.sa_mask)); - act.sa_flags = 0; - - sigaction(SIGINT, &act, NULL); - - ppos = atfile + strlen(ATJOB_DIR) + 1; - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - /* Loop over all possible file names for running something at this - * particular time, see if a file is there; the first empty slot at any - * particular time is used. Lock the file LFILE first to make sure - * we're alone when doing this. - */ - - PRIV_START - - if ((lockdes = open(LFILE, O_WRONLY)) < 0) - perr("Cannot open lockfile " LFILE); - - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - - act.sa_handler = alarmc; - sigemptyset(&(act.sa_mask)); - act.sa_flags = 0; - - /* Set an alarm so a timeout occurs after ALARMC seconds, in case - * something is seriously broken. - */ - sigaction(SIGALRM, &act, NULL); - alarm(ALARMC); - fcntl(lockdes, F_SETLKW, &lock); - alarm(0); - - if ((jobno = nextjob()) == EOF) - perr("Cannot generate job number"); - - (void)snprintf(ppos, sizeof(atfile) - (ppos - atfile), - "%c%5lx%8lx", queue, jobno, (unsigned long) (runtimer / 60)); - - for (ap = ppos; *ap != '\0'; ap++) - if (*ap == ' ') - *ap = '0'; - - if (stat(atfile, &statbuf) != 0) - if (errno != ENOENT) - perr("Cannot access " ATJOB_DIR); - - /* Create the file. The x bit is only going to be set after it has - * been completely written out, to make sure it is not executed in the - * meantime. To make sure they do not get deleted, turn off their r - * bit. Yes, this is a kluge. - */ - cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR); - if ((seteuid(effective_uid)) < 0) - perr("Error in seteuid: %s", errno); - if ((fd = open(atfile, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, S_IRUSR)) == -1) - perr("Cannot create atjob file %.500s", atfile); - - if ((fd2 = dup(fd)) < 0) - perr("Error in dup() of job file"); - - if (fchown(fd2, real_uid, real_gid) != 0) - perr("Cannot give real_uid and real_gid the file"); - - PRIV_END - - /* We've successfully created the file; let's set the flag so it - * gets removed in case of an interrupt or error. - */ - fcreated = 1; - - /* Now we can release the lock, so other people can access it - */ - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - fcntl(lockdes, F_SETLKW, &lock); - close(lockdes); - - if ((fp = fdopen(fd, "w")) == NULL) - panic("Cannot reopen atjob file"); - - /* Get the userid to mail to, first by trying getlogin(), which reads - * /var/run/utmp, then from LOGNAME, finally from getpwuid(). - */ - mailname = getlogin(); - if (mailname == NULL) - mailname = getenv("LOGNAME"); - if (mailname == NULL || mailname[0] == '\0' || getpwnam(mailname) == NULL) { - pass_entry = getpwuid(real_uid); - if (pass_entry != NULL) - mailname = pass_entry->pw_name; - } - - if ((mailname == NULL) || (mailname[0] == '\0') - || (strlen(mailname) > mailsize) ) { - panic("Cannot find username to mail output to"); - } - if (atinput != (char *) NULL) { - fpin = freopen(atinput, "r", stdin); - if (fpin == NULL) - perr("Cannot open input file %.500s", atinput); - } - - fprintf(fp, "#!/bin/sh\n# atrun uid=%d gid=%d\n# mail %s %d\n", - real_uid, real_gid, mailname, send_mail); - - /* Write out the umask at the time of invocation - */ - fprintf(fp, "umask %lo\n", (unsigned long) cmask); - - /* Write out the environment. Anything that may look like a - * special character to the shell is quoted, except for \n, which is - * done with a pair of ""'s. Dont't export the no_export list (such - * as TERM or DISPLAY) because we don't want these. - */ - for (atenv = environ; *atenv != NULL; atenv++) { - int export = 1; - char *eqp; - - /* Only accept alphanumerics and underscore in variable names. - * Also require the name to not start with a digit. - * Some shells don't like other variable names. - */ - { - char *p = *atenv; - if (isdigit(*p)) - export = 0; - for (; *p != '=' && *p != '\0'; ++p) { - if (!isalnum(*p) && *p != '_') { - export = 0; - break; - } - } - } - - eqp = strchr(*atenv, '='); - if (ap == NULL) - eqp = *atenv; - else { - unsigned int i; - for (i = 0; i < sizeof(no_export) / sizeof(no_export[0]); i++) { - export = export - && (strncmp(*atenv, no_export[i], - (size_t) (eqp - *atenv)) != 0); - } - eqp++; - } - - if (export) { - fwrite(*atenv, sizeof(char), eqp - *atenv, fp); - for (ap = eqp; *ap != '\0'; ap++) { - if (*ap == '\n') - fprintf(fp, "\"\n\""); - else { - if (!isalnum(*ap)) { - switch (*ap) { - case '%': - case '/': - case '{': - case '[': - case ']': - case '=': - case '}': - case '@': - case '+': - case '#': - case ',': - case '.': - case ':': - case '-': - case '_': - break; - default: - fputc('\\', fp); - break; - } - } - fputc(*ap, fp); - } - } - fputs("; export ", fp); - fwrite(*atenv, sizeof(char), eqp - *atenv - 1, fp); - fputc('\n', fp); - - } - } - /* Cd to the directory at the time and write out all the - * commands the user supplies from stdin. - */ - fprintf(fp, "cd "); - for (ap = cwdname(); *ap != '\0'; ap++) { - if (*ap == '\n') - fprintf(fp, "\"\n\""); - else { - if (*ap != '/' && !isalnum(*ap)) - fputc('\\', fp); - - fputc(*ap, fp); - } - } - /* Test cd's exit status: die if the original directory has been - * removed, become unreadable or whatever - */ - fprintf(fp, " || {\n\t echo 'Execution directory " - "inaccessible' >&2\n\t exit 1\n}\n"); - - istty = isatty(fileno(stdin)); - if (istty) { - fprintf(stderr, "at> "); - fflush(stderr); - } - while ((ch = getchar()) != EOF) { - fputc(ch, fp); - if (ch == '\n' && istty) { - fprintf(stderr, "at> "); - fflush(stderr); - } - } - if (istty) { - fprintf(stderr, "\n"); - } - fprintf(fp, "\n"); - if (ferror(fp)) - panic("Output error"); - fflush(fp); - if (ferror(fp)) - panic("Output error"); - - if (ferror(stdin)) - panic("Input error"); - - fclose(fp); - - /* Set the x bit so that we're ready to start executing - */ - - if (fchmod(fd2, S_IRUSR | S_IWUSR | S_IXUSR) < 0) - perr("Cannot give away file"); - - close(fd2); - - runtime = localtime(&runtimer); - - strftime(timestr, TIMESIZE, TIMEFORMAT_POSIX, runtime); - fprintf(stderr, "job %ld at %s\n", jobno, timestr); - - /* Signal atd, if present. Usual precautions taken... */ - fd = open(PIDFILE, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "Can't open " PIDFILE " to signal atd. No atd running?\n"); - return; - } - - if (fstat(fd, &statbuf) == -1) - return; - if ((statbuf.st_uid != 0) || !S_ISREG(statbuf.st_mode) || - (statbuf.st_mode & (S_IWGRP | S_IWOTH))) - return; - - fp = fdopen(fd, "r"); - if (fp == NULL) - return; - if (fscanf(fp, "%d", &pid) != 1) - return; - - kill_errno = 0; - - PRIV_START - if (kill(pid, SIGHUP) == -1) - kill_errno = errno; - PRIV_END - - switch (kill_errno) { - case 0: - break; - - case EINVAL: - panic("kill returned EINVAL"); - break; - - case EPERM: - fprintf(stderr,"Can't signal atd (permission denied)\n"); - break; - - case ESRCH: - fprintf(stderr, "Warning: at daemon not running\n"); - break; - - default: - panic("kill returned impossible error number"); - break; - } - return; -} - -static void -list_jobs(void) -{ - /* List all a user's jobs in the queue, by looping through ATJOB_DIR, - * or everybody's if we are root - */ - DIR *spool; - struct dirent *dirent; - struct stat buf; - struct tm *runtime; - unsigned long ctm; - char queue; - long jobno; - time_t runtimer; - char timestr[TIMESIZE]; - struct passwd *pwd; - - PRIV_START - - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if ((spool = opendir(".")) == NULL) - perr("Cannot open " ATJOB_DIR); - - /* Loop over every file in the directory - */ - while ((dirent = readdir(spool)) != NULL) { - if (stat(dirent->d_name, &buf) != 0) - perr("Cannot stat in " ATJOB_DIR); - - /* See it's a regular file and is the user's */ - if (!S_ISREG(buf.st_mode) - || ((buf.st_uid != real_uid) && !(real_uid == 0)) - || atverify) - continue; - - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - if (atqueue && (queue != atqueue)) - continue; - - runtimer = 60 * (time_t) ctm; - runtime = localtime(&runtimer); - - strftime(timestr, TIMESIZE, TIMEFORMAT_POSIX, runtime); - - if ((pwd = getpwuid(buf.st_uid))) - printf("%ld\t%s %c %s\n", jobno, timestr, queue, pwd->pw_name); - else - printf("%ld\t%s %c\n", jobno, timestr, queue); - } - PRIV_END -} - -static int -process_jobs(int argc, char **argv, int what) -{ - /* Delete every argument (job - ID) given - */ - int i; - struct stat buf; - DIR *spool; - struct dirent *dirent; - unsigned long ctm; - char queue; - long jobno; - int rc = EXIT_SUCCESS; - int done; - - for (i = optind; i < argc; i++) { - done = 0; - PRIV_START - - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if ((spool = opendir(".")) == NULL) - perr("Cannot open " ATJOB_DIR); - - PRIV_END - - /* Loop over every file in the directory - */ - while ((dirent = readdir(spool)) != NULL) { - - PRIV_START - if (stat(dirent->d_name, &buf) != 0) - perr("Cannot stat in " ATJOB_DIR); - PRIV_END - - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - if (atoi(argv[i]) == jobno) { - if ((buf.st_uid != real_uid) && !(real_uid == 0)) { - fprintf(stderr, "%s: Not owner\n", argv[i]); - exit(EXIT_FAILURE); - } - switch (what) { - case ATRM: - - /* - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ - PRIV_START - - if (queue == '=') { - fprintf(stderr, "Warning: deleting running job\n"); - } - if (unlink(dirent->d_name) != 0) { - perr("Cannot unlink %.500s", dirent->d_name); - rc = EXIT_FAILURE; - } - PRIV_END - - done = 1; - - break; - - case CAT: - { - FILE *fp; - int ch; - - PRIV_START - fp = fopen(dirent->d_name, "r"); - - if (fp) { - while ((ch = getc(fp)) != EOF) { - putchar(ch); - } - done = 1; - } - else { - perr("Cannot open %.500s", dirent->d_name); - rc = EXIT_FAILURE; - } - PRIV_END - } - break; - - default: - fprintf(stderr, - "Internal error, process_jobs = %d\n", what); - exit(EXIT_FAILURE); - break; - } - } - } - closedir(spool); - if (done != 1) { - fprintf(stderr, "Cannot find jobid %s\n", argv[i] ); - rc = EXIT_FAILURE; - } - } - return rc; -} /* delete_jobs */ - -/* Global functions */ - -void * -mymalloc(size_t n) -{ - void *p; - if ((p = malloc(n)) == (void *) 0) { - fprintf(stderr, "Virtual memory exhausted\n"); - exit(EXIT_FAILURE); - } - return p; -} - -int -main(int argc, char **argv) -{ - int c; - char queue = DEFAULT_QUEUE; - char queue_set = 0; - char *pgm; - - int program = AT; /* our default program */ - char *options = "q:f:MmbvlrdhVct:"; /* default options for at */ - int disp_version = 0; - time_t timer = 0; - struct passwd *pwe; - struct group *ge; - - RELINQUISH_PRIVS - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - /* Eat any leading paths - */ - if ((pgm = strrchr(argv[0], '/')) == NULL) - pgm = argv[0]; - else - pgm++; - - namep = pgm; - - /* find out what this program is supposed to do - */ - if (strcmp(pgm, "atq") == 0) { - program = ATQ; - options = "hq:V"; - } else if (strcmp(pgm, "atrm") == 0) { - program = ATRM; - options = "hV"; - } - /* process whatever options we can process - */ - opterr = 1; - while ((c = getopt(argc, argv, options)) != EOF) - switch (c) { - case 'h': - usage(); - exit (0); - - case 'v': /* verify time settings */ - atverify = 1; - break; - - case 'm': /* send mail when job is complete */ - send_mail = 1; - break; - - case 'M': /* don't send mail, even when job failed */ - send_mail = -1; - break; - - case 'f': - atinput = optarg; - break; - - case 'q': /* specify queue */ - if (strlen(optarg) > 1) - usage(); - - atqueue = queue = *optarg; - if (!(islower(queue) || isupper(queue)) & (queue != '=')) - usage(); - - queue_set = 1; - break; - - case 'r': - case 'd': - if (program != AT) - usage(); - - program = ATRM; - options = "V"; - break; - - case 'l': - if (program != AT) - usage(); - - program = ATQ; - options = "q:V"; - break; - - case 'b': - if (program != AT) - usage(); - - program = BATCH; - options = ""; - break; - - case 'V': - disp_version = 1; - break; - - case 'c': - program = CAT; - options = ""; - break; - - case 't': - if (!posixtime(&timer, optarg, PDS_LEADING_YEAR | PDS_CENTURY | PDS_SECONDS)) { - fprintf(stderr, "invalid date format: %s\n", optarg); - exit(EXIT_FAILURE); - } - /* drop seconds */ - timer -= timer % 60; - break; - - default: - usage(); - break; - } - /* end of options eating - */ - - if (disp_version) { - fprintf(stderr, "at version " VERSION "\n" - "Please report bugs to the Debian bug tracking system (http://bugs.debian.org/)\n" - "or contact the maintainers (at@packages.debian.org).\n"); - exit(EXIT_SUCCESS); - } - - /* select our program - */ - if (!check_permission()) { - fprintf(stderr, "You do not have permission to use %.100s.\n", namep); - exit(EXIT_FAILURE); - } - switch (program) { - int i; - case ATQ: - - REDUCE_PRIV(daemon_uid, daemon_gid) - - list_jobs(); - break; - - case ATRM: - - REDUCE_PRIV(daemon_uid, daemon_gid) - if (argc > optind) { - for (i = optind; i < argc ; i++ ) - if (strspn(argv[i],"0123456789") != strlen(argv[i])) { - fprintf(stderr,"at: unknown jobid: %s\n", argv[i]); - exit(EXIT_FAILURE); - } - return process_jobs(argc, argv, ATRM); - } - else - usage(); - break; - - case CAT: - - if (argc > optind) { - for (i = optind; i < argc ; i++ ) - if (strspn(argv[i],"0123456789") != strlen(argv[i])) { - fprintf(stderr,"at: unknown jobid: %s", argv[i]); - exit(EXIT_FAILURE); - } - return process_jobs(argc, argv, CAT); - } - else - usage(); - break; - - case AT: - if (argc > optind) { - if (timer != 0) { - fprintf(stderr, "Cannot give time twice.\n"); - exit(EXIT_FAILURE); - } - timer = parsetime(time(0), argc - optind, argv + optind); - } - - if (timer == 0) { - fprintf(stderr, "Garbled time\n"); - exit(EXIT_FAILURE); - } - if (atverify) { - struct tm *tm = localtime(&timer); - fprintf(stderr, "%s\n", asctime(tm)); - } - - /* POSIX.2 allows the shell specified by the user's SHELL environment - variable, the login shell from the user's password database entry, - or /bin/sh to be the command interpreter that processes the at-job. - It also alows a warning diagnostic to be printed. Because of the - possible variance, we always output the diagnostic. */ - - fprintf(stderr, "warning: commands will be executed using /bin/sh\n"); - - writefile(timer, queue); - break; - - case BATCH: - if (queue_set) - queue = toupper(queue); - else - queue = BATCH_QUEUE; - - if (argc > optind) { - if (timer != 0) { - fprintf(stderr, "Cannot give time twice.\n"); - exit(EXIT_FAILURE); - } - timer = parsetime(time(0), argc, argv); - } else if (timer == 0) - timer = time(NULL); - - if (atverify) { - struct tm *tm = localtime(&timer); - fprintf(stderr, "%s\n", asctime(tm)); - } - writefile(timer, queue); - break; - - default: - panic("Internal error"); - break; - } - exit(EXIT_SUCCESS); -} - diff --git a/at.c.pam b/at.c.pam deleted file mode 100644 index 2136e0b..0000000 --- a/at.c.pam +++ /dev/null @@ -1,982 +0,0 @@ -/* - * at.c : Put file into atd queue - * Copyright (C) 1993, 1994, 1995, 1996, 1997 Thomas Koenig - * Copyright (C) 2002, 2005 Ryan Murray - * - * Atrun & Atq modifications - * Copyright (C) 1993 David Parsons - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif defined(HAVE_SYS_FCNTL_H) -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef TM_IN_SYS_TIME -#include -#else -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "at.h" -#include "panic.h" -#include "parsetime.h" -#include "perm.h" -#include "posixtm.h" -#include "privs.h" - -/* Macros */ - -#ifndef ATJOB_MX -#define ATJOB_MX 255 -#endif - -#define ALARMC 10 /* Number of seconds to wait for timeout */ - -#define SIZE 255 - -#define TIMEFORMAT_POSIX "%a %b %e %T %Y" -#define TIMESIZE 50 - -#define DEFAULT_QUEUE 'a' -#define BATCH_QUEUE 'b' - -enum { - ATQ, BATCH, ATRM, AT, CAT -}; /* what program we want to run */ - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -char *no_export[] = -{ - "TERM", "DISPLAY", "_", "SHELLOPTS", "BASH_VERSINFO", "EUID", "GROUPS", "PPID", "UID" -}; -static int send_mail = 0; - -/* External variables */ - -extern char **environ; -int fcreated; -char *namep; -char atfile[] = ATJOB_DIR "/12345678901234"; - -char *atinput = (char *) 0; /* where to get input from */ -char atqueue = 0; /* which queue to examine for jobs (atq) */ -char atverify = 0; /* verify time instead of queuing job */ - -/* Function declarations */ - -static void sigc(int signo); -static void alarmc(int signo); -static char *cwdname(void); -static void writefile(time_t runtimer, char queue); -static void list_jobs(void); - -/* Signal catching functions */ - -static RETSIGTYPE -sigc(int signo) -{ -/* If the user presses ^C, remove the spool file and exit - */ - if (fcreated) { - /* - PRIV_START - - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ - setregid(real_gid, effective_gid); - unlink(atfile); - setregid(effective_gid, real_gid); - /* - PRIV_END - */ - } - exit(EXIT_FAILURE); -} - -static void -alarmc(int signo) -{ -/* Time out after some seconds - */ - panic("File locking timed out"); -} - -/* Local functions */ - -static char * -cwdname(void) -{ -/* Read in the current directory; the name will be overwritten on - * subsequent calls. - */ - static char *ptr = NULL; - static size_t size = SIZE; - - if (ptr == NULL) - ptr = (char *) mymalloc(size); - - while (1) { - if (ptr == NULL) - panic("Out of memory"); - - if (getcwd(ptr, size - 1) != NULL) - return ptr; - - if (errno != ERANGE) - perr("Cannot get current working directory"); - - free(ptr); - size += SIZE; - ptr = (char *) mymalloc(size); - } -} - -static long -nextjob() -{ - long jobno; - FILE *fid; - - jobno = 0; - fid = fopen(LFILE, "r+"); - if (fid != NULL) { - fscanf(fid, "%5lx", &jobno); - rewind(fid); - } else { - fid = fopen(LFILE, "w"); - if (fid == NULL) - return EOF; - } - jobno = (1 + jobno) % 0xfffff; /* 2^20 jobs enough? */ - fprintf(fid, "%05lx\n", jobno); - - fclose(fid); - return jobno; -} - -static void -writefile(time_t runtimer, char queue) -{ -/* This does most of the work if at or batch are invoked for writing a job. - */ - long jobno; - char *ap, *ppos, *mailname; - struct passwd *pass_entry; - struct stat statbuf; - int fd, lockdes, fd2; - FILE *fp, *fpin; - struct sigaction act; - char **atenv; - int ch; - mode_t cmask; - struct flock lock; - struct tm *runtime; - char timestr[TIMESIZE]; - pid_t pid; - int istty; - int kill_errno; - int rc; - int mailsize = 128; - -/* Install the signal handler for SIGINT; terminate after removing the - * spool file if necessary - */ - memset(&act, 0, sizeof act); - act.sa_handler = sigc; - sigemptyset(&(act.sa_mask)); - act.sa_flags = 0; - - sigaction(SIGINT, &act, NULL); - - ppos = atfile + strlen(ATJOB_DIR) + 1; - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - /* Loop over all possible file names for running something at this - * particular time, see if a file is there; the first empty slot at any - * particular time is used. Lock the file LFILE first to make sure - * we're alone when doing this. - */ - - PRIV_START - - if ((lockdes = open(LFILE, O_WRONLY)) < 0) - perr("Cannot open lockfile " LFILE); - - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - - act.sa_handler = alarmc; - sigemptyset(&(act.sa_mask)); - act.sa_flags = 0; - - /* Set an alarm so a timeout occurs after ALARMC seconds, in case - * something is seriously broken. - */ - sigaction(SIGALRM, &act, NULL); - alarm(ALARMC); - fcntl(lockdes, F_SETLKW, &lock); - alarm(0); - - if ((jobno = nextjob()) == EOF) - perr("Cannot generate job number"); - - (void)snprintf(ppos, sizeof(atfile) - (ppos - atfile), - "%c%5lx%8lx", queue, jobno, (unsigned long) (runtimer / 60)); - - for (ap = ppos; *ap != '\0'; ap++) - if (*ap == ' ') - *ap = '0'; - - if (stat(atfile, &statbuf) != 0) - if (errno != ENOENT) - perr("Cannot access " ATJOB_DIR); - - /* Create the file. The x bit is only going to be set after it has - * been completely written out, to make sure it is not executed in the - * meantime. To make sure they do not get deleted, turn off their r - * bit. Yes, this is a kluge. - */ - cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR); - seteuid(real_uid); - if ((fd = open(atfile, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, S_IRUSR)) == -1) - perr("Cannot create atjob file %.500s", atfile); - seteuid(effective_uid); - - if ((fd2 = dup(fd)) < 0) - perr("Error in dup() of job file"); - - /* - if (fchown(fd2, real_uid, real_gid) != 0) - perr("Cannot give away file"); - */ - - PRIV_END - - /* We no longer need suid root; now we just need to be able to write - * to the directory, if necessary. - */ - - REDUCE_PRIV(daemon_uid, daemon_gid) - /* We've successfully created the file; let's set the flag so it - * gets removed in case of an interrupt or error. - */ - fcreated = 1; - - /* Now we can release the lock, so other people can access it - */ - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - fcntl(lockdes, F_SETLKW, &lock); - close(lockdes); - - if ((fp = fdopen(fd, "w")) == NULL) - panic("Cannot reopen atjob file"); - - /* Get the userid to mail to, first by trying getlogin(), which reads - * /var/run/utmp, then from LOGNAME, finally from getpwuid(). - */ - mailname = getlogin(); - if (mailname == NULL) - mailname = getenv("LOGNAME"); - if (mailname == NULL || mailname[0] == '\0' || getpwnam(mailname) == NULL) { - pass_entry = getpwuid(real_uid); - if (pass_entry != NULL) - mailname = pass_entry->pw_name; - } - - if ((mailname == NULL) || (mailname[0] == '\0') - || (strlen(mailname) > mailsize) ) { - panic("Cannot find username to mail output to"); - } - if (atinput != (char *) NULL) { - fpin = freopen(atinput, "r", stdin); - if (fpin == NULL) - perr("Cannot open input file %.500s", atinput); - } - - fprintf(fp, "#!/bin/sh\n# atrun uid=%d gid=%d\n# mail %s %d\n", - real_uid, real_gid, mailname, send_mail); - - /* Write out the umask at the time of invocation - */ - fprintf(fp, "umask %lo\n", (unsigned long) cmask); - - /* Write out the environment. Anything that may look like a - * special character to the shell is quoted, except for \n, which is - * done with a pair of ""'s. Dont't export the no_export list (such - * as TERM or DISPLAY) because we don't want these. - */ - for (atenv = environ; *atenv != NULL; atenv++) { - int export = 1; - char *eqp; - - /* Only accept alphanumerics and underscore in variable names. - * Also require the name to not start with a digit. - * Some shells don't like other variable names. - */ - { - char *p = *atenv; - if (isdigit(*p)) - export = 0; - for (; *p != '=' && *p != '\0'; ++p) { - if (!isalnum(*p) && *p != '_') { - export = 0; - break; - } - } - } - - eqp = strchr(*atenv, '='); - if (ap == NULL) - eqp = *atenv; - else { - unsigned int i; - for (i = 0; i < sizeof(no_export) / sizeof(no_export[0]); i++) { - export = export - && (strncmp(*atenv, no_export[i], - (size_t) (eqp - *atenv)) != 0); - } - eqp++; - } - - if (export) { - fwrite(*atenv, sizeof(char), eqp - *atenv, fp); - for (ap = eqp; *ap != '\0'; ap++) { - if (*ap == '\n') - fprintf(fp, "\"\n\""); - else { - if (!isalnum(*ap)) { - switch (*ap) { - case '%': - case '/': - case '{': - case '[': - case ']': - case '=': - case '}': - case '@': - case '+': - case '#': - case ',': - case '.': - case ':': - case '-': - case '_': - break; - default: - fputc('\\', fp); - break; - } - } - fputc(*ap, fp); - } - } - fputs("; export ", fp); - fwrite(*atenv, sizeof(char), eqp - *atenv - 1, fp); - fputc('\n', fp); - - } - } - /* Cd to the directory at the time and write out all the - * commands the user supplies from stdin. - */ - fprintf(fp, "cd "); - for (ap = cwdname(); *ap != '\0'; ap++) { - if (*ap == '\n') - fprintf(fp, "\"\n\""); - else { - if (*ap != '/' && !isalnum(*ap)) - fputc('\\', fp); - - fputc(*ap, fp); - } - } - /* Test cd's exit status: die if the original directory has been - * removed, become unreadable or whatever - */ - fprintf(fp, " || {\n\t echo 'Execution directory " - "inaccessible' >&2\n\t exit 1\n}\n"); - - istty = isatty(fileno(stdin)); - if (istty) { - fprintf(stderr, "at> "); - fflush(stderr); - } - while ((ch = getchar()) != EOF) { - fputc(ch, fp); - if (ch == '\n' && istty) { - fprintf(stderr, "at> "); - fflush(stderr); - } - } - if (istty) { - fprintf(stderr, "\n"); - } - fprintf(fp, "\n"); - if (ferror(fp)) - panic("Output error"); - fflush(fp); - if (ferror(fp)) - panic("Output error"); - - if (ferror(stdin)) - panic("Input error"); - - fclose(fp); - - /* Set the x bit so that we're ready to start executing - */ - - if (fchmod(fd2, S_IRUSR | S_IWUSR | S_IXUSR) < 0) - perr("Cannot give away file"); - - close(fd2); - - runtime = localtime(&runtimer); - - strftime(timestr, TIMESIZE, TIMEFORMAT_POSIX, runtime); - fprintf(stderr, "job %ld at %s\n", jobno, timestr); - - /* Signal atd, if present. Usual precautions taken... */ - fd = open(PIDFILE, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "Can't open " PIDFILE " to signal atd. No atd running?\n"); - return; - } - - if (fstat(fd, &statbuf) == -1) - return; - if ((statbuf.st_uid != 0) || !S_ISREG(statbuf.st_mode) || - (statbuf.st_mode & (S_IWGRP | S_IWOTH))) - return; - - fp = fdopen(fd, "r"); - if (fp == NULL) - return; - if (fscanf(fp, "%d", &pid) != 1) - return; - - kill_errno = 0; - - PRIV_START - if (kill(pid, SIGHUP) == -1) - kill_errno = errno; - PRIV_END - - switch (kill_errno) { - case 0: - break; - - case EINVAL: - panic("kill returned EINVAL"); - break; - - case EPERM: - fprintf(stderr,"Can't signal atd (permission denied)\n"); - break; - - case ESRCH: - fprintf(stderr, "Warning: at daemon not running\n"); - break; - - default: - panic("kill returned impossible error number"); - break; - } - return; -} - -static void -list_jobs(void) -{ - /* List all a user's jobs in the queue, by looping through ATJOB_DIR, - * or everybody's if we are root - */ - DIR *spool; - struct dirent *dirent; - struct stat buf; - struct tm *runtime; - unsigned long ctm; - char queue; - long jobno; - time_t runtimer; - char timestr[TIMESIZE]; - struct passwd *pwd; - - PRIV_START - - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if ((spool = opendir(".")) == NULL) - perr("Cannot open " ATJOB_DIR); - - /* Loop over every file in the directory - */ - while ((dirent = readdir(spool)) != NULL) { - if (stat(dirent->d_name, &buf) != 0) - perr("Cannot stat in " ATJOB_DIR); - - /* See it's a regular file and is the user's */ - if (!S_ISREG(buf.st_mode) - || ((buf.st_uid != real_uid) && !(real_uid == 0)) - || atverify) - continue; - - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - if (atqueue && (queue != atqueue)) - continue; - - runtimer = 60 * (time_t) ctm; - runtime = localtime(&runtimer); - - strftime(timestr, TIMESIZE, TIMEFORMAT_POSIX, runtime); - - if ((pwd = getpwuid(buf.st_uid))) - printf("%ld\t%s %c %s\n", jobno, timestr, queue, pwd->pw_name); - else - printf("%ld\t%s %c\n", jobno, timestr, queue); - } - PRIV_END -} - -static int -process_jobs(int argc, char **argv, int what) -{ - /* Delete every argument (job - ID) given - */ - int i; - struct stat buf; - DIR *spool; - struct dirent *dirent; - unsigned long ctm; - char queue; - long jobno; - int rc = EXIT_SUCCESS; - int done; - - for (i = optind; i < argc; i++) { - done = 0; - PRIV_START - - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if ((spool = opendir(".")) == NULL) - perr("Cannot open " ATJOB_DIR); - - PRIV_END - - /* Loop over every file in the directory - */ - while ((dirent = readdir(spool)) != NULL) { - - PRIV_START - if (stat(dirent->d_name, &buf) != 0) - perr("Cannot stat in " ATJOB_DIR); - PRIV_END - - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - if (atoi(argv[i]) == jobno) { - if ((buf.st_uid != real_uid) && !(real_uid == 0)) { - fprintf(stderr, "%s: Not owner\n", argv[i]); - exit(EXIT_FAILURE); - } - switch (what) { - case ATRM: - - /* - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ - setregid(real_gid, effective_gid); - - if (queue == '=') { - fprintf(stderr, "Warning: deleting running job\n"); - } - if (unlink(dirent->d_name) != 0) { - perr("Cannot unlink %.500s", dirent->d_name); - rc = EXIT_FAILURE; - } - - setregid(effective_gid, real_gid); - done = 1; - - break; - - case CAT: - { - FILE *fp; - int ch; - - setregid(real_gid, effective_gid); - fp = fopen(dirent->d_name, "r"); - - if (fp) { - while ((ch = getc(fp)) != EOF) { - putchar(ch); - } - done = 1; - } - else { - perr("Cannot open %.500s", dirent->d_name); - rc = EXIT_FAILURE; - } - setregid(effective_gid, real_gid); - } - break; - - default: - fprintf(stderr, - "Internal error, process_jobs = %d\n", what); - exit(EXIT_FAILURE); - break; - } - } - } - closedir(spool); - if (done != 1) { - fprintf(stderr, "Cannot find jobid %s\n", argv[i] ); - rc = EXIT_FAILURE; - } - } - return rc; -} /* delete_jobs */ - -/* Global functions */ - -void * -mymalloc(size_t n) -{ - void *p; - if ((p = malloc(n)) == (void *) 0) { - fprintf(stderr, "Virtual memory exhausted\n"); - exit(EXIT_FAILURE); - } - return p; -} - -int -main(int argc, char **argv) -{ - int c; - char queue = DEFAULT_QUEUE; - char queue_set = 0; - char *pgm; - - int program = AT; /* our default program */ - char *options = "q:f:MmbvlrdhVct:"; /* default options for at */ - int disp_version = 0; - time_t timer = 0; - struct passwd *pwe; - struct group *ge; - - RELINQUISH_PRIVS - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - /* Eat any leading paths - */ - if ((pgm = strrchr(argv[0], '/')) == NULL) - pgm = argv[0]; - else - pgm++; - - namep = pgm; - - /* find out what this program is supposed to do - */ - if (strcmp(pgm, "atq") == 0) { - program = ATQ; - options = "hq:V"; - } else if (strcmp(pgm, "atrm") == 0) { - program = ATRM; - options = "hV"; - } - /* process whatever options we can process - */ - opterr = 1; - while ((c = getopt(argc, argv, options)) != EOF) - switch (c) { - case 'h': - usage(); - exit (0); - - case 'v': /* verify time settings */ - atverify = 1; - break; - - case 'm': /* send mail when job is complete */ - send_mail = 1; - break; - - case 'M': /* don't send mail, even when job failed */ - send_mail = -1; - break; - - case 'f': - atinput = optarg; - break; - - case 'q': /* specify queue */ - if (strlen(optarg) > 1) - usage(); - - atqueue = queue = *optarg; - if (!(islower(queue) || isupper(queue)) & (queue != '=')) - usage(); - - queue_set = 1; - break; - - case 'r': - case 'd': - if (program != AT) - usage(); - - program = ATRM; - options = "V"; - break; - - case 'l': - if (program != AT) - usage(); - - program = ATQ; - options = "q:V"; - break; - - case 'b': - if (program != AT) - usage(); - - program = BATCH; - options = ""; - break; - - case 'V': - disp_version = 1; - break; - - case 'c': - program = CAT; - options = ""; - break; - - case 't': - if (!posixtime(&timer, optarg, PDS_LEADING_YEAR | PDS_CENTURY | PDS_SECONDS)) { - fprintf(stderr, "invalid date format: %s\n", optarg); - exit(EXIT_FAILURE); - } - /* drop seconds */ - timer -= timer % 60; - break; - - default: - usage(); - break; - } - /* end of options eating - */ - - if (disp_version) { - fprintf(stderr, "at version " VERSION "\n" - "Please report bugs to the Debian bug tracking system (http://bugs.debian.org/)\n" - "or contact the maintainers (at@packages.debian.org).\n"); - exit(EXIT_SUCCESS); - } - - /* select our program - */ - if (!check_permission()) { - fprintf(stderr, "You do not have permission to use %.100s.\n", namep); - exit(EXIT_FAILURE); - } - switch (program) { - int i; - case ATQ: - - REDUCE_PRIV(daemon_uid, daemon_gid) - - list_jobs(); - break; - - case ATRM: - - REDUCE_PRIV(daemon_uid, daemon_gid) - if (argc > optind) { - for (i = optind; i < argc ; i++ ) - if (strspn(argv[i],"0123456789") != strlen(argv[i])) { - fprintf(stderr,"at: unknown jobid: %s\n", argv[i]); - exit(EXIT_FAILURE); - } - return process_jobs(argc, argv, ATRM); - } - else - usage(); - break; - - case CAT: - - if (argc > optind) { - for (i = optind; i < argc ; i++ ) - if (strspn(argv[i],"0123456789") != strlen(argv[i])) { - fprintf(stderr,"at: unknown jobid: %s", argv[i]); - exit(EXIT_FAILURE); - } - return process_jobs(argc, argv, CAT); - } - else - usage(); - break; - - case AT: - if (argc > optind) { - if (timer != 0) { - fprintf(stderr, "Cannot give time twice.\n"); - exit(EXIT_FAILURE); - } - timer = parsetime(time(0), argc - optind, argv + optind); - } - - if (timer == 0) { - fprintf(stderr, "Garbled time\n"); - exit(EXIT_FAILURE); - } - if (atverify) { - struct tm *tm = localtime(&timer); - fprintf(stderr, "%s\n", asctime(tm)); - } - - /* POSIX.2 allows the shell specified by the user's SHELL environment - variable, the login shell from the user's password database entry, - or /bin/sh to be the command interpreter that processes the at-job. - It also alows a warning diagnostic to be printed. Because of the - possible variance, we always output the diagnostic. */ - - fprintf(stderr, "warning: commands will be executed using /bin/sh\n"); - - writefile(timer, queue); - break; - - case BATCH: - if (queue_set) - queue = toupper(queue); - else - queue = BATCH_QUEUE; - - if (argc > optind) { - if (timer != 0) { - fprintf(stderr, "Cannot give time twice.\n"); - exit(EXIT_FAILURE); - } - timer = parsetime(time(0), argc, argv); - } else if (timer == 0) - timer = time(NULL); - - if (atverify) { - struct tm *tm = localtime(&timer); - fprintf(stderr, "%s\n", asctime(tm)); - } - writefile(timer, queue); - break; - - default: - panic("Internal error"); - break; - } - exit(EXIT_SUCCESS); -} - diff --git a/at.c.shell b/at.c.shell deleted file mode 100644 index 1bf8855..0000000 --- a/at.c.shell +++ /dev/null @@ -1,969 +0,0 @@ -/* - * at.c : Put file into atd queue - * Copyright (C) 1993, 1994, 1995, 1996, 1997 Thomas Koenig - * Copyright (C) 2002, 2005 Ryan Murray - * - * Atrun & Atq modifications - * Copyright (C) 1993 David Parsons - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif defined(HAVE_SYS_FCNTL_H) -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef TM_IN_SYS_TIME -#include -#else -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "at.h" -#include "panic.h" -#include "parsetime.h" -#include "perm.h" -#include "posixtm.h" -#include "privs.h" - -/* Macros */ - -#ifndef ATJOB_MX -#define ATJOB_MX 255 -#endif - -#define ALARMC 10 /* Number of seconds to wait for timeout */ - -#define SIZE 255 - -#define TIMEFORMAT_POSIX "%a %b %e %T %Y" -#define TIMESIZE 50 - -#define DEFAULT_QUEUE 'a' -#define BATCH_QUEUE 'b' - -enum { - ATQ, BATCH, ATRM, AT, CAT -}; /* what program we want to run */ - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -char *no_export[] = -{ - "TERM", "DISPLAY", "_", "SHELLOPTS", "BASH_VERSINFO", "EUID", "GROUPS", "PPID", "UID" -}; -static int send_mail = 0; - -/* External variables */ - -extern char **environ; -int fcreated; -char *namep; -char atfile[] = ATJOB_DIR "/12345678901234"; - -char *atinput = (char *) 0; /* where to get input from */ -char atqueue = 0; /* which queue to examine for jobs (atq) */ -char atverify = 0; /* verify time instead of queuing job */ - -/* Function declarations */ - -static void sigc(int signo); -static void alarmc(int signo); -static char *cwdname(void); -static void writefile(time_t runtimer, char queue); -static void list_jobs(void); - -/* Signal catching functions */ - -static RETSIGTYPE -sigc(int signo) -{ -/* If the user presses ^C, remove the spool file and exit - */ - if (fcreated) { - PRIV_START - /* - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ - unlink(atfile); - PRIV_END - } - exit(EXIT_FAILURE); -} - -static void -alarmc(int signo) -{ -/* Time out after some seconds - */ - panic("File locking timed out"); -} - -/* Local functions */ - -static char * -cwdname(void) -{ -/* Read in the current directory; the name will be overwritten on - * subsequent calls. - */ - static char *ptr = NULL; - static size_t size = SIZE; - - if (ptr == NULL) - ptr = (char *) mymalloc(size); - - while (1) { - if (ptr == NULL) - panic("Out of memory"); - - if (getcwd(ptr, size - 1) != NULL) - return ptr; - - if (errno != ERANGE) - perr("Cannot get current working directory"); - - free(ptr); - size += SIZE; - ptr = (char *) mymalloc(size); - } -} - -static long -nextjob() -{ - long jobno; - FILE *fid; - - jobno = 0; - fid = fopen(LFILE, "r+"); - if (fid != NULL) { - fscanf(fid, "%5lx", &jobno); - rewind(fid); - } else { - fid = fopen(LFILE, "w"); - if (fid == NULL) - return EOF; - } - jobno = (1 + jobno) % 0xfffff; /* 2^20 jobs enough? */ - fprintf(fid, "%05lx\n", jobno); - - fclose(fid); - return jobno; -} - -static void -writefile(time_t runtimer, char queue) -{ -/* This does most of the work if at or batch are invoked for writing a job. - */ - long jobno; - char *ap, *ppos, *mailname; - struct passwd *pass_entry; - struct stat statbuf; - int fd, lockdes, fd2; - FILE *fp, *fpin; - struct sigaction act; - char **atenv; - int ch; - mode_t cmask; - struct flock lock; - struct tm *runtime; - char timestr[TIMESIZE]; - pid_t pid; - int istty; - int kill_errno; - int rc; - int mailsize = 128; - -/* Install the signal handler for SIGINT; terminate after removing the - * spool file if necessary - */ - memset(&act, 0, sizeof act); - act.sa_handler = sigc; - sigemptyset(&(act.sa_mask)); - act.sa_flags = 0; - - sigaction(SIGINT, &act, NULL); - - ppos = atfile + strlen(ATJOB_DIR) + 1; - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - /* Loop over all possible file names for running something at this - * particular time, see if a file is there; the first empty slot at any - * particular time is used. Lock the file LFILE first to make sure - * we're alone when doing this. - */ - - PRIV_START - - if ((lockdes = open(LFILE, O_WRONLY)) < 0) - perr("Cannot open lockfile " LFILE); - - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - - act.sa_handler = alarmc; - sigemptyset(&(act.sa_mask)); - act.sa_flags = 0; - - /* Set an alarm so a timeout occurs after ALARMC seconds, in case - * something is seriously broken. - */ - sigaction(SIGALRM, &act, NULL); - alarm(ALARMC); - fcntl(lockdes, F_SETLKW, &lock); - alarm(0); - - if ((jobno = nextjob()) == EOF) - perr("Cannot generate job number"); - - (void)snprintf(ppos, sizeof(atfile) - (ppos - atfile), - "%c%5lx%8lx", queue, jobno, (unsigned long) (runtimer / 60)); - - for (ap = ppos; *ap != '\0'; ap++) - if (*ap == ' ') - *ap = '0'; - - if (stat(atfile, &statbuf) != 0) - if (errno != ENOENT) - perr("Cannot access " ATJOB_DIR); - - /* Create the file. The x bit is only going to be set after it has - * been completely written out, to make sure it is not executed in the - * meantime. To make sure they do not get deleted, turn off their r - * bit. Yes, this is a kluge. - */ - cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR); - if ((seteuid(effective_uid)) < 0) - perr("Error in seteuid: %s", errno); - if ((fd = open(atfile, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, S_IRUSR)) == -1) - perr("Cannot create atjob file %.500s", atfile); - - if ((fd2 = dup(fd)) < 0) - perr("Error in dup() of job file"); - - if (fchown(fd2, real_uid, real_gid) != 0) - perr("Cannot give real_uid and real_gid the file"); - - PRIV_END - - /* We've successfully created the file; let's set the flag so it - * gets removed in case of an interrupt or error. - */ - fcreated = 1; - - /* Now we can release the lock, so other people can access it - */ - lock.l_type = F_UNLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - fcntl(lockdes, F_SETLKW, &lock); - close(lockdes); - - if ((fp = fdopen(fd, "w")) == NULL) - panic("Cannot reopen atjob file"); - - /* Get the userid to mail to, first by trying getlogin(), which reads - * /var/run/utmp, then from LOGNAME, finally from getpwuid(). - */ - mailname = getlogin(); - if (mailname == NULL) - mailname = getenv("LOGNAME"); - if (mailname == NULL || mailname[0] == '\0' || getpwnam(mailname) == NULL) { - pass_entry = getpwuid(real_uid); - if (pass_entry != NULL) - mailname = pass_entry->pw_name; - } - - if ((mailname == NULL) || (mailname[0] == '\0') - || (strlen(mailname) > mailsize) ) { - panic("Cannot find username to mail output to"); - } - if (atinput != (char *) NULL) { - fpin = freopen(atinput, "r", stdin); - if (fpin == NULL) - perr("Cannot open input file %.500s", atinput); - } - - fprintf(fp, "#!/bin/sh\n# atrun uid=%d gid=%d\n# mail %s %d\n", - real_uid, real_gid, mailname, send_mail); - - /* Write out the umask at the time of invocation - */ - fprintf(fp, "umask %lo\n", (unsigned long) cmask); - - /* Write out the environment. Anything that may look like a - * special character to the shell is quoted, except for \n, which is - * done with a pair of ""'s. Dont't export the no_export list (such - * as TERM or DISPLAY) because we don't want these. - */ - for (atenv = environ; *atenv != NULL; atenv++) { - int export = 1; - char *eqp; - - /* Only accept alphanumerics and underscore in variable names. - * Also require the name to not start with a digit. - * Some shells don't like other variable names. - */ - { - char *p = *atenv; - if (isdigit(*p)) - export = 0; - for (; *p != '=' && *p != '\0'; ++p) { - if (!isalnum(*p) && *p != '_') { - export = 0; - break; - } - } - } - - eqp = strchr(*atenv, '='); - if (ap == NULL) - eqp = *atenv; - else { - unsigned int i; - for (i = 0; i < sizeof(no_export) / sizeof(no_export[0]); i++) { - export = export - && (strncmp(*atenv, no_export[i], - (size_t) (eqp - *atenv)) != 0); - } - eqp++; - } - - if (export) { - fwrite(*atenv, sizeof(char), eqp - *atenv, fp); - for (ap = eqp; *ap != '\0'; ap++) { - if (*ap == '\n') - fprintf(fp, "\"\n\""); - else { - if (!isalnum(*ap)) { - switch (*ap) { - case '%': - case '/': - case '{': - case '[': - case ']': - case '=': - case '}': - case '@': - case '+': - case '#': - case ',': - case '.': - case ':': - case '-': - case '_': - break; - default: - fputc('\\', fp); - break; - } - } - fputc(*ap, fp); - } - } - fputs("; export ", fp); - fwrite(*atenv, sizeof(char), eqp - *atenv - 1, fp); - fputc('\n', fp); - - } - } - /* Cd to the directory at the time and write out all the - * commands the user supplies from stdin. - */ - fprintf(fp, "cd "); - for (ap = cwdname(); *ap != '\0'; ap++) { - if (*ap == '\n') - fprintf(fp, "\"\n\""); - else { - if (*ap != '/' && !isalnum(*ap)) - fputc('\\', fp); - - fputc(*ap, fp); - } - } - /* Test cd's exit status: die if the original directory has been - * removed, become unreadable or whatever - */ - fprintf(fp, " || {\n\t echo 'Execution directory " - "inaccessible' >&2\n\t exit 1\n}\n"); - - istty = isatty(fileno(stdin)); - if (istty) { - fprintf(stderr, "at> "); - fflush(stderr); - } - while ((ch = getchar()) != EOF) { - fputc(ch, fp); - if (ch == '\n' && istty) { - fprintf(stderr, "at> "); - fflush(stderr); - } - } - if (istty) { - fprintf(stderr, "\n"); - } - fprintf(fp, "\n"); - if (ferror(fp)) - panic("Output error"); - fflush(fp); - if (ferror(fp)) - panic("Output error"); - - if (ferror(stdin)) - panic("Input error"); - - fclose(fp); - - /* Set the x bit so that we're ready to start executing - */ - - if (fchmod(fd2, S_IRUSR | S_IWUSR | S_IXUSR) < 0) - perr("Cannot give away file"); - - close(fd2); - - runtime = localtime(&runtimer); - - strftime(timestr, TIMESIZE, TIMEFORMAT_POSIX, runtime); - fprintf(stderr, "job %ld at %s\n", jobno, timestr); - - /* Signal atd, if present. Usual precautions taken... */ - fd = open(PIDFILE, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "Can't open " PIDFILE " to signal atd. No atd running?\n"); - return; - } - - if (fstat(fd, &statbuf) == -1) - return; - if ((statbuf.st_uid != 0) || !S_ISREG(statbuf.st_mode) || - (statbuf.st_mode & (S_IWGRP | S_IWOTH))) - return; - - fp = fdopen(fd, "r"); - if (fp == NULL) - return; - if (fscanf(fp, "%d", &pid) != 1) - return; - - kill_errno = 0; - - PRIV_START - if (kill(pid, SIGHUP) == -1) - kill_errno = errno; - PRIV_END - - switch (kill_errno) { - case 0: - break; - - case EINVAL: - panic("kill returned EINVAL"); - break; - - case EPERM: - fprintf(stderr,"Can't signal atd (permission denied)\n"); - break; - - case ESRCH: - fprintf(stderr, "Warning: at daemon not running\n"); - break; - - default: - panic("kill returned impossible error number"); - break; - } - return; -} - -static void -list_jobs(void) -{ - /* List all a user's jobs in the queue, by looping through ATJOB_DIR, - * or everybody's if we are root - */ - DIR *spool; - struct dirent *dirent; - struct stat buf; - struct tm *runtime; - unsigned long ctm; - char queue; - long jobno; - time_t runtimer; - char timestr[TIMESIZE]; - struct passwd *pwd; - - PRIV_START - - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if ((spool = opendir(".")) == NULL) - perr("Cannot open " ATJOB_DIR); - - /* Loop over every file in the directory - */ - while ((dirent = readdir(spool)) != NULL) { - if (stat(dirent->d_name, &buf) != 0) - perr("Cannot stat in " ATJOB_DIR); - - /* See it's a regular file and is the user's */ - if (!S_ISREG(buf.st_mode) - || ((buf.st_uid != real_uid) && !(real_uid == 0)) - || atverify) - continue; - - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - if (atqueue && (queue != atqueue)) - continue; - - runtimer = 60 * (time_t) ctm; - runtime = localtime(&runtimer); - - strftime(timestr, TIMESIZE, TIMEFORMAT_POSIX, runtime); - - if ((pwd = getpwuid(buf.st_uid))) - printf("%ld\t%s %c %s\n", jobno, timestr, queue, pwd->pw_name); - else - printf("%ld\t%s %c\n", jobno, timestr, queue); - } - PRIV_END -} - -static int -process_jobs(int argc, char **argv, int what) -{ - /* Delete every argument (job - ID) given - */ - int i; - struct stat buf; - DIR *spool; - struct dirent *dirent; - unsigned long ctm; - char queue; - long jobno; - int rc = EXIT_SUCCESS; - int done; - - for (i = optind; i < argc; i++) { - done = 0; - PRIV_START - - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if ((spool = opendir(".")) == NULL) - perr("Cannot open " ATJOB_DIR); - - PRIV_END - - /* Loop over every file in the directory - */ - while ((dirent = readdir(spool)) != NULL) { - - PRIV_START - if (stat(dirent->d_name, &buf) != 0) - perr("Cannot stat in " ATJOB_DIR); - PRIV_END - - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - if (atoi(argv[i]) == jobno) { - if ((buf.st_uid != real_uid) && !(real_uid == 0)) { - fprintf(stderr, "%s: Not owner\n", argv[i]); - exit(EXIT_FAILURE); - } - switch (what) { - case ATRM: - - /* - We need the unprivileged uid here since the file is owned by the real - (not effective) uid. - */ - PRIV_START - - if (queue == '=') { - fprintf(stderr, "Warning: deleting running job\n"); - } - if (unlink(dirent->d_name) != 0) { - perr("Cannot unlink %.500s", dirent->d_name); - rc = EXIT_FAILURE; - } - PRIV_END - - done = 1; - - break; - - case CAT: - { - FILE *fp; - int ch; - - PRIV_START - fp = fopen(dirent->d_name, "r"); - - if (fp) { - while ((ch = getc(fp)) != EOF) { - putchar(ch); - } - done = 1; - } - else { - perr("Cannot open %.500s", dirent->d_name); - rc = EXIT_FAILURE; - } - PRIV_END - } - break; - - default: - fprintf(stderr, - "Internal error, process_jobs = %d\n", what); - exit(EXIT_FAILURE); - break; - } - } - } - closedir(spool); - if (done != 1) { - fprintf(stderr, "Cannot find jobid %s\n", argv[i] ); - rc = EXIT_FAILURE; - } - } - return rc; -} /* delete_jobs */ - -/* Global functions */ - -void * -mymalloc(size_t n) -{ - void *p; - if ((p = malloc(n)) == (void *) 0) { - fprintf(stderr, "Virtual memory exhausted\n"); - exit(EXIT_FAILURE); - } - return p; -} - -int -main(int argc, char **argv) -{ - int c; - char queue = DEFAULT_QUEUE; - char queue_set = 0; - char *pgm; - - int program = AT; /* our default program */ - char *options = "q:f:MmbvlrdhVct:"; /* default options for at */ - int disp_version = 0; - time_t timer = 0; - struct passwd *pwe; - struct group *ge; - - RELINQUISH_PRIVS - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - /* Eat any leading paths - */ - if ((pgm = strrchr(argv[0], '/')) == NULL) - pgm = argv[0]; - else - pgm++; - - namep = pgm; - - /* find out what this program is supposed to do - */ - if (strcmp(pgm, "atq") == 0) { - program = ATQ; - options = "hq:V"; - } else if (strcmp(pgm, "atrm") == 0) { - program = ATRM; - options = "hV"; - } - /* process whatever options we can process - */ - opterr = 1; - while ((c = getopt(argc, argv, options)) != EOF) - switch (c) { - case 'h': - usage(); - exit (0); - - case 'v': /* verify time settings */ - atverify = 1; - break; - - case 'm': /* send mail when job is complete */ - send_mail = 1; - break; - - case 'M': /* don't send mail, even when job failed */ - send_mail = -1; - break; - - case 'f': - atinput = optarg; - break; - - case 'q': /* specify queue */ - if (strlen(optarg) > 1) - usage(); - - atqueue = queue = *optarg; - if (!(islower(queue) || isupper(queue)) & (queue != '=')) - usage(); - - queue_set = 1; - break; - - case 'r': - case 'd': - if (program != AT) - usage(); - - program = ATRM; - options = "V"; - break; - - case 'l': - if (program != AT) - usage(); - - program = ATQ; - options = "q:V"; - break; - - case 'b': - if (program != AT) - usage(); - - program = BATCH; - options = ""; - break; - - case 'V': - disp_version = 1; - break; - - case 'c': - program = CAT; - options = ""; - break; - - case 't': - if (!posixtime(&timer, optarg, PDS_LEADING_YEAR | PDS_CENTURY | PDS_SECONDS)) { - fprintf(stderr, "invalid date format: %s\n", optarg); - exit(EXIT_FAILURE); - } - /* drop seconds */ - timer -= timer % 60; - break; - - default: - usage(); - break; - } - /* end of options eating - */ - - if (disp_version) { - fprintf(stderr, "at version " VERSION "\n"); - if (argc == 2) - exit(EXIT_SUCCESS); - } - - /* select our program - */ - if (!check_permission()) { - fprintf(stderr, "You do not have permission to use %.100s.\n", namep); - exit(EXIT_FAILURE); - } - switch (program) { - int i; - case ATQ: - - REDUCE_PRIV(daemon_uid, daemon_gid) - - list_jobs(); - break; - - case ATRM: - - REDUCE_PRIV(daemon_uid, daemon_gid) - if (argc > optind) { - for (i = optind; i < argc ; i++ ) - if (strspn(argv[i],"0123456789") != strlen(argv[i])) { - fprintf(stderr,"at: unknown jobid: %s\n", argv[i]); - exit(EXIT_FAILURE); - } - return process_jobs(argc, argv, ATRM); - } - else - usage(); - break; - - case CAT: - - if (argc > optind) { - for (i = optind; i < argc ; i++ ) - if (strspn(argv[i],"0123456789") != strlen(argv[i])) { - fprintf(stderr,"at: unknown jobid: %s", argv[i]); - exit(EXIT_FAILURE); - } - return process_jobs(argc, argv, CAT); - } - else - usage(); - break; - - case AT: - if (argc > optind) { - if (timer != 0) { - fprintf(stderr, "Cannot give time twice.\n"); - exit(EXIT_FAILURE); - } - timer = parsetime(time(0), argc - optind, argv + optind); - } - - if (timer == 0) { - fprintf(stderr, "Garbled time\n"); - exit(EXIT_FAILURE); - } - if (atverify) { - struct tm *tm = localtime(&timer); - fprintf(stderr, "%s\n", asctime(tm)); - } - - /* POSIX.2 allows the shell specified by the user's SHELL environment - variable, the login shell from the user's password database entry, - or /bin/sh to be the command interpreter that processes the at-job. - It also alows a warning diagnostic to be printed. Because of the - possible variance, we always output the diagnostic. */ - - fprintf(stderr, "warning: commands will be executed using /bin/sh\n"); - - writefile(timer, queue); - break; - - case BATCH: - if (queue_set) - queue = toupper(queue); - else - queue = BATCH_QUEUE; - - if (argc > optind) { - if (timer != 0) { - fprintf(stderr, "Cannot give time twice.\n"); - exit(EXIT_FAILURE); - } - timer = parsetime(time(0), argc, argv); - } else if (timer == 0) - timer = time(NULL); - - if (atverify) { - struct tm *tm = localtime(&timer); - fprintf(stderr, "%s\n", asctime(tm)); - } - writefile(timer, queue); - break; - - default: - panic("Internal error"); - break; - } - exit(EXIT_SUCCESS); -} - diff --git a/atd.8.in b/atd.8.in index 5865b16..0f6c0d8 100644 --- a/atd.8.in +++ b/atd.8.in @@ -9,7 +9,6 @@ atd \- run jobs queued for later execution .IR batch_interval ] .RB [ -d ] .RB [ -f ] -.RB [ -n ] .RB [ -s ] .SH DESCRIPTION .B atd @@ -41,10 +40,6 @@ Run .BR atd in the foreground. .TP 8 -.B -n -Append the hostname of the system to the subject of the e-mails sent by -.BR atd . -.TP 8 .B -s Process the at/batch queue only once. This is primarily of use for compatibility with old versions of diff --git a/atd.8.in.document-n b/atd.8.in.document-n deleted file mode 100644 index 0f6c0d8..0000000 --- a/atd.8.in.document-n +++ /dev/null @@ -1,81 +0,0 @@ -.TH ATD 8 2009-11-14 -.SH NAME -atd \- run jobs queued for later execution -.SH SYNOPSIS -.B atd -.RB [ -l -.IR load_avg ] -.RB [ -b -.IR batch_interval ] -.RB [ -d ] -.RB [ -f ] -.RB [ -s ] -.SH DESCRIPTION -.B atd -runs jobs queued by -.BR at(1) . -.PP -.SH OPTIONS -.TP 8 -.B -l -Specifies a limiting load factor, over which batch jobs should -not be run, instead of the compile-time choice of @LOADAVG_MX@. -For an SMP system with -.I n -CPUs, you will probably want to set this higher than -.IR n-1. -.TP 8 -.B -b -Specify the minimum interval in seconds between the start of two -batch jobs (60 default). -.TP 8 -.B -d -Debug; print error messages to standard error instead of using -.BR syslog(3) . -This option also implies -.BR -f . -.TP -.B -f -Run -.BR atd -in the foreground. -.TP 8 -.B -s -Process the at/batch queue only once. -This is primarily of use for compatibility with old versions of -.BR at ; -.B "atd -s" -is equivalent to the old -.B atrun -command. -.SH WARNING -.B atd -won't work if its spool directory is mounted via NFS even if -.I no_root_squash -is set. -.SH FILES -.I @ATJBD@ -The directory for storing jobs; this should be mode 700, owner -@DAEMON_USERNAME@. -.PP -.I @ATSPD@ -The directory for storing output; this should be mode 700, owner -@DAEMON_USERNAME@. -.PP -.IR /etc/at.allow , -.IR /etc/at.deny -determine who can use the -.B at -system. -.SH "SEE ALSO" -.BR at (1), -.BR at.deny (5), -.BR at.allow (5), -.BR cron (8), -.BR crontab (1), -.BR syslog (3). -.SH BUGS -The functionality of -.B atd -should be merged into -.BR cron (8) . diff --git a/atd.c b/atd.c index 68f427a..7ed4bf6 100644 --- a/atd.c +++ b/atd.c @@ -74,9 +74,6 @@ #include #endif -#include -#include - /* Local headers */ #include "privs.h" @@ -94,17 +91,9 @@ int selinux_enabled = 0; /* Macros */ -#ifndef LOG_ATD -#define LOG_ATD LOG_DAEMON -#endif - #define BATCH_INTERVAL_DEFAULT 60 #define CHECK_INTERVAL 3600 -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - /* Global variables */ uid_t real_uid, effective_uid; @@ -122,11 +111,10 @@ static time_t last_chg; static int nothing_to_do; unsigned int batch_interval; static int run_as_daemon = 0; -static int mail_with_hostname = 0; static volatile sig_atomic_t term_signal = 0; -#ifdef WITH_PAM +#ifdef HAVE_PAM #include static pam_handle_t *pamh = NULL; @@ -135,7 +123,15 @@ static const struct pam_conv conv = { NULL }; -#endif /* WITH_PAM */ +#define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \ + fprintf(stderr,"\n%s\n",pam_strerror(pamh, retcode)); \ + syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \ + pam_end(pamh, retcode); exit(1); \ + } +#define PAM_END { retcode = pam_close_session(pamh,0); \ + pam_end(pamh,retcode); } + +#endif /* HAVE_PAM */ /* Signal handlers */ RETSIGTYPE @@ -204,18 +200,6 @@ myfork() #define fork myfork #endif -#undef ATD_MAIL_PROGRAM -#undef ATD_MAIL_NAME -#if defined(SENDMAIL) -#define ATD_MAIL_PROGRAM SENDMAIL -#define ATD_MAIL_NAME "sendmail" -#elif defined(MAILC) -#define ATD_MAIL_PROGRAM MAILC -#define ATD_MAIL_NAME "mail" -#elif defined(MAILX) -#define ATD_MAIL_PROGRAM MAILX -#define ATD_MAIL_NAME "mailx" -#endif #ifdef WITH_SELINUX static int @@ -291,7 +275,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) * mail to the user. */ pid_t pid; - int fd_out, fd_in, fd_std; + int fd_out, fd_in; char jobbuf[9]; char *mailname = NULL; int mailsize = 128; @@ -308,8 +292,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) char fmt[64]; unsigned long jobno; int rc; - char hostbuf[MAXHOSTNAMELEN]; -#ifdef WITH_PAM +#ifdef HAVE_PAM int retcode; #endif @@ -352,20 +335,14 @@ run_file(const char *filename, uid_t uid, gid_t gid) */ pid = fork(); - if (pid == -1) { - lerr("Cannot fork for job execution"); - free(mailname); - free(newname); - return; - } + if (pid == -1) + perr("Cannot fork"); + else if (pid != 0) { free(mailname); free(newname); return; } - - (void) setsid(); /* own session for process */ - /* Let's see who we mail to. Hopefully, we can read it from * the command file; if not, send it to the owner, or, failing that, * to root. @@ -376,10 +353,6 @@ run_file(const char *filename, uid_t uid, gid_t gid) pabort("Userid %lu not found - aborting job %8lu (%.500s)", (unsigned long) uid, jobno, filename); } - - syslog(LOG_INFO, "Starting job %lu (%.500s) for user '%s' (%lu)", - jobno, filename, pentry->pw_name, (unsigned long) uid); - PRIV_START stream = fopen(filename, "r"); @@ -417,10 +390,6 @@ run_file(const char *filename, uid_t uid, gid_t gid) fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); - if (flock(fd_in, LOCK_EX | LOCK_NB) != 0) - perr("Somebody already locked the job %8lu (%.500s) - " - "aborting", jobno, filename); - /* * If the spool directory is mounted via NFS `atd' isn't able to * read from the job file and will bump out here. The file is @@ -431,22 +400,10 @@ run_file(const char *filename, uid_t uid, gid_t gid) sprintf(fmt, "#!/bin/sh\n# atrun uid=%%d gid=%%d\n# mail %%%ds %%d", mailsize ); - /* Unlink the file unless there was an error reading it (perhaps - * temporary). - * If the file has a bogus format there is no reason in trying - * to run it again and again. - */ if (fscanf(stream, fmt, - &nuid, &ngid, mailname, &send_mail) != 4) { - if (ferror(stream)) - perr("Error reading the job file"); - - unlink(filename); - pabort("File %.500s is in wrong format - aborting", - filename); - } - - unlink(filename); + &nuid, &ngid, mailname, &send_mail) != 4) + pabort("File %.500s is in wrong format - aborting", + filename); if (mailname[0] == '-') pabort("illegal mail name %.300s in job %8lu (%.300s)", mailname, @@ -456,6 +413,12 @@ run_file(const char *filename, uid_t uid, gid_t gid) pabort("Job %8lu (%.500s) - userid %d does not match file uid %d", jobno, filename, nuid, uid); + /* We are now committed to executing this script. Unlink the + * original. + */ + + unlink(filename); + fclose(stream); if (chdir(ATSPOOL_DIR) < 0) perr("Cannot chdir to " ATSPOOL_DIR); @@ -480,22 +443,23 @@ run_file(const char *filename, uid_t uid, gid_t gid) write_string(fd_out, "Subject: Output from your job "); write_string(fd_out, jobbuf); - if (mail_with_hostname > 0) { - gethostname(hostbuf, MAXHOSTNAMELEN-1); - write_string(fd_out, " "); - write_string(fd_out, hostbuf); - } write_string(fd_out, "\nTo: "); write_string(fd_out, mailname); write_string(fd_out, "\n\n"); fstat(fd_out, &buf); size = buf.st_size; -#ifdef WITH_PAM - AT_START_PAM; - AT_OPEN_PAM_SESSION; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); +#ifdef HAVE_PAM + PRIV_START + retcode = pam_start("atd", pentry->pw_name, &conv, &pamh); + PAM_FAIL_CHECK; + retcode = pam_acct_mgmt(pamh, PAM_SILENT); + PAM_FAIL_CHECK; + retcode = pam_open_session(pamh, PAM_SILENT); + PAM_FAIL_CHECK; + retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); + PAM_FAIL_CHECK; + PRIV_END #endif close(STDIN_FILENO); @@ -509,14 +473,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) else if (pid == 0) { char *nul = NULL; char **nenvp = &nul; - char **pam_envp=0L; - PRIV_START -#ifdef WITH_PAM - pam_envp = pam_getenvlist(pamh); - if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) ) - nenvp = pam_envp; -#endif /* Set up things for the child; we want standard input from the * input file, and standard output and error sent to our output file. */ @@ -535,6 +492,8 @@ run_file(const char *filename, uid_t uid, gid_t gid) close(fd_in); close(fd_out); + PRIV_START + nice((tolower((int) queue) - 'a' + 1) * 2); #ifdef WITH_SELINUX @@ -553,23 +512,31 @@ run_file(const char *filename, uid_t uid, gid_t gid) if (setuid(uid) < 0) perr("Cannot set user id"); - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - chdir("/"); - execle("/bin/sh", "sh", (char *) NULL, nenvp); - perr("Exec failed for /bin/sh"); - /* perr exits, the PRIV_END is just for nice form */ + if (execle("/bin/sh", "sh", (char *) NULL, nenvp) != 0) + perr("Exec failed for /bin/sh"); + PRIV_END } /* We're the parent. Let's wait. - We inherited the master's SIGCHLD handler, which does a + */ + close(fd_in); + + /* We inherited the master's SIGCHLD handler, which does a non-blocking waitpid. So this blocking one will eventually return with an ECHILD error. */ waitpid(pid, (int *) NULL, 0); +#ifdef HAVE_PAM + PRIV_START + pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); + retcode = pam_close_session(pamh, PAM_SILENT); + pam_end(pamh, retcode); + PRIV_END +#endif + /* Send mail. Unlink the output file after opening it, so it * doesn't hang around after the run. */ @@ -581,14 +548,14 @@ run_file(const char *filename, uid_t uid, gid_t gid) /* some sendmail implementations are confused if stdout, stderr are * not available, so let them point to /dev/null */ - if ((fd_std = open("/dev/null", O_WRONLY)) < 0) + if ((fd_in = open("/dev/null", O_WRONLY)) < 0) perr("Could not open /dev/null."); - if (dup2(fd_std, STDOUT_FILENO) < 0) + if (dup2(fd_in, STDOUT_FILENO) < 0) perr("Could not use /dev/null as standard output."); - if (dup2(fd_std, STDERR_FILENO) < 0) + if (dup2(fd_in, STDERR_FILENO) < 0) perr("Could not use /dev/null as standard error."); - if (fd_std != STDOUT_FILENO && fd_std != STDERR_FILENO) - close(fd_std); + if (fd_in != STDOUT_FILENO && fd_in != STDERR_FILENO) + close(fd_in); if (unlink(filename) == -1) syslog(LOG_WARNING, "Warning: removing output file for job %li failed: %s", @@ -596,22 +563,12 @@ run_file(const char *filename, uid_t uid, gid_t gid) /* The job is now finished. We can delete its input file. */ - if (chdir(ATJOB_DIR) != 0) - perr("Somebody removed %s directory from under us.", ATJOB_DIR); - - /* This also removes the flock */ - (void)close(fd_in); - + chdir(ATJOB_DIR); unlink(newname); free(newname); -#ifdef ATD_MAIL_PROGRAM if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { - int mail_pid = -1; - - mail_pid = fork(); - if ( mail_pid == 0 ) { PRIV_START if (initgroups(pentry->pw_name, pentry->pw_gid)) @@ -623,9 +580,6 @@ run_file(const char *filename, uid_t uid, gid_t gid) if (setuid(uid) < 0) perr("Cannot set user id"); - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - chdir ("/"); #if defined(SENDMAIL) @@ -636,20 +590,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) perr("Exec failed for mail command"); PRIV_END - } - else if ( mail_pid == -1 ) { - syslog(LOG_ERR, "fork of mailer failed: %m"); - } - /* Parent */ - waitpid(mail_pid, (int *) NULL, 0); } - -#ifdef WITH_PAM - AT_CLOSE_PAM; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif -#endif exit(EXIT_SUCCESS); } @@ -691,19 +632,15 @@ run_loop() * up. */ - if (stat(".", &buf) == -1) { - lerr("Cannot stat " ATJOB_DIR); - return next_job; - } + if (stat(".", &buf) == -1) + perr("Cannot stat " ATJOB_DIR); if (nothing_to_do && buf.st_mtime <= last_chg) return next_job; last_chg = buf.st_mtime; - if ((spool = opendir(".")) == NULL) { - lerr("Cannot read " ATJOB_DIR); - return next_job; - } + if ((spool = opendir(".")) == NULL) + perr("Cannot read " ATJOB_DIR); run_batch = 0; nothing_to_do = 1; @@ -736,18 +673,16 @@ run_loop() /* Skip lock files */ if (queue == '=') { - if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) { - int fd; - - fd = open(dirent->d_name, O_RDONLY); - if (fd != -1) { - if (flock(fd, LOCK_EX | LOCK_NB) == 0) { - unlink(dirent->d_name); - syslog(LOG_NOTICE, "removing stale lock file %s\n", dirent->d_name); - } - (void)close(fd); - } - } + /* FIXME: calhariz */ + /* I think the following code is broken, but commenting + may haven unknow side effects. Make a release and see + in the wild how it works. For more information see: + https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818508/* + + /* if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) { */ + /* /\* Remove stale lockfile FIXME: lock the lockfile, if you fail, it's still in use. *\/ */ + /* unlink(dirent->d_name); */ + /* } */ continue; } /* Skip any other file types which may have been invented in @@ -759,18 +694,12 @@ run_loop() /* Is the file already locked? */ if (buf.st_nlink > 1) { - if (run_time < buf.st_mtime) - run_time = buf.st_mtime; if (run_time + CHECK_INTERVAL <= now) { + /* Something went wrong the last time this was executed. * Let's remove the lockfile and reschedule. - * We also change the timestamp to avoid rerunning the job more - * than once every CHECK_INTERVAL. */ strncpy(lock_name, dirent->d_name, sizeof(lock_name)); - if (utime(lock_name, 0) < 0) - syslog(LOG_ERR, "utime couldn't be set for lock file %s\n", lock_name); - lock_name[sizeof(lock_name)-1] = '\0'; lock_name[0] = '='; unlink(lock_name); next_job = now; @@ -805,7 +734,6 @@ run_loop() run_batch++; if (strcmp(batch_name, dirent->d_name) > 0) { strncpy(batch_name, dirent->d_name, sizeof(batch_name)); - batch_name[sizeof(batch_name)-1] = '\0'; batch_uid = buf.st_uid; batch_gid = buf.st_gid; batch_queue = queue; @@ -843,54 +771,6 @@ run_loop() return next_job; } -#ifdef HAVE_TIMER_CREATE -timer_t timer; -struct itimerspec timeout; - -void timer_setup() -{ - struct sigevent sev; - - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIGHUP; - sev.sigev_value.sival_ptr = &timer; - - memset(&timeout, 0, sizeof(timeout)); - - if (timer_create(CLOCK_REALTIME, &sev, &timer) < 0) - pabort("unable to create timer"); -} - -time_t atd_gettime() -{ - struct timespec curtime; - - clock_gettime(CLOCK_REALTIME, &curtime); - - return curtime.tv_sec; -} - -void atd_setalarm(time_t next) -{ - timeout.it_value.tv_sec = next; - timer_settime(timer, TIMER_ABSTIME, &timeout, NULL); - pause(); -} -#else -void timer_setup() -{ -} - -time_t atd_gettime() -{ - return time(NULL); -} - -void atd_setalarm(time_t next) -{ - sleep(next - atd_gettime()); -} -#endif /* Global functions */ int @@ -947,7 +827,7 @@ main(int argc, char *argv[]) run_as_daemon = 1; batch_interval = BATCH_INTERVAL_DEFAULT; - while ((c = getopt(argc, argv, "sdnl:b:f")) != EOF) { + while ((c = getopt(argc, argv, "sdl:b:f")) != EOF) { switch (c) { case 'l': if (sscanf(optarg, "%lf", &load_avg) != 1) @@ -969,10 +849,6 @@ main(int argc, char *argv[]) daemon_foreground++; break; - case 'n': - mail_with_hostname=1; - break; - case 's': run_as_daemon = 0; break; @@ -1000,7 +876,7 @@ main(int argc, char *argv[]) sigaction(SIGCHLD, &act, NULL); if (!run_as_daemon) { - now = atd_gettime(); + now = time(NULL); run_loop(); exit(EXIT_SUCCESS); } @@ -1023,14 +899,13 @@ main(int argc, char *argv[]) act.sa_handler = set_term; sigaction(SIGINT, &act, NULL); - timer_setup(); daemon_setup(); do { - now = atd_gettime(); + now = time(NULL); next_invocation = run_loop(); if (next_invocation > now) { - atd_setalarm(next_invocation); + sleep(next_invocation - now); } } while (!term_signal); daemon_cleanup(); diff --git a/atd.c.aborted b/atd.c.aborted deleted file mode 100644 index 07bd5dc..0000000 --- a/atd.c.aborted +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * atd.c - run jobs queued by at; run with root privileges. - * Copyright (C) 1993, 1994, 1996 Thomas Koenig - * Copyright (c) 2002, 2005 Ryan Murray - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif HAVE_SYS_FCNTL_H - -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_GETOPT_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "privs.h" -#include "daemon.h" - -#ifndef HAVE_GETLOADAVG -#include "getloadavg.h" -#endif - -#ifdef WITH_SELINUX -#include -#include -int selinux_enabled = 0; -#endif - -/* Macros */ - -#ifndef LOG_ATD -#define LOG_ATD LOG_DAEMON -#endif - -#define BATCH_INTERVAL_DEFAULT 60 -#define CHECK_INTERVAL 3600 - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -static char *namep; -static double load_avg = LOADAVG_MX; -static time_t now; -static time_t last_chg; -static int nothing_to_do; -unsigned int batch_interval; -static int run_as_daemon = 0; -static int mail_with_hostname = 0; - -static volatile sig_atomic_t term_signal = 0; - -#ifdef WITH_PAM -#include - -static pam_handle_t *pamh = NULL; - -static const struct pam_conv conv = { - NULL -}; - -#endif /* WITH_PAM */ - -/* Signal handlers */ -RETSIGTYPE -set_term(int dummy) -{ - term_signal = 1; - return; -} - -RETSIGTYPE -sdummy(int dummy) -{ - /* Empty signal handler */ - nothing_to_do = 0; - return; -} - -/* SIGCHLD handler - discards completion status of children */ -RETSIGTYPE -release_zombie(int dummy) -{ - int status; - pid_t pid; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { -#ifdef DEBUG_ZOMBIE - if (WIFEXITED(status)) - syslog(LOG_INFO, "pid %ld exited with status %d.", pid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - syslog(LOG_NOTICE, "pid %ld killed with signal %d.", pid, WTERMSIG(status)); - else if (WIFSTOPPED(status)) - syslog(LOG_NOTICE, "pid %ld stopped with signal %d.", pid, WSTOPSIG(status)); - else - syslog(LOG_WARNING, "pid %ld unknown reason for SIGCHLD", pid); -#endif - } - return; -} - - -/* Local functions */ - -static int -write_string(int fd, const char *a) -{ - return write(fd, a, strlen(a)); -} - -static int -isbatch(char queue) -{ - return isupper(queue) || (queue == 'b'); -} - -#undef DEBUG_FORK -#ifdef DEBUG_FORK -static pid_t -myfork() -{ - pid_t res; - res = fork(); - if (res == 0) - kill(getpid(), SIGSTOP); - return res; -} - -#define fork myfork -#endif -#undef ATD_MAIL_PROGRAM -#undef ATD_MAIL_NAME -#if defined(SENDMAIL) -#define ATD_MAIL_PROGRAM SENDMAIL -#define ATD_MAIL_NAME "sendmail" -#elif defined(MAILC) -#define ATD_MAIL_PROGRAM MAILC -#define ATD_MAIL_NAME "mail" -#elif defined(MAILX) -#define ATD_MAIL_PROGRAM MAILX -#define ATD_MAIL_NAME "mailx" -#endif - -#ifdef WITH_SELINUX -static int -set_selinux_context(const char *name, const char *filename) { - security_context_t user_context = NULL; - security_context_t file_context = NULL; - int retval = 0; - char *seuser = NULL; - char *level = NULL; - - if (getseuserbyname(name, &seuser, &level) == 0) { - retval = get_default_context_with_level(seuser, level, NULL, &user_context); - free(seuser); - free(level); - if (retval < 0) { - lerr("get_default_context_with_level: couldn't get security context for user %s", name); - retval = -1; - goto err; - } - } - - /* - * Since crontab files are not directly executed, - * crond must ensure that the crontab file has - * a context that is appropriate for the context of - * the user cron job. It performs an entrypoint - * permission check for this purpose. - */ - if (fgetfilecon(STDIN_FILENO, &file_context) < 0) { - lerr("fgetfilecon FAILED %s", filename); - retval = -1; - goto err; - } - - retval = selinux_check_access(user_context, file_context, "file", "entrypoint", NULL); - freecon(file_context); - if (retval < 0) { - lerr("Not allowed to set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } - if (setexeccon(user_context) < 0) { - lerr("Could not set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } -err: - if (retval < 0 && security_getenforce() != 1) - retval = 0; - if (user_context) - freecon(user_context); - return retval; -} - -static int -selinux_log_callback (int type, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsyslog (LOG_ERR, fmt, ap); - va_end(ap); - return 0; -} - -#endif - -static void -run_file(const char *filename, uid_t uid, gid_t gid) -{ -/* Run a file by by spawning off a process which redirects I/O, - * spawns a subshell, then waits for it to complete and sends - * mail to the user. - */ - pid_t pid; - int fd_out, fd_in; - char jobbuf[9]; - char *mailname = NULL; - int mailsize = 128; - char *newname; - FILE *stream; - int send_mail = 0; - struct stat buf, lbuf; - off_t size; - struct passwd *pentry; - int fflags; - int nuid; - int ngid; - char queue; - char fmt[64]; - unsigned long jobno; - int rc; - char hostbuf[MAXHOSTNAMELEN]; -#ifdef WITH_PAM - int retcode; -#endif - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - sscanf(filename, "%c%5lx", &queue, &jobno); - if ((mailname = malloc(mailsize+1)) == NULL) - pabort("Job %8lu : out of virtual memory", jobno); - - sprintf(jobbuf, "%8lu", jobno); - - if ((newname = strdup(filename)) == 0) - pabort("Job %8lu : out of virtual memory", jobno); - newname[0] = '='; - - /* We try to make a hard link to lock the file. If we fail, then - * somebody else has already locked or deleted it (a second atd?); log the - * fact and return. - */ - PRIV_START - rc = link(filename, newname); - PRIV_END - if (rc == -1) { - syslog(LOG_WARNING, "could not lock job %lu: %m", jobno); - free(mailname); - free(newname); - return; - } - /* If something goes wrong between here and the unlink() call, - * the job gets restarted as soon as the "=" entry is cleared - * by the main atd loop. - */ - - pid = fork(); - if (pid == -1) - perr("Cannot fork"); - - else if (pid != 0) { - free(mailname); - free(newname); - return; - } - - (void) setsid(); /* own session for process */ - - /* Let's see who we mail to. Hopefully, we can read it from - * the command file; if not, send it to the owner, or, failing that, - * to root. - */ - - pentry = getpwuid(uid); - if (pentry == NULL) { - pabort("Userid %lu not found - aborting job %8lu (%.500s)", - (unsigned long) uid, jobno, filename); - } - PRIV_START - - stream = fopen(filename, "r"); - - PRIV_END - - if (stream == NULL) - perr("Cannot open input file"); - - if ((fd_in = dup(fileno(stream))) < 0) - perr("Error duplicating input file descriptor"); - - if (fstat(fd_in, &buf) == -1) - perr("Error in fstat of input file descriptor"); - - if (lstat(filename, &lbuf) == -1) - perr("Error in fstat of input file"); - - if (S_ISLNK(lbuf.st_mode)) - perr("Symbolic link encountered in job %8lu (%.500s) - aborting", - jobno, filename); - - if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || - (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || - (lbuf.st_size != buf.st_size)) - perr("Somebody changed files from under us for job %8lu (%.500s) - " - "aborting", jobno, filename); - - if (buf.st_nlink > 2) { - perr("Somebody is trying to run a linked script for job %8lu (%.500s)", - jobno, filename); - } - if ((fflags = fcntl(fd_in, F_GETFD)) < 0) - perr("Error in fcntl"); - - fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); - - /* - * If the spool directory is mounted via NFS `atd' isn't able to - * read from the job file and will bump out here. The file is - * opened as "root" but it is read as "daemon" which fails over - * NFS and works with local file systems. It's not clear where - * the bug is located. -Joey - */ - sprintf(fmt, "#!/bin/sh\n# atrun uid=%%d gid=%%d\n# mail %%%ds %%d", - mailsize ); - - if (fscanf(stream, fmt, - &nuid, &ngid, mailname, &send_mail) != 4) - pabort("File %.500s is in wrong format - aborting", - filename); - - if (mailname[0] == '-') - pabort("illegal mail name %.300s in job %8lu (%.300s)", mailname, - jobno, filename); - - if (nuid != uid) - pabort("Job %8lu (%.500s) - userid %d does not match file uid %d", - jobno, filename, nuid, uid); - - /* We are now committed to executing this script. Unlink the - * original. - */ - - unlink(filename); - - fclose(stream); - if (chdir(ATSPOOL_DIR) < 0) - perr("Cannot chdir to " ATSPOOL_DIR); - - /* Create a file to hold the output of the job we are about to run. - * Write the mail header. Complain in case - */ - - if (unlink(filename) != -1) { - syslog(LOG_WARNING,"Warning: for duplicate output file for %.100s (dead job?)", - filename); - } - - if ((fd_out = open(filename, - O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) - perr("Cannot create output file"); - PRIV_START - if (fchown(fd_out, uid, ngid) == -1) - syslog(LOG_WARNING, "Warning: could not change owner of output file for job %li to %i:%i: %s", - jobno, uid, ngid, strerror(errno)); - PRIV_END - - write_string(fd_out, "Subject: Output from your job "); - write_string(fd_out, jobbuf); - if (mail_with_hostname > 0) { - gethostname(hostbuf, MAXHOSTNAMELEN-1); - write_string(fd_out, " "); - write_string(fd_out, hostbuf); - } - write_string(fd_out, "\nTo: "); - write_string(fd_out, mailname); - write_string(fd_out, "\n\n"); - fstat(fd_out, &buf); - size = buf.st_size; - -#ifdef WITH_PAM - AT_START_PAM; - AT_OPEN_PAM_SESSION; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - pid = fork(); - if (pid < 0) - perr("Error in fork"); - - else if (pid == 0) { - char *nul = NULL; - char **nenvp = &nul; - char **pam_envp=0L; - - PRIV_START -#ifdef WITH_PAM - pam_envp = pam_getenvlist(pamh); - if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) ) - nenvp = pam_envp; -#endif - /* Set up things for the child; we want standard input from the - * input file, and standard output and error sent to our output file. - */ - if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0) - perr("Error in lseek"); - - if (dup2(fd_in, STDIN_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDOUT_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDERR_FILENO) < 0) - perr("Error in I/O redirection"); - - close(fd_in); - close(fd_out); - - nice((tolower((int) queue) - 'a' + 1) * 2); - -#ifdef WITH_SELINUX - if (selinux_enabled > 0) { - if (set_selinux_context(pentry->pw_name, filename) < 0) - perr("SELinux Failed to set context\n"); - } -#endif - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(ngid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir("/"); - - execle("/bin/sh", "sh", (char *) NULL, nenvp); - perr("Exec failed for /bin/sh"); - /* perr exits, the PRIV_END is just for nice form */ - PRIV_END - } - /* We're the parent. Let's wait. - */ - close(fd_in); - - /* We inherited the master's SIGCHLD handler, which does a - non-blocking waitpid. So this blocking one will eventually - return with an ECHILD error. - */ - waitpid(pid, (int *) NULL, 0); - - /* Send mail. Unlink the output file after opening it, so it - * doesn't hang around after the run. - */ - fstat(fd_out, &buf); - lseek(fd_out, 0, SEEK_SET); - if (dup2(fd_out, STDIN_FILENO) < 0) - perr("Could not use jobfile as standard input."); - - /* some sendmail implementations are confused if stdout, stderr are - * not available, so let them point to /dev/null - */ - if ((fd_in = open("/dev/null", O_WRONLY)) < 0) - perr("Could not open /dev/null."); - if (dup2(fd_in, STDOUT_FILENO) < 0) - perr("Could not use /dev/null as standard output."); - if (dup2(fd_in, STDERR_FILENO) < 0) - perr("Could not use /dev/null as standard error."); - if (fd_in != STDOUT_FILENO && fd_in != STDERR_FILENO) - close(fd_in); - - if (unlink(filename) == -1) - syslog(LOG_WARNING, "Warning: removing output file for job %li failed: %s", - jobno, strerror(errno)); - - /* The job is now finished. We can delete its input file. - */ - chdir(ATJOB_DIR); - unlink(newname); - free(newname); - -#ifdef ATD_MAIL_PROGRAM - if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { - int mail_pid = -1; - - mail_pid = fork(); - - if ( mail_pid == 0 ) { - PRIV_START - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(gid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir ("/"); - -#if defined(SENDMAIL) - execl(SENDMAIL, "sendmail", "-i", mailname, (char *) NULL); -#else -#error "No mail command specified." -#endif - perr("Exec failed for mail command"); - - PRIV_END - } - else if ( mail_pid == -1 ) { - syslog(LOG_ERR, "fork of mailer failed: %m"); - } - /* Parent */ - waitpid(mail_pid, (int *) NULL, 0); - } - -#ifdef WITH_PAM - AT_CLOSE_PAM; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif -#endif - exit(EXIT_SUCCESS); -} - -static time_t -run_loop() -{ - DIR *spool; - struct dirent *dirent; - struct stat buf; - unsigned long ctm; - unsigned long jobno; - char queue; - char batch_queue = '\0'; - time_t run_time, next_job; - char batch_name[] = "z2345678901234"; - char lock_name[] = "z2345678901234"; - uid_t batch_uid; - gid_t batch_gid; - int run_batch; - static time_t next_batch = 0; - double currlavg[3]; - - /* Main loop. Open spool directory for reading and look over all the - * files in there. If the filename indicates that the job should be run, - * run a function which sets its user and group id to that of the files - * and execs a /bin/sh, which executes the shell. The function will - * then remove the script (hopefully). - * - * Also, pick the oldest batch job to run, at most one per run of - * the main loop. - */ - - next_job = now + CHECK_INTERVAL; - if (next_batch == 0) - next_batch = now; - - /* To avoid spinning up the disk unnecessarily, stat the directory and - * return immediately if it hasn't changed since the last time we woke - * up. - */ - - if (stat(".", &buf) == -1) - perr("Cannot stat " ATJOB_DIR); - - if (nothing_to_do && buf.st_mtime <= last_chg) - return next_job; - last_chg = buf.st_mtime; - - if ((spool = opendir(".")) == NULL) - perr("Cannot read " ATJOB_DIR); - - run_batch = 0; - nothing_to_do = 1; - - batch_uid = (uid_t) - 1; - batch_gid = (gid_t) - 1; - - while ((dirent = readdir(spool)) != NULL) { - - /* Avoid the stat if this doesn't look like a job file */ - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - /* Chances are a '=' file has been deleted from under us. - * Ignore. - */ - if (stat(dirent->d_name, &buf) != 0) - continue; - - if (!S_ISREG(buf.st_mode)) - continue; - - /* We don't want files which at(1) hasn't yet marked executable. */ - if (!(buf.st_mode & S_IXUSR)) { - nothing_to_do = 0; /* it will probably become executable soon */ - continue; - } - - run_time = (time_t) ctm *60; - - /* Skip lock files */ - if (queue == '=') { - /* FIXME: calhariz */ - /* I think the following code is broken, but commenting - may haven unknow side effects. Make a release and see - in the wild how it works. For more information see: - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818508/* - - /* if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) { */ - /* /\* Remove stale lockfile FIXME: lock the lockfile, if you fail, it's still in use. *\/ */ - /* unlink(dirent->d_name); */ - /* } */ - continue; - } - /* Skip any other file types which may have been invented in - * the meantime. - */ - if (!(isupper(queue) || islower(queue))) { - continue; - } - /* Is the file already locked? - */ - if (buf.st_nlink > 1) { - if (run_time + CHECK_INTERVAL <= now) { - - /* Something went wrong the last time this was executed. - * Let's remove the lockfile and reschedule. - */ - strncpy(lock_name, dirent->d_name, sizeof(lock_name)); - lock_name[sizeof(lock_name)-1] = '\0'; - lock_name[0] = '='; - unlink(lock_name); - next_job = now; - nothing_to_do = 0; - } - continue; - } - - /* If we got here, then there are jobs of some kind waiting. - * We could try to be smarter and leave nothing_to_do set if - * we end up processing all the jobs, but that's risky (run_file - * might fail and expect the job to be rescheduled), and it doesn't - * gain us much. */ - nothing_to_do = 0; - - /* There's a job for later. Note its execution time if it's - * the earliest so far. - */ - if (run_time > now) { - if (next_job > run_time) { - next_job = run_time; - } - continue; - } - - if (isbatch(queue)) { - - /* We could potentially run this batch job. If it's scheduled - * at a higher priority than anything before, keep its - * filename. - */ - run_batch++; - if (strcmp(batch_name, dirent->d_name) > 0) { - strncpy(batch_name, dirent->d_name, sizeof(batch_name)); - batch_name[sizeof(batch_name)-1] = '\0'; - batch_uid = buf.st_uid; - batch_gid = buf.st_gid; - batch_queue = queue; - } - } - else { - if (run_time <= now) { - run_file(dirent->d_name, buf.st_uid, buf.st_gid); - } - } - } - closedir(spool); - /* run the single batch file, if any - */ - if (run_batch && (next_batch <= now)) { - next_batch = now + batch_interval; -#ifdef GETLOADAVG_PRIVILEGED - START_PRIV -#endif - if (getloadavg(currlavg, 1) < 1) { - currlavg[0] = 0.0; - } -#ifdef GETLOADAVG_PRIVILEGED - END_PRIV -#endif - if (currlavg[0] < load_avg) { - run_file(batch_name, batch_uid, batch_gid); - run_batch--; - } - } - if (run_batch && (next_batch < next_job)) { - nothing_to_do = 0; - next_job = next_batch; - } - return next_job; -} - -#ifdef HAVE_TIMER_CREATE -timer_t timer; -struct itimerspec timeout; - -void timer_setup() -{ - struct sigevent sev; - - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIGHUP; - sev.sigev_value.sival_ptr = &timer; - - memset(&timeout, 0, sizeof(timeout)); - - if (timer_create(CLOCK_REALTIME, &sev, &timer) < 0) - pabort("unable to create timer"); -} - -time_t atd_gettime() -{ - struct timespec curtime; - - clock_gettime(CLOCK_REALTIME, &curtime); - - return curtime.tv_sec; -} - -void atd_setalarm(time_t next) -{ - timeout.it_value.tv_sec = next; - timer_settime(timer, TIMER_ABSTIME, &timeout, NULL); - pause(); -} -#else -void timer_setup() -{ -} - -time_t atd_gettime() -{ - return time(NULL); -} - -void atd_setalarm(time_t next) -{ - sleep(next - atd_gettime()); -} -#endif -/* Global functions */ - -int -main(int argc, char *argv[]) -{ -/* Browse through ATJOB_DIR, checking all the jobfiles whether they should - * be executed and or deleted. The queue is coded into the first byte of - * the job filename, the next 5 bytes encode the serial number in hex, and - * the final 8 bytes encode the date (minutes since Eon) in hex. A file - * which has not been executed yet is denoted by its execute - bit set. - * For those files which are to be executed, run_file() is called, which forks - * off a child which takes care of I/O redirection, forks off another child - * for execution and yet another one, optionally, for sending mail. - * Files which already have run are removed during the next invocation. - */ - int c; - time_t next_invocation; - struct sigaction act; - struct passwd *pwe; - struct group *ge; - -#ifdef WITH_SELINUX - selinux_enabled=is_selinux_enabled(); - - if (selinux_enabled) { - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) selinux_log_callback); - } -#endif - -/* We don't need root privileges all the time; running under uid and gid - * daemon is fine. - */ - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - RELINQUISH_PRIVS_ROOT(daemon_uid, daemon_gid) - -#ifndef LOG_CRON -#define LOG_CRON LOG_DAEMON -#endif - - openlog("atd", LOG_PID, LOG_CRON); - - opterr = 0; - errno = 0; - run_as_daemon = 1; - batch_interval = BATCH_INTERVAL_DEFAULT; - - while ((c = getopt(argc, argv, "sdnl:b:f")) != EOF) { - switch (c) { - case 'l': - if (sscanf(optarg, "%lf", &load_avg) != 1) - pabort("garbled option -l"); - if (load_avg <= 0.) - load_avg = LOADAVG_MX; - break; - - case 'b': - if (sscanf(optarg, "%ud", &batch_interval) != 1) - pabort("garbled option -b"); - break; - case 'd': - daemon_debug++; - daemon_foreground++; - break; - - case 'f': - daemon_foreground++; - break; - - case 'n': - mail_with_hostname=1; - break; - - case 's': - run_as_daemon = 0; - break; - - case '?': - pabort("unknown option"); - break; - - default: - pabort("idiotic option - aborted"); - break; - } - } - - namep = argv[0]; - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if (optind < argc) - pabort("non-option arguments - not allowed"); - - sigaction(SIGCHLD, NULL, &act); - act.sa_handler = release_zombie; - act.sa_flags = SA_NOCLDSTOP; - sigaction(SIGCHLD, &act, NULL); - - if (!run_as_daemon) { - now = atd_gettime(); - run_loop(); - exit(EXIT_SUCCESS); - } - /* Main loop. Let's sleep for a specified interval, - * or until the next job is scheduled, or until we get signaled. - * After any of these events, we rescan the queue. - * A signal handler setting term_signal will make sure there's - * a clean exit. - */ - - sigaction(SIGHUP, NULL, &act); - act.sa_handler = sdummy; - sigaction(SIGHUP, &act, NULL); - - sigaction(SIGTERM, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGTERM, &act, NULL); - - sigaction(SIGINT, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGINT, &act, NULL); - - timer_setup(); - daemon_setup(); - - do { - now = atd_gettime(); - next_invocation = run_loop(); - if (next_invocation > now) { - atd_setalarm(next_invocation); - } - } while (!term_signal); - daemon_cleanup(); - exit(EXIT_SUCCESS); -} diff --git a/atd.c.clear-nojobs b/atd.c.clear-nojobs deleted file mode 100644 index 498e50f..0000000 --- a/atd.c.clear-nojobs +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * atd.c - run jobs queued by at; run with root privileges. - * Copyright (C) 1993, 1994, 1996 Thomas Koenig - * Copyright (c) 2002, 2005 Ryan Murray - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif HAVE_SYS_FCNTL_H - -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_GETOPT_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "privs.h" -#include "daemon.h" - -#ifndef HAVE_GETLOADAVG -#include "getloadavg.h" -#endif - -#ifdef WITH_SELINUX -#include -#include -int selinux_enabled = 0; -#endif - -/* Macros */ - -#ifndef LOG_ATD -#define LOG_ATD LOG_DAEMON -#endif - -#define BATCH_INTERVAL_DEFAULT 60 -#define CHECK_INTERVAL 3600 - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -static char *namep; -static double load_avg = LOADAVG_MX; -static time_t now; -static time_t last_chg; -static int nothing_to_do; -unsigned int batch_interval; -static int run_as_daemon = 0; -static int mail_with_hostname = 0; - -static volatile sig_atomic_t term_signal = 0; - -#ifdef WITH_PAM -#include - -static pam_handle_t *pamh = NULL; - -static const struct pam_conv conv = { - NULL -}; - -#endif /* WITH_PAM */ - -/* Signal handlers */ -RETSIGTYPE -set_term(int dummy) -{ - term_signal = 1; - return; -} - -RETSIGTYPE -sdummy(int dummy) -{ - /* Empty signal handler */ - nothing_to_do = 0; - return; -} - -/* SIGCHLD handler - discards completion status of children */ -RETSIGTYPE -release_zombie(int dummy) -{ - int status; - pid_t pid; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { -#ifdef DEBUG_ZOMBIE - if (WIFEXITED(status)) - syslog(LOG_INFO, "pid %ld exited with status %d.", pid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - syslog(LOG_NOTICE, "pid %ld killed with signal %d.", pid, WTERMSIG(status)); - else if (WIFSTOPPED(status)) - syslog(LOG_NOTICE, "pid %ld stopped with signal %d.", pid, WSTOPSIG(status)); - else - syslog(LOG_WARNING, "pid %ld unknown reason for SIGCHLD", pid); -#endif - } - return; -} - - -/* Local functions */ - -static int -write_string(int fd, const char *a) -{ - return write(fd, a, strlen(a)); -} - -static int -isbatch(char queue) -{ - return isupper(queue) || (queue == 'b'); -} - -#undef DEBUG_FORK -#ifdef DEBUG_FORK -static pid_t -myfork() -{ - pid_t res; - res = fork(); - if (res == 0) - kill(getpid(), SIGSTOP); - return res; -} - -#define fork myfork -#endif -#undef ATD_MAIL_PROGRAM -#undef ATD_MAIL_NAME -#if defined(SENDMAIL) -#define ATD_MAIL_PROGRAM SENDMAIL -#define ATD_MAIL_NAME "sendmail" -#elif defined(MAILC) -#define ATD_MAIL_PROGRAM MAILC -#define ATD_MAIL_NAME "mail" -#elif defined(MAILX) -#define ATD_MAIL_PROGRAM MAILX -#define ATD_MAIL_NAME "mailx" -#endif - -#ifdef WITH_SELINUX -static int -set_selinux_context(const char *name, const char *filename) { - security_context_t user_context = NULL; - security_context_t file_context = NULL; - int retval = 0; - char *seuser = NULL; - char *level = NULL; - - if (getseuserbyname(name, &seuser, &level) == 0) { - retval = get_default_context_with_level(seuser, level, NULL, &user_context); - free(seuser); - free(level); - if (retval < 0) { - lerr("get_default_context_with_level: couldn't get security context for user %s", name); - retval = -1; - goto err; - } - } - - /* - * Since crontab files are not directly executed, - * crond must ensure that the crontab file has - * a context that is appropriate for the context of - * the user cron job. It performs an entrypoint - * permission check for this purpose. - */ - if (fgetfilecon(STDIN_FILENO, &file_context) < 0) { - lerr("fgetfilecon FAILED %s", filename); - retval = -1; - goto err; - } - - retval = selinux_check_access(user_context, file_context, "file", "entrypoint", NULL); - freecon(file_context); - if (retval < 0) { - lerr("Not allowed to set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } - if (setexeccon(user_context) < 0) { - lerr("Could not set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } -err: - if (retval < 0 && security_getenforce() != 1) - retval = 0; - if (user_context) - freecon(user_context); - return retval; -} - -static int -selinux_log_callback (int type, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsyslog (LOG_ERR, fmt, ap); - va_end(ap); - return 0; -} - -#endif - -static void -run_file(const char *filename, uid_t uid, gid_t gid) -{ -/* Run a file by by spawning off a process which redirects I/O, - * spawns a subshell, then waits for it to complete and sends - * mail to the user. - */ - pid_t pid; - int fd_out, fd_in; - char jobbuf[9]; - char *mailname = NULL; - int mailsize = 128; - char *newname; - FILE *stream; - int send_mail = 0; - struct stat buf, lbuf; - off_t size; - struct passwd *pentry; - int fflags; - int nuid; - int ngid; - char queue; - char fmt[64]; - unsigned long jobno; - int rc; - char hostbuf[MAXHOSTNAMELEN]; -#ifdef WITH_PAM - int retcode; -#endif - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - sscanf(filename, "%c%5lx", &queue, &jobno); - if ((mailname = malloc(mailsize+1)) == NULL) - pabort("Job %8lu : out of virtual memory", jobno); - - sprintf(jobbuf, "%8lu", jobno); - - if ((newname = strdup(filename)) == 0) - pabort("Job %8lu : out of virtual memory", jobno); - newname[0] = '='; - - /* We try to make a hard link to lock the file. If we fail, then - * somebody else has already locked or deleted it (a second atd?); log the - * fact and return. - */ - PRIV_START - rc = link(filename, newname); - PRIV_END - if (rc == -1) { - syslog(LOG_WARNING, "could not lock job %lu: %m", jobno); - free(mailname); - free(newname); - return; - } - /* If something goes wrong between here and the unlink() call, - * the job gets restarted as soon as the "=" entry is cleared - * by the main atd loop. - */ - - pid = fork(); - if (pid == -1) { - lerr("Cannot fork for job execution"); - free(mailname); - free(newname); - return; - } - else if (pid != 0) { - free(mailname); - free(newname); - return; - } - - (void) setsid(); /* own session for process */ - - /* Let's see who we mail to. Hopefully, we can read it from - * the command file; if not, send it to the owner, or, failing that, - * to root. - */ - - pentry = getpwuid(uid); - if (pentry == NULL) { - pabort("Userid %lu not found - aborting job %8lu (%.500s)", - (unsigned long) uid, jobno, filename); - } - PRIV_START - - stream = fopen(filename, "r"); - - PRIV_END - - if (stream == NULL) - perr("Cannot open input file"); - - if ((fd_in = dup(fileno(stream))) < 0) - perr("Error duplicating input file descriptor"); - - if (fstat(fd_in, &buf) == -1) - perr("Error in fstat of input file descriptor"); - - if (lstat(filename, &lbuf) == -1) - perr("Error in fstat of input file"); - - if (S_ISLNK(lbuf.st_mode)) - perr("Symbolic link encountered in job %8lu (%.500s) - aborting", - jobno, filename); - - if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || - (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || - (lbuf.st_size != buf.st_size)) - perr("Somebody changed files from under us for job %8lu (%.500s) - " - "aborting", jobno, filename); - - if (buf.st_nlink > 2) { - perr("Somebody is trying to run a linked script for job %8lu (%.500s)", - jobno, filename); - } - if ((fflags = fcntl(fd_in, F_GETFD)) < 0) - perr("Error in fcntl"); - - fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); - - /* - * If the spool directory is mounted via NFS `atd' isn't able to - * read from the job file and will bump out here. The file is - * opened as "root" but it is read as "daemon" which fails over - * NFS and works with local file systems. It's not clear where - * the bug is located. -Joey - */ - sprintf(fmt, "#!/bin/sh\n# atrun uid=%%d gid=%%d\n# mail %%%ds %%d", - mailsize ); - - if (fscanf(stream, fmt, - &nuid, &ngid, mailname, &send_mail) != 4) - pabort("File %.500s is in wrong format - aborting", - filename); - - if (mailname[0] == '-') - pabort("illegal mail name %.300s in job %8lu (%.300s)", mailname, - jobno, filename); - - if (nuid != uid) - pabort("Job %8lu (%.500s) - userid %d does not match file uid %d", - jobno, filename, nuid, uid); - - /* We are now committed to executing this script. Unlink the - * original. - */ - - unlink(filename); - - fclose(stream); - if (chdir(ATSPOOL_DIR) < 0) - perr("Cannot chdir to " ATSPOOL_DIR); - - /* Create a file to hold the output of the job we are about to run. - * Write the mail header. Complain in case - */ - - if (unlink(filename) != -1) { - syslog(LOG_WARNING,"Warning: for duplicate output file for %.100s (dead job?)", - filename); - } - - if ((fd_out = open(filename, - O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) - perr("Cannot create output file"); - PRIV_START - if (fchown(fd_out, uid, ngid) == -1) - syslog(LOG_WARNING, "Warning: could not change owner of output file for job %li to %i:%i: %s", - jobno, uid, ngid, strerror(errno)); - PRIV_END - - write_string(fd_out, "Subject: Output from your job "); - write_string(fd_out, jobbuf); - if (mail_with_hostname > 0) { - gethostname(hostbuf, MAXHOSTNAMELEN-1); - write_string(fd_out, " "); - write_string(fd_out, hostbuf); - } - write_string(fd_out, "\nTo: "); - write_string(fd_out, mailname); - write_string(fd_out, "\n\n"); - fstat(fd_out, &buf); - size = buf.st_size; - -#ifdef WITH_PAM - AT_START_PAM; - AT_OPEN_PAM_SESSION; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - pid = fork(); - if (pid < 0) - perr("Error in fork"); - - else if (pid == 0) { - char *nul = NULL; - char **nenvp = &nul; - char **pam_envp=0L; - - PRIV_START -#ifdef WITH_PAM - pam_envp = pam_getenvlist(pamh); - if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) ) - nenvp = pam_envp; -#endif - /* Set up things for the child; we want standard input from the - * input file, and standard output and error sent to our output file. - */ - if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0) - perr("Error in lseek"); - - if (dup2(fd_in, STDIN_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDOUT_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDERR_FILENO) < 0) - perr("Error in I/O redirection"); - - close(fd_in); - close(fd_out); - - nice((tolower((int) queue) - 'a' + 1) * 2); - -#ifdef WITH_SELINUX - if (selinux_enabled > 0) { - if (set_selinux_context(pentry->pw_name, filename) < 0) - perr("SELinux Failed to set context\n"); - } -#endif - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(ngid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir("/"); - - execle("/bin/sh", "sh", (char *) NULL, nenvp); - perr("Exec failed for /bin/sh"); - /* perr exits, the PRIV_END is just for nice form */ - PRIV_END - } - /* We're the parent. Let's wait. - */ - close(fd_in); - - /* We inherited the master's SIGCHLD handler, which does a - non-blocking waitpid. So this blocking one will eventually - return with an ECHILD error. - */ - waitpid(pid, (int *) NULL, 0); - - /* Send mail. Unlink the output file after opening it, so it - * doesn't hang around after the run. - */ - fstat(fd_out, &buf); - lseek(fd_out, 0, SEEK_SET); - if (dup2(fd_out, STDIN_FILENO) < 0) - perr("Could not use jobfile as standard input."); - - /* some sendmail implementations are confused if stdout, stderr are - * not available, so let them point to /dev/null - */ - if ((fd_in = open("/dev/null", O_WRONLY)) < 0) - perr("Could not open /dev/null."); - if (dup2(fd_in, STDOUT_FILENO) < 0) - perr("Could not use /dev/null as standard output."); - if (dup2(fd_in, STDERR_FILENO) < 0) - perr("Could not use /dev/null as standard error."); - if (fd_in != STDOUT_FILENO && fd_in != STDERR_FILENO) - close(fd_in); - - if (unlink(filename) == -1) - syslog(LOG_WARNING, "Warning: removing output file for job %li failed: %s", - jobno, strerror(errno)); - - /* The job is now finished. We can delete its input file. - */ - chdir(ATJOB_DIR); - unlink(newname); - free(newname); - -#ifdef ATD_MAIL_PROGRAM - if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { - int mail_pid = -1; - - mail_pid = fork(); - - if ( mail_pid == 0 ) { - PRIV_START - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(gid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir ("/"); - -#if defined(SENDMAIL) - execl(SENDMAIL, "sendmail", "-i", mailname, (char *) NULL); -#else -#error "No mail command specified." -#endif - perr("Exec failed for mail command"); - - PRIV_END - } - else if ( mail_pid == -1 ) { - syslog(LOG_ERR, "fork of mailer failed: %m"); - } - /* Parent */ - waitpid(mail_pid, (int *) NULL, 0); - } - -#ifdef WITH_PAM - AT_CLOSE_PAM; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif -#endif - exit(EXIT_SUCCESS); -} - -static time_t -run_loop() -{ - DIR *spool; - struct dirent *dirent; - struct stat buf; - unsigned long ctm; - unsigned long jobno; - char queue; - char batch_queue = '\0'; - time_t run_time, next_job; - char batch_name[] = "z2345678901234"; - char lock_name[] = "z2345678901234"; - uid_t batch_uid; - gid_t batch_gid; - int run_batch; - static time_t next_batch = 0; - double currlavg[3]; - - /* Main loop. Open spool directory for reading and look over all the - * files in there. If the filename indicates that the job should be run, - * run a function which sets its user and group id to that of the files - * and execs a /bin/sh, which executes the shell. The function will - * then remove the script (hopefully). - * - * Also, pick the oldest batch job to run, at most one per run of - * the main loop. - */ - - next_job = now + CHECK_INTERVAL; - if (next_batch == 0) - next_batch = now; - - /* To avoid spinning up the disk unnecessarily, stat the directory and - * return immediately if it hasn't changed since the last time we woke - * up. - */ - - if (stat(".", &buf) == -1) { - lerr("Cannot stat " ATJOB_DIR); - return next_job; - } - - if (nothing_to_do && buf.st_mtime <= last_chg) - return next_job; - last_chg = buf.st_mtime; - - if ((spool = opendir(".")) == NULL) { - lerr("Cannot read " ATJOB_DIR); - return next_job; - } - - run_batch = 0; - nothing_to_do = 1; - - batch_uid = (uid_t) - 1; - batch_gid = (gid_t) - 1; - - while ((dirent = readdir(spool)) != NULL) { - - /* Avoid the stat if this doesn't look like a job file */ - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - /* Chances are a '=' file has been deleted from under us. - * Ignore. - */ - if (stat(dirent->d_name, &buf) != 0) - continue; - - if (!S_ISREG(buf.st_mode)) - continue; - - /* We don't want files which at(1) hasn't yet marked executable. */ - if (!(buf.st_mode & S_IXUSR)) { - nothing_to_do = 0; /* it will probably become executable soon */ - continue; - } - - run_time = (time_t) ctm *60; - - /* Skip lock files */ - if (queue == '=') { - /* FIXME: calhariz */ - /* I think the following code is broken, but commenting - may haven unknow side effects. Make a release and see - in the wild how it works. For more information see: - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818508/* - - /* if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) { */ - /* /\* Remove stale lockfile FIXME: lock the lockfile, if you fail, it's still in use. *\/ */ - /* unlink(dirent->d_name); */ - /* } */ - continue; - } - /* Skip any other file types which may have been invented in - * the meantime. - */ - if (!(isupper(queue) || islower(queue))) { - continue; - } - /* Is the file already locked? - */ - if (buf.st_nlink > 1) { - if (run_time < buf.st_mtime) - run_time = buf.st_mtime; - if (run_time + CHECK_INTERVAL <= now) { - /* Something went wrong the last time this was executed. - * Let's remove the lockfile and reschedule. - * We also change the timestamp to avoid rerunning the job more - * than once every CHECK_INTERVAL. - */ - strncpy(lock_name, dirent->d_name, sizeof(lock_name)); - if (utime(lock_name, 0) < 0) - syslog(LOG_ERR, "utime couldn't be set for lock file %s\n", lock_name); - lock_name[sizeof(lock_name)-1] = '\0'; - lock_name[0] = '='; - unlink(lock_name); - next_job = now; - nothing_to_do = 0; - } - continue; - } - - /* If we got here, then there are jobs of some kind waiting. - * We could try to be smarter and leave nothing_to_do set if - * we end up processing all the jobs, but that's risky (run_file - * might fail and expect the job to be rescheduled), and it doesn't - * gain us much. */ - nothing_to_do = 0; - - /* There's a job for later. Note its execution time if it's - * the earliest so far. - */ - if (run_time > now) { - if (next_job > run_time) { - next_job = run_time; - } - continue; - } - - if (isbatch(queue)) { - - /* We could potentially run this batch job. If it's scheduled - * at a higher priority than anything before, keep its - * filename. - */ - run_batch++; - if (strcmp(batch_name, dirent->d_name) > 0) { - strncpy(batch_name, dirent->d_name, sizeof(batch_name)); - batch_name[sizeof(batch_name)-1] = '\0'; - batch_uid = buf.st_uid; - batch_gid = buf.st_gid; - batch_queue = queue; - } - } - else { - if (run_time <= now) { - run_file(dirent->d_name, buf.st_uid, buf.st_gid); - } - } - } - closedir(spool); - /* run the single batch file, if any - */ - if (run_batch && (next_batch <= now)) { - next_batch = now + batch_interval; -#ifdef GETLOADAVG_PRIVILEGED - START_PRIV -#endif - if (getloadavg(currlavg, 1) < 1) { - currlavg[0] = 0.0; - } -#ifdef GETLOADAVG_PRIVILEGED - END_PRIV -#endif - if (currlavg[0] < load_avg) { - run_file(batch_name, batch_uid, batch_gid); - run_batch--; - } - } - if (run_batch && (next_batch < next_job)) { - nothing_to_do = 0; - next_job = next_batch; - } - return next_job; -} - -#ifdef HAVE_TIMER_CREATE -timer_t timer; -struct itimerspec timeout; - -void timer_setup() -{ - struct sigevent sev; - - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIGHUP; - sev.sigev_value.sival_ptr = &timer; - - memset(&timeout, 0, sizeof(timeout)); - - if (timer_create(CLOCK_REALTIME, &sev, &timer) < 0) - pabort("unable to create timer"); -} - -time_t atd_gettime() -{ - struct timespec curtime; - - clock_gettime(CLOCK_REALTIME, &curtime); - - return curtime.tv_sec; -} - -void atd_setalarm(time_t next) -{ - timeout.it_value.tv_sec = next; - timer_settime(timer, TIMER_ABSTIME, &timeout, NULL); - pause(); -} -#else -void timer_setup() -{ -} - -time_t atd_gettime() -{ - return time(NULL); -} - -void atd_setalarm(time_t next) -{ - sleep(next - atd_gettime()); -} -#endif -/* Global functions */ - -int -main(int argc, char *argv[]) -{ -/* Browse through ATJOB_DIR, checking all the jobfiles whether they should - * be executed and or deleted. The queue is coded into the first byte of - * the job filename, the next 5 bytes encode the serial number in hex, and - * the final 8 bytes encode the date (minutes since Eon) in hex. A file - * which has not been executed yet is denoted by its execute - bit set. - * For those files which are to be executed, run_file() is called, which forks - * off a child which takes care of I/O redirection, forks off another child - * for execution and yet another one, optionally, for sending mail. - * Files which already have run are removed during the next invocation. - */ - int c; - time_t next_invocation; - struct sigaction act; - struct passwd *pwe; - struct group *ge; - -#ifdef WITH_SELINUX - selinux_enabled=is_selinux_enabled(); - - if (selinux_enabled) { - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) selinux_log_callback); - } -#endif - -/* We don't need root privileges all the time; running under uid and gid - * daemon is fine. - */ - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - RELINQUISH_PRIVS_ROOT(daemon_uid, daemon_gid) - -#ifndef LOG_CRON -#define LOG_CRON LOG_DAEMON -#endif - - openlog("atd", LOG_PID, LOG_CRON); - - opterr = 0; - errno = 0; - run_as_daemon = 1; - batch_interval = BATCH_INTERVAL_DEFAULT; - - while ((c = getopt(argc, argv, "sdnl:b:f")) != EOF) { - switch (c) { - case 'l': - if (sscanf(optarg, "%lf", &load_avg) != 1) - pabort("garbled option -l"); - if (load_avg <= 0.) - load_avg = LOADAVG_MX; - break; - - case 'b': - if (sscanf(optarg, "%ud", &batch_interval) != 1) - pabort("garbled option -b"); - break; - case 'd': - daemon_debug++; - daemon_foreground++; - break; - - case 'f': - daemon_foreground++; - break; - - case 'n': - mail_with_hostname=1; - break; - - case 's': - run_as_daemon = 0; - break; - - case '?': - pabort("unknown option"); - break; - - default: - pabort("idiotic option - aborted"); - break; - } - } - - namep = argv[0]; - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if (optind < argc) - pabort("non-option arguments - not allowed"); - - sigaction(SIGCHLD, NULL, &act); - act.sa_handler = release_zombie; - act.sa_flags = SA_NOCLDSTOP; - sigaction(SIGCHLD, &act, NULL); - - if (!run_as_daemon) { - now = atd_gettime(); - run_loop(); - exit(EXIT_SUCCESS); - } - /* Main loop. Let's sleep for a specified interval, - * or until the next job is scheduled, or until we get signaled. - * After any of these events, we rescan the queue. - * A signal handler setting term_signal will make sure there's - * a clean exit. - */ - - sigaction(SIGHUP, NULL, &act); - act.sa_handler = sdummy; - sigaction(SIGHUP, &act, NULL); - - sigaction(SIGTERM, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGTERM, &act, NULL); - - sigaction(SIGINT, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGINT, &act, NULL); - - timer_setup(); - daemon_setup(); - - do { - now = atd_gettime(); - next_invocation = run_loop(); - if (next_invocation > now) { - atd_setalarm(next_invocation); - } - } while (!term_signal); - daemon_cleanup(); - exit(EXIT_SUCCESS); -} diff --git a/atd.c.lock-locks b/atd.c.lock-locks deleted file mode 100644 index baadc1d..0000000 --- a/atd.c.lock-locks +++ /dev/null @@ -1,1023 +0,0 @@ -/* - * atd.c - run jobs queued by at; run with root privileges. - * Copyright (C) 1993, 1994, 1996 Thomas Koenig - * Copyright (c) 2002, 2005 Ryan Murray - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif HAVE_SYS_FCNTL_H - -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_GETOPT_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "privs.h" -#include "daemon.h" - -#ifndef HAVE_GETLOADAVG -#include "getloadavg.h" -#endif - -#ifdef WITH_SELINUX -#include -#include -int selinux_enabled = 0; -#endif - -/* Macros */ - -#ifndef LOG_ATD -#define LOG_ATD LOG_DAEMON -#endif - -#define BATCH_INTERVAL_DEFAULT 60 -#define CHECK_INTERVAL 3600 - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -static char *namep; -static double load_avg = LOADAVG_MX; -static time_t now; -static time_t last_chg; -static int nothing_to_do; -unsigned int batch_interval; -static int run_as_daemon = 0; -static int mail_with_hostname = 0; - -static volatile sig_atomic_t term_signal = 0; - -#ifdef WITH_PAM -#include - -static pam_handle_t *pamh = NULL; - -static const struct pam_conv conv = { - NULL -}; - -#endif /* WITH_PAM */ - -/* Signal handlers */ -RETSIGTYPE -set_term(int dummy) -{ - term_signal = 1; - return; -} - -RETSIGTYPE -sdummy(int dummy) -{ - /* Empty signal handler */ - nothing_to_do = 0; - return; -} - -/* SIGCHLD handler - discards completion status of children */ -RETSIGTYPE -release_zombie(int dummy) -{ - int status; - pid_t pid; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { -#ifdef DEBUG_ZOMBIE - if (WIFEXITED(status)) - syslog(LOG_INFO, "pid %ld exited with status %d.", pid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - syslog(LOG_NOTICE, "pid %ld killed with signal %d.", pid, WTERMSIG(status)); - else if (WIFSTOPPED(status)) - syslog(LOG_NOTICE, "pid %ld stopped with signal %d.", pid, WSTOPSIG(status)); - else - syslog(LOG_WARNING, "pid %ld unknown reason for SIGCHLD", pid); -#endif - } - return; -} - - -/* Local functions */ - -static int -write_string(int fd, const char *a) -{ - return write(fd, a, strlen(a)); -} - -static int -isbatch(char queue) -{ - return isupper(queue) || (queue == 'b'); -} - -#undef DEBUG_FORK -#ifdef DEBUG_FORK -static pid_t -myfork() -{ - pid_t res; - res = fork(); - if (res == 0) - kill(getpid(), SIGSTOP); - return res; -} - -#define fork myfork -#endif -#undef ATD_MAIL_PROGRAM -#undef ATD_MAIL_NAME -#if defined(SENDMAIL) -#define ATD_MAIL_PROGRAM SENDMAIL -#define ATD_MAIL_NAME "sendmail" -#elif defined(MAILC) -#define ATD_MAIL_PROGRAM MAILC -#define ATD_MAIL_NAME "mail" -#elif defined(MAILX) -#define ATD_MAIL_PROGRAM MAILX -#define ATD_MAIL_NAME "mailx" -#endif - -#ifdef WITH_SELINUX -static int -set_selinux_context(const char *name, const char *filename) { - security_context_t user_context = NULL; - security_context_t file_context = NULL; - int retval = 0; - char *seuser = NULL; - char *level = NULL; - - if (getseuserbyname(name, &seuser, &level) == 0) { - retval = get_default_context_with_level(seuser, level, NULL, &user_context); - free(seuser); - free(level); - if (retval < 0) { - lerr("get_default_context_with_level: couldn't get security context for user %s", name); - retval = -1; - goto err; - } - } - - /* - * Since crontab files are not directly executed, - * crond must ensure that the crontab file has - * a context that is appropriate for the context of - * the user cron job. It performs an entrypoint - * permission check for this purpose. - */ - if (fgetfilecon(STDIN_FILENO, &file_context) < 0) { - lerr("fgetfilecon FAILED %s", filename); - retval = -1; - goto err; - } - - retval = selinux_check_access(user_context, file_context, "file", "entrypoint", NULL); - freecon(file_context); - if (retval < 0) { - lerr("Not allowed to set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } - if (setexeccon(user_context) < 0) { - lerr("Could not set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } -err: - if (retval < 0 && security_getenforce() != 1) - retval = 0; - if (user_context) - freecon(user_context); - return retval; -} - -static int -selinux_log_callback (int type, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsyslog (LOG_ERR, fmt, ap); - va_end(ap); - return 0; -} - -#endif - -static void -run_file(const char *filename, uid_t uid, gid_t gid) -{ -/* Run a file by by spawning off a process which redirects I/O, - * spawns a subshell, then waits for it to complete and sends - * mail to the user. - */ - pid_t pid; - int fd_out, fd_in; - char jobbuf[9]; - char *mailname = NULL; - int mailsize = 128; - char *newname; - FILE *stream; - int send_mail = 0; - struct stat buf, lbuf; - off_t size; - struct passwd *pentry; - int fflags; - int nuid; - int ngid; - char queue; - char fmt[64]; - unsigned long jobno; - int rc; - char hostbuf[MAXHOSTNAMELEN]; -#ifdef WITH_PAM - int retcode; -#endif - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - sscanf(filename, "%c%5lx", &queue, &jobno); - if ((mailname = malloc(mailsize+1)) == NULL) - pabort("Job %8lu : out of virtual memory", jobno); - - sprintf(jobbuf, "%8lu", jobno); - - if ((newname = strdup(filename)) == 0) - pabort("Job %8lu : out of virtual memory", jobno); - newname[0] = '='; - - /* We try to make a hard link to lock the file. If we fail, then - * somebody else has already locked or deleted it (a second atd?); log the - * fact and return. - */ - PRIV_START - rc = link(filename, newname); - PRIV_END - if (rc == -1) { - syslog(LOG_WARNING, "could not lock job %lu: %m", jobno); - free(mailname); - free(newname); - return; - } - /* If something goes wrong between here and the unlink() call, - * the job gets restarted as soon as the "=" entry is cleared - * by the main atd loop. - */ - - pid = fork(); - if (pid == -1) { - lerr("Cannot fork for job execution"); - free(mailname); - free(newname); - return; - } - else if (pid != 0) { - free(mailname); - free(newname); - return; - } - - (void) setsid(); /* own session for process */ - - /* Let's see who we mail to. Hopefully, we can read it from - * the command file; if not, send it to the owner, or, failing that, - * to root. - */ - - pentry = getpwuid(uid); - if (pentry == NULL) { - pabort("Userid %lu not found - aborting job %8lu (%.500s)", - (unsigned long) uid, jobno, filename); - } - PRIV_START - - stream = fopen(filename, "r"); - - PRIV_END - - if (stream == NULL) - perr("Cannot open input file"); - - if ((fd_in = dup(fileno(stream))) < 0) - perr("Error duplicating input file descriptor"); - - if (fstat(fd_in, &buf) == -1) - perr("Error in fstat of input file descriptor"); - - if (lstat(filename, &lbuf) == -1) - perr("Error in fstat of input file"); - - if (S_ISLNK(lbuf.st_mode)) - perr("Symbolic link encountered in job %8lu (%.500s) - aborting", - jobno, filename); - - if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || - (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || - (lbuf.st_size != buf.st_size)) - perr("Somebody changed files from under us for job %8lu (%.500s) - " - "aborting", jobno, filename); - - if (buf.st_nlink > 2) { - perr("Somebody is trying to run a linked script for job %8lu (%.500s)", - jobno, filename); - } - if ((fflags = fcntl(fd_in, F_GETFD)) < 0) - perr("Error in fcntl"); - - fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); - - /* - * If the spool directory is mounted via NFS `atd' isn't able to - * read from the job file and will bump out here. The file is - * opened as "root" but it is read as "daemon" which fails over - * NFS and works with local file systems. It's not clear where - * the bug is located. -Joey - */ - sprintf(fmt, "#!/bin/sh\n# atrun uid=%%d gid=%%d\n# mail %%%ds %%d", - mailsize ); - - /* Unlink the file unless there was an error reading it (perhaps - * temporary). - * If the file has a bogus format there is no reason in trying - * to run it again and again. - */ - if (fscanf(stream, fmt, - &nuid, &ngid, mailname, &send_mail) != 4) { - if (ferror(stream)) - perr("Error reading the job file"); - - unlink(filename); - pabort("File %.500s is in wrong format - aborting", - filename); - } - - unlink(filename); - - if (mailname[0] == '-') - pabort("illegal mail name %.300s in job %8lu (%.300s)", mailname, - jobno, filename); - - if (nuid != uid) - pabort("Job %8lu (%.500s) - userid %d does not match file uid %d", - jobno, filename, nuid, uid); - - fclose(stream); - if (chdir(ATSPOOL_DIR) < 0) - perr("Cannot chdir to " ATSPOOL_DIR); - - /* Create a file to hold the output of the job we are about to run. - * Write the mail header. Complain in case - */ - - if (unlink(filename) != -1) { - syslog(LOG_WARNING,"Warning: for duplicate output file for %.100s (dead job?)", - filename); - } - - if ((fd_out = open(filename, - O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) - perr("Cannot create output file"); - PRIV_START - if (fchown(fd_out, uid, ngid) == -1) - syslog(LOG_WARNING, "Warning: could not change owner of output file for job %li to %i:%i: %s", - jobno, uid, ngid, strerror(errno)); - PRIV_END - - write_string(fd_out, "Subject: Output from your job "); - write_string(fd_out, jobbuf); - if (mail_with_hostname > 0) { - gethostname(hostbuf, MAXHOSTNAMELEN-1); - write_string(fd_out, " "); - write_string(fd_out, hostbuf); - } - write_string(fd_out, "\nTo: "); - write_string(fd_out, mailname); - write_string(fd_out, "\n\n"); - fstat(fd_out, &buf); - size = buf.st_size; - -#ifdef WITH_PAM - AT_START_PAM; - AT_OPEN_PAM_SESSION; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - pid = fork(); - if (pid < 0) - perr("Error in fork"); - - else if (pid == 0) { - char *nul = NULL; - char **nenvp = &nul; - char **pam_envp=0L; - - PRIV_START -#ifdef WITH_PAM - pam_envp = pam_getenvlist(pamh); - if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) ) - nenvp = pam_envp; -#endif - /* Set up things for the child; we want standard input from the - * input file, and standard output and error sent to our output file. - */ - if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0) - perr("Error in lseek"); - - if (dup2(fd_in, STDIN_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDOUT_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDERR_FILENO) < 0) - perr("Error in I/O redirection"); - - close(fd_in); - close(fd_out); - - nice((tolower((int) queue) - 'a' + 1) * 2); - -#ifdef WITH_SELINUX - if (selinux_enabled > 0) { - if (set_selinux_context(pentry->pw_name, filename) < 0) - perr("SELinux Failed to set context\n"); - } -#endif - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(ngid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir("/"); - - execle("/bin/sh", "sh", (char *) NULL, nenvp); - perr("Exec failed for /bin/sh"); - /* perr exits, the PRIV_END is just for nice form */ - PRIV_END - } - /* We're the parent. Let's wait. - */ - close(fd_in); - - /* We inherited the master's SIGCHLD handler, which does a - non-blocking waitpid. So this blocking one will eventually - return with an ECHILD error. - */ - waitpid(pid, (int *) NULL, 0); - - /* Send mail. Unlink the output file after opening it, so it - * doesn't hang around after the run. - */ - fstat(fd_out, &buf); - lseek(fd_out, 0, SEEK_SET); - if (dup2(fd_out, STDIN_FILENO) < 0) - perr("Could not use jobfile as standard input."); - - /* some sendmail implementations are confused if stdout, stderr are - * not available, so let them point to /dev/null - */ - if ((fd_in = open("/dev/null", O_WRONLY)) < 0) - perr("Could not open /dev/null."); - if (dup2(fd_in, STDOUT_FILENO) < 0) - perr("Could not use /dev/null as standard output."); - if (dup2(fd_in, STDERR_FILENO) < 0) - perr("Could not use /dev/null as standard error."); - if (fd_in != STDOUT_FILENO && fd_in != STDERR_FILENO) - close(fd_in); - - if (unlink(filename) == -1) - syslog(LOG_WARNING, "Warning: removing output file for job %li failed: %s", - jobno, strerror(errno)); - - /* The job is now finished. We can delete its input file. - */ - chdir(ATJOB_DIR); - unlink(newname); - free(newname); - -#ifdef ATD_MAIL_PROGRAM - if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { - int mail_pid = -1; - - mail_pid = fork(); - - if ( mail_pid == 0 ) { - PRIV_START - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(gid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir ("/"); - -#if defined(SENDMAIL) - execl(SENDMAIL, "sendmail", "-i", mailname, (char *) NULL); -#else -#error "No mail command specified." -#endif - perr("Exec failed for mail command"); - - PRIV_END - } - else if ( mail_pid == -1 ) { - syslog(LOG_ERR, "fork of mailer failed: %m"); - } - /* Parent */ - waitpid(mail_pid, (int *) NULL, 0); - } - -#ifdef WITH_PAM - AT_CLOSE_PAM; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif -#endif - exit(EXIT_SUCCESS); -} - -static time_t -run_loop() -{ - DIR *spool; - struct dirent *dirent; - struct stat buf; - unsigned long ctm; - unsigned long jobno; - char queue; - char batch_queue = '\0'; - time_t run_time, next_job; - char batch_name[] = "z2345678901234"; - char lock_name[] = "z2345678901234"; - uid_t batch_uid; - gid_t batch_gid; - int run_batch; - static time_t next_batch = 0; - double currlavg[3]; - - /* Main loop. Open spool directory for reading and look over all the - * files in there. If the filename indicates that the job should be run, - * run a function which sets its user and group id to that of the files - * and execs a /bin/sh, which executes the shell. The function will - * then remove the script (hopefully). - * - * Also, pick the oldest batch job to run, at most one per run of - * the main loop. - */ - - next_job = now + CHECK_INTERVAL; - if (next_batch == 0) - next_batch = now; - - /* To avoid spinning up the disk unnecessarily, stat the directory and - * return immediately if it hasn't changed since the last time we woke - * up. - */ - - if (stat(".", &buf) == -1) { - lerr("Cannot stat " ATJOB_DIR); - return next_job; - } - - if (nothing_to_do && buf.st_mtime <= last_chg) - return next_job; - last_chg = buf.st_mtime; - - if ((spool = opendir(".")) == NULL) { - lerr("Cannot read " ATJOB_DIR); - return next_job; - } - - run_batch = 0; - nothing_to_do = 1; - - batch_uid = (uid_t) - 1; - batch_gid = (gid_t) - 1; - - while ((dirent = readdir(spool)) != NULL) { - - /* Avoid the stat if this doesn't look like a job file */ - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - /* Chances are a '=' file has been deleted from under us. - * Ignore. - */ - if (stat(dirent->d_name, &buf) != 0) - continue; - - if (!S_ISREG(buf.st_mode)) - continue; - - /* We don't want files which at(1) hasn't yet marked executable. */ - if (!(buf.st_mode & S_IXUSR)) { - nothing_to_do = 0; /* it will probably become executable soon */ - continue; - } - - run_time = (time_t) ctm *60; - - /* Skip lock files */ - if (queue == '=') { - /* FIXME: calhariz */ - /* I think the following code is broken, but commenting - may haven unknow side effects. Make a release and see - in the wild how it works. For more information see: - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818508/* - - /* if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) { */ - /* /\* Remove stale lockfile FIXME: lock the lockfile, if you fail, it's still in use. *\/ */ - /* unlink(dirent->d_name); */ - /* } */ - continue; - } - /* Skip any other file types which may have been invented in - * the meantime. - */ - if (!(isupper(queue) || islower(queue))) { - continue; - } - /* Is the file already locked? - */ - if (buf.st_nlink > 1) { - if (run_time < buf.st_mtime) - run_time = buf.st_mtime; - if (run_time + CHECK_INTERVAL <= now) { - /* Something went wrong the last time this was executed. - * Let's remove the lockfile and reschedule. - * We also change the timestamp to avoid rerunning the job more - * than once every CHECK_INTERVAL. - */ - strncpy(lock_name, dirent->d_name, sizeof(lock_name)); - if (utime(lock_name, 0) < 0) - syslog(LOG_ERR, "utime couldn't be set for lock file %s\n", lock_name); - lock_name[sizeof(lock_name)-1] = '\0'; - lock_name[0] = '='; - unlink(lock_name); - next_job = now; - nothing_to_do = 0; - } - continue; - } - - /* If we got here, then there are jobs of some kind waiting. - * We could try to be smarter and leave nothing_to_do set if - * we end up processing all the jobs, but that's risky (run_file - * might fail and expect the job to be rescheduled), and it doesn't - * gain us much. */ - nothing_to_do = 0; - - /* There's a job for later. Note its execution time if it's - * the earliest so far. - */ - if (run_time > now) { - if (next_job > run_time) { - next_job = run_time; - } - continue; - } - - if (isbatch(queue)) { - - /* We could potentially run this batch job. If it's scheduled - * at a higher priority than anything before, keep its - * filename. - */ - run_batch++; - if (strcmp(batch_name, dirent->d_name) > 0) { - strncpy(batch_name, dirent->d_name, sizeof(batch_name)); - batch_name[sizeof(batch_name)-1] = '\0'; - batch_uid = buf.st_uid; - batch_gid = buf.st_gid; - batch_queue = queue; - } - } - else { - if (run_time <= now) { - run_file(dirent->d_name, buf.st_uid, buf.st_gid); - } - } - } - closedir(spool); - /* run the single batch file, if any - */ - if (run_batch && (next_batch <= now)) { - next_batch = now + batch_interval; -#ifdef GETLOADAVG_PRIVILEGED - START_PRIV -#endif - if (getloadavg(currlavg, 1) < 1) { - currlavg[0] = 0.0; - } -#ifdef GETLOADAVG_PRIVILEGED - END_PRIV -#endif - if (currlavg[0] < load_avg) { - run_file(batch_name, batch_uid, batch_gid); - run_batch--; - } - } - if (run_batch && (next_batch < next_job)) { - nothing_to_do = 0; - next_job = next_batch; - } - return next_job; -} - -#ifdef HAVE_TIMER_CREATE -timer_t timer; -struct itimerspec timeout; - -void timer_setup() -{ - struct sigevent sev; - - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIGHUP; - sev.sigev_value.sival_ptr = &timer; - - memset(&timeout, 0, sizeof(timeout)); - - if (timer_create(CLOCK_REALTIME, &sev, &timer) < 0) - pabort("unable to create timer"); -} - -time_t atd_gettime() -{ - struct timespec curtime; - - clock_gettime(CLOCK_REALTIME, &curtime); - - return curtime.tv_sec; -} - -void atd_setalarm(time_t next) -{ - timeout.it_value.tv_sec = next; - timer_settime(timer, TIMER_ABSTIME, &timeout, NULL); - pause(); -} -#else -void timer_setup() -{ -} - -time_t atd_gettime() -{ - return time(NULL); -} - -void atd_setalarm(time_t next) -{ - sleep(next - atd_gettime()); -} -#endif -/* Global functions */ - -int -main(int argc, char *argv[]) -{ -/* Browse through ATJOB_DIR, checking all the jobfiles whether they should - * be executed and or deleted. The queue is coded into the first byte of - * the job filename, the next 5 bytes encode the serial number in hex, and - * the final 8 bytes encode the date (minutes since Eon) in hex. A file - * which has not been executed yet is denoted by its execute - bit set. - * For those files which are to be executed, run_file() is called, which forks - * off a child which takes care of I/O redirection, forks off another child - * for execution and yet another one, optionally, for sending mail. - * Files which already have run are removed during the next invocation. - */ - int c; - time_t next_invocation; - struct sigaction act; - struct passwd *pwe; - struct group *ge; - -#ifdef WITH_SELINUX - selinux_enabled=is_selinux_enabled(); - - if (selinux_enabled) { - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) selinux_log_callback); - } -#endif - -/* We don't need root privileges all the time; running under uid and gid - * daemon is fine. - */ - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - RELINQUISH_PRIVS_ROOT(daemon_uid, daemon_gid) - -#ifndef LOG_CRON -#define LOG_CRON LOG_DAEMON -#endif - - openlog("atd", LOG_PID, LOG_CRON); - - opterr = 0; - errno = 0; - run_as_daemon = 1; - batch_interval = BATCH_INTERVAL_DEFAULT; - - while ((c = getopt(argc, argv, "sdnl:b:f")) != EOF) { - switch (c) { - case 'l': - if (sscanf(optarg, "%lf", &load_avg) != 1) - pabort("garbled option -l"); - if (load_avg <= 0.) - load_avg = LOADAVG_MX; - break; - - case 'b': - if (sscanf(optarg, "%ud", &batch_interval) != 1) - pabort("garbled option -b"); - break; - case 'd': - daemon_debug++; - daemon_foreground++; - break; - - case 'f': - daemon_foreground++; - break; - - case 'n': - mail_with_hostname=1; - break; - - case 's': - run_as_daemon = 0; - break; - - case '?': - pabort("unknown option"); - break; - - default: - pabort("idiotic option - aborted"); - break; - } - } - - namep = argv[0]; - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if (optind < argc) - pabort("non-option arguments - not allowed"); - - sigaction(SIGCHLD, NULL, &act); - act.sa_handler = release_zombie; - act.sa_flags = SA_NOCLDSTOP; - sigaction(SIGCHLD, &act, NULL); - - if (!run_as_daemon) { - now = atd_gettime(); - run_loop(); - exit(EXIT_SUCCESS); - } - /* Main loop. Let's sleep for a specified interval, - * or until the next job is scheduled, or until we get signaled. - * After any of these events, we rescan the queue. - * A signal handler setting term_signal will make sure there's - * a clean exit. - */ - - sigaction(SIGHUP, NULL, &act); - act.sa_handler = sdummy; - sigaction(SIGHUP, &act, NULL); - - sigaction(SIGTERM, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGTERM, &act, NULL); - - sigaction(SIGINT, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGINT, &act, NULL); - - timer_setup(); - daemon_setup(); - - do { - now = atd_gettime(); - next_invocation = run_loop(); - if (next_invocation > now) { - atd_setalarm(next_invocation); - } - } while (!term_signal); - daemon_cleanup(); - exit(EXIT_SUCCESS); -} diff --git a/atd.c.log-jobs b/atd.c.log-jobs deleted file mode 100644 index b6e83c5..0000000 --- a/atd.c.log-jobs +++ /dev/null @@ -1,1034 +0,0 @@ -/* - * atd.c - run jobs queued by at; run with root privileges. - * Copyright (C) 1993, 1994, 1996 Thomas Koenig - * Copyright (c) 2002, 2005 Ryan Murray - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif HAVE_SYS_FCNTL_H - -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_GETOPT_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include -#include - -/* Local headers */ - -#include "privs.h" -#include "daemon.h" - -#ifndef HAVE_GETLOADAVG -#include "getloadavg.h" -#endif - -#ifdef WITH_SELINUX -#include -#include -int selinux_enabled = 0; -#endif - -/* Macros */ - -#ifndef LOG_ATD -#define LOG_ATD LOG_DAEMON -#endif - -#define BATCH_INTERVAL_DEFAULT 60 -#define CHECK_INTERVAL 3600 - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -static char *namep; -static double load_avg = LOADAVG_MX; -static time_t now; -static time_t last_chg; -static int nothing_to_do; -unsigned int batch_interval; -static int run_as_daemon = 0; -static int mail_with_hostname = 0; - -static volatile sig_atomic_t term_signal = 0; - -#ifdef WITH_PAM -#include - -static pam_handle_t *pamh = NULL; - -static const struct pam_conv conv = { - NULL -}; - -#endif /* WITH_PAM */ - -/* Signal handlers */ -RETSIGTYPE -set_term(int dummy) -{ - term_signal = 1; - return; -} - -RETSIGTYPE -sdummy(int dummy) -{ - /* Empty signal handler */ - nothing_to_do = 0; - return; -} - -/* SIGCHLD handler - discards completion status of children */ -RETSIGTYPE -release_zombie(int dummy) -{ - int status; - pid_t pid; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { -#ifdef DEBUG_ZOMBIE - if (WIFEXITED(status)) - syslog(LOG_INFO, "pid %ld exited with status %d.", pid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - syslog(LOG_NOTICE, "pid %ld killed with signal %d.", pid, WTERMSIG(status)); - else if (WIFSTOPPED(status)) - syslog(LOG_NOTICE, "pid %ld stopped with signal %d.", pid, WSTOPSIG(status)); - else - syslog(LOG_WARNING, "pid %ld unknown reason for SIGCHLD", pid); -#endif - } - return; -} - - -/* Local functions */ - -static int -write_string(int fd, const char *a) -{ - return write(fd, a, strlen(a)); -} - -static int -isbatch(char queue) -{ - return isupper(queue) || (queue == 'b'); -} - -#undef DEBUG_FORK -#ifdef DEBUG_FORK -static pid_t -myfork() -{ - pid_t res; - res = fork(); - if (res == 0) - kill(getpid(), SIGSTOP); - return res; -} - -#define fork myfork -#endif -#undef ATD_MAIL_PROGRAM -#undef ATD_MAIL_NAME -#if defined(SENDMAIL) -#define ATD_MAIL_PROGRAM SENDMAIL -#define ATD_MAIL_NAME "sendmail" -#elif defined(MAILC) -#define ATD_MAIL_PROGRAM MAILC -#define ATD_MAIL_NAME "mail" -#elif defined(MAILX) -#define ATD_MAIL_PROGRAM MAILX -#define ATD_MAIL_NAME "mailx" -#endif - -#ifdef WITH_SELINUX -static int -set_selinux_context(const char *name, const char *filename) { - security_context_t user_context = NULL; - security_context_t file_context = NULL; - int retval = 0; - char *seuser = NULL; - char *level = NULL; - - if (getseuserbyname(name, &seuser, &level) == 0) { - retval = get_default_context_with_level(seuser, level, NULL, &user_context); - free(seuser); - free(level); - if (retval < 0) { - lerr("get_default_context_with_level: couldn't get security context for user %s", name); - retval = -1; - goto err; - } - } - - /* - * Since crontab files are not directly executed, - * crond must ensure that the crontab file has - * a context that is appropriate for the context of - * the user cron job. It performs an entrypoint - * permission check for this purpose. - */ - if (fgetfilecon(STDIN_FILENO, &file_context) < 0) { - lerr("fgetfilecon FAILED %s", filename); - retval = -1; - goto err; - } - - retval = selinux_check_access(user_context, file_context, "file", "entrypoint", NULL); - freecon(file_context); - if (retval < 0) { - lerr("Not allowed to set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } - if (setexeccon(user_context) < 0) { - lerr("Could not set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } -err: - if (retval < 0 && security_getenforce() != 1) - retval = 0; - if (user_context) - freecon(user_context); - return retval; -} - -static int -selinux_log_callback (int type, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsyslog (LOG_ERR, fmt, ap); - va_end(ap); - return 0; -} - -#endif - -static void -run_file(const char *filename, uid_t uid, gid_t gid) -{ -/* Run a file by by spawning off a process which redirects I/O, - * spawns a subshell, then waits for it to complete and sends - * mail to the user. - */ - pid_t pid; - int fd_out, fd_in, fd_std; - char jobbuf[9]; - char *mailname = NULL; - int mailsize = 128; - char *newname; - FILE *stream; - int send_mail = 0; - struct stat buf, lbuf; - off_t size; - struct passwd *pentry; - int fflags; - int nuid; - int ngid; - char queue; - char fmt[64]; - unsigned long jobno; - int rc; - char hostbuf[MAXHOSTNAMELEN]; -#ifdef WITH_PAM - int retcode; -#endif - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - sscanf(filename, "%c%5lx", &queue, &jobno); - if ((mailname = malloc(mailsize+1)) == NULL) - pabort("Job %8lu : out of virtual memory", jobno); - - sprintf(jobbuf, "%8lu", jobno); - - if ((newname = strdup(filename)) == 0) - pabort("Job %8lu : out of virtual memory", jobno); - newname[0] = '='; - - /* We try to make a hard link to lock the file. If we fail, then - * somebody else has already locked or deleted it (a second atd?); log the - * fact and return. - */ - PRIV_START - rc = link(filename, newname); - PRIV_END - if (rc == -1) { - syslog(LOG_WARNING, "could not lock job %lu: %m", jobno); - free(mailname); - free(newname); - return; - } - /* If something goes wrong between here and the unlink() call, - * the job gets restarted as soon as the "=" entry is cleared - * by the main atd loop. - */ - - pid = fork(); - if (pid == -1) { - lerr("Cannot fork for job execution"); - free(mailname); - free(newname); - return; - } - else if (pid != 0) { - free(mailname); - free(newname); - return; - } - - (void) setsid(); /* own session for process */ - - /* Let's see who we mail to. Hopefully, we can read it from - * the command file; if not, send it to the owner, or, failing that, - * to root. - */ - - pentry = getpwuid(uid); - if (pentry == NULL) { - pabort("Userid %lu not found - aborting job %8lu (%.500s)", - (unsigned long) uid, jobno, filename); - } - PRIV_START - - stream = fopen(filename, "r"); - - PRIV_END - - if (stream == NULL) - perr("Cannot open input file"); - - if ((fd_in = dup(fileno(stream))) < 0) - perr("Error duplicating input file descriptor"); - - if (fstat(fd_in, &buf) == -1) - perr("Error in fstat of input file descriptor"); - - if (lstat(filename, &lbuf) == -1) - perr("Error in fstat of input file"); - - if (S_ISLNK(lbuf.st_mode)) - perr("Symbolic link encountered in job %8lu (%.500s) - aborting", - jobno, filename); - - if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || - (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || - (lbuf.st_size != buf.st_size)) - perr("Somebody changed files from under us for job %8lu (%.500s) - " - "aborting", jobno, filename); - - if (buf.st_nlink > 2) { - perr("Somebody is trying to run a linked script for job %8lu (%.500s)", - jobno, filename); - } - if ((fflags = fcntl(fd_in, F_GETFD)) < 0) - perr("Error in fcntl"); - - fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); - - if (flock(fd_in, LOCK_EX | LOCK_NB) != 0) - perr("Somebody already locked the job %8lu (%.500s) - " - "aborting", jobno, filename); - - /* - * If the spool directory is mounted via NFS `atd' isn't able to - * read from the job file and will bump out here. The file is - * opened as "root" but it is read as "daemon" which fails over - * NFS and works with local file systems. It's not clear where - * the bug is located. -Joey - */ - sprintf(fmt, "#!/bin/sh\n# atrun uid=%%d gid=%%d\n# mail %%%ds %%d", - mailsize ); - - /* Unlink the file unless there was an error reading it (perhaps - * temporary). - * If the file has a bogus format there is no reason in trying - * to run it again and again. - */ - if (fscanf(stream, fmt, - &nuid, &ngid, mailname, &send_mail) != 4) { - if (ferror(stream)) - perr("Error reading the job file"); - - unlink(filename); - pabort("File %.500s is in wrong format - aborting", - filename); - } - - unlink(filename); - - if (mailname[0] == '-') - pabort("illegal mail name %.300s in job %8lu (%.300s)", mailname, - jobno, filename); - - if (nuid != uid) - pabort("Job %8lu (%.500s) - userid %d does not match file uid %d", - jobno, filename, nuid, uid); - - fclose(stream); - if (chdir(ATSPOOL_DIR) < 0) - perr("Cannot chdir to " ATSPOOL_DIR); - - /* Create a file to hold the output of the job we are about to run. - * Write the mail header. Complain in case - */ - - if (unlink(filename) != -1) { - syslog(LOG_WARNING,"Warning: for duplicate output file for %.100s (dead job?)", - filename); - } - - if ((fd_out = open(filename, - O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) - perr("Cannot create output file"); - PRIV_START - if (fchown(fd_out, uid, ngid) == -1) - syslog(LOG_WARNING, "Warning: could not change owner of output file for job %li to %i:%i: %s", - jobno, uid, ngid, strerror(errno)); - PRIV_END - - write_string(fd_out, "Subject: Output from your job "); - write_string(fd_out, jobbuf); - if (mail_with_hostname > 0) { - gethostname(hostbuf, MAXHOSTNAMELEN-1); - write_string(fd_out, " "); - write_string(fd_out, hostbuf); - } - write_string(fd_out, "\nTo: "); - write_string(fd_out, mailname); - write_string(fd_out, "\n\n"); - fstat(fd_out, &buf); - size = buf.st_size; - -#ifdef WITH_PAM - AT_START_PAM; - AT_OPEN_PAM_SESSION; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - pid = fork(); - if (pid < 0) - perr("Error in fork"); - - else if (pid == 0) { - char *nul = NULL; - char **nenvp = &nul; - char **pam_envp=0L; - - PRIV_START -#ifdef WITH_PAM - pam_envp = pam_getenvlist(pamh); - if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) ) - nenvp = pam_envp; -#endif - /* Set up things for the child; we want standard input from the - * input file, and standard output and error sent to our output file. - */ - if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0) - perr("Error in lseek"); - - if (dup2(fd_in, STDIN_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDOUT_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDERR_FILENO) < 0) - perr("Error in I/O redirection"); - - close(fd_in); - close(fd_out); - - nice((tolower((int) queue) - 'a' + 1) * 2); - -#ifdef WITH_SELINUX - if (selinux_enabled > 0) { - if (set_selinux_context(pentry->pw_name, filename) < 0) - perr("SELinux Failed to set context\n"); - } -#endif - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(ngid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir("/"); - - execle("/bin/sh", "sh", (char *) NULL, nenvp); - perr("Exec failed for /bin/sh"); - /* perr exits, the PRIV_END is just for nice form */ - PRIV_END - } - /* We're the parent. Let's wait. - We inherited the master's SIGCHLD handler, which does a - non-blocking waitpid. So this blocking one will eventually - return with an ECHILD error. - */ - waitpid(pid, (int *) NULL, 0); - - /* Send mail. Unlink the output file after opening it, so it - * doesn't hang around after the run. - */ - fstat(fd_out, &buf); - lseek(fd_out, 0, SEEK_SET); - if (dup2(fd_out, STDIN_FILENO) < 0) - perr("Could not use jobfile as standard input."); - - /* some sendmail implementations are confused if stdout, stderr are - * not available, so let them point to /dev/null - */ - if ((fd_std = open("/dev/null", O_WRONLY)) < 0) - perr("Could not open /dev/null."); - if (dup2(fd_std, STDOUT_FILENO) < 0) - perr("Could not use /dev/null as standard output."); - if (dup2(fd_std, STDERR_FILENO) < 0) - perr("Could not use /dev/null as standard error."); - if (fd_std != STDOUT_FILENO && fd_std != STDERR_FILENO) - close(fd_std); - - if (unlink(filename) == -1) - syslog(LOG_WARNING, "Warning: removing output file for job %li failed: %s", - jobno, strerror(errno)); - - /* The job is now finished. We can delete its input file. - */ - if (chdir(ATJOB_DIR) != 0) - perr("Somebody removed %s directory from under us.", ATJOB_DIR); - - /* This also removes the flock */ - (void)close(fd_in); - - unlink(newname); - free(newname); - -#ifdef ATD_MAIL_PROGRAM - if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { - int mail_pid = -1; - - mail_pid = fork(); - - if ( mail_pid == 0 ) { - PRIV_START - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(gid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir ("/"); - -#if defined(SENDMAIL) - execl(SENDMAIL, "sendmail", "-i", mailname, (char *) NULL); -#else -#error "No mail command specified." -#endif - perr("Exec failed for mail command"); - - PRIV_END - } - else if ( mail_pid == -1 ) { - syslog(LOG_ERR, "fork of mailer failed: %m"); - } - /* Parent */ - waitpid(mail_pid, (int *) NULL, 0); - } - -#ifdef WITH_PAM - AT_CLOSE_PAM; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif -#endif - exit(EXIT_SUCCESS); -} - -static time_t -run_loop() -{ - DIR *spool; - struct dirent *dirent; - struct stat buf; - unsigned long ctm; - unsigned long jobno; - char queue; - char batch_queue = '\0'; - time_t run_time, next_job; - char batch_name[] = "z2345678901234"; - char lock_name[] = "z2345678901234"; - uid_t batch_uid; - gid_t batch_gid; - int run_batch; - static time_t next_batch = 0; - double currlavg[3]; - - /* Main loop. Open spool directory for reading and look over all the - * files in there. If the filename indicates that the job should be run, - * run a function which sets its user and group id to that of the files - * and execs a /bin/sh, which executes the shell. The function will - * then remove the script (hopefully). - * - * Also, pick the oldest batch job to run, at most one per run of - * the main loop. - */ - - next_job = now + CHECK_INTERVAL; - if (next_batch == 0) - next_batch = now; - - /* To avoid spinning up the disk unnecessarily, stat the directory and - * return immediately if it hasn't changed since the last time we woke - * up. - */ - - if (stat(".", &buf) == -1) { - lerr("Cannot stat " ATJOB_DIR); - return next_job; - } - - if (nothing_to_do && buf.st_mtime <= last_chg) - return next_job; - last_chg = buf.st_mtime; - - if ((spool = opendir(".")) == NULL) { - lerr("Cannot read " ATJOB_DIR); - return next_job; - } - - run_batch = 0; - nothing_to_do = 1; - - batch_uid = (uid_t) - 1; - batch_gid = (gid_t) - 1; - - while ((dirent = readdir(spool)) != NULL) { - - /* Avoid the stat if this doesn't look like a job file */ - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - /* Chances are a '=' file has been deleted from under us. - * Ignore. - */ - if (stat(dirent->d_name, &buf) != 0) - continue; - - if (!S_ISREG(buf.st_mode)) - continue; - - /* We don't want files which at(1) hasn't yet marked executable. */ - if (!(buf.st_mode & S_IXUSR)) { - nothing_to_do = 0; /* it will probably become executable soon */ - continue; - } - - run_time = (time_t) ctm *60; - - /* Skip lock files */ - if (queue == '=') { - if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) { - int fd; - - fd = open(dirent->d_name, O_RDONLY); - if (fd != -1) { - if (flock(fd, LOCK_EX | LOCK_NB) == 0) { - unlink(dirent->d_name); - syslog(LOG_NOTICE, "removing stale lock file %s\n", dirent->d_name); - } - (void)close(fd); - } - } - continue; - } - /* Skip any other file types which may have been invented in - * the meantime. - */ - if (!(isupper(queue) || islower(queue))) { - continue; - } - /* Is the file already locked? - */ - if (buf.st_nlink > 1) { - if (run_time < buf.st_mtime) - run_time = buf.st_mtime; - if (run_time + CHECK_INTERVAL <= now) { - /* Something went wrong the last time this was executed. - * Let's remove the lockfile and reschedule. - * We also change the timestamp to avoid rerunning the job more - * than once every CHECK_INTERVAL. - */ - strncpy(lock_name, dirent->d_name, sizeof(lock_name)); - if (utime(lock_name, 0) < 0) - syslog(LOG_ERR, "utime couldn't be set for lock file %s\n", lock_name); - lock_name[sizeof(lock_name)-1] = '\0'; - lock_name[0] = '='; - unlink(lock_name); - next_job = now; - nothing_to_do = 0; - } - continue; - } - - /* If we got here, then there are jobs of some kind waiting. - * We could try to be smarter and leave nothing_to_do set if - * we end up processing all the jobs, but that's risky (run_file - * might fail and expect the job to be rescheduled), and it doesn't - * gain us much. */ - nothing_to_do = 0; - - /* There's a job for later. Note its execution time if it's - * the earliest so far. - */ - if (run_time > now) { - if (next_job > run_time) { - next_job = run_time; - } - continue; - } - - if (isbatch(queue)) { - - /* We could potentially run this batch job. If it's scheduled - * at a higher priority than anything before, keep its - * filename. - */ - run_batch++; - if (strcmp(batch_name, dirent->d_name) > 0) { - strncpy(batch_name, dirent->d_name, sizeof(batch_name)); - batch_name[sizeof(batch_name)-1] = '\0'; - batch_uid = buf.st_uid; - batch_gid = buf.st_gid; - batch_queue = queue; - } - } - else { - if (run_time <= now) { - run_file(dirent->d_name, buf.st_uid, buf.st_gid); - } - } - } - closedir(spool); - /* run the single batch file, if any - */ - if (run_batch && (next_batch <= now)) { - next_batch = now + batch_interval; -#ifdef GETLOADAVG_PRIVILEGED - START_PRIV -#endif - if (getloadavg(currlavg, 1) < 1) { - currlavg[0] = 0.0; - } -#ifdef GETLOADAVG_PRIVILEGED - END_PRIV -#endif - if (currlavg[0] < load_avg) { - run_file(batch_name, batch_uid, batch_gid); - run_batch--; - } - } - if (run_batch && (next_batch < next_job)) { - nothing_to_do = 0; - next_job = next_batch; - } - return next_job; -} - -#ifdef HAVE_TIMER_CREATE -timer_t timer; -struct itimerspec timeout; - -void timer_setup() -{ - struct sigevent sev; - - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIGHUP; - sev.sigev_value.sival_ptr = &timer; - - memset(&timeout, 0, sizeof(timeout)); - - if (timer_create(CLOCK_REALTIME, &sev, &timer) < 0) - pabort("unable to create timer"); -} - -time_t atd_gettime() -{ - struct timespec curtime; - - clock_gettime(CLOCK_REALTIME, &curtime); - - return curtime.tv_sec; -} - -void atd_setalarm(time_t next) -{ - timeout.it_value.tv_sec = next; - timer_settime(timer, TIMER_ABSTIME, &timeout, NULL); - pause(); -} -#else -void timer_setup() -{ -} - -time_t atd_gettime() -{ - return time(NULL); -} - -void atd_setalarm(time_t next) -{ - sleep(next - atd_gettime()); -} -#endif -/* Global functions */ - -int -main(int argc, char *argv[]) -{ -/* Browse through ATJOB_DIR, checking all the jobfiles whether they should - * be executed and or deleted. The queue is coded into the first byte of - * the job filename, the next 5 bytes encode the serial number in hex, and - * the final 8 bytes encode the date (minutes since Eon) in hex. A file - * which has not been executed yet is denoted by its execute - bit set. - * For those files which are to be executed, run_file() is called, which forks - * off a child which takes care of I/O redirection, forks off another child - * for execution and yet another one, optionally, for sending mail. - * Files which already have run are removed during the next invocation. - */ - int c; - time_t next_invocation; - struct sigaction act; - struct passwd *pwe; - struct group *ge; - -#ifdef WITH_SELINUX - selinux_enabled=is_selinux_enabled(); - - if (selinux_enabled) { - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) selinux_log_callback); - } -#endif - -/* We don't need root privileges all the time; running under uid and gid - * daemon is fine. - */ - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - RELINQUISH_PRIVS_ROOT(daemon_uid, daemon_gid) - -#ifndef LOG_CRON -#define LOG_CRON LOG_DAEMON -#endif - - openlog("atd", LOG_PID, LOG_CRON); - - opterr = 0; - errno = 0; - run_as_daemon = 1; - batch_interval = BATCH_INTERVAL_DEFAULT; - - while ((c = getopt(argc, argv, "sdnl:b:f")) != EOF) { - switch (c) { - case 'l': - if (sscanf(optarg, "%lf", &load_avg) != 1) - pabort("garbled option -l"); - if (load_avg <= 0.) - load_avg = LOADAVG_MX; - break; - - case 'b': - if (sscanf(optarg, "%ud", &batch_interval) != 1) - pabort("garbled option -b"); - break; - case 'd': - daemon_debug++; - daemon_foreground++; - break; - - case 'f': - daemon_foreground++; - break; - - case 'n': - mail_with_hostname=1; - break; - - case 's': - run_as_daemon = 0; - break; - - case '?': - pabort("unknown option"); - break; - - default: - pabort("idiotic option - aborted"); - break; - } - } - - namep = argv[0]; - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if (optind < argc) - pabort("non-option arguments - not allowed"); - - sigaction(SIGCHLD, NULL, &act); - act.sa_handler = release_zombie; - act.sa_flags = SA_NOCLDSTOP; - sigaction(SIGCHLD, &act, NULL); - - if (!run_as_daemon) { - now = atd_gettime(); - run_loop(); - exit(EXIT_SUCCESS); - } - /* Main loop. Let's sleep for a specified interval, - * or until the next job is scheduled, or until we get signaled. - * After any of these events, we rescan the queue. - * A signal handler setting term_signal will make sure there's - * a clean exit. - */ - - sigaction(SIGHUP, NULL, &act); - act.sa_handler = sdummy; - sigaction(SIGHUP, &act, NULL); - - sigaction(SIGTERM, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGTERM, &act, NULL); - - sigaction(SIGINT, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGINT, &act, NULL); - - timer_setup(); - daemon_setup(); - - do { - now = atd_gettime(); - next_invocation = run_loop(); - if (next_invocation > now) { - atd_setalarm(next_invocation); - } - } while (!term_signal); - daemon_cleanup(); - exit(EXIT_SUCCESS); -} diff --git a/atd.c.mail b/atd.c.mail deleted file mode 100644 index 566d50a..0000000 --- a/atd.c.mail +++ /dev/null @@ -1,941 +0,0 @@ -/* - * atd.c - run jobs queued by at; run with root privileges. - * Copyright (C) 1993, 1994, 1996 Thomas Koenig - * Copyright (c) 2002, 2005 Ryan Murray - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif HAVE_SYS_FCNTL_H - -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_GETOPT_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "privs.h" -#include "daemon.h" - -#ifndef HAVE_GETLOADAVG -#include "getloadavg.h" -#endif - -#ifdef WITH_SELINUX -#include -#include -int selinux_enabled = 0; -#endif - -/* Macros */ - -#ifndef LOG_ATD -#define LOG_ATD LOG_DAEMON -#endif - -#define BATCH_INTERVAL_DEFAULT 60 -#define CHECK_INTERVAL 3600 - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -static char *namep; -static double load_avg = LOADAVG_MX; -static time_t now; -static time_t last_chg; -static int nothing_to_do; -unsigned int batch_interval; -static int run_as_daemon = 0; - -static volatile sig_atomic_t term_signal = 0; - -#ifdef WITH_PAM -#include - -static pam_handle_t *pamh = NULL; - -static const struct pam_conv conv = { - NULL -}; - -#endif /* WITH_PAM */ - -/* Signal handlers */ -RETSIGTYPE -set_term(int dummy) -{ - term_signal = 1; - return; -} - -RETSIGTYPE -sdummy(int dummy) -{ - /* Empty signal handler */ - nothing_to_do = 0; - return; -} - -/* SIGCHLD handler - discards completion status of children */ -RETSIGTYPE -release_zombie(int dummy) -{ - int status; - pid_t pid; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { -#ifdef DEBUG_ZOMBIE - if (WIFEXITED(status)) - syslog(LOG_INFO, "pid %ld exited with status %d.", pid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - syslog(LOG_NOTICE, "pid %ld killed with signal %d.", pid, WTERMSIG(status)); - else if (WIFSTOPPED(status)) - syslog(LOG_NOTICE, "pid %ld stopped with signal %d.", pid, WSTOPSIG(status)); - else - syslog(LOG_WARNING, "pid %ld unknown reason for SIGCHLD", pid); -#endif - } - return; -} - - -/* Local functions */ - -static int -write_string(int fd, const char *a) -{ - return write(fd, a, strlen(a)); -} - -static int -isbatch(char queue) -{ - return isupper(queue) || (queue == 'b'); -} - -#undef DEBUG_FORK -#ifdef DEBUG_FORK -static pid_t -myfork() -{ - pid_t res; - res = fork(); - if (res == 0) - kill(getpid(), SIGSTOP); - return res; -} - -#define fork myfork -#endif -#undef ATD_MAIL_PROGRAM -#undef ATD_MAIL_NAME -#if defined(SENDMAIL) -#define ATD_MAIL_PROGRAM SENDMAIL -#define ATD_MAIL_NAME "sendmail" -#elif defined(MAILC) -#define ATD_MAIL_PROGRAM MAILC -#define ATD_MAIL_NAME "mail" -#elif defined(MAILX) -#define ATD_MAIL_PROGRAM MAILX -#define ATD_MAIL_NAME "mailx" -#endif - -#ifdef WITH_SELINUX -static int -set_selinux_context(const char *name, const char *filename) { - security_context_t user_context = NULL; - security_context_t file_context = NULL; - int retval = 0; - char *seuser = NULL; - char *level = NULL; - - if (getseuserbyname(name, &seuser, &level) == 0) { - retval = get_default_context_with_level(seuser, level, NULL, &user_context); - free(seuser); - free(level); - if (retval < 0) { - lerr("get_default_context_with_level: couldn't get security context for user %s", name); - retval = -1; - goto err; - } - } - - /* - * Since crontab files are not directly executed, - * crond must ensure that the crontab file has - * a context that is appropriate for the context of - * the user cron job. It performs an entrypoint - * permission check for this purpose. - */ - if (fgetfilecon(STDIN_FILENO, &file_context) < 0) { - lerr("fgetfilecon FAILED %s", filename); - retval = -1; - goto err; - } - - retval = selinux_check_access(user_context, file_context, "file", "entrypoint", NULL); - freecon(file_context); - if (retval < 0) { - lerr("Not allowed to set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } - if (setexeccon(user_context) < 0) { - lerr("Could not set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } -err: - if (retval < 0 && security_getenforce() != 1) - retval = 0; - if (user_context) - freecon(user_context); - return retval; -} - -static int -selinux_log_callback (int type, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsyslog (LOG_ERR, fmt, ap); - va_end(ap); - return 0; -} - -#endif - -static void -run_file(const char *filename, uid_t uid, gid_t gid) -{ -/* Run a file by by spawning off a process which redirects I/O, - * spawns a subshell, then waits for it to complete and sends - * mail to the user. - */ - pid_t pid; - int fd_out, fd_in; - char jobbuf[9]; - char *mailname = NULL; - int mailsize = 128; - char *newname; - FILE *stream; - int send_mail = 0; - struct stat buf, lbuf; - off_t size; - struct passwd *pentry; - int fflags; - int nuid; - int ngid; - char queue; - char fmt[64]; - unsigned long jobno; - int rc; -#ifdef WITH_PAM - int retcode; -#endif - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - sscanf(filename, "%c%5lx", &queue, &jobno); - if ((mailname = malloc(mailsize+1)) == NULL) - pabort("Job %8lu : out of virtual memory", jobno); - - sprintf(jobbuf, "%8lu", jobno); - - if ((newname = strdup(filename)) == 0) - pabort("Job %8lu : out of virtual memory", jobno); - newname[0] = '='; - - /* We try to make a hard link to lock the file. If we fail, then - * somebody else has already locked or deleted it (a second atd?); log the - * fact and return. - */ - PRIV_START - rc = link(filename, newname); - PRIV_END - if (rc == -1) { - syslog(LOG_WARNING, "could not lock job %lu: %m", jobno); - free(mailname); - free(newname); - return; - } - /* If something goes wrong between here and the unlink() call, - * the job gets restarted as soon as the "=" entry is cleared - * by the main atd loop. - */ - - pid = fork(); - if (pid == -1) - perr("Cannot fork"); - - else if (pid != 0) { - free(mailname); - free(newname); - return; - } - - (void) setsid(); /* own session for process */ - - /* Let's see who we mail to. Hopefully, we can read it from - * the command file; if not, send it to the owner, or, failing that, - * to root. - */ - - pentry = getpwuid(uid); - if (pentry == NULL) { - pabort("Userid %lu not found - aborting job %8lu (%.500s)", - (unsigned long) uid, jobno, filename); - } - PRIV_START - - stream = fopen(filename, "r"); - - PRIV_END - - if (stream == NULL) - perr("Cannot open input file"); - - if ((fd_in = dup(fileno(stream))) < 0) - perr("Error duplicating input file descriptor"); - - if (fstat(fd_in, &buf) == -1) - perr("Error in fstat of input file descriptor"); - - if (lstat(filename, &lbuf) == -1) - perr("Error in fstat of input file"); - - if (S_ISLNK(lbuf.st_mode)) - perr("Symbolic link encountered in job %8lu (%.500s) - aborting", - jobno, filename); - - if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || - (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || - (lbuf.st_size != buf.st_size)) - perr("Somebody changed files from under us for job %8lu (%.500s) - " - "aborting", jobno, filename); - - if (buf.st_nlink > 2) { - perr("Somebody is trying to run a linked script for job %8lu (%.500s)", - jobno, filename); - } - if ((fflags = fcntl(fd_in, F_GETFD)) < 0) - perr("Error in fcntl"); - - fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); - - /* - * If the spool directory is mounted via NFS `atd' isn't able to - * read from the job file and will bump out here. The file is - * opened as "root" but it is read as "daemon" which fails over - * NFS and works with local file systems. It's not clear where - * the bug is located. -Joey - */ - sprintf(fmt, "#!/bin/sh\n# atrun uid=%%d gid=%%d\n# mail %%%ds %%d", - mailsize ); - - if (fscanf(stream, fmt, - &nuid, &ngid, mailname, &send_mail) != 4) - pabort("File %.500s is in wrong format - aborting", - filename); - - if (mailname[0] == '-') - pabort("illegal mail name %.300s in job %8lu (%.300s)", mailname, - jobno, filename); - - if (nuid != uid) - pabort("Job %8lu (%.500s) - userid %d does not match file uid %d", - jobno, filename, nuid, uid); - - /* We are now committed to executing this script. Unlink the - * original. - */ - - unlink(filename); - - fclose(stream); - if (chdir(ATSPOOL_DIR) < 0) - perr("Cannot chdir to " ATSPOOL_DIR); - - /* Create a file to hold the output of the job we are about to run. - * Write the mail header. Complain in case - */ - - if (unlink(filename) != -1) { - syslog(LOG_WARNING,"Warning: for duplicate output file for %.100s (dead job?)", - filename); - } - - if ((fd_out = open(filename, - O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) - perr("Cannot create output file"); - PRIV_START - if (fchown(fd_out, uid, ngid) == -1) - syslog(LOG_WARNING, "Warning: could not change owner of output file for job %li to %i:%i: %s", - jobno, uid, ngid, strerror(errno)); - PRIV_END - - write_string(fd_out, "Subject: Output from your job "); - write_string(fd_out, jobbuf); - write_string(fd_out, "\nTo: "); - write_string(fd_out, mailname); - write_string(fd_out, "\n\n"); - fstat(fd_out, &buf); - size = buf.st_size; - -#ifdef WITH_PAM - AT_START_PAM; - AT_OPEN_PAM_SESSION; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - pid = fork(); - if (pid < 0) - perr("Error in fork"); - - else if (pid == 0) { - char *nul = NULL; - char **nenvp = &nul; - char **pam_envp=0L; - - PRIV_START -#ifdef WITH_PAM - pam_envp = pam_getenvlist(pamh); - if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) ) - nenvp = pam_envp; -#endif - /* Set up things for the child; we want standard input from the - * input file, and standard output and error sent to our output file. - */ - if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0) - perr("Error in lseek"); - - if (dup2(fd_in, STDIN_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDOUT_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDERR_FILENO) < 0) - perr("Error in I/O redirection"); - - close(fd_in); - close(fd_out); - - nice((tolower((int) queue) - 'a' + 1) * 2); - -#ifdef WITH_SELINUX - if (selinux_enabled > 0) { - if (set_selinux_context(pentry->pw_name, filename) < 0) - perr("SELinux Failed to set context\n"); - } -#endif - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(ngid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir("/"); - - execle("/bin/sh", "sh", (char *) NULL, nenvp); - perr("Exec failed for /bin/sh"); - /* perr exits, the PRIV_END is just for nice form */ - PRIV_END - } - /* We're the parent. Let's wait. - */ - close(fd_in); - - /* We inherited the master's SIGCHLD handler, which does a - non-blocking waitpid. So this blocking one will eventually - return with an ECHILD error. - */ - waitpid(pid, (int *) NULL, 0); - - /* Send mail. Unlink the output file after opening it, so it - * doesn't hang around after the run. - */ - fstat(fd_out, &buf); - lseek(fd_out, 0, SEEK_SET); - if (dup2(fd_out, STDIN_FILENO) < 0) - perr("Could not use jobfile as standard input."); - - /* some sendmail implementations are confused if stdout, stderr are - * not available, so let them point to /dev/null - */ - if ((fd_in = open("/dev/null", O_WRONLY)) < 0) - perr("Could not open /dev/null."); - if (dup2(fd_in, STDOUT_FILENO) < 0) - perr("Could not use /dev/null as standard output."); - if (dup2(fd_in, STDERR_FILENO) < 0) - perr("Could not use /dev/null as standard error."); - if (fd_in != STDOUT_FILENO && fd_in != STDERR_FILENO) - close(fd_in); - - if (unlink(filename) == -1) - syslog(LOG_WARNING, "Warning: removing output file for job %li failed: %s", - jobno, strerror(errno)); - - /* The job is now finished. We can delete its input file. - */ - chdir(ATJOB_DIR); - unlink(newname); - free(newname); - -#ifdef ATD_MAIL_PROGRAM - if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { - int mail_pid = -1; - - mail_pid = fork(); - - if ( mail_pid == 0 ) { - PRIV_START - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(gid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir ("/"); - -#if defined(SENDMAIL) - execl(SENDMAIL, "sendmail", "-i", mailname, (char *) NULL); -#else -#error "No mail command specified." -#endif - perr("Exec failed for mail command"); - - PRIV_END - } - else if ( mail_pid == -1 ) { - syslog(LOG_ERR, "fork of mailer failed: %m"); - } - /* Parent */ - waitpid(mail_pid, (int *) NULL, 0); - } - -#ifdef WITH_PAM - AT_CLOSE_PAM; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif -#endif - exit(EXIT_SUCCESS); -} - -static time_t -run_loop() -{ - DIR *spool; - struct dirent *dirent; - struct stat buf; - unsigned long ctm; - unsigned long jobno; - char queue; - char batch_queue = '\0'; - time_t run_time, next_job; - char batch_name[] = "z2345678901234"; - char lock_name[] = "z2345678901234"; - uid_t batch_uid; - gid_t batch_gid; - int run_batch; - static time_t next_batch = 0; - double currlavg[3]; - - /* Main loop. Open spool directory for reading and look over all the - * files in there. If the filename indicates that the job should be run, - * run a function which sets its user and group id to that of the files - * and execs a /bin/sh, which executes the shell. The function will - * then remove the script (hopefully). - * - * Also, pick the oldest batch job to run, at most one per run of - * the main loop. - */ - - next_job = now + CHECK_INTERVAL; - if (next_batch == 0) - next_batch = now; - - /* To avoid spinning up the disk unnecessarily, stat the directory and - * return immediately if it hasn't changed since the last time we woke - * up. - */ - - if (stat(".", &buf) == -1) - perr("Cannot stat " ATJOB_DIR); - - if (nothing_to_do && buf.st_mtime <= last_chg) - return next_job; - last_chg = buf.st_mtime; - - if ((spool = opendir(".")) == NULL) - perr("Cannot read " ATJOB_DIR); - - run_batch = 0; - nothing_to_do = 1; - - batch_uid = (uid_t) - 1; - batch_gid = (gid_t) - 1; - - while ((dirent = readdir(spool)) != NULL) { - - /* Avoid the stat if this doesn't look like a job file */ - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - /* Chances are a '=' file has been deleted from under us. - * Ignore. - */ - if (stat(dirent->d_name, &buf) != 0) - continue; - - if (!S_ISREG(buf.st_mode)) - continue; - - /* We don't want files which at(1) hasn't yet marked executable. */ - if (!(buf.st_mode & S_IXUSR)) { - nothing_to_do = 0; /* it will probably become executable soon */ - continue; - } - - run_time = (time_t) ctm *60; - - /* Skip lock files */ - if (queue == '=') { - /* FIXME: calhariz */ - /* I think the following code is broken, but commenting - may haven unknow side effects. Make a release and see - in the wild how it works. For more information see: - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818508/* - - /* if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) { */ - /* /\* Remove stale lockfile FIXME: lock the lockfile, if you fail, it's still in use. *\/ */ - /* unlink(dirent->d_name); */ - /* } */ - continue; - } - /* Skip any other file types which may have been invented in - * the meantime. - */ - if (!(isupper(queue) || islower(queue))) { - continue; - } - /* Is the file already locked? - */ - if (buf.st_nlink > 1) { - if (run_time + CHECK_INTERVAL <= now) { - - /* Something went wrong the last time this was executed. - * Let's remove the lockfile and reschedule. - */ - strncpy(lock_name, dirent->d_name, sizeof(lock_name)); - lock_name[sizeof(lock_name)-1] = '\0'; - lock_name[0] = '='; - unlink(lock_name); - next_job = now; - nothing_to_do = 0; - } - continue; - } - - /* If we got here, then there are jobs of some kind waiting. - * We could try to be smarter and leave nothing_to_do set if - * we end up processing all the jobs, but that's risky (run_file - * might fail and expect the job to be rescheduled), and it doesn't - * gain us much. */ - nothing_to_do = 0; - - /* There's a job for later. Note its execution time if it's - * the earliest so far. - */ - if (run_time > now) { - if (next_job > run_time) { - next_job = run_time; - } - continue; - } - - if (isbatch(queue)) { - - /* We could potentially run this batch job. If it's scheduled - * at a higher priority than anything before, keep its - * filename. - */ - run_batch++; - if (strcmp(batch_name, dirent->d_name) > 0) { - strncpy(batch_name, dirent->d_name, sizeof(batch_name)); - batch_name[sizeof(batch_name)-1] = '\0'; - batch_uid = buf.st_uid; - batch_gid = buf.st_gid; - batch_queue = queue; - } - } - else { - if (run_time <= now) { - run_file(dirent->d_name, buf.st_uid, buf.st_gid); - } - } - } - closedir(spool); - /* run the single batch file, if any - */ - if (run_batch && (next_batch <= now)) { - next_batch = now + batch_interval; -#ifdef GETLOADAVG_PRIVILEGED - START_PRIV -#endif - if (getloadavg(currlavg, 1) < 1) { - currlavg[0] = 0.0; - } -#ifdef GETLOADAVG_PRIVILEGED - END_PRIV -#endif - if (currlavg[0] < load_avg) { - run_file(batch_name, batch_uid, batch_gid); - run_batch--; - } - } - if (run_batch && (next_batch < next_job)) { - nothing_to_do = 0; - next_job = next_batch; - } - return next_job; -} - -/* Global functions */ - -int -main(int argc, char *argv[]) -{ -/* Browse through ATJOB_DIR, checking all the jobfiles whether they should - * be executed and or deleted. The queue is coded into the first byte of - * the job filename, the next 5 bytes encode the serial number in hex, and - * the final 8 bytes encode the date (minutes since Eon) in hex. A file - * which has not been executed yet is denoted by its execute - bit set. - * For those files which are to be executed, run_file() is called, which forks - * off a child which takes care of I/O redirection, forks off another child - * for execution and yet another one, optionally, for sending mail. - * Files which already have run are removed during the next invocation. - */ - int c; - time_t next_invocation; - struct sigaction act; - struct passwd *pwe; - struct group *ge; - -#ifdef WITH_SELINUX - selinux_enabled=is_selinux_enabled(); - - if (selinux_enabled) { - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) selinux_log_callback); - } -#endif - -/* We don't need root privileges all the time; running under uid and gid - * daemon is fine. - */ - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - RELINQUISH_PRIVS_ROOT(daemon_uid, daemon_gid) - -#ifndef LOG_CRON -#define LOG_CRON LOG_DAEMON -#endif - - openlog("atd", LOG_PID, LOG_CRON); - - opterr = 0; - errno = 0; - run_as_daemon = 1; - batch_interval = BATCH_INTERVAL_DEFAULT; - - while ((c = getopt(argc, argv, "sdl:b:f")) != EOF) { - switch (c) { - case 'l': - if (sscanf(optarg, "%lf", &load_avg) != 1) - pabort("garbled option -l"); - if (load_avg <= 0.) - load_avg = LOADAVG_MX; - break; - - case 'b': - if (sscanf(optarg, "%ud", &batch_interval) != 1) - pabort("garbled option -b"); - break; - case 'd': - daemon_debug++; - daemon_foreground++; - break; - - case 'f': - daemon_foreground++; - break; - - case 's': - run_as_daemon = 0; - break; - - case '?': - pabort("unknown option"); - break; - - default: - pabort("idiotic option - aborted"); - break; - } - } - - namep = argv[0]; - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if (optind < argc) - pabort("non-option arguments - not allowed"); - - sigaction(SIGCHLD, NULL, &act); - act.sa_handler = release_zombie; - act.sa_flags = SA_NOCLDSTOP; - sigaction(SIGCHLD, &act, NULL); - - if (!run_as_daemon) { - now = time(NULL); - run_loop(); - exit(EXIT_SUCCESS); - } - /* Main loop. Let's sleep for a specified interval, - * or until the next job is scheduled, or until we get signaled. - * After any of these events, we rescan the queue. - * A signal handler setting term_signal will make sure there's - * a clean exit. - */ - - sigaction(SIGHUP, NULL, &act); - act.sa_handler = sdummy; - sigaction(SIGHUP, &act, NULL); - - sigaction(SIGTERM, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGTERM, &act, NULL); - - sigaction(SIGINT, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGINT, &act, NULL); - - daemon_setup(); - - do { - now = time(NULL); - next_invocation = run_loop(); - if (next_invocation > now) { - sleep(next_invocation - now); - } - } while (!term_signal); - daemon_cleanup(); - exit(EXIT_SUCCESS); -} diff --git a/atd.c.nit b/atd.c.nit deleted file mode 100644 index 031aae2..0000000 --- a/atd.c.nit +++ /dev/null @@ -1,918 +0,0 @@ -/* - * atd.c - run jobs queued by at; run with root privileges. - * Copyright (C) 1993, 1994, 1996 Thomas Koenig - * Copyright (c) 2002, 2005 Ryan Murray - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif HAVE_SYS_FCNTL_H - -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_GETOPT_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "privs.h" -#include "daemon.h" - -#ifndef HAVE_GETLOADAVG -#include "getloadavg.h" -#endif - -#ifdef WITH_SELINUX -#include -#include -int selinux_enabled = 0; -#endif - -/* Macros */ - -#ifndef LOG_ATD -#define LOG_ATD LOG_DAEMON -#endif - -#define BATCH_INTERVAL_DEFAULT 60 -#define CHECK_INTERVAL 3600 - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -static char *namep; -static double load_avg = LOADAVG_MX; -static time_t now; -static time_t last_chg; -static int nothing_to_do; -unsigned int batch_interval; -static int run_as_daemon = 0; - -static volatile sig_atomic_t term_signal = 0; - -#ifdef WITH_PAM -#include - -static pam_handle_t *pamh = NULL; - -static const struct pam_conv conv = { - NULL -}; - -#endif /* WITH_PAM */ - -/* Signal handlers */ -RETSIGTYPE -set_term(int dummy) -{ - term_signal = 1; - return; -} - -RETSIGTYPE -sdummy(int dummy) -{ - /* Empty signal handler */ - nothing_to_do = 0; - return; -} - -/* SIGCHLD handler - discards completion status of children */ -RETSIGTYPE -release_zombie(int dummy) -{ - int status; - pid_t pid; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { -#ifdef DEBUG_ZOMBIE - if (WIFEXITED(status)) - syslog(LOG_INFO, "pid %ld exited with status %d.", pid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - syslog(LOG_NOTICE, "pid %ld killed with signal %d.", pid, WTERMSIG(status)); - else if (WIFSTOPPED(status)) - syslog(LOG_NOTICE, "pid %ld stopped with signal %d.", pid, WSTOPSIG(status)); - else - syslog(LOG_WARNING, "pid %ld unknown reason for SIGCHLD", pid); -#endif - } - return; -} - - -/* Local functions */ - -static int -write_string(int fd, const char *a) -{ - return write(fd, a, strlen(a)); -} - -static int -isbatch(char queue) -{ - return isupper(queue) || (queue == 'b'); -} - -#undef DEBUG_FORK -#ifdef DEBUG_FORK -static pid_t -myfork() -{ - pid_t res; - res = fork(); - if (res == 0) - kill(getpid(), SIGSTOP); - return res; -} - -#define fork myfork -#endif - -#ifdef WITH_SELINUX -static int -set_selinux_context(const char *name, const char *filename) { - security_context_t user_context = NULL; - security_context_t file_context = NULL; - int retval = 0; - char *seuser = NULL; - char *level = NULL; - - if (getseuserbyname(name, &seuser, &level) == 0) { - retval = get_default_context_with_level(seuser, level, NULL, &user_context); - free(seuser); - free(level); - if (retval < 0) { - lerr("get_default_context_with_level: couldn't get security context for user %s", name); - retval = -1; - goto err; - } - } - - /* - * Since crontab files are not directly executed, - * crond must ensure that the crontab file has - * a context that is appropriate for the context of - * the user cron job. It performs an entrypoint - * permission check for this purpose. - */ - if (fgetfilecon(STDIN_FILENO, &file_context) < 0) { - lerr("fgetfilecon FAILED %s", filename); - retval = -1; - goto err; - } - - retval = selinux_check_access(user_context, file_context, "file", "entrypoint", NULL); - freecon(file_context); - if (retval < 0) { - lerr("Not allowed to set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } - if (setexeccon(user_context) < 0) { - lerr("Could not set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } -err: - if (retval < 0 && security_getenforce() != 1) - retval = 0; - if (user_context) - freecon(user_context); - return retval; -} - -static int -selinux_log_callback (int type, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsyslog (LOG_ERR, fmt, ap); - va_end(ap); - return 0; -} - -#endif - -static void -run_file(const char *filename, uid_t uid, gid_t gid) -{ -/* Run a file by by spawning off a process which redirects I/O, - * spawns a subshell, then waits for it to complete and sends - * mail to the user. - */ - pid_t pid; - int fd_out, fd_in; - char jobbuf[9]; - char *mailname = NULL; - int mailsize = 128; - char *newname; - FILE *stream; - int send_mail = 0; - struct stat buf, lbuf; - off_t size; - struct passwd *pentry; - int fflags; - int nuid; - int ngid; - char queue; - char fmt[64]; - unsigned long jobno; - int rc; -#ifdef WITH_PAM - int retcode; -#endif - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - sscanf(filename, "%c%5lx", &queue, &jobno); - if ((mailname = malloc(mailsize+1)) == NULL) - pabort("Job %8lu : out of virtual memory", jobno); - - sprintf(jobbuf, "%8lu", jobno); - - if ((newname = strdup(filename)) == 0) - pabort("Job %8lu : out of virtual memory", jobno); - newname[0] = '='; - - /* We try to make a hard link to lock the file. If we fail, then - * somebody else has already locked or deleted it (a second atd?); log the - * fact and return. - */ - PRIV_START - rc = link(filename, newname); - PRIV_END - if (rc == -1) { - syslog(LOG_WARNING, "could not lock job %lu: %m", jobno); - free(mailname); - free(newname); - return; - } - /* If something goes wrong between here and the unlink() call, - * the job gets restarted as soon as the "=" entry is cleared - * by the main atd loop. - */ - - pid = fork(); - if (pid == -1) - perr("Cannot fork"); - - else if (pid != 0) { - free(mailname); - free(newname); - return; - } - /* Let's see who we mail to. Hopefully, we can read it from - * the command file; if not, send it to the owner, or, failing that, - * to root. - */ - - pentry = getpwuid(uid); - if (pentry == NULL) { - pabort("Userid %lu not found - aborting job %8lu (%.500s)", - (unsigned long) uid, jobno, filename); - } - PRIV_START - - stream = fopen(filename, "r"); - - PRIV_END - - if (stream == NULL) - perr("Cannot open input file"); - - if ((fd_in = dup(fileno(stream))) < 0) - perr("Error duplicating input file descriptor"); - - if (fstat(fd_in, &buf) == -1) - perr("Error in fstat of input file descriptor"); - - if (lstat(filename, &lbuf) == -1) - perr("Error in fstat of input file"); - - if (S_ISLNK(lbuf.st_mode)) - perr("Symbolic link encountered in job %8lu (%.500s) - aborting", - jobno, filename); - - if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || - (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || - (lbuf.st_size != buf.st_size)) - perr("Somebody changed files from under us for job %8lu (%.500s) - " - "aborting", jobno, filename); - - if (buf.st_nlink > 2) { - perr("Somebody is trying to run a linked script for job %8lu (%.500s)", - jobno, filename); - } - if ((fflags = fcntl(fd_in, F_GETFD)) < 0) - perr("Error in fcntl"); - - fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); - - /* - * If the spool directory is mounted via NFS `atd' isn't able to - * read from the job file and will bump out here. The file is - * opened as "root" but it is read as "daemon" which fails over - * NFS and works with local file systems. It's not clear where - * the bug is located. -Joey - */ - sprintf(fmt, "#!/bin/sh\n# atrun uid=%%d gid=%%d\n# mail %%%ds %%d", - mailsize ); - - if (fscanf(stream, fmt, - &nuid, &ngid, mailname, &send_mail) != 4) - pabort("File %.500s is in wrong format - aborting", - filename); - - if (mailname[0] == '-') - pabort("illegal mail name %.300s in job %8lu (%.300s)", mailname, - jobno, filename); - - if (nuid != uid) - pabort("Job %8lu (%.500s) - userid %d does not match file uid %d", - jobno, filename, nuid, uid); - - /* We are now committed to executing this script. Unlink the - * original. - */ - - unlink(filename); - - fclose(stream); - if (chdir(ATSPOOL_DIR) < 0) - perr("Cannot chdir to " ATSPOOL_DIR); - - /* Create a file to hold the output of the job we are about to run. - * Write the mail header. Complain in case - */ - - if (unlink(filename) != -1) { - syslog(LOG_WARNING,"Warning: for duplicate output file for %.100s (dead job?)", - filename); - } - - if ((fd_out = open(filename, - O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) - perr("Cannot create output file"); - PRIV_START - if (fchown(fd_out, uid, ngid) == -1) - syslog(LOG_WARNING, "Warning: could not change owner of output file for job %li to %i:%i: %s", - jobno, uid, ngid, strerror(errno)); - PRIV_END - - write_string(fd_out, "Subject: Output from your job "); - write_string(fd_out, jobbuf); - write_string(fd_out, "\nTo: "); - write_string(fd_out, mailname); - write_string(fd_out, "\n\n"); - fstat(fd_out, &buf); - size = buf.st_size; - -#ifdef WITH_PAM - AT_START_PAM; - AT_OPEN_PAM_SESSION; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - pid = fork(); - if (pid < 0) - perr("Error in fork"); - - else if (pid == 0) { - char *nul = NULL; - char **nenvp = &nul; - char **pam_envp=0L; - - PRIV_START -#ifdef WITH_PAM - pam_envp = pam_getenvlist(pamh); - if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) ) - nenvp = pam_envp; -#endif - /* Set up things for the child; we want standard input from the - * input file, and standard output and error sent to our output file. - */ - if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0) - perr("Error in lseek"); - - if (dup2(fd_in, STDIN_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDOUT_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDERR_FILENO) < 0) - perr("Error in I/O redirection"); - - close(fd_in); - close(fd_out); - - nice((tolower((int) queue) - 'a' + 1) * 2); - -#ifdef WITH_SELINUX - if (selinux_enabled > 0) { - if (set_selinux_context(pentry->pw_name, filename) < 0) - perr("SELinux Failed to set context\n"); - } -#endif - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(ngid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - chdir("/"); - - execle("/bin/sh", "sh", (char *) NULL, nenvp); - perr("Exec failed for /bin/sh"); - /* perr exits, the PRIV_END is just for nice form */ - PRIV_END - } - /* We're the parent. Let's wait. - */ - close(fd_in); - - /* We inherited the master's SIGCHLD handler, which does a - non-blocking waitpid. So this blocking one will eventually - return with an ECHILD error. - */ - waitpid(pid, (int *) NULL, 0); - - /* Send mail. Unlink the output file after opening it, so it - * doesn't hang around after the run. - */ - fstat(fd_out, &buf); - lseek(fd_out, 0, SEEK_SET); - if (dup2(fd_out, STDIN_FILENO) < 0) - perr("Could not use jobfile as standard input."); - - /* some sendmail implementations are confused if stdout, stderr are - * not available, so let them point to /dev/null - */ - if ((fd_in = open("/dev/null", O_WRONLY)) < 0) - perr("Could not open /dev/null."); - if (dup2(fd_in, STDOUT_FILENO) < 0) - perr("Could not use /dev/null as standard output."); - if (dup2(fd_in, STDERR_FILENO) < 0) - perr("Could not use /dev/null as standard error."); - if (fd_in != STDOUT_FILENO && fd_in != STDERR_FILENO) - close(fd_in); - - if (unlink(filename) == -1) - syslog(LOG_WARNING, "Warning: removing output file for job %li failed: %s", - jobno, strerror(errno)); - - /* The job is now finished. We can delete its input file. - */ - chdir(ATJOB_DIR); - unlink(newname); - free(newname); - -#ifdef ATD_MAIL_PROGRAM - if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { - int mail_pid = -1; - - mail_pid = fork(); - - if ( mail_pid == 0 ) { - PRIV_START - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(gid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - chdir ("/"); - -#if defined(SENDMAIL) - execl(SENDMAIL, "sendmail", "-i", mailname, (char *) NULL); -#else -#error "No mail command specified." -#endif - perr("Exec failed for mail command"); - - PRIV_END - } - else if ( mail_pid == -1 ) { - syslog(LOG_ERR, "fork of mailer failed: %m"); - } - /* Parent */ - waitpid(mail_pid, (int *) NULL, 0); - } - -#ifdef WITH_PAM - AT_CLOSE_PAM; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif -#endif - exit(EXIT_SUCCESS); -} - -static time_t -run_loop() -{ - DIR *spool; - struct dirent *dirent; - struct stat buf; - unsigned long ctm; - unsigned long jobno; - char queue; - char batch_queue = '\0'; - time_t run_time, next_job; - char batch_name[] = "z2345678901234"; - char lock_name[] = "z2345678901234"; - uid_t batch_uid; - gid_t batch_gid; - int run_batch; - static time_t next_batch = 0; - double currlavg[3]; - - /* Main loop. Open spool directory for reading and look over all the - * files in there. If the filename indicates that the job should be run, - * run a function which sets its user and group id to that of the files - * and execs a /bin/sh, which executes the shell. The function will - * then remove the script (hopefully). - * - * Also, pick the oldest batch job to run, at most one per run of - * the main loop. - */ - - next_job = now + CHECK_INTERVAL; - if (next_batch == 0) - next_batch = now; - - /* To avoid spinning up the disk unnecessarily, stat the directory and - * return immediately if it hasn't changed since the last time we woke - * up. - */ - - if (stat(".", &buf) == -1) - perr("Cannot stat " ATJOB_DIR); - - if (nothing_to_do && buf.st_mtime <= last_chg) - return next_job; - last_chg = buf.st_mtime; - - if ((spool = opendir(".")) == NULL) - perr("Cannot read " ATJOB_DIR); - - run_batch = 0; - nothing_to_do = 1; - - batch_uid = (uid_t) - 1; - batch_gid = (gid_t) - 1; - - while ((dirent = readdir(spool)) != NULL) { - - /* Avoid the stat if this doesn't look like a job file */ - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - /* Chances are a '=' file has been deleted from under us. - * Ignore. - */ - if (stat(dirent->d_name, &buf) != 0) - continue; - - if (!S_ISREG(buf.st_mode)) - continue; - - /* We don't want files which at(1) hasn't yet marked executable. */ - if (!(buf.st_mode & S_IXUSR)) { - nothing_to_do = 0; /* it will probably become executable soon */ - continue; - } - - run_time = (time_t) ctm *60; - - /* Skip lock files */ - if (queue == '=') { - /* FIXME: calhariz */ - /* I think the following code is broken, but commenting - may haven unknow side effects. Make a release and see - in the wild how it works. For more information see: - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818508/* - - /* if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) { */ - /* /\* Remove stale lockfile FIXME: lock the lockfile, if you fail, it's still in use. *\/ */ - /* unlink(dirent->d_name); */ - /* } */ - continue; - } - /* Skip any other file types which may have been invented in - * the meantime. - */ - if (!(isupper(queue) || islower(queue))) { - continue; - } - /* Is the file already locked? - */ - if (buf.st_nlink > 1) { - if (run_time + CHECK_INTERVAL <= now) { - - /* Something went wrong the last time this was executed. - * Let's remove the lockfile and reschedule. - */ - strncpy(lock_name, dirent->d_name, sizeof(lock_name)); - lock_name[0] = '='; - unlink(lock_name); - next_job = now; - nothing_to_do = 0; - } - continue; - } - - /* If we got here, then there are jobs of some kind waiting. - * We could try to be smarter and leave nothing_to_do set if - * we end up processing all the jobs, but that's risky (run_file - * might fail and expect the job to be rescheduled), and it doesn't - * gain us much. */ - nothing_to_do = 0; - - /* There's a job for later. Note its execution time if it's - * the earliest so far. - */ - if (run_time > now) { - if (next_job > run_time) { - next_job = run_time; - } - continue; - } - - if (isbatch(queue)) { - - /* We could potentially run this batch job. If it's scheduled - * at a higher priority than anything before, keep its - * filename. - */ - run_batch++; - if (strcmp(batch_name, dirent->d_name) > 0) { - strncpy(batch_name, dirent->d_name, sizeof(batch_name)); - batch_uid = buf.st_uid; - batch_gid = buf.st_gid; - batch_queue = queue; - } - } - else { - if (run_time <= now) { - run_file(dirent->d_name, buf.st_uid, buf.st_gid); - } - } - } - closedir(spool); - /* run the single batch file, if any - */ - if (run_batch && (next_batch <= now)) { - next_batch = now + batch_interval; -#ifdef GETLOADAVG_PRIVILEGED - START_PRIV -#endif - if (getloadavg(currlavg, 1) < 1) { - currlavg[0] = 0.0; - } -#ifdef GETLOADAVG_PRIVILEGED - END_PRIV -#endif - if (currlavg[0] < load_avg) { - run_file(batch_name, batch_uid, batch_gid); - run_batch--; - } - } - if (run_batch && (next_batch < next_job)) { - nothing_to_do = 0; - next_job = next_batch; - } - return next_job; -} - -/* Global functions */ - -int -main(int argc, char *argv[]) -{ -/* Browse through ATJOB_DIR, checking all the jobfiles whether they should - * be executed and or deleted. The queue is coded into the first byte of - * the job filename, the next 5 bytes encode the serial number in hex, and - * the final 8 bytes encode the date (minutes since Eon) in hex. A file - * which has not been executed yet is denoted by its execute - bit set. - * For those files which are to be executed, run_file() is called, which forks - * off a child which takes care of I/O redirection, forks off another child - * for execution and yet another one, optionally, for sending mail. - * Files which already have run are removed during the next invocation. - */ - int c; - time_t next_invocation; - struct sigaction act; - struct passwd *pwe; - struct group *ge; - -#ifdef WITH_SELINUX - selinux_enabled=is_selinux_enabled(); - - if (selinux_enabled) { - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) selinux_log_callback); - } -#endif - -/* We don't need root privileges all the time; running under uid and gid - * daemon is fine. - */ - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - RELINQUISH_PRIVS_ROOT(daemon_uid, daemon_gid) - -#ifndef LOG_CRON -#define LOG_CRON LOG_DAEMON -#endif - - openlog("atd", LOG_PID, LOG_CRON); - - opterr = 0; - errno = 0; - run_as_daemon = 1; - batch_interval = BATCH_INTERVAL_DEFAULT; - - while ((c = getopt(argc, argv, "sdl:b:f")) != EOF) { - switch (c) { - case 'l': - if (sscanf(optarg, "%lf", &load_avg) != 1) - pabort("garbled option -l"); - if (load_avg <= 0.) - load_avg = LOADAVG_MX; - break; - - case 'b': - if (sscanf(optarg, "%ud", &batch_interval) != 1) - pabort("garbled option -b"); - break; - case 'd': - daemon_debug++; - daemon_foreground++; - break; - - case 'f': - daemon_foreground++; - break; - - case 's': - run_as_daemon = 0; - break; - - case '?': - pabort("unknown option"); - break; - - default: - pabort("idiotic option - aborted"); - break; - } - } - - namep = argv[0]; - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if (optind < argc) - pabort("non-option arguments - not allowed"); - - sigaction(SIGCHLD, NULL, &act); - act.sa_handler = release_zombie; - act.sa_flags = SA_NOCLDSTOP; - sigaction(SIGCHLD, &act, NULL); - - if (!run_as_daemon) { - now = time(NULL); - run_loop(); - exit(EXIT_SUCCESS); - } - /* Main loop. Let's sleep for a specified interval, - * or until the next job is scheduled, or until we get signaled. - * After any of these events, we rescan the queue. - * A signal handler setting term_signal will make sure there's - * a clean exit. - */ - - sigaction(SIGHUP, NULL, &act); - act.sa_handler = sdummy; - sigaction(SIGHUP, &act, NULL); - - sigaction(SIGTERM, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGTERM, &act, NULL); - - sigaction(SIGINT, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGINT, &act, NULL); - - daemon_setup(); - - do { - now = time(NULL); - next_invocation = run_loop(); - if (next_invocation > now) { - sleep(next_invocation - now); - } - } while (!term_signal); - daemon_cleanup(); - exit(EXIT_SUCCESS); -} diff --git a/atd.c.noabort b/atd.c.noabort deleted file mode 100644 index 7021d26..0000000 --- a/atd.c.noabort +++ /dev/null @@ -1,1010 +0,0 @@ -/* - * atd.c - run jobs queued by at; run with root privileges. - * Copyright (C) 1993, 1994, 1996 Thomas Koenig - * Copyright (c) 2002, 2005 Ryan Murray - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif HAVE_SYS_FCNTL_H - -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_GETOPT_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "privs.h" -#include "daemon.h" - -#ifndef HAVE_GETLOADAVG -#include "getloadavg.h" -#endif - -#ifdef WITH_SELINUX -#include -#include -int selinux_enabled = 0; -#endif - -/* Macros */ - -#ifndef LOG_ATD -#define LOG_ATD LOG_DAEMON -#endif - -#define BATCH_INTERVAL_DEFAULT 60 -#define CHECK_INTERVAL 3600 - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -static char *namep; -static double load_avg = LOADAVG_MX; -static time_t now; -static time_t last_chg; -static int nothing_to_do; -unsigned int batch_interval; -static int run_as_daemon = 0; -static int mail_with_hostname = 0; - -static volatile sig_atomic_t term_signal = 0; - -#ifdef WITH_PAM -#include - -static pam_handle_t *pamh = NULL; - -static const struct pam_conv conv = { - NULL -}; - -#endif /* WITH_PAM */ - -/* Signal handlers */ -RETSIGTYPE -set_term(int dummy) -{ - term_signal = 1; - return; -} - -RETSIGTYPE -sdummy(int dummy) -{ - /* Empty signal handler */ - nothing_to_do = 0; - return; -} - -/* SIGCHLD handler - discards completion status of children */ -RETSIGTYPE -release_zombie(int dummy) -{ - int status; - pid_t pid; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { -#ifdef DEBUG_ZOMBIE - if (WIFEXITED(status)) - syslog(LOG_INFO, "pid %ld exited with status %d.", pid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - syslog(LOG_NOTICE, "pid %ld killed with signal %d.", pid, WTERMSIG(status)); - else if (WIFSTOPPED(status)) - syslog(LOG_NOTICE, "pid %ld stopped with signal %d.", pid, WSTOPSIG(status)); - else - syslog(LOG_WARNING, "pid %ld unknown reason for SIGCHLD", pid); -#endif - } - return; -} - - -/* Local functions */ - -static int -write_string(int fd, const char *a) -{ - return write(fd, a, strlen(a)); -} - -static int -isbatch(char queue) -{ - return isupper(queue) || (queue == 'b'); -} - -#undef DEBUG_FORK -#ifdef DEBUG_FORK -static pid_t -myfork() -{ - pid_t res; - res = fork(); - if (res == 0) - kill(getpid(), SIGSTOP); - return res; -} - -#define fork myfork -#endif -#undef ATD_MAIL_PROGRAM -#undef ATD_MAIL_NAME -#if defined(SENDMAIL) -#define ATD_MAIL_PROGRAM SENDMAIL -#define ATD_MAIL_NAME "sendmail" -#elif defined(MAILC) -#define ATD_MAIL_PROGRAM MAILC -#define ATD_MAIL_NAME "mail" -#elif defined(MAILX) -#define ATD_MAIL_PROGRAM MAILX -#define ATD_MAIL_NAME "mailx" -#endif - -#ifdef WITH_SELINUX -static int -set_selinux_context(const char *name, const char *filename) { - security_context_t user_context = NULL; - security_context_t file_context = NULL; - int retval = 0; - char *seuser = NULL; - char *level = NULL; - - if (getseuserbyname(name, &seuser, &level) == 0) { - retval = get_default_context_with_level(seuser, level, NULL, &user_context); - free(seuser); - free(level); - if (retval < 0) { - lerr("get_default_context_with_level: couldn't get security context for user %s", name); - retval = -1; - goto err; - } - } - - /* - * Since crontab files are not directly executed, - * crond must ensure that the crontab file has - * a context that is appropriate for the context of - * the user cron job. It performs an entrypoint - * permission check for this purpose. - */ - if (fgetfilecon(STDIN_FILENO, &file_context) < 0) { - lerr("fgetfilecon FAILED %s", filename); - retval = -1; - goto err; - } - - retval = selinux_check_access(user_context, file_context, "file", "entrypoint", NULL); - freecon(file_context); - if (retval < 0) { - lerr("Not allowed to set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } - if (setexeccon(user_context) < 0) { - lerr("Could not set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } -err: - if (retval < 0 && security_getenforce() != 1) - retval = 0; - if (user_context) - freecon(user_context); - return retval; -} - -static int -selinux_log_callback (int type, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsyslog (LOG_ERR, fmt, ap); - va_end(ap); - return 0; -} - -#endif - -static void -run_file(const char *filename, uid_t uid, gid_t gid) -{ -/* Run a file by by spawning off a process which redirects I/O, - * spawns a subshell, then waits for it to complete and sends - * mail to the user. - */ - pid_t pid; - int fd_out, fd_in; - char jobbuf[9]; - char *mailname = NULL; - int mailsize = 128; - char *newname; - FILE *stream; - int send_mail = 0; - struct stat buf, lbuf; - off_t size; - struct passwd *pentry; - int fflags; - int nuid; - int ngid; - char queue; - char fmt[64]; - unsigned long jobno; - int rc; - char hostbuf[MAXHOSTNAMELEN]; -#ifdef WITH_PAM - int retcode; -#endif - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - sscanf(filename, "%c%5lx", &queue, &jobno); - if ((mailname = malloc(mailsize+1)) == NULL) - pabort("Job %8lu : out of virtual memory", jobno); - - sprintf(jobbuf, "%8lu", jobno); - - if ((newname = strdup(filename)) == 0) - pabort("Job %8lu : out of virtual memory", jobno); - newname[0] = '='; - - /* We try to make a hard link to lock the file. If we fail, then - * somebody else has already locked or deleted it (a second atd?); log the - * fact and return. - */ - PRIV_START - rc = link(filename, newname); - PRIV_END - if (rc == -1) { - syslog(LOG_WARNING, "could not lock job %lu: %m", jobno); - free(mailname); - free(newname); - return; - } - /* If something goes wrong between here and the unlink() call, - * the job gets restarted as soon as the "=" entry is cleared - * by the main atd loop. - */ - - pid = fork(); - if (pid == -1) - perr("Cannot fork"); - - else if (pid != 0) { - free(mailname); - free(newname); - return; - } - - (void) setsid(); /* own session for process */ - - /* Let's see who we mail to. Hopefully, we can read it from - * the command file; if not, send it to the owner, or, failing that, - * to root. - */ - - pentry = getpwuid(uid); - if (pentry == NULL) { - pabort("Userid %lu not found - aborting job %8lu (%.500s)", - (unsigned long) uid, jobno, filename); - } - PRIV_START - - stream = fopen(filename, "r"); - - PRIV_END - - if (stream == NULL) - perr("Cannot open input file"); - - if ((fd_in = dup(fileno(stream))) < 0) - perr("Error duplicating input file descriptor"); - - if (fstat(fd_in, &buf) == -1) - perr("Error in fstat of input file descriptor"); - - if (lstat(filename, &lbuf) == -1) - perr("Error in fstat of input file"); - - if (S_ISLNK(lbuf.st_mode)) - perr("Symbolic link encountered in job %8lu (%.500s) - aborting", - jobno, filename); - - if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || - (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || - (lbuf.st_size != buf.st_size)) - perr("Somebody changed files from under us for job %8lu (%.500s) - " - "aborting", jobno, filename); - - if (buf.st_nlink > 2) { - perr("Somebody is trying to run a linked script for job %8lu (%.500s)", - jobno, filename); - } - if ((fflags = fcntl(fd_in, F_GETFD)) < 0) - perr("Error in fcntl"); - - fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); - - /* - * If the spool directory is mounted via NFS `atd' isn't able to - * read from the job file and will bump out here. The file is - * opened as "root" but it is read as "daemon" which fails over - * NFS and works with local file systems. It's not clear where - * the bug is located. -Joey - */ - sprintf(fmt, "#!/bin/sh\n# atrun uid=%%d gid=%%d\n# mail %%%ds %%d", - mailsize ); - - if (fscanf(stream, fmt, - &nuid, &ngid, mailname, &send_mail) != 4) - pabort("File %.500s is in wrong format - aborting", - filename); - - if (mailname[0] == '-') - pabort("illegal mail name %.300s in job %8lu (%.300s)", mailname, - jobno, filename); - - if (nuid != uid) - pabort("Job %8lu (%.500s) - userid %d does not match file uid %d", - jobno, filename, nuid, uid); - - /* We are now committed to executing this script. Unlink the - * original. - */ - - unlink(filename); - - fclose(stream); - if (chdir(ATSPOOL_DIR) < 0) - perr("Cannot chdir to " ATSPOOL_DIR); - - /* Create a file to hold the output of the job we are about to run. - * Write the mail header. Complain in case - */ - - if (unlink(filename) != -1) { - syslog(LOG_WARNING,"Warning: for duplicate output file for %.100s (dead job?)", - filename); - } - - if ((fd_out = open(filename, - O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) - perr("Cannot create output file"); - PRIV_START - if (fchown(fd_out, uid, ngid) == -1) - syslog(LOG_WARNING, "Warning: could not change owner of output file for job %li to %i:%i: %s", - jobno, uid, ngid, strerror(errno)); - PRIV_END - - write_string(fd_out, "Subject: Output from your job "); - write_string(fd_out, jobbuf); - if (mail_with_hostname > 0) { - gethostname(hostbuf, MAXHOSTNAMELEN-1); - write_string(fd_out, " "); - write_string(fd_out, hostbuf); - } - write_string(fd_out, "\nTo: "); - write_string(fd_out, mailname); - write_string(fd_out, "\n\n"); - fstat(fd_out, &buf); - size = buf.st_size; - -#ifdef WITH_PAM - AT_START_PAM; - AT_OPEN_PAM_SESSION; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - pid = fork(); - if (pid < 0) - perr("Error in fork"); - - else if (pid == 0) { - char *nul = NULL; - char **nenvp = &nul; - char **pam_envp=0L; - - PRIV_START -#ifdef WITH_PAM - pam_envp = pam_getenvlist(pamh); - if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) ) - nenvp = pam_envp; -#endif - /* Set up things for the child; we want standard input from the - * input file, and standard output and error sent to our output file. - */ - if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0) - perr("Error in lseek"); - - if (dup2(fd_in, STDIN_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDOUT_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDERR_FILENO) < 0) - perr("Error in I/O redirection"); - - close(fd_in); - close(fd_out); - - nice((tolower((int) queue) - 'a' + 1) * 2); - -#ifdef WITH_SELINUX - if (selinux_enabled > 0) { - if (set_selinux_context(pentry->pw_name, filename) < 0) - perr("SELinux Failed to set context\n"); - } -#endif - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(ngid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir("/"); - - execle("/bin/sh", "sh", (char *) NULL, nenvp); - perr("Exec failed for /bin/sh"); - /* perr exits, the PRIV_END is just for nice form */ - PRIV_END - } - /* We're the parent. Let's wait. - */ - close(fd_in); - - /* We inherited the master's SIGCHLD handler, which does a - non-blocking waitpid. So this blocking one will eventually - return with an ECHILD error. - */ - waitpid(pid, (int *) NULL, 0); - - /* Send mail. Unlink the output file after opening it, so it - * doesn't hang around after the run. - */ - fstat(fd_out, &buf); - lseek(fd_out, 0, SEEK_SET); - if (dup2(fd_out, STDIN_FILENO) < 0) - perr("Could not use jobfile as standard input."); - - /* some sendmail implementations are confused if stdout, stderr are - * not available, so let them point to /dev/null - */ - if ((fd_in = open("/dev/null", O_WRONLY)) < 0) - perr("Could not open /dev/null."); - if (dup2(fd_in, STDOUT_FILENO) < 0) - perr("Could not use /dev/null as standard output."); - if (dup2(fd_in, STDERR_FILENO) < 0) - perr("Could not use /dev/null as standard error."); - if (fd_in != STDOUT_FILENO && fd_in != STDERR_FILENO) - close(fd_in); - - if (unlink(filename) == -1) - syslog(LOG_WARNING, "Warning: removing output file for job %li failed: %s", - jobno, strerror(errno)); - - /* The job is now finished. We can delete its input file. - */ - chdir(ATJOB_DIR); - unlink(newname); - free(newname); - -#ifdef ATD_MAIL_PROGRAM - if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { - int mail_pid = -1; - - mail_pid = fork(); - - if ( mail_pid == 0 ) { - PRIV_START - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(gid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir ("/"); - -#if defined(SENDMAIL) - execl(SENDMAIL, "sendmail", "-i", mailname, (char *) NULL); -#else -#error "No mail command specified." -#endif - perr("Exec failed for mail command"); - - PRIV_END - } - else if ( mail_pid == -1 ) { - syslog(LOG_ERR, "fork of mailer failed: %m"); - } - /* Parent */ - waitpid(mail_pid, (int *) NULL, 0); - } - -#ifdef WITH_PAM - AT_CLOSE_PAM; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif -#endif - exit(EXIT_SUCCESS); -} - -static time_t -run_loop() -{ - DIR *spool; - struct dirent *dirent; - struct stat buf; - unsigned long ctm; - unsigned long jobno; - char queue; - char batch_queue = '\0'; - time_t run_time, next_job; - char batch_name[] = "z2345678901234"; - char lock_name[] = "z2345678901234"; - uid_t batch_uid; - gid_t batch_gid; - int run_batch; - static time_t next_batch = 0; - double currlavg[3]; - - /* Main loop. Open spool directory for reading and look over all the - * files in there. If the filename indicates that the job should be run, - * run a function which sets its user and group id to that of the files - * and execs a /bin/sh, which executes the shell. The function will - * then remove the script (hopefully). - * - * Also, pick the oldest batch job to run, at most one per run of - * the main loop. - */ - - next_job = now + CHECK_INTERVAL; - if (next_batch == 0) - next_batch = now; - - /* To avoid spinning up the disk unnecessarily, stat the directory and - * return immediately if it hasn't changed since the last time we woke - * up. - */ - - if (stat(".", &buf) == -1) - perr("Cannot stat " ATJOB_DIR); - - if (nothing_to_do && buf.st_mtime <= last_chg) - return next_job; - last_chg = buf.st_mtime; - - if ((spool = opendir(".")) == NULL) - perr("Cannot read " ATJOB_DIR); - - run_batch = 0; - nothing_to_do = 1; - - batch_uid = (uid_t) - 1; - batch_gid = (gid_t) - 1; - - while ((dirent = readdir(spool)) != NULL) { - - /* Avoid the stat if this doesn't look like a job file */ - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - /* Chances are a '=' file has been deleted from under us. - * Ignore. - */ - if (stat(dirent->d_name, &buf) != 0) - continue; - - if (!S_ISREG(buf.st_mode)) - continue; - - /* We don't want files which at(1) hasn't yet marked executable. */ - if (!(buf.st_mode & S_IXUSR)) { - nothing_to_do = 0; /* it will probably become executable soon */ - continue; - } - - run_time = (time_t) ctm *60; - - /* Skip lock files */ - if (queue == '=') { - /* FIXME: calhariz */ - /* I think the following code is broken, but commenting - may haven unknow side effects. Make a release and see - in the wild how it works. For more information see: - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818508/* - - /* if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) { */ - /* /\* Remove stale lockfile FIXME: lock the lockfile, if you fail, it's still in use. *\/ */ - /* unlink(dirent->d_name); */ - /* } */ - continue; - } - /* Skip any other file types which may have been invented in - * the meantime. - */ - if (!(isupper(queue) || islower(queue))) { - continue; - } - /* Is the file already locked? - */ - if (buf.st_nlink > 1) { - if (run_time < buf.st_mtime) - run_time = buf.st_mtime; - if (run_time + CHECK_INTERVAL <= now) { - /* Something went wrong the last time this was executed. - * Let's remove the lockfile and reschedule. - * We also change the timestamp to avoid rerunning the job more - * than once every CHECK_INTERVAL. - */ - strncpy(lock_name, dirent->d_name, sizeof(lock_name)); - if (utime(lock_name, 0) < 0) - syslog(LOG_ERR, "utime couldn't be set for lock file %s\n", lock_name); - lock_name[sizeof(lock_name)-1] = '\0'; - lock_name[0] = '='; - unlink(lock_name); - next_job = now; - nothing_to_do = 0; - } - continue; - } - - /* If we got here, then there are jobs of some kind waiting. - * We could try to be smarter and leave nothing_to_do set if - * we end up processing all the jobs, but that's risky (run_file - * might fail and expect the job to be rescheduled), and it doesn't - * gain us much. */ - nothing_to_do = 0; - - /* There's a job for later. Note its execution time if it's - * the earliest so far. - */ - if (run_time > now) { - if (next_job > run_time) { - next_job = run_time; - } - continue; - } - - if (isbatch(queue)) { - - /* We could potentially run this batch job. If it's scheduled - * at a higher priority than anything before, keep its - * filename. - */ - run_batch++; - if (strcmp(batch_name, dirent->d_name) > 0) { - strncpy(batch_name, dirent->d_name, sizeof(batch_name)); - batch_name[sizeof(batch_name)-1] = '\0'; - batch_uid = buf.st_uid; - batch_gid = buf.st_gid; - batch_queue = queue; - } - } - else { - if (run_time <= now) { - run_file(dirent->d_name, buf.st_uid, buf.st_gid); - } - } - } - closedir(spool); - /* run the single batch file, if any - */ - if (run_batch && (next_batch <= now)) { - next_batch = now + batch_interval; -#ifdef GETLOADAVG_PRIVILEGED - START_PRIV -#endif - if (getloadavg(currlavg, 1) < 1) { - currlavg[0] = 0.0; - } -#ifdef GETLOADAVG_PRIVILEGED - END_PRIV -#endif - if (currlavg[0] < load_avg) { - run_file(batch_name, batch_uid, batch_gid); - run_batch--; - } - } - if (run_batch && (next_batch < next_job)) { - nothing_to_do = 0; - next_job = next_batch; - } - return next_job; -} - -#ifdef HAVE_TIMER_CREATE -timer_t timer; -struct itimerspec timeout; - -void timer_setup() -{ - struct sigevent sev; - - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIGHUP; - sev.sigev_value.sival_ptr = &timer; - - memset(&timeout, 0, sizeof(timeout)); - - if (timer_create(CLOCK_REALTIME, &sev, &timer) < 0) - pabort("unable to create timer"); -} - -time_t atd_gettime() -{ - struct timespec curtime; - - clock_gettime(CLOCK_REALTIME, &curtime); - - return curtime.tv_sec; -} - -void atd_setalarm(time_t next) -{ - timeout.it_value.tv_sec = next; - timer_settime(timer, TIMER_ABSTIME, &timeout, NULL); - pause(); -} -#else -void timer_setup() -{ -} - -time_t atd_gettime() -{ - return time(NULL); -} - -void atd_setalarm(time_t next) -{ - sleep(next - atd_gettime()); -} -#endif -/* Global functions */ - -int -main(int argc, char *argv[]) -{ -/* Browse through ATJOB_DIR, checking all the jobfiles whether they should - * be executed and or deleted. The queue is coded into the first byte of - * the job filename, the next 5 bytes encode the serial number in hex, and - * the final 8 bytes encode the date (minutes since Eon) in hex. A file - * which has not been executed yet is denoted by its execute - bit set. - * For those files which are to be executed, run_file() is called, which forks - * off a child which takes care of I/O redirection, forks off another child - * for execution and yet another one, optionally, for sending mail. - * Files which already have run are removed during the next invocation. - */ - int c; - time_t next_invocation; - struct sigaction act; - struct passwd *pwe; - struct group *ge; - -#ifdef WITH_SELINUX - selinux_enabled=is_selinux_enabled(); - - if (selinux_enabled) { - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) selinux_log_callback); - } -#endif - -/* We don't need root privileges all the time; running under uid and gid - * daemon is fine. - */ - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - RELINQUISH_PRIVS_ROOT(daemon_uid, daemon_gid) - -#ifndef LOG_CRON -#define LOG_CRON LOG_DAEMON -#endif - - openlog("atd", LOG_PID, LOG_CRON); - - opterr = 0; - errno = 0; - run_as_daemon = 1; - batch_interval = BATCH_INTERVAL_DEFAULT; - - while ((c = getopt(argc, argv, "sdnl:b:f")) != EOF) { - switch (c) { - case 'l': - if (sscanf(optarg, "%lf", &load_avg) != 1) - pabort("garbled option -l"); - if (load_avg <= 0.) - load_avg = LOADAVG_MX; - break; - - case 'b': - if (sscanf(optarg, "%ud", &batch_interval) != 1) - pabort("garbled option -b"); - break; - case 'd': - daemon_debug++; - daemon_foreground++; - break; - - case 'f': - daemon_foreground++; - break; - - case 'n': - mail_with_hostname=1; - break; - - case 's': - run_as_daemon = 0; - break; - - case '?': - pabort("unknown option"); - break; - - default: - pabort("idiotic option - aborted"); - break; - } - } - - namep = argv[0]; - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if (optind < argc) - pabort("non-option arguments - not allowed"); - - sigaction(SIGCHLD, NULL, &act); - act.sa_handler = release_zombie; - act.sa_flags = SA_NOCLDSTOP; - sigaction(SIGCHLD, &act, NULL); - - if (!run_as_daemon) { - now = atd_gettime(); - run_loop(); - exit(EXIT_SUCCESS); - } - /* Main loop. Let's sleep for a specified interval, - * or until the next job is scheduled, or until we get signaled. - * After any of these events, we rescan the queue. - * A signal handler setting term_signal will make sure there's - * a clean exit. - */ - - sigaction(SIGHUP, NULL, &act); - act.sa_handler = sdummy; - sigaction(SIGHUP, &act, NULL); - - sigaction(SIGTERM, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGTERM, &act, NULL); - - sigaction(SIGINT, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGINT, &act, NULL); - - timer_setup(); - daemon_setup(); - - do { - now = atd_gettime(); - next_invocation = run_loop(); - if (next_invocation > now) { - atd_setalarm(next_invocation); - } - } while (!term_signal); - daemon_cleanup(); - exit(EXIT_SUCCESS); -} diff --git a/atd.c.pam b/atd.c.pam deleted file mode 100644 index 7ed4bf6..0000000 --- a/atd.c.pam +++ /dev/null @@ -1,913 +0,0 @@ -/* - * atd.c - run jobs queued by at; run with root privileges. - * Copyright (C) 1993, 1994, 1996 Thomas Koenig - * Copyright (c) 2002, 2005 Ryan Murray - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif HAVE_SYS_FCNTL_H - -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_GETOPT_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "privs.h" -#include "daemon.h" - -#ifndef HAVE_GETLOADAVG -#include "getloadavg.h" -#endif - -#ifdef WITH_SELINUX -#include -#include -int selinux_enabled = 0; -#endif - -/* Macros */ - -#define BATCH_INTERVAL_DEFAULT 60 -#define CHECK_INTERVAL 3600 - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -static char *namep; -static double load_avg = LOADAVG_MX; -static time_t now; -static time_t last_chg; -static int nothing_to_do; -unsigned int batch_interval; -static int run_as_daemon = 0; - -static volatile sig_atomic_t term_signal = 0; - -#ifdef HAVE_PAM -#include - -static pam_handle_t *pamh = NULL; - -static const struct pam_conv conv = { - NULL -}; - -#define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \ - fprintf(stderr,"\n%s\n",pam_strerror(pamh, retcode)); \ - syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \ - pam_end(pamh, retcode); exit(1); \ - } -#define PAM_END { retcode = pam_close_session(pamh,0); \ - pam_end(pamh,retcode); } - -#endif /* HAVE_PAM */ - -/* Signal handlers */ -RETSIGTYPE -set_term(int dummy) -{ - term_signal = 1; - return; -} - -RETSIGTYPE -sdummy(int dummy) -{ - /* Empty signal handler */ - nothing_to_do = 0; - return; -} - -/* SIGCHLD handler - discards completion status of children */ -RETSIGTYPE -release_zombie(int dummy) -{ - int status; - pid_t pid; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { -#ifdef DEBUG_ZOMBIE - if (WIFEXITED(status)) - syslog(LOG_INFO, "pid %ld exited with status %d.", pid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - syslog(LOG_NOTICE, "pid %ld killed with signal %d.", pid, WTERMSIG(status)); - else if (WIFSTOPPED(status)) - syslog(LOG_NOTICE, "pid %ld stopped with signal %d.", pid, WSTOPSIG(status)); - else - syslog(LOG_WARNING, "pid %ld unknown reason for SIGCHLD", pid); -#endif - } - return; -} - - -/* Local functions */ - -static int -write_string(int fd, const char *a) -{ - return write(fd, a, strlen(a)); -} - -static int -isbatch(char queue) -{ - return isupper(queue) || (queue == 'b'); -} - -#undef DEBUG_FORK -#ifdef DEBUG_FORK -static pid_t -myfork() -{ - pid_t res; - res = fork(); - if (res == 0) - kill(getpid(), SIGSTOP); - return res; -} - -#define fork myfork -#endif - -#ifdef WITH_SELINUX -static int -set_selinux_context(const char *name, const char *filename) { - security_context_t user_context = NULL; - security_context_t file_context = NULL; - int retval = 0; - char *seuser = NULL; - char *level = NULL; - - if (getseuserbyname(name, &seuser, &level) == 0) { - retval = get_default_context_with_level(seuser, level, NULL, &user_context); - free(seuser); - free(level); - if (retval < 0) { - lerr("get_default_context_with_level: couldn't get security context for user %s", name); - retval = -1; - goto err; - } - } - - /* - * Since crontab files are not directly executed, - * crond must ensure that the crontab file has - * a context that is appropriate for the context of - * the user cron job. It performs an entrypoint - * permission check for this purpose. - */ - if (fgetfilecon(STDIN_FILENO, &file_context) < 0) { - lerr("fgetfilecon FAILED %s", filename); - retval = -1; - goto err; - } - - retval = selinux_check_access(user_context, file_context, "file", "entrypoint", NULL); - freecon(file_context); - if (retval < 0) { - lerr("Not allowed to set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } - if (setexeccon(user_context) < 0) { - lerr("Could not set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } -err: - if (retval < 0 && security_getenforce() != 1) - retval = 0; - if (user_context) - freecon(user_context); - return retval; -} - -static int -selinux_log_callback (int type, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsyslog (LOG_ERR, fmt, ap); - va_end(ap); - return 0; -} - -#endif - -static void -run_file(const char *filename, uid_t uid, gid_t gid) -{ -/* Run a file by by spawning off a process which redirects I/O, - * spawns a subshell, then waits for it to complete and sends - * mail to the user. - */ - pid_t pid; - int fd_out, fd_in; - char jobbuf[9]; - char *mailname = NULL; - int mailsize = 128; - char *newname; - FILE *stream; - int send_mail = 0; - struct stat buf, lbuf; - off_t size; - struct passwd *pentry; - int fflags; - int nuid; - int ngid; - char queue; - char fmt[64]; - unsigned long jobno; - int rc; -#ifdef HAVE_PAM - int retcode; -#endif - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - sscanf(filename, "%c%5lx", &queue, &jobno); - if ((mailname = malloc(mailsize+1)) == NULL) - pabort("Job %8lu : out of virtual memory", jobno); - - sprintf(jobbuf, "%8lu", jobno); - - if ((newname = strdup(filename)) == 0) - pabort("Job %8lu : out of virtual memory", jobno); - newname[0] = '='; - - /* We try to make a hard link to lock the file. If we fail, then - * somebody else has already locked or deleted it (a second atd?); log the - * fact and return. - */ - PRIV_START - rc = link(filename, newname); - PRIV_END - if (rc == -1) { - syslog(LOG_WARNING, "could not lock job %lu: %m", jobno); - free(mailname); - free(newname); - return; - } - /* If something goes wrong between here and the unlink() call, - * the job gets restarted as soon as the "=" entry is cleared - * by the main atd loop. - */ - - pid = fork(); - if (pid == -1) - perr("Cannot fork"); - - else if (pid != 0) { - free(mailname); - free(newname); - return; - } - /* Let's see who we mail to. Hopefully, we can read it from - * the command file; if not, send it to the owner, or, failing that, - * to root. - */ - - pentry = getpwuid(uid); - if (pentry == NULL) { - pabort("Userid %lu not found - aborting job %8lu (%.500s)", - (unsigned long) uid, jobno, filename); - } - PRIV_START - - stream = fopen(filename, "r"); - - PRIV_END - - if (stream == NULL) - perr("Cannot open input file"); - - if ((fd_in = dup(fileno(stream))) < 0) - perr("Error duplicating input file descriptor"); - - if (fstat(fd_in, &buf) == -1) - perr("Error in fstat of input file descriptor"); - - if (lstat(filename, &lbuf) == -1) - perr("Error in fstat of input file"); - - if (S_ISLNK(lbuf.st_mode)) - perr("Symbolic link encountered in job %8lu (%.500s) - aborting", - jobno, filename); - - if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || - (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || - (lbuf.st_size != buf.st_size)) - perr("Somebody changed files from under us for job %8lu (%.500s) - " - "aborting", jobno, filename); - - if (buf.st_nlink > 2) { - perr("Somebody is trying to run a linked script for job %8lu (%.500s)", - jobno, filename); - } - if ((fflags = fcntl(fd_in, F_GETFD)) < 0) - perr("Error in fcntl"); - - fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); - - /* - * If the spool directory is mounted via NFS `atd' isn't able to - * read from the job file and will bump out here. The file is - * opened as "root" but it is read as "daemon" which fails over - * NFS and works with local file systems. It's not clear where - * the bug is located. -Joey - */ - sprintf(fmt, "#!/bin/sh\n# atrun uid=%%d gid=%%d\n# mail %%%ds %%d", - mailsize ); - - if (fscanf(stream, fmt, - &nuid, &ngid, mailname, &send_mail) != 4) - pabort("File %.500s is in wrong format - aborting", - filename); - - if (mailname[0] == '-') - pabort("illegal mail name %.300s in job %8lu (%.300s)", mailname, - jobno, filename); - - if (nuid != uid) - pabort("Job %8lu (%.500s) - userid %d does not match file uid %d", - jobno, filename, nuid, uid); - - /* We are now committed to executing this script. Unlink the - * original. - */ - - unlink(filename); - - fclose(stream); - if (chdir(ATSPOOL_DIR) < 0) - perr("Cannot chdir to " ATSPOOL_DIR); - - /* Create a file to hold the output of the job we are about to run. - * Write the mail header. Complain in case - */ - - if (unlink(filename) != -1) { - syslog(LOG_WARNING,"Warning: for duplicate output file for %.100s (dead job?)", - filename); - } - - if ((fd_out = open(filename, - O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) - perr("Cannot create output file"); - PRIV_START - if (fchown(fd_out, uid, ngid) == -1) - syslog(LOG_WARNING, "Warning: could not change owner of output file for job %li to %i:%i: %s", - jobno, uid, ngid, strerror(errno)); - PRIV_END - - write_string(fd_out, "Subject: Output from your job "); - write_string(fd_out, jobbuf); - write_string(fd_out, "\nTo: "); - write_string(fd_out, mailname); - write_string(fd_out, "\n\n"); - fstat(fd_out, &buf); - size = buf.st_size; - -#ifdef HAVE_PAM - PRIV_START - retcode = pam_start("atd", pentry->pw_name, &conv, &pamh); - PAM_FAIL_CHECK; - retcode = pam_acct_mgmt(pamh, PAM_SILENT); - PAM_FAIL_CHECK; - retcode = pam_open_session(pamh, PAM_SILENT); - PAM_FAIL_CHECK; - retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); - PAM_FAIL_CHECK; - PRIV_END -#endif - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - pid = fork(); - if (pid < 0) - perr("Error in fork"); - - else if (pid == 0) { - char *nul = NULL; - char **nenvp = &nul; - - /* Set up things for the child; we want standard input from the - * input file, and standard output and error sent to our output file. - */ - if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0) - perr("Error in lseek"); - - if (dup2(fd_in, STDIN_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDOUT_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDERR_FILENO) < 0) - perr("Error in I/O redirection"); - - close(fd_in); - close(fd_out); - - PRIV_START - - nice((tolower((int) queue) - 'a' + 1) * 2); - -#ifdef WITH_SELINUX - if (selinux_enabled > 0) { - if (set_selinux_context(pentry->pw_name, filename) < 0) - perr("SELinux Failed to set context\n"); - } -#endif - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(ngid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - chdir("/"); - - if (execle("/bin/sh", "sh", (char *) NULL, nenvp) != 0) - perr("Exec failed for /bin/sh"); - - PRIV_END - } - /* We're the parent. Let's wait. - */ - close(fd_in); - - /* We inherited the master's SIGCHLD handler, which does a - non-blocking waitpid. So this blocking one will eventually - return with an ECHILD error. - */ - waitpid(pid, (int *) NULL, 0); - -#ifdef HAVE_PAM - PRIV_START - pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); - retcode = pam_close_session(pamh, PAM_SILENT); - pam_end(pamh, retcode); - PRIV_END -#endif - - /* Send mail. Unlink the output file after opening it, so it - * doesn't hang around after the run. - */ - fstat(fd_out, &buf); - lseek(fd_out, 0, SEEK_SET); - if (dup2(fd_out, STDIN_FILENO) < 0) - perr("Could not use jobfile as standard input."); - - /* some sendmail implementations are confused if stdout, stderr are - * not available, so let them point to /dev/null - */ - if ((fd_in = open("/dev/null", O_WRONLY)) < 0) - perr("Could not open /dev/null."); - if (dup2(fd_in, STDOUT_FILENO) < 0) - perr("Could not use /dev/null as standard output."); - if (dup2(fd_in, STDERR_FILENO) < 0) - perr("Could not use /dev/null as standard error."); - if (fd_in != STDOUT_FILENO && fd_in != STDERR_FILENO) - close(fd_in); - - if (unlink(filename) == -1) - syslog(LOG_WARNING, "Warning: removing output file for job %li failed: %s", - jobno, strerror(errno)); - - /* The job is now finished. We can delete its input file. - */ - chdir(ATJOB_DIR); - unlink(newname); - free(newname); - - if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { - - PRIV_START - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(gid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - chdir ("/"); - -#if defined(SENDMAIL) - execl(SENDMAIL, "sendmail", "-i", mailname, (char *) NULL); -#else -#error "No mail command specified." -#endif - perr("Exec failed for mail command"); - - PRIV_END - } - exit(EXIT_SUCCESS); -} - -static time_t -run_loop() -{ - DIR *spool; - struct dirent *dirent; - struct stat buf; - unsigned long ctm; - unsigned long jobno; - char queue; - char batch_queue = '\0'; - time_t run_time, next_job; - char batch_name[] = "z2345678901234"; - char lock_name[] = "z2345678901234"; - uid_t batch_uid; - gid_t batch_gid; - int run_batch; - static time_t next_batch = 0; - double currlavg[3]; - - /* Main loop. Open spool directory for reading and look over all the - * files in there. If the filename indicates that the job should be run, - * run a function which sets its user and group id to that of the files - * and execs a /bin/sh, which executes the shell. The function will - * then remove the script (hopefully). - * - * Also, pick the oldest batch job to run, at most one per run of - * the main loop. - */ - - next_job = now + CHECK_INTERVAL; - if (next_batch == 0) - next_batch = now; - - /* To avoid spinning up the disk unnecessarily, stat the directory and - * return immediately if it hasn't changed since the last time we woke - * up. - */ - - if (stat(".", &buf) == -1) - perr("Cannot stat " ATJOB_DIR); - - if (nothing_to_do && buf.st_mtime <= last_chg) - return next_job; - last_chg = buf.st_mtime; - - if ((spool = opendir(".")) == NULL) - perr("Cannot read " ATJOB_DIR); - - run_batch = 0; - nothing_to_do = 1; - - batch_uid = (uid_t) - 1; - batch_gid = (gid_t) - 1; - - while ((dirent = readdir(spool)) != NULL) { - - /* Avoid the stat if this doesn't look like a job file */ - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - /* Chances are a '=' file has been deleted from under us. - * Ignore. - */ - if (stat(dirent->d_name, &buf) != 0) - continue; - - if (!S_ISREG(buf.st_mode)) - continue; - - /* We don't want files which at(1) hasn't yet marked executable. */ - if (!(buf.st_mode & S_IXUSR)) { - nothing_to_do = 0; /* it will probably become executable soon */ - continue; - } - - run_time = (time_t) ctm *60; - - /* Skip lock files */ - if (queue == '=') { - /* FIXME: calhariz */ - /* I think the following code is broken, but commenting - may haven unknow side effects. Make a release and see - in the wild how it works. For more information see: - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818508/* - - /* if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) { */ - /* /\* Remove stale lockfile FIXME: lock the lockfile, if you fail, it's still in use. *\/ */ - /* unlink(dirent->d_name); */ - /* } */ - continue; - } - /* Skip any other file types which may have been invented in - * the meantime. - */ - if (!(isupper(queue) || islower(queue))) { - continue; - } - /* Is the file already locked? - */ - if (buf.st_nlink > 1) { - if (run_time + CHECK_INTERVAL <= now) { - - /* Something went wrong the last time this was executed. - * Let's remove the lockfile and reschedule. - */ - strncpy(lock_name, dirent->d_name, sizeof(lock_name)); - lock_name[0] = '='; - unlink(lock_name); - next_job = now; - nothing_to_do = 0; - } - continue; - } - - /* If we got here, then there are jobs of some kind waiting. - * We could try to be smarter and leave nothing_to_do set if - * we end up processing all the jobs, but that's risky (run_file - * might fail and expect the job to be rescheduled), and it doesn't - * gain us much. */ - nothing_to_do = 0; - - /* There's a job for later. Note its execution time if it's - * the earliest so far. - */ - if (run_time > now) { - if (next_job > run_time) { - next_job = run_time; - } - continue; - } - - if (isbatch(queue)) { - - /* We could potentially run this batch job. If it's scheduled - * at a higher priority than anything before, keep its - * filename. - */ - run_batch++; - if (strcmp(batch_name, dirent->d_name) > 0) { - strncpy(batch_name, dirent->d_name, sizeof(batch_name)); - batch_uid = buf.st_uid; - batch_gid = buf.st_gid; - batch_queue = queue; - } - } - else { - if (run_time <= now) { - run_file(dirent->d_name, buf.st_uid, buf.st_gid); - } - } - } - closedir(spool); - /* run the single batch file, if any - */ - if (run_batch && (next_batch <= now)) { - next_batch = now + batch_interval; -#ifdef GETLOADAVG_PRIVILEGED - START_PRIV -#endif - if (getloadavg(currlavg, 1) < 1) { - currlavg[0] = 0.0; - } -#ifdef GETLOADAVG_PRIVILEGED - END_PRIV -#endif - if (currlavg[0] < load_avg) { - run_file(batch_name, batch_uid, batch_gid); - run_batch--; - } - } - if (run_batch && (next_batch < next_job)) { - nothing_to_do = 0; - next_job = next_batch; - } - return next_job; -} - -/* Global functions */ - -int -main(int argc, char *argv[]) -{ -/* Browse through ATJOB_DIR, checking all the jobfiles whether they should - * be executed and or deleted. The queue is coded into the first byte of - * the job filename, the next 5 bytes encode the serial number in hex, and - * the final 8 bytes encode the date (minutes since Eon) in hex. A file - * which has not been executed yet is denoted by its execute - bit set. - * For those files which are to be executed, run_file() is called, which forks - * off a child which takes care of I/O redirection, forks off another child - * for execution and yet another one, optionally, for sending mail. - * Files which already have run are removed during the next invocation. - */ - int c; - time_t next_invocation; - struct sigaction act; - struct passwd *pwe; - struct group *ge; - -#ifdef WITH_SELINUX - selinux_enabled=is_selinux_enabled(); - - if (selinux_enabled) { - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) selinux_log_callback); - } -#endif - -/* We don't need root privileges all the time; running under uid and gid - * daemon is fine. - */ - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - RELINQUISH_PRIVS_ROOT(daemon_uid, daemon_gid) - -#ifndef LOG_CRON -#define LOG_CRON LOG_DAEMON -#endif - - openlog("atd", LOG_PID, LOG_CRON); - - opterr = 0; - errno = 0; - run_as_daemon = 1; - batch_interval = BATCH_INTERVAL_DEFAULT; - - while ((c = getopt(argc, argv, "sdl:b:f")) != EOF) { - switch (c) { - case 'l': - if (sscanf(optarg, "%lf", &load_avg) != 1) - pabort("garbled option -l"); - if (load_avg <= 0.) - load_avg = LOADAVG_MX; - break; - - case 'b': - if (sscanf(optarg, "%ud", &batch_interval) != 1) - pabort("garbled option -b"); - break; - case 'd': - daemon_debug++; - daemon_foreground++; - break; - - case 'f': - daemon_foreground++; - break; - - case 's': - run_as_daemon = 0; - break; - - case '?': - pabort("unknown option"); - break; - - default: - pabort("idiotic option - aborted"); - break; - } - } - - namep = argv[0]; - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if (optind < argc) - pabort("non-option arguments - not allowed"); - - sigaction(SIGCHLD, NULL, &act); - act.sa_handler = release_zombie; - act.sa_flags = SA_NOCLDSTOP; - sigaction(SIGCHLD, &act, NULL); - - if (!run_as_daemon) { - now = time(NULL); - run_loop(); - exit(EXIT_SUCCESS); - } - /* Main loop. Let's sleep for a specified interval, - * or until the next job is scheduled, or until we get signaled. - * After any of these events, we rescan the queue. - * A signal handler setting term_signal will make sure there's - * a clean exit. - */ - - sigaction(SIGHUP, NULL, &act); - act.sa_handler = sdummy; - sigaction(SIGHUP, &act, NULL); - - sigaction(SIGTERM, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGTERM, &act, NULL); - - sigaction(SIGINT, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGINT, &act, NULL); - - daemon_setup(); - - do { - now = time(NULL); - next_invocation = run_loop(); - if (next_invocation > now) { - sleep(next_invocation - now); - } - } while (!term_signal); - daemon_cleanup(); - exit(EXIT_SUCCESS); -} diff --git a/atd.c.posix b/atd.c.posix deleted file mode 100644 index cb22dd7..0000000 --- a/atd.c.posix +++ /dev/null @@ -1,956 +0,0 @@ -/* - * atd.c - run jobs queued by at; run with root privileges. - * Copyright (C) 1993, 1994, 1996 Thomas Koenig - * Copyright (c) 2002, 2005 Ryan Murray - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include -#include - -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#elif HAVE_SYS_FCNTL_H - -#include -#endif - -#include - -#ifdef HAVE_DIRENT_H -#include -#elif HAVE_SYS_DIRENT_H -#include -#elif HAVE_SYS_DIR_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_GETOPT_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -/* Local headers */ - -#include "privs.h" -#include "daemon.h" - -#ifndef HAVE_GETLOADAVG -#include "getloadavg.h" -#endif - -#ifdef WITH_SELINUX -#include -#include -int selinux_enabled = 0; -#endif - -/* Macros */ - -#ifndef LOG_ATD -#define LOG_ATD LOG_DAEMON -#endif - -#define BATCH_INTERVAL_DEFAULT 60 -#define CHECK_INTERVAL 3600 - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -/* Global variables */ - -uid_t real_uid, effective_uid; -gid_t real_gid, effective_gid; - -uid_t daemon_uid = (uid_t) - 3; -gid_t daemon_gid = (gid_t) - 3; - -/* File scope variables */ - -static char *namep; -static double load_avg = LOADAVG_MX; -static time_t now; -static time_t last_chg; -static int nothing_to_do; -unsigned int batch_interval; -static int run_as_daemon = 0; -static int mail_with_hostname = 0; - -static volatile sig_atomic_t term_signal = 0; - -#ifdef WITH_PAM -#include - -static pam_handle_t *pamh = NULL; - -static const struct pam_conv conv = { - NULL -}; - -#endif /* WITH_PAM */ - -/* Signal handlers */ -RETSIGTYPE -set_term(int dummy) -{ - term_signal = 1; - return; -} - -RETSIGTYPE -sdummy(int dummy) -{ - /* Empty signal handler */ - nothing_to_do = 0; - return; -} - -/* SIGCHLD handler - discards completion status of children */ -RETSIGTYPE -release_zombie(int dummy) -{ - int status; - pid_t pid; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { -#ifdef DEBUG_ZOMBIE - if (WIFEXITED(status)) - syslog(LOG_INFO, "pid %ld exited with status %d.", pid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - syslog(LOG_NOTICE, "pid %ld killed with signal %d.", pid, WTERMSIG(status)); - else if (WIFSTOPPED(status)) - syslog(LOG_NOTICE, "pid %ld stopped with signal %d.", pid, WSTOPSIG(status)); - else - syslog(LOG_WARNING, "pid %ld unknown reason for SIGCHLD", pid); -#endif - } - return; -} - - -/* Local functions */ - -static int -write_string(int fd, const char *a) -{ - return write(fd, a, strlen(a)); -} - -static int -isbatch(char queue) -{ - return isupper(queue) || (queue == 'b'); -} - -#undef DEBUG_FORK -#ifdef DEBUG_FORK -static pid_t -myfork() -{ - pid_t res; - res = fork(); - if (res == 0) - kill(getpid(), SIGSTOP); - return res; -} - -#define fork myfork -#endif -#undef ATD_MAIL_PROGRAM -#undef ATD_MAIL_NAME -#if defined(SENDMAIL) -#define ATD_MAIL_PROGRAM SENDMAIL -#define ATD_MAIL_NAME "sendmail" -#elif defined(MAILC) -#define ATD_MAIL_PROGRAM MAILC -#define ATD_MAIL_NAME "mail" -#elif defined(MAILX) -#define ATD_MAIL_PROGRAM MAILX -#define ATD_MAIL_NAME "mailx" -#endif - -#ifdef WITH_SELINUX -static int -set_selinux_context(const char *name, const char *filename) { - security_context_t user_context = NULL; - security_context_t file_context = NULL; - int retval = 0; - char *seuser = NULL; - char *level = NULL; - - if (getseuserbyname(name, &seuser, &level) == 0) { - retval = get_default_context_with_level(seuser, level, NULL, &user_context); - free(seuser); - free(level); - if (retval < 0) { - lerr("get_default_context_with_level: couldn't get security context for user %s", name); - retval = -1; - goto err; - } - } - - /* - * Since crontab files are not directly executed, - * crond must ensure that the crontab file has - * a context that is appropriate for the context of - * the user cron job. It performs an entrypoint - * permission check for this purpose. - */ - if (fgetfilecon(STDIN_FILENO, &file_context) < 0) { - lerr("fgetfilecon FAILED %s", filename); - retval = -1; - goto err; - } - - retval = selinux_check_access(user_context, file_context, "file", "entrypoint", NULL); - freecon(file_context); - if (retval < 0) { - lerr("Not allowed to set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } - if (setexeccon(user_context) < 0) { - lerr("Could not set exec context to %s for user %s", user_context, name); - retval = -1; - goto err; - } -err: - if (retval < 0 && security_getenforce() != 1) - retval = 0; - if (user_context) - freecon(user_context); - return retval; -} - -static int -selinux_log_callback (int type, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsyslog (LOG_ERR, fmt, ap); - va_end(ap); - return 0; -} - -#endif - -static void -run_file(const char *filename, uid_t uid, gid_t gid) -{ -/* Run a file by by spawning off a process which redirects I/O, - * spawns a subshell, then waits for it to complete and sends - * mail to the user. - */ - pid_t pid; - int fd_out, fd_in; - char jobbuf[9]; - char *mailname = NULL; - int mailsize = 128; - char *newname; - FILE *stream; - int send_mail = 0; - struct stat buf, lbuf; - off_t size; - struct passwd *pentry; - int fflags; - int nuid; - int ngid; - char queue; - char fmt[64]; - unsigned long jobno; - int rc; - char hostbuf[MAXHOSTNAMELEN]; -#ifdef WITH_PAM - int retcode; -#endif - -#ifdef _SC_LOGIN_NAME_MAX - errno = 0; - rc = sysconf(_SC_LOGIN_NAME_MAX); - if (rc > 0) - mailsize = rc; -#else -# ifdef LOGIN_NAME_MAX - mailsize = LOGIN_NAME_MAX; -# endif -#endif - sscanf(filename, "%c%5lx", &queue, &jobno); - if ((mailname = malloc(mailsize+1)) == NULL) - pabort("Job %8lu : out of virtual memory", jobno); - - sprintf(jobbuf, "%8lu", jobno); - - if ((newname = strdup(filename)) == 0) - pabort("Job %8lu : out of virtual memory", jobno); - newname[0] = '='; - - /* We try to make a hard link to lock the file. If we fail, then - * somebody else has already locked or deleted it (a second atd?); log the - * fact and return. - */ - PRIV_START - rc = link(filename, newname); - PRIV_END - if (rc == -1) { - syslog(LOG_WARNING, "could not lock job %lu: %m", jobno); - free(mailname); - free(newname); - return; - } - /* If something goes wrong between here and the unlink() call, - * the job gets restarted as soon as the "=" entry is cleared - * by the main atd loop. - */ - - pid = fork(); - if (pid == -1) - perr("Cannot fork"); - - else if (pid != 0) { - free(mailname); - free(newname); - return; - } - - (void) setsid(); /* own session for process */ - - /* Let's see who we mail to. Hopefully, we can read it from - * the command file; if not, send it to the owner, or, failing that, - * to root. - */ - - pentry = getpwuid(uid); - if (pentry == NULL) { - pabort("Userid %lu not found - aborting job %8lu (%.500s)", - (unsigned long) uid, jobno, filename); - } - PRIV_START - - stream = fopen(filename, "r"); - - PRIV_END - - if (stream == NULL) - perr("Cannot open input file"); - - if ((fd_in = dup(fileno(stream))) < 0) - perr("Error duplicating input file descriptor"); - - if (fstat(fd_in, &buf) == -1) - perr("Error in fstat of input file descriptor"); - - if (lstat(filename, &lbuf) == -1) - perr("Error in fstat of input file"); - - if (S_ISLNK(lbuf.st_mode)) - perr("Symbolic link encountered in job %8lu (%.500s) - aborting", - jobno, filename); - - if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || - (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || - (lbuf.st_size != buf.st_size)) - perr("Somebody changed files from under us for job %8lu (%.500s) - " - "aborting", jobno, filename); - - if (buf.st_nlink > 2) { - perr("Somebody is trying to run a linked script for job %8lu (%.500s)", - jobno, filename); - } - if ((fflags = fcntl(fd_in, F_GETFD)) < 0) - perr("Error in fcntl"); - - fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); - - /* - * If the spool directory is mounted via NFS `atd' isn't able to - * read from the job file and will bump out here. The file is - * opened as "root" but it is read as "daemon" which fails over - * NFS and works with local file systems. It's not clear where - * the bug is located. -Joey - */ - sprintf(fmt, "#!/bin/sh\n# atrun uid=%%d gid=%%d\n# mail %%%ds %%d", - mailsize ); - - if (fscanf(stream, fmt, - &nuid, &ngid, mailname, &send_mail) != 4) - pabort("File %.500s is in wrong format - aborting", - filename); - - if (mailname[0] == '-') - pabort("illegal mail name %.300s in job %8lu (%.300s)", mailname, - jobno, filename); - - if (nuid != uid) - pabort("Job %8lu (%.500s) - userid %d does not match file uid %d", - jobno, filename, nuid, uid); - - /* We are now committed to executing this script. Unlink the - * original. - */ - - unlink(filename); - - fclose(stream); - if (chdir(ATSPOOL_DIR) < 0) - perr("Cannot chdir to " ATSPOOL_DIR); - - /* Create a file to hold the output of the job we are about to run. - * Write the mail header. Complain in case - */ - - if (unlink(filename) != -1) { - syslog(LOG_WARNING,"Warning: for duplicate output file for %.100s (dead job?)", - filename); - } - - if ((fd_out = open(filename, - O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) - perr("Cannot create output file"); - PRIV_START - if (fchown(fd_out, uid, ngid) == -1) - syslog(LOG_WARNING, "Warning: could not change owner of output file for job %li to %i:%i: %s", - jobno, uid, ngid, strerror(errno)); - PRIV_END - - write_string(fd_out, "Subject: Output from your job "); - write_string(fd_out, jobbuf); - if (mail_with_hostname > 0) { - gethostname(hostbuf, MAXHOSTNAMELEN-1); - write_string(fd_out, " "); - write_string(fd_out, hostbuf); - } - write_string(fd_out, "\nTo: "); - write_string(fd_out, mailname); - write_string(fd_out, "\n\n"); - fstat(fd_out, &buf); - size = buf.st_size; - -#ifdef WITH_PAM - AT_START_PAM; - AT_OPEN_PAM_SESSION; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - pid = fork(); - if (pid < 0) - perr("Error in fork"); - - else if (pid == 0) { - char *nul = NULL; - char **nenvp = &nul; - char **pam_envp=0L; - - PRIV_START -#ifdef WITH_PAM - pam_envp = pam_getenvlist(pamh); - if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) ) - nenvp = pam_envp; -#endif - /* Set up things for the child; we want standard input from the - * input file, and standard output and error sent to our output file. - */ - if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0) - perr("Error in lseek"); - - if (dup2(fd_in, STDIN_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDOUT_FILENO) < 0) - perr("Error in I/O redirection"); - - if (dup2(fd_out, STDERR_FILENO) < 0) - perr("Error in I/O redirection"); - - close(fd_in); - close(fd_out); - - nice((tolower((int) queue) - 'a' + 1) * 2); - -#ifdef WITH_SELINUX - if (selinux_enabled > 0) { - if (set_selinux_context(pentry->pw_name, filename) < 0) - perr("SELinux Failed to set context\n"); - } -#endif - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(ngid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir("/"); - - execle("/bin/sh", "sh", (char *) NULL, nenvp); - perr("Exec failed for /bin/sh"); - /* perr exits, the PRIV_END is just for nice form */ - PRIV_END - } - /* We're the parent. Let's wait. - */ - close(fd_in); - - /* We inherited the master's SIGCHLD handler, which does a - non-blocking waitpid. So this blocking one will eventually - return with an ECHILD error. - */ - waitpid(pid, (int *) NULL, 0); - - /* Send mail. Unlink the output file after opening it, so it - * doesn't hang around after the run. - */ - fstat(fd_out, &buf); - lseek(fd_out, 0, SEEK_SET); - if (dup2(fd_out, STDIN_FILENO) < 0) - perr("Could not use jobfile as standard input."); - - /* some sendmail implementations are confused if stdout, stderr are - * not available, so let them point to /dev/null - */ - if ((fd_in = open("/dev/null", O_WRONLY)) < 0) - perr("Could not open /dev/null."); - if (dup2(fd_in, STDOUT_FILENO) < 0) - perr("Could not use /dev/null as standard output."); - if (dup2(fd_in, STDERR_FILENO) < 0) - perr("Could not use /dev/null as standard error."); - if (fd_in != STDOUT_FILENO && fd_in != STDERR_FILENO) - close(fd_in); - - if (unlink(filename) == -1) - syslog(LOG_WARNING, "Warning: removing output file for job %li failed: %s", - jobno, strerror(errno)); - - /* The job is now finished. We can delete its input file. - */ - chdir(ATJOB_DIR); - unlink(newname); - free(newname); - -#ifdef ATD_MAIL_PROGRAM - if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { - int mail_pid = -1; - - mail_pid = fork(); - - if ( mail_pid == 0 ) { - PRIV_START - - if (initgroups(pentry->pw_name, pentry->pw_gid)) - perr("Cannot initialize the supplementary group access list"); - - if (setgid(gid) < 0) - perr("Cannot change group"); - - if (setuid(uid) < 0) - perr("Cannot set user id"); - - if (SIG_ERR == signal(SIGCHLD, SIG_DFL)) - perr("Cannot reset signal handler to default"); - - chdir ("/"); - -#if defined(SENDMAIL) - execl(SENDMAIL, "sendmail", "-i", mailname, (char *) NULL); -#else -#error "No mail command specified." -#endif - perr("Exec failed for mail command"); - - PRIV_END - } - else if ( mail_pid == -1 ) { - syslog(LOG_ERR, "fork of mailer failed: %m"); - } - /* Parent */ - waitpid(mail_pid, (int *) NULL, 0); - } - -#ifdef WITH_PAM - AT_CLOSE_PAM; - closelog(); - openlog("atd", LOG_PID, LOG_ATD); -#endif -#endif - exit(EXIT_SUCCESS); -} - -static time_t -run_loop() -{ - DIR *spool; - struct dirent *dirent; - struct stat buf; - unsigned long ctm; - unsigned long jobno; - char queue; - char batch_queue = '\0'; - time_t run_time, next_job; - char batch_name[] = "z2345678901234"; - char lock_name[] = "z2345678901234"; - uid_t batch_uid; - gid_t batch_gid; - int run_batch; - static time_t next_batch = 0; - double currlavg[3]; - - /* Main loop. Open spool directory for reading and look over all the - * files in there. If the filename indicates that the job should be run, - * run a function which sets its user and group id to that of the files - * and execs a /bin/sh, which executes the shell. The function will - * then remove the script (hopefully). - * - * Also, pick the oldest batch job to run, at most one per run of - * the main loop. - */ - - next_job = now + CHECK_INTERVAL; - if (next_batch == 0) - next_batch = now; - - /* To avoid spinning up the disk unnecessarily, stat the directory and - * return immediately if it hasn't changed since the last time we woke - * up. - */ - - if (stat(".", &buf) == -1) - perr("Cannot stat " ATJOB_DIR); - - if (nothing_to_do && buf.st_mtime <= last_chg) - return next_job; - last_chg = buf.st_mtime; - - if ((spool = opendir(".")) == NULL) - perr("Cannot read " ATJOB_DIR); - - run_batch = 0; - nothing_to_do = 1; - - batch_uid = (uid_t) - 1; - batch_gid = (gid_t) - 1; - - while ((dirent = readdir(spool)) != NULL) { - - /* Avoid the stat if this doesn't look like a job file */ - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) - continue; - - /* Chances are a '=' file has been deleted from under us. - * Ignore. - */ - if (stat(dirent->d_name, &buf) != 0) - continue; - - if (!S_ISREG(buf.st_mode)) - continue; - - /* We don't want files which at(1) hasn't yet marked executable. */ - if (!(buf.st_mode & S_IXUSR)) { - nothing_to_do = 0; /* it will probably become executable soon */ - continue; - } - - run_time = (time_t) ctm *60; - - /* Skip lock files */ - if (queue == '=') { - /* FIXME: calhariz */ - /* I think the following code is broken, but commenting - may haven unknow side effects. Make a release and see - in the wild how it works. For more information see: - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818508/* - - /* if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) { */ - /* /\* Remove stale lockfile FIXME: lock the lockfile, if you fail, it's still in use. *\/ */ - /* unlink(dirent->d_name); */ - /* } */ - continue; - } - /* Skip any other file types which may have been invented in - * the meantime. - */ - if (!(isupper(queue) || islower(queue))) { - continue; - } - /* Is the file already locked? - */ - if (buf.st_nlink > 1) { - if (run_time + CHECK_INTERVAL <= now) { - - /* Something went wrong the last time this was executed. - * Let's remove the lockfile and reschedule. - */ - strncpy(lock_name, dirent->d_name, sizeof(lock_name)); - lock_name[sizeof(lock_name)-1] = '\0'; - lock_name[0] = '='; - unlink(lock_name); - next_job = now; - nothing_to_do = 0; - } - continue; - } - - /* If we got here, then there are jobs of some kind waiting. - * We could try to be smarter and leave nothing_to_do set if - * we end up processing all the jobs, but that's risky (run_file - * might fail and expect the job to be rescheduled), and it doesn't - * gain us much. */ - nothing_to_do = 0; - - /* There's a job for later. Note its execution time if it's - * the earliest so far. - */ - if (run_time > now) { - if (next_job > run_time) { - next_job = run_time; - } - continue; - } - - if (isbatch(queue)) { - - /* We could potentially run this batch job. If it's scheduled - * at a higher priority than anything before, keep its - * filename. - */ - run_batch++; - if (strcmp(batch_name, dirent->d_name) > 0) { - strncpy(batch_name, dirent->d_name, sizeof(batch_name)); - batch_name[sizeof(batch_name)-1] = '\0'; - batch_uid = buf.st_uid; - batch_gid = buf.st_gid; - batch_queue = queue; - } - } - else { - if (run_time <= now) { - run_file(dirent->d_name, buf.st_uid, buf.st_gid); - } - } - } - closedir(spool); - /* run the single batch file, if any - */ - if (run_batch && (next_batch <= now)) { - next_batch = now + batch_interval; -#ifdef GETLOADAVG_PRIVILEGED - START_PRIV -#endif - if (getloadavg(currlavg, 1) < 1) { - currlavg[0] = 0.0; - } -#ifdef GETLOADAVG_PRIVILEGED - END_PRIV -#endif - if (currlavg[0] < load_avg) { - run_file(batch_name, batch_uid, batch_gid); - run_batch--; - } - } - if (run_batch && (next_batch < next_job)) { - nothing_to_do = 0; - next_job = next_batch; - } - return next_job; -} - -/* Global functions */ - -int -main(int argc, char *argv[]) -{ -/* Browse through ATJOB_DIR, checking all the jobfiles whether they should - * be executed and or deleted. The queue is coded into the first byte of - * the job filename, the next 5 bytes encode the serial number in hex, and - * the final 8 bytes encode the date (minutes since Eon) in hex. A file - * which has not been executed yet is denoted by its execute - bit set. - * For those files which are to be executed, run_file() is called, which forks - * off a child which takes care of I/O redirection, forks off another child - * for execution and yet another one, optionally, for sending mail. - * Files which already have run are removed during the next invocation. - */ - int c; - time_t next_invocation; - struct sigaction act; - struct passwd *pwe; - struct group *ge; - -#ifdef WITH_SELINUX - selinux_enabled=is_selinux_enabled(); - - if (selinux_enabled) { - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) selinux_log_callback); - } -#endif - -/* We don't need root privileges all the time; running under uid and gid - * daemon is fine. - */ - - if ((pwe = getpwnam(DAEMON_USERNAME)) == NULL) - perr("Cannot get uid for " DAEMON_USERNAME); - - daemon_uid = pwe->pw_uid; - - if ((ge = getgrnam(DAEMON_GROUPNAME)) == NULL) - perr("Cannot get gid for " DAEMON_GROUPNAME); - - daemon_gid = ge->gr_gid; - - RELINQUISH_PRIVS_ROOT(daemon_uid, daemon_gid) - -#ifndef LOG_CRON -#define LOG_CRON LOG_DAEMON -#endif - - openlog("atd", LOG_PID, LOG_CRON); - - opterr = 0; - errno = 0; - run_as_daemon = 1; - batch_interval = BATCH_INTERVAL_DEFAULT; - - while ((c = getopt(argc, argv, "sdnl:b:f")) != EOF) { - switch (c) { - case 'l': - if (sscanf(optarg, "%lf", &load_avg) != 1) - pabort("garbled option -l"); - if (load_avg <= 0.) - load_avg = LOADAVG_MX; - break; - - case 'b': - if (sscanf(optarg, "%ud", &batch_interval) != 1) - pabort("garbled option -b"); - break; - case 'd': - daemon_debug++; - daemon_foreground++; - break; - - case 'f': - daemon_foreground++; - break; - - case 'n': - mail_with_hostname=1; - break; - - case 's': - run_as_daemon = 0; - break; - - case '?': - pabort("unknown option"); - break; - - default: - pabort("idiotic option - aborted"); - break; - } - } - - namep = argv[0]; - if (chdir(ATJOB_DIR) != 0) - perr("Cannot change to " ATJOB_DIR); - - if (optind < argc) - pabort("non-option arguments - not allowed"); - - sigaction(SIGCHLD, NULL, &act); - act.sa_handler = release_zombie; - act.sa_flags = SA_NOCLDSTOP; - sigaction(SIGCHLD, &act, NULL); - - if (!run_as_daemon) { - now = time(NULL); - run_loop(); - exit(EXIT_SUCCESS); - } - /* Main loop. Let's sleep for a specified interval, - * or until the next job is scheduled, or until we get signaled. - * After any of these events, we rescan the queue. - * A signal handler setting term_signal will make sure there's - * a clean exit. - */ - - sigaction(SIGHUP, NULL, &act); - act.sa_handler = sdummy; - sigaction(SIGHUP, &act, NULL); - - sigaction(SIGTERM, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGTERM, &act, NULL); - - sigaction(SIGINT, NULL, &act); - act.sa_handler = set_term; - sigaction(SIGINT, &act, NULL); - - daemon_setup(); - - do { - now = time(NULL); - next_invocation = run_loop(); - if (next_invocation > now) { - sleep(next_invocation - now); - } - } while (!term_signal); - daemon_cleanup(); - exit(EXIT_SUCCESS); -} diff --git a/config.guess b/config.guess index 872b96a..40eaed4 100755 --- a/config.guess +++ b/config.guess @@ -2,9 +2,9 @@ # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. +# 2011 Free Software Foundation, Inc. -timestamp='2012-09-25' +timestamp='2011-05-11' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -17,7 +17,9 @@ timestamp='2012-09-25' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -55,8 +57,8 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -143,7 +145,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward @@ -200,10 +202,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} - exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} @@ -306,7 +304,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) + arm:riscos:*:*|arm:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) @@ -794,26 +792,21 @@ EOF echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; - *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 - exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 @@ -868,13 +861,6 @@ EOF i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; - aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; @@ -909,16 +895,13 @@ EOF echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu + echo cris-axis-linux-gnu exit ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu + echo crisv32-axis-linux-gnu exit ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo frv-unknown-linux-gnu exit ;; i*86:Linux:*:*) LIBC=gnu @@ -960,7 +943,7 @@ EOF test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo or32-unknown-linux-gnu exit ;; padre:Linux:*:*) echo sparc-unknown-linux-gnu @@ -995,13 +978,13 @@ EOF echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-tilera-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo x86_64-unknown-linux-gnu exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu @@ -1208,9 +1191,6 @@ EOF BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; - x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; @@ -1266,7 +1246,7 @@ EOF NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; - NSE-*:NONSTOP_KERNEL:*:*) + NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) @@ -1335,11 +1315,11 @@ EOF i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; - x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx - exit ;; esac +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + eval $set_cc_for_build cat >$dummy.c < and include a ChangeLog -# entry. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free -Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - case ${UNAME_MACHINE} in - pc98) - echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-gnu - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-gnueabi - else - echo ${UNAME_MACHINE}-unknown-linux-gnueabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - cris:Linux:*:*) - echo cris-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) - echo crisv32-axis-linux-gnu - exit ;; - frv:Linux:*:*) - echo frv-unknown-linux-gnu - exit ;; - i*86:Linux:*:*) - LIBC=gnu - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) - echo or32-unknown-linux-gnu - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-gnu - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-tilera-linux-gnu - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu - exit ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - i386) - eval $set_cc_for_build - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - UNAME_PROCESSOR="x86_64" - fi - fi ;; - unknown) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/config.h.in b/config.h.in index 16dbbba..681d68e 100644 --- a/config.h.in +++ b/config.h.in @@ -38,9 +38,6 @@ /* Define to 1 if you have the `getloadavg' function. */ #undef HAVE_GETLOADAVG -/* Define to 1 if you have the `timer_create' function. */ -#undef HAVE_TIMER_CREATE - /* Define to 1 if you have the header file. */ #undef HAVE_GETOPT_H @@ -71,8 +68,8 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NLIST_H -/* Define if you are building with_pam */ -#undef WITH_PAM +/* Define to 1 for PAM support */ +#undef HAVE_PAM /* Define to 1 if you have the `pstat_getdynamic' function. */ #undef HAVE_PSTAT_GETDYNAMIC diff --git a/config.h.in.pam b/config.h.in.pam deleted file mode 100644 index 681d68e..0000000 --- a/config.h.in.pam +++ /dev/null @@ -1,221 +0,0 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Where do we place out input directories? */ -#undef ATJOB_DIR - -/* Where do we spool our output? */ -#undef ATSPOOL_DIR - -/* Define to 1 if using `getloadavg.c'. */ -#undef C_GETLOADAVG - -/* Define to 1 for DGUX with . */ -#undef DGUX - -/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. - */ -#undef GETLOADAVG_PRIVILEGED - -/* Define to 1 if compiler supports __attribute__((noreturn)) */ -#undef HAVE_ATTRIBUTE_NORETURN - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_DIRENT_H - -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -#undef HAVE_DOPRNT - -/* Define to 1 if you have the header file. */ -#undef HAVE_ERRNO_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_FCNTL_H - -/* Define to 1 if you have the `getcwd' function. */ -#undef HAVE_GETCWD - -/* Define to 1 if you have the `getloadavg' function. */ -#undef HAVE_GETLOADAVG - -/* Define to 1 if you have the header file. */ -#undef HAVE_GETOPT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the `dgc' library (-ldgc). */ -#undef HAVE_LIBDGC - -/* Define to 1 if you have the `fl' library (-lfl). */ -#undef HAVE_LIBFL - -/* Define to 1 if you have the `kstat' library (-lkstat). */ -#undef HAVE_LIBKSTAT - -/* Define to 1 if you have the header file. */ -#undef HAVE_MACH_MACH_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the `mktime' function. */ -#undef HAVE_MKTIME - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -#undef HAVE_NDIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NLIST_H - -/* Define to 1 for PAM support */ -#undef HAVE_PAM - -/* Define to 1 if you have the `pstat_getdynamic' function. */ -#undef HAVE_PSTAT_GETDYNAMIC - -/* Define to 1 if you have the header file. */ -#undef HAVE_SECURITY_PAM_APPL_H - -/* Define to 1 if you have the `setlocale' function. */ -#undef HAVE_SETLOCALE - -/* Define to 1 if you have the `setresuid' function. */ -#undef HAVE_SETRESUID - -/* Define to 1 if you have the `setreuid' function. */ -#undef HAVE_SETREUID - -/* Define to 1 if you have the `sigaction' function. */ -#undef HAVE_SIGACTION - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDARG_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the `strftime' function. */ -#undef HAVE_STRFTIME - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if `n_un.n_name' is a member of `struct nlist'. */ -#undef HAVE_STRUCT_NLIST_N_UN_N_NAME - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYSLOG_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_DIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_FCNTL_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_NDIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have that is POSIX.1 compatible. */ -#undef HAVE_SYS_WAIT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the `vprintf' function. */ -#undef HAVE_VPRINTF - -/* Define to 1 if you have the `waitpid' function. */ -#undef HAVE_WAITPID - -/* Define to 1 if we need to provide our own yywrap() */ -#undef NEED_YYWRAP - -/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend - on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ -#undef NLIST_NAME_UNION - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* What is the name of our PID file? */ -#undef PIDFILE - -/* Define as the return type of signal handlers (`int' or `void'). */ -#undef RETSIGTYPE - -/* Define mail command for sending */ -#undef SENDMAIL - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define to 1 on System V Release 4. */ -#undef SVR4 - -/* Define to 1 if your declares `struct tm'. */ -#undef TM_IN_SYS_TIME - -/* Define to 1 for Encore UMAX. */ -#undef UMAX - -/* Define to 1 for Encore UMAX 4.3 that has instead of - . */ -#undef UMAX4_3 - -/* Define if you are building with_selinux */ -#undef WITH_SELINUX - -/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a - `char[]'. */ -#undef YYTEXT_POINTER - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to `int' if doesn't define. */ -#undef gid_t - -/* Define to `int' if does not define. */ -#undef mode_t - -/* Define to `long int' if does not define. */ -#undef off_t - -/* Define to `int' if does not define. */ -#undef pid_t - -/* Define to `unsigned int' if does not define. */ -#undef size_t - -/* Define to `int' if doesn't define. */ -#undef uid_t diff --git a/config.h.in.posix b/config.h.in.posix deleted file mode 100644 index d1be135..0000000 --- a/config.h.in.posix +++ /dev/null @@ -1,221 +0,0 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Where do we place out input directories? */ -#undef ATJOB_DIR - -/* Where do we spool our output? */ -#undef ATSPOOL_DIR - -/* Define to 1 if using `getloadavg.c'. */ -#undef C_GETLOADAVG - -/* Define to 1 for DGUX with . */ -#undef DGUX - -/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. - */ -#undef GETLOADAVG_PRIVILEGED - -/* Define to 1 if compiler supports __attribute__((noreturn)) */ -#undef HAVE_ATTRIBUTE_NORETURN - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_DIRENT_H - -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -#undef HAVE_DOPRNT - -/* Define to 1 if you have the header file. */ -#undef HAVE_ERRNO_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_FCNTL_H - -/* Define to 1 if you have the `getcwd' function. */ -#undef HAVE_GETCWD - -/* Define to 1 if you have the `getloadavg' function. */ -#undef HAVE_GETLOADAVG - -/* Define to 1 if you have the header file. */ -#undef HAVE_GETOPT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the `dgc' library (-ldgc). */ -#undef HAVE_LIBDGC - -/* Define to 1 if you have the `fl' library (-lfl). */ -#undef HAVE_LIBFL - -/* Define to 1 if you have the `kstat' library (-lkstat). */ -#undef HAVE_LIBKSTAT - -/* Define to 1 if you have the header file. */ -#undef HAVE_MACH_MACH_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the `mktime' function. */ -#undef HAVE_MKTIME - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -#undef HAVE_NDIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NLIST_H - -/* Define if you are building with_pam */ -#undef WITH_PAM - -/* Define to 1 if you have the `pstat_getdynamic' function. */ -#undef HAVE_PSTAT_GETDYNAMIC - -/* Define to 1 if you have the header file. */ -#undef HAVE_SECURITY_PAM_APPL_H - -/* Define to 1 if you have the `setlocale' function. */ -#undef HAVE_SETLOCALE - -/* Define to 1 if you have the `setresuid' function. */ -#undef HAVE_SETRESUID - -/* Define to 1 if you have the `setreuid' function. */ -#undef HAVE_SETREUID - -/* Define to 1 if you have the `sigaction' function. */ -#undef HAVE_SIGACTION - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDARG_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the `strftime' function. */ -#undef HAVE_STRFTIME - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if `n_un.n_name' is a member of `struct nlist'. */ -#undef HAVE_STRUCT_NLIST_N_UN_N_NAME - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYSLOG_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_DIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_FCNTL_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_NDIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have that is POSIX.1 compatible. */ -#undef HAVE_SYS_WAIT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the `vprintf' function. */ -#undef HAVE_VPRINTF - -/* Define to 1 if you have the `waitpid' function. */ -#undef HAVE_WAITPID - -/* Define to 1 if we need to provide our own yywrap() */ -#undef NEED_YYWRAP - -/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend - on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ -#undef NLIST_NAME_UNION - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* What is the name of our PID file? */ -#undef PIDFILE - -/* Define as the return type of signal handlers (`int' or `void'). */ -#undef RETSIGTYPE - -/* Define mail command for sending */ -#undef SENDMAIL - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define to 1 on System V Release 4. */ -#undef SVR4 - -/* Define to 1 if your declares `struct tm'. */ -#undef TM_IN_SYS_TIME - -/* Define to 1 for Encore UMAX. */ -#undef UMAX - -/* Define to 1 for Encore UMAX 4.3 that has instead of - . */ -#undef UMAX4_3 - -/* Define if you are building with_selinux */ -#undef WITH_SELINUX - -/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a - `char[]'. */ -#undef YYTEXT_POINTER - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to `int' if doesn't define. */ -#undef gid_t - -/* Define to `int' if does not define. */ -#undef mode_t - -/* Define to `long int' if does not define. */ -#undef off_t - -/* Define to `int' if does not define. */ -#undef pid_t - -/* Define to `unsigned int' if does not define. */ -#undef size_t - -/* Define to `int' if doesn't define. */ -#undef uid_t diff --git a/config.sub b/config.sub index 826e4c6..30fdca8 100755 --- a/config.sub +++ b/config.sub @@ -2,9 +2,9 @@ # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. +# 2011 Free Software Foundation, Inc. -timestamp='2012-10-10' +timestamp='2011-03-23' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -21,7 +21,9 @@ timestamp='2012-10-10' # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -74,8 +76,8 @@ version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -123,17 +125,13 @@ esac maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] @@ -156,7 +154,7 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) + -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; @@ -225,12 +223,6 @@ case $os in -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; -lynx*) os=-lynxos ;; @@ -255,25 +247,20 @@ case $basic_machine in # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ - | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ - | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ - | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ @@ -304,7 +291,7 @@ case $basic_machine in | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ - | rl78 | rx \ + | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ @@ -313,7 +300,7 @@ case $basic_machine in | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | v850 | v850e \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) @@ -328,7 +315,8 @@ case $basic_machine in c6x) basic_machine=tic6x-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; @@ -341,10 +329,7 @@ case $basic_machine in strongarm | thumb | xscale) basic_machine=arm-unknown ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; + xscaleeb) basic_machine=armeb-unknown ;; @@ -367,13 +352,11 @@ case $basic_machine in # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ - | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ - | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ @@ -382,15 +365,12 @@ case $basic_machine in | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ - | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ @@ -420,7 +400,7 @@ case $basic_machine in | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ + | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ @@ -428,11 +408,10 @@ case $basic_machine in | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ + | tile-* | tilegx-* \ | tron-* \ | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ + | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -732,6 +711,7 @@ case $basic_machine in i370-ibm* | ibm*) basic_machine=i370-ibm ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 @@ -789,13 +769,9 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; - microblaze*) + microblaze) basic_machine=microblaze-xilinx ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; mingw32) basic_machine=i386-pc os=-mingw32 @@ -832,18 +808,10 @@ case $basic_machine in ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; - msys) - basic_machine=i386-pc - os=-msys - ;; mvs) basic_machine=i370-ibm os=-mvs ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; ncr3000) basic_machine=i486-ncr os=-sysv4 @@ -1152,8 +1120,13 @@ case $basic_machine in basic_machine=t90-cray os=-unicos ;; + # This must be matched before tile*. + tilegx*) + basic_machine=tilegx-unknown + os=-linux-gnu + ;; tile*) - basic_machine=$basic_machine-unknown + basic_machine=tile-unknown os=-linux-gnu ;; tx39) @@ -1357,15 +1330,15 @@ case $os in | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ + | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ @@ -1548,9 +1521,6 @@ case $basic_machine in c4x-* | tic4x-*) os=-coff ;; - hexagon-*) - os=-elf - ;; tic54x-*) os=-coff ;; @@ -1578,6 +1548,9 @@ case $basic_machine in ;; m68000-sun) os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 ;; m68*-cisco) os=-aout diff --git a/config.sub.arm b/config.sub.arm deleted file mode 100755 index 30fdca8..0000000 --- a/config.sub.arm +++ /dev/null @@ -1,1760 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011 Free Software Foundation, Inc. - -timestamp='2011-03-23' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Please send patches to . Submit a context -# diff and a properly formatted GNU ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free -Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 \ - | ns16k | ns32k \ - | open8 \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | picochip) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile-* | tilegx-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze) - basic_machine=microblaze-xilinx - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - # This must be matched before tile*. - tilegx*) - basic_machine=tilegx-unknown - os=-linux-gnu - ;; - tile*) - basic_machine=tile-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/configure.ac b/configure.ac index ef3aaa1..75b6393 100644 --- a/configure.ac +++ b/configure.ac @@ -78,7 +78,7 @@ AC_FUNC_GETLOADAVG AC_CHECK_FUNCS(getcwd mktime strftime setreuid setresuid sigaction waitpid) AC_CHECK_HEADERS(security/pam_appl.h, [ PAMLIB="-lpam" - AC_DEFINE(WITH_PAM, 1, [Define to 1 for PAM support]) + AC_DEFINE(HAVE_PAM, 1, [Define to 1 for PAM support]) ]) dnl Checking for programs @@ -239,13 +239,6 @@ AC_ARG_WITH(daemon_username, ) AC_SUBST(DAEMON_USERNAME) -AC_ARG_WITH(pam, -[ --with-pam Define to enable pam support ], -AC_DEFINE(WITH_PAM), -) -AC_CHECK_LIB(pam, pam_start, PAMLIB='-lpam -lpam_misc') -AC_SUBST(PAMLIB) - AC_ARG_WITH(selinux, [ --with-selinux Define to run with selinux (default=check)], [], @@ -265,10 +258,6 @@ fi AC_SUBST(SELINUXLIB) AC_SUBST(WITH_SELINUX) -dnl check for POSIX timer functions -AC_SEARCH_LIBS([timer_create],[rt]) -AC_CHECK_FUNCS([timer_create]) - AC_MSG_CHECKING(groupname to run under) AC_ARG_WITH(daemon_groupname, [ --with-daemon_groupname=DAEMON_GROUPNAME Groupname to run under (default daemon) ], diff --git a/configure.ac.pam b/configure.ac.pam deleted file mode 100644 index 75b6393..0000000 --- a/configure.ac.pam +++ /dev/null @@ -1,283 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. - -AC_INIT(at, 3.1.20) -AC_CONFIG_SRCDIR(at.c) - -AC_PREFIX_DEFAULT(/usr) -AC_CONFIG_HEADER(config.h) -AC_PREREQ([2.64]) - -VERSION=AC_PACKAGE_VERSION -if test "X$CFLAGS" = "X"; then -CFLAGS="-O2 -g -Wall" -fi - -AC_SUBST(VERSION) - -AC_CANONICAL_HOST - -dnl Checks for programs. - -AC_PROG_CC -AC_PROG_INSTALL -AC_PROG_LN_S -AC_PROG_YACC -AC_PROG_LEX - -AC_MSG_CHECKING(HP-UX -Aa) - -case "$host" in - *-*-hpux*) - # HPUX flags from jgotts@engin.umich.edu - if test -z "$GCC"; then - CFLAGS="$CFLAGS -Aa -D_HPUX_SOURCE" - fi - AC_MSG_RESULT(yes) - ;; - *) - AC_MSG_RESULT(no) - ;; -esac - -AC_MSG_CHECKING(__attribute__((noreturn))) -AC_TRY_COMPILE([], [void __attribute__((noreturn)) panic(void);], - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_ATTRIBUTE_NORETURN, 1, - [Define to 1 if compiler supports __attribute__((noreturn))]), - AC_MSG_RESULT(no) -) -dnl Checks for libraries. - -AC_CHECK_LIB(fl,yywrap, - [], - AC_DEFINE(NEED_YYWRAP, 1, - [Define to 1 if we need to provide our own yywrap()]) -) - -dnl Checks for header files. -AC_HEADER_DIRENT -AC_HEADER_STDC -AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(fcntl.h syslog.h unistd.h errno.h sys/fcntl.h getopt.h) -AC_CHECK_HEADERS(stdarg.h) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_TYPE_SIGNAL -AC_TYPE_UID_T -AC_TYPE_MODE_T -AC_TYPE_OFF_T -AC_TYPE_PID_T -AC_TYPE_SIZE_T -AC_STRUCT_TM - - -dnl Checks for library functions. -AC_FUNC_VPRINTF -AC_FUNC_GETLOADAVG -AC_CHECK_FUNCS(getcwd mktime strftime setreuid setresuid sigaction waitpid) -AC_CHECK_HEADERS(security/pam_appl.h, [ - PAMLIB="-lpam" - AC_DEFINE(HAVE_PAM, 1, [Define to 1 for PAM support]) -]) - -dnl Checking for programs - -AC_PATH_PROG(SENDMAIL, sendmail, , $PATH:/usr/lib:/usr/sbin ) -if test "$SENDMAIL" != "" ; then -AC_DEFINE_UNQUOTED(SENDMAIL,"$SENDMAIL", [Define mail command for sending]) -MAIL_CMD="$SENDMAIL" -fi - -AC_SUBST(MAIL_CMD) -AC_SUBST(PAMLIB) - -AC_MSG_CHECKING(etcdir) -AC_ARG_WITH(etcdir, -[ --with-etcdir=PATH Directory containing permission files (default /etc).], -[ case "$withval" in - no) - AC_MSG_ERROR(Need ETCDIR.) - ;; - yes) - ETCDIR=/etc - AC_MSG_RESULT(/etc) - ;; - *) - ETCDIR="$withval" - AC_MSG_RESULT($withval) - ;; - esac ], - ETCDIR="/etc" - AC_MSG_RESULT(/etc) -) -AC_SUBST(ETCDIR) - -AC_ARG_WITH(systemdsystemunitdir, -[ --with-systemdsystemunitdir=PATH Directory for systemd service files], -[], -[with_systemdsystemunitdir=no] -) -AC_SUBST(systemdsystemunitdir, [$with_systemdsystemunitdir]) - -AC_MSG_CHECKING(location of pid file) -if test -d /var/run ; then - PIDDIR=/var/run -elif test -d /usr/run ; then - PIDDIR=/usr/run -else - PIDDIR="$ETCDIR" -fi -AC_DEFINE_UNQUOTED(PIDFILE, "$PIDDIR/atd.pid", [What is the name of our PID file?]) -AC_MSG_RESULT($PIDDIR) - -AC_MSG_CHECKING(location of spool directory) -if test -d /var/spool/atjobs ; then - sp=/var/spool - AC_MSG_RESULT(Using existing /var/spool/at{jobs|run}) -elif test -d /var/spool/cron ; then - sp=/var/spool/cron - AC_MSG_RESULT(/var/spool/cron) -elif test -d /usr/spool/cron ; then - sp=/usr/spool/cron - AC_MSG_RESULT(/usr/spool/cron) -else - AC_MSG_RESULT(not found) -fi - -AC_MSG_CHECKING(jobdir) -AC_ARG_WITH(jobdir, -[ --with-jobdir=PATH Directory containing at jobs (default SPOOLDIR/atjobs).], -[ case "$withval" in - no) - AC_MSG_ERROR(Need JOBDIR.) - ;; - yes) - if test x$sp == x ; then - AC_MSG_ERROR(Need explicit JOBDIR when SPOOLDIR not found.) - fi - ATJBD="$sp/atjobs" - ;; - *) - ATJBD="$withval" - ;; - esac ], - if test x$sp == x ; then - AC_MSG_ERROR(Need --with-jobdir=PATH when SPOOLDIR not found.) - fi - ATJBD="$sp/atjobs" -) -AC_DEFINE_UNQUOTED(ATJOB_DIR, "$ATJBD", [Where do we place out input directories?]) -AC_MSG_RESULT($ATJBD) -AC_SUBST(ATJBD) - -AC_MSG_CHECKING(atspool) -AC_ARG_WITH(atspool, -[ --with-atspool=PATH Directory containing at spool (default SPOOLDIR/atspool).], -[ case "$withval" in - no) - AC_MSG_ERROR(Need ATSPOOL.) - ;; - yes) - if test x$sp == x ; then - AC_MSG_ERROR(Need explicit ATSPOOL when SPOOLDIR not found.) - fi - ATSPD=$sp/atspool - ;; - *) - ATSPD=$withval - ;; - esac ], - if test x$sp == x ; then - AC_MSG_ERROR(Need --with-atspool=PATH when SPOOLDIR not found.) - fi - ATSPD=$sp/atspool -) -AC_DEFINE_UNQUOTED(ATSPOOL_DIR, "$ATSPD", [Where do we spool our output?]) -AC_MSG_RESULT($ATSPD) -AC_SUBST(ATSPD) - -AC_MSG_CHECKING(maximum load average for batch to start jobs) -AC_ARG_WITH(loadavg_mx, -[ --with-loadavg_mx=LOADAVG_MX Default max. load average for batch (default 0.8). ], -[ case "$withval" in - no) - AC_MSG_ERROR(Need LOADAVG_MX.) - ;; - yes) - LOADAVG_MX=0.8 - AC_MSG_RESULT(0.8) - ;; - *) - LOADAVG_MX="$withval"; - AC_MSG_RESULT($withval) - ;; - esac ], - LOADAVG_MX=0.8 - AC_MSG_RESULT(0.8) -) -AC_SUBST(LOADAVG_MX) - -AC_MSG_CHECKING(username to run under) -AC_ARG_WITH(daemon_username, -[ --with-daemon_username=DAEMON_USERNAME Username to run under (default daemon) ], -[ case "$withval" in - no) - AC_MSG_ERROR(Need DAEMON_USERNAME.) - ;; - yes) - DAEMON_USERNAME=daemon - AC_MSG_RESULT(daemon) - ;; - *) - DAEMON_USERNAME="$withval"; - AC_MSG_RESULT($withval) - ;; - esac ], - DAEMON_USERNAME=daemon - AC_MSG_RESULT(daemon) -) -AC_SUBST(DAEMON_USERNAME) - -AC_ARG_WITH(selinux, -[ --with-selinux Define to run with selinux (default=check)], -[], -[with_selinux=check]) - -if test "x$with_selinux" != xno; then - AC_CHECK_LIB([selinux], [is_selinux_enabled], - [SELINUXLIB=-lselinux - AC_DEFINE(WITH_SELINUX, 1, [Define if you are building with_selinux]) - ], - [if test "x$with_selinux" != xcheck; then - AC_MSG_FAILURE([--with-selinux is given, but test for selinux failed $with_selinux]) - fi - ] - ) -fi -AC_SUBST(SELINUXLIB) -AC_SUBST(WITH_SELINUX) - -AC_MSG_CHECKING(groupname to run under) -AC_ARG_WITH(daemon_groupname, -[ --with-daemon_groupname=DAEMON_GROUPNAME Groupname to run under (default daemon) ], -[ case "$withval" in - no) - AC_MSG_ERROR(Need DAEMON_GROUPNAME.) - ;; - yes) - DAEMON_GROUPNAME=daemon - AC_MSG_RESULT(daemon) - ;; - *) - DAEMON_GROUPNAME="$withval"; - AC_MSG_RESULT($withval) - ;; - esac ], - DAEMON_GROUPNAME=daemon - AC_MSG_RESULT(daemon) -) -AC_SUBST(DAEMON_GROUPNAME) - -AC_CONFIG_FILES(Makefile atrun atd.8 atrun.8 at.1 at.allow.5 batch) -AC_OUTPUT diff --git a/configure.ac.posix b/configure.ac.posix deleted file mode 100644 index 6af123f..0000000 --- a/configure.ac.posix +++ /dev/null @@ -1,290 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. - -AC_INIT(at, 3.1.20) -AC_CONFIG_SRCDIR(at.c) - -AC_PREFIX_DEFAULT(/usr) -AC_CONFIG_HEADER(config.h) -AC_PREREQ([2.64]) - -VERSION=AC_PACKAGE_VERSION -if test "X$CFLAGS" = "X"; then -CFLAGS="-O2 -g -Wall" -fi - -AC_SUBST(VERSION) - -AC_CANONICAL_HOST - -dnl Checks for programs. - -AC_PROG_CC -AC_PROG_INSTALL -AC_PROG_LN_S -AC_PROG_YACC -AC_PROG_LEX - -AC_MSG_CHECKING(HP-UX -Aa) - -case "$host" in - *-*-hpux*) - # HPUX flags from jgotts@engin.umich.edu - if test -z "$GCC"; then - CFLAGS="$CFLAGS -Aa -D_HPUX_SOURCE" - fi - AC_MSG_RESULT(yes) - ;; - *) - AC_MSG_RESULT(no) - ;; -esac - -AC_MSG_CHECKING(__attribute__((noreturn))) -AC_TRY_COMPILE([], [void __attribute__((noreturn)) panic(void);], - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_ATTRIBUTE_NORETURN, 1, - [Define to 1 if compiler supports __attribute__((noreturn))]), - AC_MSG_RESULT(no) -) -dnl Checks for libraries. - -AC_CHECK_LIB(fl,yywrap, - [], - AC_DEFINE(NEED_YYWRAP, 1, - [Define to 1 if we need to provide our own yywrap()]) -) - -dnl Checks for header files. -AC_HEADER_DIRENT -AC_HEADER_STDC -AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(fcntl.h syslog.h unistd.h errno.h sys/fcntl.h getopt.h) -AC_CHECK_HEADERS(stdarg.h) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_TYPE_SIGNAL -AC_TYPE_UID_T -AC_TYPE_MODE_T -AC_TYPE_OFF_T -AC_TYPE_PID_T -AC_TYPE_SIZE_T -AC_STRUCT_TM - - -dnl Checks for library functions. -AC_FUNC_VPRINTF -AC_FUNC_GETLOADAVG -AC_CHECK_FUNCS(getcwd mktime strftime setreuid setresuid sigaction waitpid) -AC_CHECK_HEADERS(security/pam_appl.h, [ - PAMLIB="-lpam" - AC_DEFINE(WITH_PAM, 1, [Define to 1 for PAM support]) -]) - -dnl Checking for programs - -AC_PATH_PROG(SENDMAIL, sendmail, , $PATH:/usr/lib:/usr/sbin ) -if test "$SENDMAIL" != "" ; then -AC_DEFINE_UNQUOTED(SENDMAIL,"$SENDMAIL", [Define mail command for sending]) -MAIL_CMD="$SENDMAIL" -fi - -AC_SUBST(MAIL_CMD) -AC_SUBST(PAMLIB) - -AC_MSG_CHECKING(etcdir) -AC_ARG_WITH(etcdir, -[ --with-etcdir=PATH Directory containing permission files (default /etc).], -[ case "$withval" in - no) - AC_MSG_ERROR(Need ETCDIR.) - ;; - yes) - ETCDIR=/etc - AC_MSG_RESULT(/etc) - ;; - *) - ETCDIR="$withval" - AC_MSG_RESULT($withval) - ;; - esac ], - ETCDIR="/etc" - AC_MSG_RESULT(/etc) -) -AC_SUBST(ETCDIR) - -AC_ARG_WITH(systemdsystemunitdir, -[ --with-systemdsystemunitdir=PATH Directory for systemd service files], -[], -[with_systemdsystemunitdir=no] -) -AC_SUBST(systemdsystemunitdir, [$with_systemdsystemunitdir]) - -AC_MSG_CHECKING(location of pid file) -if test -d /var/run ; then - PIDDIR=/var/run -elif test -d /usr/run ; then - PIDDIR=/usr/run -else - PIDDIR="$ETCDIR" -fi -AC_DEFINE_UNQUOTED(PIDFILE, "$PIDDIR/atd.pid", [What is the name of our PID file?]) -AC_MSG_RESULT($PIDDIR) - -AC_MSG_CHECKING(location of spool directory) -if test -d /var/spool/atjobs ; then - sp=/var/spool - AC_MSG_RESULT(Using existing /var/spool/at{jobs|run}) -elif test -d /var/spool/cron ; then - sp=/var/spool/cron - AC_MSG_RESULT(/var/spool/cron) -elif test -d /usr/spool/cron ; then - sp=/usr/spool/cron - AC_MSG_RESULT(/usr/spool/cron) -else - AC_MSG_RESULT(not found) -fi - -AC_MSG_CHECKING(jobdir) -AC_ARG_WITH(jobdir, -[ --with-jobdir=PATH Directory containing at jobs (default SPOOLDIR/atjobs).], -[ case "$withval" in - no) - AC_MSG_ERROR(Need JOBDIR.) - ;; - yes) - if test x$sp == x ; then - AC_MSG_ERROR(Need explicit JOBDIR when SPOOLDIR not found.) - fi - ATJBD="$sp/atjobs" - ;; - *) - ATJBD="$withval" - ;; - esac ], - if test x$sp == x ; then - AC_MSG_ERROR(Need --with-jobdir=PATH when SPOOLDIR not found.) - fi - ATJBD="$sp/atjobs" -) -AC_DEFINE_UNQUOTED(ATJOB_DIR, "$ATJBD", [Where do we place out input directories?]) -AC_MSG_RESULT($ATJBD) -AC_SUBST(ATJBD) - -AC_MSG_CHECKING(atspool) -AC_ARG_WITH(atspool, -[ --with-atspool=PATH Directory containing at spool (default SPOOLDIR/atspool).], -[ case "$withval" in - no) - AC_MSG_ERROR(Need ATSPOOL.) - ;; - yes) - if test x$sp == x ; then - AC_MSG_ERROR(Need explicit ATSPOOL when SPOOLDIR not found.) - fi - ATSPD=$sp/atspool - ;; - *) - ATSPD=$withval - ;; - esac ], - if test x$sp == x ; then - AC_MSG_ERROR(Need --with-atspool=PATH when SPOOLDIR not found.) - fi - ATSPD=$sp/atspool -) -AC_DEFINE_UNQUOTED(ATSPOOL_DIR, "$ATSPD", [Where do we spool our output?]) -AC_MSG_RESULT($ATSPD) -AC_SUBST(ATSPD) - -AC_MSG_CHECKING(maximum load average for batch to start jobs) -AC_ARG_WITH(loadavg_mx, -[ --with-loadavg_mx=LOADAVG_MX Default max. load average for batch (default 0.8). ], -[ case "$withval" in - no) - AC_MSG_ERROR(Need LOADAVG_MX.) - ;; - yes) - LOADAVG_MX=0.8 - AC_MSG_RESULT(0.8) - ;; - *) - LOADAVG_MX="$withval"; - AC_MSG_RESULT($withval) - ;; - esac ], - LOADAVG_MX=0.8 - AC_MSG_RESULT(0.8) -) -AC_SUBST(LOADAVG_MX) - -AC_MSG_CHECKING(username to run under) -AC_ARG_WITH(daemon_username, -[ --with-daemon_username=DAEMON_USERNAME Username to run under (default daemon) ], -[ case "$withval" in - no) - AC_MSG_ERROR(Need DAEMON_USERNAME.) - ;; - yes) - DAEMON_USERNAME=daemon - AC_MSG_RESULT(daemon) - ;; - *) - DAEMON_USERNAME="$withval"; - AC_MSG_RESULT($withval) - ;; - esac ], - DAEMON_USERNAME=daemon - AC_MSG_RESULT(daemon) -) -AC_SUBST(DAEMON_USERNAME) - -AC_ARG_WITH(pam, -[ --with-pam Define to enable pam support ], -AC_DEFINE(WITH_PAM), -) -AC_CHECK_LIB(pam, pam_start, PAMLIB='-lpam -lpam_misc') -AC_SUBST(PAMLIB) - -AC_ARG_WITH(selinux, -[ --with-selinux Define to run with selinux (default=check)], -[], -[with_selinux=check]) - -if test "x$with_selinux" != xno; then - AC_CHECK_LIB([selinux], [is_selinux_enabled], - [SELINUXLIB=-lselinux - AC_DEFINE(WITH_SELINUX, 1, [Define if you are building with_selinux]) - ], - [if test "x$with_selinux" != xcheck; then - AC_MSG_FAILURE([--with-selinux is given, but test for selinux failed $with_selinux]) - fi - ] - ) -fi -AC_SUBST(SELINUXLIB) -AC_SUBST(WITH_SELINUX) - -AC_MSG_CHECKING(groupname to run under) -AC_ARG_WITH(daemon_groupname, -[ --with-daemon_groupname=DAEMON_GROUPNAME Groupname to run under (default daemon) ], -[ case "$withval" in - no) - AC_MSG_ERROR(Need DAEMON_GROUPNAME.) - ;; - yes) - DAEMON_GROUPNAME=daemon - AC_MSG_RESULT(daemon) - ;; - *) - DAEMON_GROUPNAME="$withval"; - AC_MSG_RESULT($withval) - ;; - esac ], - DAEMON_GROUPNAME=daemon - AC_MSG_RESULT(daemon) -) -AC_SUBST(DAEMON_GROUPNAME) - -AC_CONFIG_FILES(Makefile atrun atd.8 atrun.8 at.1 at.allow.5 batch) -AC_OUTPUT diff --git a/parsetime.y b/parsetime.y index 7cb2ad3..7005e88 100644 --- a/parsetime.y +++ b/parsetime.y @@ -476,8 +476,8 @@ parsetime(time_t currtime, int argc, char **argv) exectm = *localtime(&currtime); currtime -= exectm.tm_sec; exectm.tm_sec = 0; - memcpy(&currtm,&exectm,sizeof(currtm)); exectm.tm_isdst = -1; + memcpy(&currtm,&exectm,sizeof(currtm)); time_only = 0; yearspec = 0; @@ -503,8 +503,8 @@ parsetime(time_t currtime, int argc, char **argv) return 0; if (isgmt) { exectime -= timezone; - if (exectm.tm_isdst) - exectime += 3600; + if (currtm.tm_isdst && !exectm.tm_isdst) + exectime -= 3600; } if (exectime < currtime) panic("refusing to create job destined in the past"); diff --git a/parsetime.y.dst b/parsetime.y.dst deleted file mode 100644 index 7005e88..0000000 --- a/parsetime.y.dst +++ /dev/null @@ -1,650 +0,0 @@ -%{ -#include -#include -#include -#include -#include "parsetime.h" -#include "panic.h" - -#define YYDEBUG 1 - -struct tm exectm; -static int isgmt; -static int yearspec; -static int time_only; - -extern int yyerror(char *s); -extern int yylex(); - -int add_date(int number, int period); -%} - -%union { - char * charval; - int intval; -} - -%token DOTTEDDATE -%token HYPHENDATE -%token HOURMIN -%token INT1DIGIT -%token INT2DIGIT -%token INT4DIGIT -%token INT5_8DIGIT -%token INT -%token NOW -%token AM PM -%token NOON MIDNIGHT TEATIME -%token SUN MON TUE WED THU FRI SAT -%token TODAY TOMORROW -%token NEXT -%token MINUTE HOUR DAY WEEK MONTH YEAR -%token JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC -%token UTC - -%type concatenated_date -%type hr24clock_hr_min -%type int1_2digit -%type int2_or_4digit -%type integer -%type inc_dec_period -%type inc_dec_number -%type day_of_week - -%start timespec -%% -timespec : spec_base - | spec_base inc_or_dec - ; - -spec_base : date - | time - { - time_only = 1; - } - | time date - | NOW - { - yearspec = 1; - } - ; - -time : time_base - | time_base timezone_name - ; - -time_base : hr24clock_hr_min - { - exectm.tm_min = -1; - exectm.tm_hour = -1; - sscanf($1, "%2d %2d", &exectm.tm_hour, - &exectm.tm_min); - free($1); - - if (exectm.tm_min > 60 || exectm.tm_min < 0) { - yyerror("Problem in minutes specification"); - YYERROR; - } - if (exectm.tm_hour > 24 || exectm.tm_hour < 0) { - yyerror("Problem in hours specification"); - YYERROR; - } - } - | time_hour am_pm - | time_hour_min - | time_hour_min am_pm - | NOON - { - exectm.tm_hour = 12; - exectm.tm_min = 0; - } - | MIDNIGHT - { - exectm.tm_hour = 0; - exectm.tm_min = 0; - } - | TEATIME - { - exectm.tm_hour = 16; - exectm.tm_min = 0; - } - ; - -hr24clock_hr_min: INT4DIGIT - ; - -time_hour : int1_2digit - { - sscanf($1, "%d", &exectm.tm_hour); - exectm.tm_min = 0; - free($1); - - if (exectm.tm_hour > 24 || exectm.tm_hour < 0) { - yyerror("Problem in hours specification"); - YYERROR; - } - } - ; - -time_hour_min : HOURMIN - { - exectm.tm_min = -1; - exectm.tm_hour = -1; - sscanf($1, "%d %*c %d", &exectm.tm_hour, - &exectm.tm_min); - free($1); - - if (exectm.tm_min > 60 || exectm.tm_min < 0) { - yyerror("Problem in minutes specification"); - YYERROR; - } - if (exectm.tm_hour > 24 || exectm.tm_hour < 0) { - yyerror("Problem in hours specification"); - YYERROR; - } - } - ; - -am_pm : AM - { - if (exectm.tm_hour > 12) { - yyerror("Hour too large for AM"); - YYERROR; - } - else if (exectm.tm_hour == 12) { - exectm.tm_hour = 0; - } - } - | PM - { - if (exectm.tm_hour > 12) { - yyerror("Hour too large for PM"); - YYERROR; - } - else if (exectm.tm_hour < 12) { - exectm.tm_hour +=12; - } - } - ; - -timezone_name : UTC - { - isgmt = 1; - } - ; - -date : month_name day_number - | month_name day_number year_number - | month_name day_number ',' year_number - | day_of_week - { - add_date ((6 + $1 - exectm.tm_wday) %7 + 1, DAY); - } - | TODAY - | TOMORROW - { - add_date(1, DAY); - } - | HYPHENDATE - { - int ynum = -1; - int mnum = -1; - int dnum = -1; - - yearspec = 1; - if (sscanf($1, "%d %*c %d %*c %d", &ynum, &mnum, &dnum) != 3) { - yyerror("Error in hypenated date"); - YYERROR; - } - - if (mnum < 1 || mnum > 12) { - yyerror("Error in month number"); - YYERROR; - } - exectm.tm_mon = mnum -1; - - if (ynum < 70) { - ynum += 100; - } - else if (ynum > 1900) { - ynum -= 1900; - } - exectm.tm_year = ynum ; - - if ( dnum < 1 - || ((mnum == 1 || mnum == 3 || mnum == 5 || - mnum == 7 || mnum == 8 || mnum == 10 || - mnum == 12) && dnum > 31) - || ((mnum == 4 || mnum == 6 || mnum == 9 || - mnum == 11) && dnum > 30) - || (mnum == 2 && dnum > 29 && __isleap(ynum+1900)) - || (mnum == 2 && dnum > 28 && !__isleap(ynum+1900)) - ) - { - yyerror("Error in day of month"); - YYERROR; - } - exectm.tm_mday = dnum; - - free($1); - } - | DOTTEDDATE - { - int ynum = -1; - int mnum = -1; - int dnum = -1; - - yearspec = 1; - - if (sscanf($1, "%d %*c %d %*c %d", &dnum, &mnum, &ynum) != 3) { - yyerror("Error in dotted date"); - YYERROR; - } - - if (mnum < 1 || mnum > 12) { - yyerror("Error in month number"); - YYERROR; - } - exectm.tm_mon = mnum -1; - - if (ynum < 70) { - ynum += 100; - } - else if (ynum > 1900) { - ynum -= 1900; - } - exectm.tm_year = ynum ; - - if ( dnum < 1 - || ((mnum == 1 || mnum == 3 || mnum == 5 || - mnum == 7 || mnum == 8 || mnum == 10 || - mnum == 12) && dnum > 31) - || ((mnum == 4 || mnum == 6 || mnum == 9 || - mnum == 11) && dnum > 30) - || (mnum == 2 && dnum > 29 && __isleap(ynum+1900)) - || (mnum == 2 && dnum > 28 && !__isleap(ynum+1900)) - ) - { - yyerror("Error in day of month"); - YYERROR; - } - exectm.tm_mday = dnum; - - free($1); - } - | day_number month_name - | day_number month_name year_number - | month_number '/' day_number '/' year_number - | concatenated_date - { - /* Ok, this is a kluge. I hate design errors... -Joey */ - char shallot[5]; - char *onion; - - yearspec = 1; - onion=$1; - memset (shallot, 0, sizeof (shallot)); - if (strlen($1) == 5 || strlen($1) == 7) { - strncpy (shallot,onion,1); - onion++; - } else { - strncpy (shallot,onion,2); - onion+=2; - } - sscanf(shallot, "%d", &exectm.tm_mon); - - if (exectm.tm_mon < 1 || exectm.tm_mon > 12) { - yyerror("Error in month number"); - YYERROR; - } - exectm.tm_mon--; - - memset (shallot, 0, sizeof (shallot)); - strncpy (shallot,onion,2); - sscanf(shallot, "%d", &exectm.tm_mday); - if (exectm.tm_mday < 0 || exectm.tm_mday > 31) - { - yyerror("Error in day of month"); - YYERROR; - } - - onion+=2; - memset (shallot, 0, sizeof (shallot)); - strncpy (shallot,onion,4); - if ( sscanf(shallot, "%d", &exectm.tm_year) != 1) { - yyerror("Error in year"); - YYERROR; - } - if (exectm.tm_year < 70) { - exectm.tm_year += 100; - } - else if (exectm.tm_year > 1900) { - exectm.tm_year -= 1900; - } - - free ($1); - } - | NEXT inc_dec_period - { - add_date(1, $2); - } - | NEXT day_of_week - { - add_date ((6 + $2 - exectm.tm_wday) %7 +1, DAY); - } - ; - -concatenated_date: INT5_8DIGIT - ; - -month_name : JAN { exectm.tm_mon = 0; } - | FEB { exectm.tm_mon = 1; } - | MAR { exectm.tm_mon = 2; } - | APR { exectm.tm_mon = 3; } - | MAY { exectm.tm_mon = 4; } - | JUN { exectm.tm_mon = 5; } - | JUL { exectm.tm_mon = 6; } - | AUG { exectm.tm_mon = 7; } - | SEP { exectm.tm_mon = 8; } - | OCT { exectm.tm_mon = 9; } - | NOV { exectm.tm_mon =10; } - | DEC { exectm.tm_mon =11; } - ; - -month_number : int1_2digit - { - { - int mnum = -1; - sscanf($1, "%d", &mnum); - - if (mnum < 1 || mnum > 12) { - yyerror("Error in month number"); - YYERROR; - } - exectm.tm_mon = mnum -1; - free($1); - } - } - ; - -day_number : int1_2digit - { - exectm.tm_mday = -1; - sscanf($1, "%d", &exectm.tm_mday); - if (exectm.tm_mday < 1 || exectm.tm_mday > 31) - { - yyerror("Error in day of month"); - YYERROR; - } - free($1); - } - ; - -year_number : int2_or_4digit - { - yearspec = 1; - { - int ynum; - - if ( sscanf($1, "%d", &ynum) != 1) { - yyerror("Error in year"); - YYERROR; - } - if (ynum < 70) { - ynum += 100; - } - else if (ynum > 1900) { - ynum -= 1900; - } - - exectm.tm_year = ynum ; - free($1); - } - } - ; - -day_of_week : SUN { $$ = 0; } - | MON { $$ = 1; } - | TUE { $$ = 2; } - | WED { $$ = 3; } - | THU { $$ = 4; } - | FRI { $$ = 5; } - | SAT { $$ = 6; } - ; - -inc_or_dec : increment - | decrement - ; - -increment : '+' inc_dec_number inc_dec_period - { - add_date($2, $3); - } - ; - -decrement : '-' inc_dec_number inc_dec_period - { - add_date(-$2, $3); - } - ; - -inc_dec_number : integer - { - if (sscanf($1, "%d", &$$) != 1) { - yyerror("Unknown increment"); - YYERROR; - } - free($1); - } - ; - -inc_dec_period : MINUTE { $$ = MINUTE ; } - | HOUR { $$ = HOUR ; } - | DAY { $$ = DAY ; time_only = 0; } - | WEEK { $$ = WEEK ; time_only = 0; } - | MONTH { $$ = MONTH ; time_only = 0; } - | YEAR { $$ = YEAR ; time_only = 0; } - ; - -int1_2digit : INT1DIGIT - | INT2DIGIT - ; - -int2_or_4digit : INT2DIGIT - | INT4DIGIT - ; - -integer : INT - | INT1DIGIT - | INT2DIGIT - | INT4DIGIT - | INT5_8DIGIT - ; - -%% - - -time_t parsetime(time_t, int, char **); - -time_t -parsetime(time_t currtime, int argc, char **argv) -{ - time_t exectime; - struct tm currtm; - - my_argv = argv; - exectm = *localtime(&currtime); - currtime -= exectm.tm_sec; - exectm.tm_sec = 0; - exectm.tm_isdst = -1; - memcpy(&currtm,&exectm,sizeof(currtm)); - time_only = 0; - yearspec = 0; - - if (yyparse() == 0) { - if (time_only) - { - if (exectm.tm_mday == currtm.tm_mday && - (exectm.tm_hour < currtm.tm_hour || - (exectm.tm_hour == currtm.tm_hour && - exectm.tm_min <= currtm.tm_min))) - exectm.tm_mday++; - } - else if (!yearspec) { - if (exectm.tm_year == currtm.tm_year && - (exectm.tm_mon < currtm.tm_mon || - (exectm.tm_mon == currtm.tm_mon && - exectm.tm_mday < currtm.tm_mday))) - exectm.tm_year++; - } - - exectime = mktime(&exectm); - if (exectime == (time_t)-1) - return 0; - if (isgmt) { - exectime -= timezone; - if (currtm.tm_isdst && !exectm.tm_isdst) - exectime -= 3600; - } - if (exectime < currtime) - panic("refusing to create job destined in the past"); - return exectime; - } - else { - return 0; - } -} - -#ifdef TEST_PARSER - -int -main(int argc, char **argv) -{ - int retval = 1; - time_t res; - time_t currtime; - - if (argc < 3) { - fprintf(stderr, "usage: parsetest [now] [timespec] ...\n"); - exit(EXIT_FAILURE); - } - - currtime = atoll(argv[1]); - res = parsetime(currtime, argc-2, argv + 2); - if (res > 0) { - printf("%s",ctime(&res)); - retval = 0; - } - else { - printf("Ooops...\n"); - retval = 1; - } - return retval; -} - -void -panic(char *a) -{ - fputs(a, stderr); - exit(EXIT_FAILURE); -} -#endif - -int yyerror(char *s) -{ - if (last_token == NULL) - last_token = "(empty)"; - fprintf(stderr,"%s. Last token seen: %s\n",s, last_token); - return 0; -} - -void -add_seconds(struct tm *tm, long numsec) -{ - struct tm basetm = *tm; - time_t timeval; - - timeval = mktime(tm); - if (timeval == (time_t)-1) - timeval = (time_t)0; - timeval += numsec; - *tm = *localtime(&timeval); - - /* - * Adjust +-1 hour when moving in or out of DST - */ - - if (daylight > 0) /* Only check if DST is used here */ - { - /* Set tm_isdst on &basetm and tm */ - (void) mktime(&basetm); - (void) mktime(tm); - - if (basetm.tm_isdst > 0 && tm->tm_isdst < 1) - { /* DST to no DST */ - timeval += 3600l; - *tm = *localtime(&timeval); - } - else if (basetm.tm_isdst < 1 && tm->tm_isdst > 0) - { /* no DST to DST */ - timeval -= 3600l; - *tm = *localtime(&timeval); - } - } -} - -int -add_date(int number, int period) -{ - switch(period) { - case MINUTE: - add_seconds(&exectm , 60l*number); - break; - - case HOUR: - add_seconds(&exectm, 3600l * number); - break; - - case DAY: - add_seconds(&exectm, 24*3600l * number); - break; - - case WEEK: - add_seconds(&exectm, 7*24*3600l*number); - break; - - case MONTH: - { - int newmonth = exectm.tm_mon + number; - number = 0; - while (newmonth < 0) { - newmonth += 12; - number --; - } - exectm.tm_mon = newmonth % 12; - number += newmonth / 12 ; - - /* Recalculate tm_isdst so we don't get a +-1 hour creep */ - exectm.tm_isdst = -1; - (void) mktime(&exectm); - } - if (number == 0) { - break; - } - /* fall through */ - - case YEAR: - exectm.tm_year += number; - /* Recalculate tm_isdst so we don't get a +-1 hour creep */ - exectm.tm_isdst = -1; - (void) mktime(&exectm); - break; - - default: - yyerror("Internal parser error"); - fprintf(stderr,"Unexpected case %d\n", period); - abort(); - } - - return 0; -} diff --git a/perm.c b/perm.c index 93b8af2..b35e384 100644 --- a/perm.c +++ b/perm.c @@ -51,14 +51,6 @@ #define PRIV_END while(0) #endif -#ifdef WITH_PAM -#include -static pam_handle_t *pamh = NULL; -static const struct pam_conv conv = { - NULL -}; -#endif - /* Structures and unions */ @@ -116,45 +108,18 @@ user_in_file(const char *path, const char *name) int check_permission() { - uid_t euid = geteuid(), uid=getuid(), egid=getegid(), gid=getgid(); + uid_t uid = geteuid(); struct passwd *pentry; int allow = 0, deny = 1; - int retcode = 0; - if (euid == 0) + if (uid == 0) return 1; - if ((pentry = getpwuid(euid)) == NULL) { + if ((pentry = getpwuid(uid)) == NULL) { perror("Cannot access user database"); exit(EXIT_FAILURE); } -#ifdef WITH_PAM -/* - * We must check if the atd daemon userid will be allowed to gain the job owner user's - * credentials with PAM . If not, the user has been denied at(1) usage, eg. with pam_access. - */ - if (setreuid(daemon_uid, daemon_uid) != 0) { - fprintf(stderr, "cannot set egid: %s", strerror(errno)); - exit(1); - } - if (setregid(daemon_gid, daemon_gid) != 0) { - fprintf(stderr, "cannot set euid: %s", strerror(errno)); - exit(1); - } - - AT_START_PAM; - AT_CLOSE_PAM; - if (setregid(gid,egid) != 0) { - fprintf(stderr, "cannot set egid: %s", strerror(errno)); - exit(1); - } - if (setreuid(uid,euid) != 0) { - fprintf(stderr, "cannot set euid: %s", strerror(errno)); - exit(1); - } -#endif - allow = user_in_file(ETCDIR "/at.allow", pentry->pw_name); if (allow==0 || allow==1) return allow; diff --git a/perm.c.pam b/perm.c.pam deleted file mode 100644 index b35e384..0000000 --- a/perm.c.pam +++ /dev/null @@ -1,145 +0,0 @@ -/* - * perm.c - check user permission for at(1) - * Copyright (C) 1994 Thomas Koenig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* System Headers */ - -#include - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -/* Local headers */ - -#include "privs.h" -#include "at.h" - -/* Macros */ - -#if defined(DEBUG_PERM_C) -#define ETCDIR "../test/etc" -#undef PRIV_START -#define PRIV_START while(0) -#undef PRIV_END -#define PRIV_END while(0) -#endif - -/* Structures and unions */ - - -/* File scope variables */ - - -/* Function declarations */ - -static int user_in_file(const char *path, const char *name); - -/* Local functions */ - -/* - */ -static int -user_in_file(const char *path, const char *name) -{ - FILE *fp; - char buffer[256]; - int found = 0; - int c = '\n'; - - PRIV_START; - fp = fopen( path, "r"); - PRIV_END; - - if ( fp == NULL ) - return -1; - - - while ( !found && fgets(buffer, sizeof(buffer), fp) != NULL) { - size_t llen = strlen(buffer); - - c = buffer[llen-1]; - - if (c == '\n') - buffer[llen-1] = '\0'; - while (c != '\n' && c != EOF) - c = fgetc(fp); - - found = (strcmp(buffer, name)==0); - } - - fclose(fp); - - if (c == EOF) { - fprintf(stderr, "%s: incomplete last line.\n", path); - } - - return found; -} - - -/* Global functions */ -int -check_permission() -{ - uid_t uid = geteuid(); - struct passwd *pentry; - int allow = 0, deny = 1; - - if (uid == 0) - return 1; - - if ((pentry = getpwuid(uid)) == NULL) { - perror("Cannot access user database"); - exit(EXIT_FAILURE); - } - - allow = user_in_file(ETCDIR "/at.allow", pentry->pw_name); - if (allow==0 || allow==1) - return allow; - - /* There was an error while looking for pw_name in at.allow. - * Check at.deny only when at.allow doesn't exist. - */ - - deny = user_in_file(ETCDIR "/at.deny", pentry->pw_name); - return deny == 0; -} - - -#if defined(DEBUG_PERM_C) - -int -main(int argc, char *argv[]) -{ - printf("check_permission() ==> %d\n", check_permission()); - return 0; -} - -#endif diff --git a/privs.h b/privs.h index 1440f32..2fad055 100644 --- a/privs.h +++ b/privs.h @@ -144,63 +144,3 @@ extern gid_t real_gid, effective_gid, daemon_gid; #error "Cannot implement user ID swapping without setreuid or setresuid" #endif #endif - -#ifdef WITH_PAM -/* PAM failed after session was open. */ -#define PAM_SESSION_FAIL if (retcode != PAM_SUCCESS) \ - pam_close_session(pamh,PAM_SILENT); - -/* syslog will be logging error messages */ -#ifdef HAVE_UNISTD_H -#include -#endif - -/* PAM fail even before opening the session */ -#define PAM_FAIL_CHECK \ - do { if (retcode != PAM_SUCCESS) { \ - fprintf(stderr,"PAM failure: %s\n",pam_strerror(pamh, retcode)); \ - syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \ - if (pamh) \ - pam_end(pamh, retcode); \ - if (setregid(getgid(),getegid()) != 0) { \ - fprintf(stderr, "cannot set egid: %s", strerror(errno)); \ - exit(1); \ - } \ - if (setreuid(getuid(),geteuid()) != 0) { \ - fprintf(stderr, "cannot set euid: %s", strerror(errno)); \ - exit(1); \ - } \ - exit(1); \ - } \ - } while (0) \ - -static int pam_session_opened = 0; //global for open session - -#define AT_START_PAM { \ - retcode = pam_start("atd", pentry->pw_name, &conv, &pamh); \ - PAM_FAIL_CHECK; \ - retcode = pam_set_item(pamh, PAM_TTY, "atd"); \ - PAM_FAIL_CHECK; \ - retcode = pam_acct_mgmt(pamh, PAM_SILENT); \ - PAM_FAIL_CHECK; \ -} - -#define AT_OPEN_PAM_SESSION { \ - retcode = pam_open_session(pamh, PAM_SILENT); \ - PAM_FAIL_CHECK; \ - retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); \ - PAM_FAIL_CHECK; \ - if (retcode == PAM_SUCCESS) \ - pam_session_opened = 1; \ -} - -#define AT_CLOSE_PAM { \ - if (pam_session_opened != 0) { \ - pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); \ - pam_close_session(pamh, PAM_SILENT); \ - } \ - pam_end(pamh, PAM_SUCCESS); \ -} - -#endif - diff --git a/privs.h.pam b/privs.h.pam deleted file mode 100644 index 2fad055..0000000 --- a/privs.h.pam +++ /dev/null @@ -1,146 +0,0 @@ -/* - * privs.h - header for privileged operations - * Copyright (C) 1993 Thomas Koenig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _PRIVS_H -#define _PRIVS_H - -#ifndef _USE_BSD -#define _USE_BSD 1 -#include -#undef _USE_BSD -#else -#include -#endif - -/* Relinquish privileges temporarily for a setuid or setgid program - * with the option of getting them back later. This is done by swapping - * the real and effective userid BSD style. Call RELINQUISH_PRIVS once - * at the beginning of the main program. This will cause all operations - * to be executed with the real userid. When you need the privileges - * of the setuid/setgid invocation, call PRIV_START; when you no longer - * need it, call PRIV_END. Note that it is an error to call PRIV_START - * and not PRIV_END within the same function. - * - * Use RELINQUISH_PRIVS_ROOT(a,b) if your program started out running - * as root, and you want to drop back the effective userid to a - * and the effective group id to b, with the option to get them back - * later. - * - * If you no longer need root privileges, but those of some other - * userid/groupid, you can call REDUCE_PRIV(a,b) when your effective - * is the user's. - * - * Problems: Do not use return between PRIV_START and PRIV_END; this - * will cause the program to continue running in an unprivileged - * state. - * - * It is NOT safe to call exec(), system() or popen() with a user- - * supplied program (i.e. without carefully checking PATH and any - * library load paths) with relinquished privileges; the called program - * can aquire them just as easily. Set both effective and real userid - * to the real userid before calling any of them. - */ - -extern uid_t real_uid, effective_uid, daemon_uid; - -extern gid_t real_gid, effective_gid, daemon_gid; - -#ifdef HAVE_SETREUID -#define RELINQUISH_PRIVS { \ - real_uid = getuid(); \ - effective_uid = geteuid(); \ - real_gid = getgid(); \ - effective_gid = getegid(); \ - setreuid(effective_uid, real_uid); \ - setregid(effective_gid, real_gid); \ - } - -#define RELINQUISH_PRIVS_ROOT(a,b) { \ - real_uid = (a); \ - effective_uid = geteuid(); \ - real_gid = (b); \ - effective_gid = getegid(); \ - setregid(effective_gid, real_gid); \ - setreuid(effective_uid, real_uid); \ - } - -#define PRIV_START {\ - setreuid(real_uid, effective_uid); \ - setregid(real_gid, effective_gid); - -#define PRIV_END \ - setregid(effective_gid, real_gid); \ - setreuid(effective_uid, real_uid); \ - } - -#define REDUCE_PRIV(a,b) {\ - setreuid(real_uid, effective_uid); \ - setregid(real_gid, effective_gid); \ - effective_uid = (a); \ - effective_gid = (b); \ - setregid(effective_gid, real_gid); \ - setreuid(effective_uid, real_uid); \ - } -#elif HAVE_SETRESUID -#define RELINQUISH_PRIVS { \ - real_uid = getuid(); \ - effective_uid = geteuid(); \ - real_gid = getgid(); \ - effective_gid = getegid(); \ - setresuid(effective_uid, real_uid, -1); \ - setresgid(effective_gid, real_gid, -1); \ - } - -/* - * HP-UX kill(2) requires that the real or effective user ID of the - * sender match the real or _saved_ user ID of the recipient. In order - * for "at" (with random real ID and effective ID "daemon") to signal - * "atd" (with real ID "root" and effective ID "daemon"), we must make - * "atd"'s saved ID "daemon". - */ -#define RELINQUISH_PRIVS_ROOT(a,b) { \ - real_uid = (a); \ - effective_uid = geteuid(); \ - real_gid = (b); \ - effective_gid = getegid(); \ - setresgid(effective_gid, real_gid, real_gid); \ - setresuid(effective_uid, real_uid, real_uid); \ - } - -#define PRIV_START {\ - setresuid(real_uid, effective_uid, -1); \ - setresgid(real_gid, effective_gid, -1); - -#define PRIV_END \ - setresgid(effective_gid, real_gid, -1); \ - setresuid(effective_uid, real_uid, -1); \ - } - -#define REDUCE_PRIV(a,b) {\ - setresuid(real_uid, effective_uid, -1); \ - setresgid(real_gid, effective_gid, -1); \ - effective_uid = (a); \ - effective_gid = (b); \ - setresgid(effective_gid, real_gid, -1); \ - setresuid(effective_uid, real_uid, -1); \ - } -#else -#error "Cannot implement user ID swapping without setreuid or setresuid" -#endif -#endif