[comp.bugs.4bsd] Patches for lib/libc/syslog.c

ehrlich@psuvax1.psu.edu (Dan Ehrlich) (09/17/87)

After being serverley chastised for my mods to syslogd.c to fix logging
ftpd after a chroot.  I submit the following for you amusement.  This
is probably they way it should have been done to begin with.  In
lib/libc/gen/syslog.c openlog will do a "connect" as well as creating
the socket when LOG_NDELAY is specified.  There was also the same
problem  with chroot for /dev/console as for /dev/log so that should
now work also.

--Dan Ehrlich

RCS file: RCS/syslog.c,v
retrieving revision 1.1
diff -c -r1.1 syslog.c
*** /tmp/,RCSt1008669	Wed Sep 16 18:37:56 1987
--- syslog.c	Wed Sep 16 18:27:40 1987
***************
*** 6,11 ****
--- 6,12 ----
  
  #if defined(LIBC_SCCS) && !defined(lint)
  static char sccsid[] = "@(#)syslog.c	5.9 (Berkeley) 5/7/86";
+ static char RCSsrc[] = "$Source: /usr/src/lib/libc/gen/RCS/syslog.c,v $";
  #endif LIBC_SCCS and not lint
  
  /*
***************
*** 44,49 ****
--- 45,51 ----
  static char	ctty[] = "/dev/console";
  
  static int	LogFile = -1;		/* fd for log */
+ static int	ConsFD = -1;		/* fd for console */
  static int	LogStat	= 0;		/* status bits, set by openlog() */
  static char	*LogTag = "syslog";	/* string to tag the entry with */
  static int	LogMask = 0xff;		/* mask of priorities to be logged */
***************
*** 63,71 ****
  	register int c;
  	long now;
  	int pid, olderrno = errno;
  
  	/* see if we should just throw out this message */
! 	if (pri <= 0 || PRIFAC(pri) >= LOG_NFACILITIES || (PRIMASK(pri) & LogMask) == 0)
  		return;
  	if (LogFile < 0)
  		openlog(LogTag, LogStat | LOG_NDELAY, 0);
--- 65,74 ----
  	register int c;
  	long now;
  	int pid, olderrno = errno;
+ 	int oldh_errno = h_errno;
  
  	/* see if we should just throw out this message */
! 	if (pri <= LOG_EMERG || PRIFAC(pri) >= LOG_NFACILITIES || (PRIMASK(pri) & LogMask) == 0)
  		return;
  	if (LogFile < 0)
  		openlog(LogTag, LogStat | LOG_NDELAY, 0);
***************
*** 101,115 ****
  			*b++ = c;
  			continue;
  		}
! 		if ((c = *f++) != 'm') {
  			*b++ = '%';
  			*b++ = c;
  			continue;
  		}
! 		if ((unsigned)olderrno > sys_nerr)
! 			sprintf(b, "error %d", olderrno);
! 		else
! 			strcpy(b, sys_errlist[olderrno]);
  		b += strlen(b);
  	}
  	*b++ = '\n';
--- 104,131 ----
  			*b++ = c;
  			continue;
  		}
! 		if (((c = *f++) != 'm') && (c != 'h')) {
  			*b++ = '%';
  			*b++ = c;
  			continue;
  		}
! 		/*
! 		 *	Handle %m and %h formats.
! 		 *	%m prints text associated with errno
! 		 *	%h prints text associated with h_errno.
! 		 */
! 		switch (c) {
! 		    case 'm': if ((unsigned)olderrno > sys_nerr)
! 				sprintf(b, "error %d", olderrno);
! 			      else
! 				strcpy(b, sys_errlist[olderrno]);
! 			      break;
! 		    case 'h': if ((unsigned)oldh_errno > sys_nherr)
! 				sprintf(b, "herror %d", oldh_errno);
! 			      else
! 				strcpy(b, sys_herrlist[oldh_errno]);
! 			      break;
! 		}
  		b += strlen(b);
  	}
  	*b++ = '\n';
***************
*** 120,127 ****
  		c = MAXLINE;
  
  	/* output the message to the local logger */
! 	if (sendto(LogFile, outline, c, 0, &SyslogAddr, sizeof SyslogAddr) >= 0)
  		return;
  	if (!(LogStat & LOG_CONS))
  		return;
  
--- 136,145 ----
  		c = MAXLINE;
  
  	/* output the message to the local logger */
! 	if (send(LogFile, outline, c, 0) >= 0)
  		return;
+ 	else
+ 		perror("syslog: send");
  	if (!(LogStat & LOG_CONS))
  		return;
  
***************
*** 130,146 ****
  	if (pid == -1)
  		return;
  	if (pid == 0) {
! 		int fd;
! 
! 		signal(SIGALRM, SIG_DFL);
! 		sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
! 		alarm(5);
! 		fd = open(ctty, O_WRONLY);
! 		alarm(0);
  		strcat(o, "\r");
  		o = index(outline, '>') + 1;
! 		write(fd, o, c + 1 - (o - outline));
! 		close(fd);
  		_exit(0);
  	}
  	if (!(LogStat & LOG_NOWAIT))
--- 148,162 ----
  	if (pid == -1)
  		return;
  	if (pid == 0) {
! 		/*
! 		 * Open console if not already.
! 		 */
! 		if (ConsFD == -1)
! 			ConsFD = open(ctty, O_WRONLY | O_NDELAY);
  		strcat(o, "\r");
  		o = index(outline, '>') + 1;
! 		write(ConsFD, o, c + 1 - (o - outline));
! 		close(ConsFD);
  		_exit(0);
  	}
  	if (!(LogStat & LOG_NOWAIT))
***************
*** 166,173 ****
--- 182,198 ----
  	SyslogAddr.sa_family = AF_UNIX;
  	strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data);
  	if (LogStat & LOG_NDELAY) {
+ 		/*
+ 		 * If LOG_NDELAY, connect to the socket and grab a
+ 		 * descriptor for /dev/console (if LOG_CONS), in
+ 		 * case the user wants to chroot.
+ 		 */
  		LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
  		fcntl(LogFile, F_SETFD, 1);
+ 		if (connect(LogFile, &SyslogAddr, sizeof SyslogAddr) < 0)
+ 			perror("openlog: connect");
+ 		if (LogStat & LOG_CONS)
+ 			ConsFD = open(ctty, O_WRONLY | O_NDELAY);
  	}
  }
  

chris@mimsy.UUCP (Chris Torek) (09/21/87)

There is a problem with these patches.  According to syslog(3),
LOG_CONS `... is safe to use in daemon processes that have no
controlling terminal since syslog will fork before opening the
console'.  This version of syslog() does not do that.

My own solution is simply to allow syslog() with LOG_CONS to
fail if the connect() fails and the program using syslog does
a chdir().  This is not right either, but does not attach the
program to the console.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris