⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svcproc.cxx

📁 opal的ptlib c++源程序 可以从官方网站上下载
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/*
 * svcproc.cxx
 *
 * Service process (daemon) implementation.
 *
 * Portable Windows Library
 *
 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is Portable Windows Library.
 *
 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
 *
 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
 * All Rights Reserved.
 *
 * Contributor(s): ______________________________________.
 *
 * $Revision: 19008 $
 * $Author: rjongbloed $
 * $Date: 2007-11-29 09:17:41 +0000 (Thu, 29 Nov 2007) $
 */

#include <ptlib.h>

#pragma implementation "svcproc.h"
#include <ptlib/svcproc.h>

#ifdef P_VXWORKS
#include <logLib.h>
#define LOG_EMERG      0
#define LOG_ALERT      1
#define LOG_CRIT      2
#define LOG_ERR        3
#define LOG_WARNING      4
#define  LOG_NOTICE      5
#define LOG_INFO      6
#define LOG_DEBUG      7
#else
#include <syslog.h>
#include <pwd.h>
#include <grp.h>
#endif

#include <stdarg.h>
#if (__GNUC__ >= 3)
#include <fstream>
#else
#include <fstream.h>
#endif
#include <signal.h>

#include "uerror.h"

#ifdef P_LINUX
#include <sys/resource.h>
#endif

#define new PNEW

extern void PXSignalHandler(int);

#define  MAX_LOG_LINE_LEN  1024

#ifndef P_VXWORKS
static int PwlibLogToUnixLog[PSystemLog::NumLogLevels] = {
  LOG_CRIT,    // LogFatal,   
  LOG_ERR,     // LogError,   
  LOG_WARNING, // LogWarning, 
  LOG_INFO,    // LogInfo,    
  LOG_DEBUG,   // LogDebug
  LOG_DEBUG,
  LOG_DEBUG,
  LOG_DEBUG,
  LOG_DEBUG,
  LOG_DEBUG
};
#endif // !P_VXWORKS

static const char * const PLevelName[PSystemLog::NumLogLevels+1] = {
  "Message",
  "Fatal error",
  "Error",
  "Warning",
  "Info",
  "Debug",
  "Debug2",
  "Debug3",
  "Debug4",
  "Debug5",
  "Debug6",
};

#ifdef P_MAC_MPTHREADS
// alas, this can't be statically initialized
// XXX This ought to be an MPCriticalRegionID, but they're broken in
// XXX Mac OS X 10.0.x!
static MPSemaphoreID logMutex;

// yuck.
static void SetUpLogMutex()
{
    if (logMutex == 0) {
        MPSemaphoreID tempCrit;
        long err = MPCreateSemaphore(1, 1, &tempCrit);
        PAssertOS(err == 0);
        if (!OTCompareAndSwap32(0, (UInt32)tempCrit, (UInt32*)&logMutex)) {
            // lost the race
            MPDeleteSemaphore(tempCrit);
        }
    }
}
#endif
#ifdef P_PTHREADS

static pthread_mutex_t logMutex = PTHREAD_MUTEX_INITIALIZER;

#endif

void PSystemLog::Output(Level level, const char * cmsg)
{
  PString systemLogFileName = PServiceProcess::Current().systemLogFileName;
  if (systemLogFileName.IsEmpty()) {
#ifdef P_VXWORKS
    printf("%s\n",cmsg);
    logMsg((char *)(const char)cmsg,0,0,0,0,0,0);
#else
    syslog(PwlibLogToUnixLog[level], "%s", cmsg);
#endif
  }
  else {
#ifdef P_PTHREADS
    pthread_mutex_lock(&logMutex);
#endif
#ifdef P_MAC_MPTHREADS
    SetUpLogMutex();
    (void)MPWaitOnSemaphore(logMutex, kDurationForever);
#endif

    ostream * out;
    if (systemLogFileName == "-")
      out = &cerr;
    else
      out = new ofstream(systemLogFileName, ios::app);

    PTime now;
    *out << now.AsString("yyyy/MM/dd hh:mm:ss.uuu\t");

    PThread * thread = PThread::Current();
    if (thread == NULL) {
#ifdef P_MAC_MPTHREADS
      unsigned tid = (unsigned)MPCurrentTaskID();
#elif defined(P_VXWORKS)
      unsigned tid = ::taskIdSelf();
#elif defined(BE_THREADS)
      thread_id tid = ::find_thread(NULL);
#else
      unsigned tid = (unsigned) pthread_self();
#endif
      *out << "ThreadID=0x"
           << setfill('0') << ::hex
           << setw(8) << tid
           << setfill(' ') << ::dec;
    } else {
      PString threadName = thread->GetThreadName();
      if (threadName.GetLength() <= 23)
        *out << setw(23) << threadName;
      else
        *out << threadName.Left(10) << "..." << threadName.Right(10);
    }

    *out << '\t'
         << PLevelName[level+1]
         << '\t'
         << cmsg << endl;

    if (out != &cerr)
      delete out;

#ifdef P_PTHREADS
    pthread_mutex_unlock(&logMutex);
#endif
#ifdef P_MAC_MPTHREADS
    MPSignalSemaphore(logMutex);
#endif
  }
}


int PSystemLog::Buffer::overflow(int c)
{
  if (pptr() >= epptr()) {
    int ppos = pptr() - pbase();
    char * newptr = string.GetPointer(string.GetSize() + 10);
    setp(newptr, newptr + string.GetSize() - 1);
    pbump(ppos);
  }
  if (c != EOF) {
    *pptr() = (char)c;
    pbump(1);
  }
  return 0;
}


