зеркало из https://github.com/mozilla/gecko-dev.git
306 строки
7.4 KiB
C
306 строки
7.4 KiB
C
#include "xp.h"
|
|
#include "xpgetstr.h"
|
|
|
|
#include <signal.h>
|
|
#include <pwd.h>
|
|
|
|
#ifdef NSPR20
|
|
#include "private/prpriv.h" /* for PR_NewNamedMonitor */
|
|
#endif /* NSPR20 */
|
|
|
|
extern int GNOMEFE_APP_HAS_DETECTED_LOCK;
|
|
extern int GNOMEFE_ANOTHER_USER_IS_RUNNING_APP;
|
|
extern int GNOMEFE_EXISTED_BUT_WAS_NOT_A_DIRECTORY;
|
|
extern int GNOMEFE_EXISTS_BUT_UNABLE_TO_RENAME;
|
|
extern int GNOMEFE_UNABLE_TO_CREATE_DIRECTORY;
|
|
extern int GNOMEFE_UNKNOWN_ERROR;
|
|
extern int GNOMEFE_APPEARS_TO_BE_RUNNING_ON_HOST_UNDER_PID;
|
|
extern int GNOMEFE_YOU_MAY_CONTINUE_TO_USE;
|
|
extern int GNOMEFE_OTHERWISE_CHOOSE_CANCEL;
|
|
|
|
char *fe_config_dir;
|
|
char *fe_home_dir;
|
|
char *fe_pidlock;
|
|
|
|
#define MAXTRIES 100
|
|
|
|
static XP_Bool
|
|
fe_ensure_config_dir_exists ()
|
|
{
|
|
char *dir, *fmt;
|
|
static char buf [2048];
|
|
struct stat st;
|
|
XP_Bool exists;
|
|
|
|
dir = PR_smprintf ("%s/%s", fe_home_dir, MOZ_USER_DIR);
|
|
if (!dir)
|
|
return FALSE;
|
|
|
|
exists = !stat (dir, &st);
|
|
|
|
if (exists && !(st.st_mode & S_IFDIR))
|
|
{
|
|
/* It exists but is not a directory!
|
|
Rename the old file so that we can create the directory.
|
|
*/
|
|
char *loser = (char *) XP_ALLOC (XP_STRLEN (dir) + 100);
|
|
XP_STRCPY (loser, dir);
|
|
XP_STRCAT (loser, ".BAK");
|
|
if (rename (dir, loser) == 0)
|
|
{
|
|
fmt = XP_GetString( GNOMEFE_EXISTED_BUT_WAS_NOT_A_DIRECTORY );
|
|
exists = FALSE;
|
|
}
|
|
else
|
|
{
|
|
fmt = XP_GetString( GNOMEFE_EXISTS_BUT_UNABLE_TO_RENAME );
|
|
}
|
|
|
|
PR_snprintf (buf, sizeof (buf), fmt, XP_AppName, dir, loser);
|
|
XP_FREE (loser);
|
|
FE_Alert(FE_GetInitContext(), buf);
|
|
if (exists)
|
|
{
|
|
free (dir);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (!exists)
|
|
{
|
|
/* ~/.netscape/ does not exist. Create the directory.
|
|
*/
|
|
if (mkdir (dir, 0700) < 0)
|
|
{
|
|
fmt = XP_GetString( GNOMEFE_UNABLE_TO_CREATE_DIRECTORY );
|
|
PR_snprintf (buf, sizeof (buf), fmt, XP_AppName, dir,
|
|
((errno >= 0 && errno < sys_nerr)
|
|
? sys_errlist [errno] : XP_GetString( GNOMEFE_UNKNOWN_ERROR )));
|
|
FE_Alert(FE_GetInitContext(), buf);
|
|
free (dir);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
fe_config_dir = dir;
|
|
return TRUE;
|
|
}
|
|
|
|
static int
|
|
fe_create_pidlock (const char *name, unsigned long *paddr, pid_t *ppid)
|
|
{
|
|
char hostname[64]; /* should use MAXHOSTNAMELEN */
|
|
PRHostEnt *hp, hpbuf;
|
|
char dbbuf[PR_NETDB_BUF_SIZE];
|
|
unsigned long myaddr, addr;
|
|
struct in_addr inaddr;
|
|
char *signature;
|
|
int len, tries, rval;
|
|
char buf[1024]; /* should use PATH_MAX or pathconf */
|
|
char *colon, *after;
|
|
pid_t pid;
|
|
|
|
#ifndef NSPR20
|
|
if (gethostname (hostname, sizeof hostname) < 0 ||
|
|
(hp = PR_gethostbyname (hostname, &hpbuf, dbbuf, sizeof(dbbuf), 0)) == NULL)
|
|
inaddr.s_addr = INADDR_LOOPBACK;
|
|
else
|
|
memcpy (&inaddr, hp->h_addr, sizeof inaddr);
|
|
#else
|
|
{
|
|
PRStatus sts;
|
|
|
|
sts = PR_GetSystemInfo(PR_SI_HOSTNAME, hostname, sizeof(hostname));
|
|
if (sts == PR_FAILURE)
|
|
inaddr.s_addr = INADDR_LOOPBACK;
|
|
else {
|
|
sts = PR_GetHostByName (hostname, dbbuf, sizeof(dbbuf), &hpbuf);
|
|
if (sts == PR_FAILURE)
|
|
inaddr.s_addr = INADDR_LOOPBACK;
|
|
else {
|
|
hp = &hpbuf;
|
|
memcpy (&inaddr, hp->h_addr, sizeof inaddr);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
myaddr = inaddr.s_addr;
|
|
signature = PR_smprintf ("%s:%u", inet_ntoa (inaddr), (unsigned)getpid ());
|
|
tries = 0;
|
|
addr = 0;
|
|
pid = 0;
|
|
while ((rval = symlink (signature, name)) < 0)
|
|
{
|
|
if (errno != EEXIST)
|
|
break;
|
|
len = readlink (name, buf, sizeof buf - 1);
|
|
if (len > 0)
|
|
{
|
|
buf[len] = '\0';
|
|
colon = strchr (buf, ':');
|
|
if (colon != NULL)
|
|
{
|
|
*colon++ = '\0';
|
|
if ((addr = inet_addr (buf)) != (unsigned long)-1)
|
|
{
|
|
pid = strtol (colon, &after, 0);
|
|
if (pid != 0 && *after == '\0')
|
|
{
|
|
if (addr != myaddr)
|
|
{
|
|
/* Remote pid: give up even if lock is stuck. */
|
|
break;
|
|
}
|
|
|
|
/* signator was a local process -- check liveness */
|
|
if (kill (pid, 0) == 0 || errno != ESRCH)
|
|
{
|
|
/* Lock-owning process appears to be alive. */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Try to claim a bogus or stuck lock. */
|
|
(void) unlink (name);
|
|
if (++tries > MAXTRIES)
|
|
break;
|
|
}
|
|
|
|
if (rval == 0)
|
|
{
|
|
struct sigaction act, oldact;
|
|
|
|
act.sa_handler = exit; /* XXXX */
|
|
act.sa_flags = 0;
|
|
sigfillset (&act.sa_mask);
|
|
|
|
/* Set SIGINT, SIGTERM and SIGHUP to our fe_Exit(). If these signals
|
|
* have already been ignored, dont install our handler because we
|
|
* could have been started up in the background with a nohup.
|
|
*/
|
|
sigaction (SIGINT, NULL, &oldact);
|
|
if (oldact.sa_handler != SIG_IGN)
|
|
sigaction (SIGINT, &act, NULL);
|
|
|
|
sigaction (SIGHUP, NULL, &oldact);
|
|
if (oldact.sa_handler != SIG_IGN)
|
|
sigaction (SIGHUP, &act, NULL);
|
|
|
|
sigaction (SIGTERM, NULL, &oldact);
|
|
if (oldact.sa_handler != SIG_IGN)
|
|
sigaction (SIGTERM, &act, NULL);
|
|
|
|
#ifndef SUNOS4
|
|
/* atexit() is not available in sun4. We need to find someother
|
|
* mechanism to do this in sun4. Maybe we will get a signal or
|
|
* something.
|
|
*/
|
|
|
|
#if 0
|
|
/* Register a atexit() handler to remove lock file */
|
|
atexit(fe_atexit_handler);
|
|
#endif
|
|
#endif /* SUNOS4 */
|
|
}
|
|
free (signature);
|
|
*paddr = addr;
|
|
*ppid = pid;
|
|
return rval;
|
|
}
|
|
|
|
void check_for_lock_file()
|
|
{
|
|
/* See if another instance is running. If so, don't use the .db files */
|
|
if (fe_ensure_config_dir_exists ())
|
|
{
|
|
char *name;
|
|
unsigned long addr;
|
|
pid_t pid;
|
|
|
|
name = PR_smprintf ("%s/lock", fe_config_dir);
|
|
addr = 0;
|
|
pid = 0;
|
|
if (name == NULL)
|
|
/* out of memory -- what to do? */;
|
|
else if (fe_create_pidlock (name, &addr, &pid) == 0)
|
|
{
|
|
/* Remember name in fe_pidlock so we can unlink it on exit. */
|
|
fe_pidlock = name;
|
|
|
|
/* Remember that we have access to the databases.
|
|
* This lets us know when we can enable the history window. */
|
|
#if 0
|
|
fe_globalData.all_databases_locked = FALSE;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
char *fmt = NULL;
|
|
char *lock = name ? name : MOZ_USER_DIR "/lock";
|
|
|
|
fmt = PR_sprintf_append(fmt, XP_GetString(GNOMEFE_APP_HAS_DETECTED_LOCK),
|
|
XP_AppName, lock);
|
|
fmt = PR_sprintf_append(fmt,
|
|
XP_GetString(GNOMEFE_ANOTHER_USER_IS_RUNNING_APP),
|
|
XP_AppName,
|
|
fe_config_dir);
|
|
|
|
if (addr != 0 && pid != 0)
|
|
{
|
|
struct in_addr inaddr;
|
|
PRHostEnt *hp, hpbuf;
|
|
char dbbuf[PR_NETDB_BUF_SIZE];
|
|
const char *host;
|
|
|
|
inaddr.s_addr = addr;
|
|
#ifndef NSPR20
|
|
hp = PR_gethostbyaddr((char *)&inaddr, sizeof inaddr, AF_INET,
|
|
&hpbuf, dbbuf, sizeof(dbbuf), 0);
|
|
#else
|
|
{
|
|
PRStatus sts;
|
|
PRNetAddr pr_addr;
|
|
|
|
pr_addr.inet.family = AF_INET;
|
|
pr_addr.inet.ip = addr;
|
|
sts = PR_GetHostByAddr(&pr_addr,dbbuf, sizeof(dbbuf), &hpbuf);
|
|
if (sts == PR_FAILURE)
|
|
hp = NULL;
|
|
else
|
|
hp = &hpbuf;
|
|
}
|
|
#endif
|
|
host = (hp == NULL) ? inet_ntoa(inaddr) : hp->h_name;
|
|
fmt = PR_sprintf_append(fmt,
|
|
XP_GetString(GNOMEFE_APPEARS_TO_BE_RUNNING_ON_HOST_UNDER_PID),
|
|
host, (unsigned)pid);
|
|
}
|
|
|
|
fmt = PR_sprintf_append(fmt,
|
|
XP_GetString(GNOMEFE_YOU_MAY_CONTINUE_TO_USE),
|
|
XP_AppName);
|
|
fmt = PR_sprintf_append(fmt,
|
|
XP_GetString(GNOMEFE_OTHERWISE_CHOOSE_CANCEL),
|
|
XP_AppName, lock, XP_AppName);
|
|
|
|
if (fmt)
|
|
{
|
|
if (!FE_Confirm(FE_GetInitContext(), fmt))
|
|
exit (0);
|
|
free (fmt);
|
|
}
|
|
if (name) free (name);
|
|
|
|
/* Keep on-disk databases from being open-able. */
|
|
dbSetOrClearDBLock (LockOutDatabase);
|
|
#if 0
|
|
fe_globalData.all_databases_locked = TRUE;
|
|
#endif
|
|
}
|
|
}
|
|
}
|