1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the Qt Solutions component.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 **     of its contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qtservice.h"
42 #include "qtservice_p.h"
43 #include <QCoreApplication>
44 #include <stdio.h>
45 #include <QTimer>
46 #include <QVector>
47 #include <QProcess>
48 
49 #if defined(QTSERVICE_DEBUG)
50 #include <QDebug>
51 #include <QString>
52 #include <QFile>
53 #include <QTime>
54 #include <QMutex>
55 #if defined(Q_OS_WIN32)
56 #include <qt_windows.h>
57 #else
58 #include <unistd.h>
59 #include <stdlib.h>
60 #endif
61 
62 static QFile* f = 0;
63 
qtServiceCloseDebugLog()64 static void qtServiceCloseDebugLog()
65 {
66     if (!f)
67         return;
68     f->write(QTime::currentTime().toString("HH:mm:ss.zzz").toLatin1());
69     f->write(" --- DEBUG LOG CLOSED ---\n\n");
70     f->flush();
71     f->close();
72     delete f;
73     f = 0;
74 }
75 
76 #if QT_VERSION >= 0x050000
qtServiceLogDebug(QtMsgType type,const QMessageLogContext & context,const QString & msg)77 void qtServiceLogDebug(QtMsgType type, const QMessageLogContext &context, const QString &msg)
78 #else
79 void qtServiceLogDebug(QtMsgType type, const char* msg)
80 #endif
81 {
82     static QMutex mutex;
83     QMutexLocker locker(&mutex);
84 #if defined(Q_OS_WIN32)
85     const qulonglong processId = GetCurrentProcessId();
86 #else
87     const qulonglong processId = getpid();
88 #endif
89     QByteArray s(QTime::currentTime().toString("HH:mm:ss.zzz").toLatin1());
90     s += " [";
91     s += QByteArray::number(processId);
92     s += "] ";
93 
94     if (!f) {
95 #if defined(Q_OS_WIN32)
96         f = new QFile("c:/service-debuglog.txt");
97 #else
98         f = new QFile("/tmp/service-debuglog.txt");
99 #endif
100         if (!f->open(QIODevice::WriteOnly | QIODevice::Append)) {
101             delete f;
102             f = 0;
103             return;
104         }
105         QByteArray ps('\n' + s + "--- DEBUG LOG OPENED ---\n");
106         f->write(ps);
107     }
108 
109     switch (type) {
110     case QtWarningMsg:
111         s += "WARNING: ";
112         break;
113     case QtCriticalMsg:
114         s += "CRITICAL: ";
115         break;
116     case QtFatalMsg:
117         s+= "FATAL: ";
118         break;
119     case QtDebugMsg:
120         s += "DEBUG: ";
121         break;
122     default:
123         // Nothing
124         break;
125     }
126 
127 #if QT_VERSION >= 0x050400
128     s += qFormatLogMessage(type, context, msg).toLocal8Bit();
129 #elif QT_VERSION >= 0x050000
130     s += msg.toLocal8Bit();
131     Q_UNUSED(context)
132 #else
133     s += msg;
134 #endif
135     s += '\n';
136 
137     f->write(s);
138     f->flush();
139 
140     if (type == QtFatalMsg) {
141         qtServiceCloseDebugLog();
142         exit(1);
143     }
144 }
145 
146 #endif
147 
148 /*!
149     \class QtServiceController
150 
151     \brief The QtServiceController class allows you to control
152     services from separate applications.
153 
154     QtServiceController provides a collection of functions that lets
155     you install and run a service controlling its execution, as well
156     as query its status.
157 
158     In order to run a service, the service must be installed in the
159     system's service database using the install() function. The system
160     will start the service depending on the specified StartupType; it
161     can either be started during system startup, or when a process
162     starts it manually.
163 
164     Once a service is installed, the service can be run and controlled
165     manually using the start(), stop(), pause(), resume() or
166     sendCommand() functions.  You can at any time query for the
167     service's status using the isInstalled() and isRunning()
168     functions, or you can query its properties using the
169     serviceDescription(), serviceFilePath(), serviceName() and
170     startupType() functions. For example:
171 
172     \code
173     MyService service;       \\ which inherits QtService
174     QString serviceFilePath;
175 
176     QtServiceController controller(service.serviceName());
177 
178     if (controller.install(serviceFilePath))
179         controller.start()
180 
181     if (controller.isRunning())
182         QMessageBox::information(this, tr("Service Status"),
183                                  tr("The %1 service is started").arg(controller.serviceName()));
184 
185     ...
186 
187     controller.stop();
188     controller.uninstall();
189     }
190     \endcode
191 
192     An instance of the service controller can only control one single
193     service. To control several services within one application, you
194     must create en equal number of service controllers.
195 
196     The QtServiceController destructor neither stops nor uninstalls
197     the associated service. To stop a service the stop() function must
198     be called explicitly. To uninstall a service, you can use the
199     uninstall() function.
200 
201     \sa QtServiceBase, QtService
202 */
203 
204 /*!
205     \enum QtServiceController::StartupType
206     This enum describes when a service should be started.
207 
208     \value AutoStartup The service is started during system startup.
209     \value ManualStartup The service must be started manually by a process.
210 
211     \warning The \a StartupType enum is ignored under UNIX-like
212     systems. A service, or daemon, can only be started manually on such
213     systems with current implementation.
214 
215     \sa startupType()
216 */
217 
218 
219 /*!
220     Creates a controller object for the service with the given
221     \a name.
222 */
QtServiceController(const QString & name)223 QtServiceController::QtServiceController(const QString &name)
224  : d_ptr(new QtServiceControllerPrivate())
225 {
226     Q_D(QtServiceController);
227     d->q_ptr = this;
228     d->serviceName = name;
229 }
230 /*!
231     Destroys the service controller. This neither stops nor uninstalls
232     the controlled service.
233 
234     To stop a service the stop() function must be called
235     explicitly. To uninstall a service, you can use the uninstall()
236     function.
237 
238     \sa stop(), QtServiceController::uninstall()
239 */
~QtServiceController()240 QtServiceController::~QtServiceController()
241 {
242     delete d_ptr;
243 }
244 /*!
245     \fn bool QtServiceController::isInstalled() const
246 
247     Returns true if the service is installed; otherwise returns false.
248 
249     On Windows it uses the system's service control manager.
250 
251     On Unix it checks configuration written to QSettings::SystemScope
252     using "QtSoftware" as organization name.
253 
254     \sa install()
255 */
256 
257 /*!
258     \fn bool QtServiceController::isRunning() const
259 
260     Returns true if the service is running; otherwise returns false. A
261     service must be installed before it can be run using a controller.
262 
263     \sa start(), isInstalled()
264 */
265 
266 /*!
267     Returns the name of the controlled service.
268 
269     \sa QtServiceController(), serviceDescription()
270 */
serviceName() const271 QString QtServiceController::serviceName() const
272 {
273     Q_D(const QtServiceController);
274     return d->serviceName;
275 }
276 /*!
277     \fn QString QtServiceController::serviceDescription() const
278 
279     Returns the description of the controlled service.
280 
281     \sa install(), serviceName()
282 */
283 
284 /*!
285     \fn QtServiceController::StartupType QtServiceController::startupType() const
286 
287     Returns the startup type of the controlled service.
288 
289     \sa install(), serviceName()
290 */
291 
292 /*!
293     \fn QString QtServiceController::serviceFilePath() const
294 
295     Returns the file path to the controlled service.
296 
297     \sa install(), serviceName()
298 */
299 
300 /*!
301     Installs the service with the given \a serviceFilePath
302     and returns true if the service is installed
303     successfully; otherwise returns false.
304 
305     On Windows service is installed in the system's service control manager with the given
306     \a account and \a password.
307 
308     On Unix service configuration is written to QSettings::SystemScope
309     using "QtSoftware" as organization name. \a account and \a password
310     arguments are ignored.
311 
312     \warning Due to the different implementations of how services (daemons)
313     are installed on various UNIX-like systems, this method doesn't
314     integrate the service into the system's startup scripts.
315 
316     \sa uninstall(), start()
317 */
install(const QString & serviceFilePath,const QString & account,const QString & password)318 bool QtServiceController::install(const QString &serviceFilePath, const QString &account,
319                 const QString &password)
320 {
321     QStringList arguments;
322     arguments << QLatin1String("-i");
323     arguments << account;
324     arguments << password;
325     return (QProcess::execute(serviceFilePath, arguments) == 0);
326 }
327 
328 
329 /*!
330     \fn bool QtServiceController::uninstall()
331 
332     Uninstalls the service and returns true if successful; otherwise returns false.
333 
334     On Windows service is uninstalled using the system's service control manager.
335 
336     On Unix service configuration is cleared using QSettings::SystemScope
337     with "QtSoftware" as organization name.
338 
339 
340     \sa install()
341 */
342 
343 /*!
344     \fn bool QtServiceController::start(const QStringList &arguments)
345 
346     Starts the installed service passing the given \a arguments to the
347     service. A service must be installed before a controller can run it.
348 
349     Returns true if the service could be started; otherwise returns
350     false.
351 
352     \sa install(), stop()
353 */
354 
355 /*!
356     \overload
357 
358     Starts the installed service without passing any arguments to the service.
359 */
start()360 bool QtServiceController::start()
361 {
362     return start(QStringList());
363 }
364 
365 /*!
366     \fn bool QtServiceController::stop()
367 
368     Requests the running service to stop. The service will call the
369     QtServiceBase::stop() implementation unless the service's state
370     is QtServiceBase::CannotBeStopped.  This function does nothing if
371     the service is not running.
372 
373     Returns true if a running service was successfully stopped;
374     otherwise false.
375 
376     \sa start(), QtServiceBase::stop(), QtServiceBase::ServiceFlags
377 */
378 
379 /*!
380     \fn bool QtServiceController::pause()
381 
382     Requests the running service to pause. If the service's state is
383     QtServiceBase::CanBeSuspended, the service will call the
384     QtServiceBase::pause() implementation. The function does nothing
385     if the service is not running.
386 
387     Returns true if a running service was successfully paused;
388     otherwise returns false.
389 
390     \sa resume(), QtServiceBase::pause(), QtServiceBase::ServiceFlags
391 */
392 
393 /*!
394     \fn bool QtServiceController::resume()
395 
396     Requests the running service to continue. If the service's state
397     is QtServiceBase::CanBeSuspended, the service will call the
398     QtServiceBase::resume() implementation. This function does nothing
399     if the service is not running.
400 
401     Returns true if a running service was successfully resumed;
402     otherwise returns false.
403 
404     \sa pause(), QtServiceBase::resume(), QtServiceBase::ServiceFlags
405 */
406 
407 /*!
408     \fn bool QtServiceController::sendCommand(int code)
409 
410     Sends the user command \a code to the service. The service will
411     call the QtServiceBase::processCommand() implementation.  This
412     function does nothing if the service is not running.
413 
414     Returns true if the request was sent to a running service;
415     otherwise returns false.
416 
417     \sa QtServiceBase::processCommand()
418 */
419 
420 class QtServiceStarter : public QObject
421 {
422     Q_OBJECT
423 public:
QtServiceStarter(QtServiceBasePrivate * service)424     QtServiceStarter(QtServiceBasePrivate *service)
425         : QObject(), d_ptr(service) {}
426 public slots:
slotStart()427     void slotStart()
428     {
429         d_ptr->startService();
430     }
431 private:
432     QtServiceBasePrivate *d_ptr;
433 };
434 #include "qtservice.moc"
435 
436 QtServiceBase *QtServiceBasePrivate::instance = 0;
437 
QtServiceBasePrivate(const QString & name)438 QtServiceBasePrivate::QtServiceBasePrivate(const QString &name)
439     : startupType(QtServiceController::ManualStartup), serviceFlags(0), controller(name)
440 {
441 
442 }
443 
~QtServiceBasePrivate()444 QtServiceBasePrivate::~QtServiceBasePrivate()
445 {
446 
447 }
448 
startService()449 void QtServiceBasePrivate::startService()
450 {
451     q_ptr->start();
452 }
453 
run(bool asService,const QStringList & argList)454 int QtServiceBasePrivate::run(bool asService, const QStringList &argList)
455 {
456     int argc = argList.size();
457     QVector<char *> argv(argc);
458     QList<QByteArray> argvData;
459     for (int i = 0; i < argc; ++i)
460         argvData.append(argList.at(i).toLocal8Bit());
461     for (int i = 0; i < argc; ++i)
462         argv[i] = argvData[i].data();
463 
464     if (asService && !sysInit())
465         return -1;
466 
467     q_ptr->createApplication(argc, argv.data());
468     QCoreApplication *app = QCoreApplication::instance();
469     if (!app)
470         return -1;
471 
472     if (asService)
473         sysSetPath();
474 
475     QtServiceStarter starter(this);
476     QTimer::singleShot(0, &starter, SLOT(slotStart()));
477     int res = q_ptr->executeApplication();
478     delete app;
479 
480     if (asService)
481         sysCleanup();
482     return res;
483 }
484 
485 
486 /*!
487     \class QtServiceBase
488 
489     \brief The QtServiceBase class provides an API for implementing
490     Windows services and Unix daemons.
491 
492     A Windows service or Unix daemon (a "service"), is a program that
493     runs "in the background" independently of whether a user is logged
494     in or not. A service is often set up to start when the machine
495     boots up, and will typically run continuously as long as the
496     machine is on.
497 
498     Services are usually non-interactive console applications. User
499     interaction, if required, is usually implemented in a separate,
500     normal GUI application that communicates with the service through
501     an IPC channel. For simple communication,
502     QtServiceController::sendCommand() and QtService::processCommand()
503     may be used, possibly in combination with a shared settings
504     file. For more complex, interactive communication, a custom IPC
505     channel should be used, e.g. based on Qt's networking classes. (In
506     certain circumstances, a service may provide a GUI itself,
507     ref. the "interactive" example documentation).
508 
509     Typically, you will create a service by subclassing the QtService
510     template class which inherits QtServiceBase and allows you to
511     create a service for a particular application type.
512 
513     The Windows implementation uses the NT Service Control Manager,
514     and the application can be controlled through the system
515     administration tools. Services are usually launched using the
516     system account, which requires that all DLLs that the service
517     executable depends on (i.e. Qt), are located in the same directory
518     as the service, or in a system path.
519 
520     On Unix a service is implemented as a daemon.
521 
522     You can retrieve the service's description, state, and startup
523     type using the serviceDescription(), serviceFlags() and
524     startupType() functions respectively. The service's state is
525     decribed by the ServiceFlag enum. The mentioned properites can
526     also be set using the corresponding set functions. In addition you
527     can retrieve the service's name using the serviceName() function.
528 
529     Several of QtServiceBase's protected functions are called on
530     requests from the QtServiceController class:
531 
532     \list
533         \o start()
534         \o pause()
535         \o processCommand()
536         \o resume()
537         \o stop()
538     \endlist
539 
540     You can control any given service using an instance of the
541     QtServiceController class which also allows you to control
542     services from separate applications. The mentioned functions are
543     all virtual and won't do anything unless they are
544     reimplemented. You can reimplement these functions to pause and
545     resume the service's execution, as well as process user commands
546     and perform additional clean-ups before shutting down.
547 
548     QtServiceBase also provides the static instance() function which
549     returns a pointer to an application's QtServiceBase instance. In
550     addition, a service can report events to the system's event log
551     using the logMessage() function. The MessageType enum describes
552     the different types of messages a service reports.
553 
554     The implementation of a service application's main function
555     typically creates an service object derived by subclassing the
556     QtService template class. Then the main function will call this
557     service's exec() function, and return the result of that call. For
558     example:
559 
560     \code
561         int main(int argc, char **argv)
562         {
563             MyService service(argc, argv);
564             return service.exec();
565         }
566     \endcode
567 
568     When the exec() function is called, it will parse the service
569     specific arguments passed in \c argv, perform the required
570     actions, and return.
571 
572     \target serviceSpecificArguments
573 
574     The following arguments are recognized as service specific:
575 
576     \table
577     \header \i Short \i Long \i Explanation
578     \row \i -i \i -install \i Install the service.
579     \row \i -u \i -uninstall \i Uninstall the service.
580     \row \i -e \i -exec
581          \i Execute the service as a standalone application (useful for debug purposes).
582             This is a blocking call, the service will be executed like a normal application.
583             In this mode you will not be able to communicate with the service from the contoller.
584     \row \i -t \i -terminate \i Stop the service.
585     \row \i -p \i -pause \i Pause the service.
586     \row \i -r \i -resume \i Resume a paused service.
587     \row \i -c \e{cmd} \i -command \e{cmd}
588 	 \i Send the user defined command code \e{cmd} to the service application.
589     \row \i -v \i -version \i Display version and status information.
590     \endtable
591 
592     If \e none of the arguments is recognized as service specific,
593     exec() will first call the createApplication() function, then
594     executeApplication() and finally the start() function. In the end,
595     exec() returns while the service continues in its own process
596     waiting for commands from the service controller.
597 
598     \sa QtService, QtServiceController
599 */
600 
601 /*!
602     \enum QtServiceBase::MessageType
603 
604     This enum describes the different types of messages a service
605     reports to the system log.
606 
607     \value Success An operation has succeeded, e.g. the service
608            is started.
609     \value Error An operation failed, e.g. the service failed to start.
610     \value Warning An operation caused a warning that might require user
611            interaction.
612     \value Information Any type of usually non-critical information.
613 */
614 
615 /*!
616     \enum QtServiceBase::ServiceFlag
617 
618     This enum describes the different capabilities of a service.
619 
620     \value Default The service can be stopped, but not suspended.
621     \value CanBeSuspended The service can be suspended.
622     \value CannotBeStopped The service cannot be stopped.
623     \value NeedsStopOnShutdown (Windows only) The service will be stopped before the system shuts down. Note that Microsoft recommends this only for services that must absolutely clean up during shutdown, because there is a limited time available for shutdown of services.
624 */
625 
626 /*!
627     Creates a service instance called \a name. The \a argc and \a argv
628     parameters are parsed after the exec() function has been
629     called. Then they are passed to the application's constructor.
630     The application type is determined by the QtService subclass.
631 
632     The service is neither installed nor started. The name must not
633     contain any backslashes or be longer than 255 characters. In
634     addition, the name must be unique in the system's service
635     database.
636 
637     \sa exec(), start(), QtServiceController::install()
638 */
QtServiceBase(int argc,char ** argv,const QString & name)639 QtServiceBase::QtServiceBase(int argc, char **argv, const QString &name)
640 {
641 #if defined(QTSERVICE_DEBUG)
642 #  if QT_VERSION >= 0x050000
643     qInstallMessageHandler(qtServiceLogDebug);
644 #  else
645     qInstallMsgHandler(qtServiceLogDebug);
646 #  endif
647     qAddPostRoutine(qtServiceCloseDebugLog);
648 #endif
649 
650     Q_ASSERT(!QtServiceBasePrivate::instance);
651     QtServiceBasePrivate::instance = this;
652 
653     QString nm(name);
654     if (nm.length() > 255) {
655 	qWarning("QtService: 'name' is longer than 255 characters.");
656 	nm.truncate(255);
657     }
658     if (nm.contains('\\')) {
659 	qWarning("QtService: 'name' contains backslashes '\\'.");
660 	nm.replace((QChar)'\\', (QChar)'\0');
661     }
662 
663     d_ptr = new QtServiceBasePrivate(nm);
664     d_ptr->q_ptr = this;
665 
666     d_ptr->serviceFlags = 0;
667     d_ptr->sysd = 0;
668     for (int i = 0; i < argc; ++i)
669         d_ptr->args.append(QString::fromLocal8Bit(argv[i]));
670 }
671 
672 /*!
673     Destroys the service object. This neither stops nor uninstalls the
674     service.
675 
676     To stop a service the stop() function must be called
677     explicitly. To uninstall a service, you can use the
678     QtServiceController::uninstall() function.
679 
680     \sa stop(), QtServiceController::uninstall()
681 */
~QtServiceBase()682 QtServiceBase::~QtServiceBase()
683 {
684     delete d_ptr;
685     QtServiceBasePrivate::instance = 0;
686 }
687 
688 /*!
689     Returns the name of the service.
690 
691     \sa QtServiceBase(), serviceDescription()
692 */
serviceName() const693 QString QtServiceBase::serviceName() const
694 {
695     return d_ptr->controller.serviceName();
696 }
697 
698 /*!
699     Returns the description of the service.
700 
701     \sa setServiceDescription(), serviceName()
702 */
serviceDescription() const703 QString QtServiceBase::serviceDescription() const
704 {
705     return d_ptr->serviceDescription;
706 }
707 
708 /*!
709     Sets the description of the service to the given \a description.
710 
711     \sa serviceDescription()
712 */
setServiceDescription(const QString & description)713 void QtServiceBase::setServiceDescription(const QString &description)
714 {
715     d_ptr->serviceDescription = description;
716 }
717 
718 /*!
719     Returns the service's startup type.
720 
721     \sa QtServiceController::StartupType, setStartupType()
722 */
startupType() const723 QtServiceController::StartupType QtServiceBase::startupType() const
724 {
725     return d_ptr->startupType;
726 }
727 
728 /*!
729     Sets the service's startup type to the given \a type.
730 
731     \sa QtServiceController::StartupType, startupType()
732 */
setStartupType(QtServiceController::StartupType type)733 void QtServiceBase::setStartupType(QtServiceController::StartupType type)
734 {
735     d_ptr->startupType = type;
736 }
737 
738 /*!
739     Returns the service's state which is decribed using the
740     ServiceFlag enum.
741 
742     \sa ServiceFlags, setServiceFlags()
743 */
serviceFlags() const744 QtServiceBase::ServiceFlags QtServiceBase::serviceFlags() const
745 {
746     return d_ptr->serviceFlags;
747 }
748 
749 /*!
750     \fn void QtServiceBase::setServiceFlags(ServiceFlags flags)
751 
752     Sets the service's state to the state described by the given \a
753     flags.
754 
755     \sa ServiceFlags, serviceFlags()
756 */
757 
758 /*!
759     Executes the service.
760 
761     When the exec() function is called, it will parse the \l
762     {serviceSpecificArguments} {service specific arguments} passed in
763     \c argv, perform the required actions, and exit.
764 
765     If none of the arguments is recognized as service specific, exec()
766     will first call the createApplication() function, then executeApplication() and
767     finally the start() function. In the end, exec()
768     returns while the service continues in its own process waiting for
769     commands from the service controller.
770 
771     \sa QtServiceController
772 */
exec()773 int QtServiceBase::exec()
774 {
775     if (d_ptr->args.size() > 1) {
776         QString a =  d_ptr->args.at(1);
777         if (a == QLatin1String("-i") || a == QLatin1String("-install")) {
778             if (!d_ptr->controller.isInstalled()) {
779                 QString account;
780                 QString password;
781                 if (d_ptr->args.size() > 2)
782                     account = d_ptr->args.at(2);
783                 if (d_ptr->args.size() > 3)
784                     password = d_ptr->args.at(3);
785                 if (!d_ptr->install(account, password)) {
786                     fprintf(stderr, "The service %s could not be installed\n", serviceName().toLatin1().constData());
787                     return -1;
788                 } else {
789                     printf("The service %s has been installed under: %s\n",
790                         serviceName().toLatin1().constData(), d_ptr->filePath().toLatin1().constData());
791                 }
792             } else {
793                 fprintf(stderr, "The service %s is already installed\n", serviceName().toLatin1().constData());
794             }
795             return 0;
796         } else if (a == QLatin1String("-u") || a == QLatin1String("-uninstall")) {
797             if (d_ptr->controller.isInstalled()) {
798                 if (!d_ptr->controller.uninstall()) {
799                     fprintf(stderr, "The service %s could not be uninstalled\n", serviceName().toLatin1().constData());
800                     return -1;
801                 } else {
802                     printf("The service %s has been uninstalled.\n",
803                         serviceName().toLatin1().constData());
804                 }
805             } else {
806                 fprintf(stderr, "The service %s is not installed\n", serviceName().toLatin1().constData());
807             }
808             return 0;
809         } else if (a == QLatin1String("-v") || a == QLatin1String("-version")) {
810             printf("The service\n"
811                 "\t%s\n\t%s\n\n", serviceName().toLatin1().constData(), d_ptr->args.at(0).toLatin1().constData());
812             printf("is %s", (d_ptr->controller.isInstalled() ? "installed" : "not installed"));
813             printf(" and %s\n\n", (d_ptr->controller.isRunning() ? "running" : "not running"));
814             return 0;
815         } else if (a == QLatin1String("-e") || a == QLatin1String("-exec")) {
816             d_ptr->args.removeAt(1);
817             int ec = d_ptr->run(false, d_ptr->args);
818             if (ec == -1)
819                 qErrnoWarning("The service could not be executed.");
820             return ec;
821         } else if (a == QLatin1String("-t") || a == QLatin1String("-terminate")) {
822             if (!d_ptr->controller.stop())
823                 qErrnoWarning("The service could not be stopped.");
824             return 0;
825         } else if (a == QLatin1String("-p") || a == QLatin1String("-pause")) {
826             d_ptr->controller.pause();
827             return 0;
828         } else if (a == QLatin1String("-r") || a == QLatin1String("-resume")) {
829             d_ptr->controller.resume();
830             return 0;
831         } else if (a == QLatin1String("-c") || a == QLatin1String("-command")) {
832             int code = 0;
833             if (d_ptr->args.size() > 2)
834                 code = d_ptr->args.at(2).toInt();
835             d_ptr->controller.sendCommand(code);
836             return 0;
837         } else  if (a == QLatin1String("-h") || a == QLatin1String("-help")) {
838             printf("\n%s -[i|u|e|t|p|r|c|v|h]\n"
839                    "\t-i(nstall) [account] [password]\t: Install the service, optionally using given account and password\n"
840                    "\t-u(ninstall)\t: Uninstall the service.\n"
841                    "\t-e(xec)\t\t: Run as a regular application. Useful for debugging.\n"
842                    "\t-t(erminate)\t: Stop the service.\n"
843                    "\t-p(ause)\t: Pause the service.\n"
844                    "\t-r(esume)\t: Resume a paused service.\n"
845                    "\t-c(ommand) num\t: Send command code num to the service.\n"
846                    "\t-v(ersion)\t: Print version and status information.\n"
847                    "\t-h(elp)   \t: Show this help\n"
848                    "\tNo arguments\t: Start the service.\n",
849                    d_ptr->args.at(0).toLatin1().constData());
850             return 0;
851         }
852     }
853 #if defined(Q_OS_UNIX)
854     if (::getenv("QTSERVICE_RUN")) {
855         // Means we're the detached, real service process.
856         int ec = d_ptr->run(true, d_ptr->args);
857         if (ec == -1)
858             qErrnoWarning("The service failed to run.");
859         return ec;
860     }
861 #endif
862     if (!d_ptr->start()) {
863         fprintf(stderr, "The service %s could not start\n", serviceName().toLatin1().constData());
864         return -4;
865     }
866     return 0;
867 }
868 
869 /*!
870     \fn void QtServiceBase::logMessage(const QString &message, MessageType type,
871             int id, uint category, const QByteArray &data)
872 
873     Reports a message of the given \a type with the given \a message
874     to the local system event log.  The message identifier \a id and
875     the message \a category are user defined values. The \a data
876     parameter can contain arbitrary binary data.
877 
878     Message strings for \a id and \a category must be provided by a
879     message file, which must be registered in the system registry.
880     Refer to the MSDN for more information about how to do this on
881     Windows.
882 
883     \sa MessageType
884 */
885 
886 /*!
887     Returns a pointer to the current application's QtServiceBase
888     instance.
889 */
instance()890 QtServiceBase *QtServiceBase::instance()
891 {
892     return QtServiceBasePrivate::instance;
893 }
894 
895 /*!
896     \fn void QtServiceBase::start()
897 
898     This function must be implemented in QtServiceBase subclasses in
899     order to perform the service's work. Usually you create some main
900     object on the heap which is the heart of your service.
901 
902     The function is only called when no service specific arguments
903     were passed to the service constructor, and is called by exec()
904     after it has called the executeApplication() function.
905 
906     Note that you \e don't need to create an application object or
907     call its exec() function explicitly.
908 
909     \sa exec(), stop(), QtServiceController::start()
910 */
911 
912 /*!
913     Reimplement this function to perform additional cleanups before
914     shutting down (for example deleting a main object if it was
915     created in the start() function).
916 
917     This function is called in reply to controller requests. The
918     default implementation does nothing.
919 
920     \sa start(), QtServiceController::stop()
921 */
stop()922 void QtServiceBase::stop()
923 {
924 }
925 
926 /*!
927     Reimplement this function to pause the service's execution (for
928     example to stop a polling timer, or to ignore socket notifiers).
929 
930     This function is called in reply to controller requests.  The
931     default implementation does nothing.
932 
933     \sa resume(), QtServiceController::pause()
934 */
pause()935 void QtServiceBase::pause()
936 {
937 }
938 
939 /*!
940     Reimplement this function to continue the service after a call to
941     pause().
942 
943     This function is called in reply to controller requests. The
944     default implementation does nothing.
945 
946     \sa pause(), QtServiceController::resume()
947 */
resume()948 void QtServiceBase::resume()
949 {
950 }
951 
952 /*!
953     Reimplement this function to process the user command \a code.
954 
955 
956     This function is called in reply to controller requests.  The
957     default implementation does nothing.
958 
959     \sa QtServiceController::sendCommand()
960 */
processCommand(int)961 void QtServiceBase::processCommand(int /*code*/)
962 {
963 }
964 
965 /*!
966     \fn void QtServiceBase::createApplication(int &argc, char **argv)
967 
968     Creates the application object using the \a argc and \a argv
969     parameters.
970 
971     This function is only called when no \l
972     {serviceSpecificArguments}{service specific arguments} were
973     passed to the service constructor, and is called by exec() before
974     it calls the executeApplication() and start() functions.
975 
976     The createApplication() function is implemented in QtService, but
977     you might want to reimplement it, for example, if the chosen
978     application type's constructor needs additional arguments.
979 
980     \sa exec(), QtService
981 */
982 
983 /*!
984     \fn int QtServiceBase::executeApplication()
985 
986     Executes the application previously created with the
987     createApplication() function.
988 
989     This function is only called when no \l
990     {serviceSpecificArguments}{service specific arguments} were
991     passed to the service constructor, and is called by exec() after
992     it has called the createApplication() function and before start() function.
993 
994     This function is implemented in QtService.
995 
996     \sa exec(), createApplication()
997 */
998 
999 /*!
1000     \class QtService
1001 
1002     \brief The QtService is a convenient template class that allows
1003     you to create a service for a particular application type.
1004 
1005     A Windows service or Unix daemon (a "service"), is a program that
1006     runs "in the background" independently of whether a user is logged
1007     in or not. A service is often set up to start when the machine
1008     boots up, and will typically run continuously as long as the
1009     machine is on.
1010 
1011     Services are usually non-interactive console applications. User
1012     interaction, if required, is usually implemented in a separate,
1013     normal GUI application that communicates with the service through
1014     an IPC channel. For simple communication,
1015     QtServiceController::sendCommand() and QtService::processCommand()
1016     may be used, possibly in combination with a shared settings file. For
1017     more complex, interactive communication, a custom IPC channel
1018     should be used, e.g. based on Qt's networking classes. (In certain
1019     circumstances, a service may provide a GUI itself, ref. the
1020     "interactive" example documentation).
1021 
1022     \bold{Note:} On Unix systems, this class relies on facilities
1023     provided by the QtNetwork module, provided as part of the
1024     \l{Qt Open Source Edition} and certain \l{Qt Commercial Editions}.
1025 
1026     The QtService class functionality is inherited from QtServiceBase,
1027     but in addition the QtService class binds an instance of
1028     QtServiceBase with an application type.
1029 
1030     Typically, you will create a service by subclassing the QtService
1031     template class. For example:
1032 
1033     \code
1034     class MyService : public QtService<QApplication>
1035     {
1036     public:
1037         MyService(int argc, char **argv);
1038         ~MyService();
1039 
1040     protected:
1041         void start();
1042         void stop();
1043         void pause();
1044         void resume();
1045         void processCommand(int code);
1046     };
1047     \endcode
1048 
1049     The application type can be QCoreApplication for services without
1050     GUI, QApplication for services with GUI or you can use your own
1051     custom application type.
1052 
1053     You must reimplement the QtServiceBase::start() function to
1054     perform the service's work. Usually you create some main object on
1055     the heap which is the heart of your service.
1056 
1057     In addition, you might want to reimplement the
1058     QtServiceBase::pause(), QtServiceBase::processCommand(),
1059     QtServiceBase::resume() and QtServiceBase::stop() to intervene the
1060     service's process on controller requests. You can control any
1061     given service using an instance of the QtServiceController class
1062     which also allows you to control services from separate
1063     applications. The mentioned functions are all virtual and won't do
1064     anything unless they are reimplemented.
1065 
1066     Your custom service is typically instantiated in the application's
1067     main function. Then the main function will call your service's
1068     exec() function, and return the result of that call. For example:
1069 
1070     \code
1071         int main(int argc, char **argv)
1072         {
1073             MyService service(argc, argv);
1074             return service.exec();
1075         }
1076     \endcode
1077 
1078     When the exec() function is called, it will parse the \l
1079     {serviceSpecificArguments} {service specific arguments} passed in
1080     \c argv, perform the required actions, and exit.
1081 
1082     If none of the arguments is recognized as service specific, exec()
1083     will first call the createApplication() function, then executeApplication() and
1084     finally the start() function. In the end, exec()
1085     returns while the service continues in its own process waiting for
1086     commands from the service controller.
1087 
1088     \sa QtServiceBase, QtServiceController
1089 */
1090 
1091 /*!
1092     \fn QtService::QtService(int argc, char **argv, const QString &name)
1093 
1094     Constructs a QtService object called \a name. The \a argc and \a
1095     argv parameters are parsed after the exec() function has been
1096     called. Then they are passed to the application's constructor.
1097 
1098     There can only be one QtService object in a process.
1099 
1100     \sa QtServiceBase()
1101 */
1102 
1103 /*!
1104     \fn QtService::~QtService()
1105 
1106     Destroys the service object.
1107 */
1108 
1109 /*!
1110     \fn Application *QtService::application() const
1111 
1112     Returns a pointer to the application object.
1113 */
1114 
1115 /*!
1116     \fn void QtService::createApplication(int &argc, char **argv)
1117 
1118     Creates application object of type Application passing \a argc and
1119     \a argv to its constructor.
1120 
1121     \reimp
1122 
1123 */
1124 
1125 /*!
1126     \fn int QtService::executeApplication()
1127 
1128     \reimp
1129 */
1130