aboutsummaryrefslogtreecommitdiffhomepage
path: root/common.cpp
diff options
context:
space:
mode:
authorGravatar Peter Ammon <corydoras@ridiculousfish.com>2012-03-02 00:27:40 -0800
committerGravatar Peter Ammon <corydoras@ridiculousfish.com>2012-03-02 00:27:40 -0800
commit8b26d0104c1d85c271e5ce6e08bfe64a779beba7 (patch)
tree995568526f190084fd12d74bc6dcd0e828b1018a /common.cpp
parent36622c35781c3212c2102c45781a496f3e1b3659 (diff)
Some initial changes to use CLO_EXEC, with an eye towards some day using it correctly.
Diffstat (limited to 'common.cpp')
-rw-r--r--common.cpp238
1 files changed, 1 insertions, 237 deletions
diff --git a/common.cpp b/common.cpp
index a0c3fe79..012bf13c 100644
--- a/common.cpp
+++ b/common.cpp
@@ -49,14 +49,6 @@ parts of fish.
#include <execinfo.h>
#endif
-#ifndef HOST_NAME_MAX
-/**
- Maximum length of hostname return. It is ok if this is too short,
- getting the actual hostname is not critical, so long as the string
- is unique in the filesystem namespace.
-*/
-#define HOST_NAME_MAX 255
-#endif
#if HAVE_NCURSES_H
#include <ncurses.h>
@@ -88,11 +80,7 @@ parts of fish.
#include "util.cpp"
#include "fallback.cpp"
-/**
- The number of milliseconds to wait between polls when attempting to acquire
- a lockfile
-*/
-#define LOCKPOLLINTERVAL 10
+
struct termios shell_modes;
@@ -1693,231 +1681,7 @@ bool unescape_string(wcstring &str, int escape_special)
return success;
}
-/**
- Writes a pid_t in decimal representation to str.
- str must contain sufficient space.
- The conservatively approximate maximum number of characters a pid_t will
- represent is given by: (int)(0.31 * sizeof(pid_t) + CHAR_BIT + 1)
- Returns the length of the string
-*/
-static int sprint_pid_t( pid_t pid, char *str )
-{
- int len, i = 0;
- int dig;
-
- /* Store digits in reverse order into string */
- while( pid != 0 )
- {
- dig = pid % 10;
- str[i] = '0' + dig;
- pid = ( pid - dig ) / 10;
- i++;
- }
- len = i;
- /* Reverse digits */
- i /= 2;
- while( i )
- {
- i--;
- dig = str[i];
- str[i] = str[len - 1 - i];
- str[len - 1 - i] = dig;
- }
- return len;
-}
-
-/**
- Writes a pseudo-random number (between one and maxlen) of pseudo-random
- digits into str.
- str must point to an allocated buffer of size of at least maxlen chars.
- Returns the number of digits written.
- Since the randomness in part depends on machine time it has _some_ extra
- strength but still not enough for use in concurrent locking schemes on a
- single machine because gettimeofday may not return a different value on
- consecutive calls when:
- a) the OS does not support fine enough resolution
- b) the OS is running on an SMP machine.
- Additionally, gettimeofday errors are ignored.
- Excludes chars other than digits since ANSI C only guarantees that digits
- are consecutive.
-*/
-static int sprint_rand_digits( char *str, int maxlen )
-{
- int i, max;
- struct timeval tv;
-
- /*
- Seed the pseudo-random generator based on time - this assumes
- that consecutive calls to gettimeofday will return different values
- and ignores errors returned by gettimeofday.
- Cast to unsigned so that wrapping occurs on overflow as per ANSI C.
- */
- (void)gettimeofday( &tv, NULL );
- srand( (unsigned int)tv.tv_sec + (unsigned int)tv.tv_usec * 1000000UL );
- max = 1 + (maxlen - 1) * (rand() / (RAND_MAX + 1.0));
- for( i = 0; i < max; i++ )
- {
- str[i] = '0' + 10 * (rand() / (RAND_MAX + 1.0));
- }
- return i;
-}
-/**
- Generate a filename unique in an NFS namespace by creating a copy of str and
- appending .{hostname}.{pid} to it. If gethostname() fails then a pseudo-
- random string is substituted for {hostname} - the randomness of the string
- should be strong enough across different machines. The main assumption
- though is that gethostname will not fail and this is just a "safe enough"
- fallback.
- The memory returned should be freed using free().
-*/
-static char *gen_unique_nfs_filename( const char *filename )
-{
- int pidlen, hnlen, orglen = strlen( filename );
- char hostname[HOST_NAME_MAX + 1];
- char *newname;
-
- if ( gethostname( hostname, HOST_NAME_MAX + 1 ) == 0 )
- {
- hnlen = strlen( hostname );
- }
- else
- {
- hnlen = sprint_rand_digits( hostname, HOST_NAME_MAX );
- hostname[hnlen] = '\0';
- }
- newname = (char *)malloc( orglen + 1 /* period */ + hnlen + 1 /* period */ +
- /* max possible pid size: 0.31 ~= log(10)2 */
- (int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1)
- + 1 /* '\0' */ );
-
- if ( newname == NULL )
- {
- debug( 1, L"gen_unique_nfs_filename: %s", strerror( errno ) );
- return newname;
- }
- memcpy( newname, filename, orglen );
- newname[orglen] = '.';
- memcpy( newname + orglen + 1, hostname, hnlen );
- newname[orglen + 1 + hnlen] = '.';
- pidlen = sprint_pid_t( getpid(), newname + orglen + 1 + hnlen + 1 );
- newname[orglen + 1 + hnlen + 1 + pidlen] = '\0';
-/* debug( 1, L"gen_unique_nfs_filename returning with: newname = \"%s\"; "
- L"HOST_NAME_MAX = %d; hnlen = %d; orglen = %d; "
- L"sizeof(pid_t) = %d; maxpiddigits = %d; malloc'd size: %d",
- newname, (int)HOST_NAME_MAX, hnlen, orglen,
- (int)sizeof(pid_t),
- (int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1),
- (int)(orglen + 1 + hnlen + 1 +
- (int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1) + 1) ); */
- return newname;
-}
-
-int acquire_lock_file( const char *lockfile, const int timeout, int force )
-{
- int fd, timed_out = 0;
- int ret = 0; /* early exit returns failure */
- struct timespec pollint;
- struct timeval start, end;
- double elapsed;
- struct stat statbuf;
-
- /*
- (Re)create a unique file and check that it has one only link.
- */
- char *linkfile = gen_unique_nfs_filename( lockfile );
- if( linkfile == NULL )
- {
- goto done;
- }
- (void)unlink( linkfile );
- if( ( fd = open( linkfile, O_CREAT|O_RDONLY, 0600 ) ) == -1 )
- {
- debug( 1, L"acquire_lock_file: open: %s", strerror( errno ) );
- goto done;
- }
- /*
- Don't need to check exit status of close on read-only file descriptors
- */
- close( fd );
- if( stat( linkfile, &statbuf ) != 0 )
- {
- debug( 1, L"acquire_lock_file: stat: %s", strerror( errno ) );
- goto done;
- }
- if ( statbuf.st_nlink != 1 )
- {
- debug( 1, L"acquire_lock_file: number of hardlinks on unique "
- L"tmpfile is %d instead of 1.", (int)statbuf.st_nlink );
- goto done;
- }
- if( gettimeofday( &start, NULL ) != 0 )
- {
- debug( 1, L"acquire_lock_file: gettimeofday: %s", strerror( errno ) );
- goto done;
- }
- end = start;
- pollint.tv_sec = 0;
- pollint.tv_nsec = LOCKPOLLINTERVAL * 1000000;
- do
- {
- /*
- Try to create a hard link to the unique file from the
- lockfile. This will only succeed if the lockfile does not
- already exist. It is guaranteed to provide race-free
- semantics over NFS which the alternative of calling
- open(O_EXCL|O_CREAT) on the lockfile is not. The lock
- succeeds if the call to link returns 0 or the link count on
- the unique file increases to 2.
- */
- if( link( linkfile, lockfile ) == 0 ||
- ( stat( linkfile, &statbuf ) == 0 &&
- statbuf.st_nlink == 2 ) )
- {
- /* Successful lock */
- ret = 1;
- break;
- }
- elapsed = end.tv_sec + end.tv_usec/1000000.0 -
- ( start.tv_sec + start.tv_usec/1000000.0 );
- /*
- The check for elapsed < 0 is to deal with the unlikely event
- that after the loop is entered the system time is set forward
- past the loop's end time. This would otherwise result in a
- (practically) infinite loop.
- */
- if( timed_out || elapsed >= timeout || elapsed < 0 )
- {
- if ( timed_out == 0 && force )
- {
- /*
- Timed out and force was specified - attempt to
- remove stale lock and try a final time
- */
- (void)unlink( lockfile );
- timed_out = 1;
- continue;
- }
- else
- {
- /*
- Timed out and final try was unsuccessful or
- force was not specified
- */
- debug( 1, L"acquire_lock_file: timed out "
- L"trying to obtain lockfile %s using "
- L"linkfile %s", lockfile, linkfile );
- break;
- }
- }
- nanosleep( &pollint, NULL );
- } while( gettimeofday( &end, NULL ) == 0 );
- done:
- /* The linkfile is not needed once the lockfile has been created */
- (void)unlink( linkfile );
- free( linkfile );
- return ret;
-}
void common_handle_winch( int signal )
{