~ubuntu-branches/ubuntu/raring/consolekit/raring

« back to all changes in this revision

Viewing changes to .pc/99-kfreebsd-empty-env.patch/src/ck-sysdeps-freebsd.c

  • Committer: Package Import Robot
  • Author(s): Christoph Egger
  • Date: 2012-07-30 13:57:55 UTC
  • mfrom: (0.1.21 sid)
  • Revision ID: package-import@ubuntu.com-20120730135755-1o3bx2e8gq4bbeio
Tags: 0.4.5-3.1
* Non-maintainer upload.
* Include patch by Petr Salinger to ignore empty environments (Closes: #570015)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
 
4
 * Copyright (C) 2007 Joe Marcus Clarke <marcus@FreeBSD.org>
 
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
19
 *
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include <stdlib.h>
 
25
#include <stdio.h>
 
26
#include <fcntl.h>
 
27
#include <unistd.h>
 
28
#include <string.h>
 
29
#include <errno.h>
 
30
#include <paths.h>
 
31
#include <ttyent.h>
 
32
#include <kvm.h>
 
33
#include <sys/param.h>
 
34
#include <sys/types.h>
 
35
#include <sys/stat.h>
 
36
#include <sys/sysctl.h>
 
37
#include <sys/user.h>
 
38
#include <sys/ioctl.h>
 
39
 
 
40
#include <sys/consio.h>
 
41
 
 
42
#define DEV_ENCODE(M,m) ( \
 
43
  ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \
 
44
)
 
45
 
 
46
#include "ck-sysdeps.h"
 
47
 
 
48
#ifndef ERROR
 
49
#define ERROR -1
 
50
#endif
 
51
 
 
52
/* adapted from procps */
 
53
struct _CkProcessStat
 
54
{
 
55
        int pid;
 
56
        int ppid;                       /* stat,status     pid of parent process */
 
57
        char state;                     /* stat,status     single-char code for process state (S=sleeping) */
 
58
        char cmd[16];                   /* stat,status     basename of executable file in call to exec(2) */
 
59
        unsigned long long utime;       /* stat            user-mode CPU time accumulated by process */
 
60
        unsigned long long stime;       /* stat            kernel-mode CPU time accumulated by process */
 
61
        unsigned long long cutime;      /* stat            cumulative utime of process and reaped children */
 
62
        unsigned long long cstime;      /* stat            cumulative stime of process and reaped children */
 
63
        unsigned long long start_time;  /* stat            start time of process -- seconds since 1-1-70 */
 
64
        unsigned long start_code;       /* stat            address of beginning of code segment */
 
65
        unsigned long end_code;         /* stat            address of end of code segment */
 
66
        unsigned long start_stack;      /* stat            address of the bottom of stack for the process */
 
67
        unsigned long kstk_esp;         /* stat            kernel stack pointer */
 
68
        unsigned long kstk_eip;         /* stat            kernel instruction pointer */
 
69
        unsigned long wchan;            /* stat (special)  address of kernel wait channel proc is sleeping in */
 
70
        long priority;                  /* stat            kernel scheduling priority */
 
71
        long nice;                      /* stat            standard unix nice level of process */
 
72
        long rss;                       /* stat            resident set size from /proc/#/stat (pages) */
 
73
        long alarm;                     /* stat            ? */
 
74
        unsigned long rtprio;           /* stat            real-time priority */
 
75
        unsigned long sched;            /* stat            scheduling class */
 
76
        unsigned long vsize;            /* stat            number of pages of virtual memory ... */
 
77
        unsigned long rss_rlim;         /* stat            resident set size limit? */
 
78
        unsigned long flags;            /* stat            kernel flags for the process */
 
79
        unsigned long min_flt;          /* stat            number of minor page faults since process start */
 
80
        unsigned long maj_flt;          /* stat            number of major page faults since process start */
 
81
        unsigned long cmin_flt;         /* stat            cumulative min_flt of process and child processes */
 
82
        unsigned long cmaj_flt;         /* stat            cumulative maj_flt of process and child processes */
 
83
        int     pgrp;                   /* stat            process group id */
 
84
        int session;                    /* stat            session id */
 
85
        int nlwp;                       /* stat    number of threads, or 0 if no clue */
 
86
        int tty;                        /* stat            full device number of controlling terminal */
 
87
        int tpgid;                      /* stat            terminal process group id */
 
88
        int exit_signal;                /* stat            might not be SIGCHLD */
 
89
        int processor;                  /* stat            current (or most recent?) CPU */
 
90
        uintptr_t penv;                 /* stat            address of initial environment vector */
 
91
        char tty_text[16];              /* stat            device name */
 
92
 
 
93
};
 
94
 
 
95
pid_t
 
96
ck_process_stat_get_ppid (CkProcessStat *stat)
 
97
{
 
98
        g_return_val_if_fail (stat != NULL, -1);
 
99
 
 
100
        return stat->ppid;
 
101
}
 
102
 
 
103
char *
 
104
ck_process_stat_get_cmd (CkProcessStat *stat)
 
105
{
 
106
        g_return_val_if_fail (stat != NULL, NULL);
 
107
 
 
108
        return g_strdup (stat->cmd);
 
109
}
 
110
 
 
111
char *
 
112
ck_process_stat_get_tty (CkProcessStat *stat)
 
113
{
 
114
        g_return_val_if_fail (stat != NULL, NULL);
 
115
 
 
116
        return g_strdup (stat->tty_text);
 
117
}
 
118
 
 
119
static gboolean
 
120
get_kinfo_proc (pid_t pid,
 
121
                struct kinfo_proc *p)
 
122
{
 
123
        int    mib[4];
 
124
        size_t len;
 
125
 
 
126
        len = 4;
 
127
        sysctlnametomib ("kern.proc.pid", mib, &len);
 
128
 
 
129
        len = sizeof(struct kinfo_proc);
 
130
        mib[3] = pid;
 
131
 
 
132
        if (sysctl (mib, 4, p, &len, NULL, 0) == -1) {
 
133
                return FALSE;
 
134
        }
 
135
 
 
136
        return TRUE;
 
137
}
 
138
 
 
139
/* return 1 if it works, or 0 for failure */
 
140
static gboolean
 
141
stat2proc (pid_t        pid,
 
142
           CkProcessStat *P)
 
143
{
 
144
        struct kinfo_proc p;
 
145
        char              *ttname;
 
146
        int               num;
 
147
        int               tty_maj;
 
148
        int               tty_min;
 
149
 
 
150
        if (! get_kinfo_proc (pid, &p)) {
 
151
                return FALSE;
 
152
        }
 
153
 
 
154
        num = OCOMMLEN;
 
155
        if (num >= sizeof P->cmd) {
 
156
                num = sizeof P->cmd - 1;
 
157
        }
 
158
 
 
159
        memcpy (P->cmd, p.ki_ocomm, num);
 
160
 
 
161
        P->cmd[num]   = '\0';
 
162
        P->pid        = p.ki_pid;
 
163
        P->ppid       = p.ki_ppid;
 
164
        P->pgrp       = p.ki_pgid;
 
165
        P->session    = p.ki_sid;
 
166
        P->rss        = p.ki_rssize;
 
167
        P->vsize      = p.ki_size;
 
168
        P->start_time = p.ki_start.tv_sec;
 
169
        P->wchan      = (unsigned long) p.ki_wchan;
 
170
        P->state      = p.ki_stat;
 
171
        P->nice       = p.ki_nice;
 
172
        P->flags      = p.ki_sflag;
 
173
        P->tpgid      = p.ki_tpgid;
 
174
        P->processor  = p.ki_oncpu;
 
175
        P->nlwp       = p.ki_numthreads;
 
176
 
 
177
        /* we like it Linux-encoded :-) */
 
178
        tty_maj = major (p.ki_tdev);
 
179
        tty_min = minor (p.ki_tdev);
 
180
        P->tty = DEV_ENCODE (tty_maj,tty_min);
 
181
 
 
182
        snprintf (P->tty_text, sizeof P->tty_text, "%3d,%-3d", tty_maj, tty_min);
 
183
 
 
184
        if (p.ki_tdev != NODEV && (ttname = devname (p.ki_tdev, S_IFCHR)) != NULL) {
 
185
                memcpy (P->tty_text, ttname, sizeof P->tty_text);
 
186
        }
 
187
 
 
188
        if (p.ki_tdev == NODEV) {
 
189
                memcpy (P->tty_text, "   ?   ", sizeof P->tty_text);
 
190
        }
 
191
 
 
192
        if (P->pid != pid) {
 
193
                return FALSE;
 
194
        }
 
195
 
 
196
        return TRUE;
 
197
}
 
198
 
 
199
gboolean
 
200
ck_process_stat_new_for_unix_pid (pid_t           pid,
 
201
                                  CkProcessStat **stat,
 
202
                                  GError        **error)
 
203
{
 
204
        gboolean       res;
 
205
        GError        *local_error;
 
206
        CkProcessStat *proc;
 
207
 
 
208
        g_return_val_if_fail (pid > 1, FALSE);
 
209
 
 
210
        if (stat == NULL) {
 
211
                return FALSE;
 
212
        }
 
213
 
 
214
        proc = g_new0 (CkProcessStat, 1);
 
215
        proc->pid = pid;
 
216
        res = stat2proc (pid, proc);
 
217
        if (res) {
 
218
                *stat = proc;
 
219
        } else {
 
220
                g_propagate_error (error, local_error);
 
221
                *stat = NULL;
 
222
        }
 
223
 
 
224
        return res;
 
225
}
 
226
 
 
227
void
 
228
ck_process_stat_free (CkProcessStat *stat)
 
229
{
 
230
        g_free (stat);
 
231
}
 
232
 
 
233
GHashTable *
 
234
ck_unix_pid_get_env_hash (pid_t pid)
 
235
{
 
236
        GHashTable       *hash;
 
237
        char            **penv;
 
238
        kvm_t            *kd;
 
239
        struct kinfo_proc p;
 
240
        int               i;
 
241
 
 
242
        kd = kvm_openfiles (_PATH_DEVNULL, _PATH_DEVNULL, NULL, O_RDONLY, NULL);
 
243
        if (kd == NULL) {
 
244
                return NULL;
 
245
        }
 
246
 
 
247
        if (! get_kinfo_proc (pid, &p)) {
 
248
                return NULL;
 
249
        }
 
250
 
 
251
        penv = kvm_getenvv (kd, &p, 0);
 
252
        if (penv == NULL) {
 
253
                return NULL;
 
254
        }
 
255
 
 
256
        hash = g_hash_table_new_full (g_str_hash,
 
257
                                      g_str_equal,
 
258
                                      g_free,
 
259
                                      g_free);
 
260
 
 
261
        for (i = 0; penv[i] != NULL; i++) {
 
262
                char **vals;
 
263
 
 
264
                vals = g_strsplit (penv[i], "=", 2);
 
265
                if (vals != NULL) {
 
266
                        g_hash_table_insert (hash,
 
267
                                             g_strdup (vals[0]),
 
268
                                             g_strdup (vals[1]));
 
269
                        g_strfreev (vals);
 
270
                }
 
271
        }
 
272
 
 
273
        kvm_close (kd);
 
274
 
 
275
        return hash;
 
276
}
 
277
 
 
278
char *
 
279
ck_unix_pid_get_env (pid_t       pid,
 
280
                     const char *var)
 
281
{
 
282
        GHashTable *hash;
 
283
        char       *val;
 
284
 
 
285
        /*
 
286
         * Would probably be more efficient to just loop through the
 
287
         * environment and return the value, avoiding building the hash
 
288
         * table, but this works for now.
 
289
         */
 
290
        hash = ck_unix_pid_get_env_hash (pid);
 
291
        val  = g_strdup (g_hash_table_lookup (hash, var));
 
292
        g_hash_table_destroy (hash);
 
293
 
 
294
        return val;
 
295
}
 
296
 
 
297
uid_t
 
298
ck_unix_pid_get_uid (pid_t pid)
 
