1#!/bin/sh
2# This is a Tcl/Tk script to be interpreted by tclsh (>=8.3): \
3exec tclsh "$0" "$@"
4
5#  instupdate - install GPSMan updates in a Unix/Linux system
6#
7#  Copyright (c) 2004 Miguel Filgueiras (mig@ncc.up.pt) / Universidade do Porto
8#
9#    This program is free software; you can redistribute it and/or modify
10#      it under the terms of the GNU General Public License as published by
11#      the Free Software Foundation; either version 2 of the License, or
12#      (at your option) any later version.
13#
14#      This program is distributed in the hope that it will be useful,
15#      but WITHOUT ANY WARRANTY; without even the implied warranty of
16#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17#      GNU General Public License for more details.
18#
19#      You should have received a copy of the GNU General Public License
20#      along with this program.
21#
22# Last change:  29 January 2004
23
24# after unpacking the update archive:
25#   cd util
26#   instupdate.tcl [-n]
27
28############# NO CONFIGURATION NEEDED
29
30if { $tcl_platform(platform) != "unix" } {
31    puts "This script needs utilities only available on Unix/Linux"
32    exit 1
33}
34
35if { $argv == "-n" } {
36    set DEBUG 1
37} elseif { $argv != "" } {
38    puts stderr "Usage: instupdate.tcl [-n]"
39    puts stderr "  option -n prevents any change in the installed files"
40    exit 1
41} else { set DEBUG 0 }
42
43if { $env(USER) == "root" } {
44    set rexec 1
45} else { set rexec 0 }
46
47proc FindValues {vars file} {
48    # find out values in first "set ... ..." instruction in $file for
49    #  each variable in $vars
50    # the order in the list must be the order in the file
51    # return list of values aligned with $vars
52    # could not use grep because of space being taken as argument separator
53
54    set f [open $file r]
55    set var [lindex $vars 0] ; set vars [lreplace $vars 0 0]
56    set vals ""
57    while { ! [eof $f] } {
58	gets $f line
59	if { [regexp "^(\\t| )*set $var (.+)\$" $line m m val] } {
60	    lappend vals [string trim $val " \t"]
61	    if { $vars == "" } {
62		close $f
63		return $vals
64	    }
65	    set var [lindex $vars 0] ; set vars [lreplace $vars 0 0]
66	}
67    }
68    puts stderr "No definition of $var in $file"
69    exit 1
70}
71
72proc SetValues {vars vals file tmp} {
73    # change value in first "set" instruction in $file for each variable
74    #  in $vars
75    #  $vals is list of values aligned with $vars
76    #  $tmp is path to directory to use for temporary files
77    # the order in the list must be the order in the file
78    # not using sed because of problems with repeated replacements
79    global DEBUG
80
81    set f [open $file r]
82    set tf $tmp/TMPgiup-[clock seconds]
83    set out [open $tf w]
84    set var [lindex $vars 0] ; set vars [lreplace $vars 0 0]
85    set val [lindex $vals 0] ; set vals [lreplace $vals 0 0]
86    while { ! [eof $f] } {
87	gets $f line
88	if { $var != "" && \
89		[regexp "^(\\t| )*set $var (.+)\$" $line m prefix m] } {
90	    puts $out "${prefix}set $var $val"
91	    set var [lindex $vars 0] ; set vars [lreplace $vars 0 0]
92	    set val [lindex $vals 0] ; set vals [lreplace $vals 0 0]
93	} else { puts $out $line }
94    }
95    close $f
96    close $out
97    if { $var != "" } {
98	puts stderr "No definition of $var in $file"
99	file delete -force $tf
100	exit 1
101    }
102    if { ! $DEBUG } {
103	file rename -force $tf $file
104    } else {
105	puts "DEBUG: file rename -force $tf $file"
106    }
107    return
108}
109
110# start
111
112set wd [pwd]
113
114if { [set bwd [file tail $wd]] != "util" } {
115    puts stderr "After unpacking the update archive, cd to the util directory"
116    puts stderr "Usage: inst_update"
117    exit 1
118}
119
120set ugd "../gmsrc"
121
122if { ! [file isdirectory $ugd] } {
123    puts stderr "gmsrc directory from update archive not found"
124    puts stderr "After unpacking the update archive, cd to the util directory"
125    exit 1
126}
127
128## check versions
129# find update version in line "Update to GPSMan version VERSION"
130
131if { [catch {set uv [exec grep "GPSMan version" $ugd/UPDATE]}] } {
132    puts stderr "Cannot execute grep $ugd/UPDATE"
133    exit 1
134}
135
136if { ! [regexp {GPSMan version (.+)$} $uv x uv] } {
137    puts stderr "Bad format of UPDATE file"
138    exit 1
139}
140
141if { [catch {set iv [exec gpsman show version]}] } {
142    if { $rexec } {
143	puts "Will not compare installed version with that of update"
144	set iv $uv
145	set rexec 0
146    } else {
147	puts stderr "GPSMan not installed (or very old version)"
148	exit 1
149    }
150} else { set rexec 1 }
151
152if { $uv != $iv } {
153    puts stderr "GPSMan installed version ($iv) not that of the update ($uv)"
154    exit 1
155}
156
157## find installed executable to find out path to installed source directory
158
159set iex ""
160
161if { [catch {set iex [exec which gpsman]}] && \
162	! [catch {set exs [exec whereis gpsman]}] } {
163    foreach f $exs {
164	if { ! [file isdirectory $f] && [file executable $f] } {
165	    set iex $f
166	    break
167	}
168    }
169}
170
171if { $rexec } {
172    if { $iex == "" || [catch {set  v [exec $iex show version]}] || \
173	    $v != $iv } {
174	puts -nonewline "Absolute path to gpsman executable? "
175	flush stdout
176	gets stdin iex
177	if { [file pathtype $iex] != "absolute" || \
178		[catch {set  v [exec $iex show version]}] || $v != $iv } {
179	    puts stderr "Bad path"
180	    exit 1
181	}
182    } elseif { $DEBUG } { puts "DEBUG: using $iex as GPSMan executable" }
183} elseif { $iex == "" } {
184    puts -nonewline "Absolute path to gpsman executable? "
185    flush stdout
186    gets stdin iex
187    if { [file pathtype $iex] != "absolute" } {
188	puts stderr "Bad path"
189	exit 1
190    }
191} elseif { $DEBUG } { puts "DEBUG: using $iex as GPSMan executable" }
192
193set isd [FindValues SRCDIR $iex]
194
195if { ! [file isdirectory $isd] || ! [file exists $isd/wrtdials.tcl] } {
196    puts -nonewline "Absolute path to the GPSMan source directory?"
197    flush stdout
198    gets stdin isd
199    if { [file pathtype $isd] != "absolute" || \
200	    ! [file isdirectory $isd] || ! [file exists $isd/wrtdials.tcl] } {
201	puts stderr "Bad path"
202	exit 1
203    }
204} elseif { $DEBUG } { puts "DEBUG: using $isd as installed source directory" }
205
206if { [file exists [set uex $ugd/gpsman.tcl]] } {
207    ## editing updated executable (if any) to set crucial variables to
208    #   the values in the installed executable
209    #  assume each set instruction still has a single line with single spaces
210    #   surrounding the variable name
211    #  assume the order of in which these variables are set is as follows:
212    #   DEFSPORT, USERDIR, USEROPTIONS, PRINTCMD, SRCDIR
213    #   and that the values for Unix-like systems appear before than those
214    #   for other systems
215
216    puts "Making backup copy of $iex to $isd/gpsman.tcl-old"
217    # take care of links
218    set fiex $iex
219    while { [file type $fiex] == "link" } {
220	if { [file pathtype [set tgt [file link $fiex]]] == "relative" } {
221	    set fiex [file join [file dirname $fiex] $tgt]
222	} else { set fiex $tgt }
223    }
224    if { ! $DEBUG } {
225	file copy -force $fiex $isd/gpsman.tcl-old
226    } else {
227	puts "DEBUG: file copy -force $fiex $isd/gpsman.tcl-old"
228    }
229
230    puts "The following variables in $iex will be preserved:"
231    puts "\tSRCDIR  \t$isd"
232    set vars "DEFSPORT USERDIR USEROPTIONS PRINTCMD"
233    set vals [FindValues $vars $iex]
234    foreach v $vars val $vals {
235	puts "\t$v  \t$val"
236    }
237    puts "Preserving any other change to $iex must be made by hand!"
238    if { ! $DEBUG } {
239	file copy -force $ugd/gpsman.tcl $fiex
240    } else {
241	puts "DEBUG: file copy -force $ugd/gpsman.tcl $fiex"
242    }
243    lappend vars SRCDIR ; lappend vals $isd
244    SetValues $vars $vals $fiex .
245    if { ! $DEBUG } {
246	file attributes $fiex -permissions 0755
247    } else {
248	puts "DEBUG: file attributes $fiex -permissions 0755"
249    }
250}
251
252# other source files and icons
253
254puts "Copying updated files to $isd..."
255
256foreach f [glob $ugd/*.tcl] {
257    if { $f != "$ugd/gpsman.tcl" } {
258	if { ! $DEBUG } {
259	    file copy -force $f $isd
260	    file attributes $isd/[file tail $f] -permissions 0644
261	} else {
262	    puts "DEBUG: file copy -force $f $isd"
263	    puts "DEBUG: file attributes $isd/[file tail $f] -permissions 0644"
264	}
265    }
266}
267
268if { [file exists $ugd/gmicons] } {
269    foreach f [glob $ugd/gmicons/*] {
270	if { ! $DEBUG } {
271	    file copy -force $f $isd/gmicons
272	    file attributes $isd/gmicons/[file tail $f] -permissions 0644
273	} else {
274	    puts "DEBUG: file copy -force $f $isd/gmicons"
275	    puts \
276	 "DEBUG: file attributes $isd/gmicons/[file tail $f] -permissions 0644"
277	}
278    }
279}
280
281# utilities
282
283set uud $ugd/util
284if { [file exists $uud] } {
285    set iud ""
286    foreach d "$isd $isd/util" {
287	if { [file exists $d] && [file isdirectory $d] && \
288		[file exists $d/exerciser.tcl] } {
289	    set iud $d
290	    break
291	}
292    }
293    if { $iud == "" } {
294	puts -nonewline "Absolute path to util directory? "
295	flush stdout
296	gets stdin iud
297	if { [file pathtype $iud] != "absolute" || \
298		! [file isdirectory $iud] } {
299	    puts stderr "Bad path"
300	    exit 1
301	}
302    }
303    puts "Copying updated utilities to $iud..."
304    foreach f [glob $uud/*] {
305	if { ! $DEBUG } {
306	    file copy -force $f $iud
307	    file attributes $iud/[file tail $f] -permissions 0755
308	} else {
309	    puts "DEBUG: file copy -force $f $iud"
310	    puts "DEBUG: file attributes $iud/[file tail $f] -permissions 0755"
311	}
312    }
313    puts "The utility  programs may also require configuration by hand!"
314}
315
316puts "Finished"
317
318exit 0
319
320
321
322