int PSystemLog::Buffer::underflow()
{
  return EOF;
}


int PSystemLog::Buffer::sync()
{
  PSystemLog::Output(log->logLevel, string);

  string = PString();
  char * base = string.GetPointer(10);
  setp(base, base + string.GetSize() - 1);
  return 0;
}


PServiceProcess::PServiceProcess(const char * manuf,
                                 const char * name,
                                         WORD majorVersion,
                                         WORD minorVersion,
                                   CodeStatus status,
                                         WORD buildNumber)
  : PProcess(manuf, name, majorVersion, minorVersion, status, buildNumber)
{
  currentLogLevel = PSystemLog::Warning;
  isTerminating = PFalse;
}


PServiceProcess::~PServiceProcess()
{
  PSetErrorStream(NULL);
  PTrace::SetStream(NULL);
  PTrace::ClearOptions(PTrace::SystemLogStream);

  if (!pidFileToRemove)
    PFile::Remove(pidFileToRemove);

#ifndef P_VXWORKS
  // close the system log
  if (systemLogFileName.IsEmpty())
    closelog();
#endif // !P_VXWORKS
}


PServiceProcess & PServiceProcess::Current()
{
  PProcess & process = PProcess::Current();
  PAssert(PIsDescendant(&process, PServiceProcess), "Not a service process!");
  return (PServiceProcess &)process;
}


#ifndef P_VXWORKS
static int KillProcess(int pid, int sig)
{
  if (kill(pid, sig) != 0)
    return -1;

  cout << "Sent SIG";
  if (sig == SIGTERM)
    cout << "TERM";
  else
    cout << "KILL";
  cout << " to daemon at pid " << pid << ' ' << flush;

  for (PINDEX retry = 1; retry <= 10; retry++) {
    PThread::Sleep(1000);
    if (kill(pid, 0) != 0) {
      cout << "\nDaemon stopped." << endl;
      return 0;
    }
    cout << '.' << flush;
  }
  cout << "\nDaemon has not stopped." << endl;

  return 1;
}
#endif // !P_VXWORKS


void PServiceProcess::_PXShowSystemWarning(PINDEX code, const PString & str)
{
  PSYSTEMLOG(Warning, "PWLib\t" << GetOSClass() << " error #" << code << '-' << str);
}


int PServiceProcess::InitialiseService()
{
#ifndef P_VXWORKS
#if PMEMORY_CHECK
  PMemoryHeap::SetIgnoreAllocations(PTrue);
#endif
  PSetErrorStream(new PSystemLog(PSystemLog::StdError));
  PTrace::SetStream(new PSystemLog(PSystemLog::Debug3));
  PTrace::ClearOptions(PTrace::FileAndLine);
  PTrace::SetOptions(PTrace::SystemLogStream);
  PTrace::SetLevel(4);
#if PMEMORY_CHECK
  PMemoryHeap::SetIgnoreAllocations(PFalse);
#endif
  debugMode = PFalse;

  // parse arguments so we can grab what we want
  PArgList & args = GetArguments();

  args.Parse("v-version."
             "d-daemon."
             "c-console."
             "h-help."
             "x-execute."
             "p-pid-file:"
       "H-handlemax:"
             "i-ini-file:"
             "k-kill."
             "t-terminate."
             "s-status."
             "l-log-file:"
             "u-uid:"
             "g-gid:"
             "C-core-size:");

  // if only displaying version information, do it and finish
  if (args.HasOption('v')) {
    cout << "Product Name: " << productName << endl
         << "Manufacturer: " << manufacturer << endl
         << "Version     : " << GetVersion(PTrue) << endl
         << "System      : " << GetOSName() << '-'
                             << GetOSHardware() << ' '
                             << GetOSVersion() << endl;
    return 0;
  }

  PString pidfilename;
  if (args.HasOption('p'))
    pidfilename = args.GetOptionString('p');
#ifdef _PATH_VARRUN
  else
    pidfilename =  _PATH_VARRUN;
#endif

  if (!pidfilename && PDirectory::Exists(pidfilename))
    pidfilename = PDirectory(pidfilename) + PProcess::Current().GetFile().GetFileName() + ".pid";

  if (args.HasOption('k') || args.HasOption('t') || args.HasOption('s')) {
    pid_t pid;

    {
      ifstream pidfile(pidfilename);
      if (!pidfile.is_open()) {
        cout << "Could not open pid file: \"" << pidfilename << "\""
                " - " << strerror(errno) << endl;
        return 1;
      }

      pidfile >> pid;
      if (pid == 0) {
        cout << "Illegal format pid file \"" << pidfilename << '"' << endl;
        return 1;
      }
    }

    if (args.HasOption('s')) {
      cout << "Process at " << pid << ' ';
      if (kill(pid, 0) == 0)
        cout << "is running.";
      else if (errno == ESRCH)
        cout << "does not exist.";
      else
        cout << " status could not be determined, error: " << strerror(errno);
      cout << endl;
      return 0;
    }

    int sig = args.HasOption('t') ? SIGTERM : SIGKILL;
    switch (KillProcess(pid, sig)) {
      case -1 :
        break;
      case 0 :
        PFile::Remove(pidfilename);
        return 0;
      case 1 :
        if (args.HasOption('t') && args.HasOption('k')) {
          switch (KillProcess(pid, SIGKILL)) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -