~ubuntu-branches/ubuntu/oneiric/kdelibs/oneiric

« back to all changes in this revision

Viewing changes to .pc/21_kfreebsd_support.diff/kdecore/kpty.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2010-10-15 19:20:42 UTC
  • mfrom: (1.1.19 sid)
  • Revision ID: james.westby@ubuntu.com-20101015192042-jv1fhj33n4f5b398
Tags: 4:3.5.10.dfsg.1-5ubuntu1
* Merge from Debian unstable. Remaining Ubuntu changes:
  - make sure control and control.in are in sync
  - --with-distribution="Kubuntu (`lsb_release --codename --short`)
    $(DEB_VERSION)"
  - binary-install/kdelibs-data installs aboutkde-kubuntu.png.uu and
    cr*-device-system.png.uu
  - don't build-dep on libgamin-dev, libfam-dev
  - stop kdelibs4-dev depending on gamin/fam
  - don't install .svgz icons, docs or all_languages in kdelibs-data.install
  - rosetta support in rules common-install-prehook-impl:: [and
    common-post-build-arch:: ?] and include debian/kubuntu-desktop-i18n/
  - build-dep on: gettext-kde, kdesdk-scripts, lsb-release, base-files, sudo
  - cdbs build-dep 0.4.41ubuntu2
  - kdelibs4-dev depends on gettext-kde, kdesdk-scripts
  - copy debian/icons over
  - Make kdelibs4c2a depend on launchpad-integration, sudo.  Recommends on
    xdg-user-dirs
  - Remove 19_debianize_useragent.diff (changed to
    kubuntu_19_debianize_useragent.diff) s/Debian/Kubuntu
  - remove kdelibs4c2a depends on menu-xdg
  - include kubuntu_01_kdepot.diff and kde.pot in debian/patches/common
  - use a local copy of kde.mk without the common-install-prehook-impl::
    rule; edit debian-qt-kde.mk to include debian/cdbs/kde.mk
  - build with --with-sudo-kdesu-backend and build-dep on sudo and make
    kdelibs4c2a depend on sudo
  - kdelibs-data.install : Add nzb mimetype
  - Make kdelibs4-dev replace more recent kdelibs4c2a for overlapping files
  - remove /usr/bin/preparetips, arts files and ksvntopng from
    kdelibs4-dev.install
  - Drop the package kdelibs4-doc completely. It contained API documentation
    which is now obsolete, but still available via api.kde.org.
  - make sure control and control.in are in sync
  - in debian/rule remove .pot files outside .po directory
  - 97_automake_cleanup.diff becomes kubuntu_97_automake_cleanup.diff
  - Remove libarts1-dev from build-depends and kdelibs4-dev depends from
    control.in
* Drop kubuntu_98_fix_khc_invocation.diff, replaced by
  68_support_khelpcenter4.diff
* Drop kubuntu_97_automake_cleanup.diff, replaced by 97_automake_cleanup.diff
* Re-add security_05_XMLHttpRequest_vulnerability.diff which has been
  accidentally dropped
* Fix FTBFS, in debian/rules:
  - Add -Wl,--add-needed to LDFLAGS
  - Disable parallel building

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
   This file is part of the KDE libraries
 
4
   Copyright (C) 1997-2002 The Konsole Developers
 
5
   Copyright (C) 2002 Waldo Bastian <bastian@kde.org>
 
6
   Copyright (C) 2002-2003 Oswald Buddenhagen <ossi@kde.org>
 
7
 
 
8
   This library is free software; you can redistribute it and/or
 
9
   modify it under the terms of the GNU Library General Public
 
10
   License as published by the Free Software Foundation; either
 
11
   version 2 of the License, or (at your option) any later version.
 
12
 
 
13
   This library is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
   Library General Public License for more details.
 
17
 
 
18
   You should have received a copy of the GNU Library General Public License
 
19
   along with this library; see the file COPYING.LIB.  If not, write to
 
20
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
21
   Boston, MA 02110-1301, USA.
 
22
*/
 
23
 
 
24
#include <config.h>
 
25
 
 
26
#include "kpty.h"
 
27
#include "kprocess.h"
 
28
 
 
29
#ifdef __sgi
 
30
#define __svr4__
 
31
#endif
 
32
 
 
33
#ifdef __osf__
 
34
#define _OSF_SOURCE
 
35
#include <float.h>
 
36
#endif
 
37
 
 
38
#ifdef _AIX
 
39
#define _ALL_SOURCE
 
40
#endif
 
41
 
 
42
// __USE_XOPEN isn't defined by default in ICC
 
43
// (needed for ptsname(), grantpt() and unlockpt())
 
44
#ifdef __INTEL_COMPILER
 
45
#  ifndef __USE_XOPEN
 
46
#    define __USE_XOPEN
 
47
#  endif
 
48
#endif
 
49
 
 
50
#include <sys/types.h>
 
51
#include <sys/ioctl.h>
 
52
#include <sys/time.h>
 
53
#include <sys/resource.h>
 
54
#include <sys/stat.h>
 
55
#include <sys/param.h>
 
56
 
 
57
#ifdef HAVE_SYS_STROPTS_H
 
58
# include <sys/stropts.h>       // Defines I_PUSH
 
59
# define _NEW_TTY_CTRL
 
60
#endif
 
61
 
 
62
#include <errno.h>
 
63
#include <fcntl.h>
 
64
#include <time.h>
 
65
#include <stdlib.h>
 
66
#include <stdio.h>
 
67
#include <string.h>
 
68
#include <unistd.h>
 
69
#include <grp.h>
 
70
 
 
71
#ifdef HAVE_LIBUTIL_H
 
72
# include <libutil.h>
 
73
# define USE_LOGIN
 
74
#elif defined(HAVE_UTIL_H)
 
75
# include <util.h>
 
76
# define USE_LOGIN
 
77
#endif
 
78
 
 
79
#ifdef USE_LOGIN
 
80
# include <utmp.h>
 
81
#endif
 
82
 
 
83
#ifdef HAVE_TERMIOS_H
 
84
/* for HP-UX (some versions) the extern C is needed, and for other
 
85
   platforms it doesn't hurt */
 
86
extern "C" {
 
87
# include <termios.h>
 
88
}
 
89
#endif
 
90
 
 
91
#if !defined(__osf__)
 
92
# ifdef HAVE_TERMIO_H
 
93
/* needed at least on AIX */
 
94
#  include <termio.h>
 
95
# endif
 
96
#endif
 
97
 
 
98
#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__bsdi__) || defined(__APPLE__) || defined (__DragonFly__)
 
99
# define _tcgetattr(fd, ttmode) ioctl(fd, TIOCGETA, (char *)ttmode)
 
100
#else
 
101
# if defined(_HPUX_SOURCE) || defined(__Lynx__) || defined (__CYGWIN__)
 
102
#  define _tcgetattr(fd, ttmode) tcgetattr(fd, ttmode)
 
103
# else
 
104
#  define _tcgetattr(fd, ttmode) ioctl(fd, TCGETS, (char *)ttmode)
 
105
# endif
 
106
#endif
 
107
 
 
108
#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__bsdi__) || defined(__APPLE__) || defined (__DragonFly__)
 
109
# define _tcsetattr(fd, ttmode) ioctl(fd, TIOCSETA, (char *)ttmode)
 
110
#else
 
111
# if defined(_HPUX_SOURCE) || defined(__CYGWIN__)
 
112
#  define _tcsetattr(fd, ttmode) tcsetattr(fd, TCSANOW, ttmode) 
 
113
# else
 
114
#  define _tcsetattr(fd, ttmode) ioctl(fd, TCSETS, (char *)ttmode)
 
115
# endif
 
116
#endif
 
117
 
 
118
#if defined (_HPUX_SOURCE)
 
119
# define _TERMIOS_INCLUDED
 
120
# include <bsdtty.h>
 
121
#endif
 
122
 
 
123
#if defined(HAVE_PTY_H)
 
124
# include <pty.h>
 
125
#endif
 
126
 
 
127
#include <kdebug.h>
 
128
#include <kstandarddirs.h>      // locate
 
129
 
 
130
#ifndef CINTR
 
131
#define CINTR   0x03
 
132
#endif
 
133
#ifndef CQUIT
 
134
#define CQUIT   0x1c
 
135
#endif
 
136
#ifndef CERASE
 
137
#define CERASE  0x7f
 
138
#endif
 
139
 
 
140
#define TTY_GROUP "tty"
 
141
 
 
142
///////////////////////
 
143
// private functions //
 
144
///////////////////////
 
145
 
 
146
#ifdef HAVE_UTEMPTER
 
147
class KProcess_Utmp : public KProcess
 
148
{
 
149
public:
 
150
   int commSetupDoneC()
 
151
   {
 
152
     dup2(cmdFd, 0);
 
153
     dup2(cmdFd, 1);
 
154
     dup2(cmdFd, 3);
 
155
     return 1;
 
156
   }
 
157
   int cmdFd;
 
158
};
 
159
#endif
 
160
 
 
161
#define BASE_CHOWN "kgrantpty"
 
162
 
 
163
 
 
164
 
 
165
//////////////////
 
166
// private data //
 
167
//////////////////
 
168
 
 
169
struct KPtyPrivate {
 
170
   KPtyPrivate() :
 
171
     xonXoff(false),
 
172
     utf8(false),
 
173
     masterFd(-1), slaveFd(-1)
 
174
   {
 
175
     memset(&winSize, 0, sizeof(winSize));
 
176
     winSize.ws_row = 24;
 
177
     winSize.ws_col = 80;
 
178
   }
 
179
 
 
180
   bool xonXoff : 1;
 
181
   bool utf8    : 1;
 
182
   int masterFd;
 
183
   int slaveFd;
 
184
   struct winsize winSize;
 
185
 
 
186
   QCString ttyName;
 
187
};
 
188
 
 
189
/////////////////////////////
 
190
// public member functions //
 
191
/////////////////////////////
 
192
 
 
193
KPty::KPty()
 
194
{
 
195
  d = new KPtyPrivate;
 
196
}
 
197
 
 
198
KPty::~KPty()
 
199
{
 
200
  close();
 
201
  delete d;
 
202
}
 
203
 
 
204
bool KPty::open()
 
205
{
 
206
  if (d->masterFd >= 0)
 
207
    return true;
 
208
 
 
209
  QCString ptyName;
 
210
 
 
211
  // Find a master pty that we can open ////////////////////////////////
 
212
 
 
213
  // Because not all the pty animals are created equal, they want to
 
214
  // be opened by several different methods.
 
215
 
 
216
  // We try, as we know them, one by one.
 
217
 
 
218
#if defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT)
 
219
#ifdef _AIX
 
220
  d->masterFd = ::open("/dev/ptc",O_RDWR);
 
221
#else
 
222
  d->masterFd = ::open("/dev/ptmx",O_RDWR);
 
223
#endif
 
224
  if (d->masterFd >= 0)
 
225
  {
 
226
    char *ptsn = ptsname(d->masterFd);
 
227
    if (ptsn) {
 
228
        grantpt(d->masterFd);
 
229
        d->ttyName = ptsn;
 
230
        goto gotpty;
 
231
    } else {
 
232
       ::close(d->masterFd);
 
233
       d->masterFd = -1;
 
234
    }
 
235
  }
 
236
#endif
 
237
 
 
238
  // Linux device names, FIXME: Trouble on other systems?
 
239
  for (const char* s3 = "pqrstuvwxyzabcdefghijklmno"; *s3; s3++)
 
240
  {
 
241
    for (const char* s4 = "0123456789abcdefghijklmnopqrstuvwxyz"; *s4; s4++)
 
242
    {
 
243
      ptyName.sprintf("/dev/pty%c%c", *s3, *s4);
 
244
      d->ttyName.sprintf("/dev/tty%c%c", *s3, *s4);
 
245
 
 
246
      d->masterFd = ::open(ptyName.data(), O_RDWR);
 
247
      if (d->masterFd >= 0)
 
248
      {
 
249
#ifdef __sun
 
250
        /* Need to check the process group of the pty.
 
251
         * If it exists, then the slave pty is in use,
 
252
         * and we need to get another one.
 
253
         */
 
254
        int pgrp_rtn;
 
255
        if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) {
 
256
          ::close(d->masterFd);
 
257
          d->masterFd = -1;
 
258
          continue;
 
259
        }
 
260
#endif /* sun */
 
261
        if (!access(d->ttyName.data(),R_OK|W_OK)) // checks availability based on permission bits
 
262
        {
 
263
          if (!geteuid())
 
264
          {
 
265
            struct group* p = getgrnam(TTY_GROUP);
 
266
            if (!p)
 
267
              p = getgrnam("wheel");
 
268
            gid_t gid = p ? p->gr_gid : getgid ();
 
269
 
 
270
            chown(d->ttyName.data(), getuid(), gid);
 
271
            chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
 
272
          }
 
273
          goto gotpty;
 
274
        }
 
275
        ::close(d->masterFd);
 
276
        d->masterFd = -1;
 
277
      }
 
278
    }
 
279
  }
 
280
 
 
281
  kdWarning(175) << "Can't open a pseudo teletype" << endl;
 
282
  return false;
 
283
 
 
284
 gotpty:
 
285
  struct stat st;
 
286
  if (stat(d->ttyName.data(), &st))
 
287
    return false; // this just cannot happen ... *cough*  Yeah right, I just
 
288
                  // had it happen when pty #349 was allocated.  I guess
 
289
                  // there was some sort of leak?  I only had a few open.
 
290
  if (((st.st_uid != getuid()) ||
 
291
       (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&
 
292
      !chownpty(true))
 
293
  {
 
294
    kdWarning(175)
 
295
      << "chownpty failed for device " << ptyName << "::" << d->ttyName
 
296
      << "\nThis means the communication can be eavesdropped." << endl;
 
297
  }
 
298
 
 
299
#ifdef BSD
 
300
  revoke(d->ttyName.data());
 
301
#endif
 
302
 
 
303
#ifdef HAVE_UNLOCKPT
 
304
  unlockpt(d->masterFd);
 
305
#endif
 
306
 
 
307
  d->slaveFd = ::open(d->ttyName.data(), O_RDWR | O_NOCTTY);
 
308
  if (d->slaveFd < 0)
 
309
  {
 
310
    kdWarning(175) << "Can't open slave pseudo teletype" << endl;
 
311
    ::close(d->masterFd);
 
312
    d->masterFd = -1;
 
313
    return false;
 
314
  }
 
315
 
 
316
#if (defined(__svr4__) || defined(__sgi__))
 
317
  // Solaris
 
318
  ioctl(d->slaveFd, I_PUSH, "ptem");
 
319
  ioctl(d->slaveFd, I_PUSH, "ldterm");
 
320
#endif
 
321
 
 
322
    // set xon/xoff & control keystrokes
 
323
  // without the '::' some version of HP-UX thinks, this declares
 
324
  // the struct in this class, in this method, and fails to find
 
325
  // the correct tc[gs]etattr
 
326
  struct ::termios ttmode;
 
327
 
 
328
  _tcgetattr(d->slaveFd, &ttmode);
 
329
 
 
330
  if (!d->xonXoff)
 
331
    ttmode.c_iflag &= ~(IXOFF | IXON);
 
332
  else
 
333
    ttmode.c_iflag |= (IXOFF | IXON);
 
334
 
 
335
#ifdef IUTF8
 
336
  if (!d->utf8)
 
337
    ttmode.c_iflag &= ~IUTF8;
 
338
  else
 
339
    ttmode.c_iflag |= IUTF8;
 
340
#endif
 
341
 
 
342
  ttmode.c_cc[VINTR] = CINTR;
 
343
  ttmode.c_cc[VQUIT] = CQUIT;
 
344
  ttmode.c_cc[VERASE] = CERASE;
 
345
 
 
346
  _tcsetattr(d->slaveFd, &ttmode);
 
347
 
 
348
  // set screen size
 
349
  ioctl(d->slaveFd, TIOCSWINSZ, (char *)&d->winSize);
 
350
 
 
351
  fcntl(d->masterFd, F_SETFD, FD_CLOEXEC);
 
352
  fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC);
 
353
 
 
354
  return true;
 
355
}
 