299
{
 
300
        uid_t             uid;
 
301
        gboolean          res;
 
302
        struct kinfo_proc p;
 
303
 
 
304
        g_return_val_if_fail (pid > 1, 0);
 
305
 
 
306
        uid = -1;
 
307
 
 
308
        res = get_kinfo_proc (pid, &p);
 
309
 
 
310
        if (res) {
 
311
                uid = p.ki_uid;
 
312
        }
 
313
 
 
314
        return uid;
 
315
}
 
316
 
 
317
gboolean
 
318
ck_unix_pid_get_login_session_id (pid_t  pid,
 
319
                                  char **idp)
 
320
{
 
321
        g_return_val_if_fail (pid > 1, FALSE);
 
322
 
 
323
        return FALSE;
 
324
}
 
325
 
 
326
gboolean
 
327
ck_get_max_num_consoles (guint *num)
 
328
{
 
329
        int      max_consoles;
 
330
        int      res;
 
331
        gboolean ret;
 
332
        struct ttyent *t;
 
333
 
 
334
        ret = FALSE;
 
335
        max_consoles = 0;
 
336
 
 
337
        res = setttyent ();
 
338
        if (res == 0) {
 
339
                goto done;
 
340
        }
 
341
 
 
342
        while ((t = getttyent ()) != NULL) {
 
343
                if (t->ty_status & TTY_ON && strncmp (t->ty_name, "ttyv", 4) == 0)
 
344
                        max_consoles++;
 
345
        }
 
346
 
 
347
        /* Increment one more so that all consoles are properly counted
 
348
         * this is arguable a bug in vt_add_watches().
 
349
         */
 
350
        max_consoles++;
 
351
 
 
352
        ret = TRUE;
 
353
 
 
354
        endttyent ();
 
355
 
 
356
done:
 
357
        if (num != NULL) {
 
358
                *num = max_consoles;
 
359
        }
 
360
 
 
361
        return ret;
 
362
}
 
363
 
 
364
gboolean
 
365
ck_supports_activatable_consoles (void)
 
366
{
 
367
        return TRUE;
 
368
}
 
369
 
 
370
char *
 
371
ck_get_console_device_for_num (guint num)
 
372
{
 
373
        char *device;
 
374
 
 
375
        /* The device number is always one less than the VT number. */
 
376
        num--;
 
377
 
 
378
        device = g_strdup_printf ("/dev/ttyv%u", num);
 
379
 
 
380
        return device;
 
381
}
 
382
 
 
383
gboolean
 
384
ck_get_console_num_from_device (const char *device,
 
385
                                guint      *num)
 
386
{
 
387
        guint    n;
 
388
        gboolean ret;
 
389
 
 
390
        n = 0;
 
391
        ret = FALSE;
 
392
 
 
393
        if (device == NULL) {
 
394
                return FALSE;
 
395
        }
 
396
 
 
397
        if (sscanf (device, "/dev/ttyv%u", &n) == 1) {
 
398
                /* The VT number is always one more than the device number. */
 
399
                n++;
 
400
                ret = TRUE;
 
401
        }
 
402
 
 
403
        if (num != NULL) {
 
404
                *num = n;
 
405
        }
 
406
 
 
407
        return ret;
 
408
}
 
409
 
 
410
gboolean
 
411
ck_get_active_console_num (int    console_fd,
 
412
                           guint *num)
 
413
{
 
414
        gboolean ret;
 
415
        int      res;
 
416
        int      active;
 
417
 
 
418
        g_assert (console_fd != -1);
 
419
 
 
420
        active = 0;
 
421
        ret = FALSE;
 
422
 
 
423
        res = ioctl (console_fd, VT_GETACTIVE, &active);
 
424
        if (res == ERROR) {
 
425
                perror ("ioctl VT_GETACTIVE");
 
426
                goto out;
 
427
        }
 
428
 
 
429
        g_debug ("Active VT is: %d (ttyv%d)", active, active - 1);
 
430
        ret = TRUE;
 
431
 
 
432
 out:
 
433
        if (num != NULL) {
 
434
                *num = active;
 
435
        }
 
436
 
 
437
        return ret;
 
438
}