Subject: Re: at command [build script attached]
From: Joe Buehler <[email-masked]>
To: [email-masked]
Date: Wed, 04 Jun 2003 09:50:00 -0400

Chuck wrote:

> Is there a unix style "at" command for cygwin? I've searched the libs but 
> found nothing.

I did an initial port of the linux "at" some time back (I believe I used
the Redhat 3.1.8-31 rpm).  The build script I used is attached.  There is
some weirdness in unpacking the rpm file, since there was no rpm2cpio
at the time.

Note that this could be made a little better in that I think some system
calls are now in Cygwin that were not at the time I did this.
-- 
Joe Buehler
#!/bin/bash

VERSION=3.1.8-31

patch1()
{
patch -p0 -N <<\EOF
--- parsetime.y	2002-11-19 12:07:36.000000000 -0500
+++ parsetime.y	2002-11-19 12:17:07.000000000 -0500
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include "parsetime.h"
+#include <tzfile.h>
 
 #define YYDEBUG 1
 
@@ -215,8 +216,8 @@
 				 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))
+			    || (mnum ==  2 && dnum > 29 &&  isleap(ynum+1900))
+			    || (mnum ==  2 && dnum > 28 && !isleap(ynum+1900))
 			   )
 			{
 			    yyerror("Error in day of month");
@@ -257,8 +258,8 @@
 				 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))
+			    || (mnum ==  2 && dnum > 29 &&  isleap(ynum+1900))
+			    || (mnum ==  2 && dnum > 28 && !isleap(ynum+1900))
 			   )
 			{
 			    yyerror("Error in day of month");
@@ -474,7 +475,7 @@
     if (yyparse() == 0) {
 	exectime = mktime(&exectm);
 	if (isgmt) {
-	    exectime -= timezone;
+	    exectime -= _timezone;
 	}
 	if (time_only && (currtime > exectime)) {
 	    exectime += 24*3600;
--- privs.h	1997-05-06 04:28:18.000000000 -0400
+++ privs.h	2002-11-19 14:27:01.000000000 -0500
@@ -140,6 +140,42 @@
 			setresgid(effective_gid, real_gid, -1); \
 			setresuid(effective_uid, real_uid, -1); \
 		    }
+#elif __CYGWIN__
+#define RELINQUISH_PRIVS { \
+			      real_uid = getuid(); \
+			      effective_uid = geteuid(); \
+			      real_gid = getgid(); \
+			      effective_gid = getegid(); \
+			      setuid(effective_uid); seteuid(real_uid); \
+			      setgid(effective_gid); setegid(real_gid); \
+		          }
+
+#define RELINQUISH_PRIVS_ROOT(a,b) { \
+			      real_uid = (a); \
+			      effective_uid = geteuid(); \
+			      real_gid = (b); \
+			      effective_gid = getegid(); \
+			      setgid(effective_gid); setegid(real_gid); \
+			      setuid(effective_uid); seteuid(real_uid); \
+		          }
+
+#define PRIV_START {\
+		    setuid(real_uid); seteuid(effective_uid); \
+		    setgid(real_gid); setegid(effective_gid);
+
+#define PRIV_END \
+		    setgid(effective_gid); setegid(real_gid); \
+		    setuid(effective_uid); seteuid(real_uid); \
+		    }
+
+#define REDUCE_PRIV(a,b) {\
+			setuid(real_uid); seteuid(effective_uid); \
+			setgid(real_gid); setegid(effective_gid); \
+			effective_uid = (a); \
+			effective_gid = (b); \
+			setgid(effective_gid); setegid(real_gid); \
+			setuid(effective_uid); seteuid(real_uid); \
+		    }
 #else
 #error "Cannot implement user ID swapping without setreuid or setresuid"
 #endif
--- at.c	2002-11-19 14:28:10.000000000 -0500
+++ at.c	2002-11-19 14:55:17.000000000 -0500
@@ -188,25 +188,27 @@
 }
 
 static long
-nextjob()
+nextjob(int fd)
 {
     long jobno;
-    FILE *fid;
+	int ret;
+	char buf[32];
 
-    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;
-    }
+	ret = read(fd, buf, sizeof(buf)-1);
+	if (ret < 0) {
+		buf[0] = 0;
+	} else {
+		buf[ret] = 0;
+	}
+
+	jobno = strtol(buf, 0, 16);
     jobno = (1 + jobno) % 0xfffff;	/* 2^20 jobs enough? */
-    fprintf(fid, "%05lx\n", jobno);
+    ret = sprintf(buf, "%05lx\n", jobno);
+
+	lseek(fd, 0, SEEK_SET);
+
+	write(fd, buf, ret);
 
-    fclose(fid);
     return jobno;
 }
 
@@ -252,7 +254,7 @@
 
     PRIV_START
 
-	if ((lockdes = open(LFILE, O_WRONLY)) < 0)
+	if ((lockdes = open(LFILE, O_RDWR)) < 0)
 	    perr("Cannot open lockfile " LFILE);
 
 	lock.l_type = F_WRLCK;
