head	1.6;
access;
symbols
	RELENG_8_4:1.6.0.2
	RELENG_9_1_0_RELEASE:1.5.42.1.4.2
	RELENG_9_1:1.5.42.1.0.4
	RELENG_9_1_BP:1.5.42.1
	RELENG_8_3_0_RELEASE:1.5.36.1.8.1
	RELENG_8_3:1.5.36.1.0.8
	RELENG_8_3_BP:1.5.36.1
	RELENG_9_0_0_RELEASE:1.5.42.1.2.1
	RELENG_9_0:1.5.42.1.0.2
	RELENG_9_0_BP:1.5.42.1
	RELENG_9:1.5.0.42
	RELENG_9_BP:1.5
	RELENG_7_4_0_RELEASE:1.5.40.1
	RELENG_8_2_0_RELEASE:1.5.36.1.6.1
	RELENG_7_4:1.5.0.40
	RELENG_7_4_BP:1.5
	RELENG_8_2:1.5.36.1.0.6
	RELENG_8_2_BP:1.5.36.1
	RELENG_8_1_0_RELEASE:1.5.36.1.4.1
	RELENG_8_1:1.5.36.1.0.4
	RELENG_8_1_BP:1.5.36.1
	RELENG_7_3_0_RELEASE:1.5.38.1
	RELENG_7_3:1.5.0.38
	RELENG_7_3_BP:1.5
	RELENG_8_0_0_RELEASE:1.5.36.1.2.1
	RELENG_8_0:1.5.36.1.0.2
	RELENG_8_0_BP:1.5.36.1
	RELENG_8:1.5.0.36
	RELENG_8_BP:1.5
	RELENG_7_2_0_RELEASE:1.5.34.1
	RELENG_7_2:1.5.0.34
	RELENG_7_2_BP:1.5
	RELENG_7_1_0_RELEASE:1.5.32.1
	RELENG_6_4_0_RELEASE:1.5.30.1
	RELENG_7_1:1.5.0.32
	RELENG_7_1_BP:1.5
	RELENG_6_4:1.5.0.30
	RELENG_6_4_BP:1.5
	RELENG_7_0_0_RELEASE:1.5
	RELENG_6_3_0_RELEASE:1.5
	RELENG_7_0:1.5.0.28
	RELENG_7_0_BP:1.5
	RELENG_6_3:1.5.0.26
	RELENG_6_3_BP:1.5
	RELENG_7:1.5.0.24
	RELENG_7_BP:1.5
	RELENG_6_2_0_RELEASE:1.5
	RELENG_6_2:1.5.0.22
	RELENG_6_2_BP:1.5
	RELENG_5_5_0_RELEASE:1.5
	RELENG_5_5:1.5.0.20
	RELENG_5_5_BP:1.5
	RELENG_6_1_0_RELEASE:1.5
	RELENG_6_1:1.5.0.18
	RELENG_6_1_BP:1.5
	RELENG_6_0_0_RELEASE:1.5
	RELENG_6_0:1.5.0.16
	RELENG_6_0_BP:1.5
	RELENG_6:1.5.0.14
	RELENG_6_BP:1.5
	RELENG_5_4_0_RELEASE:1.5
	RELENG_5_4:1.5.0.12
	RELENG_5_4_BP:1.5
	RELENG_4_11_0_RELEASE:1.4.2.1
	RELENG_4_11:1.4.2.1.0.18
	RELENG_4_11_BP:1.4.2.1
	RELENG_5_3_0_RELEASE:1.5
	RELENG_5_3:1.5.0.10
	RELENG_5_3_BP:1.5
	RELENG_5:1.5.0.8
	RELENG_5_BP:1.5
	RELENG_4_10_0_RELEASE:1.4.2.1
	RELENG_4_10:1.4.2.1.0.16
	RELENG_4_10_BP:1.4.2.1
	RELENG_5_2_1_RELEASE:1.5
	RELENG_5_2_0_RELEASE:1.5
	RELENG_5_2:1.5.0.6
	RELENG_5_2_BP:1.5
	RELENG_4_9_0_RELEASE:1.4.2.1
	RELENG_4_9:1.4.2.1.0.14
	RELENG_4_9_BP:1.4.2.1
	RELENG_5_1_0_RELEASE:1.5
	RELENG_5_1:1.5.0.4
	RELENG_5_1_BP:1.5
	RELENG_4_8_0_RELEASE:1.4.2.1
	RELENG_4_8:1.4.2.1.0.12
	RELENG_4_8_BP:1.4.2.1
	RELENG_5_0_0_RELEASE:1.5
	RELENG_5_0:1.5.0.2
	RELENG_5_0_BP:1.5
	RELENG_4_7_0_RELEASE:1.4.2.1
	RELENG_4_7:1.4.2.1.0.10
	RELENG_4_7_BP:1.4.2.1
	RELENG_4_6_2_RELEASE:1.4.2.1
	RELENG_4_6_1_RELEASE:1.4.2.1
	RELENG_4_6_0_RELEASE:1.4.2.1
	RELENG_4_6:1.4.2.1.0.8
	RELENG_4_6_BP:1.4.2.1
	RELENG_4_5_0_RELEASE:1.4.2.1
	RELENG_4_5:1.4.2.1.0.6
	RELENG_4_5_BP:1.4.2.1
	RELENG_4_4_0_RELEASE:1.4.2.1
	RELENG_4_4:1.4.2.1.0.4
	RELENG_4_4_BP:1.4.2.1
	RELENG_4_3_0_RELEASE:1.4.2.1
	RELENG_4_3:1.4.2.1.0.2
	RELENG_4_3_BP:1.4.2.1
	RELENG_4_2_0_RELEASE:1.4
	RELENG_4_1_1_RELEASE:1.4
	PRE_SMPNG:1.4
	RELENG_4_1_0_RELEASE:1.4
	RELENG_3_5_0_RELEASE:1.3.2.1
	RELENG_4_0_0_RELEASE:1.4
	RELENG_4:1.4.0.2
	RELENG_4_BP:1.4
	RELENG_3_4_0_RELEASE:1.3.2.1
	RELENG_3_3_0_RELEASE:1.3.2.1
	RELENG_3_2_PAO:1.3.0.4
	RELENG_3_2_PAO_BP:1.3
	RELENG_3_2_0_RELEASE:1.3
	RELENG_3_1_0_RELEASE:1.3
	RELENG_3:1.3.0.2
	RELENG_3_BP:1.3
	RELENG_2_2_8_RELEASE:1.1.1.1.2.1
	RELENG_3_0_0_RELEASE:1.3
	RELENG_2_2_7_RELEASE:1.1.1.1.2.1
	RELENG_2_2_6_RELEASE:1.1.1.1
	RELENG_2_2_5_RELEASE:1.1.1.1
	RELENG_2_2_2_RELEASE:1.1.1.1
	RELENG_2_2_1_RELEASE:1.1.1.1
	RELENG_2_2_0_RELEASE:1.1.1.1
	RELENG_2_2:1.1.1.1.0.2
	initial:1.1.1.1
	MSMITH:1.1.1;
locks; strict;
comment	@# @;


1.6
date	2012.11.17.01.54.09;	author svnexp;	state Exp;
branches
	1.6.2.1;
next	1.5;

1.5
date	2001.02.18.10.43.27;	author asmodai;	state Exp;
branches
	1.5.14.1
	1.5.24.1
	1.5.30.1
	1.5.32.1
	1.5.34.1
	1.5.36.1
	1.5.38.1
	1.5.40.1
	1.5.42.1;
next	1.4;

1.4
date	99.08.28.00.54.29;	author peter;	state Exp;
branches
	1.4.2.1;
next	1.3;

1.3
date	98.05.06.05.45.16;	author msmith;	state Exp;
branches
	1.3.2.1;
next	1.2;

1.2
date	97.06.10.01.53.01;	author msmith;	state Exp;
branches;
next	1.1;

1.1
date	97.01.21.08.34.14;	author msmith;	state Exp;
branches
	1.1.1.1;
next	;

1.6.2.1
date	2012.11.17.01.54.09;	author svnexp;	state dead;
branches;
next	1.6.2.2;

1.6.2.2
date	2013.03.28.13.05.58;	author svnexp;	state Exp;
branches;
next	;

1.5.14.1
date	2012.11.17.07.45.29;	author svnexp;	state Exp;
branches;
next	;

1.5.24.1
date	2012.11.17.08.08.14;	author svnexp;	state Exp;
branches;
next	;

1.5.30.1
date	2008.10.02.02.57.24;	author kensmith;	state Exp;
branches;
next	;

1.5.32.1
date	2008.11.25.02.59.29;	author kensmith;	state Exp;
branches;
next	;

1.5.34.1
date	2009.04.15.03.14.26;	author kensmith;	state Exp;
branches;
next	;

1.5.36.1
date	2009.08.03.08.13.06;	author kensmith;	state Exp;
branches
	1.5.36.1.2.1
	1.5.36.1.4.1
	1.5.36.1.6.1
	1.5.36.1.8.1;
next	1.5.36.2;

1.5.36.2
date	2012.11.17.10.37.14;	author svnexp;	state Exp;
branches;
next	;

1.5.36.1.2.1
date	2009.10.25.01.10.29;	author kensmith;	state Exp;
branches;
next	;

1.5.36.1.4.1
date	2010.06.14.02.09.06;	author kensmith;	state Exp;
branches;
next	;

1.5.36.1.6.1
date	2010.12.21.17.09.25;	author kensmith;	state Exp;
branches;
next	;

1.5.36.1.8.1
date	2012.03.03.06.15.13;	author kensmith;	state Exp;
branches;
next	1.5.36.1.8.2;

1.5.36.1.8.2
date	2012.11.17.08.25.47;	author svnexp;	state Exp;
branches;
next	;

1.5.38.1
date	2010.02.10.00.26.20;	author kensmith;	state Exp;
branches;
next	;

1.5.40.1
date	2010.12.21.17.10.29;	author kensmith;	state Exp;
branches;
next	1.5.40.2;

1.5.40.2
date	2012.11.17.08.17.40;	author svnexp;	state Exp;
branches;
next	;

1.5.42.1
date	2011.09.23.00.51.37;	author kensmith;	state Exp;
branches
	1.5.42.1.2.1
	1.5.42.1.4.1;
next	1.5.42.2;

1.5.42.2
date	2012.11.17.11.37.35;	author svnexp;	state Exp;
branches;
next	;

1.5.42.1.2.1
date	2011.11.11.04.20.22;	author kensmith;	state Exp;
branches;
next	1.5.42.1.2.2;

1.5.42.1.2.2
date	2012.11.17.08.37.32;	author svnexp;	state Exp;
branches;
next	;

1.5.42.1.4.1
date	2012.08.05.23.54.33;	author kensmith;	state Exp;
branches;
next	1.5.42.1.4.2;

1.5.42.1.4.2
date	2012.11.17.08.48.23;	author svnexp;	state Exp;
branches;
next	;

1.4.2.1
date	2001.03.05.12.17.23;	author kris;	state Exp;
branches;
next	1.4.2.2;

1.4.2.2
date	2012.11.17.07.27.18;	author svnexp;	state Exp;
branches;
next	;

1.3.2.1
date	99.08.29.15.18.24;	author peter;	state Exp;
branches;
next	;

1.1.1.1
date	97.01.21.08.34.14;	author msmith;	state Exp;
branches
	1.1.1.1.2.1;
next	;

1.1.1.1.2.1
date	98.05.06.05.46.15;	author msmith;	state Exp;
branches;
next	1.1.1.1.2.2;

1.1.1.1.2.2
date	99.09.05.11.29.23;	author peter;	state Exp;
branches;
next	;


desc
@@


