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