summaryrefslogtreecommitdiffstats
path: root/kinit/start_tdeinit_wrapper.c
blob: 0328f3e4367db3ee803649d4b9bd6f2ba48e0a29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
 * This file is part of the KDE libraries
 * Copyright (c) 2007 Lubos Lunak <[email protected]>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License version 2 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <config.h>

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#ifdef TDEINIT_OOM_PROTECT

/*
 The start_tdeinit wrapper is setuid, which means some shell variables like LD_LIBRARY_PATH
 get unset before it's launched. However tdeinit is used to launch most of KDE, so such variables
 should not be dropped. Therefore this wrapper for the setuid wrapper read the environment
 and writes it to start_tdeinit's stdin, which after dropping priviledges reads it and uses it
 for launching the real tdeinit.
*/
int main(int argc, char **argv)
{
   int pipes[ 2 ];
   if(argc == 0)
      return 1;
   if( pipe( pipes ) < 0 ) {
      perror( "pipe()" );
      return 1;
   }
   switch( fork()) {
      case -1:
         perror( "fork()" );
         return 1;
      default: /* parent, exec */ 
         close( pipes[ 1 ] );
         close( 0 ); /* stdin */
         dup2( pipes[ 0 ], 0 );
         close( pipes[ 0 ] );
         argv[ 0 ] = (char*)"start_tdeinit";
         execvp("start_tdeinit", argv);
         perror("start_tdeinit");
         return 1;
      case 0: { /* child, pass env and exit */
         extern char** environ;
         int i;
         close( pipes[ 0 ] );
         write( pipes[ 1 ], "environ", 7 ); /* header, just in case */
         for( i = 0;
              environ[ i ] != NULL;
              ++i )
             {}
         write( pipes[ 1 ], &i, sizeof( int )); /* write count */
         for( i = 0;
              environ[ i ] != NULL;
              ++i )
             {
             int len = strlen( environ[ i ] );
             write( pipes[ 1 ], &len, sizeof( int )); /* write length */
             write( pipes[ 1 ], environ[ i ], strlen( environ[ i ] ));
             }
         close( pipes[ 1 ] );
         }     
   }
   return 0;
}

#else /* not Linux, the simple non-setuid case */

int main(int argc, char **argv)
{
   if(argc == 0)
      return 1;
   argv[0] = "start_tdeinit";
   execvp("start_tdeinit",argv);
   perror("start_tdeinit");
   return 1;
}
#endif