1.6
log
@Switching exporter and resync
@
text
@#!/bin/sh
# Tcl magic -*- tcl -*- \
exec tclsh $0 $*
################################################################################
#
# KernelDriver - FreeBSD driver source installer
#
################################################################################
#
# Copyright (C) 1997
#      Michael Smith.  All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. Neither the name of the author nor the names of any co-contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Michael Smith AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL Michael Smith OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
################################################################################
#
# KernelDriver provides a means for installing source-form drivers into FreeBSD 
# kernel source trees in an automated fashion.  It can also remove drivers it 
# has installed.
#
# Driver information is read from a control file, with the following syntax :
#
# description {<text>}		Driver description; used in comments inserted into
#				files.
# driver <name>			The name of the driver. (Note that this can't end in .drvinfo :)
# filei386 <path> <name>	The file <name> in the driver package is installed into
#				<path> in the kernel source tree.  Files whose names
#				end in '.c' have an entry added to i386/conf/files.i386.
# fileconf <path> <name>	The file <name> in the driver package is installed into
#				<path> in the kernel source tree.  Files whose names
#				end in '.c' have an entry added to conf/files.
# optioni386 <name> <hdr>	Adds an entry to i386/conf/options.i386, such that
#				the option <name> will be placed in the header <hdr>.
# optionconf <name> <hdr>	Adds an entry to conf/options, such that
#				the option <name> will be placed in the header <hdr>.
# linttext			Lines between this and a subsequent 'end' line are added
#				to the LINT file to provide configuration examples,
#				comments, etc.
# end				Ends a text region.
# 
# Possible additions :
#
# patch <name>		Applies the patch contained in <name>; patch is invoked
#			at the top level of the kernel source tree, and the 
#			patch must apply cleanly (this is checked).
#
# option <name> <file>	Adds an entry to i386/conf/options.i386
#
# Lines beginning with '#' or blanks are considered comments, except in
# 'linttext' regions.
#
################################################################################
#
# $FreeBSD: head/tools/tools/kdrv/KernelDriver 72645 2001-02-18 10:43:53Z asmodai $
#
################################################################################

################################################################################
# findDrvFile
#
# Given (hint), use it to locate a driver information file.
# (Possible extension; support drivers in gzipped tarballs...)
#
proc findDrvFile_try {hint} {

    # points to something already
    if {[file exists $hint]} {
	# unwind symbolic links
	while {[file type $hint] == "link"} {
	    set hint [file readlink $hint];
	}
	switch [file type $hint] {
	    file {
		# run with it as it is
		return $hint;
	    }
	    directory {
		# look for a drvinfo file in the directory
		set candidate [glob -nocomplain "$hint/*.drvinfo"];
		switch [llength $candidate] {
		    0 {
			# nothing there
		    }
		    1 {
			return $candidate;
		    }
		    default {
			error "multiple driver info files in directory : $hint";
		    }
		}
	    }
	    default {
		error "driver info file may be a typewriter : $hint";
	    }
	}
    }
    # maybe we need an extension
    if {[file exists $hint.drvinfo]} {
	return $hint.drvinfo;
    }
    error "can't find a driver info file using '$hint'";
}

proc findDrvFile {hint} {

    set result [findDrvFile_try $hint];
    if {$result != ""} {
	return $result;
    }
    set result [findDrvFile_try ${hint}.drvinfo];
    if {$result != ""} {
	return $result;
    }
    error "can't find driver information file using : $hint";
}

################################################################################
# readDrvFile
#
# Reads the contents of (fname), which are expected to be in the format 
# described above, and fill in the global Drv array.
#
proc readDrvFile {fname} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ read options from '$fname'";}
    set fh [open $fname r];
    
    # set defaults
    set Drv(description) "";
    set Drv(driver) "";
    set Drv(filesi386) "";
    set Drv(filesconf) "";
    set Drv(optionsi386) "";
    set Drv(optionsconf) "";
    set Drv(patches) "";
    set Drv(linttext) "";

    while {[gets $fh line] >= 0} {
	
	# blank lines/comments
	if {([llength $line] == 0) ||
	    ([string index $line 0] == "\#")} {
	    continue ;
	}

	# get keyword, process
	switch -- [lindex $line 0] {
	    description {
		set Drv(description) [lindex $line 1];
	    }
	    driver {
		set Drv(driver) [lindex $line 1];
	    }
	    filei386 {
		set path [lindex $line 1];
		set plast [expr [string length $path] -1];
		if {[string index $path $plast] != "/"} {
		    append path "/";
		}
		set name [lindex $line 2];
		set Drv(filei386:$name) $path;
		lappend Drv(filesi386) $name;
	    }
	    fileconf {
		set path [lindex $line 1];
		set plast [expr [string length $path] -1];
		if {[string index $path $plast] != "/"} {
		    append path "/";
		}
		set name [lindex $line 2];
		set Drv(fileconf:$name) $path;
		lappend Drv(filesconf) $name;
	    }
	    optioni386 {
		set opt [lindex $line 1];
		set hdr [lindex $line 2];
		lappend Drv(optionsi386) $opt;
		set Drv(optioni386:$opt) $hdr;
	    }
	    optionconf {
		set opt [lindex $line 1];
		set hdr [lindex $line 2];
		lappend Drv(optionsconf) $opt;
		set Drv(optionconf:$opt) $hdr;
	    }
	    patch {
		lappend Drv(patches) [lindex $line 1];
	    }
	    linttext {
		while {[gets $fh line] >= 0} {
		    if {$line == "end"} {
			break ;
		    }
		    lappend Drv(linttext) $line;
		}
	    }
	}
    }
    close $fh;
    if {$Options(verbose)} {
	printDrv;
    }
}
		
################################################################################
# validateDrvPackage
#
# With the global Drv filled in, check that the files required are all in
# (dir), and that the kernel config at (kpath) can be written.
#
proc validateDrvPackage {dir kpath} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ checking driver package...";}
    set missing "";
    set unwritable "";

    # check files, patches
    foreach f $Drv(filesi386) {
	if {![file readable $dir$f]} {
	    lappend missing $f;
	}
    }
    foreach f $Drv(filesconf) {
	if {![file readable $dir$f]} {
	    lappend missing $f;
	}
    }
    foreach f $Drv(patches) {
	if {![file readable $dir$f]} {
	    lappend missing $f;
	}
    }
    if {$missing != ""} {
	error "missing files : $missing";
    }

    # check writability
    if {$Options(verbose)} {puts "+ checking kernel source writability...";}
    foreach f $Drv(filesi386) {
	set p $Drv(filei386:$f);
	if {![file isdirectory $kpath$p]} {
	    lappend missing $p;
	} else {
	    if {![file writable $kpath$p]} {
		if {[lsearch -exact $unwritable $p] == -1} {
		    lappend unwritable $p;
		}
	    }
	}
    }
    foreach f $Drv(filesconf) {
	set p $Drv(fileconf:$f);
	if {![file isdirectory $kpath$p]} {
	    lappend missing $p;
	} else {
	    if {![file writable $kpath$p]} {
		if {[lsearch -exact $unwritable $p] == -1} {
		    lappend unwritable $p;
		}
	    }
	}
    }
    foreach f [list \
		   "conf/files" \
		   "i386/conf/files.i386" \
		   "i386/conf/options.i386" \
		   "i386/conf/LINT"] {
	if {![file writable $kpath$f]} {
	    lappend unwritable $f;
	}
    }
    if {$missing != ""} {
	error "missing directories : $missing";
    }
    if {$unwritable != ""} {
	error "can't write to : $unwritable";
    }
}

################################################################################
# installDrvFiles
#
# Install the files listed in the global Drv into (kpath) from (dir)
#
proc installDrvFiles {dir kpath} {

    global Drv Options;

    # clear 'installed' record
    set Drv(installedi386) "";
    set Drv(installedconf) "";
    set failed "";

    if {$Options(verbose)} {puts "+ installing driver files...";}
    foreach f $Drv(filesi386) {
	if {$Options(verbose)} {puts "$f -> $kpath$Drv(filei386:$f)";}
	if {$Options(real)} {
	    if {[catch {exec cp $dir$f $kpath$Drv(filei386:$f)} msg]} {
		lappend failed $f;
	    } else {
		lappend Drv(installedi386) $f;
	    }
	}
    }
    foreach f $Drv(filesconf) {
	if {$Options(verbose)} {puts "$f -> $kpath$Drv(fileconf:$f)";}
	if {$Options(real)} {
	    if {[catch {exec cp $dir$f $kpath$Drv(fileconf:$f)} msg]} {
		lappend failed $f;
	    } else {
		lappend Drv(installedconf) $f;
	    }
	}
    }
    if {$failed != ""} {
	error "failed to install files : $failed";
    }
}

################################################################################
# backoutDrvChanges
#
# Remove files from a failed installation in (kpath)
#
proc backoutDrvChanges {kpath} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ backing out installed files...";}
    # delete installed files
    foreach f $Drv(installedi386) {
	exec rm -f $kpath$Drv(filei386:$f)$f;
    }
    foreach f $Drv(installedconf) {
	exec rm -f $kpath$Drv(fileconf:$f)$f;
    }
}

################################################################################
# registerDrvFiles
#
# Adds an entry to i386/conf/files.i386 and conf/files for the .c files in the driver.  
# (kpath) points to the kernel.
#
# A comment is added to the file preceding the new entries :
#
#  ## driver: <drivername>
#  # <description>
#  # filei386: <path><file>
#  <file spec (.c files only)>
#  ## enddriver
#
# We only append to the end of the file.
#
# Add linttext to the LINT file.
# Add options to i386/conf/options.i386 if any are specified
#
proc registerDrvFiles {kpath} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ registering installed files...";}

# Add stuff to LINT
    if {$Drv(linttext) != ""} {

	if {$Options(verbose)} {puts "+ updating LINT...";}
	if {$Options(real)} {
	    set fname [format "%si386/conf/LINT" $kpath];
	    set fh [open $fname a];

	    # header
	    puts $fh "\#\# driver: $Drv(driver)";
	    puts $fh "\# $Drv(description)";
	    foreach l $Drv(linttext) {
		puts $fh $l;
	    }
	    puts $fh "\#\# enddriver";
	    close $fh;
	}
    }

# Do filesi386 stuff
    if {$Options(real)} {
	set fname [format "%si386/conf/files.i386" $kpath];
	set fh [open $fname a];

	# header
	puts $fh "\#\# driver: $Drv(driver)";
	puts $fh "\# $Drv(description)";
	# file information
	foreach f $Drv(filesi386) {
	    puts $fh "\# file: $Drv(filei386:$f)$f";
	    # is it a compilable object?
	    if {[string match "*.c" $f]} {
		puts $fh "$Drv(filei386:$f)$f\t\toptional\t$Drv(driver)\tdevice-driver";
	    }
	}
	puts $fh "\#\# enddriver";
	close $fh;
    }
    if {$Drv(optionsi386) != ""} {
	if {$Options(verbose)} {puts "+ adding options...";}
	if {$Options(real)} {
	    set fname [format "%si386/conf/options.i386" $kpath];
	    set fh [open $fname a];

	    # header
	    puts $fh "\#\# driver: $Drv(driver)";
	    puts $fh "\# $Drv(description)";
	    # options
	    foreach opt $Drv(optionsi386) {
		puts $fh "$opt\t$Drv(optioni386:$opt)";
	    }
	    puts $fh "\#\# enddriver";
	    close $fh;
	}
    }

# Do filesconf stuff
    if {$Options(real)} {
	set fname [format "%sconf/files" $kpath];
	set fh [open $fname a];

	# header
	puts $fh "\#\# driver: $Drv(driver)";
	puts $fh "\# $Drv(description)";
	# file information
	foreach f $Drv(filesconf) {
	    puts $fh "\# file: $Drv(fileconf:$f)$f";
	    # is it a compilable object?
	    if {[string match "*.c" $f]} {
		puts $fh "$Drv(fileconf:$f)$f\t\toptional\t$Drv(driver)\tdevice-driver";
	    }
	}
	puts $fh "\#\# enddriver";
	close $fh;
    }
     if {$Drv(optionsconf) != ""} {
 	if {$Options(verbose)} {puts "+ adding options...";}
 	if {$Options(real)} {
 	    set fname [format "%sconf/options" $kpath];
 	    set fh [open $fname a];

 	    # header
 	    puts $fh "\#\# driver: $Drv(driver)";
 	    puts $fh "\# $Drv(description)";
 	    # options
 	    foreach opt $Drv(optionsconf) {
 		puts $fh "$opt\t$Drv(optionconf:$opt)";
 	    }
 	    puts $fh "\#\# enddriver";
 	    close $fh;
 	}
     }

}

