Subject: bin/19121: calendar patch (to support NIS)
To: None <gnats-bugs@gnats.netbsd.org>
From: None <joerg@gmx.net>
List: netbsd-bugs
Date: 11/21/2002 15:04:02
>Number:         19121
>Category:       bin
>Synopsis:       calendar patch (to support NIS)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Nov 21 06:07:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Joerg Klemenz
>Release:        NetBSD 1.6
>Organization:
All Virtual Devils
>Environment:
	
	
System: NetBSD evo.infnet.sa 1.6 NetBSD 1.6 (VPC5) #0: Sun Nov 3 21:01:51 UTC 2002 root@faith.infnet.sa:/usr/src/sys/arch/i386/compile/VPC5 i386
Architecture: i386
Machine: i386
>Description:

Here is a patch for the calendar(1) program.
It adds a new function (inuidlist) that builds a dynamicly allocated
linked list to check if the specified UID has already been processed.

Due to the reverse-sorted nature of the list (3-2-1) there is almost
no overhead for a typical no-NIS system where the password file is
semi-sorted in an 1-2-3 fashion. The added functionality for NIS
systems makes it well worth the little overhead IMHO.

The reason is that without that function "calendar -a" will send out
multiple copies of mail to individual users in a NIS environment (see
man getpwent).

I have used the patch for some time and it looks OK.

The patch also contains some cosmetic fixes that you can ignore.

>How-To-Repeat:
>Fix:
--- calendar.c_org	Tue Nov  5 09:32:36 2002
+++ calendar.c	Wed Nov 20 10:18:47 2002
@@ -1,4 +1,4 @@
-/*	$NetBSD: calendar.c,v 1.26 2001/12/04 15:55:32 christos Exp $	*/
+/*	$Id: calendar.c,v 1.6 2002/11/20 10:18:38 joerg Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993, 1994
@@ -43,7 +43,7 @@
 #if 0
 static char sccsid[] = "@(#)calendar.c	8.4 (Berkeley) 1/7/95";
 #endif
-__RCSID("$NetBSD: calendar.c,v 1.26 2001/12/04 15:55:32 christos Exp $");
+__RCSID("$Id: calendar.c,v 1.6 2002/11/20 10:18:38 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -75,7 +75,7 @@
 #endif
 
 static unsigned short lookahead = 1, weekend = 2;
-static char *fname = "calendar", *datestr = NULL;
+static char *fname = ".calendar", *datestr = NULL;	/* cal -> .cal (jk) */
 static struct passwd *pw;
 static int doall;
 static char path[MAXPATHLEN + 1];
@@ -108,6 +108,12 @@
 	"jul", "aug", "sep", "oct", "nov", "dec", NULL,
 };
 
+struct uidlist_s {
+   uid_t uid;
+   struct uidlist_s *next;
+};
+
+
 int	 main(int, char **);
 
 static void	 atodays(int, char *, unsigned short *);
@@ -118,10 +124,12 @@
 static void	 getmmdd(struct tm *, char *);
 static int	 getmonth(char *);
 static int	 isnow(char *);
+static int	 inuidlist(struct uidlist_s *, uid_t);
 static FILE	*opencal(void);
 static void	 settime(void);
 static void	 usage(void) __attribute__((__noreturn__));
 
+
 int
 main(argc, argv)
 	int argc;
@@ -129,6 +137,11 @@
 {
 	int ch;
 	const char *caldir;
+        struct uidlist_s *uidlist_ptr;
+   
+        /* create the tail of the linked list */
+        if (uidlist_ptr=malloc(sizeof *uidlist_ptr))
+          uidlist_ptr->next=NULL;
 
 	while ((ch = getopt(argc, argv, "-ad:f:l:w:")) != -1)
 		switch (ch) {
@@ -164,13 +177,16 @@
 
 	settime();
 	if (doall) {
-		while ((pw = getpwent()) != NULL) {
+	   while ((pw = getpwent()) != NULL) 
+	     {
+		if (!inuidlist(uidlist_ptr, pw->pw_uid)) {
 			(void)setegid(pw->pw_gid);
 			(void)seteuid(pw->pw_uid);
 			if (!chdir(pw->pw_dir))
 				cal();
 			(void)seteuid(0);
 		}
+	     }
 	} else if ((caldir = getenv("CALENDAR_DIR")) != NULL) {
 		if(!chdir(caldir))
 			cal();
@@ -180,6 +196,24 @@
 	exit(0);
 }
 
+/* make list of uids to avoid doubles (see man getpwent) */
+static int
+inuidlist(uidlist_ptr, uid)
+    struct uidlist_s *uidlist_ptr;
+    uid_t uid;
+{
+   struct uidlist_s *p,*tmp;
+   
+   for (p=uidlist_ptr; p->next && (p->uid > uid); p=p->next);
+   if ((p->uid==uid) && p->next) return (1);
+   if (tmp=malloc(sizeof *tmp)) {
+      *tmp=*p;
+      p->next=tmp;
+      p->uid=uid;
+     }
+   return (0);
+}
+
 static void
 cal(void)
 {
@@ -199,10 +233,13 @@
 		free(line);
 
 	}
+   
+        if (doall)
 	closecal(fp);
+        else
+          (void)fclose(fp);
 }
 
-
 static void
 settime(void)
 {
@@ -383,9 +420,6 @@
 	int nread, pdes[2], status;
 	char buf[1024];
 
-	if (!doall)
-		return;
-
 	(void)rewind(fp);
 	if (fstat(fileno(fp), &sbuf) || !sbuf.st_size)
 		goto done;
@@ -419,7 +453,7 @@
 	(void)close(pdes[1]);
 
 done:	(void)fclose(fp);
-	(void)unlink(path);
+        (void)unlink(path); /* it should close descriptor first... */
 	while (wait(&status) >= 0)
 		continue;
 }
>Release-Note:
>Audit-Trail:
>Unformatted: