2 # -*- coding: utf-8 -*-
6 # Purpose: wrapper for startx on grml [providing new xconfiguration tool]
7 # Authors: grml-team (grml.org), (c) Christian Hofstaedtler <ch@grml.org>
8 # Bug-Reports: see http://grml.org/bugs/
9 # License: This file is licensed under the GPL v2.
10 ###############################################################################
12 # Requires python 2.6 or, possibly, a newer version of python 2.X.
14 import fileinput, os, subprocess, sys, tempfile, time, traceback
15 from optparse import OptionParser
17 class Section(object):
18 def __init__(self, name, identifier, data):
20 self.identifer = identifier
24 s = "Section \"%s\"\n\tIdentifier \"%s\"\n" % (self.name, self.identifer)
27 if isinstance(v, list):
29 elif not isinstance(v, basestring): # int, others
31 elif '-' in v: # sync range
35 s += "\t%s %s\n" % (k, v)
40 def get_monitor_section(options, force):
41 if not options.hsync and not options.vsync and not force:
44 d['HorizSync'] = options.hsync or '28.0 - 96.0'
45 d['VertRefresh'] = options.vsync or '50.0 - 60.0'
46 return Section('Monitor', 'Monitor0', d)
48 def get_device_section(options):
49 if not options.module:
52 d['Driver'] = options.module
53 d['VendorName'] = 'All'
54 d['BoardName'] = 'All'
55 return Section('Device', 'Card0', d)
57 def build_bootparams():
59 def walk_bootparams_path(p):
61 if not os.path.exists(p): return
62 for root, dirs, files in os.walk(p):
64 f = open(os.path.join(root, name))
65 lines.extend(f.readlines())
68 print 'W: Error while getting bootparams from %s' % p
69 f = open('/proc/cmdline')
70 lines.append(f.readline())
72 walk_bootparams_path('/cdrom/bootparams')
73 walk_bootparams_path('/live/image/bootparams')
75 for p in ' '.join(lines).split(' '):
77 (k,v) = p.split('=', 1)
84 f = open('/proc/cpuinfo')
85 x = ''.join(f.readlines())
87 if 'QEMU' in x: return True
90 def get_program_output(args):
91 p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
92 return p.communicate()[0]
94 def run_program(args):
95 subprocess.Popen(args, close_fds=True).wait()
99 return os.path.exists(fpath) and os.access(fpath, os.X_OK)
101 fpath, fname = os.path.split(program)
106 for path in os.environ["PATH"].split(os.pathsep):
107 exe_file = os.path.join(path, program)
113 XORG_CONF_HEADER = "# Automatically generated by grml-x."
114 def check_old_xorg_conf(filename, overwrite):
115 # True: no problem, we can create/overwrite the config file
116 # False: pre-existing config file, and we are not to overwrite it
117 if overwrite: return True
118 if not os.path.exists(filename): return True
120 f = file(filename, 'r')
121 lines = f.readlines()
123 return (not XORG_CONF_HEADER in lines)
127 parser = OptionParser(usage="usage: %prog [options] [window-manager]")
128 parser.add_option("--nostart", action="store_false", dest="start_server", default=True,
129 help="Don't start X server")
130 parser.add_option("--display", action="store", type="string", dest="display",
131 help="Start X server on display DISPLAY")
132 parser.add_option("--hsync", action="store", type="string", dest="hsync",
133 help="Force writing a HorizSync range")
134 parser.add_option("--vsync", action="store", type="string", dest="vsync",
135 help="Force writing a VertRefresh range")
136 parser.add_option("--mode", action="store", type="string", dest="mode",
137 help="Force a specific resolution")
138 parser.add_option("--module", action="store", type="string", dest="module",
139 help="Force driver MODULE instead of Xorg autodetection")
140 parser.add_option("-o", action="store", type="string", dest="xorg_conf", default="/etc/X11/xorg.conf",
141 help="Specify alternate xorg.conf file [default: %default]")
142 parser.add_option("-f", "--force", action="store_true", dest="overwrite", default=False,
143 help="Overwrite xorg.conf if it exists [default: %default]")
146 (options, args) = parser.parse_args()
147 bootparams = build_bootparams()
149 if os.getuid() == 0 and options.start_server:
150 print "W: running as root is unsupported and may not work."
153 if not check_old_xorg_conf(options.xorg_conf, options.overwrite):
154 print "E: Not overwriting existing %r without --force." % options.xorg_conf
155 print "I: If you previously ran grml-x, use startx /usr/bin/x-window-manager"
158 if 'xmode' in bootparams and not options.mode: options.mode = bootparams['xmode']
159 if 'xmodule' in bootparams and not options.module: options.module = bootparams['xmodule']
161 force_monitor = False
162 # cirrus driver for QEMU doesn't do 1024x768 without HorizSync set
163 if detect_qemu(): force_monitor = True
165 monitor = get_monitor_section(options, force_monitor)
166 device = get_device_section(options)
168 # build Screen section ourselves
170 if monitor: d['Monitor'] = monitor.identifer
171 if device: d['Device'] = device.identifer
172 screen = Section('Screen', 'Screen0', d)
174 d['DefaultColorDepth'] = 16
175 for depth in [8, 15, 16, 24, 32]:
176 screen.subsect += "SubSection \"Display\"\n\tDepth %d\n\tModes \"%s\"\t\nEndSubSection\n" % (depth, options.mode)
178 xinitrc = '~/.xinitrc'
179 if 'XINITRC' in os.environ: xinitrc = os.environ['XINITRC']
180 xinitrc = os.path.expanduser(xinitrc)
182 window_manager = 'x-window-manager'
183 if len(args) == 1: window_manager = args[0]
184 window_manager_path = which(window_manager)
185 if not window_manager_path:
186 print "E: Cannot find window manager %r, aborting." % window_manager
189 wm_exec = "exec %s\n" % window_manager_path
190 if not os.path.exists(xinitrc):
191 f = open(xinitrc, 'w')
192 f.write("#!/bin/sh\n")
196 f = open(xinitrc, 'r')
197 lines = f.readlines()
199 f = open(xinitrc, 'w')
201 if line.startswith('exec '): line = wm_exec
203 os.fchmod(f.fileno(), 0750)
207 if monitor or device or len(screen.data) > 0 or screen.subsect != '':
209 f = tempfile.NamedTemporaryFile(delete=False)
210 f.write(XORG_CONF_HEADER + "\n")
211 f.write("# DO NOT MODIFY, YOUR CHANGES WILL BE LOST - OR REMOVE ALL HEADER LINES\n")
212 f.write("# See man xorg.conf or /etc/X11/xorg.conf.example for more\n")
213 if monitor: f.write(str(monitor))
214 if device: f.write(str(device))
217 os.fchmod(f.fileno(), 0644)
218 run_program(['sudo', 'mv', '-f', f.name, options.xorg_conf])
222 if options.start_server:
223 startx = ['startx', xinitrc, '--']
224 if options.display: startx.append(':' + options.display)
225 print "Starting X: %r" % startx
230 if __name__ == '__main__':
235 print "E: Exception: ",
236 traceback.print_exc()