/*********************************************************************** * * Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, Novell, Inc. * * To contact Novell about this file by physical or electronic mail, * you may find current contact information at www.novell.com. * ***********************************************************************/ using System; using System.IO; using System.Text; using System.Threading; using System.Diagnostics; using sscs.communication; using sscs.constants; using sscs.common; class SecretStoreClientService { private static Communication server = null; private static Thread listeningThread = null; public static void Main(string[] args) { CSSSLogger.ExecutionTrace(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); try { /* If getting a lock fails, just exit. */ if(!AcquireLock()) { Console.WriteLine("Another instance of micasad is already running"); Mono.Unix.Native.Syscall.exit(-1); } RegisterSignals(); CSSSLogger.DbgLog("Client Side SecretStore Service has started."); server = CommunicationFactory.CreateCommunicationEndPoint(); listeningThread = new Thread(new ThreadStart(StartServer)); listeningThread.Start(); listeningThread.Join(); } catch(Exception e) { Terminate(); } } /* The thread which listens and spawns threads on every accept * starts its execution from this method. */ private static void StartServer() { try { CSSSLogger.ExecutionTrace(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); server.StartCommunicationEndPoint(); } catch(ThreadAbortException exp) { CSSSLogger.DbgLog("Listening thread of miCASAd is going down."); CSSSLogger.ExpLog(exp.ToString()); } catch(Exception exp) { CSSSLogger.ExpLog(exp.ToString()); } CSSSLogger.DbgLog("Listening thread of miCASAd is going down."); } /* This ensures that there is only one instance of * SSCS at any point. */ private static bool AcquireLock() { CSSSLogger.ExecutionTrace(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); int platform = (int)Environment.OSVersion.Platform; if( (platform == 128) || (platform == 4) ) { if(File.Exists(ConstStrings.SSCS_LINUX_PIDFILE)) { if(CheckIfMiCASAdIsRunning()) { CSSSLogger.DbgLog("Acquiring lock failed. Terminating miCASAd."); return false; } else { File.Delete(ConstStrings.SSCS_LINUX_PIDFILE); CreatePidFile(); return true; } } else { CreatePidFile(); return true; } } else return false; } private static void RegisterSignals() { CSSSLogger.ExecutionTrace(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); if(( (int)Environment.OSVersion.Platform) == 128) { //SIGTERM Mono.Unix.Native.Stdlib.signal(Mono.Unix.Native.Signum.SIGTERM, new Mono.Unix.Native.SignalHandler(Terminate)); //SIGINT Mono.Unix.Native.Stdlib.signal(Mono.Unix.Native.Signum.SIGINT, new Mono.Unix.Native.SignalHandler(Terminate)); //SIGHUP Mono.Unix.Native.Stdlib.signal(Mono.Unix.Native.Signum.SIGHUP, new Mono.Unix.Native.SignalHandler(Terminate)); } } private static void Terminate(int sigNum) { CSSSLogger.ExecutionTrace(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); Terminate(); } private static void Terminate() { CSSSLogger.ExecutionTrace(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); CSSSLogger.DbgLog("Client Side SecretStore Service is now exiting."); if( listeningThread != null ) { listeningThread.Abort("Aborting listening thread"); } int platform = (int)Environment.OSVersion.Platform; if( (platform == 128) || (platform == 4) ) { if( File.Exists(ConstStrings.SSCS_LINUX_PIDFILE) ) { File.Delete(ConstStrings.SSCS_LINUX_PIDFILE); } Mono.Unix.Native.Syscall.exit(0); } } private static void CreatePidFile() { int pid = Mono.Unix.Native.Syscall.getpid(); string pidStr = String.Format("{0}",pid); FileInfo fInfo = new FileInfo(ConstStrings.SSCS_LINUX_PIDFILE); FileStream fs = fInfo.Open(System.IO.FileMode.OpenOrCreate, FileAccess.ReadWrite); StreamWriter w = new StreamWriter(fs); w.Write(pidStr); w.Flush(); fs.Close(); } private static bool CheckIfMiCASAdIsRunning() { try { StreamReader sr = new StreamReader(ConstStrings.SSCS_LINUX_PIDFILE); string line = sr.ReadLine(); if( line == null ) { sr.Close(); return false; } string procPath = "/proc/"+ line + "/cmdline"; /* If the file procPath itself does not exist, * then another instance is surely not running. */ if( !File.Exists(procPath) ) { return false; } /* There is a possibility that the pid stored in * the pidfile has been reassigned to another process. * So, if procPath exists, check if the process is * micasad.exe. */ StreamReader procReader = new StreamReader(procPath); string cmdline = procReader.ReadLine(); /* string assemblyName = (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType).Assembly.FullName + ".exe\0"; */ string assemblyName = "micasad.exe\0"; if(cmdline.EndsWith(assemblyName)) { return true; } else { return false; } } catch(Exception e) { return false; } } }