################################################################################
# listInstalledDrv
#
# List all drivers recorded as installed, in the kernel at (kpath)
#
# XXX : fix me so I understand conf/{options,files} stuff!
proc listInstalledDrv {kpath} {

    global Drv;

    # pick up all the i386 options information first
    set fname [format "%si386/conf/options.i386" $kpath];
    if {![file readable $fname]} {
	error "not a kernel directory";
    }
    set fh [open $fname r];

    while {[gets $fh line] >= 0} {
    
	# got a driver?
	if {[scan $line "\#\# driver: %s" driver] == 1} {
	    # read driver details, ignore
	    gets $fh line;
	    # loop reading option details
	    while {[gets $fh line] >= 0} {
		# end of driver info
		if {$line == "\#\# enddriver"} {
		    break ;
		}
		# parse option/header tuple
		if {[scan $line "%s %s" opt hdr] == 2} {
		    # remember that this driver uses this option
		    lappend drivers($driver:optionsi386) $opt;
		    # remember that this option goes in this header
		    set optionsi386($opt) $hdr;
		}
	    }
	}
    }
    close $fh;

    # pick up all the conf options information first
    set fname [format "%sconf/options" $kpath];
    if {![file readable $fname]} {
	error "not a kernel directory";
    }
    set fh [open $fname r];

    while {[gets $fh line] >= 0} {
    
	# got a driver?
	if {[scan $line "\#\# driver: %s" driver] == 1} {
	    # read driver details, ignore
	    gets $fh line;
	    # loop reading option details
	    while {[gets $fh line] >= 0} {
		# end of driver info
		if {$line == "\#\# enddriver"} {
		    break ;
		}
		# parse option/header tuple
		if {[scan $line "%s %s" opt hdr] == 2} {
		    # remember that this driver uses this option
		    lappend drivers($driver:optionsconf) $opt;
		    # remember that this option goes in this header
		    set optionsconf($opt) $hdr;
		}
	    }
	}
    }
    close $fh;

    set fname [format "%si386/conf/files.i386" $kpath];
    set fh [open $fname r];
    
    while {[gets $fh line] >= 0} {

	# got a driver? 
	if {[scan $line "\#\# driver: %s" driver] == 1} {
	    # clear global and reset
	    catch {unset Drv};
	    set Drv(driver) $driver;
	    # read driver details
	    gets $fh line;
	    set Drv(description) [string range $line 2 end];
	    set Drv(filesi386) "";
	    # options?
	    if {[info exists drivers($Drv(driver):optionsi386)]} {
		set Drv(optionsi386) $drivers($Drv(driver):optionsi386);
		# get pathnames
		foreach opt $Drv(optionsi386) {
		    set Drv(optioni386:$opt) $optionsi386($opt);
		}
	    }
	    # loop reading file details
	    while {[gets $fh line] >= 0} {
		if {$line == "\#\# enddriver"} {
		    # print this driver and loop
		    printDrv;
		    break ;
		}
		if {[scan $line "\# filei386: %s" fpath] == 1} {
		    set f [file tail $fpath];	
		    set Drv(filei386:$f) "[file dirname $fpath]/";
		    lappend Drv(filesi386) $f;
		}
	    }
	}
    }
    close $fh;

    set fname [format "%sconf/files" $kpath];
    set fh [open $fname r];
    
    while {[gets $fh line] >= 0} {

	# got a driver? 
	if {[scan $line "\#\# driver: %s" driver] == 1} {
	    # clear global and reset
	    catch {unset Drv};
	    set Drv(driver) $driver;
	    # read driver details
	    gets $fh line;
	    set Drv(description) [string range $line 2 end];
	    set Drv(filesconf) "";
	    # options?
	    if {[info exists drivers($Drv(driver):optionsconf)]} {
		set Drv(optionsconf) $drivers($Drv(driver):optionsconf);
		# get pathnames
		foreach opt $Drv(optionsconf) {
		    set Drv(optionconf:$opt) $optionsconf($opt);
		}
	    }
	    # loop reading file details
	    while {[gets $fh line] >= 0} {
		if {$line == "\#\# enddriver"} {
		    # print this driver and loop
		    printDrv;
		    break ;
		}
		if {[scan $line "\# fileconf: %s" fpath] == 1} {
		    set f [file tail $fpath];	
		    set Drv(fileconf:$f) "[file dirname $fpath]/";
		    lappend Drv(filesconf) $f;
		}
	    }
	}
    }
    close $fh;
}

################################################################################
# printDrv
#
# Print the contents of the global Drv.
#
proc printDrv {} {

    global Drv Options;

    puts "$Drv(driver) : $Drv(description)";
    if {$Options(verbose)} {
	foreach f $Drv(filesi386) {
	    puts " $Drv(filei386:$f)$f"
	}
	foreach f $Drv(filesconf) {
	    puts " $Drv(fileconf:$f)$f"
	}
	if {[info exists Drv(optionsi386)]} {
	    foreach opt $Drv(optionsi386) {
		puts " $opt in $Drv(optioni386:$opt)";
	    }
	}
	if {[info exists Drv(optionsconf)]} {
	    foreach opt $Drv(optionsconf) {
		puts " $opt in $Drv(optionconf:$opt)";
	    }
	}
    }
}

################################################################################
# findInstalledDrv
#
# Given a kernel tree at (kpath), get driver details about an installed
# driver (drvname)
#

proc findInstalledDrvi386 {drvname kpath} {

    global Drv;

    set fname [format "%si386/conf/files.i386" $kpath];
    set fh [open $fname r];
    
    puts "checking i386/conf/files.i386";

    while {[gets $fh line] >= 0} {
	if {[scan $line "\#\# driver: %s" name] == 1} {
	    if {$name != $drvname} {
		continue ;		# not us
	    }
	    # read information
	    set Drv(driver) $drvname;
	    set line [gets $fh];
	    set Drv(description) [string range $line 2 end];
	    set Drv(filesi386) "";
	    # loop reading file details
	    while {[gets $fh line] >= 0} {
		if {$line == "\#\# enddriver"} {
		    close $fh;
		    return 1;		# all done
		}
		if {[scan $line "\# file: %s" fpath] == 1} {
		    set f [file tail $fpath];	
		    set Drv(filei386:$f) "[file dirname $fpath]/";
		    lappend Drv(filesi386) $f;
		}
	    }
	    close $fh;
	    error "unexpected EOF reading '$fname'";
	}
    }
    close $fh

    return 0;
}

proc findInstalledDrvconf {drvname kpath} {

    global Drv;

    set fname [format "%sconf/files" $kpath];
    set fh [open $fname r];

    puts "checking conf/files";
    
    while {[gets $fh line] >= 0} {
	if {[scan $line "\#\# driver: %s" name] == 1} {
	    if {$name != $drvname} {
		continue ;		# not us
	    }
	    # read information
	    set Drv(driver) $drvname;
	    set line [gets $fh];
	    set Drv(description) [string range $line 2 end];
	    set Drv(filesconf) "";
	    # loop reading file details
	    while {[gets $fh line] >= 0} {
		if {$line == "\#\# enddriver"} {
		    close $fh;
		    return 1;		# all done
		}
		if {[scan $line "\# file: %s" fpath] == 1} {
		    set f [file tail $fpath];	
		    set Drv(fileconf:$f) "[file dirname $fpath]/";
		    lappend Drv(filesconf) $f;
		}
	    }
	    close $fh;
	    error "unexpected EOF reading '$fname'";
	}
    }
    close $fh

    return 0;
}

proc findInstalledDrv {drvname kpath} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ look for driver '$drvname' in '$kpath'";}

# Whoops... won't work in a single if statement due to expression shortcircuiting
    set a [findInstalledDrvi386 $drvname $kpath];
    set b [findInstalledDrvconf $drvname $kpath];
    if {$a || $b} {
	return;
    }

    error "driver '$drvname' not recorded as installed";
}

################################################################################
# validateDrvRemoval
#
# Verify that we can remove the driver described in the global Drv installed
# at (kpath).
#
proc validateDrvRemoval {kpath} {

    global Drv Options;

    set missing "";
    set unwritable "";

    if {$Options(verbose)} {puts "+ checking for removabilty...";}

    # admin files?
    foreach f [list \
		   "i386/conf/files.i386" \
		   "i386/conf/options.i386" \
		   "i386/conf/LINT" \
		   "conf/files" \
		   "conf/options" ] { 
	if {![file exists $kpath$f]} {
	    lappend missing $kpath$f;
	} else {
	    if {![file writable $kpath$f]} {
		lappend unwritable $f;
	    }
	}
    }
    # driver components?
    foreach f $Drv(filesi386) {
	set p $Drv(filei386:$f);
	if {![file isdirectory $kpath$p]} {
	    lappend missing $p;
	} else {
	    if {![file writable $kpath$p]} {
		if {[lsearch -exact $unwritable $p] == -1} {
		    lappend unwritable $p;
		}
	    }
	}
    }
    foreach f $Drv(filesconf) {
	set p $Drv(fileconf:$f);
	if {![file isdirectory $kpath$p]} {
	    lappend missing $p;
	} else {
	    if {![file writable $kpath$p]} {
		if {[lsearch -exact $unwritable $p] == -1} {
		    lappend unwritable $p;
		}
	    }
	}
    }
    if {$missing != ""} {
	error "files/directories missing : $missing";
    }
    if {$unwritable != ""} {
	error "can't write to : $unwritable";
    }
}

################################################################################
# deleteDrvFiles
#
# Delete the files belonging to the driver devfined in the global Drv in
# the kernel tree at (kpath)
#
proc deleteDrvFiles {kpath} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ delete driver files...";}

    # loop deleting files
    foreach f $Drv(filesi386) {
	if {$Options(verbose)} {puts "- $Drv(filei386:$f)$f";}
	if {$Options(real)} {
	    exec rm $kpath$Drv(filei386:$f)$f;
	}
    }
    foreach f $Drv(filesconf) {
	if {$Options(verbose)} {puts "- $Drv(fileconf:$f)$f";}
	if {$Options(real)} {
	    exec rm $kpath$Drv(fileconf:$f)$f;
	}
    }
}    

################################################################################
# unregisterDrvFiles
#
# Remove any mention of the current driver from the files.i386 and LINT
# files in (ksrc)
#
proc unregisterDrvFiles {ksrc} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ deregister driver files...";}

    # don't really do it?
    if {!$Options(real)} { return ; }

    foreach f [list \
		   "i386/conf/files.i386" \
		   "i386/conf/options.i386" \
		   "i386/conf/LINT" \
		   "conf/files" \
		   "conf/options" ] {
	set ifh [open $ksrc$f r];
	set ofh [open $ksrc$f.new w];
	set copying 1;

	while {[gets $ifh line] >= 0} {

	    if {[scan $line "\#\# driver: %s" name] == 1} {
		if {$name == $Drv(driver)} {
		    set copying 0;			# don't copy this one
		}
	    }
	    if {$copying} {
		puts $ofh $line;		# copy through
	    }
	    if {$line == "\#\# enddriver"} {	# end of driver detail
		set copying 1;
	    }
	}
	close $ifh;
	close $ofh;
	exec mv $ksrc$f.new $ksrc$f;		# move new over old
    }
}

################################################################################
# usage
#
# Remind the user what goes where
#
proc usage {} {

    global argv0;

    set progname [file tail $argv0];

    puts stderr "Usage is :";
    puts stderr "  $progname \[-v -n\] add <drvinfo> \[<kpath>\]";
    puts stderr "  $progname \[-v -n\] delete <drvname> \[<kpath>\]";
    puts stderr "  $progname \[-v\] list \[<kpath>\]";
    puts stderr "  <drvinfo> is a driver info file";
    puts stderr "  <drvname> is a driver name";
    puts stderr "  <kpath> is the path to the kernel source (default /sys/)";
    puts stderr "  -v  be verbose";
    puts stderr "  -n  don't actually do anything";
    exit ;
}

################################################################################
# getOptions
#
# Parse commandline options, return anything that doesn't look like an option
#
proc getOptions {} {

    global argv Options;

    set Options(real) 1;
    set Options(verbose) 0;
    set ret "";
    
    for {set index 0} {$index < [llength $argv]} {incr index} {
	
	switch -- [lindex $argv $index] {

	    -n {
		set Options(real) 0;		# 'do-nothing' mode
	    }
	    -v {
		set Options(verbose) 1;		# brag
	    }
	    default {
		lappend ret [lindex $argv $index];
	    }
	}
    }
    return $ret;
}

