Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 23 Nov 2005 06:18:28 GMT
From:      soc-andrew <soc-andrew@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 87114 for review
Message-ID:  <200511230618.jAN6ISJV023288@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=87114

Change 87114 by soc-andrew@soc-andrew_serv on 2005/11/23 06:18:18

	Update the BSD Installer

Affected files ...

.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/install/220_format_disk.lua#3 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/network.lua#4 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/package.lua#4 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/storage.lua#4 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/target_system.lua#5 edit
.. //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/target_system_ui.lua#3 edit

Differences ...

==== //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/install/220_format_disk.lua#3 (text+ko) ====

@@ -1,12 +1,113 @@
--- $Id: 220_format_disk.lua,v 1.13 2005/10/05 21:29:03 cpressey Exp $
+-- $Id: 220_format_disk.lua,v 1.14 2005/10/12 00:50:12 cpressey Exp $
 
 --
 -- Allow the user to format the selected disk, if they so desire.
 --
 
+--
+-- Utility function which asks the user what geometry they'd like to use.
+--
+local select_geometry = function(step, dd)
+	local c_cyl, c_head, c_sec = dd:get_geometry()
+	local geom_msg = _(
+	    "The system is reports that the geometry of %s is\n\n"	..
+	    "%d cylinders, %d heads, %d sectors\n\n",
+	    dd:get_name(),
+	    dd:get_geometry_cyl(),
+	    dd:get_geometry_head(),
+	    dd:get_geometry_sec()
+	)
+	local valid_msg
+	if dd:is_geometry_bios_friendly() then
+		valid_msg = _(
+		    "This geometry should enable you to boot from "	..
+		    "this disk.  Unless you have a pressing reason "	..
+		    "to do otherwise, it is recommended that you use "	..
+		    "it.\n\n"
+		)
+	else
+		c_cyl, c_head, c_sec = dd:get_normalized_geometry()
+		valid_msg = _(
+		    "This geometry will NOT enable you to boot from "	..
+		    "this disk!  Unless you have a pressing reason "	..
+		    "to do otherwise, it is recommended that you use "	..
+		    "the following modified geometry:\n\n"		..
+		    "%d cylinders, %d heads, %d sectors\n\n",
+		    c_cyl, c_head, c_sec
+		)
+	end
+	local end_msg = _(
+	    "If you don't understand what any of this means, just "	..
+	    "select 'Use this Geometry' to continue."
+	)
+
+	local response = App.ui:present{
+	    id = "select_geometry",
+	    name = _("Select Geometry"),
+	    short_desc = geom_msg .. valid_msg .. end_msg,
+
+	    fields = {
+		{
+		    id = "cyl",
+		    name = _("Cylinders"),
+		    short_desc = _("Enter the number of cylinders in this disk's geometry")
+		},
+		{
+		    id = "head",
+		    name = _("Heads"),
+		    short_desc = _("Enter the number of heads in this disk's geometry")
+		},
+		{
+		    id = "sec",
+		    name = _("Sectors"),
+		    short_desc = _("Enter the number of sectors in this disk's geometry")
+		},
+	    },
+
+	    datasets = {
+		{
+		    cyl  = tostring(c_cyl),
+		    head = tostring(c_head),
+		    sec  = tonumber(c_sec)
+		}
+	    },
+
+	    actions = {
+		{
+		    id = "ok",
+		    name = _("Use this Geometry")
+		},
+		{
+		    id = "cancel",
+		    accelerator = "ESC",
+		    name = _("Return to %s", step:get_prev_name())
+		}
+	    }
+	}
+
+	if response.action_id == "ok" then
+		dd:set_geometry(
+		    tonumber(response.datasets[1].cyl),
+		    tonumber(response.datasets[1].head),
+		    tonumber(response.datasets[1].sec)
+		)
+		return true
+	else
+		return false
+	end
+end
+
+--
+-- Utility function which confirms that the user would like to proceed,
+-- and actually executes the formatting commands.
+--
 local format_disk = function(step, dd)
 	local cmds = CmdChain.new()
 
