1#! /bin/sh
2#
3# This script is used to configure the linux kernel.
4#
5# It was inspired by a desire to not have to hit <enter> 9 million times
6# or startup the X server just to change a single kernel parameter.
7#
8# This script attempts to parse the configuration files, which are
9# scattered throughout the kernel source tree, and creates a temporary
10# set of mini scripts which are in turn used to create nested menus and
11# radiolists.
12#
13# It uses a very modified/mutilated version of the "dialog" utility
14# written by Savio Lam (lam836@cs.cuhk.hk). Savio is not responsible
15# for this script or the version of dialog used by this script.
16# Please do not contact him with questions. The official version of
17# dialog is available at sunsite.unc.edu or a sunsite mirror.
18#
19# Portions of this script were borrowed from the original Configure
20# script.
21#
22# William Roadcap was the original author of Menuconfig.
23# Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
24#
25# 070497 Bernhard Kaindl (bkaindl@netway.at) - get default values for
26# new bool, tristate and dep_tristate parameters from the defconfig file.
27# new configuration parameters are marked with '(NEW)' as in make config.
28#
29# 180697 Bernhard Kaindl (bkaindl@netway.at) - added the needed support
30# for string options. They are handled like the int and hex options.
31#
32# 081297 Pavel Machek (pavel@atrey.karlin.mff.cuni.cz) - better error
33# handling
34#
35# 131197 Michael Chastain (mec@shout.net) - output all lines for a
36# choice list, not just the selected one.  This makes the output
37# the same as Configure output, which is important for smart config
38# dependencies.
39#
40# 101297 Michael Chastain (mec@shout.net) - remove sound driver cruft.
41#
42# 221297 Michael Chastain (mec@shout.net) - make define_bool actually
43# define its arguments so that later tests on them work right.
44#
45# 160198 Michael Chastain (mec@shout.net) - fix bug with 'c' command
46# (complement existing value) when used on virgin uninitialized variables.
47#
48# 090398 Axel Boldt (boldt@math.ucsb.edu) - allow for empty lines in help
49# texts.
50#
51# 12 Dec 1998, Michael Elizabeth Chastain (mec@shout.net)
52# Remove a /tmp security hole in get_def (also makes it faster).
53# Give uninitialized variables canonical values rather than null value.
54# Change a lot of places to call set_x_info uniformly.
55# Take out message about preparing version (old sound driver cruft).
56#
57# 13 Dec 1998, Riley H Williams <Riley@Williams.Name>
58# When an error occurs, actually display the error message as well as
59# our comments thereon.
60#
61# 31 Dec 1998, Michael Elizabeth Chastain (mec@shout.net)
62# Fix mod_bool to honor $CONFIG_MODULES.
63# Fix dep_tristate to call define_bool when dependency is "n".
64#
65# 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
66# Blow away lxdialog.scrltmp on entry to activate_menu.  This protects
67# against people who use commands like ' ' to select menus.
68#
69# 24 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
70# - Improve the exit message (Jeff Ronne).
71#
72# 06 July 1999, Andrzej M. Krzysztofowicz, <ankry@mif.pg.gda.pl>
73# - Support for multiple conditions in dep_tristate().
74# - Implemented new functions: define_tristate(), define_int(), define_hex(),
75#   define_string(), dep_bool().
76#
77# 12 November 2001, Keith Owens <kaos@ocs.com.au>
78# Escape double quotes on eval so the quotes are still there on the second
79# evaluation, required to handle strings with special characters.
80#
81
82
83#
84# Change this to TRUE if you prefer all kernel options listed
85# in a single menu rather than the standard menu hierarchy.
86#
87single_menu_mode=
88
89#
90# Make sure we're really running bash.
91#
92[ -z "$BASH" ] && { echo "Menuconfig requires bash" 1>&2; exit 1; }
93
94#
95# Cache function definitions, turn off posix compliance
96#
97set -h +o posix
98
99
100
101# Given a configuration variable, set the global variable $x to its value,
102# and the global variable $info to the string " (NEW)" if this is a new
103# variable.
104#
105# This function looks for: (1) the current value, or (2) the default value
106# from the arch-dependent defconfig file, or (3) a default passed by the caller.
107
108function set_x_info () {
109    eval x=\$$1
110    if [ -z "$x" ]; then
111	eval `sed -n -e 's/# \(.*\) is not set.*/\1=n/' -e "/^$1=/p" arch/$ARCH/defconfig`
112	eval x=\${$1:-\"$2\"}
113	eval $1=$x
114	eval INFO_$1="' (NEW)'"
115    fi
116    eval info=\"\$INFO_$1\"
117}
118
119#
120# Load the functions used by the config.in files.
121#
122# I do this because these functions must be redefined depending
123# on whether they are being called for interactive use or for
124# saving a configuration to a file.
125#
126# Thank the heavens bash supports nesting function definitions.
127#
128load_functions () {
129
130#
131# Additional comments
132#
133function comment () {
134	comment_ctr=$[ comment_ctr + 1 ]
135	echo -ne "': $comment_ctr' '--- $1' " >>MCmenu
136}
137
138#
139# Define a boolean to a specific value.
140#
141function define_bool () {
142	eval $1=$2
143}
144
145function define_tristate () {
146	eval $1=$2
147}
148
149function define_hex () {
150	eval $1=$2
151}
152
153function define_int () {
154	eval $1=$2
155}
156
157function define_string () {
158	eval $1=\"$2\"
159}
160
161#
162# Create a boolean (Yes/No) function for our current menu
163# which calls our local bool function.
164#
165function bool () {
166	set_x_info "$2" "n"
167
168	case $x in
169	y|m)	flag="*" ;;
170	n)	flag=" " ;;
171	esac
172
173	echo -ne "'$2' '[$flag] $1$info' " >>MCmenu
174
175	echo -e "function $2 () { l_bool '$2' \"\$1\" ;}\n" >>MCradiolists
176}
177
178#
179# Create a tristate (Yes/No/Module) radiolist function
180# which calls our local tristate function.
181#
182# Collapses to a boolean (Yes/No) if module support is disabled.
183#
184function tristate () {
185	if [ "$CONFIG_MODULES" != "y" ]
186	then
187		bool "$1" "$2"
188	else
189		set_x_info "$2" "n"
190
191		case $x in
192		y) flag="*" ;;
193		m) flag="M" ;;
194		*) flag=" " ;;
195		esac
196
197		echo -ne "'$2' '<$flag> $1$info' " >>MCmenu
198
199		echo -e "
200		function $2 () { l_tristate '$2' \"\$1\" ;}" >>MCradiolists
201	fi
202}
203
204#
205# Create a tristate radiolist function which is dependent on
206# another kernel configuration option.
207#
208# Quote from the original configure script:
209#
210#       If the option we depend upon is a module,
211#       then the only allowable options are M or N.  If Y, then
212#       this is a normal tristate.  This is used in cases where modules
213#       are nested, and one module requires the presence of something
214#       else in the kernel.
215#
216function dep_tristate () {
217	ques="$1"
218	var="$2"
219	dep=y
220	shift 2
221	while [ $# -gt 0 ]; do
222		if   [ "$1" = y ]; then
223			shift
224		elif [ "$1" = m ]; then
225			dep=m
226			shift
227		else
228			dep=n
229			shift $#
230		fi
231	done
232	if [ "$dep" = y ]; then
233	    tristate "$ques" "$var"
234	elif [ "$dep" = m ]; then
235	    mod_bool "$ques" "$var"
236	else
237	    define_tristate "$var" n
238	fi
239}
240
241#
242#   Same as above, but now only Y and N are allowed as dependency
243#   (i.e. third and next arguments).
244#
245function dep_bool () {
246	ques="$1"
247	var="$2"
248	dep=y
249	shift 2
250	while [ $# -gt 0 ]; do
251		if [ "$1" = y ]; then
252			shift
253		else
254			dep=n
255			shift $#
256		fi
257	done
258	if [ "$dep" = y ]; then
259	    bool "$ques" "$var"
260	else
261	    define_bool "$var" n
262	fi
263}
264
265function dep_mbool () {
266	ques="$1"
267	var="$2"
268	dep=y
269	shift 2
270	while [ $# -gt 0 ]; do
271		if [ "$1" = y -o "$1" = m ]; then
272			shift
273		else
274			dep=n
275			shift $#
276		fi
277	done
278	if [ "$dep" = y ]; then
279	    bool "$ques" "$var"
280	else
281	    define_bool "$var" n
282	fi
283}
284
285#
286# Add a menu item which will call our local int function.
287#
288function int () {
289	set_x_info "$2" "$3"
290
291	echo -ne "'$2' '($x) $1$info' " >>MCmenu
292
293	echo -e "function $2 () { l_int '$1' '$2' '$3' '$x' ;}" >>MCradiolists
294}
295
296#
297# Add a menu item which will call our local hex function.
298#
299function hex () {
300	set_x_info "$2" "$3"
301	x=${x##*[x,X]}
302
303	echo -ne "'$2' '($x) $1$info' " >>MCmenu
304
305	echo -e "function $2 () { l_hex '$1' '$2' '$3' '$x' ;}" >>MCradiolists
306}
307
308#
309# Add a menu item which will call our local string function.
310#
311function string () {
312	set_x_info "$2" "$3"
313
314	echo -ne "'$2' '     $1: \"$x\"$info' " >>MCmenu
315
316	echo -e "function $2 () { l_string '$1' '$2' '$3' '$x' ;}" >>MCradiolists
317}
318
319#
320# Add a menu item which will call our local One-of-Many choice list.
321#
322function choice () {
323	#
324	# Need to remember params cause they're gonna get reset.
325	#
326	title=$1
327	choices=$2
328	default=$3
329	current=
330
331	#
332	# Find out if one of the choices is already set.
333	# If it's not then make it the default.
334	#
335	set -- $choices
336	firstchoice=$2
337
338	while [ -n "$2" ]
339	do
340		if eval [ \"_\$$2\" = \"_y\" ]
341		then
342			current=$1
343			break
344		fi
345		shift ; shift
346	done
347
348	: ${current:=$default}
349
350	echo -ne "'$firstchoice' '($current) $title' " >>MCmenu
351
352	echo -e "
353	function $firstchoice () \
354		{ l_choice '$title' \"$choices\" \"$current\" ;}" >>MCradiolists
355}
356
357} # END load_functions()
358
359
360
361
362
363#
364# Extract available help for an option from Configure.help
365# and send it to standard output.
366#
367# Most of this function was borrowed from the original kernel
368# Configure script.
369#
370function extract_help () {
371  if [ -f Documentation/Configure.help ]
372  then
373     #first escape regexp special characters in the argument:
374     var=$(echo "$1"|sed 's/[][\/.^$*]/\\&/g')
375     #now pick out the right help text:
376     text=$(sed -n "/^$var[ 	]*\$/,\${
377                        /^$var[ 	]*\$/c\\
378${var}:\\
379
380                        /^#/b
381                        /^[^ 	]/q
382                        s/^  //
383			/<file:\\([^>]*\\)>/s//\\1/g
384                        p
385                    }" Documentation/Configure.help)
386
387     if [ -z "$text" ]
388     then
389          echo "There is no help available for this kernel option."
390	  return 1
391     else
392	  echo "$text"
393     fi
394  else
395	 echo "There is no help available for this kernel option."
396         return 1
397  fi
398}
399
400#
401# Activate a help dialog.
402#
403function help () {
404	if extract_help $1 >help.out
405	then
406		$DIALOG	--backtitle "$backtitle" --title "$2"\
407			--textbox help.out $ROWS $COLS
408	else
409		$DIALOG	--backtitle "$backtitle" \
410			--textbox help.out $ROWS $COLS
411	fi
412	rm -f help.out
413}
414
415#
416# Show the README file.
417#
418function show_readme () {
419	$DIALOG --backtitle "$backtitle" \
420		--textbox scripts/README.Menuconfig $ROWS $COLS
421}
422
423#
424# Begin building the dialog menu command and Initialize the
425# Radiolist function file.
426#
427function menu_name () {
428	echo -ne "$DIALOG --title '$1'\
429			--backtitle '$backtitle' \
430			--menu '$menu_instructions' \
431			$ROWS $COLS $((ROWS-10)) \
432			'$default' " >MCmenu
433	>MCradiolists
434}
435
436#
437# Add a submenu option to the menu currently under construction.
438#
439function submenu () {
440	echo -ne "'activate_menu $2' '$1  --->' " >>MCmenu
441}
442
443#
444# Handle a boolean (Yes/No) option.
445#
446function l_bool () {
447	if [ -n "$2" ]
448	then
449		case "$2" in
450		y|m)	eval $1=y ;;
451		c)	eval x=\$$1
452		   	case $x in
453		   	y) eval $1=n ;;
454		   	n) eval $1=y ;;
455			*) eval $1=y ;;
456		   	esac ;;
457		*)	eval $1=n ;;
458		esac
459	else
460		echo -ne "\007"
461	fi
462}
463
464#
465# Same as bool() except options are (Module/No)
466#
467function mod_bool () {
468	if [ "$CONFIG_MODULES" != "y" ]; then
469	    define_bool "$2" "n"
470	else
471	    set_x_info "$2" "n"
472
473	    case $x in
474	    y|m) flag='M' ;;
475	    *)   flag=' ' ;;
476	    esac
477
478	    echo -ne "'$2' '<$flag> $1$info' " >>MCmenu
479
480	    echo -e "function $2 () { l_mod_bool '$2' \"\$1\" ;}" >>MCradiolists
481	fi
482}
483
484#
485# Same as l_bool() except options are (Module/No)
486#
487function l_mod_bool() {
488	if [ -n "$2" ]
489	then
490		case "$2" in
491		y)	echo -en "\007"
492			${DIALOG} --backtitle "$backtitle" \
493				  --infobox "\
494This feature depends on another which has been configured as a module.  \
495As a result, this feature will be built as a module." 4 70
496			sleep 5
497			eval $1=m ;;
498		m)	eval $1=m ;;
499		c)	eval x=\$$1
500			case $x in
501			m) eval $1=n ;;
502			n) eval $1=m ;;
503			*) eval $1=m ;;
504			esac ;;
505		*)	eval $1=n ;;
506		esac
507	else
508		echo -ne "\007"
509	fi
510}
511
512#
513# Handle a tristate (Yes/No/Module) option.
514#
515function l_tristate () {
516	if [ -n "$2" ]
517	then
518		eval x=\$$1
519
520		case "$2" in
521		y) eval $1=y ;;
522		m) eval $1=m ;;
523		c) eval x=\$$1
524		   case $x in
525		   y) eval $1=n ;;
526		   n) eval $1=m ;;
527		   m) eval $1=y ;;
528		   *) eval $1=y ;;
529		   esac ;;
530		*) eval $1=n ;;
531		esac
532	else
533		echo -ne "\007"
534	fi
535}
536
537#
538# Create a dialog for entering an integer into a kernel option.
539#
540function l_int () {
541	while true
542	do
543		if $DIALOG --title "$1" \
544			--backtitle "$backtitle" \
545			--inputbox "$inputbox_instructions_int" \
546			10 75 "$4" 2>MCdialog.out
547		then
548			answer="`cat MCdialog.out`"
549			answer="${answer:-$3}"
550
551			# Semantics of + and ? in GNU expr changed, so
552			# we avoid them:
553			if expr "$answer" : '0$' '|' "$answer" : '[1-9][0-9]*$' '|' "$answer" : '-[1-9][0-9]*$' >/dev/null
554			then
555				eval $2=\"$answer\"
556			else
557				eval $2=\"$3\"
558				echo -en "\007"
559				${DIALOG} --backtitle "$backtitle" \
560					--infobox "You have made an invalid entry." 3 43
561				sleep 2
562			fi
563
564			break
565		fi
566
567		help "$2" "$1"
568	done
569}
570
571#
572# Create a dialog for entering a hexadecimal into a kernel option.
573#
574function l_hex () {
575	while true
576	do
577		if $DIALOG --title "$1" \
578			--backtitle "$backtitle" \
579			--inputbox "$inputbox_instructions_hex" \
580			10 75 "$4" 2>MCdialog.out
581		then
582			answer="`cat MCdialog.out`"
583			answer="${answer:-$3}"
584			answer="${answer##*[x,X]}"
585
586			if expr "$answer" : '[0-9a-fA-F][0-9a-fA-F]*$' >/dev/null
587			then
588				eval $2=\"$answer\"
589			else
590				eval $2=\"$3\"
591				echo -en "\007"
592				${DIALOG} --backtitle "$backtitle" \
593					--infobox "You have made an invalid entry." 3 43
594				sleep 2
595			fi
596
597			break
598		fi
599
600		help "$2" "$1"
601	done
602}
603
604#
605# Create a dialog for entering a string into a kernel option.
606#
607function l_string () {
608	while true
609	do
610		if $DIALOG --title "$1" \
611			--backtitle "$backtitle" \
612			--inputbox "$inputbox_instructions_string" \
613			10 75 "$4" 2>MCdialog.out
614		then
615			answer="`cat MCdialog.out`"
616			answer="${answer:-$3}"
617
618			#
619			# Someone may add a nice check for the entered
620			# string here...
621			#
622			eval $2=\"$answer\"
623
624			break
625		fi
626
627		help "$2" "$1"
628	done
629}
630
631
632#
633# Handle a one-of-many choice list.
634#
635function l_choice () {
636	#
637	# Need to remember params cause they're gonna get reset.
638	#
639	title="$1"
640	choices="$2"
641	current="$3"
642        chosen=
643
644	#
645	# Scan current value of choices and set radiolist switches.
646	#
647	list=
648	set -- $choices
649	firstchoice=$2
650	while [ -n "$2" ]
651	do
652		case "$1" in
653		"$current"*)	if [ -z "$chosen" ]; then
654					list="$list $2 $1 ON "
655					chosen=1
656				else
657					list="$list $2 $1 OFF "
658				fi  ;;
659		*)		list="$list $2 $1 OFF " ;;
660		esac
661
662		shift ; shift
663	done
664
665	while true
666	do
667		if $DIALOG --title "$title" \
668			--backtitle "$backtitle" \
669			--radiolist "$radiolist_instructions" \
670			15 70 6 $list 2>MCdialog.out
671		then
672			choice=`cat MCdialog.out`
673			break
674		fi
675
676		help "$firstchoice" "$title"
677	done
678
679	#
680	# Now set the boolean value of each option based on
681	# the selection made from the radiolist.
682	#
683	set -- $choices
684	while [ -n "$2" ]
685	do
686		if [ "$2" = "$choice" ]
687		then
688			eval $2=\"y\"
689		else
690			eval $2=\"n\"
691		fi
692
693		shift ; shift
694	done
695}
696
697#
698# Call awk, and watch for error codes, etc.
699#
700function callawk () {
701awk "$1" || { echo "Awk died with error code $?. Giving up."; exit 1; }
702}
703
704#
705# A faster awk based recursive parser. (I hope)
706#
707function parser1 () {
708callawk '
709BEGIN {
710	menu_no = 0
711	comment_is_option = 0
712	parser("'$CONFIG_IN'","MCmenu0")
713}
714
715function parser(ifile,menu) {
716
717	while ((getline <ifile) > 0) {
718		if ($1 == "mainmenu_option") {
719			comment_is_option = "1"
720		}
721		else if ($1 == "comment" && comment_is_option == "1") {
722			comment_is_option= "0"
723			sub($1,"",$0)
724			++menu_no
725
726			printf("submenu %s MCmenu%s\n", $0, menu_no) >>menu
727
728			newmenu = sprintf("MCmenu%d", menu_no);
729			printf( "function MCmenu%s () {\n"\
730				"default=$1\n"\
731				"menu_name %s\n",\
732				 menu_no, $0) >newmenu
733
734			parser(ifile, newmenu)
735		}
736		else if ($0 ~ /^#|\$MAKE|mainmenu_name/) {
737			printf("") >>menu
738		}
739		else if ($1 ~ "endmenu") {
740			printf("}\n") >>menu
741			return
742		}
743		else if ($1 == "source") {
744			parser($2,menu)
745		}
746		else {
747			print >>menu
748		}
749	}
750}'
751}
752
753#
754# Secondary parser for single menu mode.
755#
756function parser2 () {
757callawk '
758BEGIN {
759	parser("'$CONFIG_IN'","MCmenu0")
760}
761
762function parser(ifile,menu) {
763
764	while ((getline <ifile) > 0) {
765		if ($0 ~ /^#|$MAKE|mainmenu_name/) {
766			printf("") >>menu
767		}
768		else if ($1 ~ /mainmenu_option|endmenu/) {
769			printf("") >>menu
770		}
771		else if ($1 == "source") {
772			parser($2,menu)
773		}
774		else {
775			print >>menu
776		}
777	}
778}'
779}
780
781#
782# Parse all the config.in files into mini scripts.
783#
784function parse_config_files () {
785	rm -f MCmenu*
786
787	echo "function MCmenu0 () {" >MCmenu0
788	echo 'default=$1' >>MCmenu0
789	echo "menu_name 'Main Menu'" >>MCmenu0
790
791	if [ "_$single_menu_mode" = "_TRUE" ]
792	then
793		parser2
794	else
795		parser1
796	fi
797
798	echo "comment ''"	>>MCmenu0
799	echo "g_alt_config" 	>>MCmenu0
800	echo "s_alt_config" 	>>MCmenu0
801
802	echo "}" >>MCmenu0
803
804	#
805	# These mini scripts must be sourced into the current
806	# environment in order for all of this to work.  Leaving
807	# them on the disk as executables screws up the recursion
808	# in activate_menu(), among other things.  Once they are
809	# sourced we can discard them.
810	#
811	for i in MCmenu*
812	do
813		echo -n "."
814		source ./$i
815	done
816	rm -f MCmenu*
817}
818
819#
820# This is the menu tree's bootstrap.
821#
822# Executes the parsed menus on demand and creates a set of functions,
823# one per configuration option.  These functions will in turn execute
824# dialog commands or recursively call other menus.
825#
826function activate_menu () {
827	rm -f lxdialog.scrltmp
828	while true
829	do
830		comment_ctr=0		#So comment lines get unique tags
831
832		$1 "$default" 2> MCerror #Create the lxdialog menu & functions
833
834		if [ "$?" != "0" ]
835		then
836			clear
837			cat <<EOM
838
839Menuconfig has encountered a possible error in one of the kernel's
840configuration files and is unable to continue.  Here is the error
841report:
842
843EOM
844			sed 's/^/ Q> /' MCerror
845			cat <<EOM
846
847Please report this to the maintainer <mec@shout.net>.  You may also
848send a problem report to <linux-kernel@vger.kernel.org>.
849
850Please indicate the kernel version you are trying to configure and
851which menu you were trying to enter when this error occurred.
852
853EOM
854			cleanup
855			exit 1
856		fi
857		rm -f MCerror
858
859		. ./MCradiolists		#Source the menu's functions
860
861		. ./MCmenu 2>MCdialog.out	#Activate the lxdialog menu
862		ret=$?
863
864		read selection <MCdialog.out
865
866		case "$ret" in
867		0|3|4|5|6)
868			defaults="$selection$defaults"  #pseudo stack
869			case "$ret" in
870			0) eval $selection   ;;
871			3) eval $selection y ;;
872			4) eval $selection n ;;
873			5) eval $selection m ;;
874			6) eval $selection c ;;
875			esac
876			default="${defaults%%*}" defaults="${defaults#*}"
877			;;
878		2)
879			default="${selection%%\ *}"
880
881			case "$selection" in
882			*"-->"*|*"alt_config"*)
883				show_readme ;;
884			*)
885				eval help $selection ;;
886			esac
887			;;
888		255|1)
889			break
890			;;
891		139)
892			stty sane
893			clear
894			cat <<EOM
895
896There seems to be a problem with the lxdialog companion utility which is
897built prior to running Menuconfig.  Usually this is an indicator that you
898have upgraded/downgraded your ncurses libraries and did not remove the 
899old ncurses header file(s) in /usr/include or /usr/include/ncurses.
900
901It is VERY important that you have only one set of ncurses header files
902and that those files are properly version matched to the ncurses libraries 
903installed on your machine.
904
905You may also need to rebuild lxdialog.  This can be done by moving to
906the /usr/src/linux/scripts/lxdialog directory and issuing the 
907"make clean all" command.
908
909If you have verified that your ncurses install is correct, you may email
910the maintainer <mec@shout.net> or post a message to
911<linux-kernel@vger.kernel.org> for additional assistance. 
912
913EOM
914			cleanup
915			exit 139
916			;;
917		esac
918	done
919}
920
921#
922# Create a menu item to load an alternate configuration file.
923#
924g_alt_config () {
925	echo -n "get_alt_config 'Load an Alternate Configuration File' "\
926		>>MCmenu
927}
928
929#
930# Get alternate config file name and load the
931# configuration from it.
932#
933get_alt_config () {
934	set -f ## Switch file expansion OFF
935
936	while true
937	do
938		ALT_CONFIG="${ALT_CONFIG:-$DEFAULTS}"
939
940		$DIALOG --backtitle "$backtitle" \
941			--inputbox "\
942Enter the name of the configuration file you wish to load.  \
943Accept the name shown to restore the configuration you \
944last retrieved.  Leave blank to abort."\
945			11 55 "$ALT_CONFIG" 2>MCdialog.out
946
947		if [ "$?" = "0" ]
948		then
949			ALT_CONFIG=`cat MCdialog.out`
950
951			[ "_" = "_$ALT_CONFIG" ] && break
952
953			if eval [ -r \"$ALT_CONFIG\" ]
954			then
955				eval load_config_file \"$ALT_CONFIG\"
956				break
957			else
958				echo -ne "\007"
959				$DIALOG	--backtitle "$backtitle" \
960					--infobox "File does not exist!"  3 38
961				sleep 2
962			fi
963		else
964			cat <<EOM >help.out
965
966For various reasons, one may wish to keep several different kernel
967configurations available on a single machine.  
968
969If you have saved a previous configuration in a file other than the
970kernel's default, entering the name of the file here will allow you
971to modify that configuration.
972
973If you are uncertain, then you have probably never used alternate 
974configuration files.  You should therefor leave this blank to abort.
975
976EOM
977			$DIALOG	--backtitle "$backtitle"\
978				--title "Load Alternate Configuration"\
979				--textbox help.out $ROWS $COLS
980		fi
981	done
982
983	set +f ## Switch file expansion ON
984	rm -f help.out MCdialog.out
985}
986
987#
988# Create a menu item to store an alternate config file.
989#
990s_alt_config () {
991	echo -n "save_alt_config 'Save Configuration to an Alternate File' "\
992		 >>MCmenu
993}
994
995#
996# Get an alternate config file name and save the current
997# configuration to it.
998#
999save_alt_config () {
1000	set -f  ## Switch file expansion OFF
1001
1002	while true
1003	do
1004		$DIALOG --backtitle "$backtitle" \
1005			--inputbox "\
1006Enter a filename to which this configuration should be saved \
1007as an alternate.  Leave blank to abort."\
1008			10 55 "$ALT_CONFIG" 2>MCdialog.out
1009
1010		if [ "$?" = "0" ]
1011		then
1012			ALT_CONFIG=`cat MCdialog.out`
1013
1014			[ "_" = "_$ALT_CONFIG" ] && break
1015
1016			if eval touch $ALT_CONFIG 2>/dev/null
1017			then
1018				eval save_configuration $ALT_CONFIG
1019				load_functions  ## RELOAD
1020				break
1021			else
1022				echo -ne "\007"
1023				$DIALOG	--backtitle "$backtitle" \
1024					--infobox "Can't create file!  Probably a nonexistent directory." 3 60
1025				sleep 2
1026			fi
1027		else
1028			cat <<EOM >help.out
1029
1030For various reasons, one may wish to keep different kernel
1031configurations available on a single machine.  
1032
1033Entering a file name here will allow you to later retrieve, modify
1034and use the current configuration as an alternate to whatever 
1035configuration options you have selected at that time.
1036
1037If you are uncertain what all this means then you should probably
1038leave this blank.
1039EOM
1040			$DIALOG	--backtitle "$backtitle"\
1041				--title "Save Alternate Configuration"\
1042				--textbox help.out $ROWS $COLS
1043		fi
1044	done
1045
1046	set +f  ## Switch file expansion ON
1047	rm -f help.out MCdialog.out
1048}
1049
1050#
1051# Load config options from a file.
1052# Converts all "# OPTION is not set" lines to "OPTION=n" lines
1053#
1054function load_config_file () {
1055	awk '
1056	  /# .* is not set.*/ { printf("%s=n\n", $2) }
1057	! /# .* is not set.*/ { print }
1058	' $1 >.tmpconfig
1059
1060	source ./.tmpconfig
1061	rm -f .tmpconfig
1062}
1063
1064#
1065# Just what it says.
1066#
1067save_configuration () {
1068        echo
1069	echo -n "Saving your kernel configuration."
1070
1071	#
1072	# Now, let's redefine the configuration functions for final
1073	# output to the config files.
1074	#
1075	# Nested function definitions, YIPEE!
1076	#
1077	function bool () {
1078		set_x_info "$2" "n"
1079		eval define_bool \"$2\" \"$x\"
1080	}
1081
1082	function tristate () {
1083		set_x_info "$2" "n"
1084		eval define_tristate \"$2\" \"$x\"
1085	}
1086
1087	function dep_tristate () {
1088		set_x_info "$2" "n"
1089		var="$2"
1090		shift 2
1091		while [ $# -gt 0 ]; do
1092			if   [ "$1" = y ]; then
1093				shift
1094			elif [ "$1" = m -a "$x" != n ]; then
1095				x=m; shift
1096			else
1097				x=n; shift $#
1098			fi
1099		done
1100		define_tristate "$var" "$x"
1101	}
1102
1103	function dep_bool () {
1104		set_x_info "$2" "n"
1105		var="$2"
1106		shift 2
1107		while [ $# -gt 0 ]; do
1108			if   [ "$1" = y ]; then
1109				shift
1110			else
1111				x=n; shift $#
1112			fi
1113		done
1114		define_bool "$var" "$x"
1115	}
1116
1117	function dep_mbool () {
1118		set_x_info "$2" "n"
1119		var="$2"
1120		shift 2
1121		while [ $# -gt 0 ]; do
1122			if   [ "$1" = y -o "$1" = m ]; then
1123				shift
1124			else
1125				x=n; shift $#
1126			fi
1127		done
1128		define_bool "$var" "$x"
1129	}
1130
1131	function int () {
1132		set_x_info "$2" "$3"
1133		echo "$2=$x" 		>>$CONFIG
1134		echo "#define $2 ($x)"	>>$CONFIG_H
1135	}
1136
1137	function hex () {
1138		set_x_info "$2" "$3"
1139		echo "$2=$x" 			 >>$CONFIG
1140		echo "#define $2 0x${x##*[x,X]}" >>$CONFIG_H
1141	}
1142
1143	function string () {
1144		set_x_info "$2" "$3"
1145		echo "$2=\"$x\"" 			 >>$CONFIG
1146		echo "#define $2 \"$x\""	>>$CONFIG_H
1147	}
1148
1149	function define_hex () {
1150		eval $1=\"$2\"
1151               	echo "$1=$2"			>>$CONFIG
1152		echo "#define $1 0x${2##*[x,X]}"	>>$CONFIG_H
1153	}
1154
1155	function define_int () {
1156		eval $1=\"$2\"
1157		echo "$1=$2" 			>>$CONFIG
1158		echo "#define $1 ($2)"		>>$CONFIG_H
1159	}
1160
1161	function define_string () {
1162		eval $1=\"$2\"
1163		echo "$1=\"$2\""		>>$CONFIG
1164		echo "#define $1 \"$2\""	>>$CONFIG_H
1165	}
1166
1167	function define_bool () {
1168		define_tristate "$1" "$2"
1169	}
1170
1171	function define_tristate () {
1172		eval $1=\"$2\"
1173
1174   		case "$2" in
1175         	y)
1176                	echo "$1=y" 		>>$CONFIG
1177                	echo "#define $1 1"	>>$CONFIG_H
1178                	;;
1179
1180         	m)
1181			if [ "$CONFIG_MODULES" = "y" ]
1182			then
1183                		echo "$1=m"		   >>$CONFIG
1184                		echo "#undef  $1"	   >>$CONFIG_H
1185                		echo "#define $1_MODULE 1" >>$CONFIG_H
1186			else
1187                		echo "$1=y" 		>>$CONFIG
1188                		echo "#define $1 1"	>>$CONFIG_H
1189			fi
1190                	;;
1191
1192         	n)
1193			echo "# $1 is not set"	>>$CONFIG
1194                	echo "#undef  $1"	>>$CONFIG_H
1195                	;;
1196        	esac
1197	}
1198
1199	function choice () {
1200		#
1201		# Find the first choice that's already set to 'y'
1202		#
1203		choices="$2"
1204		default="$3"
1205		current=
1206		chosen=
1207
1208		set -- $choices
1209		while [ -n "$2" ]
1210		do
1211			if eval [ \"_\$$2\" = \"_y\" ]
1212			then
1213				current=$1
1214				break
1215			fi
1216			shift ; shift
1217		done
1218
1219		#
1220		# Use the default if none were set.
1221		#
1222		: ${current:=$default}
1223
1224		#
1225		# Output all choices (to be compatible with other configs).
1226		#
1227		set -- $choices
1228		while [ -n "$2" ]
1229		do
1230			case "$1" in
1231			"$current"*)	if [ -z "$chosen" ]; then
1232						define_bool "$2" "y"
1233						chosen=1
1234					else
1235						define_bool "$2" "n"
1236					fi ;;
1237			*)		define_bool "$2" "n" ;;
1238			esac
1239			shift ; shift
1240		done
1241	}
1242
1243	function mainmenu_name () {
1244		:
1245	}
1246
1247	function mainmenu_option () {
1248		comment_is_option=TRUE
1249	}
1250
1251	function endmenu () {
1252		:
1253	}
1254
1255	function comment () {
1256		if [ "$comment_is_option" ]
1257		then
1258			comment_is_option=
1259			echo        >>$CONFIG
1260			echo "#"    >>$CONFIG
1261			echo "# $1" >>$CONFIG
1262			echo "#"    >>$CONFIG
1263
1264			echo         >>$CONFIG_H
1265			echo "/*"    >>$CONFIG_H
1266			echo " * $1" >>$CONFIG_H
1267			echo " */"   >>$CONFIG_H
1268		fi
1269	}
1270
1271	echo -n "."
1272
1273	DEF_CONFIG="${1:-.config}"
1274	DEF_CONFIG_H="include/linux/autoconf.h"
1275
1276	CONFIG=.tmpconfig
1277	CONFIG_H=.tmpconfig.h
1278
1279	echo "#" >$CONFIG
1280	echo "# Automatically generated by make menuconfig: don't edit" >>$CONFIG
1281	echo "#" >>$CONFIG
1282
1283	echo "/*" >$CONFIG_H
1284	echo " * Automatically generated by make menuconfig: don't edit" >>$CONFIG_H
1285	echo " */" >>$CONFIG_H
1286	echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H
1287
1288	echo -n "."
1289	if . $CONFIG_IN >>.menuconfig.log 2>&1
1290	then
1291		if [ "$DEF_CONFIG" = ".config" ]
1292		then
1293			mv $CONFIG_H $DEF_CONFIG_H
1294		fi
1295
1296		if [ -f "$DEF_CONFIG" ]
1297		then
1298			rm -f ${DEF_CONFIG}.old
1299			mv $DEF_CONFIG ${DEF_CONFIG}.old
1300		fi
1301
1302		mv $CONFIG $DEF_CONFIG
1303
1304		return 0
1305	else
1306		return 1
1307	fi
1308}
1309
1310#
1311# Remove temporary files
1312#
1313cleanup () {
1314	cleanup1
1315	cleanup2
1316}
1317
1318cleanup1 () {
1319	rm -f MCmenu* MCradiolists MCdialog.out help.out
1320}
1321
1322cleanup2 () {
1323	rm -f .tmpconfig .tmpconfig.h
1324}
1325
1326set_geometry () {
1327	# Some distributions export these with incorrect values
1328	# which can really screw up some ncurses programs.
1329	LINES=  COLUMNS=
1330
1331	ROWS=${1:-24}  COLS=${2:-80}
1332
1333	# Just in case the nasty rlogin bug returns.
1334	#
1335	[ $ROWS = 0 ] && ROWS=24
1336	[ $COLS = 0 ] && COLS=80
1337
1338	if [ $ROWS -lt 19 -o $COLS -lt 80 ]
1339	then
1340		echo -e "\n\007Your display is too small to run Menuconfig!"
1341		echo "It must be at least 19 lines by 80 columns."
1342		exit 1
1343	fi
1344
1345	ROWS=$((ROWS-4))  COLS=$((COLS-5))
1346}
1347
1348
1349set_geometry `stty size 2>/dev/null`
1350
1351menu_instructions="\
1352Arrow keys navigate the menu.  \
1353<Enter> selects submenus --->.  \
1354Highlighted letters are hotkeys.  \
1355Pressing <Y> includes, <N> excludes, <M> modularizes features.  \
1356Press <Esc><Esc> to exit, <?> for Help.  \
1357Legend: [*] built-in  [ ] excluded  <M> module  < > module capable"
1358
1359radiolist_instructions="\
1360Use the arrow keys to navigate this window or \
1361press the hotkey of the item you wish to select \
1362followed by the <SPACE BAR>.
1363Press <?> for additional information about this option."
1364
1365inputbox_instructions_int="\
1366Please enter a decimal value. \
1367Fractions will not be accepted.  \
1368Use the <TAB> key to move from the input field to the buttons below it."
1369
1370inputbox_instructions_hex="\
1371Please enter a hexadecimal value. \
1372Use the <TAB> key to move from the input field to the buttons below it."
1373
1374inputbox_instructions_string="\
1375Please enter a string value. \
1376Use the <TAB> key to move from the input field to the buttons below it."
1377
1378DIALOG="./scripts/lxdialog/lxdialog"
1379
1380kernel_version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
1381
1382backtitle="Linux Kernel v$kernel_version Configuration"
1383
1384trap "cleanup ; exit 1" 1 2 15
1385
1386
1387#
1388# Locate default files.
1389#
1390CONFIG_IN=./config.in
1391if [ "$1" != "" ] ; then
1392	CONFIG_IN=$1
1393fi
1394
1395DEFAULTS=arch/$ARCH/defconfig
1396if [ -f .config ]; then
1397  DEFAULTS=.config
1398fi
1399
1400if [ -f $DEFAULTS ]
1401then
1402  echo "Using defaults found in" $DEFAULTS
1403  load_config_file $DEFAULTS
1404else
1405  echo "No defaults found"
1406fi
1407
1408
1409# Fresh new log.
1410>.menuconfig.log
1411
1412# Load the functions used by the config.in files.
1413echo -n "Preparing scripts: functions"
1414load_functions
1415
1416if [ ! -e $CONFIG_IN ]
1417then
1418	echo "Your main config.in file ($CONFIG_IN) does not exist"
1419	exit 1
1420fi
1421
1422if [ ! -x $DIALOG ]
1423then
1424	echo "Your lxdialog utility does not exist"
1425	exit 1
1426fi
1427
1428#
1429# Read config.in files and parse them into one shell function per menu.
1430#
1431echo -n ", parsing"
1432parse_config_files $CONFIG_IN
1433
1434echo "done."
1435#
1436# Start the ball rolling from the top.
1437#
1438activate_menu MCmenu0
1439
1440#
1441# All done!
1442#
1443cleanup1
1444
1445#
1446# Confirm and Save
1447#
1448if $DIALOG --backtitle "$backtitle" \
1449	   --yesno "Do you wish to save your new kernel configuration?" 5 60
1450then
1451	save_configuration
1452	echo
1453	echo
1454	echo "*** End of Linux kernel configuration."
1455	echo "*** Check the top-level Makefile for additional configuration."
1456	if [ ! -f .hdepend -o "$CONFIG_MODVERSIONS" = "y" ] ; then
1457	    echo "*** Next, you must run 'make dep'."
1458	else
1459	    echo "*** Next, you may run 'make bzImage', 'make bzdisk', or 'make install'."
1460	fi
1461	echo
1462else
1463	echo
1464    	echo
1465	echo Your kernel configuration changes were NOT saved.
1466	echo
1467fi
1468
1469# Remove log if empty.
1470if [ ! -s .menuconfig.log ] ; then
1471	rm -f .menuconfig.log
1472fi
1473
1474exit 0
1475