356
 
 
357
void KPty::close()
 
358
{
 
359
   if (d->masterFd < 0)
 
360
      return;
 
361
   // don't bother resetting unix98 pty, it will go away after closing master anyway.
 
362
   if (memcmp(d->ttyName.data(), "/dev/pts/", 9)) {
 
363
      if (!geteuid()) {
 
364
         struct stat st;
 
365
         if (!stat(d->ttyName.data(), &st)) {
 
366
            chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1);
 
367
            chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
 
368
         }
 
369
      } else {
 
370
         fcntl(d->masterFd, F_SETFD, 0);
 
371
         chownpty(false);
 
372
      }
 
373
   }
 
374
   ::close(d->slaveFd);
 
375
   ::close(d->masterFd);
 
376
   d->masterFd = d->slaveFd = -1;
 
377
}
 
378
 
 
379
void KPty::setCTty()
 
380
{
 
381
    // Setup job control //////////////////////////////////
 
382
 
 
383
    // Become session leader, process group leader,
 
384
    // and get rid of the old controlling terminal.
 
385
    setsid();
 
386
 
 
387
    // make our slave pty the new controlling terminal.
 
388
#ifdef TIOCSCTTY
 
389
    ioctl(d->slaveFd, TIOCSCTTY, 0);
 
390
#else
 
391
    // SVR4 hack: the first tty opened after setsid() becomes controlling tty
 
392
    ::close(::open(d->ttyName, O_WRONLY, 0));
 
393
#endif
 
394
 
 
395
    // make our new process group the foreground group on the pty
 
396
    int pgrp = getpid();
 
397
#if defined(_POSIX_VERSION) || defined(__svr4__)
 
398
    tcsetpgrp (d->slaveFd, pgrp);
 
399
#elif defined(TIOCSPGRP)
 
400
    ioctl(d->slaveFd, TIOCSPGRP, (char *)&pgrp);
 
401
#endif
 
402
}
 
403
 
 
404
void KPty::login(const char *user, const char *remotehost)
 
405
{
 
406
#ifdef HAVE_UTEMPTER
 
407
    KProcess_Utmp utmp;
 
408
    utmp.cmdFd = d->masterFd;
 
409
    utmp << "/usr/sbin/utempter" << "-a" << d->ttyName << "";
 
410
    utmp.start(KProcess::Block);
 
411
    Q_UNUSED(user);
 
412
    Q_UNUSED(remotehost);
 
413
#elif defined(USE_LOGIN)
 
414
    const char *str_ptr;
 
415
    struct utmp l_struct;
 
416
    memset(&l_struct, 0, sizeof(struct utmp));
 
417
    // note: strncpy without terminators _is_ correct here. man 4 utmp
 
418
 
 
419
    if (user)
 
420
      strncpy(l_struct.ut_name, user, UT_NAMESIZE);
 
421
 
 
422
    if (remotehost)
 
423
      strncpy(l_struct.ut_host, remotehost, UT_HOSTSIZE);
 
424
 
 
425
# ifndef __GLIBC__
 
426
    str_ptr = d->ttyName.data();
 
427
    if (!memcmp(str_ptr, "/dev/", 5))
 
428
        str_ptr += 5;
 
429
    strncpy(l_struct.ut_line, str_ptr, UT_LINESIZE);
 
430
# endif
 
431
 
 
432
    // Handle 64-bit time_t properly, where it may be larger
 
433
    // than the integral type of ut_time.
 
434
    {
 
435
        time_t ut_time_temp;
 
436
        time(&ut_time_temp);
 
437
        l_struct.ut_time=ut_time_temp;
 
438
    }
 
439
 
 
440
    ::login(&l_struct);
 
441
#else
 
442
    Q_UNUSED(user);
 
443
    Q_UNUSED(remotehost);
 
444
#endif
 
445
}
 
