1 /*
2  * Copyright (c) 1997  Metro Link Incorporated
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  *
22  * Except as contained in this notice, the name of the Metro Link shall not be
23  * used in advertising or otherwise to promote the sale, use or other dealings
24  * in this Software without prior written authorization from Metro Link.
25  *
26  */
27 /*
28  * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
29  *
30  * Permission is hereby granted, free of charge, to any person obtaining a
31  * copy of this software and associated documentation files (the "Software"),
32  * to deal in the Software without restriction, including without limitation
33  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
34  * and/or sell copies of the Software, and to permit persons to whom the
35  * Software is furnished to do so, subject to the following conditions:
36  *
37  * The above copyright notice and this permission notice shall be included in
38  * all copies or substantial portions of the Software.
39  *
40  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
43  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
44  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
45  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
46  * OTHER DEALINGS IN THE SOFTWARE.
47  *
48  * Except as contained in this notice, the name of the copyright holder(s)
49  * and author(s) shall not be used in advertising or otherwise to promote
50  * the sale, use or other dealings in this Software without prior written
51  * authorization from the copyright holder(s) and author(s).
52  */
53 
54 #ifdef HAVE_XORG_CONFIG_H
55 #include <xorg-config.h>
56 #endif
57 
58 #include "os.h"
59 #include "xf86Parser.h"
60 #include "xf86tokens.h"
61 #include "Configint.h"
62 
63 #include <unistd.h>
64 #include <sys/types.h>
65 #include <sys/wait.h>
66 #include <errno.h>
67 
68 #if defined(HAVE_SETEUID) && defined(_POSIX_SAVED_IDS) && _POSIX_SAVED_IDS > 0
69 #define HAS_SAVED_IDS_AND_SETEUID
70 #endif
71 #if defined(WIN32)
72 #define HAS_NO_UIDS
73 #endif
74 
75 static int
doWriteConfigFile(const char * filename,XF86ConfigPtr cptr)76 doWriteConfigFile(const char *filename, XF86ConfigPtr cptr)
77 {
78     FILE *cf;
79 
80     if ((cf = fopen(filename, "w")) == NULL) {
81         return 0;
82     }
83 
84     if (cptr->conf_comment)
85         fprintf(cf, "%s\n", cptr->conf_comment);
86 
87     xf86printLayoutSection(cf, cptr->conf_layout_lst);
88 
89     if (cptr->conf_files != NULL) {
90         fprintf(cf, "Section \"Files\"\n");
91         xf86printFileSection(cf, cptr->conf_files);
92         fprintf(cf, "EndSection\n\n");
93     }
94 
95     if (cptr->conf_modules != NULL) {
96         fprintf(cf, "Section \"Module\"\n");
97         xf86printModuleSection(cf, cptr->conf_modules);
98         fprintf(cf, "EndSection\n\n");
99     }
100 
101     xf86printVendorSection(cf, cptr->conf_vendor_lst);
102 
103     xf86printServerFlagsSection(cf, cptr->conf_flags);
104 
105     xf86printInputSection(cf, cptr->conf_input_lst);
106 
107     xf86printInputClassSection(cf, cptr->conf_inputclass_lst);
108 
109     xf86printOutputClassSection(cf, cptr->conf_outputclass_lst);
110 
111     xf86printVideoAdaptorSection(cf, cptr->conf_videoadaptor_lst);
112 
113     xf86printModesSection(cf, cptr->conf_modes_lst);
114 
115     xf86printMonitorSection(cf, cptr->conf_monitor_lst);
116 
117     xf86printDeviceSection(cf, cptr->conf_device_lst);
118 
119     xf86printScreenSection(cf, cptr->conf_screen_lst);
120 
121     xf86printDRISection(cf, cptr->conf_dri);
122 
123     xf86printExtensionsSection(cf, cptr->conf_extensions);
124 
125     fclose(cf);
126     return 1;
127 }
128 
129 int
xf86writeConfigFile(const char * filename,XF86ConfigPtr cptr)130 xf86writeConfigFile(const char *filename, XF86ConfigPtr cptr)
131 {
132 #ifndef HAS_NO_UIDS
133     int ret;
134 
135     if (getuid() != geteuid()) {
136 
137 #if !defined(HAS_SAVED_IDS_AND_SETEUID)
138         int pid, p;
139         int status;
140         void (*csig) (int);
141 
142         /* Need to fork to change ruid without losing euid */
143         csig = OsSignal(SIGCHLD, SIG_DFL);
144         switch ((pid = fork())) {
145         case -1:
146             ErrorF("xf86writeConfigFile(): fork failed (%s)\n",
147                    strerror(errno));
148             return 0;
149         case 0:                /* child */
150             if (setuid(getuid()) == -1)
151                 FatalError("xf86writeConfigFile(): "
152                            "setuid failed(%s)\n", strerror(errno));
153             ret = doWriteConfigFile(filename, cptr);
154             exit(ret);
155             break;
156         default:               /* parent */
157             do {
158                 p = waitpid(pid, &status, 0);
159             } while (p == -1 && errno == EINTR);
160         }
161         OsSignal(SIGCHLD, csig);
162         if (p != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0)
163             return 1;           /* success */
164         else
165             return 0;
166 
167 #else                           /* HAS_SAVED_IDS_AND_SETEUID */
168         int ruid, euid;
169 
170         ruid = getuid();
171         euid = geteuid();
172 
173         if (seteuid(ruid) == -1) {
174             ErrorF("xf86writeConfigFile(): seteuid(%d) failed (%s)\n",
175                    ruid, strerror(errno));
176             return 0;
177         }
178         ret = doWriteConfigFile(filename, cptr);
179 
180         if (seteuid(euid) == -1) {
181             ErrorF("xf86writeConfigFile(): seteuid(%d) failed (%s)\n",
182                    euid, strerror(errno));
183         }
184         return ret;
185 
186 #endif                          /* HAS_SAVED_IDS_AND_SETEUID */
187 
188     }
189     else
190 #endif                          /* !HAS_NO_UIDS */
191         return doWriteConfigFile(filename, cptr);
192 }
193