+	if not select_geometry(step, dd) then
+		return false
+	end
+
 	dd:cmds_format(cmds)
 
 	local confirm = function()

==== //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/network.lua#4 (text+ko) ====

@@ -1,4 +1,4 @@
--- $Id: network.lua,v 1.21 2005/09/02 22:07:53 cpressey Exp $
+-- $Id: network.lua,v 1.22 2005/11/10 16:38:02 cpressey Exp $
 -- Lua abstraction for the Network Interfaces of a system.
 
 --

==== //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/package.lua#4 (text+ko) ====

@@ -93,7 +93,7 @@
 	--
 	method.is_archived_on = function(ps, ts)
 		local filename = App.expand(
-		    "${root}${base}usr/ports/packages/All/${name}.${suffix}",
+		    "${root}${base}usr/packages/All/${name}.${suffix}",
 		    {
 			base = ts:get_base(),
 			name = name,
@@ -119,7 +119,7 @@
 		if self:is_archived_on(ts) then
 			cmd = App.expand(
 			    "${root}${TAR} -O -z -x -f " ..
-			      "${root}usr/ports/packages/All/${pkg_name}.${suffix} " ..
+			      "${root}usr/packages/All/${pkg_name}.${suffix} " ..
 			      "+CONTENTS | ${root}${GREP} '^@pkgdep'", {
 				base = ts:get_base(),
 				pkg_name = self:get_name(),
@@ -253,7 +253,7 @@
 		--
 		if self:is_archived_on(App.state.source) then
 			cmds:add(
-			    "${root}${CP} ${root}usr/ports/packages/All/${pkg_name}.${pkg_suffix} " .. 
+			    "${root}${CP} ${root}usr/packages/All/${pkg_name}.${pkg_suffix} " .. 
 			        "${root}${base}${pkg_tmp}/${pkg_name}.${pkg_suffix}"
 			)
 		else
@@ -485,7 +485,7 @@
 	--
 	method.enumerate_archived_on = function(self, ts)
 		self:enumerate_archives_in(
-		    App.expand("${root}${base}usr/ports/packages/All", {
+		    App.expand("${root}${base}usr/packages/All", {
 			base = ts:get_base()
 		    })
 		)

==== //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/storage.lua#4 (text+ko) ====

@@ -1,4 +1,4 @@
--- $Id: storage.lua,v 1.177 2005/10/05 20:27:40 cpressey Exp $
+-- $Id: storage.lua,v 1.182 2005/10/28 02:48:02 cpressey Exp $
 -- Storage Descriptors (a la libinstaller) in Lua.
 
 --
@@ -685,6 +685,46 @@
 		return sec
 	end
 
+	method.set_geometry = function(self, c, h, s)
+		cyl = c or cyl
+		head = h or head
+		sec = s or sec
+	end
+
+	--
+	-- Determine whether the geometry of the disk is "BIOS friendly"
+	-- or not, i.e., whether the C/H/S parameters are within the
+	-- limits of what is supported by legacy means of reading the
+	-- disk (int 13h), which are required during e.g. booting.
+	--
+	-- This is needed because sometimes the system reports a
+	-- geometry for an unformatted disk as having some number of
+	-- sectors per track, such as 255, that will not permit booting
+	-- from the BIOS.
+	--
+	-- XXX It is also possible that some systems require the number
+	-- of heads to be 16 or less, especially if they are set to
+	-- use "LBA" geometry translation.
+	--
+	method.is_geometry_bios_friendly = function(self)
+		return sec >= 1 and sec <= 63
+	end
+
+	--
+	-- Find a "BIOS-friendly" geometry that corresponds to the
+	-- capacity of this disk, so we can at least boot from it.
+	--
+	method.get_normalized_geometry = function(self)
+		--
+		-- Convert to something that the BIOS can boot from.
+		--
+		local sec = 63
+		local head = 255
+		local cyl = math.floor(capacity:in_units("S") / (sec * head))
+
+		return cyl, head, sec
+	end
+
 	--
 	-- Return the name of the device which handles this disk.
 	-- Note that, on all currently supported operating systems,
@@ -907,28 +947,89 @@
 	end
 
 	--
-	-- Create commands to format (create one big partition on) this disk.
+	-- Create commands to format this disk.  'Format' in this sense
+	-- means to create one big partition, and to install a partition
+	-- table with the appropriate information in it.
 	--
 	method.cmds_format = function(self, cmds)
 		self:cmds_ensure_dev(cmds)
 
 		--
-		-- Currently you need to pass 'yes' to OpenBSD's fdisk to
-		-- be able to do these.  (XXX this is a shot in the dark)
+		-- Initialize the disk.
+		--
+		cmds:add("${root}${FDISK} -I " ..
+		    self:get_raw_device_name())
+
+		--
+		-- Under more pleasant conditions, we could just
+		-- shell 'fdisk -BI' here and be done with it.
+		-- However, life is not that simple.  In order to
+		-- get fdisk to honour the geometry we have
+		-- selected, we need to create a fdisk script which
+		-- tells fdisk exactly the geometry of the disk and
+		-- the size of the partition we'd like to make.
+		--
+		cmds:add{
+		    cmdline = "${root}${ECHO} 'g c${cyl} h${head} s${sec}' >${tmp}format.fdisk",
+		    replacements = {
+			cyl = cyl,
+			head = head,
+			sec = sec
+		    }
+		}
+
+		--
+		-- Allot the first partition as taking up the entire disk,
+		-- assuming the given geometry.  This means that the part:
+		-- * has the default sysid (depends on the operating system);
+		-- * starts at the first track (after the zero'th track,)
+		-- * extends to the end of the disk.
+		--
+		cmds:add{
+		    cmdline = "${root}${ECHO} 'p 1 ${sysid} ${start} ${size}' >>${tmp}format.fdisk",
+		    replacements = {
+			sysid = App.conf.default_sysid,
+			start = sec,
+			size = (cyl * head * sec) - sec
+		    }
+		}
+
+		--
+		-- Mark the other partitions as unused.
+		-- Mark the first partition as the active one.
+		-- Send a copy of this script to the log, and make sure
+		-- the system knows that it should delete it when done.
+		--
+		cmds:add(
+		    "${root}${ECHO} 'p 2 0 0 0' >>${tmp}format.fdisk",
+		    "${root}${ECHO} 'p 3 0 0 0' >>${tmp}format.fdisk",
+		    "${root}${ECHO} 'p 4 0 0 0' >>${tmp}format.fdisk",
+		    "${root}${ECHO} 'a 1' >>${tmp}format.fdisk",
+		    "${root}${CAT} ${tmp}format.fdisk"
+		)
+		App.register_tmpfile("format.fdisk")
+
+		--
+		-- Execute the fdisk script.
 		--
-		if App.conf.os.name == "OpenBSD" then -- XXXXXX
-			cmds:add("${root}${ECHO} 'yes\nyes\nyes\n' | " ..
-			    "${root}${FDISK} -I " ..
-			    self:get_raw_device_name())
-			cmds:add("${root}${ECHO} 'yes\nyes\nyes\n' | " ..
-			    "${root}${FDISK} -B " ..
-			    self:get_raw_device_name())
+		if App.conf.os.name == "NetBSD" then -- XXXXXX
+			-- XXX Going to need to do this differently
 		else
-			cmds:add("${root}${FDISK} -I " ..
-			    self:get_raw_device_name())
-			cmds:add("${root}${YES} | ${root}${FDISK} -B " ..
-			    self:get_raw_device_name())
+			cmds:add("${root}${FDISK} -v -f ${tmp}format.fdisk " ..
+			    self:get_device_name())
 		end
+
+		--
+		-- Show the new state of the disk in the log.
+		--
+		cmds:add("${root}${FDISK} " ..
+		    self:get_device_name())
+
+		--
+		-- Make the disk bootable.
+		--
+		cmds:add("${root}${YES} | ${root}${FDISK} -B " ..
+		    self:get_raw_device_name())
 	end
 
 	--
@@ -1107,20 +1208,28 @@
 	end
 
 	--
-	-- Probe the (BIOS) geometry and the capacity of the disk.
-	-- Returns true, then the geometry (C, H, S,) then the capacity,
-	-- if all went well.  Returns nil and an error message if not.
+	-- Probe the (BIOS) geometry of the disk.
+	-- Returns three values: cylinder, head, and sec/trk, if all went well.
+	-- Returns nil values if all did not go well.
+	-- Capacity in sectors can then be calculated by C * H * S, or an error
+	-- can be flagged, by the caller of this function.
+	--
 	-- This is the FreeBSD/DragonFly version of this function.
 	--
 	local probe_geometry_freebsd = function(self)
-		local cyl, head, sec, capacity
+		local cyl, head, sec
 
 		--
-		-- Tell 'fdisk' to pretend to initialize the disk and
-		-- parse its output, to determine total # of sectors.
+		-- Tell 'fdisk' to give us the rundown of the disk.
+		-- Note that this does not use the 'summary' (-s)
+		-- feature of fdisk, because that feature has markedly
+		-- different behaviour when the disk is blank or
+		-- otherwise has an invalid boot sector: it fails
+		-- immediately.  Whereas we need it to provide at least
+		-- the geometry (even if the part table is ficticious.)
 		--
 		local cmd = App.expand(
-		    "${root}${FDISK} -t -I " .. self:get_raw_device_name()
+		    "${root}${FDISK} " .. self:get_raw_device_name()
 		)
 		local pty = Pty.Logged.open(cmd, App.log_string)
 		if not pty then
@@ -1128,53 +1237,43 @@
 		end
 		local line = pty:readline()
 		while line do
-			local found_size, len, start, size =
-			    string.find(line, "start%s*(%d+)%s*,%s*size%s*(%d+)")
-			if found_size then
-				capacity = Storage.Capacity.new(
-				    tonumber(start) + tonumber(size), "S"
-				)
-			end
-			local found_bios_geom =
-			    string.find(line, "^%s*parameters to be used for BIOS")
-			line = pty:readline()
-			if found_bios_geom then
+			if string.find(line, "^%s*parameters to be used for BIOS") then
 				--
 				-- Parse the line following.
 				--
+				line = pty:readline()
 				found, len, cyl, head, sec =
 				    string.find(line, "^%s*cylinders=(%d+)%s*heads=(%d+)%s*" ..
 						      "sectors/track=(%d+)")
-				cyl = tonumber(cyl)
-				head = tonumber(head)
-				sec = tonumber(sec)
-				found_bios_geom = false
+				if found then
+					cyl = tonumber(cyl)
+					head = tonumber(head)
+					sec = tonumber(sec)
+				end
+				line = pty:readline()
+			else
+				--
+				-- Keep looking...
+				--
 				line = pty:readline()
 			end
 		end
 		pty:close()
 
-		if not cyl or not head or not sec then
-			return nil, string.format(
-			    "could not determine geometry of disk '%s'", name
-			)
-		end
-		if not capacity then
-			return nil, string.format(
-			    "could not determine capacity of disk '%s'", name
-			)
-		end
-		return true, cyl, head, sec, capacity
+		return cyl, head, sec
 	end
 
 	--
-	-- Probe the (BIOS) geometry and the capacity of the disk.
-	-- Returns true, then the geometry (C, H, S,) then the capacity,
-	-- if all went well.  Returns nil and an error message if not.
+	-- Probe the (BIOS) geometry of the disk.
+	-- Returns three values: cylinder, head, and sec/trk, if all went well.
+	-- Returns nil values if all did not go well.
+	-- Capacity in sectors can then be calculated by C * H * S, or an error
+	-- can be flagged, by the caller of this function.
+	--
 	-- This is the NetBSD version of this function.
 	--
 	local probe_geometry_netbsd = function(self)
-		local cyl, head, sec, capacity
+		local cyl, head, sec
 
 		--
 		-- Call 'fdisk' and parse its output.
@@ -1188,13 +1287,6 @@
 		end
 		local line = pty:readline()
 		while line do
-			local found_size, len, size =
-			    string.find(line, "^%s*total%s*sectors:%s*(%d+)")
-			if found_size then
-				capacity = Storage.Capacity.new(
-				    tonumber(size), "S"
-				)
-			end
 			local found_bios_geom =
 			    string.find(line, "^%s*NetBSD%s*disklabel%s*disk%s*geometry")
 			line = pty:readline()
@@ -1214,17 +1306,7 @@
 		end
 		pty:close()
 
-		if not cyl or not head or not sec then
-			return nil, string.format(
-			    "could not determine geometry of disk '%s'", name
-			)
-		end
-		if not capacity then
-			return nil, string.format(
-			    "could not determine capacity of disk '%s'", name
-			)
-		end
-		return true, cyl, head, sec, capacity
+		return cyl, head, sec
 	end
 
 	local probe_partitions_freebsd = function(self)
@@ -1381,18 +1463,25 @@
 
 		local success
 		if App.conf.os.name == "NetBSD" then -- XXXXXX netbsd needs its own subclass here
-			success, cyl, head, sec, capacity =
+			cyl, head, sec =
 			    probe_geometry_netbsd(self)
 		else
-			success, cyl, head, sec, capacity =
+			cyl, head, sec =
 			    probe_geometry_freebsd(self)
 		end
 		
-		if not success then
-			App.log_warn(cyl) -- 'cyl' is the error message
+		if not cyl or not head or not sec then
+			App.log_warn(
+			    "could not determine geometry of disk '%s'", name
+			)
 			return false
 		end
 
+		--
+		-- Calculate disk's capacity from its geometry.
+		--
+		capacity = Storage.Capacity.new(cyl * head * sec, "S")
+
 		App.log("Disk " .. name .. " (" .. desc .. "): " ..
 			capacity:format() .. ": " ..
 			cyl .. "/" .. head .. "/" .. sec)

==== //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/target_system.lua#5 (text+ko) ====

@@ -413,9 +413,9 @@
 					dir = src
 				end
 				cmds:add{
-				    cmdline = "${root}${TAR} "	..
-					"-x -C ${root}${base}${dest} -f " ..
-					"${root}usr/${uname}/${dir}/${src}.${dist_suffix}",
+				    cmdline = "${root}${TAR} -f " ..
+					"${root}usr/${uname}/${dir}/${src}.${dist_suffix}" ..
+					"-x -C ${root}${base}${dest}"
 				    replacements = {
 					base = base,
 					src  = src,

==== //depot/projects/soc2005/bsdinstaller/src/contrib/bsdinstaller/backend/lua/lib/target_system_ui.lua#3 (text+ko) ====

@@ -1,4 +1,4 @@
--- $Id: target_system_ui.lua,v 1.15 2005/08/26 04:25:25 cpressey Exp $
+-- $Id: target_system_ui.lua,v 1.16 2005/10/12 00:43:51 cpressey Exp $
 
 --
 -- Copyright (c)2005 Chris Pressey.  All rights reserved.
@@ -49,579 +49,579 @@
 end
 
 TargetSystemUI.set_root_password = function(ts)
-		local done = false
-		local result
-		local cmds
-		local form = {
-		    id = "root_passwd",
-		    name = _("Set Root Password"),
-		    short_desc = _(
-			"Here you can set the super-user (root) password."
-		    ),
-	
-		    fields = {
-			{
-			    id = "root_passwd_1",
-			    name = _("Root Password"),
-			    short_desc = _("Enter the root password you would like to use"),
-			    obscured = "true"
-			},
-			{
-			    id = "root_passwd_2",
-			    name = _("Re-type Root Password"),
-			    short_desc = _("Enter the same password again to confirm"),
-			    obscured = "true"
-			}
-		    },
-		    
-		    actions = {
-			{
-			    id = "ok",
-			    name = _("Accept and Set Password")
-			},
-			{
-			    id = "cancel",
-			    accelerator = "ESC",
-			    name = _("Return to Configure Menu")
-			}
-		    },
-	
-		    datasets = {
-			{ root_passwd_1 = "", root_passwd_2 = "" }
-		    }
+	local done = false
+	local result
+	local cmds
+	local form = {
+	    id = "root_passwd",
+	    name = _("Set Root Password"),
+	    short_desc = _(
+		"Here you can set the super-user (root) password."
+	    ),
+
+	    fields = {
+		{
+		    id = "root_passwd_1",
+		    name = _("Root Password"),
+		    short_desc = _("Enter the root password you would like to use"),
+		    obscured = "true"
+		},
+		{
+		    id = "root_passwd_2",
+		    name = _("Re-type Root Password"),
+		    short_desc = _("Enter the same password again to confirm"),
+		    obscured = "true"
+		}
+	    },
+
+	    actions = {
+		{
+		    id = "ok",
+		    name = _("Accept and Set Password")
+		},
+		{
+		    id = "cancel",
+		    accelerator = "ESC",
+		    name = _("Return to Configure Menu")
 		}
-	
-		while not done do
-			result = ui:present(form)
-	
-			if result.action_id == "ok" then
-				form.datasets = result.datasets
+	    },
+
+	    datasets = {
+		{ root_passwd_1 = "", root_passwd_2 = "" }
+	    }
+	}
+
+	while not done do
+		result = ui:present(form)
+
+		if result.action_id == "ok" then
+			form.datasets = result.datasets
+
+			--
+			-- Fetch form field values.
+			--
+
+			local root_passwd_1 = result.datasets[1].root_passwd_1
+			local root_passwd_2 = result.datasets[1].root_passwd_2
 
+			-- XXX validate password for bad characters here XXX
+			
+			if root_passwd_1 == root_passwd_2 then
 				--
-				-- Fetch form field values.
+				-- Passwords match, so set the root password.
 				--
-	
-				local root_passwd_1 = result.datasets[1].root_passwd_1
-				local root_passwd_2 = result.datasets[1].root_passwd_2
-
-				-- XXX validate password for bad characters here XXX
-				
-				if root_passwd_1 == root_passwd_2 then
-					--
-					-- Passwords match, so set the root password.
-					--
-					cmds = CmdChain.new()
-					ts:cmds_set_password(cmds,
-					    "root", root_passwd_1)
-					if cmds:execute() then
-						ui:inform(
-						    _("The root password has been changed.")
-						)
-						done = true
-					else
-						ui:inform(
-						    _("An error occurred when " ..
-						      "setting the root password.")
-						)
-						done = false
-					end
+				cmds = CmdChain.new()
+				ts:cmds_set_password(cmds,
+				    "root", root_passwd_1)
+				if cmds:execute() then
+					ui:inform(
+					    _("The root password has been changed.")
+					)
+					done = true
 				else
-					--
-					-- Passwords don't match - tell the user, let them try again.
-					--
 					ui:inform(
-					    _("The passwords do not match.")
+					    _("An error occurred when " ..
+					      "setting the root password.")
 					)
 					done = false
 				end
 			else
-				-- Cancelled
-				done = true
+				--
+				-- Passwords don't match - tell the user, let them try again.
+				--
+				ui:inform(
+				    _("The passwords do not match.")
+				)
+				done = false
 			end
+		else
+			-- Cancelled
+			done = true
 		end
+	end
 end
 
 TargetSystemUI.add_user = function(ts)
-		local done = false
-		local result
-		local cmds
+	local done = false
+	local result
+	local cmds
 
-		--
-		-- Predicates which validate entered data.
-		--
-		local is_gecos_clean = function(gecos)
-			local i, char
+	--
+	-- Predicates which validate entered data.
+	--
+	local is_gecos_clean = function(gecos)
+		local i, char
 
-			i = 1
-			while i <= string.len(gecos) do
-				char = string.sub(gecos, i, i)
-				if string.find(char, "%c") or		  -- no ctrl chars
-				   string.byte(char) == 127 or		  -- no 'DEL' char
-				   string.find(":!@", char, 1, true) then -- none of these
-					return false
-				end
-				i = i + 1
+		i = 1
+		while i <= string.len(gecos) do
+			char = string.sub(gecos, i, i)
+			if string.find(char, "%c") or		  -- no ctrl chars
+			   string.byte(char) == 127 or		  -- no 'DEL' char
+			   string.find(":!@", char, 1, true) then -- none of these
+				return false
 			end
+			i = i + 1
+		end
 
-			return true
-		end
+		return true
+	end
 
-		local is_name_clean = function(name)
-			local i, char
+	local is_name_clean = function(name)
+		local i, char
 
-			i = 1
-			while i <= string.len(name) do
-				char = string.sub(name, i, i)
-				if string.find(char, "%c") or		-- no ctrl chars
-				   string.byte(char) == 127 or		-- no 'DEL' char
-				   string.byte(char) > 127 or		-- no 8-bit chars
-									-- and none of these:
-				   string.find(" ,\t:+&#%^()!@~*?<>=|\\/\"", char, 1, true) or
-				   (char == "-" and i == 1) or		-- no '-' at start
-									-- '$' only at end:
-				   (char == "$" and i ~= string.len(name)) then
-					return false
-				end
-				i = i + 1
+		i = 1
+		while i <= string.len(name) do
+			char = string.sub(name, i, i)
+			if string.find(char, "%c") or		-- no ctrl chars
+			   string.byte(char) == 127 or		-- no 'DEL' char
+			   string.byte(char) > 127 or		-- no 8-bit chars
+								-- and none of these:
+			   string.find(" ,\t:+&#%^()!@~*?<>=|\\/\"", char, 1, true) or
+			   (char == "-" and i == 1) or		-- no '-' at start
+								-- '$' only at end:
+			   (char == "$" and i ~= string.len(name)) then
+				return false
 			end
+			i = i + 1
+		end
 
-			return true
-		end
+		return true
+	end
 
-		local is_filename_clean = function(filename)	-- XXX incomplete
-			return true
-		end
+	local is_filename_clean = function(filename)	-- XXX incomplete
+		return true
+	end
 
-		local is_uid_clean = function(uid)		-- XXX incomplete
-			return true
-		end
+	local is_uid_clean = function(uid)		-- XXX incomplete
+		return true
+	end
 
-		local is_grouplist_clean = function(grouplist)	-- XXX incomplete
-			return true
-		end
+	local is_grouplist_clean = function(grouplist)	-- XXX incomplete
+		return true
+	end
 
-		--
-		-- Description of the form to display.
-		--
-		local form = {
-		    id = "add_user",
-		    name = _("Add User"),
-		    short_desc = _("Here you can add a user to an installed system.\n\n" ..
-			"You can leave the Home Directory, User ID, and Login Group "	..
-			"fields empty if you want these items to be automatically "	..
-			"allocated by the system."),
-		    fields = {
-			{
-			    id = "username",
-			    name = _("Username"),
-			    short_desc = _("Enter the username the user will log in as")
-			},
-			{
-			    id = "gecos",
-			    name = _("Real Name"),
-			    short_desc = _("Enter the real name (or GECOS field) of this user")
-			},
-			{
-			    id = "passwd_1",
-			    name = _("Password"),
-			    short_desc = _("Enter the user's password (will not be displayed)"),
-			    obscured = "true"
-			},
-			{
-			    id = "passwd_2",
-			    name = _("Password (Again)"),
-			    short_desc = _("Re-enter the user's password to confirm"),
-			    obscured = "true"
-			},
-			{
-			    id = "shell",
-			    name = _("Shell"),
-			    short_desc = _("Enter the full path to the user's shell program")
-			},
-			{
-			    id = "home",
-			    name = _("Home Directory"),
-			    short_desc = _("Enter the full path to the user's home directory, or leave blank")
-			},
-			{
-			    id = "uid",
-			    name = _("User ID"),
-			    short_desc = _("Enter this account's numeric user id, or leave blank")
-			},
-			{
-			    id = "group",
-			    name = _("Login Group"),
-			    short_desc = _("Enter the primary group for this account, or leave blank")
-			},
-			{
-			    id = "groups",
-			    name = _("Other Group Memberships"),
-			    short_desc = _(
-				"Enter a comma-separated list of other groups "	..
-				"that this user should belong to"
-			    )
-			}
-		    },
-		    actions = {
-			{
-			    id = "ok",
-			    name = _("Accept and Add User")
-			},
-			{
-			    id = "cancel",
-			    accelerator = "ESC",
-			    name = _("Return to Configure Menu")
-			}
-		    },
-		    datasets = {
-			{
-			    username = "",
-			    gecos = "",
-			    passwd_1 = "",
-			    passwd_2 = "",
-			    shell = "/bin/tcsh",
-			    home = "",
-			    uid = "",
-			    group = "",
-			    groups = ""
-			}
-		    }
+	--
+	-- Description of the form to display.
+	--
+	local form = {
+	    id = "add_user",
+	    name = _("Add User"),
+	    short_desc = _("Here you can add a user to an installed system.\n\n" ..
+		"You can leave the Home Directory, User ID, and Login Group "	..
+		"fields empty if you want these items to be automatically "	..
+		"allocated by the system."),
+	    fields = {
+		{
+		    id = "username",
+		    name = _("Username"),
+		    short_desc = _("Enter the username the user will log in as")
+		},
+		{
+		    id = "gecos",
+		    name = _("Real Name"),
+		    short_desc = _("Enter the real name (or GECOS field) of this user")
+		},
+		{
+		    id = "passwd_1",
+		    name = _("Password"),
+		    short_desc = _("Enter the user's password (will not be displayed)"),
+		    obscured = "true"
+		},
+		{
+		    id = "passwd_2",
+		    name = _("Password (Again)"),
+		    short_desc = _("Re-enter the user's password to confirm"),
+		    obscured = "true"
+		},
+		{
+		    id = "shell",
+		    name = _("Shell"),
+		    short_desc = _("Enter the full path to the user's shell program")
+		},
+		{
+		    id = "home",
+		    name = _("Home Directory"),
+		    short_desc = _("Enter the full path to the user's home directory, or leave blank")
+		},
+		{
+		    id = "uid",
+		    name = _("User ID"),
+		    short_desc = _("Enter this account's numeric user id, or leave blank")
+		},
+		{
+		    id = "group",
+		    name = _("Login Group"),
+		    short_desc = _("Enter the primary group for this account, or leave blank")
+		},
+		{
+		    id = "groups",
+		    name = _("Other Group Memberships"),
+		    short_desc = _(
+			"Enter a comma-separated list of other groups "	..
+			"that this user should belong to"
+		    )
+		}
+	    },
+	    actions = {
+		{
+		    id = "ok",
+		    name = _("Accept and Add User")
+		},
+		{
+		    id = "cancel",
+		    accelerator = "ESC",
+		    name = _("Return to Configure Menu")
+		}
+	    },
+	    datasets = {
+		{
+		    username = "",
+		    gecos = "",
+		    passwd_1 = "",
+		    passwd_2 = "",
+		    shell = "/bin/tcsh",
+		    home = "",
+		    uid = "",
+		    group = "",
+		    groups = ""
 		}
+	    }
+	}
+
+	--
+	-- Main loop which repeatedly displays the form until either
+	-- the user cancels or everything validates.
+	--
+	while not done do
+		result = ui:present(form)
+		if result.action_id == "ok" then
+			form.datasets = result.datasets
 

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200511230618.jAN6ISJV023288>