Subject: Re: calendar vs. NIS
To: David Laight , tech-userlevel <tech-userlevel@netbsd.org>
From: Joerg Klemenz <joerg@gmx.net>
List: tech-userlevel
Date: 11/06/2002 21:17:33
David Laight wrote:
> I'd use a static array of pointers to malloc()ed buffers and set
> bits. Say 16k pointers each to 32k data, 2^14 * 2^15 * 2^3 = 2^32. Ok
> provided the UIDs are in dense blocks... (or you need 512Mbytes).
> Alternatively some kind of sorted data. Actually this code doesn't
> scale very well at all if there are many thousand users!

Uhh... that sounds complicated. How about that (it's kinda lame, but
should work for all cases)


--- calendar.c_org	Tue Nov  5 09:32:36 2002
+++ calendar.c	Wed Nov  6 21:06:13 2002
@@ -108,8 +108,16 @@
 	"jul", "aug", "sep", "oct", "nov", "dec", NULL,
 };
 
+struct uidlist_s 
+{
+   struct uidlist_s *next;
+   uid_t uid;
+};
+
+
 int	 main(int, char **);
 
+static int	 checkForDoubleUID(struct uidlist_s *,  uid_t);
 static void	 atodays(int, char *, unsigned short *);
 static void	 cal(void);
 static void	 closecal(FILE *);
@@ -121,6 +129,8 @@
 static FILE	*opencal(void);
 static void	 settime(void);
 static void	 usage(void) __attribute__((__noreturn__));
+static void	 malloc_panic(void) __attribute__((__noreturn__));
+
 
 int
 main(argc, argv)
@@ -129,6 +139,12 @@
 {
 	int ch;
 	const char *caldir;
+        struct uidlist_s *uidlist_ptr;
+   
+        /* create the tail of the linked list */
+        uidlist_ptr=(struct uidlist_s*)malloc(sizeof(struct uidlist_s));
+        if (uidlist_ptr==NULL) malloc_panic;
+        uidlist_ptr->next=NULL;
 
 	while ((ch = getopt(argc, argv, "-ad:f:l:w:")) != -1)
 		switch (ch) {
@@ -165,12 +181,16 @@
 	settime();
 	if (doall) {
 		while ((pw = getpwent()) != NULL) {
+			/* avoid double mail when using NIS etc.
+			   (see man getpwent) */
+			if (!checkForDoubleUID(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 +200,32 @@
 	exit(0);
 }
 
+static int 
+checkForDoubleUID(uidlist_ptr,uid)
+    /* return values
+     * 1 uid already in list
+     * 0 uid not in list (added)
+     */
+    struct uidlist_s *uidlist_ptr;
+    uid_t uid;
+{
+   struct uidlist_s *working_uidlist_ptr;
+   
+   while (working_uidlist_ptr->next != NULL) 
+     {
+	if (working_uidlist_ptr->uid == uid) return 1;
+	working_uidlist_ptr=working_uidlist_ptr->next;	
+     }
+   
+   /* working pointer points on tail now */
+   working_uidlist_ptr->next=(struct uidlist_s*)malloc(sizeof(struct uidlist_s));
+   if (working_uidlist_ptr->next==NULL) malloc_panic;   
+   working_uidlist_ptr->uid=uid;   
+   working_uidlist_ptr->next->next=NULL;
+
+   return 0;
+}
+
 static void
 cal(void)
 {
@@ -518,4 +564,11 @@
 	(void)fprintf(stderr, "Usage: %s [-a] [-d MMDD[[YY]YY]"
 	    " [-f fname] [-l days] [-w days]\n", getprogname());
 	exit(1);
+}
+
+static void
+malloc_panic(void)
+{
+	(void)fprintf(stderr, "%s: malloc panic\n", getprogname());
+	exit(2);
 }







	joerg  <joerg@gmx.net>