$NetBSD: patch-ab,v 1.2 1998/08/07 11:10:38 agc Exp $ --- tty.c.orig Sat Jul 1 01:41:05 1995 +++ tty.c Sat Sep 9 08:37:14 1995 @@ -140,9 +140,10 @@ int tty_lock ( char *path, int mode ) { +#define MAX_LOCK_ATTEMPTS 3 struct passwd *pw; - - int fd; + char number[12], *temp_path; + int fd, i, saved_errno; if ( mode ) /* locking on ? */ @@ -152,32 +153,71 @@ return 0; /* standard input */ } - if ( saved_path != NULL ) + temp_path = (char*) malloc ( sizeof ( PATH_LOCKD ) + + strlen("TMP..") + 10); /* max PID */ + + (void) sprintf ( number, "%u", (unsigned)getpid() ); + (void) strcpy ( temp_path, PATH_LOCKD ); + (void) strcat ( temp_path, "TMP.." ); + (void) strcat ( temp_path, number ); + + if ( opt_debg ) + printf ( "DIP: tty: trying to create lock temp file %s\n", temp_path ); + if ( ( fd = open ( temp_path, O_CREAT|O_TRUNC|O_WRONLY, 0644 ) ) < 0) { - free ( saved_path ); - saved_path = NULL; + (void) fprintf ( stderr, "DIP: tty: lock: (%s): %s\n", + temp_path, strerror ( errno ) ); + free(temp_path); + return -1; } + /* + * now enter our PID; + * Note: the 10 digits + newline are convention and cannot be changed + */ + (void) sprintf ( number, "%10u\n", getpid() ); + if ( opt_debg ) + printf ( "DIP: tty: writing \"%10u\" into lock temp file\n", getpid() ); + if ( write (fd, number, 11) != 11 ) + { + (void) fprintf ( stderr, "DIP: tty: lock write error: %s\n", + strerror ( errno ) ); + free(temp_path); + return -1; + } + (void) close ( fd ); + + free ( saved_path ); /* just in case [NB: free(NULL) is legal] */ saved_path = (char*) malloc ( sizeof ( PATH_LOCKD ) + - strlen ( path ) + 1 ); + strlen ( path ) + 3 ); (void) strcpy ( saved_path, PATH_LOCKD ); + (void) strcat ( saved_path, ".." ); (void) strcat ( saved_path, path ); - - if ( ( fd = creat ( saved_path, 0644 ) ) < 0) - { - if ( errno != EEXIST ) + if ( opt_debg ) + printf ( "DIP: tty: linking %s to %s\n", temp_path, saved_path ); + for ( i = 0; i < MAX_LOCK_ATTEMPTS; i++ ) { - (void) fprintf ( stderr, "DIP: tty: lock: (%s): %s\n", - saved_path, strerror ( errno ) ); + /* now attempt to actually get the lock */ + if ( link ( temp_path, saved_path ) == 0 ) + break; + sleep(2 * (i + 1)); + } + saved_errno = errno; + (void) unlink ( temp_path ); + free(temp_path); + + if ( i >= MAX_LOCK_ATTEMPTS ) + { + /* did not get it */ + if ( saved_errno != EEXIST ) + (void) fprintf ( stderr, "DIP: tty: lock: (%s): %s\n", + saved_path, strerror ( saved_errno ) ); + else if ( opt_debg ) + printf ( "DIP: tty: lock attempt failed, EEXIST\n" ); + return -1; } - - return -1; - } - - (void) close ( fd ); - /* * Make sure UUCP owns the lockfile. Required by some packages. @@ -215,7 +255,26 @@ return 0; } +/* + * Enter daemon's PID into the lock file; + * This is icky. + */ +void tty_relock ( void ) +{ + int fd; + char number[12]; + if ( saved_path == NULL ) + return; + + (void) sprintf ( number, "%10u\n", (unsigned)getpid() ); + if ( opt_debg ) + printf ( "DIP: tty: rewriting lock file (PID = %u)\n", getpid() ); + if ( (fd = open ( saved_path, O_WRONLY, 0 )) == -1 ) + return; + (void) write ( fd, number, 11); + (void) close ( fd ); +} /* * Find a serial speed code in the table. @@ -965,7 +1024,6 @@ char *sp; char path [ MAXPATHLEN ]; - /* * Try opening the TTY device. */ @@ -985,8 +1043,10 @@ else sp = name; - - if ( ( fd = open ( path, O_RDWR | O_NONBLOCK ) ) < 0 ) + if ( tty_lock ( sp, 1 ) == -1 ) + return -1; + + if ( ( fd = open ( path, O_RDWR | O_NONBLOCK | O_EXCL ) ) < 0 ) { (void) fprintf ( stderr, "DIP: tty: open(%s, RW): %s\n", path, strerror ( errno ) ); @@ -1118,10 +1178,4 @@ { return 0 ; } - - - /* - * OK, all done. Lock this terminal line. - */ - return tty_lock ( sp, 1 ); } --- daemon.c.orig Sat Jul 1 01:41:05 1995 +++ daemon.c Sat Sep 9 08:20:00 1995 @@ -168,6 +168,8 @@ openlog ( "DIP", LOG_PID, LOG_DAEMON ); } + /* note the race condition here; ick! */ + tty_relock(); (void) signal ( SIGALRM, sig_catcher ); (void) alarm ( mydip.timeout );