################################################################################
# getKpath
#
# Given (hint), return the kernel path.  If (hint) is empty, return /sys.
# If the kernel path is not a directory, complain and dump the usage.
#
proc getKpath {hint} {

    set kpath "";

    # check the kernel path
    if {$hint == ""} {
	set kpath "/sys/";
    } else {
	set kpath $hint;
    }
    if {![file isdirectory $kpath]} {
	puts "not a directory : $kpath";
	usage ;
    }
    set plast [expr [string length $kpath] -1];
    if {[string index $kpath $plast] != "/"} {
	append kpath "/";
    }
    return $kpath;
}

################################################################################
# main
#
# Start somewhere here.
#
proc main {} {

    global Options;

    # Work out what we're trying to do
    set cmdline [getOptions];
    set mode [lindex $cmdline 0];

    # do stuff
    switch -- $mode {
	add {
	    set hint [lindex $cmdline 1];
	    set kpath [getKpath [lindex $cmdline 2]];

	    # check driver file argument
	    if {[catch {set drv [findDrvFile $hint]} msg]} {
		puts stderr $msg;
		usage ;
	    }
	    if {([file type $drv] != "file") ||
		![file readable $drv]} {
		puts "can't read driver file : $drv";
		usage ; 
	    }
	    set drvdir "[file dirname $drv]/";

	    # read driver file
	    if {[catch {readDrvFile $drv} msg]} {
		puts stderr $msg;
		exit ;
	    }
	    # validate driver
	    if {[catch {validateDrvPackage $drvdir $kpath} msg]} {
		puts stderr $msg;
		exit ;
	    }
	    # install new files
	    if {[catch {installDrvFiles $drvdir $kpath} msg]} {
		backoutDrvChanges $kpath;		# oops, unwind
		puts stderr $msg;
		exit ;
	    }
	    # register files in config
	    if {[catch {registerDrvFiles $kpath} msg]} {
		backoutDrvChanges $kpath;		# oops, unwind
		puts stderr $msg;
		exit ;
	    }
	}
	delete {
	    set drv [lindex $cmdline 1];
	    set kpath [getKpath [lindex $cmdline 2]];

	    if {[string last ".drvinfo" $drv] != -1} {
		set drv [string range $drv 0 [expr [string length $drv] - 9]];
		puts "Driver name ends in .drvinfo, removing, is now $drv";
	    }

	    if {[catch {findInstalledDrv $drv $kpath} msg]} {
		puts stderr $msg;
		exit ;
	    }
	    if {[catch {validateDrvRemoval $kpath} msg]} {
		puts stderr $msg;
		exit ;
	    }
	    if {[catch {unregisterDrvFiles $kpath} msg]} {
		puts stderr $msg;
		exit ;
	    }
	    if {[catch {deleteDrvFiles $kpath} msg]} {
		puts stderr $msg;
		exit ;
	    }
	}
	list { 
	    set kpath [getKpath [lindex $cmdline 1]];
	    if {[catch {listInstalledDrv $kpath} msg]} {
		puts stderr "can't list drivers in '$kpath' : $msg";
	    }
	}
	default {
	    puts stderr "unknown command '$mode'";
	    usage ;
	}
    }
}



################################################################################
main;
@


1.6.2.1
log
@file KernelDriver was added on branch RELENG_8_4 on 2013-03-28 13:05:58 +0000
@
text
@d1 1081
@


1.6.2.2
log
@## SVN ## Exported commit - http://svnweb.freebsd.org/changeset/base/248810
## SVN ## CVS IS DEPRECATED: http://wiki.freebsd.org/CvsIsDeprecated
@
text
@a0 1081
#!/bin/sh
# Tcl magic -*- tcl -*- \
exec tclsh $0 $*
################################################################################
#
# KernelDriver - FreeBSD driver source installer
#
################################################################################
#
# Copyright (C) 1997
#      Michael Smith.  All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. Neither the name of the author nor the names of any co-contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Michael Smith AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL Michael Smith OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
################################################################################
#
# KernelDriver provides a means for installing source-form drivers into FreeBSD 
# kernel source trees in an automated fashion.  It can also remove drivers it 
# has installed.
#
# Driver information is read from a control file, with the following syntax :
#
# description {<text>}		Driver description; used in comments inserted into
#				files.
# driver <name>			The name of the driver. (Note that this can't end in .drvinfo :)
# filei386 <path> <name>	The file <name> in the driver package is installed into
#				<path> in the kernel source tree.  Files whose names
#				end in '.c' have an entry added to i386/conf/files.i386.
# fileconf <path> <name>	The file <name> in the driver package is installed into
#				<path> in the kernel source tree.  Files whose names
#				end in '.c' have an entry added to conf/files.
# optioni386 <name> <hdr>	Adds an entry to i386/conf/options.i386, such that
#				the option <name> will be placed in the header <hdr>.
# optionconf <name> <hdr>	Adds an entry to conf/options, such that
#				the option <name> will be placed in the header <hdr>.
# linttext			Lines between this and a subsequent 'end' line are added
#				to the LINT file to provide configuration examples,
#				comments, etc.
# end				Ends a text region.
# 
# Possible additions :
#
# patch <name>		Applies the patch contained in <name>; patch is invoked
#			at the top level of the kernel source tree, and the 
#			patch must apply cleanly (this is checked).
#
# option <name> <file>	Adds an entry to i386/conf/options.i386
#
# Lines beginning with '#' or blanks are considered comments, except in
# 'linttext' regions.
#
################################################################################
#
# $FreeBSD: releng/8.4/tools/tools/kdrv/KernelDriver 72645 2001-02-18 10:43:53Z asmodai $
#
################################################################################

################################################################################
# findDrvFile
#
# Given (hint), use it to locate a driver information file.
# (Possible extension; support drivers in gzipped tarballs...)
#
proc findDrvFile_try {hint} {

    # points to something already
    if {[file exists $hint]} {
	# unwind symbolic links
	while {[file type $hint] == "link"} {
	    set hint [file readlink $hint];
	}
	switch [file type $hint] {
	    file {
		# run with it as it is
		return $hint;
	    }
	    directory {
		# look for a drvinfo file in the directory
		set candidate [glob -nocomplain "$hint/*.drvinfo"];
		switch [llength $candidate] {
		    0 {
			# nothing there
		    }
		    1 {
			return $candidate;
		    }
		    default {
			error "multiple driver info files in directory : $hint";
		    }
		}
	    }
	    default {
		error "driver info file may be a typewriter : $hint";
	    }
	}
    }
    # maybe we need an extension
    if {[file exists $hint.drvinfo]} {
	return $hint.drvinfo;
    }
    error "can't find a driver info file using '$hint'";
}

proc findDrvFile {hint} {

    set result [findDrvFile_try $hint];
    if {$result != ""} {
	return $result;
    }
    set result [findDrvFile_try ${hint}.drvinfo];
    if {$result != ""} {
	return $result;
    }
    error "can't find driver information file using : $hint";
}

################################################################################
# readDrvFile
#
# Reads the contents of (fname), which are expected to be in the format 
# described above, and fill in the global Drv array.
#
proc readDrvFile {fname} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ read options from '$fname'";}
    set fh [open $fname r];
    
    # set defaults
    set Drv(description) "";
    set Drv(driver) "";
    set Drv(filesi386) "";
    set Drv(filesconf) "";
    set Drv(optionsi386) "";
    set Drv(optionsconf) "";
    set Drv(patches) "";
    set Drv(linttext) "";

    while {[gets $fh line] >= 0} {
	
	# blank lines/comments
	if {([llength $line] == 0) ||
	    ([string index $line 0] == "\#")} {
	    continue ;
	}

	# get keyword, process
	switch -- [lindex $line 0] {
	    description {
		set Drv(description) [lindex $line 1];
	    }
	    driver {
		set Drv(driver) [lindex $line 1];
	    }
	    filei386 {
		set path [lindex $line 1];
		set plast [expr [string length $path] -1];
		if {[string index $path $plast] != "/"} {
		    append path "/";
		}
		set name [lindex $line 2];
		set Drv(filei386:$name) $path;
		lappend Drv(filesi386) $name;
	    }
	    fileconf {
		set path [lindex $line 1];
		set plast [expr [string length $path] -1];
		if {[string index $path $plast] != "/"} {
		    append path "/";
		}
		set name [lindex $line 2];
		set Drv(fileconf:$name) $path;
		lappend Drv(filesconf) $name;
	    }
	    optioni386 {
		set opt [lindex $line 1];
		set hdr [lindex $line 2];
		lappend Drv(optionsi386) $opt;
		set Drv(optioni386:$opt) $hdr;
	    }
	    optionconf {
		set opt [lindex $line 1];
		set hdr [lindex $line 2];
		lappend Drv(optionsconf) $opt;
		set Drv(optionconf:$opt) $hdr;
	    }
	    patch {
		lappend Drv(patches) [lindex $line 1];
	    }
	    linttext {
		while {[gets $fh line] >= 0} {
		    if {$line == "end"} {
			break ;
		    }
		    lappend Drv(linttext) $line;
		}
	    }
	}
    }
    close $fh;
    if {$Options(verbose)} {
	printDrv;
    }
}
		
################################################################################
# validateDrvPackage
#
# With the global Drv filled in, check that the files required are all in
# (dir), and that the kernel config at (kpath) can be written.
#
proc validateDrvPackage {dir kpath} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ checking driver package...";}
    set missing "";
    set unwritable "";

    # check files, patches
    foreach f $Drv(filesi386) {
	if {![file readable $dir$f]} {
	    lappend missing $f;
	}
    }
    foreach f $Drv(filesconf) {
	if {![file readable $dir$f]} {
	    lappend missing $f;
	}
    }
    foreach f $Drv(patches) {
	if {![file readable $dir$f]} {
	    lappend missing $f;
	}
    }
    if {$missing != ""} {
	error "missing files : $missing";
    }

    # check writability
    if {$Options(verbose)} {puts "+ checking kernel source writability...";}
    foreach f $Drv(filesi386) {
	set p $Drv(filei386:$f);
	if {![file isdirectory $kpath$p]} {
	    lappend missing $p;
	} else {
	    if {![file writable $kpath$p]} {
		if {[lsearch -exact $unwritable $p] == -1} {
		    lappend unwritable $p;
		}
	    }
	}
    }
    foreach f $Drv(filesconf) {
	set p $Drv(fileconf:$f);
	if {![file isdirectory $kpath$p]} {
	    lappend missing $p;
	} else {
	    if {![file writable $kpath$p]} {
		if {[lsearch -exact $unwritable $p] == -1} {
		    lappend unwritable $p;
		}
	    }
	}
    }
    foreach f [list \
		   "conf/files" \
		   "i386/conf/files.i386" \
		   "i386/conf/options.i386" \
		   "i386/conf/LINT"] {
	if {![file writable $kpath$f]} {
	    lappend unwritable $f;
	}
    }
    if {$missing != ""} {
	error "missing directories : $missing";
    }
    if {$unwritable != ""} {
	error "can't write to : $unwritable";
    }
}

################################################################################
# installDrvFiles
#
# Install the files listed in the global Drv into (kpath) from (dir)
#
proc installDrvFiles {dir kpath} {

    global Drv Options;

    # clear 'installed' record
    set Drv(installedi386) "";
    set Drv(installedconf) "";
    set failed "";

    if {$Options(verbose)} {puts "+ installing driver files...";}
    foreach f $Drv(filesi386) {
	if {$Options(verbose)} {puts "$f -> $kpath$Drv(filei386:$f)";}
	if {$Options(real)} {
	    if {[catch {exec cp $dir$f $kpath$Drv(filei386:$f)} msg]} {
		lappend failed $f;
	    } else {
		lappend Drv(installedi386) $f;
	    }
	}
    }
    foreach f $Drv(filesconf) {
	if {$Options(verbose)} {puts "$f -> $kpath$Drv(fileconf:$f)";}
	if {$Options(real)} {
	    if {[catch {exec cp $dir$f $kpath$Drv(fileconf:$f)} msg]} {
		lappend failed $f;
	    } else {
		lappend Drv(installedconf) $f;
	    }
	}
    }
    if {$failed != ""} {
	error "failed to install files : $failed";
    }
}

################################################################################
# backoutDrvChanges
#
# Remove files from a failed installation in (kpath)
#
proc backoutDrvChanges {kpath} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ backing out installed files...";}
    # delete installed files
    foreach f $Drv(installedi386) {
	exec rm -f $kpath$Drv(filei386:$f)$f;
    }
    foreach f $Drv(installedconf) {
	exec rm -f $kpath$Drv(fileconf:$f)$f;
    }
}

