1#!/bin/sh
2#
3# $Id$
4#
5# script to merge custom code into updated mib2c code
6#
7#----- example .mib2c-updaterc -----
8#UPDATE_OID=ipAddressTable
9#UPDATE_CONF=mib2c.mfd.conf
10#UPDATE_MIB2C_OPTS=
11#UPDATE_NOPROBE=1
12#----- example .mib2c-updaterc -----
13
14#----------------------------------------------------------------------
15#
16# defaults
17#
18UPDATE_CURR=$PWD
19UPDATE_ORIG=$PWD/.orig
20UPDATE_NEW=$PWD/.new
21UPDATE_MERGED=$PWD/.merged
22UPDATE_BACKUP=$PWD/.backup
23UPDATE_PATCH=$PWD/.patch
24
25#
26# number of diff context lines / patch fuzz factor
27#
28FUZZ=5
29FIRST_RUN=0
30
31#----------------------------------------------------------------------
32#
33debug()
34{
35    if [ $UPDATE_DEBUG -ge 1 ]; then
36        echo $1
37    fi
38}
39
40error()
41{
42    echo "ERROR: $@" >&2
43}
44
45die()
46{
47    error "$@"
48    exit 99
49}
50
51safecd()
52{
53    cd $1
54    if [ $? -ne 0 ]; then
55        die "changing to directory $1 from $PWD failed!"
56    fi
57}
58
59safecp()
60{
61    cp $@
62    if [ $? -ne 0 ]; then
63        die "'cp $@' failed!"
64    fi
65}
66
67#----------------------------------------------------------------------
68#
69check_setup()
70{
71    rc=1
72    for d in $UPDATE_CURR $UPDATE_ORIG $UPDATE_NEW $UPDATE_MERGED $UPDATE_PATCH $UPDATE_BACKUP $UPDATE_BACKUP/curr $UPDATE_BACKUP/orig
73    do
74        if [ ! -d $d ]; then
75            echo "Creating missing directory $d"
76            mkdir -p $d
77            if [ $? -ne 0 ]; then
78                error "Could not create directory $d"
79                rc=0
80            fi
81        fi
82    done
83
84    if [ -z "$UPDATE_OID" ]; then
85        error "Environment variable missing! Set UPDATE_OID in .mib2c-updaterc"
86        rc=0
87    fi
88
89    if [ -z "$UPDATE_CONF" ]; then
90        error "Environment variable missing! Set UPDATE_CONF in .mib2c-updaterc"
91        rc=0
92    fi
93
94#    if [ -z "$UPDATE_" ]; then
95#        error "Environment variable missing! Set UPDATE_ in .mib2c-updaterc"
96#        rc=0
97#    fi
98
99    if [ $rc -eq 0 ] && [ $UPDATE_NOPROBE -ne 1 ]; then
100        mib2c -c unknown  > /dev/null 2>&1
101        if [ $? -eq 0 ]; then
102            error "WARNING: mib2c returns 0 on error conditions!"
103            rc=0
104        fi
105    fi
106
107    return $rc
108}
109
110#----------------------------------------------------------------------
111#
112do_diff()
113{
114    DD_ORIG=$1
115    DD_CURR=$2
116    DD_OUTPUT=$3
117    # u | c unified | context
118    # r     recursive
119    # b     ignore blank lines
120    # w     ignore white space
121    # p     Show which C function each change is in.
122    # d     smaller changes
123    #    --exclude='*Makefile' --unidirectional-new-file
124    local rc=0
125    local rcs=0
126    safecd $DD_ORIG
127    echo "  checking files in $1 ($PWD)"
128    files=`ls *$UPDATE_OID* 2>/dev/null`
129    if [ ! -z "$files" ]; then
130        for f in $files; do
131            diff -U $FUZZ -p -b -w --show-c-function \
132                -I "$""Id:" $f $DD_CURR/$f >> $DD_OUTPUT
133            rc=$?
134            rcs=`expr $rcs + $rc`
135            if [ $rc -eq 1 ]; then
136                echo "   $f is different"
137            fi
138        done
139    fi
140    if [ $rcs -eq 0 ]; then
141        rm -f $DD_OUTPUT
142    fi
143    safecd -
144    return $rcs
145}
146
147#----------------------------------------------------------------------
148#
149do_cp()
150{
151    src=$1
152    dest=$2
153    if [ ! -d $dest ]; then
154        die "dest $dest is not a directory"
155    fi
156    if [ ! -d $src ]; then
157        die "src $src is not a directory"
158    fi
159    safecd $src
160    files=`ls *$UPDATE_OID* 2>/dev/null| egrep "(file|onf|m2d|txt|\.c|\.h)$"`
161    if [ -z "$files" ]; then
162       echo "   no files to copy from $src"
163    else
164       safecp $files $dest
165       if [ $? -ne 0 ]; then
166           die "error while copying files from $src to $dest in $PWD"
167       fi
168    fi
169    safecd -
170}
171
172#----------------------------------------------------------------------
173#
174save_diff()
175{
176    echo "Creating patch for your custom code"
177    cnt=`ls $UPDATE_CURR/*$UPDATE_OID* 2>/dev/null | egrep "(file|onf|m2d|txt|\.c|\.h)$" | wc -l`
178    if [ $cnt -eq 0 ]; then
179        echo "   no custom code!"
180        FIRST_RUN=1
181        return
182    fi
183
184    do_diff $UPDATE_ORIG/ $UPDATE_CURR/ $UPDATE_PATCH/custom.$UPDATE_DATE
185    if [ $? -eq 0 ]; then
186        echo "   no custom code changes found."
187    fi
188}
189
190#----------------------------------------------------------------------
191#
192gen_code()
193{
194    copy_defaults . $UPDATE_NEW
195
196    safecd $UPDATE_NEW
197    files=`ls *$UPDATE_OID* 2>/dev/null | grep -v "^default"`
198    if [ ! -z "$files" ]; then
199       rm -f $files > /dev/null 2>&1
200    fi
201    echo "mib2c $@ -c $UPDATE_CONF $UPDATE_MIB2C_OPTS $UPDATE_OID"
202    mib2c $@ -c $UPDATE_CONF $UPDATE_MIB2C_OPTS $UPDATE_OID
203    if [ $? -ne 0 ]; then
204        die "bad rc $rc from mib2 while generation new code."
205    fi
206    safecd -
207}
208
209#----------------------------------------------------------------------
210#
211check_new()
212{
213    echo "Checking for updates to generated code"
214    do_diff $UPDATE_ORIG/ $UPDATE_NEW/ $UPDATE_PATCH/generated.$UPDATE_DATE
215    if [ $? -eq 0 ]; then
216        echo "Generated code has not changed."
217        safecd $UPDATE_PATCH
218        files=`ls *.$UPDATE_DATE 2>/dev/null `
219        if [ ! -z "$files" ]; then
220           rm $files
221        fi
222        exit 0
223    fi
224}
225
226#----------------------------------------------------------------------
227#
228merge_code()
229{
230    files=`ls $UPDATE_MERGED/* 2>/dev/null `
231    if [ ! -z "$files" ]; then
232       rm $UPDATE_MERGED/*
233    fi
234    do_cp $UPDATE_NEW $UPDATE_MERGED
235
236    if [ -f $UPDATE_PATCH/custom.$UPDATE_DATE ]; then
237       touch .M2C-UPDATE-MERGE-FAILED
238       echo "Patching new generated code in $UPDATE_MERGED ($PWD)"
239       # --forward = ignore already applied
240       patch --forward -F $FUZZ -N -d $UPDATE_MERGED -i $UPDATE_PATCH/custom.$UPDATE_DATE
241       if [ $? -ne 0 ]; then
242           error "Could not apply custom code patch to new generated code"
243           die   "You must fix the problem in $UPDATE_MERGED, and then re-run mib2c-update."
244       fi
245       rm .M2C-UPDATE-MERGE-FAILED
246    fi
247}
248
249copy_defaults()
250{
251    SRC=$1
252    DST=$2
253    if [ -d $SRC/defaults ]; then
254       safecp -a $SRC/defaults $DST
255    else
256        files=`ls $SRC/default-*.m2d 2>/dev/null `
257        if [ ! -z "$files" ]; then
258           safecp $files $DST
259        fi
260    fi
261
262}
263
264copy_merged()
265{
266    echo "Backing up current code to $UPDATE_BACKUP/curr"
267    do_cp $UPDATE_CURR $UPDATE_BACKUP/curr/
268    copy_defaults . $UPDATE_BACKUP/curr/
269
270    echo "Copying merged code to $UPDATE_CURR"
271    do_cp $UPDATE_MERGED $UPDATE_CURR/
272
273
274    echo "Backing up original code to $UPDATE_BACKUP/orig"
275    do_cp $UPDATE_ORIG $UPDATE_BACKUP/orig/
276    echo "Saving new original code to $UPDATE_ORIG"
277    do_cp $UPDATE_NEW $UPDATE_ORIG/
278}
279
280copy_new()
281{
282    echo "Copying code to $UPDATE_CURR"
283    do_cp $UPDATE_NEW $UPDATE_CURR/
284    # copy defaults back to current dir (which may not be UPDATE_CURR)
285    copy_defaults $UPDATE_NEW .
286
287    echo "Saving original code to $UPDATE_ORIG"
288    do_cp $UPDATE_NEW $UPDATE_ORIG/
289}
290
291copy_code()
292{
293    if [ $FIRST_RUN -ne 1 ]; then
294        copy_merged
295    else
296        copy_new
297    fi
298
299    # always get defaults from UPDATE_NEW, since those are what were used.
300    copy_defaults $UPDATE_NEW .
301}
302
303
304#----------------------------------------------------------------------
305UPDATE_NOPROBE=0
306
307if [ -f $HOME/.mib2c-updaterc ]; then
308    . $HOME/.mib2c-updaterc
309fi
310
311if [ -f $PWD/.mib2c-updaterc ]; then
312    . $PWD/.mib2c-updaterc
313else
314   echo "creating example .mib2c-udpaterc. edit as needed and re-run "
315   echo "mib2c-update."
316
317   echo "UPDATE_OID=ipAddressTable" >> .mib2c-updaterc
318   echo "UPDATE_CONF=mib2c.mfd.conf" >> .mib2c-updaterc
319   echo "UPDATE_MIB2C_OPTS=" >> .mib2c-updaterc
320   echo "#UPDATE_NOPROBE=1" >> .mib2c-updaterc
321fi
322
323check_setup
324if [ $? -ne 1 ]; then
325    exit 1
326fi
327
328UPDATE_DATE=`date "+%F_%I.%M"`
329echo "Starting regneration of $UPDATE_OID using $UPDATE_CONF at $UPDATE_DATE"
330
331if [ -f .M2C-UPDATE-MERGE-FAILED ]; then
332    echo "It appears that the last run of mib2c-update was not able to merge"
333    echo "your changes automatically. Do you want to:"
334    echo
335    while : ; do
336        echo "[c)opy merged files to $UPDATE_CURR]"
337        echo "[r)e-run from scratch]"
338        echo "[q)uit]"
339        echo "(c|r|q) ?"
340        read ans
341        if [ "x$ans" = "xr" ]; then
342            rm .M2C-UPDATE-MERGE-FAILED
343            break
344        elif [ "x$ans" = "xc" ]; then
345            echo "Have you have manually merged all the"
346            echo "changes into the merged directory?"
347            echo "(y|n)"
348            read ans
349            if [ "x$ans" != "xy" ]; then
350                echo "Ok. Try again after you've done that."
351                exit 1
352            fi
353            rm .M2C-UPDATE-MERGE-FAILED
354            copy_code
355            exit 0
356        fi
357    done
358fi
359
360save_diff
361gen_code $@
362if [ $FIRST_RUN -ne 1 ]; then
363    check_new
364    merge_code
365fi
366copy_code
367