446
 
 
447
void KPty::logout()
 
448
{
 
449
#ifdef HAVE_UTEMPTER
 
450
    KProcess_Utmp utmp;
 
451
    utmp.cmdFd = d->masterFd;
 
452
    utmp << "/usr/sbin/utempter" << "-d" << d->ttyName;
 
453
    utmp.start(KProcess::Block);
 
454
#elif defined(USE_LOGIN)
 
455
    const char *str_ptr = d->ttyName.data();
 
456
    if (!memcmp(str_ptr, "/dev/", 5))
 
457
        str_ptr += 5;
 
458
# ifdef __GLIBC__
 
459
    else {
 
460
        const char *sl_ptr = strrchr(str_ptr, '/');
 
461
        if (sl_ptr)
 
462
            str_ptr = sl_ptr + 1;
 
463
    }
 
464
# endif
 
465
    ::logout(str_ptr);
 
466
#endif
 
467
}
 
468
 
 
469
void KPty::setWinSize(int lines, int columns)
 
470
{
 
471
  d->winSize.ws_row = (unsigned short)lines;
 
472
  d->winSize.ws_col = (unsigned short)columns;
 
473
  if (d->masterFd >= 0)
 
474
    ioctl( d->masterFd, TIOCSWINSZ, (char *)&d->winSize );
 
475
}
 
476
 
 
477
void KPty::setXonXoff(bool useXonXoff)
 
478
{
 
479
  d->xonXoff = useXonXoff;
 
480
  if (d->masterFd >= 0) {
 
481
    // without the '::' some version of HP-UX thinks, this declares
 
482
    // the struct in this class, in this method, and fails to find
 
483
    // the correct tc[gs]etattr
 
484
    struct ::termios ttmode;
 
485
 
 
486
    _tcgetattr(d->masterFd, &ttmode);
 
487
 
 
488
    if (!useXonXoff)
 
489
      ttmode.c_iflag &= ~(IXOFF | IXON);
 
490
    else
 
491
      ttmode.c_iflag |= (IXOFF | IXON);
 
492
 
 
493
    _tcsetattr(d->masterFd, &ttmode);
 
494
  }
 
495
}
 
496
 
 
497
void KPty::setUtf8Mode(bool useUtf8)
 
498
{
 
499
  d->utf8 = useUtf8;
 
500
#ifdef IUTF8
 
501
  if (d->masterFd >= 0) {
 
502
    // without the '::' some version of HP-UX thinks, this declares
 
503
    // the struct in this class, in this method, and fails to find
 
504
    // the correct tc[gs]etattr
 
505
    struct ::termios ttmode;
 
506
 
 
507
    _tcgetattr(d->masterFd, &ttmode);
 
508
 
 
509
    if (!useUtf8)
 
510
      ttmode.c_iflag &= ~IUTF8;
 
511
    else
 
512
      ttmode.c_iflag |= IUTF8;
 
513
 
 
514
    _tcsetattr(d->masterFd, &ttmode);
 
515
  }
 
516
#endif
 
517
}
 
518
 
 
519
const char *KPty::ttyName() const
 
520
{
 
521
    return d->ttyName.data();
 
522
}
 
523
 
 
524
int KPty::masterFd() const
 
525
{
 
526
    return d->masterFd;
 
527
}
 
528
 
 
529
int KPty::slaveFd() const
 
530
{
 
531
    return d->slaveFd;
 
532
}
 
533
 
 
534
// private
 
535
bool KPty::chownpty(bool grant)
 
536
{
 
537
  KProcess proc;
 
538
  proc << locate("exe", BASE_CHOWN) << (grant?"--grant":"--revoke") << QString::number(d->masterFd);
 
539
  return proc.start(KProcess::Block) && proc.normalExit() && !proc.exitStatus();
 
540
}
 
541