135c4bbdfSmrg/*
205b261ecSmrg * Copyright (c) 1997  Metro Link Incorporated
335c4bbdfSmrg *
405b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
535c4bbdfSmrg * copy of this software and associated documentation files (the "Software"),
605b261ecSmrg * to deal in the Software without restriction, including without limitation
705b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
805b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
905b261ecSmrg * Software is furnished to do so, subject to the following conditions:
1035c4bbdfSmrg *
1105b261ecSmrg * The above copyright notice and this permission notice shall be included in
1205b261ecSmrg * all copies or substantial portions of the Software.
1335c4bbdfSmrg *
1405b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1705b261ecSmrg * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1805b261ecSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
1905b261ecSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2005b261ecSmrg * SOFTWARE.
2135c4bbdfSmrg *
2205b261ecSmrg * Except as contained in this notice, the name of the Metro Link shall not be
2305b261ecSmrg * used in advertising or otherwise to promote the sale, use or other dealings
2405b261ecSmrg * in this Software without prior written authorization from Metro Link.
2535c4bbdfSmrg *
2605b261ecSmrg */
2705b261ecSmrg/*
2805b261ecSmrg * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
2905b261ecSmrg *
3005b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
3105b261ecSmrg * copy of this software and associated documentation files (the "Software"),
3205b261ecSmrg * to deal in the Software without restriction, including without limitation
3305b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
3405b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
3505b261ecSmrg * Software is furnished to do so, subject to the following conditions:
3605b261ecSmrg *
3705b261ecSmrg * The above copyright notice and this permission notice shall be included in
3805b261ecSmrg * all copies or substantial portions of the Software.
3905b261ecSmrg *
4005b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4105b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4205b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
4305b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
4405b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4505b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4605b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE.
4705b261ecSmrg *
4805b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s)
4905b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote
5005b261ecSmrg * the sale, use or other dealings in this Software without prior written
5105b261ecSmrg * authorization from the copyright holder(s) and author(s).
5205b261ecSmrg */
5305b261ecSmrg
5405b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
5505b261ecSmrg#include <xorg-config.h>
5605b261ecSmrg#endif
5705b261ecSmrg
5835c4bbdfSmrg#include "os.h"
5905b261ecSmrg#include "xf86Parser.h"
6005b261ecSmrg#include "xf86tokens.h"
6105b261ecSmrg#include "Configint.h"
6205b261ecSmrg
6305b261ecSmrg#include <unistd.h>
6405b261ecSmrg#include <sys/types.h>
6505b261ecSmrg#include <sys/wait.h>
6605b261ecSmrg#include <errno.h>
6705b261ecSmrg
6835c4bbdfSmrg#if defined(HAVE_SETEUID) && defined(_POSIX_SAVED_IDS) && _POSIX_SAVED_IDS > 0
6905b261ecSmrg#define HAS_SAVED_IDS_AND_SETEUID
7005b261ecSmrg#endif
7105b261ecSmrg#if defined(WIN32)
7205b261ecSmrg#define HAS_NO_UIDS
7305b261ecSmrg#endif
7405b261ecSmrg
751b5d61b8Smrgstatic int
7635c4bbdfSmrgdoWriteConfigFile(const char *filename, XF86ConfigPtr cptr)
7705b261ecSmrg{
7835c4bbdfSmrg    FILE *cf;
7935c4bbdfSmrg
8035c4bbdfSmrg    if ((cf = fopen(filename, "w")) == NULL) {
8135c4bbdfSmrg        return 0;
8235c4bbdfSmrg    }
8305b261ecSmrg
8435c4bbdfSmrg    if (cptr->conf_comment)
8535c4bbdfSmrg        fprintf(cf, "%s\n", cptr->conf_comment);
8605b261ecSmrg
8735c4bbdfSmrg    xf86printLayoutSection(cf, cptr->conf_layout_lst);
8805b261ecSmrg
8935c4bbdfSmrg    if (cptr->conf_files != NULL) {
9035c4bbdfSmrg        fprintf(cf, "Section \"Files\"\n");
9135c4bbdfSmrg        xf86printFileSection(cf, cptr->conf_files);
9235c4bbdfSmrg        fprintf(cf, "EndSection\n\n");
9335c4bbdfSmrg    }
9405b261ecSmrg
9535c4bbdfSmrg    if (cptr->conf_modules != NULL) {
9635c4bbdfSmrg        fprintf(cf, "Section \"Module\"\n");
9735c4bbdfSmrg        xf86printModuleSection(cf, cptr->conf_modules);
9835c4bbdfSmrg        fprintf(cf, "EndSection\n\n");
9935c4bbdfSmrg    }
10005b261ecSmrg
10135c4bbdfSmrg    xf86printVendorSection(cf, cptr->conf_vendor_lst);
10205b261ecSmrg
10335c4bbdfSmrg    xf86printServerFlagsSection(cf, cptr->conf_flags);
10405b261ecSmrg
10535c4bbdfSmrg    xf86printInputSection(cf, cptr->conf_input_lst);
10605b261ecSmrg
10735c4bbdfSmrg    xf86printInputClassSection(cf, cptr->conf_inputclass_lst);
10805b261ecSmrg
10935c4bbdfSmrg    xf86printOutputClassSection(cf, cptr->conf_outputclass_lst);
1106747b715Smrg
11135c4bbdfSmrg    xf86printVideoAdaptorSection(cf, cptr->conf_videoadaptor_lst);
11205b261ecSmrg
11335c4bbdfSmrg    xf86printModesSection(cf, cptr->conf_modes_lst);
11405b261ecSmrg
11535c4bbdfSmrg    xf86printMonitorSection(cf, cptr->conf_monitor_lst);
11605b261ecSmrg
11735c4bbdfSmrg    xf86printDeviceSection(cf, cptr->conf_device_lst);
11805b261ecSmrg
11935c4bbdfSmrg    xf86printScreenSection(cf, cptr->conf_screen_lst);
12005b261ecSmrg
12135c4bbdfSmrg    xf86printDRISection(cf, cptr->conf_dri);
12205b261ecSmrg
12335c4bbdfSmrg    xf86printExtensionsSection(cf, cptr->conf_extensions);
12405b261ecSmrg
12535c4bbdfSmrg    fclose(cf);
12635c4bbdfSmrg    return 1;
12705b261ecSmrg}
12805b261ecSmrg
12905b261ecSmrgint
13035c4bbdfSmrgxf86writeConfigFile(const char *filename, XF86ConfigPtr cptr)
13105b261ecSmrg{
1321b5d61b8Smrg#ifndef HAS_NO_UIDS
13335c4bbdfSmrg    int ret;
13405b261ecSmrg
13535c4bbdfSmrg    if (getuid() != geteuid()) {
13605b261ecSmrg
13705b261ecSmrg#if !defined(HAS_SAVED_IDS_AND_SETEUID)
1381b5d61b8Smrg        int pid, p;
1391b5d61b8Smrg        int status;
1401b5d61b8Smrg        void (*csig) (int);
1411b5d61b8Smrg
142ed6184dfSmrg        /* Need to fork to change ruid without losing euid */
1431b5d61b8Smrg        csig = OsSignal(SIGCHLD, SIG_DFL);
14435c4bbdfSmrg        switch ((pid = fork())) {
14535c4bbdfSmrg        case -1:
14635c4bbdfSmrg            ErrorF("xf86writeConfigFile(): fork failed (%s)\n",
14735c4bbdfSmrg                   strerror(errno));
14835c4bbdfSmrg            return 0;
14935c4bbdfSmrg        case 0:                /* child */
15035c4bbdfSmrg            if (setuid(getuid()) == -1)
15135c4bbdfSmrg                FatalError("xf86writeConfigFile(): "
15235c4bbdfSmrg                           "setuid failed(%s)\n", strerror(errno));
15335c4bbdfSmrg            ret = doWriteConfigFile(filename, cptr);
15435c4bbdfSmrg            exit(ret);
15535c4bbdfSmrg            break;
15635c4bbdfSmrg        default:               /* parent */
15735c4bbdfSmrg            do {
15835c4bbdfSmrg                p = waitpid(pid, &status, 0);
15935c4bbdfSmrg            } while (p == -1 && errno == EINTR);
16035c4bbdfSmrg        }
1611b5d61b8Smrg        OsSignal(SIGCHLD, csig);
16235c4bbdfSmrg        if (p != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0)
16335c4bbdfSmrg            return 1;           /* success */
16435c4bbdfSmrg        else
16535c4bbdfSmrg            return 0;
16635c4bbdfSmrg
16735c4bbdfSmrg#else                           /* HAS_SAVED_IDS_AND_SETEUID */
1681b5d61b8Smrg        int ruid, euid;
16935c4bbdfSmrg
17035c4bbdfSmrg        ruid = getuid();
17135c4bbdfSmrg        euid = geteuid();
17235c4bbdfSmrg
17335c4bbdfSmrg        if (seteuid(ruid) == -1) {
17435c4bbdfSmrg            ErrorF("xf86writeConfigFile(): seteuid(%d) failed (%s)\n",
17535c4bbdfSmrg                   ruid, strerror(errno));
17635c4bbdfSmrg            return 0;
17735c4bbdfSmrg        }
17835c4bbdfSmrg        ret = doWriteConfigFile(filename, cptr);
17935c4bbdfSmrg
18035c4bbdfSmrg        if (seteuid(euid) == -1) {
18135c4bbdfSmrg            ErrorF("xf86writeConfigFile(): seteuid(%d) failed (%s)\n",
18235c4bbdfSmrg                   euid, strerror(errno));
18335c4bbdfSmrg        }
18435c4bbdfSmrg        return ret;
18535c4bbdfSmrg
18635c4bbdfSmrg#endif                          /* HAS_SAVED_IDS_AND_SETEUID */
18735c4bbdfSmrg
18835c4bbdfSmrg    }
1891b5d61b8Smrg    else
1901b5d61b8Smrg#endif                          /* !HAS_NO_UIDS */
19135c4bbdfSmrg        return doWriteConfigFile(filename, cptr);
19205b261ecSmrg}
193