################################################################################
# registerDrvFiles
#
# Adds an entry to i386/conf/files.i386 and conf/files for the .c files in the driver.  
# (kpath) points to the kernel.
#
# A comment is added to the file preceding the new entries :
#
#  ## driver: <drivername>
#  # <description>
#  # filei386: <path><file>
#  <file spec (.c files only)>
#  ## enddriver
#
# We only append to the end of the file.
#
# Add linttext to the LINT file.
# Add options to i386/conf/options.i386 if any are specified
#
proc registerDrvFiles {kpath} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ registering installed files...";}

# Add stuff to LINT
    if {$Drv(linttext) != ""} {

	if {$Options(verbose)} {puts "+ updating LINT...";}
	if {$Options(real)} {
	    set fname [format "%si386/conf/LINT" $kpath];
	    set fh [open $fname a];

	    # header
	    puts $fh "\#\# driver: $Drv(driver)";
	    puts $fh "\# $Drv(description)";
	    foreach l $Drv(linttext) {
		puts $fh $l;
	    }
	    puts $fh "\#\# enddriver";
	    close $fh;
	}
    }

# Do filesi386 stuff
    if {$Options(real)} {
	set fname [format "%si386/conf/files.i386" $kpath];
	set fh [open $fname a];

	# header
	puts $fh "\#\# driver: $Drv(driver)";
	puts $fh "\# $Drv(description)";
	# file information
	foreach f $Drv(filesi386) {
	    puts $fh "\# file: $Drv(filei386:$f)$f";
	    # is it a compilable object?
	    if {[string match "*.c" $f]} {
		puts $fh "$Drv(filei386:$f)$f\t\toptional\t$Drv(driver)\tdevice-driver";
	    }
	}
	puts $fh "\#\# enddriver";
	close $fh;
    }
    if {$Drv(optionsi386) != ""} {
	if {$Options(verbose)} {puts "+ adding options...";}
	if {$Options(real)} {
	    set fname [format "%si386/conf/options.i386" $kpath];
	    set fh [open $fname a];

	    # header
	    puts $fh "\#\# driver: $Drv(driver)";
	    puts $fh "\# $Drv(description)";
	    # options
	    foreach opt $Drv(optionsi386) {
		puts $fh "$opt\t$Drv(optioni386:$opt)";
	    }
	    puts $fh "\#\# enddriver";
	    close $fh;
	}
    }

# Do filesconf stuff
    if {$Options(real)} {
	set fname [format "%sconf/files" $kpath];
	set fh [open $fname a];

	# header
	puts $fh "\#\# driver: $Drv(driver)";
	puts $fh "\# $Drv(description)";
	# file information
	foreach f $Drv(filesconf) {
	    puts $fh "\# file: $Drv(fileconf:$f)$f";
	    # is it a compilable object?
	    if {[string match "*.c" $f]} {
		puts $fh "$Drv(fileconf:$f)$f\t\toptional\t$Drv(driver)\tdevice-driver";
	    }
	}
	puts $fh "\#\# enddriver";
	close $fh;
    }
     if {$Drv(optionsconf) != ""} {
 	if {$Options(verbose)} {puts "+ adding options...";}
 	if {$Options(real)} {
 	    set fname [format "%sconf/options" $kpath];
 	    set fh [open $fname a];

 	    # header
 	    puts $fh "\#\# driver: $Drv(driver)";
 	    puts $fh "\# $Drv(description)";
 	    # options
 	    foreach opt $Drv(optionsconf) {
 		puts $fh "$opt\t$Drv(optionconf:$opt)";
 	    }
 	    puts $fh "\#\# enddriver";
 	    close $fh;
 	}
     }

}

################################################################################
# listInstalledDrv
#
# List all drivers recorded as installed, in the kernel at (kpath)
#
# XXX : fix me so I understand conf/{options,files} stuff!
proc listInstalledDrv {kpath} {

    global Drv;

    # pick up all the i386 options information first
    set fname [format "%si386/conf/options.i386" $kpath];
    if {![file readable $fname]} {
	error "not a kernel directory";
    }
    set fh [open $fname r];

    while {[gets $fh line] >= 0} {
    
	# got a driver?
	if {[scan $line "\#\# driver: %s" driver] == 1} {
	    # read driver details, ignore
	    gets $fh line;
	    # loop reading option details
	    while {[gets $fh line] >= 0} {
		# end of driver info
		if {$line == "\#\# enddriver"} {
		    break ;
		}
		# parse option/header tuple
		if {[scan $line "%s %s" opt hdr] == 2} {
		    # remember that this driver uses this option
		    lappend drivers($driver:optionsi386) $opt;
		    # remember that this option goes in this header
		    set optionsi386($opt) $hdr;
		}
	    }
	}
    }
    close $fh;

    # pick up all the conf options information first
    set fname [format "%sconf/options" $kpath];
    if {![file readable $fname]} {
	error "not a kernel directory";
    }
    set fh [open $fname r];

    while {[gets $fh line] >= 0} {
    
	# got a driver?
	if {[scan $line "\#\# driver: %s" driver] == 1} {
	    # read driver details, ignore
	    gets $fh line;
	    # loop reading option details
	    while {[gets $fh line] >= 0} {
		# end of driver info
		if {$line == "\#\# enddriver"} {
		    break ;
		}
		# parse option/header tuple
		if {[scan $line "%s %s" opt hdr] == 2} {
		    # remember that this driver uses this option
		    lappend drivers($driver:optionsconf) $opt;
		    # remember that this option goes in this header
		    set optionsconf($opt) $hdr;
		}
	    }
	}
    }
    close $fh;

    set fname [format "%si386/conf/files.i386" $kpath];
    set fh [open $fname r];
    
    while {[gets $fh line] >= 0} {

	# got a driver? 
	if {[scan $line "\#\# driver: %s" driver] == 1} {
	    # clear global and reset
	    catch {unset Drv};
	    set Drv(driver) $driver;
	    # read driver details
	    gets $fh line;
	    set Drv(description) [string range $line 2 end];
	    set Drv(filesi386) "";
	    # options?
	    if {[info exists drivers($Drv(driver):optionsi386)]} {
		set Drv(optionsi386) $drivers($Drv(driver):optionsi386);
		# get pathnames
		foreach opt $Drv(optionsi386) {
		    set Drv(optioni386:$opt) $optionsi386($opt);
		}
	    }
	    # loop reading file details
	    while {[gets $fh line] >= 0} {
		if {$line == "\#\# enddriver"} {
		    # print this driver and loop
		    printDrv;
		    break ;
		}
		if {[scan $line "\# filei386: %s" fpath] == 1} {
		    set f [file tail $fpath];	
		    set Drv(filei386:$f) "[file dirname $fpath]/";
		    lappend Drv(filesi386) $f;
		}
	    }
	}
    }
    close $fh;

    set fname [format "%sconf/files" $kpath];
    set fh [open $fname r];
    
    while {[gets $fh line] >= 0} {

	# got a driver? 
	if {[scan $line "\#\# driver: %s" driver] == 1} {
	    # clear global and reset
	    catch {unset Drv};
	    set Drv(driver) $driver;
	    # read driver details
	    gets $fh line;
	    set Drv(description) [string range $line 2 end];
	    set Drv(filesconf) "";
	    # options?
	    if {[info exists drivers($Drv(driver):optionsconf)]} {
		set Drv(optionsconf) $drivers($Drv(driver):optionsconf);
		# get pathnames
		foreach opt $Drv(optionsconf) {
		    set Drv(optionconf:$opt) $optionsconf($opt);
		}
	    }
	    # loop reading file details
	    while {[gets $fh line] >= 0} {
		if {$line == "\#\# enddriver"} {
		    # print this driver and loop
		    printDrv;
		    break ;
		}
		if {[scan $line "\# fileconf: %s" fpath] == 1} {
		    set f [file tail $fpath];	
		    set Drv(fileconf:$f) "[file dirname $fpath]/";
		    lappend Drv(filesconf) $f;
		}
	    }
	}
    }
    close $fh;
}

################################################################################
# printDrv
#
# Print the contents of the global Drv.
#
proc printDrv {} {

    global Drv Options;

    puts "$Drv(driver) : $Drv(description)";
    if {$Options(verbose)} {
	foreach f $Drv(filesi386) {
	    puts " $Drv(filei386:$f)$f"
	}
	foreach f $Drv(filesconf) {
	    puts " $Drv(fileconf:$f)$f"
	}
	if {[info exists Drv(optionsi386)]} {
	    foreach opt $Drv(optionsi386) {
		puts " $opt in $Drv(optioni386:$opt)";
	    }
	}
	if {[info exists Drv(optionsconf)]} {
	    foreach opt $Drv(optionsconf) {
		puts " $opt in $Drv(optionconf:$opt)";
	    }
	}
    }
}

################################################################################
# findInstalledDrv
#
# Given a kernel tree at (kpath), get driver details about an installed
# driver (drvname)
#

proc findInstalledDrvi386 {drvname kpath} {

    global Drv;

    set fname [format "%si386/conf/files.i386" $kpath];
    set fh [open $fname r];
    
    puts "checking i386/conf/files.i386";

    while {[gets $fh line] >= 0} {
	if {[scan $line "\#\# driver: %s" name] == 1} {
	    if {$name != $drvname} {
		continue ;		# not us
	    }
	    # read information
	    set Drv(driver) $drvname;
	    set line [gets $fh];
	    set Drv(description) [string range $line 2 end];
	    set Drv(filesi386) "";
	    # loop reading file details
	    while {[gets $fh line] >= 0} {
		if {$line == "\#\# enddriver"} {
		    close $fh;
		    return 1;		# all done
		}
		if {[scan $line "\# file: %s" fpath] == 1} {
		    set f [file tail $fpath];	
		    set Drv(filei386:$f) "[file dirname $fpath]/";
		    lappend Drv(filesi386) $f;
		}
	    }
	    close $fh;
	    error "unexpected EOF reading '$fname'";
	}
    }
    close $fh

    return 0;
}

proc findInstalledDrvconf {drvname kpath} {

    global Drv;

    set fname [format "%sconf/files" $kpath];
    set fh [open $fname r];

    puts "checking conf/files";
    
    while {[gets $fh line] >= 0} {
	if {[scan $line "\#\# driver: %s" name] == 1} {
	    if {$name != $drvname} {
		continue ;		# not us
	    }
	    # read information
	    set Drv(driver) $drvname;
	    set line [gets $fh];
	    set Drv(description) [string range $line 2 end];
	    set Drv(filesconf) "";
	    # loop reading file details
	    while {[gets $fh line] >= 0} {
		if {$line == "\#\# enddriver"} {
		    close $fh;
		    return 1;		# all done
		}
		if {[scan $line "\# file: %s" fpath] == 1} {
		    set f [file tail $fpath];	
		    set Drv(fileconf:$f) "[file dirname $fpath]/";
		    lappend Drv(filesconf) $f;
		}
	    }
	    close $fh;
	    error "unexpected EOF reading '$fname'";
	}
    }
    close $fh

    return 0;
}

proc findInstalledDrv {drvname kpath} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ look for driver '$drvname' in '$kpath'";}

# Whoops... won't work in a single if statement due to expression shortcircuiting
    set a [findInstalledDrvi386 $drvname $kpath];
    set b [findInstalledDrvconf $drvname $kpath];
    if {$a || $b} {
	return;
    }

    error "driver '$drvname' not recorded as installed";
}

