1/*
2 kwrited is a write(1) receiver for KDE.
3 Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
4 Copyright 2008 by George Kiagiadakis <gkiagia@users.sourceforge.net>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20*/
21
22// Own
23#include "kwrited.h"
24
25#include <kdebug.h>
26#include <kptydevice.h>
27#include <kuser.h>
28#include <knotification.h>
29#include <klocalizedstring.h>
30#include <kaboutdata.h>
31#include <config-workspace.h>
32
33#if defined(BUILD_AS_EXECUTABLE)
34# include <QtCore/QCoreApplication>
35# include <kcomponentdata.h>
36# include <signal.h>
37# include <sys/types.h>
38# include <unistd.h>
39#else
40# include <kpluginfactory.h>
41# include <kpluginloader.h>
42#endif
43
44static inline KAboutData aboutData()
45{
46 return KAboutData("kwrited", 0, ki18n("kwrited"), WORKSPACE_VERSION_STRING);
47}
48
49#if defined(BUILD_AS_EXECUTABLE)
50
51static uid_t original_euid;
52static gid_t original_egid;
53
54static void sigterm_handler(int signal)
55{
56 Q_UNUSED(signal)
57 QCoreApplication::quit();
58}
59
60int main(int argc, char **argv)
61{
62 //drop elevated privileges temporarily
63 original_euid = geteuid();
64 original_egid = getegid();
65 seteuid(getuid());
66 setegid(getgid());
67
68 //install a signal handler to exit gracefully
69 //(so that pty->logout() is called in ~KWrited())
70 signal(SIGTERM, sigterm_handler);
71 signal(SIGINT, sigterm_handler);
72 signal(SIGHUP, sigterm_handler);
73
74 KComponentData kcompdata(aboutData());
75 QCoreApplication a(argc, argv);
76 KWrited w;
77 return a.exec();
78}
79
80#else // BUILD_AS_EXECUTABLE
81
82KWritedModule::KWritedModule(QObject* parent, const QList<QVariant>&)
83 : KDEDModule(parent)
84{
85 pro = new KWrited;
86}
87
88KWritedModule::~KWritedModule()
89{
90 delete pro;
91}
92
93K_PLUGIN_FACTORY(KWritedFactory,
94 registerPlugin<KWritedModule>();
95 )
96K_EXPORT_PLUGIN(KWritedFactory(aboutData()))
97
98#endif //BUILD_AS_EXECUTABLE
99
100
101KWrited::KWrited() : QObject()
102{
103 pty = new KPtyDevice();
104 pty->open();
105
106#if defined(BUILD_AS_EXECUTABLE)
107 dup2(pty->slaveFd(), 0); //HACK: login() from glibc requires this to login correctly
108 //restore elevated privileges
109 seteuid(original_euid);
110 setegid(original_egid);
111#endif
112
113 pty->login(KUser(KUser::UseRealUserID).loginName().toLocal8Bit().data(), qgetenv("DISPLAY"));
114
115#if defined(BUILD_AS_EXECUTABLE)
116 //drop privileges again
117 seteuid(getuid());
118 setegid(getgid());
119#endif
120
121 connect(pty, SIGNAL(readyRead()), this, SLOT(block_in()));
122 kDebug() << "listening on device" << pty->ttyName();
123}
124
125KWrited::~KWrited()
126{
127#if defined(BUILD_AS_EXECUTABLE)
128 //restore elevated privileges
129 seteuid(original_euid);
130 setegid(original_egid);
131#endif
132
133 pty->logout();
134
135#if defined(BUILD_AS_EXECUTABLE)
136 //drop privileges again
137 seteuid(getuid());
138 setegid(getgid());
139#endif
140
141 delete pty;
142}
143
144void KWrited::block_in()
145{
146 QByteArray buf = pty->readAll();
147 QString msg = QString::fromLocal8Bit( buf.constData(), buf.size() );
148 msg.remove('\r');
149 msg.remove('\a');
150
151 KNotification *notification = new KNotification("NewMessage", 0, KNotification::Persistent);
152#if !defined(BUILD_AS_EXECUTABLE)
153 notification->setComponentData( KWritedFactory::componentData() );
154#endif
155 notification->setText( msg );
156 connect(notification, SIGNAL(closed()), notification, SLOT(deleteLater()) );
157 notification->sendEvent();
158}
159
160#include "kwrited.moc"
161