@@ -272,7 +274,7 @@
 	fcntl(lockdes, F_SETLKW, &lock);
 	alarm(0);
 
-	if ((jobno = nextjob()) == EOF)
+	if ((jobno = nextjob(lockdes)) == EOF)
 	    perr("Cannot generate job number");
 
 	(void)snprintf(ppos, sizeof(atfile) - (ppos - atfile),
@@ -460,7 +460,7 @@
     /* Set the x bit so that we're ready to start executing
      */
 
-    if (fchmod(fd2, S_IRUSR | S_IWUSR | S_IXUSR) < 0)
+    if (fchmod(fd2, 0777) < 0)
 	perr("Cannot give away file");
 
     close(fd2);
--- atd.c	2002-11-19 14:55:51.000000000 -0500
+++ atd.c	2002-11-19 15:35:46.000000000 -0500
@@ -486,7 +486,9 @@
 
 	    chdir ("/");
 
-#if defined(SENDMAIL)
+#if defined(__CYGWIN__)
+	    execl("/usr/sbin/ssmtp", "ssmtp", mailname, (char *) NULL);
+#elif defined(SENDMAIL)
 	    execl(SENDMAIL, "sendmail", mailname, (char *) NULL);
 #elif  defined(MAILC)
 	    execl(MAILC, "mail", mailname, (char *) NULL);
EOF
}

install_files()
{
#	/usr/bin/install -c -m 755 -d /etc
#	/usr/bin/install -c -m 755 -d /usr/bin
#	/usr/bin/install -c -m 755 -d /usr/sbin
#	/usr/bin/install -c -m 755 -d /usr/doc
	/usr/bin/install -c -m 755 -d /usr/doc/at
	/usr/bin/install -c -m 755 -d /var/spool/at
	/usr/bin/install -c -g system -o system -m 755 -d /var/spool/at/spool
	chmod 755 /var/spool/at /var/spool/at/spool
	chown system:system /var/spool/at /var/spool/at/spool
	touch /var/spool/at/.SEQ
	chmod 666 /var/spool/at/.SEQ
	chown system:system /var/spool/at/.SEQ
	test -f /etc/at.allow || test -f /etc/at.deny || /usr/bin/install -c  -m 644 at.deny /etc/
	/usr/bin/install -c   -m 4755 -s at /usr/bin
	ln -s -f at /usr/bin/atq
	ln -s -f at /usr/bin/atrm
	/usr/bin/install -c   -m 755 batch /usr/bin
	/usr/bin/install -c -d   -m 755 /usr/man/man1
	/usr/bin/install -c -d   -m 755 /usr/man/man5
	/usr/bin/install -c -d   -m 755 /usr/man/man8
	/usr/bin/install -c   -m 755 -s atd /usr/sbin
	/usr/bin/install -c   -m 755 atrun /usr/sbin
	/usr/bin/install -c   -m 644 at.1 /usr/man/man1/
	( cd /usr/man/man1 && ln -s -f at.1 atq.1 && ln -s -f at.1 batch.1 && ln -s -f at.1 atrm.1 )
	/usr/bin/install -c   -m 644 atd.8 /usr/man/man8/
	sed "s,\${exec_prefix},/usr,g" <atrun.8>tmpman
	/usr/bin/install -c   -m 644 tmpman /usr/man/man8/atrun.8
	rm -f tmpman
	/usr/bin/install -c   -m 644 at_allow.5 /usr/man/man5/
	( cd /usr/man/man5 && ln -s -f at_allow.5 at_deny.5 )
	/usr/bin/install -c   -m 644 Problems Copyright README ChangeLog timespec /usr/doc/at
	rm -f /usr/man/cat1/at.1* /usr/man/cat1/batch.1* \
		/usr/man/cat1/atq.1*
	rm -f /usr/man/cat1/atd.8*
}

rm -fr at-$VERSION &&
mkdir at-$VERSION &&
(
	cd at-$VERSION &&
	dd skip=1 bs=8874 if=../at-$VERSION.src.rpm |
		gunzip |
		cpio -idmu &&
	bunzip2 <at-3.1.8.tar.bz2 | cpio -idmu &&
	(
		cd at-3.1.8 &&
		perl -n -e '
			chomp;
			if (/^Patch([0-9]+): (.*)/) {
				$number = $1;
				$file = $2;
				$patchfile{$number} = $file;
			}
			if (/^\%patch([0-9]+)(.*)$/) {
				$number = $1;
				$options = " $2 ";
				$options =~ s/^.*\s(-p\d*)\s.*$/$1/go;
				print STDOUT "patch $options < ../$patchfile{$number}\n";
			}
		' ../at.spec | bash -x &&
		patch1 &&
		./configure --with-atspool=/var/spool/at/spool --with-jobdir=/var/spool/at &&
		rm -f lex.yy.* y.tab.* &&
		make DAEMON_USERNAME=system DAEMON_GROUPNAME=system &&
		install_files &&
		true
	)
) &&
rm -fr at-$VERSION &&
true

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/