################################################################################
# validateDrvRemoval
#
# Verify that we can remove the driver described in the global Drv installed
# at (kpath).
#
proc validateDrvRemoval {kpath} {

    global Drv Options;

    set missing "";
    set unwritable "";

    if {$Options(verbose)} {puts "+ checking for removabilty...";}

    # admin files?
    foreach f [list \
		   "i386/conf/files.i386" \
		   "i386/conf/options.i386" \
		   "i386/conf/LINT" \
		   "conf/files" \
		   "conf/options" ] { 
	if {![file exists $kpath$f]} {
	    lappend missing $kpath$f;
	} else {
	    if {![file writable $kpath$f]} {
		lappend unwritable $f;
	    }
	}
    }
    # driver components?
    foreach f $Drv(filesi386) {
	set p $Drv(filei386:$f);
	if {![file isdirectory $kpath$p]} {
	    lappend missing $p;
	} else {
	    if {![file writable $kpath$p]} {
		if {[lsearch -exact $unwritable $p] == -1} {
		    lappend unwritable $p;
		}
	    }
	}
    }
    foreach f $Drv(filesconf) {
	set p $Drv(fileconf:$f);
	if {![file isdirectory $kpath$p]} {
	    lappend missing $p;
	} else {
	    if {![file writable $kpath$p]} {
		if {[lsearch -exact $unwritable $p] == -1} {
		    lappend unwritable $p;
		}
	    }
	}
    }
    if {$missing != ""} {
	error "files/directories missing : $missing";
    }
    if {$unwritable != ""} {
	error "can't write to : $unwritable";
    }
}

################################################################################
# deleteDrvFiles
#
# Delete the files belonging to the driver devfined in the global Drv in
# the kernel tree at (kpath)
#
proc deleteDrvFiles {kpath} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ delete driver files...";}

    # loop deleting files
    foreach f $Drv(filesi386) {
	if {$Options(verbose)} {puts "- $Drv(filei386:$f)$f";}
	if {$Options(real)} {
	    exec rm $kpath$Drv(filei386:$f)$f;
	}
    }
    foreach f $Drv(filesconf) {
	if {$Options(verbose)} {puts "- $Drv(fileconf:$f)$f";}
	if {$Options(real)} {
	    exec rm $kpath$Drv(fileconf:$f)$f;
	}
    }
}    

################################################################################
# unregisterDrvFiles
#
# Remove any mention of the current driver from the files.i386 and LINT
# files in (ksrc)
#
proc unregisterDrvFiles {ksrc} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ deregister driver files...";}

    # don't really do it?
    if {!$Options(real)} { return ; }

    foreach f [list \
		   "i386/conf/files.i386" \
		   "i386/conf/options.i386" \
		   "i386/conf/LINT" \
		   "conf/files" \
		   "conf/options" ] {
	set ifh [open $ksrc$f r];
	set ofh [open $ksrc$f.new w];
	set copying 1;

	while {[gets $ifh line] >= 0} {

	    if {[scan $line "\#\# driver: %s" name] == 1} {
		if {$name == $Drv(driver)} {
		    set copying 0;			# don't copy this one
		}
	    }
	    if {$copying} {
		puts $ofh $line;		# copy through
	    }
	    if {$line == "\#\# enddriver"} {	# end of driver detail
		set copying 1;
	    }
	}
	close $ifh;
	close $ofh;
	exec mv $ksrc$f.new $ksrc$f;		# move new over old
    }
}

################################################################################
# usage
#
# Remind the user what goes where
#
proc usage {} {

    global argv0;

    set progname [file tail $argv0];

    puts stderr "Usage is :";
    puts stderr "  $progname \[-v -n\] add <drvinfo> \[<kpath>\]";
    puts stderr "  $progname \[-v -n\] delete <drvname> \[<kpath>\]";
    puts stderr "  $progname \[-v\] list \[<kpath>\]";
    puts stderr "  <drvinfo> is a driver info file";
    puts stderr "  <drvname> is a driver name";
    puts stderr "  <kpath> is the path to the kernel source (default /sys/)";
    puts stderr "  -v  be verbose";
    puts stderr "  -n  don't actually do anything";
    exit ;
}

################################################################################
# getOptions
#
# Parse commandline options, return anything that doesn't look like an option
#
proc getOptions {} {

    global argv Options;

    set Options(real) 1;
    set Options(verbose) 0;
    set ret "";
    
    for {set index 0} {$index < [llength $argv]} {incr index} {
	
	switch -- [lindex $argv $index] {

	    -n {
		set Options(real) 0;		# 'do-nothing' mode
	    }
	    -v {
		set Options(verbose) 1;		# brag
	    }
	    default {
		lappend ret [lindex $argv $index];
	    }
	}
    }
    return $ret;
}

################################################################################
# getKpath
#
# Given (hint), return the kernel path.  If (hint) is empty, return /sys.
# If the kernel path is not a directory, complain and dump the usage.
#
proc getKpath {hint} {

    set kpath "";

    # check the kernel path
    if {$hint == ""} {
	set kpath "/sys/";
    } else {
	set kpath $hint;
    }
    if {![file isdirectory $kpath]} {
	puts "not a directory : $kpath";
	usage ;
    }
    set plast [expr [string length $kpath] -1];
    if {[string index $kpath $plast] != "/"} {
	append kpath "/";
    }
    return $kpath;
}

################################################################################
# main
#
# Start somewhere here.
#
proc main {} {

    global Options;

    # Work out what we're trying to do
    set cmdline [getOptions];
    set mode [lindex $cmdline 0];

    # do stuff
    switch -- $mode {
	add {
	    set hint [lindex $cmdline 1];
	    set kpath [getKpath [lindex $cmdline 2]];

	    # check driver file argument
	    if {[catch {set drv [findDrvFile $hint]} msg]} {
		puts stderr $msg;
		usage ;
	    }
	    if {([file type $drv] != "file") ||
		![file readable $drv]} {
		puts "can't read driver file : $drv";
		usage ; 
	    }
	    set drvdir "[file dirname $drv]/";

	    # read driver file
	    if {[catch {readDrvFile $drv} msg]} {
		puts stderr $msg;
		exit ;
	    }
	    # validate driver
	    if {[catch {validateDrvPackage $drvdir $kpath} msg]} {
		puts stderr $msg;
		exit ;
	    }
	    # install new files
	    if {[catch {installDrvFiles $drvdir $kpath} msg]} {
		backoutDrvChanges $kpath;		# oops, unwind
		puts stderr $msg;
		exit ;
	    }
	    # register files in config
	    if {[catch {registerDrvFiles $kpath} msg]} {
		backoutDrvChanges $kpath;		# oops, unwind
		puts stderr $msg;
		exit ;
	    }
	}
	delete {
	    set drv [lindex $cmdline 1];
	    set kpath [getKpath [lindex $cmdline 2]];

	    if {[string last ".drvinfo" $drv] != -1} {
		set drv [string range $drv 0 [expr [string length $drv] - 9]];
		puts "Driver name ends in .drvinfo, removing, is now $drv";
	    }

	    if {[catch {findInstalledDrv $drv $kpath} msg]} {
		puts stderr $msg;
		exit ;
	    }
	    if {[catch {validateDrvRemoval $kpath} msg]} {
		puts stderr $msg;
		exit ;
	    }
	    if {[catch {unregisterDrvFiles $kpath} msg]} {
		puts stderr $msg;
		exit ;
	    }
	    if {[catch {deleteDrvFiles $kpath} msg]} {
		puts stderr $msg;
		exit ;
	    }
	}
	list { 
	    set kpath [getKpath [lindex $cmdline 1]];
	    if {[catch {listInstalledDrv $kpath} msg]} {
		puts stderr "can't list drivers in '$kpath' : $msg";
	    }
	}
	default {
	    puts stderr "unknown command '$mode'";
	    usage ;
	}
    }
}



################################################################################
main;
@


1.5
log
@Preceed/preceeding are not english words.  Use precede and preceding.
@
text
@d76 1
a76 1
# $FreeBSD: src/tools/tools/kdrv/KernelDriver,v 1.4 1999/08/28 00:54:29 peter Exp $
@


1.5.24.1
log
@Switch importer
@
text
@d76 1
a76 1
# $FreeBSD: stable/7/tools/tools/kdrv/KernelDriver 72645 2001-02-18 10:43:53Z asmodai $
@


1.5.14.1
log
@Switch importer
@
text
@d76 1
a76 1
# $FreeBSD: stable/6/tools/tools/kdrv/KernelDriver 72645 2001-02-18 10:43:53Z asmodai $
@


1.5.42.1
log
@SVN rev 225736 on 2011-09-23 00:51:37Z by kensmith

Copy head to stable/9 as part of 9.0-RELEASE release cycle.

Approved by:	re (implicit)
@
text
@d76 1
a76 1
# $FreeBSD$
@


1.5.42.2
log
@## SVN ##
## SVN ## Exported commit - http://svnweb.freebsd.org/changeset/base/ 242902
## SVN ## CVS IS DEPRECATED: http://wiki.freebsd.org/CvsIsDeprecated
## SVN ##
## SVN ## ------------------------------------------------------------------------
## SVN ## r242902 | dteske | 2012-11-11 23:29:45 +0000 (Sun, 11 Nov 2012) | 10 lines
## SVN ##
## SVN ## Fix a regression introduced by SVN r211417 that saw the breakage of a feature
## SVN ## documented in usr.sbin/sysinstall/help/shortcuts.hlp (reproduced below):
## SVN ##
## SVN ## If /usr/sbin/sysinstall is linked to another filename, say
## SVN ## `/usr/local/bin/configPackages', then the basename will be used
## SVN ## as an implicit command name.
## SVN ##
## SVN ## Reviewed by:	adrian (co-mentor)
## SVN ## Approved by:	adrian (co-mentor)
## SVN ##
## SVN ## ------------------------------------------------------------------------
## SVN ##
@
text
@d76 1
a76 1
# $FreeBSD: stable/9/tools/tools/kdrv/KernelDriver 72645 2001-02-18 10:43:53Z asmodai $
@


1.5.42.1.4.1
log
@SVN rev 239080 on 2012-08-05 23:54:33Z by kensmith

Copy stable/9 to releng/9.1 as part of the 9.1-RELEASE release process.

Approved by:	re (implicit)
@
text
@@


1.5.42.1.4.2
log
@Switch importer
@
text
@d76 1
a76 1
# $FreeBSD: releng/9.1/tools/tools/kdrv/KernelDriver 72645 2001-02-18 10:43:53Z asmodai $
@


1.5.42.1.2.1
log
@SVN rev 227445 on 2011-11-11 04:20:22Z by kensmith

Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
cycle.

Approved by:	re (implicit)
@
text
@@


1.5.42.1.2.2
log
@Switch importer
@
text
@d76 1
a76 1
# $FreeBSD: releng/9.0/tools/tools/kdrv/KernelDriver 72645 2001-02-18 10:43:53Z asmodai $
@


1.5.40.1
log
@SVN rev 216618 on 2010-12-21 17:10:29Z by kensmith

Copy stable/7 to releng/7.4 in preparation for FreeBSD-7.4 release.

Approved by:	re (implicit)
@
text
@d76 1
a76 1
# $FreeBSD$
@


1.5.40.2
log
@Switch importer
@
text
@d76 1
a76 1
# $FreeBSD: releng/7.4/tools/tools/kdrv/KernelDriver 72645 2001-02-18 10:43:53Z asmodai $
@


1.5.38.1
log
@SVN rev 203736 on 2010-02-10 00:26:20Z by kensmith

Copy stable/7 to releng/7.3 as part of the 7.3-RELEASE process.

Approved by:	re (implicit)
@
text
@d76 1
a76 1
# $FreeBSD$
@


1.5.36.1
log
@SVN rev 196045 on 2009-08-03 08:13:06Z by kensmith

Copy head to stable/8 as part of 8.0 Release cycle.

Approved by:	re (Implicit)
@
text
@d76 1
a76 1
# $FreeBSD$
@


1.5.36.2
log
@## SVN ##
## SVN ## Exported commit - http://svnweb.freebsd.org/changeset/base/ 242909
## SVN ## CVS IS DEPRECATED: http://wiki.freebsd.org/CvsIsDeprecated
## SVN ##
## SVN ## ------------------------------------------------------------------------
## SVN ## r242909 | dim | 2012-11-12 07:47:19 +0000 (Mon, 12 Nov 2012) | 20 lines
## SVN ##
## SVN ## MFC r242625:
## SVN ##
## SVN ## Remove duplicate const specifiers in many drivers (I hope I got all of
## SVN ## them, please let me know if not).  Most of these are of the form:
## SVN ##
## SVN ## static const struct bzzt_type {
## SVN ##       [...list of members...]
## SVN ## } const bzzt_devs[] = {
## SVN ##       [...list of initializers...]
## SVN ## };
## SVN ##
## SVN ## The second const is unnecessary, as arrays cannot be modified anyway,
## SVN ## and if the elements are const, the whole thing is const automatically
## SVN ## (e.g. it is placed in .rodata).
## SVN ##
## SVN ## I have verified this does not change the binary output of a full kernel
## SVN ## build (except for build timestamps embedded in the object files).
## SVN ##
## SVN ## Reviewed by:	yongari, marius
## SVN ##
## SVN ## ------------------------------------------------------------------------
## SVN ##
@
text
@d76 1
a76 1
# $FreeBSD: stable/8/tools/tools/kdrv/KernelDriver 72645 2001-02-18 10:43:53Z asmodai $
@


