aboutsummaryrefslogtreecommitdiff
blob: 42fb5d06bbe9cd2f1df2634ed14344060cab1c36 (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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
#!/usr/bin/python
# Copyright 1999-2005 Gentoo Foundation
# This source code is distributed under the terms of version 2 of the GNU
# General Public License as published by the Free Software Foundation, a copy
# of which can be found in the main directory of this project.

import sys
sys.path.append("../..")

import dialog
import GLIException, GLIInstallProfile, GLIClientController, GLIUtility, Partitioning

import string, copy, time, re, glob, os, platform
import gettext
try:
	gettext.install('gli-dialog', './languages')
	translator = gettext.translation('gli-dialog', './languages')
	_ = translator.gettext
except:
	_ = gettext.gettext


# ------------------------------------------------------------------
class GLIDialog(object):
	def __init__(self):
		self._d = dialog.Dialog()
		self._install_profile = GLIInstallProfile.InstallProfile()
		self._cc = GLIClientController.GLIClientController(self._install_profile,pretend=False,verbose=True)  #FIXME change to False
		
		self._DLG_OK = 0
		self._DLG_YES = 0
		self._DLG_CANCEL = 1
		self._DLG_NO = 1
		self._DLG_ESC = 2
		self._DLG_ERROR = 3
		self._DLG_EXTRA = 4
		self._DLG_HELP = 5
		self._d.setBackgroundTitle("Gentoo Linux Installer")
		self.profile_xml_file = None
		self.advanced_mode = False
		self.networkless = True
		self.just_starting = 1


############ ACCESSOR FUNCTIONS #############
	def _dmenu_list_to_choices(self, list):
		choices = []
		for i in range(0, len(list)):
			choices.append((str(i + 1), list[i]))
		return choices
	
	def install_profile(self):
		return self._install_profile
	
	def fatal(self,message):
		self._d.msgbox(message)
		sys.exit(0)

############ QUESTION FUNCTIONS  #################
	def show_welcome_screen(self):
		
		welcome_string = _(u"""Welcome to the Gentoo Linux Installer!  This program will help install Gentoo on your computer.
Before proceeding please thoroughly read the Gentoo Installation Handbook available at 
http://www.gentoo.org/doc/en/handbook/index.xml \n
Press OK to continue""")
		self._d.msgbox(welcome_string, height=25, width=78, title=_(u"Welcome"))

	def ask_advanced_mode(self):
		#Set the Yes/No labels.
		self._d.add_persistent_args(["--yes-label", _(u"Standard")])
		self._d.add_persistent_args(["--no-label",_(u"Advanced")])
		advanced_string = _(u"""This installer has two modes, an advanced mode for those knowledgable with the inner details of their computer and a standard mode where many of the defaults will be chosen for the user for simplicity and to speed up the install process.  The advanced mode offers full customizability and is required for generating profiles to be used other computers. \nThe advanced mode is recommended by the developers.
		""")
		if self._d.yesno(advanced_string, width=65, height=15) == self._DLG_NO:
			self.advanced_mode = True
		else:
			self.advanced_mode = False
			
	def ask_networkless(self):
		networkless_string = _(u"Do you want to do a networkless installation?  This will limit the customizability of your install due to the limitations of the LiveCD.  For example, choosing networkless will set your installation stage, portage snapshot, and limit your extra packages selections.  NOTE: It is easily possible to do a networkless installation on a machine with an active Internet connection; in fact this may result in the fastest installations for many users.")
		#Change the Yes/No buttons
		#self._d.add_persistent_args(["--yes-label", _(u"Networkless")])
		#self._d.add_persistent_args(["--no-label", _(u"Internet enabled")])
		#if self._d.yesno(networkless_string, width=70, height=20) == self._DLG_YES:
		self.networkless = True
		#	try:
		self._install_profile.set_grp_install(None, True, None)
		self._install_profile.set_install_stage(None, "3", None)
		self._install_profile.set_dynamic_stage3(None, True, None)
		self._install_profile.set_portage_tree_sync_type(None,"snapshot", None)
		cd_snapshot_uri = GLIUtility.get_cd_snapshot_uri()
		self._install_profile.set_portage_tree_snapshot_uri(None, cd_snapshot_uri, None)
		self._install_profile.set_kernel_source_pkg(None, "livecd-kernel", None)
		self._install_profile.set_cron_daemon_pkg(None, "vixie-cron", None)
		self._install_profile.set_logging_daemon_pkg(None,"syslog-ng", None)
		#	except:
		#		self._d.msgbox(_(u"ERROR: Could not set networkless information in the profile"))
		#else:
		#	self.networkless = False

	def ask_load_profile(self):
		#Reset the Yes/No labels.
		self._d.add_persistent_args(["--yes-label", _(u"Yes")])
		self._d.add_persistent_args(["--no-label",_(u"No")])
		#Ask 
		while 1:
			string = _(u"""
	All of the installation settings are stored in an XML file, which we call the InstallProfile. If you have a previously-created profile, you can load it now
	for use in this installation.
	Do you have a previously generated profile for the installer?
	""")
			if self._d.yesno(string, width=70, height=15, defaultno=1) == self._DLG_YES:
				code, self.profile_xml_file = self._d.inputbox(_(u"Enter the filename of the XML file"))
				if code != self._DLG_OK: 
					break
				if GLIUtility.is_file(self.profile_xml_file): 
					break
				self._d.msgbox(_(u"Cannot open file %s") % self.profile_xml_file, height=7, width=50)
				self.profile_xml_file = None
				continue
			else:
				break
		if self.profile_xml_file != None:
			self._install_profile.parse(self.profile_xml_file)
			self.run_phase5()
			sys.exit(0)

############ STAGE1 FUNCTIONS    #################

	def set_arch_template(self):
		subarches = { 'i386': 'x86', 'i486': 'x86', 'i586': 'x86', 'i686': 'x86', 'x86_64': 'amd64', 'parisc': 'hppa' }
		arch = platform.machine()
		if arch in subarches: 
			arch = subarches[arch]
		self._arch = arch
	
	def set_verbose(self):
		#Don't show unless advanced.
		if self.advanced_mode:
			#Change the Yes/No buttons back.
			self._d.add_persistent_args(["--yes-label", _(u"Yes")])
			self._d.add_persistent_args(["--no-label", _(u"No")])
			if self._d.yesno(_(u"Do you want debugging output enabled during the install?  This is mainly meant to help the developers debug any bugs."), width=65) == self._DLG_YES:
				self._install_profile.set_verbose(None, True, None)
			else:
				self._install_profile.set_verbose(None, False, None)
	
	def set_client_networking(self):
		if self.networkless: return
		if GLIUtility.ping("www.gentoo.org"):	#If an active connection exists, ignore this step.
			return
		
		device_list = GLIUtility.get_eth_devices()
	
		choice_list = []
		for device in device_list:
			choice_list.append((device, GLIUtility.get_interface_realname(device)))
		choice_list.append((_(u"Other"),_(u"Type your own.")))
		cnet_string1 = _(u"In order to complete most installs, an active Internet connection is required.  Listed are the network devices already detected.  In this step you will need to setup one network connection for GLI to use to connect to the Internet.  If your desired device does not show up in the list, you can select Other and input the device name manually.")
		code, interface = self._d.menu(cnet_string1, width=75, height=20, choices=choice_list)
	
		if interface == _(u"Other"):
			code, interface = self._d.inputbox(_(u"Enter the interface (NIC) you would like to use for installation (e.g. eth0):"))
			if code != self._DLG_OK: 
				return
		
		dhcp_options = ""
		
		#Change the Yes/No buttons to new labels for this question.
		self._d.add_persistent_args(["--yes-label", _(u"DHCP")])
		self._d.add_persistent_args(["--no-label", _(u"Static IP/Manual")])
		cnet_string2 = _(u"To setup your network interface, you can either use DHCP if enabled, or manually enter your network information.\n  DHCP (Dynamic Host Configuration Protocol) makes it possible to automatically receive networking information (IP address, netmask, broadcast address, gateway, nameservers etc.). This only works if you have a DHCP server in your network (or if your provider provides a DHCP service).  If you do not, you must enter the information manually.  Please select your networking configuration method:")
		if self._d.yesno(cnet_string2, height=15, width=70) == self._DLG_YES: #DHCP
			network_type = 'dhcp'
			if self.advanced_mode:
				code, dhcp_options = self._d.inputbox(_(u"If you have any additional DHCP options to pass, type them here in a space-separated list.  If you have none, just press Enter."), height=13, width=60)
		else:
			network_type = 'static'
			code, data = self._d.form(_(u'Enter your networking information: (See Chapter 3 of the Handbook for more information)  Your broadcast address is probably your IP address with 255 as the last tuple.  DO NOT PRESS ENTER until all fields you intend to fill out are complete!'), 
			((_(u'Enter your IP address:'), 15),
			 (_(u'Enter your Broadcast address:'), 15),
			 (_(u'Enter your Netmask:'),15,'255.255.255.0'),
			 (_(u'Enter your default gateway:'),15), 
			 (_(u'Enter a DNS server:'),15,'4.2.2.1'),
			 (_(u'Enter a HTTP Proxy IP:'), 15),
			 (_(u'Enter a FTP Proxy IP:'), 15), 
			 (_(u'Enter a RSYNC Proxy:'),15)
			))
			(ip_address, broadcast, netmask, gateway, dnsservers, http_proxy, ftp_proxy, rsync_proxy) = data[:-1].split('\n')
			if code != self._DLG_OK: 
				return
			
			if ftp_proxy and ftp_proxy != "":
				os.environ['ftp_proxy'] = ftp_proxy

			if http_proxy and http_proxy != "":
				os.environ['http_proxy'] = http_proxy

			if rsync_proxy and rsync_proxy != "":
				os.environ['RSYNC_PROXY'] = rsync_proxy

		#Set the info now that it's all gathered.
		if network_type == "dhcp":
			if dhcp_options:
				status = GLIUtility.spawn("/sbin/dhcpcd -t 15 " + dhcp_options + " " + interface)
			else:
				status = GLIUtility.spawn("/sbin/dhcpcd -t 15 -n " + interface)
			if not GLIUtility.exitsuccess(status):
				self._d.msgbox("ERROR: Could not run dhcpcd command!")  #FIXME LANGUAGE
		elif network_type == "static":
			# Configure the network from the settings they gave.
			if not GLIUtility.set_ip(interface, ip_address, broadcast, netmask):
				self._d.msgbox("ERROR: Could not set the IP address!")  #FIXME LANGUAGE

			if not GLIUtility.set_default_route(gateway):
				self._d.msgbox("ERROR: Could not set the default route!")  #FIXME LANGUAGE

			if dns_servers:
				try:
					resolv_conf = open("/etc/resolv.conf", "w")
					for dns_server in dns_servers:
						resolv_conf.write("nameserver " + dns_server + "\n")
					resolv_conf.close()
				except:
					self._d.msgbox("ERROR: Could not set the DNS servers!")  #FIXME LANGUAGE
					
		time.sleep(5)	#Give the backgrounded process a chance.
		#Test the connection to make sure everything worked.
		if not GLIUtility.ping("www.gentoo.org"):	
			self._d.msgbox(_(u"Sorry, but the network could not be set up successfully.  Please configure yourself manually and restart the installer."))
			sys.exit(0)
	
	def set_enable_ssh(self):
		#Change the Yes/No buttons back.
		self._d.add_persistent_args(["--yes-label", _(u"Yes")])
		self._d.add_persistent_args(["--no-label", _(u"No")])
		if self.advanced_mode and not self.networkless:
			if self._d.yesno(_(u"Do you want SSH enabled during the install?  This will allow you to login remotely during the installation process.  If choosing Yes, be sure you select a new LiveCD root password!"), width=65) == self._DLG_YES:
			# Enables SSH **Code originally from GLIClientController**
				status = GLIUtility.spawn("/etc/init.d/sshd start")
				if not GLIUtility.exitsuccess(status):
					self._d.msgbox(_(u"ERROR! : Could not start the SSH daemon!"))
	
	def set_livecd_password(self):
		# The root password will be set here only if in advanced mode.  Otherwise it is auto-scrambled.
		if self.advanced_mode:
			self._root_passwd = ""
			match = False;
			while not match:
				livecd_password_string = _(u"""If you want to be able to login to your machine from another console during the installation,
	you will want to enter a new root password for the LIVECD.
	Note that this can be different from your new system's root password.
	Presss Enter twice to skip this step.
	Enter the new LIVECD root password (will not be echoed):	""")
				code, passwd1 = self._d.passwordbox(livecd_password_string, width=65, height=17)
				if code != self._DLG_OK: 
					return
				code, passwd2 = self._d.passwordbox(_(u"Enter the new LIVECD root password again to verify:"))
				if code != self._DLG_OK: 
					return
				if passwd1 != passwd2:
					self._d.msgbox(_(u"The passwords do not match.  Please try again."))
					return
				else:
					match = True;
					if passwd1 != "":  #don't want to hash an empty password.
						try:
							self._root_passwd = GLIUtility.hash_password(passwd1)
						except:
							self._d.msgbox(_(u"ERROR! Could not hash the root password on the LiveCD!"))
						##
			# Actually set it now.  **Code originally from GLIClientController**
			#self._logger.log("Setting root password.")
			if self._root_passwd != "":
				# The password specified in the configuration is encrypted.
				status = GLIUtility.spawn("echo 'root:" + self._root_passwd + "' | chpasswd -e")
		
				if not GLIUtility.exitsuccess(status):
					self._d.msgbox(_(u"ERROR! Could not set the root password on the livecd environment!"))
			#	else:
			#		self._logger.log("Livecd root password set.")
		
	def set_client_kernel_modules(self):
		if self.advanced_mode:
			status, output = GLIUtility.spawn("lsmod", return_output=True)
			cmodules_string1 = _(u"Here is a list of modules currently loaded on your machine.\n  Please look through and see if any modules are missing\n that you would like loaded.\n\n")
			self._d.add_persistent_args(["--exit-label", _(u"Continue")])
			self._d.scrollbox(cmodules_string1+output, height=20, width=70, title=_(u"Loaded Modules"))
			cmodules_string2 = _(u"If you have additional modules you would like loaded before the installation begins (ex. a network driver), enter them in a space-separated list.")
			code, kernel_modules_list = self._d.inputbox(cmodules_string2, init="", width=60, height=12)
			if code != self._DLG_OK:
				return
				
		
			# Actually Load the kernel modules  **Code originally from GLIClientController
		
			#self._logger.log("DEBUG: load_kernel_modules(): modules are " + str(modules))
			for module in kernel_modules_list.split():
				try:
			#		if self._configuration.get_verbose(): self._logger.log("DEBUG: load_kernel_modules(): trying to load module " + module)
					ret = GLIUtility.spawn('modprobe ' + module)
					if not GLIUtility.exitsuccess(ret):
						self._d.msgbox(_(u"ERROR! : Could not load module: %s ") % module)
					#	raise GLIException("KernelModuleError", 'warning', 'load_kernel_modules', 'Could not load module: ' + module)
					#else:
					#	self._logger.log('kernel module: ' + module + ' loaded.')
				except:
					self._d.msgbox(_(u"ERROR!:  An unknown error occurred during modprobing the modules.  Please load them manually and then restart the installer."))

#######################################
#######################################
### MAIN INSTALL SETUP FUNCTIONS START HERE

############ STAGE2 FUNCTIONS    #################

	def set_mounts(self):
		mounts = copy.deepcopy(self._install_profile.get_mounts())
		
		if not mounts:
			#No mountpoints defined. lets at least find the swap partitions and add them.
			for drive in self._drives:
				for part in self._devices[drive]:
					if part['type'] == "linux-swap":
						mounts.append({'devnode': part['devnode'], 'mountopts': '', 'mountpoint': '', 'type': "linux-swap"})
			
		while 1:
			menulist = []
			for mount in mounts:
				if mount['type'] == "linux-swap":
					menulist.append(mount['devnode'] + " - swap")
				else:
					menulist.append(mount['devnode'] + " - " + mount['mountpoint'])
			#menulist.append(_(u"Define a new mountpoint"))
			choices = self._dmenu_list_to_choices(menulist)
			choices.append((_(u"Add"),_(u"Define a new mountpoint")))
			code, choice = self._d.menu(_(u"Please define the mountpoints of your partitions for the new system.  At minimum, a / mountpoint must be defined.  Defining  /boot and /home mountpoints is recommended."),choices=choices, cancel=_(u"Save and Continue"), height=18, width=65)
			if code == self._DLG_CANCEL:
				#Apply a check here for the existence of at least a root partition.
				foundroot = False
				for mount in mounts:
					if mount['mountpoint'] == "/":
						foundroot = True
				if not foundroot:
					continue
				try:
					self._install_profile.set_mounts(mounts)
				except:
					self._d.msgbox(_(u"ERROR: Could net set mounts!"))
				break
			if choice == _(u"Add"):
				parts = []
				fstypes = {}
				
				#Make a list of the partitions
				for drive in self._drives:
					for tmppart in self._devices[drive]:
						skip = False
						devnode = tmppart['devnode']
						entry = ""
						if tmppart['type'] == "free":
							continue
						elif tmppart['type'] == "extended":
							continue
						else:
							if tmppart.is_logical():
								entry += _(u"Logical (")
							else:
								entry += _(u"Primary (")
							entry += tmppart['type'] + ", "
							entry += str(tmppart['mb']) + "MB)"
							
						#Go through and remove any already defined. 
						for mount in mounts:
							if mount['devnode'] == devnode:
								skip = True
						
						if not skip:
							#Add to the choices list.
							parts.append((devnode,entry))
							fstypes[devnode] = tmppart['type']
				
				if not parts:
					continue
				code, partition = self._d.menu(_(u"Select a Partition to define a mountpoint for"), choices=parts, height=18, width=65)
				if code != self._DLG_OK: 
					continue
				
				fstype = fstypes[partition]
				#Ask for mountpoint for this partition. #FIXME use Partition to get the type.
			#	choices_list = ['ext2', 'ext3', 'linux-swap', 'xfs', 'jfs', 'reiserfs','ntfs', 'fat16', 'fat32']
			#	choices = self._dmenu_list_to_choices(choices_list)
			#	code,fstypeidx = self._d.menu(_(u"Select the filesystem for partition %s") % partition, choices=choices, height=18)
			#	if fstypeidx:
			#		fstype = choices_list[int(fstypeidx)-1]
			#	else: continue
				
				if fstype == 'linux-swap':
					#We have all the info we need, now add the mount
					mounts.append({'devnode': partition, 'mountopts': '', 'mountpoint': '', 'type': fstype})
					continue
				
				#Ask for the mountpoint
				mountpoint_menu = ["/","/boot","/etc","/home","/lib","/mnt","/mnt/windows","/opt","/root","/usr","/usr/local","/usr/portage","/var",_(u"Other")]
				code, mountpt = self._d.menu(_(u"Choose a mountpoint from the list or choose Other to type your own for partition %s. ") % partition, choices=self._dmenu_list_to_choices(mountpoint_menu), width=65) #may have to make that an integer
				if code == self._DLG_OK:
					mountpoint = mountpoint_menu[int(mountpt)-1]
					if mountpoint == _(u"Other"):
						code, mountpoint = self._d.inputbox(_(u"Enter a mountpoint for partition %s") % partition)
					
				if not mountpoint: continue
				
				#Ask for mountopts
				code, mountopts = self._d.inputbox(_(u"Enter mount options for mountpoint %s. Leave blank for defaults") % mountpoint, height=13, width=60)
				if code != self._DLG_OK: 
					continue
				
				#We have all the info we need, now add the mount
				mounts.append({'devnode': partition, 'mountopts': mountopts, 'mountpoint': mountpoint, 'type': fstype})
			elif choice:  #EDITING A MOUNTPOINT
				#Find the mount in question, based on devnode
				idx = int(choice) - 1
				devnode = mounts[idx]['devnode']
				mountpoint = mounts[idx]['mountpoint']
				mountopts = mounts[idx]['mountopts']
				fstype = mounts[idx]['type']
						
				menu = [_(u"Change Mountpoint"), 
					_(u"Change Filesystem Type"),
					_(u"Change Mountoptions"),
					_(u"Delete This Mountpoint")]
				code, editchoice = self._d.menu(_(u"Select an option for device %(dev)s : Mountpoint: %(mt)s, Type: %(type)s, Options: %(opt)s" % {'dev': devnode, 'mt': mountpoint, 'type': fstype, 'opt': mountopts}), choices=self._dmenu_list_to_choices(menu))
				if code == self._DLG_CANCEL:
					continue
				editchoice = menu[int(editchoice)-1]
				if editchoice == _(u"Change Mountpoint"):
					mountpoint_menu = ["/","/boot","/etc","/home","/lib","/mnt","/mnt/windows","/opt","/root","/usr","/usr/local","/usr/portage","/var",_(u"Other")]
					code, mountpt = self._d.menu(_(u"Choose a mountpoint from the list or choose Other to type your own for partition %(part)s. Current mountpoint is: %(mt)s" % {'part': devnode, 'mt': mountpoint}) , choices=self._dmenu_list_to_choices(mountpoint_menu), height=18) #may have to make that an integer
					if code == self._DLG_OK:
						mountpoint = mountpoint_menu[int(mountpt)-1]
						if mountpoint == _(u"Other"):
							code, mountpoint = self._d.inputbox(_(u"Enter a mountpoint for partition %s") % devnode)
					if not mountpoint: continue
					mounts[idx]['mountpoint'] = mountpoint
				elif editchoice == _(u"Change Filesystem Type"):
					choices_list = ['ext2', 'ext3', 'linux-swap', 'xfs', 'jfs', 'reiserfs','ntfs', 'fat16', 'fat32']
					choices = self._dmenu_list_to_choices(choices_list)
					code,fstypeidx = self._d.menu(_(u"Select the filesystem for partition %(part)s. It is currently %(fs)s." % {'part': devnode,'fs': fstype}), choices=choices, height=18)
					if fstypeidx:
						fstype = choices_list[int(fstypeidx)-1]
					else: continue
					mounts[idx]['type'] = fstype
				elif editchoice == _(u"Change Mountoptions"):
					code, mountopts = self._d.inputbox(_(u"Enter mount options for mountpoint %s. Leave blank for defaults") % mountpoint, init=mountopts,height=13, width=50)
					if code != self._DLG_OK: 
						continue
					mounts[idx]['mountopts'] = mountopts
				elif editchoice == _(u"Delete This Mountpoint"):
					del mounts[idx]
				else: continue #catchall.
	def set_partitions(self):
		partitions_string1 = _(u"""The first thing on the new system to setup is the partitoning.
	You will first select a drive and then edit its partitions.
	WARNING: CHANGES ARE MADE IMMEDIATELY TO DISK. BE CAREFUL
	NOTE: YOU MUST AT LEAST SELECT ONE PARTITION AS YOUR ROOT PARTITION "/"
	If your drive is pre-partitioned, just select the mountpoints and make 
	sure that the format option is set to FALSE or it will erase your data.
	The installer does not yet support resizing of partitions (its not safe).
	When in doubt, **Partition it yourself and then re-run the installer**
	Please refer to the Gentoo Installation Handbook for more information
	on partitioning and the various filesystem types available in Linux.""")
		self._d.msgbox(partitions_string1, height=17, width=78)
		drives = []
		devices = {}
		choice_list = []
		tmp_drives = Partitioning.detect_devices()
		tmp_drives.sort()
		for drive in tmp_drives:
			devices[drive] = Partitioning.Device(drive, self._arch, self._install_profile)
			drives.append(drive)
			choice_list.append((drive, devices[drive].get_model()))
		self._drives = drives  #Store for use in mounts.
		self._devices = devices  #Store for use in mounts.
		while 1:
			code, drive_to_partition = self._d.menu(_(u"Which drive would you like to partition?\n Info provided: Type, Size in MB"), choices=choice_list, cancel=_(u"Done"), width=65)
			if code != self._DLG_OK: break
			while 1:
				partsmenu = []
#				for part in partlist:
				for tmppart in devices[drive_to_partition]:
#					tmppart = tmpparts[part]
					entry = ""
					if tmppart['type'] == "free":
						#partschoice = "New"
						entry = _(u" - Unallocated space (")
						if tmppart.is_logical():
							entry += _(u"logical, ")
						entry += str(tmppart['mb']) + "MB)"
					elif tmppart['type'] == "extended":
						entry = str(int(tmppart['minor']))
						entry += _(u" - Extended Partition (") + str(tmppart['mb']) + "MB)"
					else:
						entry = str(int(tmppart['minor'])) + " - "
						# Type: " + tmppart.get_type() + ", Mountpoint: " + tmppart.get_mountpoint() + ", Mountopts: " + tmppart.get_mountopts() + "("
						if tmppart.is_logical():
							entry += _(u"Logical (")
						else:
							entry += _(u"Primary (")
						entry += tmppart['type'] + ", "
						entry += str(tmppart['mb']) + "MB)"
					partsmenu.append(entry)
				#Add recommended partitioning option and clear option
				partsmenu.append(_(u"Set Recommended Layout"))
				partsmenu.append(_(u"Clear Partitions On This Drive."))
				code, part_to_edit = self._d.menu(_(u"Select a partition or unallocated space to edit\nKey: Minor, Pri/Ext, Filesystem, Size."), width=70, choices=self._dmenu_list_to_choices(partsmenu), cancel=_(u"Back"))
				if code != self._DLG_OK: break
				partmenuchoice = partsmenu[int(part_to_edit)-1]
				#Check for recommended and clear here before setting the tmppart
				if partmenuchoice == _(u"Set Recommended Layout"):
					if self._d.yesno(_(u"This will ERASE YOUR DRIVE and apply a recommended layout. Are you sure you wish to do this?")) == self._DLG_YES:
						if self._d.yesno(_(u"This is your last chance.  Are you SURE you want to CLEAR this drive and set a recommended layout?  THERE IS NO TURNING BACK IF YOU SELECT YES."), width=65, defaultno=1) == self._DLG_YES:
							devices[drive_to_partition].do_recommended()
					continue
				if partmenuchoice == _(u"Clear Partitions On This Drive."):
					if self._d.yesno(_(u"This will remove all partitions on your drive. Are you sure you wish to do this?")) == self._DLG_YES:
						if self._d.yesno(_(u"This is your last chance.  Are you SURE you want to CLEAR this drive?  THIS WILL DELETE ANY DATA ON THE DRIVE!"), width=65, defaultno=1) == self._DLG_YES:
							devices[drive_to_partition].clear_partitions()
#						self._d.msgbox(_(u"Partition table cleared successfully"))
#					except:
#						self._d.msgbox(_(u"ERROR: could not clear the partition table!"))
					continue
				#all other cases (partitions)
				part_to_edit = int(part_to_edit) - 1
				tmppart = devices[drive_to_partition][part_to_edit]
				if tmppart['type'] == "free":
					# partition size first
					free_mb = long(tmppart['mb'])
					code, new_mb = self._d.inputbox(_(u"Enter the size of the new partition in MB (max %s MB).  If creating an extended partition input its entire size (not just the first logical size):") % str(free_mb), init=str(free_mb))
					if code != self._DLG_OK: continue
					if int(new_mb) > free_mb:
						self._d.msgbox(_(u"The size you entered (%(entered)s MB) is larger than the maximum of %(max)s MB" % {'entered': new_mb, 'max': str(free_mb)}))
						continue
					# partition type
					part_types = [("ext2", _(u"Old, stable, but no journaling")),
					("ext3", _(u"ext2 with journaling and b-tree indexing (RECOMMENDED)")),
					("linux-swap", _(u"Swap partition for memory overhead")),
					("fat32", _(u"Windows filesystem format used in Win9X and XP")),
#					("ntfs", _(u"Windows filesystem format used in Win2K and NT")),
#					("jfs", _(u"IBM's journaling filesystem.  stability unknown.")),
#					("xfs", _(u"Don't use this unless you know you need it.")),
					("reiserfs", _(u"B*-tree based filesystem. great performance. Only V3 supported.")),
					("extended", _(u"Create an extended partition containing other logical partitions")),
					(_(u"Other"), _(u"Something else we probably don't support."))]
					code, type = self._d.menu(_(u"Choose the filesystem type for this new partition."), height=20, width=77, choices=part_types)
					if code != self._DLG_OK: continue
										
					# 'other' partition type
					if type == _(u"Other"):
						code, type = self._d.inputbox(_(u"Please enter the new partition's type:"))
					if code != self._DLG_OK: continue
					
					# now add it to the data structure
					devices[drive_to_partition].add_partition(part_to_edit, int(new_mb), type)
				else:
					while 1:
						tmppart = devices[drive_to_partition][part_to_edit]
						tmptitle = drive_to_partition + str(tmppart['minor']) + " - "
						if tmppart.is_logical():
							tmptitle += _(u"Logical (")
						else:
							tmptitle += _(u"Primary (")
						tmptitle += tmppart['type'] + ", "
						tmptitle += str(tmppart['mb']) + "MB)"
						menulist = [_(u"Delete"), _(u"Extra mkfs.* Parameters")]
						code, part_action = self._d.menu(tmptitle, choices=self._dmenu_list_to_choices(menulist), cancel=_(u"Back"))
						if code != self._DLG_OK: break
						part_action = menulist[int(part_action)-1]
						if part_action == _(u"Delete"):
							answer = (self._d.yesno(_(u"Are you sure you want to delete the partition ") + drive_to_partition + str(tmppart['minor']) + "?") == self._DLG_YES)
							if answer == True:
								devices[drive_to_partition].remove_partition(part_to_edit)
								break

						elif part_action == _(u"Extra mkfs.* Parameters"):
							self._d.msgbox(_(u"This feature is coming soon.  Please go to console and do it yourself for now."))

	def set_network_mounts(self):
	# This is where any NFS mounts will be specified
		network_mounts = copy.deepcopy(self._install_profile.get_network_mounts())
		while 1:
			menulist = []
			for mount in network_mounts:
				menulist.append(mount['host'] + ":" + mount['export'])
			menulist.append(_(u"Add a new network mount"))
			choices = self._dmenu_list_to_choices(menulist)
			code, menuitemidx = self._d.menu(_(u"If you have any network shares you would like to mount during the install and for your new system, define them here. Select a network mount to edit or add a new mount.  Currently GLI only supports NFS mounts."), choices=choices, cancel=_(u"Save and Continue"), height=18, width=65)
			if code == self._DLG_CANCEL:
				try:
					self._install_profile.set_network_mounts(network_mounts)
				except:
					self._d.msgbox(_(u"ERROR: Could net set network mounts!"))
				break
			menuitem = menulist[int(menuitemidx)-1]
			if menuitem == _(u"Add a new network mount"):
				#Change the Yes/No buttons back.
				self._d.add_persistent_args(["--yes-label", _(u"Yes")])
				self._d.add_persistent_args(["--no-label", _(u"No")])
				if self._d.yesno(_(u"Do you want to start portmap to be able to search for NFS mounts?"), width=60) == self._DLG_YES:
					status = GLIUtility.start_portmap()
					if not status:
						self._d.msgbox(_(u"ERROR: Could not start portmap!"))
			
				code, nfsmount = self._d.inputbox(_(u"Enter NFS mount or just enter the IP/hostname to search for available mounts"), height=13, width=50)
				if code != self._DLG_OK: 
					continue
				if not GLIUtility.is_nfs(nfsmount):
					if GLIUtility.is_ip(nfsmount) or GLIUtility.is_hostname(nfsmount):
						status, remotemounts = GLIUtility.spawn("/usr/sbin/showmount -e " + nfsmount + " 2>&1 | egrep '^/' | cut -d ' ' -f 1 && echo", return_output=True)
						remotemounts = remotemounts.strip().split("\n")
						if (not GLIUtility.exitsuccess(status)) or (not len(remotemounts)) or not remotemounts[0]:
							self._d.msgbox(_(u"No NFS exports were detected on ") + nfsmount)
							continue
						code, nfsmount2 = self._d.menu(_(u"Select a NFS export"), choices=self._dmenu_list_to_choices(remotemounts), cancel=_(u"Back"))
						if code != self._DLG_OK: 
							continue
						nfsmount2 = remotemounts[int(nfsmount2)-1]
					else:
						self._d.msgbox(_(u"The address you entered, %s, is not a valid IP or hostname.  Please try again.") % nfsmount)
						continue
				else:
					colon_location = nfsmount.find(':')
					menuitem = nfsmount
					nfsmount = menuitem[:colon_location]
					nfsmount2 = menuitem[colon_location+1:]
				for mount in network_mounts:
					if nfsmount == mount['host'] and nfsmount2 == mount['export']:
						self._d.msgbox(_(u"There is already an entry for ") + nfsmount + ":" + nfsmount2 + ".")
						nfsmount = None
						break
				if nfsmount == None: 
					continue
				network_mounts.append({'export': nfsmount2, 'host': nfsmount, 'mountopts': '', 'mountpoint': '', 'type': 'nfs'})
				menuitem = nfsmount + ":" + nfsmount2
				menuitemidx = len(network_mounts)
	
			if menuitem.find(':') != -1:
				colon_location = menuitem.find(':')
				tmpmount = network_mounts[int(menuitemidx)-1]
				code, mountpoint = self._d.inputbox(_(u"Enter a mountpoint"), init=tmpmount['mountpoint'])
				if code == self._DLG_OK: 
					tmpmount['mountpoint'] = mountpoint
				code, mountopts = self._d.inputbox(_(u"Enter mount options"), init=tmpmount['mountopts'])
				if code == self._DLG_OK: 
					tmpmount['mountopts'] = mountopts
				network_mounts[int(menuitemidx)-1] = tmpmount
	
############ STAGE3 FUNCTIONS    #################	

	def set_install_stage(self):
		if self.networkless: return
	# The install stage and stage tarball will be selected here
		install_stages = (("3",_(u"Stage3 is a basic system that has been built for you (no compiling).")), 
							("3+GRP", _(u"A Stage3 install but using binaries from the LiveCD when able.")))
		code, install_stage = self._d.menu(_(u"Which stage do you want to start at?"), choices=install_stages, cancel=_(u"Back"), width=78)
		stage3warning = ""
		if code == self._DLG_OK:
			if install_stage == "3+GRP":
				stage3warning = _(u"WARNING: Since you are doing a GRP install it is HIGHLY recommended you choose Create from CD to avoid a potentially broken installation.")
				try:
					self._install_profile.set_grp_install(None, True, None)
				except:
					self._d.msgbox(_(u"ERROR! Could not set install stage!"))
				install_stage = "3"
			try:			
				self._install_profile.set_install_stage(None, install_stage, None)
			except:
				self._d.msgbox(_(u"ERROR! Could not set install stage!"))
		has_systempkgs = GLIUtility.is_file("/usr/livecd/systempkgs.txt")
		if install_stage == "3" and has_systempkgs:
			#Change the Yes/No buttons to new labels for this question.
			self._d.add_persistent_args(["--yes-label", _(u"Create from CD")])
			self._d.add_persistent_args(["--no-label", _(u"Specify URI")])
			if self._d.yesno(_(u"Do you want to generate a stage3 on the fly using the files on the LiveCD (fastest) or do you want to grab your stage tarball from the Internet?\n")+stage3warning, width=55) == self._DLG_YES:
				#Generate on the FLY				
				try:
					self._install_profile.set_dynamic_stage3(None, True, None)
				except:
					self._d.msgbox(_(u"ERROR: Could not set the stage tarball URI!"))
				return
		#Specify URI
		#subarches = { 'x86': ("x86", "i686", "pentium3", "pentium4", "athlon-xp"), 'hppa': ("hppa1.1", "hppa2.0"), 'ppc': ("g3", "g4", "g5", "ppc"), 'sparc': ("sparc32", "sparc64")}

		stage_tarball = ""
		while (not stage_tarball) and (not GLIUtility.is_uri(stage_tarball)): #LOOP till valid.
			type_it_in = False
			if GLIUtility.ping("www.gentoo.org"):  #Test for network connectivity
				mirrors = GLIUtility.list_mirrors()
				mirrornames = []
				mirrorurls = []
				for item in mirrors:
					mirrornames.append(item[1])
					mirrorurls.append(item[0])
				code, mirror = self._d.menu(_(u"Select a mirror to grab the tarball from or select Cancel to enter an URI manually."), choices=self._dmenu_list_to_choices(mirrornames), width=77, height=20)
				if code != self._DLG_OK:
					type_it_in = True
				else:
					mirror = mirrorurls[int(mirror)-1]
					tarballs = GLIUtility.list_stage_tarballs_from_mirror(mirror, self._arch)
					code, stage_tarball = self._d.menu(_(u"Select your desired stage tarball:"), choices=self._dmenu_list_to_choices(tarballs), width=77, height=20)
					if (code != self._DLG_OK):
						type_it_in = True
					else:
						stage_tarball = mirror + "/releases/" + self._arch + "/current/stages/" + tarballs[int(stage_tarball)-1]
			#get portageq envvar value of cflags and look for x86, i686,etc.
				#URL SYNTAX
				#http://gentoo.osuosl.org/releases/ARCHITECTURE/current/stages/
			else:
				type_it_in = True
			if type_it_in:
				code, stage_tarball = self._d.inputbox(_(u"Specify the stage tarball URI or local file:"), init=self._install_profile.get_stage_tarball_uri())
				if code != self._DLG_OK:
					return
			#If Doing a local install, check for valid file:/// uri
			if stage_tarball:
				if not GLIUtility.is_uri(stage_tarball):
					self._d.msgbox(_(u"The specified URI is invalid.  It was not saved.  Please go back and try again."));
				else: self._install_profile.set_stage_tarball_uri(None, stage_tarball, None)
			else: self._d.msgbox(_(u"No URI was specified!"))
	
	def set_portage_tree(self):
	# This section will ask whether to sync the tree, whether to use a snapshot, etc.
		if self._install_profile.get_dynamic_stage3():  #special case
			try:
				self._install_profile.set_portage_tree_sync_type(None,"snapshot", None)
				cd_snapshot_uri = GLIUtility.get_cd_snapshot_uri()
				self._install_profile.set_portage_tree_snapshot_uri(None, cd_snapshot_uri, None)
			except:
				self._d.msgbox(_(u"ERROR! Could not set the portage cd snapshot URI!"))
			return
			
		#Normal case
		menulist = [("Sync", _(u"Normal. Use emerge sync RECOMMENDED!")),
		("Webrsync", _(u"HTTP daily snapshot. Use when rsync is firewalled.")),
		("Snapshot", _(u"Use a portage snapshot, either a local file or a URL")),
		("None", _(u"Extra cases such as if /usr/portage is an NFS mount"))]
		code, portage_tree_sync = self._d.menu(_(u"Which method do you want to use to sync the portage tree for the installation?  If choosing a snapshot you will need to provide the URI for the snapshot if it is not on the livecd."),width=75, height=17, choices=menulist)
		if code != self._DLG_OK: 
			return
		self._install_profile.set_portage_tree_sync_type(None, portage_tree_sync.lower(), None)
		if portage_tree_sync == "Snapshot":
			if self._install_profile.get_portage_tree_snapshot_uri():
				initval = self._install_profile.get_portage_tree_snapshot_uri()
			else:
				initval = GLIUtility.get_cd_snapshot_uri()
			code, snapshot = self._d.inputbox(_(u"Enter portage tree snapshot URI"), init=initval)
			if code == self._DLG_OK:
				if snapshot: 
					if not GLIUtility.is_uri(snapshot):
						self._d.msgbox(_(u"The specified URI is invalid.  It was not saved.  Please go back and try again."))
					else: 
						self._install_profile.set_portage_tree_snapshot_uri(None, snapshot, None)
			
				else: 
					self._d.msgbox(_(u"No URI was specified! Returning to default emerge sync."))
			#if d.yesno("The specified URI is invalid. Use it anyway?") == DLG_YES: install_profile.set_stage_tarball_uri(None, stage_tarball, None)
	
############ STAGE4 FUNCTIONS    #################
	
	def set_make_conf(self):
	# This section will be for setting things like CFLAGS, ACCEPT_KEYWORDS, and USE
		#special case for dynamic stage3
		if self._install_profile.get_dynamic_stage3() or not self.advanced_mode:
			return
		
		etc_files = self._install_profile.get_etc_files()
		if etc_files.has_key("make.conf"):
			make_conf = etc_files['make.conf']
		else:
			make_conf = {}
		
		self._d.msgbox(_(u"""The installer will now gather information regarding the contents of /etc/make.conf
	One of the unique (and best) features of Gentoo is the ability to
	define flags (called USE flags) that define what components are 
	compiled into applications.  For example, you can enable the alsa
	flag and programs that have alsa capability will use it.  
	The result is a finely tuned OS with no unnecessary components to
	slow you down.
	The installer divides USE flag selection into two screens, one for
	global USE flags and one for local flags specific to each program.
	Please be patient while the screens load. It may take awhile."""), width=73, height=16)
		
		#First grab the system USE flags.  These will be used often.
		system_use_flags = GLIUtility.spawn("portageq envvar USE", return_output=True)[1].strip().split()
		
		#Now get any stored USE flags.
		remove_from_system = {}
		add_flags = []
		if make_conf.has_key("USE"): 
			stored_use_flags = make_conf["USE"].split()
			for flag in stored_use_flags:
				if "-" in flag: #A subtraction of a flag in the system USE
					remove_flag = flag[1:]
					remove_from_system[remove_flag] = 1
				else:
					add_flags.append(flag)  #Add to checked list
		
		
		#Load data.
		use_flags = []
		use_local_flags = []
		use_desc = GLIUtility.get_global_use_flags()
		use_local_desc = GLIUtility.get_local_use_flags()
		
		#populate the choices list
		sorted_use = use_desc.keys()
		sorted_use.sort()
		for flagname in sorted_use:
			use_flags.append((flagname, use_desc[flagname], int((flagname in system_use_flags or flagname in add_flags) and not remove_from_system.has_key(flagname) )))
		#present the menu
		code, chosen_use_flags = self._d.checklist(_(u"Choose which *global* USE flags you want on the new system"), height=25, width=80,list_height=17, choices=use_flags)	
		
		#populate the chocies list
		sorted_use = use_local_desc.keys()
		sorted_use.sort()
		for flagname in sorted_use:
			use_local_flags.append((flagname, use_local_desc[flagname], int((flagname in system_use_flags or flagname in add_flags) and not remove_from_system.has_key(flagname) )))
		#present the menu
		code, chosen_use_local_flags = self._d.checklist(_(u"Choose which *local* USE flags you want on the new system"), height=25, width=80,list_height=17, choices=use_local_flags)	
		
		
		#Hash the chosen list for speed.
		chosen_hash = {}
		for flag in chosen_use_flags:
			chosen_hash[flag] = 1
		for flag in chosen_use_local_flags:
			chosen_hash[flag] = 1
		
		#Create the new string.  Loop through ALL flags, look for match in hash then in USE
		temp_use = ""
		for flag in use_desc:
			if chosen_hash.has_key(flag) and (flag in system_use_flags):
				continue   #Already in USE, don't need to add.
			elif chosen_hash.has_key(flag):
				temp_use += flag + " "  #Checked.  Add.
			elif not chosen_hash.has_key(flag) and (flag in system_use_flags):
				temp_use += "-"+flag+" "   #Was unchecked.  add a -flag to USE
			
		for flag in use_local_desc:
			if chosen_hash.has_key(flag) and (flag in system_use_flags):
				continue   #Already in USE, don't need to add.
			elif chosen_hash.has_key(flag):
				temp_use += flag + " "  #Checked.  Add.
			elif not chosen_hash.has_key(flag) and (flag in system_use_flags):
				temp_use += "-"+flag+" "   #Was unchecked.  add a -flag to USE
		#Store it!
		make_conf["USE"] = temp_use
		
		if not self._install_profile.get_dynamic_stage3() and self.advanced_mode:
			#Second, set the ACCEPT_KEYWORDS
			#Change the Yes/No buttons to new labels for this question.
			self._d.add_persistent_args(["--yes-label", _(u"Stable")])
			self._d.add_persistent_args(["--no-label", _(u"Unstable")])
			if self._d.yesno(_(u"Do you want to run the normal stable portage tree, or the bleeding edge unstable (i.e. ACCEPT_KEYWORDS=%s)?  If unsure select stable.  Stable is required for GRP installs." % self._arch), height=12, width=55) == self._DLG_YES:
				#Stable
				make_conf["ACCEPT_KEYWORDS"] = ""
			else:  #Unstable
				make_conf["ACCEPT_KEYWORDS"] = "~" + self._arch
		#Third, misc. stuff.
		while self.advanced_mode:
			menulist = [("CFLAGS",_(u"Edit your C Flags and Optimization level")),
			("CHOST", _(u"Change the Host Setting")),
			("MAKEOPTS", _(u"Specify number of parallel makes (-j) to perform.")),
			("FEATURES", _(u"Change portage functionality settings. (distcc/ccache)")),
			("GENTOO_MIRRORS", _(u"Specify mirrors to use for source retrieval.")),
			("SYNC", _(u"Specify server used by rsync to sync the portage tree.")),
			(_(u"Other"), _(u"Specify your own variable and value."))]
			if self._install_profile.get_dynamic_stage3():  #SPECIAL LIST WITHOUT CHOST
				menulist = [("CFLAGS",_(u"Edit your C Flags and Optimization level")),
					("MAKEOPTS", _(u"Specify number of parallel makes (-j) to perform.")),
					("FEATURES", _(u"Change portage functionality settings. (distcc/ccache)")),
					("GENTOO_MIRRORS", _(u"Specify mirrors to use for source retrieval.")),
					("SYNC", _(u"Specify server used by rsync to sync the portage tree.")),
					(_(u"Other"), _(u"Specify your own variable and value."))]
			code, menuitem = self._d.menu(_(u"For experienced users, the following /etc/make.conf variables can also be defined.  Choose a variable to edit or Done to continue."), choices=menulist, cancel=_(u"Done"), width=77)
			if code != self._DLG_OK: 
				break
			if menuitem == _(u"Other"):
				code,menuitem = self._d.inputbox(_(u"Enter the variable name: "))
				if code != self._DLG_OK:
					continue
			oldval = ""
			if make_conf.has_key(menuitem): 
				oldval = make_conf[menuitem]
				if oldval:
					code, newval = self._d.inputbox(_(u"Enter new value for ") + menuitem, init=oldval)
					if code == self._DLG_OK:
						make_conf[menuitem] = newval
					continue
			#SPECIAL CASES here with their own menus.
			if menuitem == "CFLAGS":
				if not make_conf.has_key("CFLAGS"):
					try:
						cflags = GLIUtility.get_value_from_config("/etc/make.conf","CFLAGS")
					except:
						cflags = ""
				else:
					cflags = make_conf['CFLAGS']
				while 1:
					choices_list = [
					(_(u"CLEAR"),_(u"Erase the current value and start over.")),
					("-mcpu",_(u"Add a CPU optimization (deprecated in GCC 3.4)")),
					("-mtune",_(u"Add a CPU optimization (GCC 3.4+)")),
					("-march",_(u"Add an Architecture optimization")),
					("-O",_(u"Add optimization level (please do NOT go over 2)")),
					("-fomit-frame-pointer",_(u"For advanced users only.")),
					("-pipe",_(u"Common additional flag")),
					(_(u"Manual"),_(u"Specify your CFLAGS manually"))
					]
					code, choice = self._d.menu(_(u"Choose a flag to add to the CFLAGS variable or Done to go back.  The current value is: ")+ cflags, choices=choices_list, cancel=_(u"Done"), width=70)
					if code != self._DLG_OK:
						break
					if choice == _(u"CLEAR"):
						cflags = ""
					elif choice == _(u"Manual"):
						code, cflags = self._d.inputbox(_(u"Enter new value for ") + menuitem)
						break
					elif choice in ["-fomit-frame-pointer","-pipe"]:
						cflags += " "+choice
					else:
						code, newval = self._d.inputbox(_(u"Enter the new value for %s (value only):") % choice)
						if code != self._DLG_OK or not newval:
							continue
						if choice == "-O":
							cflags += " "+choice+newval
						else:
							cflags += " "+choice+"="+newval
				if cflags:
					make_conf['CFLAGS'] = cflags
			elif menuitem == "CHOST":
				choices_list = GLIUtility.get_chosts(self._arch)
				code, chost = self._d.menu(_(u"Choose from the available CHOSTs for your architecture."), choices=self._dmenu_list_to_choices(choices_list), width=77)
				if code != self._DLG_OK: 
					continue
				chost = choices_list[int(chost)-1]
				make_conf['CHOST'] = chost
			elif menuitem == "MAKEOPTS":
				makeopt_string = _(u"Presently the only use is for specifying the number of parallel makes (-j) to perform. The suggested number for parallel makes is CPUs+1.  Enter the NUMBER ONLY:")
				code, newval = self._d.inputbox(makeopt_string, width=60)
				if code != self._DLG_OK:
					continue
				make_conf['MAKEOPTS'] = "-j"+str(newval)
			elif menuitem == "FEATURES":
				choices_list = [("sandbox",_(u"enables sandboxing when running emerge and ebuild."),0),
				("ccache",_(u"enables ccache support via CC."),0),
				("distcc",_(u"enables distcc support via CC."),0),
				("distlocks",_(u"enables distfiles locking using fcntl or hardlinks."),0),
				("buildpkg",_(u"create binaries of all packages emerged"),0),
				(_(u"Other"),_(u"Input your list of FEATURES manually."),0)	]
				features_string = _(u"FEATURES are settings that affect the functionality of portage. Most of these settings are for developer use, but some are available to non-developers as well.")
				code, choices = self._d.checklist(features_string, choices=choices_list, width=75)
				if code != self._DLG_OK:
					continue
				if _(u"Other") in choices:
					code, features = self._d.inputbox(_(u"Enter the value of FEATURES: "))
				elif choices:
					features = string.join(choices, ' ')
				else:
					features = ""
				if features:
					make_conf['FEATURES'] = features
			else:
				code, newval = self._d.inputbox(_(u"Enter new value for ") + menuitem)
				if code == self._DLG_OK and newval:
					make_conf[menuitem] = newval
	
		try:
			if make_conf:
				etc_files['make.conf'] = make_conf
				self._install_profile.set_etc_files(etc_files)
		except:
			self._d.msgbox(_(u"ERROR! Could not set the make_conf correctly!"))
	
	def set_distcc(self):
		#Change the Yes/No buttons for this question.
		if self._install_profile.get_dynamic_stage3() or not self.advanced_mode:
			return
		self._d.add_persistent_args(["--yes-label", _(u"Yes")])
		self._d.add_persistent_args(["--no-label", _(u"No")])
		if self._d.yesno(_(u"Do you want to use distcc to compile your extra packages during the install and for future compilations as well?"), height=12, width=60, defaultno=1) == self._DLG_YES:
			#Add distcc to the services list.
			if self._install_profile.get_services():
				services = self._install_profile.get_services()
				if isinstance(services, str):
					services = services.split(',')
			else:
				services = []
			if not "distccd" in services:
				services.append("distccd")
			try:
				services = string.join(services, ',')
				if services:
					self._install_profile.set_services(None, services, None)
			except:
				self._d.msgbox(_(u"ERROR! Could not set the services list."))
				return
			#Set the distcc flag to emerge earlier than other packages.
			try:
				self._install_profile.set_install_distcc(None, True, None)
			except:
				self._d.msgbox(_(u"ERROR! Could not set the install distcc flag!"))
				return
	
			#Add distcc to the FEATURES in make.conf and add DISTCC_HOSTS too.
			etc_files = self._install_profile.get_etc_files()
			#load up the make.conf
			if etc_files.has_key("make.conf"):
				make_conf = etc_files['make.conf']
			else:
				make_conf = {}
			#Check for FEATURES and add if not already there.
			if make_conf.has_key("FEATURES"):
				if not "distcc" in make_conf['FEATURES']:
					make_conf['FEATURES'] += " distcc"
			else:
				make_conf['FEATURES'] = "distcc"
			#Now while still working in make.conf, figure out what HOSTS to set.
			if make_conf.has_key("DISTCC_HOSTS"):
				initval = make_conf['DISTCC_HOSTS']
			else:
				initval = "localhost "
			distcc_string = _(u"Enter the hosts to be used by distcc for compilation:\nExample: localhost    192.168.0.2     192.168.0.3:4000/10")
			code, hosts = self._d.inputbox(distcc_string, width=75, init=initval)
			if code != self._DLG_OK:
				hosts = initval
			make_conf['DISTCC_HOSTS'] = hosts
			try:
				etc_files['make.conf'] = make_conf
				self._install_profile.set_etc_files(etc_files)
			except:
				self._d.msgbox(_(u"ERROR! Could not set the make_conf correctly!"))	
	
	def set_etc_portage(self):
		if self.networkless: return
	#This section will be for editing the /etc/portage/* files and other /etc/* files.  This should be for advanced users only.
		etc_files = self._install_profile.get_etc_files()
		while self.advanced_mode:
			
			menulist = [("portage/package.mask",_(u"A list of DEPEND atoms to mask.")),
			("portage/package.unmask",_(u"A list of packages to unmask.")),
			("portage/package.keywords",_(u"Per-package KEYWORDS (like ACCEPT_KEYWORDS).")),
			("portage/package.use",_(u"Per-package USE flags.")),
			(_(u"Other"),_(u"Type your own name of a file to edit in /etc/"))]
			code, menuitem = self._d.menu(_(u"For experienced users, the following /etc/* variables can also be defined.  Choose a variable to edit or Done to continue."), choices=menulist, cancel=_(u"Done"), width=77)
			if code != self._DLG_OK: 
				break  #get out of the while loop. then save and continue
			
			if menuitem == _(u"Other"):
				code, menuitem = self._d.inputbox(_(u"Enter the name of the /etc/ file you would like to edit (DO NOT type /etc/)"))
				if code != self._DLG_OK:
					return
			oldval = ""
			if etc_files.has_key(menuitem): 
				oldval = etc_files[menuitem]
				
			code, newval = self._d.inputbox(_(u"Enter new contents (use \\n for newline) of ") + menuitem, init=oldval)
			if code == self._DLG_OK:
				etc_files[menuitem] = []
				etc_files[menuitem].append(newval)
		try:
			self._install_profile.set_etc_files(etc_files)
		except:
			self._d.msgbox(_(u"ERROR! Could not set etc/portage/* correctly!"))
	
		
	
	def set_kernel(self):
		if self.networkless: return
	# This section will be for choosing kernel sources, choosing (and specifying) a custom config or genkernel, modules to load at startup, etc.
		kernel_sources = [("livecd-kernel", _(u"Copy over the current running kernel (fastest)")),
		("vanilla-sources", _(u"The Unaltered Linux Kernel ver 2.6+ (safest)")),
		("gentoo-sources", _(u"Gentoo's optimized 2.6+ kernel. (less safe)")+" (RECOMMENDED)"),  #FIXME LANGUAGE
		("hardened-sources", _(u"Hardened sources for the 2.6 kernel tree")),
		("grsec-sources",_(u"Vanilla sources with grsecurity patches")),
		(_(u"Other"), _(u"Choose one of the other sources available."))]
		code, menuitem = self._d.menu(_(u"Choose which kernel sources to use for your system.  If using a previously-made kernel configuration, make sure the sources match the kernel used to create the configuration."), choices=kernel_sources, width=77, height=17)
		if code != self._DLG_OK: 
			return
		if menuitem == _(u"Other"):
			code, menuitem = self._d.inputbox(_(u"Please enter the desired kernel sources package name:"))
			if code != self._DLG_OK: return
		try:
			self._install_profile.set_kernel_source_pkg(None, menuitem, None)
		except:
			self._d.msgbox(_(u"ERROR! Could not set the kernel source package!"))
		if not menuitem == "livecd-kernel":
			#Change the Yes/No buttons to new labels for this question.
			self._d.add_persistent_args(["--yes-label", _(u"Genkernel")])
			self._d.add_persistent_args(["--no-label", _(u"Traditional (requires a config!)")])
			kernel_string1 = _(u"There are currently two ways the installer can compile a kernel for your new system.  You can either provide a previously-made kernel configuration file and use the traditional kernel-compiling procedure (no initrd) or have genkernel automatically create your kernel for you (with initrd).  \n\n If you do not have a previously-made kernel configuration, YOU MUST CHOOSE Genkernel.  Choose which method you want to use.")
			if self._d.yesno(kernel_string1, width=76,height=13) == self._DLG_YES:   #Genkernel
				self._install_profile.set_kernel_build_method(None,"genkernel", None)
				if self.advanced_mode:
					#Change the Yes/No buttons back.
					self._d.add_persistent_args(["--yes-label", _(u"Yes")])
					self._d.add_persistent_args(["--no-label", _(u"No")])
					if self._d.yesno(_(u"Do you want the bootsplash screen to show up on bootup?")) == self._DLG_YES:
						self._install_profile.set_kernel_bootsplash(None, True, None)
					else:
						self._install_profile.set_kernel_bootsplash(None, False, None)
			else: 	#Custom
				self._install_profile.set_kernel_build_method(None,"custom", None)
			if self.advanced_mode:
				code, custom_kernel_uri = self._d.inputbox(_(u"If you have a custom kernel configuration, enter its location (otherwise just press Enter to continue):"), height=13, width=50)
				if code == self._DLG_OK: 
					if custom_kernel_uri: 
						if not GLIUtility.is_uri(custom_kernel_uri, checklocal=self.local_install):
							self._d.msgbox(_(u"The specified URI is invalid.  It was not saved.  Please go back and try again."))
						else: 
							try:
								self._install_profile.set_kernel_config_uri(None, custom_kernel_uri, None)
							except:
								self._d.msgbox(_(u"ERROR! Could not set the kernel config URI!"))
				#else: self._d.msgbox(_(u"No URI was specified!  Reverting to using genkernel"))
				
	def set_boot_loader(self):
		mounts = self._install_profile.get_mounts()
		boot_drive_choices = []
		#Bootloader code yanked from the x86ArchTemplate
		kernel_params = self._install_profile.get_bootloader_kernel_args()
		if self._install_profile.get_boot_device():
			boot_device = self._install_profile.get_boot_device()
		else:
			boot_device = ""
			foundboot = False
			for mount in mounts:
				#if not mount['devnode'][:-1] in boot_drive_choices:
				#	boot_drive_choices.append(mount['devnode'][:-1])
				mountpoint = mount['mountpoint']
				if (mountpoint == "/boot"):
					foundboot = True
				if (( (mountpoint == "/") and (not foundboot) ) or (mountpoint == "/boot")):
					if not "doscsi" in kernel_params.split():
						if mount['devnode'].startswith("/dev/sd"): kernel_params += " doscsi"
			for drive in self._drives:
				boot_drive_choices.append((drive, self._devices[drive].get_model()))
		arch_loaders = { 'x86': [
			("grub",_(u"GRand Unified Bootloader, newer, RECOMMENDED")),
		],
		'amd64': [
			("grub",_(u"GRand Unified Bootloader, newer, RECOMMENDED"))]} #FIXME ADD OTHER ARCHS
		if not self.networkless: 	 
			arch_loaders['x86'].append(("lilo",_(u"LInux LOader, older, traditional.(detects windows partitions)")))
		boot_loaders = arch_loaders[self._arch]
		boot_loaders.append(("none", _(u"Do not install a bootloader.  (System may be unbootable!)")))
		boot_string1 = _(u"To boot successfully into your new Linux system, a bootloader will be needed.  If you already have a bootloader you want to use you can select None here.  The bootloader choices available are dependent on what GLI supports and what architecture your system is.  Choose a bootloader")
		code, menuitem = self._d.menu(boot_string1, choices=boot_loaders, height=16, width=74)
		if code != self._DLG_OK: 
			return
		try:
			self._install_profile.set_boot_loader_pkg(None, menuitem, None)
		except:
			self._d.msgbox(_(u"ERROR! Could not set boot loader pkg! ")+menuitem)
		if menuitem == "none":
			return
		if self.advanced_mode:
			#Reset the Yes/No labels.
			self._d.add_persistent_args(["--yes-label", _(u"Yes")])
			self._d.add_persistent_args(["--no-label",_(u"No")])
			boot_string2 = _(u"Most bootloaders have the ability to install to either the Master Boot Record (MBR) or some other partition.  Most people will want their bootloader installed on the MBR for successful boots, but if you have special circumstances, you can have the bootloader installed to the /boot partition instead.  Do you want the boot loader installed in the MBR? (YES is RECOMMENDED)")
			if self._d.yesno(boot_string2, height=13, width=55) == self._DLG_YES:
				self._install_profile.set_boot_loader_mbr(None, True, None)
			else:
				self._install_profile.set_boot_loader_mbr(None, False, None)
		if self._install_profile.get_boot_loader_mbr():  #If we're installing to MBR gotta check the device.
			if self.advanced_mode or (boot_device and boot_device[-1] != 'a'):
				#show the menu.
				boot_string3_std = _(u"Your boot device may not be correct.  It is currently set to %s, but this device may not be the first to boot.  Usually boot devices end in 'a' such as hda or sda.") % boot_device
				boot_string3 = _(u"  Please confirm your boot device by choosing it from the menu.")
				if not self.advanced_mode:
					boot_string3 = boot_string3_std + boot_string3
				if not boot_drive_choices:
					self._d.msgbox(_(u"ERROR: No drives set up.  Please complete the Partitioning screen first!"))
					return
				code, boot_drive_choice = self._d.menu(boot_string3, choices=boot_drive_choices, height=16, width=70)
				if code != self._DLG_OK:
					return
				try:
					self._install_profile.set_boot_device(None,boot_drive_choice,None)
				except:
					self._d.msgbox(_(u"ERROR! Could not set the boot device!")+boot_drive_choice)
		if self.advanced_mode:
			code, bootloader_kernel_args = self._d.inputbox(_(u"If you have any additional optional arguments you want to pass to the kernel at boot, type them here or just press Enter to continue:"), height=12, width=55, init=kernel_params)
			if code == self._DLG_OK:
				try:
					self._install_profile.set_bootloader_kernel_args(None, bootloader_kernel_args, None)
				except:
					self._d.msgbox(_(u"ERROR! Could not set bootloader kernel arguments! ")+bootloader_kernel_args)
		elif kernel_params:  #If we are in standard mode but have the dosci to add.
			try:
				self._install_profile.set_bootloader_kernel_args(None, kernel_params, None)
			except:
				self._d.msgbox(_(u"ERROR! Could not set bootloader kernel arguments! ")+bootloader_kernel_args)
				
	
	def set_timezone(self):
	# This section will be for setting the timezone.
		zonepath = "/usr/share/zoneinfo"
		skiplist = ["zone.tab","iso3166.tab","posixrules"]
		while 1:
			tzlist = []
			for entry in os.listdir(zonepath):
				if entry not in skiplist:
					if os.path.isdir(zonepath + "/" + entry): entry += "/"
					tzlist.append(entry)
			tzlist.sort()
			timezone_string = _(u"Please select the timezone for the new installation.  Entries ending with a / can be selected to reveal a sub-list of more specific locations. For example, you can select America/ and then Chicago.")
			code, tznum = self._d.menu(timezone_string, choices=self._dmenu_list_to_choices(tzlist), height=20, cancel="Back")
			if code == self._DLG_OK:
				zonepath = os.path.join(zonepath,tzlist[int(tznum)-1])
				if tzlist[int(tznum)-1][-1:] != "/": 
					break
			else:
				if zonepath == "/usr/share/zoneinfo": 
					return
				slashloc = zonepath[:-1].rfind("/")
				zonepath = zonepath[:slashloc]
		try:
			self._install_profile.set_time_zone(None, zonepath[20:], None)
		except:
			self._d.msgbox(_(u"ERROR: Could not set that timezone!"))
	
	def set_networking(self):
	# This section will be for setting up network interfaces
		interfaces = self._install_profile.get_network_interfaces()
			
		while 1:
			net_string1 = _(u"Here you will enter all of your network interface information for the new system.  You can either choose a network interface to edit, add a network interface, delete an interface, or edit the miscellaneous options such as hostname and proxy servers.")
			net_string2 = _(u"To setup your network interface, you can either use DHCP if enabled, or manually enter your network information.\n  DHCP (Dynamic Host Configuration Protocol) makes it possible to automatically receive networking information (IP address, netmask, broadcast address, gateway, nameservers etc.). This only works if you have a DHCP server in your network (or if your provider provides a DHCP service).  If you do not, you must enter the information manually.  Please select your networking configuration method:")
			choice_list = []
			for iface in interfaces:
				if interfaces[iface][0] == 'dhcp':
					choice_list.append((iface, _(u"Settings: DHCP. Options: ")+ interfaces[iface][1]))
				else:
					choice_list.append((iface, _(u"IP: ")+interfaces[iface][0]+_(u" Broadcast: ")+interfaces[iface][1]+_(u" Netmask: ")+interfaces[iface][2]))
			choice_list.append((_(u"Add"),_(u"Add a new network interface")))
			code, iface_choice = self._d.menu(net_string1, choices=choice_list, cancel=_(u"Save and Continue"), height=18, width=77)
			if code != self._DLG_OK:
				try:
					self._install_profile.set_network_interfaces(interfaces)
				except:
					self._d.msgbox(_(u"ERROR! Could not set the network interfaces!"))
				break  #This should hopefully move the user down to part two of set_networking
			if iface_choice == _(u"Add"):
				
				device_list = GLIUtility.get_eth_devices()
				newchoice_list = []
				for device in device_list:
					if device not in interfaces:
						newchoice_list.append((device, GLIUtility.get_interface_realname(device)))
				newchoice_list.append((_(u"Other"),_(u"Type your own.")))
				code, newnic = self._d.menu(_(u"Choose an interface from the list or Other to type your own if it was not detected."), choices=newchoice_list, width=75)
				
				if newnic == _(u"Other"):
					code, newnic = self._d.inputbox(_(u"Enter name for new interface (eth0, ppp0, etc.)"))
					if code != self._DLG_OK: 
						continue
					if newnic in interfaces:
						self._d.msgbox(_(u"An interface with the name is already defined."))
						continue
				#create the interface in the data structure.
				#interfaces[newnic] = ("", "", "")
				#Change the Yes/No buttons to new labels for this question.
				self._d.add_persistent_args(["--yes-label", _(u"DHCP")])
				self._d.add_persistent_args(["--no-label", _(u"Static IP/Manual")])
				if self._d.yesno(net_string2, height=17, width=70) == self._DLG_YES: #DHCP
					dhcp_options = ""
					if self.advanced_mode:
						code, dhcp_options = self._d.inputbox(_(u"If you have any additional DHCP options to pass, type them here in a space-separated list.  If you have none, just press Enter."), height=13, width=60)
					interfaces[newnic] = ('dhcp', dhcp_options, None)
				else:
					network_type = 'static'
					code, data = self._d.form(_(u'Enter your networking information: (See Chapter 3 of the Handbook for more information)  Your broadcast address is probably your IP address with 255 as the last tuple.  Do not press Enter until all fields are complete!'),
					((_(u'Enter your IP address:'), 15),
					 (_(u'Enter your Broadcast address:'), 15),
					 (_(u'Enter your Netmask:'),15,'255.255.255.0')))
					(ip_address, broadcast, netmask) = data[:-1].split('\n')
					if code != self._DLG_OK: 
						continue
					#Set the info now that it's all gathered.
					interfaces[newnic] = (ip_address, broadcast, netmask)
			else:  #they have chosen an interface, present them with edit/delete
				#Change the Yes/No buttons to new labels for this question.
				self._d.add_persistent_args(["--yes-label", _(u"Edit")])
				self._d.add_persistent_args(["--no-label", _(u"Delete")])
				if self._d.yesno(_(u"For interface %s, you can either edit the interface information (IP Address, Broadcast, Netmask) or Delete the interface.") % iface_choice) == self._DLG_YES:
					#Edit
					#Change the Yes/No buttons to new labels for this question.
					self._d.add_persistent_args(["--yes-label", _(u"DHCP")])
					self._d.add_persistent_args(["--no-label", _(u"Static IP/Manual")])
					if self._d.yesno(net_string2, height=15, width=60) == self._DLG_YES: #DHCP
						dhcp_options = ""
						if self.advanced_mode:
							code, dhcp_options = self._d.inputbox(_(u"If you have any additional DHCP options to pass, type them here in a space-separated list.  If you have none, just press Enter."), height=13, width=50)
						interfaces[iface_choice] = ('dhcp', dhcp_options, None)
					else:
						network_type = 'static'
						code, data = self._d.form(_(u'Enter your networking information: (See Chapter 3 of the Handbook for more information)  Your broadcast address is probably your IP address with 255 as the last tuple.  Do not press Enter until all fields are complete!'), 
						((_(u'Enter your IP address:'), 15, interfaces[iface_choice][0]),
						 (_(u'Enter your Broadcast address:'), 15, interfaces[iface_choice][1]),
						 (_(u'Enter your Netmask:'),15,interfaces[iface_choice][2])))
						(ip_address, broadcast, netmask) = data[:-1].split('\n')
						if code != self._DLG_OK: 
							continue
						#Set the info now that it's all gathered.
						interfaces[iface_choice] = (ip_address, broadcast, netmask)
				else:
					#Delete
					#Reset the Yes/No buttons
					self._d.add_persistent_args(["--yes-label", _(u"Yes")])
					self._d.add_persistent_args(["--no-label", _(u"No")])
					if self._d.yesno(_(u"Are you sure you want to remove the interface ") + iface_choice + "?") == self._DLG_YES:
						del interfaces[iface_choice]
			
		#This section is for defining DNS servers, default routes/gateways, hostname, etc.
		#First ask for the default gateway device and IP
		interfaces = self._install_profile.get_network_interfaces()
		choice_list = []
		for iface in interfaces:
			if interfaces[iface][0] == 'dhcp':
				choice_list.append((iface, _(u"Settings: DHCP. Options: ")+ interfaces[iface][1],0))
			else:
				choice_list.append((iface, _(u"IP: ")+interfaces[iface][0]+_(u" Broadcast: ")+interfaces[iface][1]+_(u" Netmask: ")+interfaces[iface][2],0))
		net_string3 = _(u"To be able to surf on the internet, you must know which host shares the Internet connection. This host is called the gateway.  It is usually similar to your IP address, but ending in .1\nIf you have DHCP then just select your primary Internet interface (no IP will be needed)  Start by choosing which interface accesses the Internet:")
		if choice_list:
			if len(choice_list) == 1:  #Only one, no need for menu.
				gateway_iface = choice_list[0][0]
			else:
				code, gateway_iface = self._d.radiolist(net_string3, choices=choice_list, height=20, width=67)
			if (code == self._DLG_OK) or gateway_iface:  #They made a choice.  Ask the IP if not DHCP.
				while interfaces[gateway_iface][0] != 'dhcp':
					code, ip = self._d.inputbox(_(u"Enter the gateway IP address for ") + gateway_iface, init=interfaces[gateway_iface][0])
					if code != self._DLG_OK:
						break
					if not GLIUtility.is_ip(ip):
						self._d.msgbox(_(u"Invalid IP Entered!  Please try again."))
						continue
					try:
						self._install_profile.set_default_gateway(None, ip,{'interface': gateway_iface})
					except:
						self._d.msgbox(_(u"ERROR! Coult not set the default gateway with IP %(ip)s for interface %(iface)s" % {'ip': ip, 'iface' : gateway_iface}))
					break
		#Now ask for the other info in a large form.
		error = True
		hostname = ""
		domainname = ""
		nisdomainname = ""
		primary_dns = ""
		backup_dns = ""
		http_proxy = ""
		ftp_proxy = ""
		rsync_proxy = ""
		while error:
			error = False
			if self.advanced_mode:
				code, data = self._d.form(_(u'Fill out the remaining networking settings.  The hostname is manditory as that is the name of your computer.  Leave the other fields blank if you are not using them.  If using DHCP you do not need to enter DNS servers.  Do not press Enter until all fields are complete!'),
				((_(u'Enter your Hostname:'), 25, self._install_profile.get_hostname()),
				 (_(u'Enter your Domain Name:'), 25, self._install_profile.get_domainname()),
				 (_(u'Enter your NIS Domain Name:'),25,self._install_profile.get_nisdomainname()),
				 (_(u'Enter a primary DNS server:'),15),
				 (_(u'Enter a backup DNS server:'),15),
				 (_(u'Enter a HTTP Proxy IP:'), 15,self._install_profile.get_http_proxy()),
				 (_(u'Enter a FTP Proxy IP:'), 15, self._install_profile.get_ftp_proxy()), 
				 (_(u'Enter a RSYNC Proxy:'),15,self._install_profile.get_rsync_proxy())))
				if code != self._DLG_OK:
					return
				(hostname, domainname, nisdomainname, primary_dns, backup_dns, http_proxy, ftp_proxy, rsync_proxy) = data[:-1].split('\n')
			else: #standard mode
				code, data = self._d.form(_(u'Fill out the remaining networking settings.  The hostname is manditory as that is the name of your computer.  Leave the other fields blank if you are not using them.  If using DHCP you do not need to enter DNS servers.  Do not press Enter until all fields are complete!'),
				((_(u'Enter your Hostname:'), 25, self._install_profile.get_hostname()),
				 (_(u'Enter your Domain Name:'), 25, self._install_profile.get_domainname()),
				 (_(u'Enter a primary DNS server:'),15),
				 (_(u'Enter a backup DNS server:'),15)))
				if code != self._DLG_OK:
					return
				(hostname, domainname, primary_dns, backup_dns) = data[:-1].split('\n')
			#Check the data before entering it.				
			if hostname:
				if type(hostname) != str:
					self._d.msgbox(_(u"Incorrect hostname!  It must be a string.  Not saved."))
					error = True	
				else:
					try:			
						self._install_profile.set_hostname(None, hostname, None)
					except:
						self._d.msgbox(_(u"ERROR! Could not set the hostname:")+hostname)
						error = True
			if domainname:
				if type(domainname) != str:
					self._d.msgbox(_(u"Incorrect domainname!  It must be a string.  Not saved."))
					error = True	
				else:
					try:			
						self._install_profile.set_domainname(None, domainname, None)
					except:
						self._d.msgbox(_(u"ERROR! Could not set the domainname:")+domainname)
						error = True
			if nisdomainname:
				if type(nisdomainname) != str:
					self._d.msgbox(_(u"Incorrect nisdomainname!  It must be a string.  Not saved."))
					error = True	
				else:
					try:			
						self._install_profile.set_nisdomainname(None, nisdomainname, None)
					except:
						self._d.msgbox(_(u"ERROR! Could not set the nisdomainname:")+nisdomainname)
						error = True					
			if primary_dns:
				if not GLIUtility.is_ip(primary_dns):
					self._d.msgbox(_(u"Incorrect Primary DNS Server! Not saved."))
					error = True
				else:
					if backup_dns:
						if not GLIUtility.is_ip(backup_dns):
							self._d.msgbox(_(u"Incorrect Backup DNS Server! Not saved."))
							error = True
						else:
							primary_dns = primary_dns + " " + backup_dns
					try:			
						self._install_profile.set_dns_servers(None, primary_dns, None)
					except:
						self._d.msgbox(_(u"ERROR! Could not set the DNS Servers:")+primary_dns)
						error = True
			if http_proxy:
				if not GLIUtility.is_uri(http_proxy):
					self._d.msgbox(_(u"Incorrect HTTP Proxy! It must be a uri. Not saved."))
					error = True
				else:
					try:
						self._install_profile.set_http_proxy(None, http_proxy, None)
					except:
						self._d.msgbox(_(u"ERROR! Could not set the HTTP Proxy:")+http_proxy)
						error = True					
			if ftp_proxy:
				if not GLIUtility.is_uri(ftp_proxy):
					self._d.msgbox(_(u"Incorrect FTP Proxy! It must be a uri. Not saved."))
					error = True
				else:
					try:
						self._install_profile.set_ftp_proxy(None, ftp_proxy, None)
					except:
						self._d.msgbox(_(u"ERROR! Could not set the FTP Proxy:")+ftp_proxy)
						error = True
			if rsync_proxy:
				if not GLIUtility.is_uri(rsync_proxy):
					self._d.msgbox(_(u"Incorrect RSYNC Proxy! It must be a uri. Not saved."))
					error = True
				else:
					try:
						self._install_profile.set_rsync_proxy(None, rsync_proxy, None)
					except:
						self._d.msgbox(_(u"ERROR! Could not set the RSYNC Proxy:")+rsync_proxy)
						error = True
	
	
	def set_cron_daemon(self):
		if self.networkless: return
		cron_daemons = (("vixie-cron", _(u"Paul Vixie's cron daemon, fully featured, RECOMMENDED.")),
		("dcron",_(u"A cute little cron from Matt Dillon.")), 
		("fcron", _(u"A scheduler with extended capabilities over cron & anacron")), 
		("None", _(u"Don't use a cron daemon. (NOT Recommended!)")))
		cron_string = _(u"A cron daemon executes scheduled commands. It is very handy if you need to execute some command regularly (for instance daily, weekly or monthly).  Gentoo offers three possible cron daemons: dcron, fcron and vixie-cron. Installing one of them is similar to installing a system logger. However, dcron and fcron require an extra configuration command, namely crontab /etc/crontab. If you don't know what to choose, use vixie-cron.  If doing a networkless install, choose vixie-cron.  Choose your cron daemon:")
		code, menuitem = self._d.menu(cron_string, choices=cron_daemons, height=21, width=77)
		if code == self._DLG_OK:
			if menuitem == "None": 
				menuitem = ""
			self._install_profile.set_cron_daemon_pkg(None, menuitem, None)
	
	def set_logger(self):
		if self.networkless: return
		loggers = (("syslog-ng", _(u"An advanced system logger.")), 
		("metalog", _(u"A Highly-configurable system logger.")), 
		("syslogkd", _(u"The traditional set of system logging daemons.")))
		logger_string = _(u"Linux has an excellent history of logging capabilities -- if you want you can log everything that happens on your system in logfiles. This happens through the system logger. Gentoo offers several system loggers to choose from.  If you plan on using sysklogd or syslog-ng you might want to install logrotate afterwards as those system loggers don't provide any rotation mechanism for the log files.  If doing networkless, choose syslog-ng.  Choose a system logger:")
		code, menuitem = self._d.menu(logger_string, choices=loggers, height=21, width=68)
		if code == self._DLG_OK:
			self._install_profile.set_logging_daemon_pkg(None, menuitem, None)
	
	def set_extra_packages(self):
		#d.msgbox("This section is for selecting extra packages (pcmcia-cs, rp-pppoe, xorg-x11, etc.) and setting them up")
		if self._install_profile.get_install_packages():
			install_packages = self._install_profile.get_install_packages()
			if isinstance(install_packages, str):
				install_packages = install_packages.split()
		else:
			install_packages = []
		package_list = self._install_profile.get_install_package_list()
		highlevel_menu = []
		for group in package_list:
			highlevel_menu.append( (group, package_list[group][0]) )
		highlevel_menu.append( (_(u"Manual"), "Type your own space-separated list of packages.") )
	
		while 1:
			extra_string1 = _(u"There are thousands of applications available to Gentoo users through Portage, Gentoo's package management system.  Select some of the more common ones below or add your own additional package list by choosing 'Manual'.")
			code, submenu = self._d.menu(extra_string1+ _(u"\nYour current package list is: ")+string.join(install_packages, ','), choices=highlevel_menu, cancel=_(u"Save and Continue"), width=70, height=23)
			if code != self._DLG_OK:  #Save and move on.
				try:
					packages = string.join(install_packages, ' ')
					if packages:
						self._install_profile.set_install_packages(None, packages, None)
				except:
					self._d.msgbox(_(u"ERROR! Could not set the install packages! List of packages:"))
				return
			#Popular Desktop Applications
			choices_list = []
			#pkgs = {}
			
			#Special case first.
			if submenu == _(u"Manual"):
				code, tmp_install_packages = self._d.inputbox(_(u"Enter a space-separated list of extra packages to install on the system"), init=string.join(install_packages, ' '), width=70) 
				if code == self._DLG_OK:
					install_packages = tmp_install_packages.split()
				continue
				
			#All other cases load pkgs and GRP
			pkgs = package_list[submenu][1]
			grp_list = GLIUtility.get_grp_pkgs_from_cd()
			for pkg in pkgs:
				if pkg in grp_list:
					choices_list.append((pkg, "(GRP) "+pkgs[pkg], int(pkg in install_packages)))
				else:
					if not self.networkless:
						choices_list.append((pkg, pkgs[pkg], int(pkg in install_packages)))
			if not choices_list: continue
			code, choices = self._d.checklist(_(u"Choose from the listed packages.  If doing a networkless install, only choose (GRP) packages."), choices=choices_list, height=19, list_height=10, width=77)
			if code != self._DLG_OK: 
				continue
			for pkg in pkgs:  #clear out packages from this list that are already in install_packages so that you can uncheck packages and they will be removed.  the ones that remain checked will be re-added.
				for i, tmppkg in enumerate(install_packages):
					if tmppkg == pkg:
						del install_packages[i]
					
			for package in choices:
				install_packages.append(package)
				#special cases for desktop environments
				if package in ["x11-base/xorg-x11", "gnome-base/gnome","kde", "kde-base/kde-meta","x11-wm/blackbox","x11-wm/enlightenment","x11-wm/e17", "x11-wm/fluxbox","x11-wm/xfce4"]:  #ask about X
					#Add xorg-x11 if not already there.
					if not 'x11-base/xorg-x11' in install_packages:
						install_packages.append('x11-base/xorg-x11')
				
					#Reset the Yes/No buttons
					self._d.add_persistent_args(["--yes-label", _(u"Yes")])
					self._d.add_persistent_args(["--no-label", _(u"No")])
					if not self.advanced_mode or self._d.yesno(_(u"Do you want to start X on bootup?")) == self._DLG_YES:
						services = self._install_profile.get_services() or 'xdm'
						if isinstance(services, list):
							services = string.join(services, ',')
						if not 'xdm' in services:
							services += ',xdm'
						try:
							self._install_profile.set_services(None, services, None)
						except:
							self._d.msgbox(_(u"ERROR! Could not set the services list."))
					#rc.conf changes specific to packages.
					if package == "gnome":
						etc_files = self._install_profile.get_etc_files()
						if not "rc.conf" in etc_files:
							etc_files['rc.conf'] = {}
						etc_files['rc.conf']['DISPLAYMANAGER'] = "gdm"
						self._install_profile.set_etc_files(etc_files)
					if package == "kde" or package == "kde-meta":
						etc_files = self._install_profile.get_etc_files()
						if not "rc.conf" in etc_files:
							etc_files['rc.conf'] = {}
						etc_files['rc.conf']['DISPLAYMANAGER'] = "kdm"
						self._install_profile.set_etc_files(etc_files)
					if package == "enlightenment":
						etc_files = self._install_profile.get_etc_files()
						if not "rc.conf" in etc_files:
							etc_files['rc.conf'] = {}
						etc_files['rc.conf']['DISPLAYMANAGER'] = "entrance"
						self._install_profile.set_etc_files(etc_files)
					if package == "fluxbox":
						etc_files = self._install_profile.get_etc_files()
						if not "rc.conf" in etc_files:
							etc_files['rc.conf'] = {}
						etc_files['rc.conf']['XSESSION'] = "fluxbox"
						self._install_profile.set_etc_files(etc_files)	
						
						
	
	def set_services(self):
		if self._install_profile.get_services():
			services = self._install_profile.get_services()
			if isinstance(services, str):
				services = services.split(',')
		else:
			services = []
		choice_list = [("alsasound", _(u"ALSA Sound Daemon"),int("alsasound" in services)),
		("apache", _(u"Common web server (version 1.x)"),int("apache" in services)),
		("apache2", _(u"Common web server (version 2.x)"),int("apache2" in services)),
		("distccd", _(u"Distributed Compiling System"),int("distccd" in services)),
		("esound", _(u"ESD Sound Daemon"),int("esound" in services)),
		("hdparm", _(u"Hard Drive Tweaking Utility"),int("hdparm" in services)),
		("local", _(u"Run scripts found in /etc/conf.d/local.start"),int("local" in services)),
		("portmap", _(u"Port Mapping Service"),int("portmap" in services)),
		("proftpd", _(u"Common FTP server"),int("proftpd" in services)),
		("sshd", _(u"SSH Daemon (allows remote logins)"),int("sshd" in services)),
		("xfs", _(u"X Font Server"),int("xfs" in services)),
		("xdm", _(u"X Daemon"),int("xdm" in services)),
		(_(u"Other"),_(u"Manually specify your services in a comma-separated list."),0)]
		services_string = _(u"Choose the services you want started on bootup.  Note that depending on what packages are selected, some services listed will not exist.")
		code, services_list = self._d.checklist(services_string, choices=choice_list, height=21, list_height=12, width=77)
		if code != self._DLG_OK:
			return
		services = []
		for service in services_list:
			services.append(service)
		if _(u"Other") in services_list:
			code, services = self._d.inputbox(_(u"Enter a comma-separated list of services to start on boot"), init=string.join(services, ','))
		if code != self._DLG_OK: 
			return
		try:
			services = string.join(services, ',')
			if services:
				self._install_profile.set_services(None, services, None)
		except:
			self._d.msgbox(_(u"ERROR! Could not set the services list."))
			return
		
	def set_rc_conf(self):
	# This section is for editing /etc/rc.conf
		if not self.advanced_mode:
			return
		etc_files = self._install_profile.get_etc_files()
		keymap = ""
		windowkeys = ""
		ext_keymap = ""
		font = ""
		trans = ""
		clock = ""
		editor = ""
		disp_manager = ""
		xsession = ""
		rc_string1 = _(u"Additional configuration settings for Advanced users (rc.conf)\nHere are some other variables you can set in various configuration files on the new system.  If you don't know what a variable does, don't change it!")
		menulist = [("KEYMAP",_(u"Use KEYMAP to specify the default console keymap.")),
		("SET_WINDOWKEYS", _(u"Decision to first load the 'windowkeys' console keymap")),
		("EXTENDED_KEYMAPS", _(u"maps to load for extended keyboards.  Most users will leave this as is.")),
		("CONSOLEFONT", _(u"Specifies the default font that you'd like Linux to use on the console.")),
		("CONSOLETRANSLATION", _(u"The charset map file to use.")),
		("CLOCK", _(u"Set the clock to either UTC or local")),
		("EDITOR", _(u"Set EDITOR to your preferred editor.")),
		("DISPLAYMANAGER", _(u"What display manager do you use ?  [ xdm | gdm | kdm | entrance ]")),
		("XSESSION", _(u"a new variable to control what window manager to start default with X"))]
		while 1:
			code, variable = self._d.menu(rc_string1, choices=menulist, cancel=_(u"Save and Continue"), width=77, height=19)
			if code != self._DLG_OK: 
				break
			if variable == "KEYMAP":
				keymap_list = GLIUtility.generate_keymap_list()
				code, keymap = self._d.menu(_(u"Choose your desired keymap:"), choices=self._dmenu_list_to_choices(keymap_list), height=19)
				if code != self._DLG_OK:
					continue
				keymap = keymap_list[int(keymap)-1]
				
			elif variable == "SET_WINDOWKEYS":
				#Reset the Yes/No buttons
				self._d.add_persistent_args(["--yes-label", _(u"Yes")])
				self._d.add_persistent_args(["--no-label", _(u"No")])
				if self._d.yesno(_(u"Should we first load the 'windowkeys' console keymap?  Most x86 users will say 'yes' here.  Note that non-x86 users should leave it as 'no'.")) == self._DLG_YES:
					windowkeys = "yes"
				else:
					windowkeys = "no"
			elif variable == "EXTENDED_KEYMAPS":
				code, ext_keymap = self._d.inputbox(_(u"This sets the maps to load for extended keyboards.  Most users will leave this as is.  Enter new value for EXTENDED_KEYMAPS"), width=60)
			elif variable == "CONSOLEFONT":
				font_list = GLIUtility.generate_consolefont_list()
				code, font = self._d.menu(_(u"Choose your desired console font:"), choices=self._dmenu_list_to_choices(font_list), height=19)
				if code != self._DLG_OK:
					continue
				font = font_list[int(font)-1]
			elif variable == "CONSOLETRANSLATION":
				trans_list = GLIUtility.generate_consoletranslation_list()
				code, trans = self._d.menu(_(u"Choose your desired console translation:"), choices=self._dmenu_list_to_choices(trans_list), height=19)
				if code != self._DLG_OK:
					continue
				trans = trans_list[int(trans)-1]
			elif variable == "CLOCK":
				#Change the Yes/No buttons to new labels for this question.
				self._d.add_persistent_args(["--yes-label", "UTC"])
				self._d.add_persistent_args(["--no-label", "local"])
				if self._d.yesno(_(u"Should CLOCK be set to UTC or local?  Unless you set your timezone to UTC you will want to choose local.")) == self._DLG_YES:
					clock = "UTC"
				else:
					clock = "local"
			elif variable == "EDITOR":
				choice_list = [("/bin/nano", _(u"Default editor.")), ("/usr/bin/vim", _(u"vi improved editor.")), ("/usr/bin/emacs", _(u"The emacs editor."))]
				code, editor = self._d.menu(_(u"Choose your default editor: "), choices=choice_list)
			elif variable == "DISPLAYMANAGER":
				choice_list = [("xdm", _(u"X Display Manager")), 
				("gdm", _(u"Gnome Display Manager")), 
				("kdm", _(u"KDE Display Manager")), 
				("entrance", _(u"Login Manager for Enlightenment"))]
				code, disp_manager = self._d.menu(_(u"Choose your desired display manager to use when starting X (note you must make sure that package also gets installed for it to work):"), choices=choice_list, width=65)
			elif variable == "XSESSION":
				code, xsession = self._d.inputbox(_(u"Choose what window manager you want to start default with X if run with xdm, startx, or xinit. (common options are Gnome or Xsession):"), width=65, height=12)
			
		if not "conf.d/keymaps" in etc_files: 
			if keymap or windowkeys or ext_keymap:
				etc_files['conf.d/keymaps'] = {}
		if not "conf.d/consolefont" in etc_files: 
			if font or trans:
				etc_files['conf.d/consolefont'] = {}
		if not "conf.d/clock" in etc_files: 
			if clock:
				etc_files['conf.d/clock'] = {}
		if not "rc.conf" in etc_files: 
			if editor or disp_manager or xsession:
				etc_files['rc.conf'] = {}
		if keymap:
			etc_files['conf.d/keymaps']['KEYMAP'] = keymap
		if windowkeys:
			etc_files['conf.d/keymaps']['SET_WINDOWKEYS'] = windowkeys
		if ext_keymap:
			etc_files['conf.d/keymaps']['EXTENDED_KEYMAPS'] = ext_keymap
		if font:	
			etc_files['conf.d/consolefont']['CONSOLEFONT'] = font
		if trans:
			etc_files['conf.d/consolefont']['CONSOLETRANSLATION'] = trans
		if clock:
			etc_files['conf.d/clock']['CLOCK'] = clock
		if editor:
			etc_files['rc.conf']['EDITOR'] = editor
		if disp_manager:
			etc_files['rc.conf']['DISPLAYMANAGER'] = disp_manager
		if xsession:
			etc_files['rc.conf']['XSESSION'] = xsession
		self._install_profile.set_etc_files(etc_files)
	
	def set_root_password(self):
	# The root password will be set here
		while 1:
			code, passwd1 = self._d.passwordbox(_(u"Please enter your desired password for the root account.  (note it will not show the password.  Also do not try to use backspace.):"))
			if code != self._DLG_OK: 
				return
			code, passwd2 = self._d.passwordbox(_(u"Enter the new root password again for confirmation"))
			if code != self._DLG_OK: 
				return
			if passwd1 != passwd2:
				self._d.msgbox(_(u"The passwords do not match.  Please try again or cancel."))
			else:
				try:
					self._install_profile.set_root_pass_hash(None, GLIUtility.hash_password(passwd1), None)
				except:
					self._d.msgbox(_(u"ERROR! Could not set the new system root password!"))
				self._d.msgbox(_(u"Password saved.  Press Enter to continue."))
				return
	
	def set_additional_users(self):
	# This section will be for adding non-root users
		users = {}
		for user in self._install_profile.get_users():
			users[user[0]] = (user[0], user[1], user[2], user[3], user[4], user[5], user[6])
		while 1:
			menu_list = []
			for user in users:
				menu_list.append(user)
			menu_list.sort()
			menu_list.append(_(u"Add user"))
			users_string1 = _(u"Working as root on a Unix/Linux system is dangerous and should be avoided as much as possible. Therefore it is strongly recommended to add a user for day-to-day use.  Choose a user to edit:")
			code, menuitem = self._d.menu(users_string1, choices=self._dmenu_list_to_choices(menu_list), cancel=_(u"Save and Continue"), height=19, width=70)
			if code != self._DLG_OK:
				#if self._d.yesno("Do you want to save changes?") == self._DLG_YES:
				tmpusers = []
				for user in users:
					tmpusers.append(users[user])
				try:
					self._install_profile.set_users(tmpusers)
				except:
					self._d.msgbox(_(u"ERROR! Could not set the additional users!"))
				break
			menuitem = menu_list[int(menuitem)-1]
			if menuitem == _(u"Add user"):
				code, newuser = self._d.inputbox(_(u"Enter the username for the new user"))
				if code != self._DLG_OK: 
					continue
				if newuser in users:
					self._d.msgbox(_(u"A user with that name already exists"))
					continue
				match = False
				while not match:
					code, passwd1 = self._d.passwordbox(_(u"Enter the new password for user %s. (will not be echoed)") % newuser)
					code, passwd2 = self._d.passwordbox(_(u"Enter the new password again for confirmation"))
					if code == self._DLG_OK: 
						if passwd1 != passwd2:
							self._d.msgbox(_(u"The passwords do not match! Please try again."))
						else:
							match = True
					else:
						self._d.msgbox(_(u"You must enter a password for the user!  Even a blank password will do.  You can always edit it again later from the menu."));
				#Create the entry for the new user
				new_user = [newuser, GLIUtility.hash_password(passwd1), ('users',), '/bin/bash', '/home/' + newuser, '', '']
				users[newuser] = new_user
				menuitem = newuser
			while 1:
				menulist = [_(u"Password"), _(u"Group Membership"), _(u"Shell"), _(u"Home Directory"), _(u"UID"), _(u"Comment"), _(u"Delete")]
				code, menuitem2 = self._d.menu(_(u"Choose an option for user %s") % menuitem, choices=self._dmenu_list_to_choices(menulist), cancel=_(u"Back"))
				if code != self._DLG_OK: 
					break
				menuitem2 = menulist[int(menuitem2)-1]
				if menuitem2 == _(u"Password"):
					code, passwd1 = self._d.passwordbox(_(u"Enter the new password"))
					if code != self._DLG_OK: 
						continue
					code, passwd2 = self._d.passwordbox(_(u"Enter the new password again"))
					if code != self._DLG_OK: 
						continue
					if passwd1 != passwd2:
						self._d.msgbox(_(u"The passwords do not match! Try again."))
						continue
					self._d.msgbox(_(u"Password saved.  Press Enter to continue."))
					users[menuitem][1] = GLIUtility.hash_password(passwd1)
				elif menuitem2 == _(u"Group Membership"):
					prechk = users[menuitem][2]
					choice_list = [("users", _(u"The usual group for normal users."), int("users" in prechk)),
					("wheel", _(u"Allows users to attempt to su to root."), int("wheel" in prechk)),
					("audio", _(u"Allows access to audio devices."), int("audio" in prechk)),
					("games", _(u"Allows access to games."), int("games" in prechk)),
					("apache", _(u"For users who know what they're doing only."), int("apache" in prechk)),
					("cdrom", _(u"For users who know what they're doing only."), int("cdrom" in prechk)),
					("ftp", _(u"For users who know what they're doing only."), int("ftp" in prechk)),
					("video", _(u"For users who know what they're doing only."), int("video" in prechk)),
					(_(u"Other"), _(u"Manually specify your groups in a comma-separated list."), 0)]
					users_string2 = _(u"Select which groups you would like the user %s to be in." % menuitem)
					code, group_list = self._d.checklist(users_string2, choices=choice_list, height=19, list_height=10, width=77)
					if code != self._DLG_OK:
						break
					groups = ""
					for group in group_list:
						groups += group + ","
					if groups:
						groups = groups[:-1]
					if _(u"Other") in group_list:
						code, groups = self._d.inputbox(_(u"Enter a comma-separated list of groups the user is to be in"), init=",".join(users[menuitem][2]))
						if code != self._DLG_OK: continue
					users[menuitem][2] = string.split(groups, ",")
				elif menuitem2 == _(u"Shell"):
					code, shell = self._d.inputbox(_(u"Enter the shell you want the user to use.  default is /bin/bash.  "), init=users[menuitem][3])
					if code != self._DLG_OK: 
						continue
					users[menuitem][3] = shell
				elif menuitem2 == _(u"Home Directory"):
					code, homedir = self._d.inputbox(_(u"Enter the user's home directory. default is /home/username.  "), init=users[menuitem][4])
					if code != self._DLG_OK: 
						continue
					users[menuitem][4] = homedir
				elif menuitem2 == _(u"UID"):
					code, uid = self._d.inputbox(_(u"Enter the user's UID. If left blank the system will choose a default value (this is recommended)."), init=users[menuitem][5], height=11, width=55)
					if code != self._DLG_OK: 
						continue
					if type(uid) != int: 
						continue
					users[menuitem][5] = uid
				elif menuitem2 == _(u"Comment"):
					code, comment = self._d.inputbox(_(u"Enter the user's comment.  This is completely optional."), init=users[menuitem][6])
					if code != self._DLG_OK: 
						continue
					users[menuitem][6] = comment
				elif menuitem2 == _(u"Delete"):
					#Reset the Yes/No buttons
					self._d.add_persistent_args(["--yes-label", _(u"Yes")])
					self._d.add_persistent_args(["--no-label", _(u"No")])
					if self._d.yesno(_(u"Are you sure you want to delete the user %s ?") % menuitem) == self._DLG_YES:
						del users[menuitem]
						break
	
	def save_install_profile(self, xmlfilename="", askforfilename=True):
		#Reset the Yes/No buttons
		self._d.add_persistent_args(["--yes-label", _(u"Yes")])
		self._d.add_persistent_args(["--no-label", _(u"No")])
		if self._d.yesno(_(u"Would you like to save these install settings for use again later?")) == self._DLG_YES:
			code = 0
			filename = xmlfilename
			if askforfilename:
				code, filename = self._d.inputbox(_(u"Enter a filename for the XML file. Use full path!"), init=xmlfilename)
				if code != self._DLG_OK or not filename: 
					return None
			if GLIUtility.is_file(filename):
				if not self._d.yesno(_(u"The file %s already exists. Do you want to overwrite it?") % filename) == self._DLG_YES:
					return None
			try:
				configuration = open(filename ,"w")
				configuration.write(self._install_profile.serialize())
				configuration.close()
			except:
				self._d.msgbox(_(u"Error.  File couldn't be saved.  Saving to /tmp/installprofile.xml instead."))
		else:
			filename = "/tmp/installprofile.xml"
		try:
			configuration = open("/tmp/installprofile.xml", "w")
			configuration.write(self._install_profile.serialize())
			configuration.close()
		except:
			self._d.msgbox(_(u"Complete failure to save install profile!"))
		return filename	

############ RUN PHASE FUNCTIONS ############
	def run_phase1(self):
		self.set_arch_template()
		self.set_verbose()
		self.set_client_networking()
		self.set_enable_ssh()
		self.set_livecd_password()
		self.set_client_kernel_modules()
	def run_phase2(self):
		self.set_partitions()
		self.set_mounts()
		self.set_network_mounts()
		self.try_steps(['mount_local_partitions','mount_network_shares'])
	def run_phase3(self):
		self.set_install_stage()
		self.set_portage_tree()
		self.try_steps(['unpack_stage_tarball', 'update_config_files', 'configure_make_conf','prepare_chroot','install_portage_tree'])
	def run_phase4(self):
		self.set_make_conf()
		self.set_etc_portage()
		self.set_distcc()
		self.try_steps(['update_config_files', 'configure_make_conf', 'stage1', 'stage2', 'install_distcc'])
		
		self.set_root_password()
		self.set_timezone()
		self.try_steps(['set_root_password','set_timezone'])
		
		self.set_kernel()
		self.try_steps(['emerge_kernel_sources','build_kernel'])
		
		self.set_networking()
		self.try_steps(['setup_network_post'])
		
		if self.advanced_mode:
			self.set_cron_daemon()
			self.set_logger()
		self.try_steps(['install_logging_daemon','install_cron_daemon','install_filesystem_tools'])
		
		self.set_boot_loader()
		self.try_steps(['install_bootloader','setup_and_run_bootloader'])
		
		self.set_additional_users()
		self.try_steps(['set_users'])
		
		self.set_extra_packages()
		if self.advanced_mode:
			self.set_services()
			self.set_rc_conf()
			
		#Save the profile
		self.save_install_profile()
		
		self.try_steps(['update_config_files','install_mta','install_packages','set_services','run_post_install_script','finishing_cleanup'])

		

	
	def run_phase5(self):
		#test function for getting steps.
		steps = ['do_recommended_partitioning',
			'mount_local_partitions',
			'mount_network_shares',
			'unpack_stage_tarball',
			'update_config_files',
			'configure_make_conf',
			'prepare_chroot',
			'install_portage_tree',
			'stage1',
			'stage2',
			'set_root_password',
			'set_timezone',
			'emerge_kernel_sources',
			'build_kernel',
			'install_distcc',
			'install_mta',
			'install_logging_daemon',
			'install_cron_daemon',
			'install_filesystem_tools',
			'setup_network_post',
			'install_bootloader',
			'setup_and_run_bootloader',
			'update_config_files',
			'set_users',
			'install_packages',
			# services for startup need to come after installing extra packages
			# otherwise some of the scripts will not exist.
			'set_services',
			'run_post_install_script',
			'finishing_cleanup']

		self.try_steps(steps)
	
	def finish_up(self):
		self._d.gauge_update(100, _(u"Install completed!"), update_text=1)
		self._d.gauge_stop()
		print _(u"Install done!")
		sys.exit(0)	
	
	def try_steps(self, steps):
		try:
			self.do_steps(steps)
			sys.stderr.write('\07')  #BEEP
		except GLIException.GLIException, e:
			sys.stderr.write('\07')  #BEEP
			error = e.get_error_msg()
			self.handle_exception(error,steps)
	
	def handle_exception(self, error, steps):
		#Reset the Yes/No labels.
		self._d.add_persistent_args(["--yes-label", _(u"Yes")])
		self._d.add_persistent_args(["--no-label",_(u"No")])
		message = _(u"There was an Exception received during the install that is outside of the normal install errors.  This is a bad thing. The error was: %s \n  You have several ways of handling this.  If you cannot resolve it, please submit a bug report (after searching to make sure it's not a known issue and verifying you didn't do something stupid) with the contents of /var/log/install.log and /tmp/installprofile.xml and the version of the installer you used." % str(error))
		#options: 1. drop to console and retry  2. retry.  3. restart the phase  4. clean up and exit  5. don't clean up and exit.
		choices = ['Drop to console and then retry on return.',
			'Just retry the step.',
			#'Go back and change your choices.',
			'Clean up (unmount partitions) and exit.',
			'Just exit']
		code, choice = self._d.menu(message,choices=self._dmenu_list_to_choices(choices), width=77, height=22)
		if code == self._DLG_CANCEL:
			sys.exit(0)
		choice = choices[int(choice)-1]
		if choice == 'Drop to console and then retry on return.':
			GLIUtility.spawn_bash()
			self.try_steps(steps)
		elif choice == 'Just retry the step.':
			self.try_steps(steps)  #Not sure if this will leave me in a bad spot.
		elif choice == 'Go back and change your choices.':	
			sys.exit(0)
		elif choice == 'Clean up (unmount partitions) and exit.':
			self.do_steps(['install_failed_cleanup'])
			configuration = open("/tmp/installprofile.xml", "w")
			configuration.write(self._install_profile.serialize())
			configuration.close()
			sys.exit(0)
		else: #just exit
			configuration = open("/tmp/installprofile.xml", "w")
			configuration.write(self._install_profile.serialize())
			configuration.close()
			sys.exit(0)

	def do_steps(self, install_steps):	
		#Start the rest of the installation
		# INSTALLATION TIME
#		current_item = 0
#		self._cc.set_install_profile(self._install_profile)
		install_steps = list(install_steps)
#		self._cc.start_install()
		if self.just_starting == 1:
			self._d.gauge_start(_(u"Installation Started!"), title=_(u"Installation progress"), height="10")
			self.just_starting = 0
		else:
			self._d.gauge_start(_(u"Continuing Installation"), title=_(u"Installation progress"), height="10")
		self.num_steps_completed = 1
		self.num_steps = len(install_steps)
		step_name = install_steps.pop(0)
		next_step = self._cc.get_step_info(step_name)
		self._cc.run_step(step_name)
		i = 0
		while 1:
			notification = self._cc.getNotification()
			if notification == None:
				time.sleep(1)
				continue
			type_r = notification.get_type()
			data = notification.get_data()
			if type_r == "exception":
				#We need to raise an exception here.  This will hopefully be caught by the calling function in a try/except block so that they can decide how best to handle this.
				raise GLIException.GLIException("DoStepFailure",'fatal','do_steps',str(data))
			elif type_r == "progress":
				#SECONDARY UPDATIN' GOIN ON IN HERE
				diff = (data[0]*100)/self.num_steps
				self._d.gauge_update(i+diff, _(u"On step %(A)d of %(B)d. Current step: %(C)s\n%(D)s" % {'A': self.num_steps_completed, 'B': self.num_steps, 'C': next_step, 'D': data[1]}), update_text=1)
			elif type_r == "int":
				if data == GLIClientController.NEXT_STEP_READY:
					if len(install_steps):
						step_name = install_steps.pop(0)
					else:
						return
					#print "Step name: " + step_name
					next_step = self._cc.get_step_info(step_name)
#					num_steps = self._cc.get_num_steps()
					i = (self.num_steps_completed*100)/self.num_steps
					self._d.gauge_update(i, _(u"On step %(A)d of %(B)d. Current step: %(C)s" % {'A': self.num_steps_completed, 'B': self.num_steps, 'C': next_step}), update_text=1)
					self.num_steps_completed += 1
					#print "Next step: " + next_step
					#if self._cc.has_more_steps():
					self._cc.run_step(step_name)
					continue

# --------------------------End of functions------------------------
# --------------------------Beginning of MAIN-----------------------
if __name__ == '__main__':


	#d = dialog.Dialog()

	gli = GLIDialog()
	
	gli.show_welcome_screen()
	gli.ask_load_profile()
	#gli.ask_advanced_mode() -- Disabled.  Standard mode now forced.
	gli.ask_networkless() #  This is now forced.
	

	gli.run_phase1()  #Set up networking
	gli.run_phase2()  #Do partitioning
	gli.run_phase3()  #Install stage tarball and portage
	gli.run_phase4()  #Do everything else

	gli.finish_up()

	sys.exit(0)
#########################End of main#################################