1.5.36.1.8.1
log
@SVN rev 232438 on 2012-03-03 06:15:13Z by kensmith

Copy stable/8 to releng/8.3 as part of 8.3-RELEASE release cycle.

Approved by:	re (implicit)
@
text
@@


1.5.36.1.8.2
log
@Switch importer
@
text
@d76 1
a76 1
# $FreeBSD: releng/8.3/tools/tools/kdrv/KernelDriver 72645 2001-02-18 10:43:53Z asmodai $
@


1.5.36.1.6.1
log
@SVN rev 216617 on 2010-12-21 17:09:25Z by kensmith

Copy stable/8 to releng/8.2 in preparation for FreeBSD-8.2 release.

Approved by:	re (implicit)
@
text
@@


1.5.36.1.4.1
log
@SVN rev 209145 on 2010-06-14 02:09:06Z by kensmith

Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.

Approved by:	re (implicit)
@
text
@@


1.5.36.1.2.1
log
@SVN rev 198460 on 2009-10-25 01:10:29Z by kensmith

Copy stable/8 to releng/8.0 as part of 8.0-RELEASE release procedure.

Approved by:	re (implicit)
@
text
@@


1.5.34.1
log
@SVN rev 191087 on 2009-04-15 03:14:26Z by kensmith

Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.

Approved by:	re (implicit)
@
text
@d76 1
a76 1
# $FreeBSD$
@


1.5.32.1
log
@SVN rev 185281 on 2008-11-25 02:59:29Z by kensmith

Create releng/7.1 in preparation for moving into RC phase of 7.1 release
cycle.

Approved by:	re (implicit)
@
text
@d76 1
a76 1
# $FreeBSD$
@


1.5.30.1
log
@SVN rev 183531 on 2008-10-02 02:57:24Z by kensmith

Create releng/6.4 from stable/6 in preparation for 6.4-RC1.

Approved by:	re (implicit)
@
text
@d76 1
a76 1
# $FreeBSD$
@


1.4
log
@$Id$ -> $FreeBSD$
@
text
@d76 1
a76 1
# $FreeBSD$
d371 1
a371 1
# A comment is added to the file preceeding the new entries :
@


1.4.2.1
log
@MFC: 1.5: correct typo
@
text
@d76 1
a76 1
# $FreeBSD: src/tools/tools/kdrv/KernelDriver,v 1.4 1999/08/28 00:54:29 peter Exp $
d371 1
a371 1
# A comment is added to the file preceding the new entries :
@


1.4.2.2
log
@Switch importer
@
text
@d76 1
a76 1
# $FreeBSD: stable/4/tools/tools/kdrv/KernelDriver 73734 2001-03-05 12:17:23Z kris $
@


1.3
log
@Updates to support adding driver files outside the i386 area.
Submitted by:	Daniel O'Connor <doconnor@@gsoft.com.au>
@
text
@d76 1
a76 1
# $Id: KernelDriver,v 1.4 1998/05/04 03:30:43 doconnor Exp $
@


1.3.2.1
log
@$Id$ -> $FreeBSD$
@
text
@d76 1
a76 1
# $FreeBSD$
@


1.2
log
@Some helpful improvements :

 - be smarter about locating driver description files.
 - be smarter about whether we are really looking at a kernel tree
 - fix option handling
@
text
@d45 17
a61 12
# description {<text>}	Driver description; used in comments inserted into
#			files.
# driver <name>		The name of the driver.
# file <path> <name>	The file <name> in the driver package is installed into
#			<path> in the kernel source tree.  Files whose names
#			end in '.c' have an entry added to i386/conf/files.i386.
# option <name> <hdr>	Adds an entry to i386/conf/options.i386, such that
#			the option <name> will be placed in the header <hdr>.
# linttext		Lines between this and a subsequent 'end' line are added
#			to the LINT file to provide configuration examples,
#			comments, etc.
# end			Ends a text region.
d76 1
a76 1
# $Id: KernelDriver,v 1.1.1.1 1997/01/21 08:34:14 msmith Exp $
d155 4
a158 2
    set Drv(files) "";
    set Drv(options) "";
d178 11
a188 1
	    file {
d195 8
a202 2
		set Drv(file:$name) $path;
		lappend Drv(files) $name;
d204 1
a204 1
	    option {
d207 2
a208 2
		lappend Drv(options) $opt;
		set Drv(option:$opt) $hdr;
d244 6
a249 1
    foreach f $Drv(files) {
d265 14
a278 2
    foreach f $Drv(files) {
	set p $Drv(file:$f);
d290 1
d316 2
a317 1
    set Drv(installed) "";
d321 12
a332 2
    foreach f $Drv(files) {
	if {$Options(verbose)} {puts "$f -> $kpath$Drv(file:$f)";}
d334 1
a334 1
	    if {[catch {exec cp $dir$f $kpath$Drv(file:$f)} msg]} {
d337 1
a337 1
		lappend Drv(installed) $f;
d357 5
a361 2
    foreach f $Drv(installed) {
	exec rm -f $kpath$Drv(file:$f)$f;
d368 1
a368 1
# Adds an entry to i386/conf/files.i386 for the .c files in the driver.  
d375 1
a375 1
#  # file: <path><file>
d390 1
a390 18
    if {$Options(real)} {
	set fname [format "%si386/conf/files.i386" $kpath];
	set fh [open $fname a];

	# header
	puts $fh "\#\# driver: $Drv(driver)";
	puts $fh "\# $Drv(description)";
	# file information
	foreach f $Drv(files) {
	    puts $fh "\# file: $Drv(file:$f)$f";
	    # is it a compilable object?
	    if {[string match "*.c" $f]} {
		puts $fh "$Drv(file:$f)$f\t\toptional\t$Drv(driver)\tdevice-driver";
	    }
	}
	puts $fh "\#\# enddriver";
	close $fh;
    }
d408 21
a428 1
    if {$Drv(options) != ""} {
d438 2
a439 2
	    foreach opt $Drv(options) {
		puts $fh "$opt\t$Drv(option:$opt)";
d445 38
d490 1
d495 1
a495 1
    # pick up all the options information first
d517 1
a517 1
		    lappend drivers($driver:options) $opt;
d519 32
a550 1
		    set options($opt) $hdr;
d570 1
a570 1
	    set Drv(files) "";
d572 2
a573 2
	    if {[info exists drivers($Drv(driver):options)]} {
		set Drv(options) $drivers($Drv(driver):options);
d575 2
a576 2
		foreach opt $Drv(options) {
		    set Drv(option:$opt) $options($opt);
d586 40
a625 1
		if {[scan $line "\# file: %s" fpath] == 1} {
d627 2
a628 2
		    set Drv(file:$f) "[file dirname $fpath]/";
		    lappend Drv(files) $f;
d647 10
a656 2
	foreach f $Drv(files) {
	    puts " $Drv(file:$f)$f"
d658 3
a660 3
	if {[info exists Drv(options)]} {
	    foreach opt $Drv(options) {
		puts " $opt in $Drv(option:$opt)";
a671 1
proc findInstalledDrv {drvname kpath} {
d673 1
a673 1
    global Drv Options;
d675 1
a675 1
    if {$Options(verbose)} {puts "+ look for driver '$drvname' in '$kpath'";}
d680 42
d731 1
a731 1
	    set Drv(files) "";
d736 1
a736 1
		    return ;		# all done
d740 2
a741 2
		    set Drv(file:$f) "[file dirname $fpath]/";
		    lappend Drv(files) $f;
d749 17
d788 3
a790 1
		   "i386/conf/LINT"] {
d800 14
a813 2
    foreach f $Drv(files) {
	set p $Drv(file:$f);
d845 2
a846 2
    foreach f $Drv(files) {
	if {$Options(verbose)} {puts "- $Drv(file:$f)$f";}
d848 7
a854 1
	    exec rm $kpath$Drv(file:$f)$f;
d877 3
a879 1
		   "i386/conf/LINT"] {
d1042 5
@


1.1
log
@Initial revision
@
text
@d71 1
a71 1
# $Id: KernelDriver,v 1.3 1997/01/21 08:23:31 msmith Exp $
d99 1
a99 1
			error "no driver info files in directory : $hint";
d114 5
a118 1
    return "";
a397 2
    set drvopt "";    	# drivers with options
    
d400 3
d408 1
a408 1
	if {[scan $line "\#\# driver: %s" Drv(driver)] == 1} {
d417 6
a422 5
		# parse
		if {[scan $line "%s %s" $opt $hdr] == 2} {
		    lappend opts($driver:list) $opt;
		    # learn all of the options at once
		    set Drv(option:$opt) $hdr;
a424 2
	    # this driver has options
	    lappend drvopt $driver;
d434 5
a438 2
	# got a driver?
	if {[scan $line "\#\# driver: %s" Drv(driver)] == 1} {
d444 6
a449 2
	    if {[lsearch -exact $drvopt $Drv(driver)] != -1} {
		set Drv(options) $opts($Drv(driver));
d454 1
d483 4
a486 2
	foreach opt $Drv(options) {
	    puts " $opt in $Drv(option:$opt)";
d707 1
a707 1
# If the kernel path is not a directory, dump the usage.
d720 1
d751 1
a751 1
		puts stderr msg;
d805 1
a805 1
	list {
d807 3
a809 1
	    listInstalledDrv $kpath
d812 1
@


1.1.1.1
log
@This is KernelDriver, a tool for automating the addition of
third-party device-driver source to the FreeBSD kernel (at versions
2.2 and later).  It can list and remove drivers it's added too.

It can (should) be included by device-driver authors in their driver
distributions, but is perhaps a little too specific to warrant a place
in the mainstream distribution.
@
text
@@


1.1.1.1.2.1
log
@MFC - updates to handle files outside i386/
Submitted by:	Daniel O'Connor <doconnor@@gsoft.com.au>
@
text
@d45 12
a56 17
# description {<text>}		Driver description; used in comments inserted into
#				files.
# driver <name>			The name of the driver. (Note that this can't end in .drvinfo :)
# filei386 <path> <name>	The file <name> in the driver package is installed into
#				<path> in the kernel source tree.  Files whose names
#				end in '.c' have an entry added to i386/conf/files.i386.
# fileconf <path> <name>	The file <name> in the driver package is installed into
#				<path> in the kernel source tree.  Files whose names
#				end in '.c' have an entry added to conf/files.
# optioni386 <name> <hdr>	Adds an entry to i386/conf/options.i386, such that
#				the option <name> will be placed in the header <hdr>.
# optionconf <name> <hdr>	Adds an entry to conf/options, such that
#				the option <name> will be placed in the header <hdr>.
# linttext			Lines between this and a subsequent 'end' line are added
#				to the LINT file to provide configuration examples,
#				comments, etc.
# end				Ends a text region.
d71 1
a71 1
# $Id: KernelDriver,v 1.4 1998/05/04 03:30:43 doconnor Exp $
d99 1
a99 1
			# nothing there
d114 1
a114 5
    # maybe we need an extension
    if {[file exists $hint.drvinfo]} {
	return $hint.drvinfo;
    }
    error "can't find a driver info file using '$hint'";
d146 2
a147 4
    set Drv(filesi386) "";
    set Drv(filesconf) "";
    set Drv(optionsi386) "";
    set Drv(optionsconf) "";
d167 1
a167 1
	    filei386 {
d174 2
a175 2
		set Drv(filei386:$name) $path;
		lappend Drv(filesi386) $name;
d177 1
a177 17
	    fileconf {
		set path [lindex $line 1];
		set plast [expr [string length $path] -1];
		if {[string index $path $plast] != "/"} {
		    append path "/";
		}
		set name [lindex $line 2];
		set Drv(fileconf:$name) $path;
		lappend Drv(filesconf) $name;
	    }
	    optioni386 {
		set opt [lindex $line 1];
		set hdr [lindex $line 2];
		lappend Drv(optionsi386) $opt;
		set Drv(optioni386:$opt) $hdr;
	    }
	    optionconf {
d180 2
a181 2
		lappend Drv(optionsconf) $opt;
		set Drv(optionconf:$opt) $hdr;
d217 1
a217 6
    foreach f $Drv(filesi386) {
	if {![file readable $dir$f]} {
	    lappend missing $f;
	}
    }
    foreach f $Drv(filesconf) {
d233 2
a234 14
    foreach f $Drv(filesi386) {
	set p $Drv(filei386:$f);
	if {![file isdirectory $kpath$p]} {
	    lappend missing $p;
	} else {
	    if {![file writable $kpath$p]} {
		if {[lsearch -exact $unwritable $p] == -1} {
		    lappend unwritable $p;
		}
	    }
	}
    }
    foreach f $Drv(filesconf) {
	set p $Drv(fileconf:$f);
a245 1
		   "conf/files" \
d271 1
a271 2
    set Drv(installedi386) "";
    set Drv(installedconf) "";
d275 2
a276 12
    foreach f $Drv(filesi386) {
	if {$Options(verbose)} {puts "$f -> $kpath$Drv(filei386:$f)";}
	if {$Options(real)} {
	    if {[catch {exec cp $dir$f $kpath$Drv(filei386:$f)} msg]} {
		lappend failed $f;
	    } else {
		lappend Drv(installedi386) $f;
	    }
	}
    }
    foreach f $Drv(filesconf) {
	if {$Options(verbose)} {puts "$f -> $kpath$Drv(fileconf:$f)";}
d278 1
a278 1
	    if {[catch {exec cp $dir$f $kpath$Drv(fileconf:$f)} msg]} {
d281 1
a281 1
		lappend Drv(installedconf) $f;
d301 2
a302 5
    foreach f $Drv(installedi386) {
	exec rm -f $kpath$Drv(filei386:$f)$f;
    }
    foreach f $Drv(installedconf) {
	exec rm -f $kpath$Drv(fileconf:$f)$f;
d309 1
a309 1
# Adds an entry to i386/conf/files.i386 and conf/files for the .c files in the driver.  
d316 1
a316 1
#  # filei386: <path><file>
d331 18
a348 1
# Add stuff to LINT
d366 1
a366 21

# Do filesi386 stuff
    if {$Options(real)} {
	set fname [format "%si386/conf/files.i386" $kpath];
	set fh [open $fname a];

	# header
	puts $fh "\#\# driver: $Drv(driver)";
	puts $fh "\# $Drv(description)";
	# file information
	foreach f $Drv(filesi386) {
	    puts $fh "\# file: $Drv(filei386:$f)$f";
	    # is it a compilable object?
	    if {[string match "*.c" $f]} {
		puts $fh "$Drv(filei386:$f)$f\t\toptional\t$Drv(driver)\tdevice-driver";
	    }
	}
	puts $fh "\#\# enddriver";
	close $fh;
    }
    if {$Drv(optionsi386) != ""} {
d376 2
a377 2
	    foreach opt $Drv(optionsi386) {
		puts $fh "$opt\t$Drv(optioni386:$opt)";
a382 38

# Do filesconf stuff
    if {$Options(real)} {
	set fname [format "%sconf/files" $kpath];
	set fh [open $fname a];

	# header
	puts $fh "\#\# driver: $Drv(driver)";
	puts $fh "\# $Drv(description)";
	# file information
	foreach f $Drv(filesconf) {
	    puts $fh "\# file: $Drv(fileconf:$f)$f";
	    # is it a compilable object?
	    if {[string match "*.c" $f]} {
		puts $fh "$Drv(fileconf:$f)$f\t\toptional\t$Drv(driver)\tdevice-driver";
	    }
	}
	puts $fh "\#\# enddriver";
	close $fh;
    }
     if {$Drv(optionsconf) != ""} {
 	if {$Options(verbose)} {puts "+ adding options...";}
 	if {$Options(real)} {
 	    set fname [format "%sconf/options" $kpath];
 	    set fh [open $fname a];

 	    # header
 	    puts $fh "\#\# driver: $Drv(driver)";
 	    puts $fh "\# $Drv(description)";
 	    # options
 	    foreach opt $Drv(optionsconf) {
 		puts $fh "$opt\t$Drv(optionconf:$opt)";
 	    }
 	    puts $fh "\#\# enddriver";
 	    close $fh;
 	}
     }

a389 1
# XXX : fix me so I understand conf/{options,files} stuff!
d394 3
a396 1
    # pick up all the i386 options information first
a397 3
    if {![file readable $fname]} {
	error "not a kernel directory";
    }
d403 1
a403 1
	if {[scan $line "\#\# driver: %s" driver] == 1} {
d412 5
a416 37
		# parse option/header tuple
		if {[scan $line "%s %s" opt hdr] == 2} {
		    # remember that this driver uses this option
		    lappend drivers($driver:optionsi386) $opt;
		    # remember that this option goes in this header
		    set optionsi386($opt) $hdr;
		}
	    }
	}
    }
    close $fh;

    # pick up all the conf options information first
    set fname [format "%sconf/options" $kpath];
    if {![file readable $fname]} {
	error "not a kernel directory";
    }
    set fh [open $fname r];

    while {[gets $fh line] >= 0} {
    
	# got a driver?
	if {[scan $line "\#\# driver: %s" driver] == 1} {
	    # read driver details, ignore
	    gets $fh line;
	    # loop reading option details
	    while {[gets $fh line] >= 0} {
		# end of driver info
		if {$line == "\#\# enddriver"} {
		    break ;
		}
		# parse option/header tuple
		if {[scan $line "%s %s" opt hdr] == 2} {
		    # remember that this driver uses this option
		    lappend drivers($driver:optionsconf) $opt;
		    # remember that this option goes in this header
		    set optionsconf($opt) $hdr;
d419 2
d430 2
a431 5
	# got a driver? 
	if {[scan $line "\#\# driver: %s" driver] == 1} {
	    # clear global and reset
	    catch {unset Drv};
	    set Drv(driver) $driver;
d435 1
a435 1
	    set Drv(filesi386) "";
d437 2
a438 6
	    if {[info exists drivers($Drv(driver):optionsi386)]} {
		set Drv(optionsi386) $drivers($Drv(driver):optionsi386);
		# get pathnames
		foreach opt $Drv(optionsi386) {
		    set Drv(optioni386:$opt) $optionsi386($opt);
		}
a442 1
		    # print this driver and loop
d446 1
a446 40
		if {[scan $line "\# filei386: %s" fpath] == 1} {
		    set f [file tail $fpath];	
		    set Drv(filei386:$f) "[file dirname $fpath]/";
		    lappend Drv(filesi386) $f;
		}
	    }
	}
    }
    close $fh;

    set fname [format "%sconf/files" $kpath];
    set fh [open $fname r];
    
    while {[gets $fh line] >= 0} {

	# got a driver? 
	if {[scan $line "\#\# driver: %s" driver] == 1} {
	    # clear global and reset
	    catch {unset Drv};
	    set Drv(driver) $driver;
	    # read driver details
	    gets $fh line;
	    set Drv(description) [string range $line 2 end];
	    set Drv(filesconf) "";
	    # options?
	    if {[info exists drivers($Drv(driver):optionsconf)]} {
		set Drv(optionsconf) $drivers($Drv(driver):optionsconf);
		# get pathnames
		foreach opt $Drv(optionsconf) {
		    set Drv(optionconf:$opt) $optionsconf($opt);
		}
	    }
	    # loop reading file details
	    while {[gets $fh line] >= 0} {
		if {$line == "\#\# enddriver"} {
		    # print this driver and loop
		    printDrv;
		    break ;
		}
		if {[scan $line "\# fileconf: %s" fpath] == 1} {
d448 2
a449 2
		    set Drv(fileconf:$f) "[file dirname $fpath]/";
		    lappend Drv(filesconf) $f;
d468 2
a469 5
	foreach f $Drv(filesi386) {
	    puts " $Drv(filei386:$f)$f"
	}
	foreach f $Drv(filesconf) {
	    puts " $Drv(fileconf:$f)$f"
d471 2
a472 9
	if {[info exists Drv(optionsi386)]} {
	    foreach opt $Drv(optionsi386) {
		puts " $opt in $Drv(optioni386:$opt)";
	    }
	}
	if {[info exists Drv(optionsconf)]} {
	    foreach opt $Drv(optionsconf) {
		puts " $opt in $Drv(optionconf:$opt)";
	    }
d483 1
d485 1
a485 1
proc findInstalledDrvi386 {drvname kpath} {
d487 1
a487 1
    global Drv;
a491 2
    puts "checking i386/conf/files.i386";

d501 1
a501 1
	    set Drv(filesi386) "";
d506 1
a506 1
		    return 1;		# all done
d510 2
a511 2
		    set Drv(filei386:$f) "[file dirname $fpath]/";
		    lappend Drv(filesi386) $f;
a518 57

    return 0;
}

proc findInstalledDrvconf {drvname kpath} {

    global Drv;

    set fname [format "%sconf/files" $kpath];
    set fh [open $fname r];

    puts "checking conf/files";
    
    while {[gets $fh line] >= 0} {
	if {[scan $line "\#\# driver: %s" name] == 1} {
	    if {$name != $drvname} {
		continue ;		# not us
	    }
	    # read information
	    set Drv(driver) $drvname;
	    set line [gets $fh];
	    set Drv(description) [string range $line 2 end];
	    set Drv(filesconf) "";
	    # loop reading file details
	    while {[gets $fh line] >= 0} {
		if {$line == "\#\# enddriver"} {
		    close $fh;
		    return 1;		# all done
		}
		if {[scan $line "\# file: %s" fpath] == 1} {
		    set f [file tail $fpath];	
		    set Drv(fileconf:$f) "[file dirname $fpath]/";
		    lappend Drv(filesconf) $f;
		}
	    }
	    close $fh;
	    error "unexpected EOF reading '$fname'";
	}
    }
    close $fh

    return 0;
}

proc findInstalledDrv {drvname kpath} {

    global Drv Options;

    if {$Options(verbose)} {puts "+ look for driver '$drvname' in '$kpath'";}

# Whoops... won't work in a single if statement due to expression shortcircuiting
    set a [findInstalledDrvi386 $drvname $kpath];
    set b [findInstalledDrvconf $drvname $kpath];
    if {$a || $b} {
	return;
    }

d541 1
a541 3
		   "i386/conf/LINT" \
		   "conf/files" \
		   "conf/options" ] { 
d551 2
a552 14
    foreach f $Drv(filesi386) {
	set p $Drv(filei386:$f);
	if {![file isdirectory $kpath$p]} {
	    lappend missing $p;
	} else {
	    if {![file writable $kpath$p]} {
		if {[lsearch -exact $unwritable $p] == -1} {
		    lappend unwritable $p;
		}
	    }
	}
    }
    foreach f $Drv(filesconf) {
	set p $Drv(fileconf:$f);
d584 2
a585 8
    foreach f $Drv(filesi386) {
	if {$Options(verbose)} {puts "- $Drv(filei386:$f)$f";}
	if {$Options(real)} {
	    exec rm $kpath$Drv(filei386:$f)$f;
	}
    }
    foreach f $Drv(filesconf) {
	if {$Options(verbose)} {puts "- $Drv(fileconf:$f)$f";}
d587 1
a587 1
	    exec rm $kpath$Drv(fileconf:$f)$f;
d610 1
a610 3
		   "i386/conf/LINT" \
		   "conf/files" \
		   "conf/options" ] {
d693 1
a693 1
# If the kernel path is not a directory, complain and dump the usage.
a705 1
	puts "not a directory : $kpath";
d736 1
a736 1
		puts stderr $msg;
a772 5
	    if {[string last ".drvinfo" $drv] != -1} {
		set drv [string range $drv 0 [expr [string length $drv] - 9]];
		puts "Driver name ends in .drvinfo, removing, is now $drv";
	    }

d790 1
a790 1
	list { 
d792 1
a792 3
	    if {[catch {listInstalledDrv $kpath} msg]} {
		puts stderr "can't list drivers in '$kpath' : $msg";
	    }
a794 1
	    puts stderr "unknown command '$mode'";
@


1.1.1.1.2.2
log
@$Id$ -> $FreeBSD$
@
text
@d76 1
a76 1
# $FreeBSD$
@

