Subversion Repositories LCARS

Rev

Rev 20 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
20 PointedEar 1
#!/bin/sh
2
appname="${0##*/}"
21 PointedEar 3
ver="0.6.1.2007011316"
4
copy="2005-2007"
20 PointedEar 5
mail_feedback="dvd@PointedEars.de"
6
# ----------------------------------------------------------------------------
21 PointedEar 7
# DVD Subtitles 0.6.1 -- Extracts subtitles from DVD-Video data to a text file
20 PointedEar 8
# Copyright (C) 2005, 2006  Thomas Lahn <PointedEars@gmx.de>
9
#
10
#     This program is free software; you can redistribute it and/or modify it
11
#     under the terms of the GNU General Public License (GPL) as published
12
#     by the Free Software Foundation; either version 2 of the License, or
13
#     (at your option) any later version.
14
#
15
#     This program is distributed in the hope that it will be useful,
16
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
17
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
#     GNU General Public License for more details.
19
#
20
#     You should have received a copy of the GNU GPL along with this
21
#     program; if not, write to the Free Software Foundation, Inc.,
22
#     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
23
#
24
## Standard shell script disclaimer blurb thing:
25
##
26
## This script is a hack.  It's brute force.  It's horrible.
27
## It doesn't use Artificial Intelligence.  It doesn't use Virtual Reality.
28
## It's not perl.  It's not python.  It probably won't work unchanged on
29
## the "other" thousands of unices.  But it worksforme.  --ramiro
30
# (from /usr/local/mozilla/run-mozilla.sh)
31
#
32
#     This is work in progress.  If you have an improvement, patch,
33
#     idea, whatever, on how to make this script better, please
34
#     send it to <dvd@PointedEars.de>
35
 
36
_title ()
37
{
38
  echo "\
39
${extd}DVD Subtitles $ver
40
Copyright (C) $copy  Thomas Lahn <$mail_feedback>$norm
41
Distributed under the terms of the GNU General Public License (GPL), see
42
COPYING file or http://www.gnu.org/licenses/licenses.html#GPL for details.
43
"
44
}
45
 
46
_help ()
47
{
48
  echo "\
21 PointedEar 49
Extracts a subtitle stream from DVD-Video data and converts it to a text file.
20 PointedEar 50
 
51
$extd$appname$norm [options] ${ital}SOURCE$norm
21 PointedEar 52
 
53
Deprecated:
54
  $extd$appname$norm [$extd-hVkl$norm] [${ital}SOURCE$norm [${ital}TITLE$norm\
20 PointedEar 55
 [${ital}SUBTITLE$norm [${ital}TARGET$norm [${ital}GREY_LEVELS$norm]]]]]
56
 
57
Any option argument is overwritten by the respective additional program
58
argument.  Options may be given in any order, and are also considered
59
options if located after the first program argument.  Too many program
60
arguments are silently ignored.
61
 
62
$extd-c$norm, $extd--compile$norm ${ital}FILE$norm | ${ital}DIRECTORY$norm
63
             Compile subtitle text files according to subtitle index\
64
 ${ital}FILE$norm
65
             or to subtitle index files in ${ital}DIRECTORY$norm to\
21 PointedEar 66
 ${ital}TARGET$norm.  Clean up
67
             if this is successful, then exit.
20 PointedEar 68
 
69
$extd-k$norm, $extd--keep$norm   Keep subtitle stream file even if\
70
 conversion is successful.
71
 
72
$extd-l$norm, $extd--list$norm   List subtitles for TITLE using\
73
 ${extd}mplayer$norm(1) and exit.
74
               If TITLE is not provided or \`$extd-$norm', list subtitles for
75
               title #2 (as title #1 may be an intro without subtitles)
76
               and exit.
77
 
78
SOURCE       Video DVD data source, i.e. a device (usually /dev/dvd),
79
               a directory (e.g. one containing content created via
80
               ${extd}dvdbackup$norm(1)) or a Video DVD image file.
81
               If \`$extd-$norm', a previously created subtitle stream file\
82
 named
83
               ${extd}subtitle_stream-$norm*$extd-${norm}TITLE${extd}-${norm}SUBTITLE\
84
 in the current working
85
               directory will be used for only the stream-to-graphics-
86
               to-text conversion instead.  Both TITLE and SUBTITLE
87
               must not be \`$extd-$norm' in that case.
88
               The default is \`$extd/dev/dvd$norm'.
89
 
90
$extd-t$norm, $extd--title$norm
91
  TITLE        Number of the title (1-n) which will be accessed for
92
               subtitle stream extraction.  If left out or \`$extd-$norm', the
93
               program uses ${extd}mplayer$norm(1) to detect how many titles are
94
               available on the DVD data source and asks for the
95
               title to be accessed.
96
 
97
$extd-s$norm, $extd--subtitle-id$norm
98
  SUBTITLE     ID of the subtitle stream to be extracted (0-n).
99
               If left out or \`$extd-$norm', the program uses its\
100
 ${extd}-l$norm option to detect
101
               which subtitles are available for the given TITLE and asks
102
               for the ID to be used.
103
 
104
$extd-o$norm, $extd--output-target$norm
105
  TARGET       Name of the resulting subtitles text file.
106
               If not provided, the file is named after the subtitle stream
107
               file.  NOTE: Unlike previous versions, this version appends
108
               the filename suffix $extd.srt$norm automagically ONLY in that\
109
 case.
110
 
111
$extd-g$norm, $extd--grey-levels$norm
112
  GREY_LEVELS  Optional grey-levels value\
113
 (\`c0$extd,${norm}c1$extd,${norm}c2$extd,${norm}c3' with 0 <= cN <= 255,
114
               where 0 is black and 255 is white) to be used for converting
115
               the subtitle stream graphics to text via OCR.  The default is
116
               \`${extd}255,255,0,255$norm'.  Unfortunately, the\
117
 ${extd}subtitle2pgm$norm program,
118
               which requires this value, appears to be poorly documented;
119
               if you find a more detailed, working documentation, please
120
               refer to it and inform this program's author about it.
121
 
122
$extd-h$norm, $extd--help$norm     Display this help and exit.
123
$extd-v$norm, $extd--verbose$norm  Be verbose.  The number of ${extd}-v$norm\
124
 options specify the level of
125
                 verbosity.
126
$extd-V$norm, $extd--version$norm  Display version information and exit.
127
 
128
${extd}EXIT STATUS$norm
129
  ${extd}  0$norm  Successful program execution
130
  ${extd}  1$norm  Error detecting/extracting subtitle stream, or cancelled
131
         without selecting a title number or subtitle ID
132
  ${extd}  2$norm  Unable to convert subtitle stream to image files
133
  ${extd}  3$norm  Cancelled due to ${extd}gocr$norm(1) error or without\
134
 entering another
135
         grey-levels value
136
  ${extd}  4$norm  Unable to compile to text file
137
  ${extd}  5$norm  Unable to clean up
138
  ${extd}127$norm  Insufficient number of arguments / help was displayed
139
 
140
See the $extd$appname$norm(1) manpage for complete documentation."
141
}
142
 
143
if test -z "$LINES" -o -z "$COLUMNS" ; then
144
    eval `stty size 2>/dev/null | (read L C; \
145
    echo LINES=${L:-24} COLUMNS=${C:-80})`
146
fi
147
test $LINES   -eq 0 && LINES=24
148
test $COLUMNS -eq 0 && COLUMNS=80
149
 
150
if test "$TERM" != "raw" && stty size >/dev/null 2>&1 ; then
151
# esc=`echo -en "\033"`
152
# extd="${esc}[1m"
153
  extd=`tput bold 2>/dev/null`
154
  ital=`tput sitm 2>/dev/null`
155
# norm=`echo -en "${esc}[m\017"`
156
  norm=`tput sgr0 2>/dev/null`
157
else
158
  esc=""
159
  extd=""
160
  norm=""
161
fi
162
 
163
# Note that we use `"$@"' to let each command-line parameter expand to a
164
# separate word. The quotes around `$@' are essential!
165
# We need `tmp' as the `eval set --' would nuke the return value of getopt.
166
 
167
[ "$1" = "-vv" ] && echo "$extd
168
Debug output for POSIX conform command-line parsing
169
 
170
Original arguments: $*" >&2
171
if `getopt -T >/dev/null 2>&1` ; [ $? = 4 ] ; then
172
  getopt_type=long
173
  [ "$1" = "-vv" ] && echo "getopt(1) type:     enhanced" >&2
174
  tmp=`getopt -o c:klg:o:S::s:t:hVv \
175
              -l compile:,keep-stream,list,grey-levels:,output-target:\
176
,spell-check,subtitle-id:,title:,help,verbose,version \
177
              -n "$appname" -s sh \
178
              -- "$@"`
179
else
180
  getopt_type=short
181
  [ "$1" = "-vv" ] && echo "getopt(1) type:     old" >&2
182
  tmp=`getopt c:klg:o:S:s:t:hVv "$@"`
183
fi
184
 
185
# exit status
186
ESUCCESS=0
187
ECANTEXTRACT=1
188
ECANTCONVERT=2
189
EOCRERROR=3
190
ECANTCOMPILE=4
191
ECANTCLEANUP=5
192
EARGERROR=127
193
 
194
getopt_exit_code=$?
195
help=0
196
verbose=0
197
version=0
198
list=0
199
source='/dev/dvd'
200
title='-'
201
sid='-'
202
target='-'
203
args=''
204
keep=0
205
compile=0
206
if [ $getopt_exit_code -eq 0 ]; then
207
##     getopt  returns  error  code 0 for successful parsing, 1 if
208
##     getopt(3) returns errors, 2 if it does not understand  its
209
##     own parameters, 3 if an internal error occurs like out-of-
210
##     memory, and 4 if it is called with -T.
211
#
212
# Note the quotes around `$tmp': they are essential!
213
#  echo $tmp
214
# remove "--"
215
#  for i in $tmp; do if [ "$i" != "--" ]; then tmp2="${tmp2} $i"; fi; done
216
  eval set -- "$tmp"
217
  [ "$1" = "-vv" ] && echo "New arguments:      $*$norm
218
" >&2
219
  while true ; do
220
    case "$1" in
221
      -h | --help)
222
        help=1
223
        shift;;
224
 
225
      -v | --verbose)
226
        let verbose++
227
        shift;;
228
 
229
      -V | --version)
230
        version=1
231
        shift;;
232
 
233
      -c | --compile)
234
        compile=1
235
        source=$2
236
        shift 2;;
237
 
238
      -k | --keep)
239
        keep=1
240
        shift;;
241
 
242
      -l | --list)
243
        list=1
244
        shift;;
245
 
246
      -g | --grey-levels)
247
        grey_levels=$2
248
        shift 2;;
249
 
250
      -o | --output-target)
251
        target=$2
252
        shift 2;;
253
 
254
      -s | --subtitle-id)
255
        sid=$2
256
        shift 2;;
257
 
258
      -t | --title)
259
        title=$2
260
        shift 2;;
261
 
262
      --)
263
        shift
264
        break;;
265
    esac
266
  done
267
  [ -n "$*" ] && args=$args" $*"
268
  set -- $args
269
else
270
  [ $verbose -gt 1 ] && echo "getopt exited: $getopt_exit_code
271
  " >&2
272
  if [ $getopt_exit_code -eq 1 -o $getopt_exit_code -eq 2 ]; then
273
    help=1
274
  else
275
    exit $getopt_exit_code
276
  fi
277
fi
278
 
279
[ $list -eq 0 ] && _title
280
[ $version -eq 1 ] && exit $ESUCCESS
281
[ $help -eq 1 ] &&
282
{
283
  _help "$0"
284
  exit $EARGERROR
285
}
286
 
287
result=$ESUCCESS
288
[ $compile -eq 0 ] &&
289
{
290
  [ -n "$1"                      ] && source=$1
291
  [ -z "$title"       -a -n "$2" ] && title=$2
292
  [ -z "$sid"         -a -n "$3" ] && sid=$3
293
  [ -z "$target"      -a -n "$4" ] && target=$4
294
  [ -z "$grey_levels" -a -n "$5" ] && grey_levels=$5
295
 
296
  getsubtitles ()
297
  {
298
    mplayer -dvd-device "$1" -vo null -ao null -frames 0 \
299
            -v "dvd://${2:-2}" 2>&1 |
300
      sed -n '/sid/ s/^[^:]\{1,\}:[[:space:]]//p'
301
  # echo "$subtitles"
302
  }
303
 
304
  [ $list -eq 1 ] &&
305
  {
306
    # first title may be only an intro
307
    [ "$title" = '-' ] && title=2
308
    tmp=`getsubtitles $source $title`
309
    if [ -n "$tmp" ]; then
310
      echo "${extd}The following subtitles are available for title #$title:$norm
311
$tmp"
312
      exit $ESUCCESS
313
    else
314
      exit $ECANTEXTRACT
315
    fi
316
  }
317
 
318
  [ "$sid" != '-' -a "$title" != '-' ] &&
319
  {
320
    subtitles=`getsubtitles $source $title`
321
    [ -n "$subtitles" ] &&
322
      st_descr=`echo "$subtitles" | grep "^$sid[[:space:]]" |
323
                  cut -f 2- -d ' '`
324
  }
325
 
326
  if [ "$source" = '-' ]; then
327
    stream_file=`ls subtitle_stream-*-$title-$sid 2>/dev/null | head -n 1`
328
    if [ $? -eq 0 ]; then
329
      read -r -s -p "Use '$stream_file' [Y/n]? " -n 1
330
      case $REPLY in
331
        [Nn])
332
          echo $REPLY
333
          exit 1;;
334
        *)
335
          echo Y
336
      esac
337
      echo
338
 
339
      id=${stream_file#*-}
340
    else
341
      echo "$appname: No such file: subtitle_stream-*-$title-$sid" >&2
342
      exit $ECANTEXTRACT
343
    fi
344
  else
345
    read_error ()
346
    {
347
      case $1 in
348
        0) subject='titles available on this DVD source.';;
349
        *) subject='subtitles available for this title.';;
350
      esac
351
 
352
      echo >&2 "\
353
Sorry, there are no $subject
354
Please verify that the DVD data source is available and
355
that its filesystem is consistent."
356
 
357
      unset subject
358
      exit $ECANTEXTRACT
359
    }
360
 
361
    if [ "$title" = '-' ]; then
362
      titles=`mplayer -dvd-device "$source" -vo null -ao null -frames 0 \
363
                      -v dvd:// 2>&1 | egrep '[0-9]+ titles'`
364
      num_titles=`echo "$titles" | awk '{print $3}'`
365
 
366
      [ $(($num_titles)) -lt 1 ] && read_error 0
367
 
368
      echo "$titles"
369
      while true
370
      do
371
        read -r -p "\
372
${extd}Enter title# (1-$num_titles), or nothing to abort: $norm"
373
        if [ -n "$REPLY" ]; then
374
          title=$(($REPLY))
375
          [ $title -ge 1 -a $title -le $num_titles ] && break
376
        else
377
          exit $ECANTEXTRACT
378
        fi
379
      done
380
      echo
381
    fi
382
 
383
    if [ "$sid" = '-' ]; then
384
      if [ -z "$subtitles" ]; then subtitles=`"$0" -lt "$title" "$source"`; fi
385
      if [ $? -eq 0 ]; then
386
        sid_max=`echo "$subtitles" | tail -n 1 | awk '{print $1}'`      
387
        echo "$subtitles"
388
        while true; do
389
          read -r -p "\
390
${extd}Enter ID of subtitle stream (0-$sid_max) to extract, or nothing to abort: $norm"
391
          if [ -n "$REPLY" ]; then
392
            sid=$(($REPLY))
393
            [ $sid -ge 0 -a $sid -lt $sid_max ] && break
394
          else
395
            exit $ECANTEXTRACT
396
          fi
397
        done
398
      else
399
        read_error 1
400
      fi
401
    fi
402
 
403
    # remove trailing /
404
    source=${source%/}
405
 
406
    vol=`(echo $(volname $source 2>/dev/null); exit $?;) || echo ${source##*/}`
407
    id=$vol-$title-$sid
408
    stream_file=subtitle_stream-$id
409
 
410
    unset REPLY
411
    [ -f "$stream_file" ] &&
412
    {
413
      read -r -s -p "${extd}Use existing '$stream_file' [Y/n]? $norm" -n 1
414
      case $REPLY in
415
        [Nn])
416
          echo $REPLY
417
          read -r -s -p "${extd}Overwrite existing '$stream_file' [y/N]? $norm"\
418
               -n 1 REPLY2
419
          case $REPLY2 in
420
            [Yy]) echo $REPLY2;;
421
            *)
422
              echo N
423
              id=$vol-$title-$sid-$$
424
              stream_file=subtitle_stream-$id
425
              echo "Using '$stream_file'"
426
          esac
427
          echo
428
          unset REPLY2;;
429
        *)
430
          echo Y
431
          REPLY='y'
432
      esac
433
      echo
434
    }
435
 
436
    [ "$target" = '-' ] && target="$stream_file.srt"
437
 
438
    [ -z "$REPLY" -o "$REPLY" == 'N' -o "$REPLY" == 'n' ] &&
439
    {
440
      echo "\
441
${extd}Extracting subtitle stream $norm$sid${st_descr:+ ($st_descr)}$extd
442
of title $norm#$title$extd
443
on $norm$source$extd
444
to \"$norm$target$extd\" ...$norm
445
" >&2
446
 
447
      > "$stream_file"
448
      tccat -i "$source" -T "$title" -L |
449
        tcextract -x ps1 -t vob -a 0x2$sid > "$stream_file"
450
    }
451
  fi
452
 
453
  if [ -f "$stream_file" -a -s "$stream_file" ]; then
454
    echo "${extd}... done.$norm"
455
  else
456
    echo "${extd}... failed.$norm"
457
    [ -f "$stream_file" ] && rm ./"$stream_file"
458
    exit $ECANTEXTRACT
459
  fi
460
 
461
  result=$ESUCCESS
462
  while true
463
  do
464
    echo -n "
465
${extd}Converting subtitle stream \"$norm$stream_file$extd\"
466
to Netpbm Portable Greymaps (PGMs) ... $norm" | fold -s >&2
467
    subtitle2pgm -o ./${id}- ${grey_levels:+-c "$grey_levels"} < $stream_file
468
    result=$?
469
    if [ $result -eq 0 ]; then
470
      echo "${extd}done.$norm
471
 
472
${extd}Converting PGMs to text files (TXTs) using GNU OCR (gocr) ... $norm"
473
      st_lang=$(echo "$st_descr" | sed 's/.*language: \([a-z]\{2\}\)/\1/')
474
      pgm2txt ${st_lang:+-f $st_lang} ./${id}-
475
      result=$?
476
      if [ $result -eq 0 ]; then
477
        echo "${extd}done, using a grey-levels value of\
478
 \`$norm${grey_levels:-255,255,0,255}$extd'.$norm"
479
        break
480
      else
481
        echo "${extd}failed.
482
 
483
If the conversion was cancelled due to inappropriate grey-levels value
484
\`${grey_levels:-255,255,0,255}', you may try another value,\
485
 else you should abort:
486
$norm"
487
        select grey_levels in \
488
            `[ "$grey_levels" != '0,255,255,255' ] && echo 0,255,255,255` \
489
            `[ "$grey_levels" != '255,0,255,255' ] && echo 255,0,255,255` \
490
            `[ -n "$grey_levels" -a "$grey_levels" != '255,255,0,255' ] &&
491
              echo 255,255,0,255` \
492
            `[ "$grey_levels" != '255,255,255,0' ] && echo 255,255,255,0` \
493
            Other \
494
            Abort
495
        do
496
          case $grey_levels in
497
            Other)
498
              read -r -p "
499
${extd}Enter new value (\`c0$extd,${norm}c1$extd,${norm}c2$extd,${norm}c3'\
500
 with 0 <= cN <= 255), or nothing to select a value:
501
$norm" grey_levels
502
              [ -n "$grey_levels" ] && break;;
503
 
504
            Abort)
505
              result=$EOCRERROR
506
              break;;
507
 
508
            *)
509
              break
510
          esac
511
        done
512
      fi
513
    else
514
      echo "${extd}failed.$norm"
515
      result=$ECANTCONVERT
516
      break
517
    fi
518
  done
519
 
520
  echo -n "${extd}Cleaning up PGMs ... $norm"
521
  rm ./${id}-*.pgm
522
  if [ $? -eq 0 ]; then
523
    echo "${extd}done.$norm"
524
  else
525
    echo "${extd}failed.$norm"
526
  fi
527
}
528
 
529
[ $result -eq $ESUCCESS ] &&
530
{
531
  if [ $compile -eq 1 ]; then
532
    try_file ()
533
    {
534
      [ ! -f "$source" ] && source="$source.srtx"
535
      [ -f "$source" ]
536
    }
537
 
538
    if [ -d "$source" ]; then
539
# TODO: loop through all .srtx files in the directory
540
      if [ "$source" != '.' ]; then cd "$source"; fi
541
      [ $? -eq 0 ] &&
542
      {
543
        ls "$source"/*.srtx 2>/dev/null
544
      }
545
      echo >&2 "$appname: $source: Directory compile is not yet supported."
546
      exit $ECANTCOMPILE
547
    elif try_file; then
548
      d=${source%/*}
549
      if [ -a -d "$d" -a "$d" != '.' ]; then cd "$d"; fi
550
      id=${source%-*}
551
      stream_file=subtitle_stream-$id
552
      source="./${source##*/}"
553
    else
554
      echo >&2 "$appname: $source: No such file or directory."
555
      exit $ECANTCOMPILE
556
    fi
557
  else
558
    source="${id}-.srtx"
559
  fi
560
 
561
  unset REPLY
562
  [ -f "$target" ] &&
563
  {
564
# TODO: allow for diff
565
    read -r -s -p "${extd}'$target' exists.
566
Append, overwrite, create new file, or abort [a/o/n/Esc]? $norm" \
567
         -n 1
568
    case $REPLY in
569
      [Oo]) echo $REPLY;;
570
      [Aa]) echo $REPLY;;
571
      [Nn])
572
        echo $REPLY
573
        target="${target%.*}-$$.${target##*.}";;
574
      *)
575
        REPLY=Abort
576
        echo $REPLY
577
        exit $ECANTCOMPILE;;
578
    esac
579
  }
580
 
581
  echo "
582
${extd}Compiling TXTs into \"$norm$target$extd\" ... $norm"
583
 
584
  case "$REPLY" in
585
    [Oo]) > "$target";;
586
    [Aa])
587
      # append new content marker here
588
      echo "
589
-- `whoami`@`hostname` -- `date` --
590
" >> "$target"
591
  esac
592
 
593
  (
594
# sed: thx to Erkan Yanar <erkan.yanar@t-online.de>, see
595
# message ID <lduohb.v74.ln@510002093148-0001.dialin.t-online.de>
596
    srttool -s -i "$source"
597
 
598
    # only if srttool is not available
599
    if [ $? -gt 1 ]; then
600
      sed -n 's,^\(\([^/]*\)\(/\)\(.*\.pgm\.txt\)\)$,/^\2\\\3\4$/ { \
601
          r \1 \
602
          d \
603
        },gp' "$source" | sed -f - "$source"
604
    fi
605
  ) >> "$target"
606
 
607
  if [ $? -eq 0 ]; then
608
    echo "${extd}... done.$norm"
609
  else
610
    echo "${extd}... failed.$norm"
611
    exit $ECANTCOMPILE
612
  fi
613
 
614
  echo -n "${extd}Cleaning up
615
  ${id}-*.pgm.txt files ... $norm"
616
  rm ./"${id}"-*.pgm.txt
617
  if [ $? -eq 0 ]; then
618
    echo "${extd}done.$norm"
619
  else
620
    echo "${extd}failed.$norm"
621
    result=$ECANTCLEANUP
622
  fi
623
 
624
  echo -n "  ${extd}Subtitle index file '${id}-.srtx' ... $norm"
625
  rm ./"${id}-.srtx" # "$target.srtx"
626
  if [ $? -eq 0 ]; then
627
    echo "${extd}done.$norm"
628
  else
629
    echo "${extd}failed.$norm"
630
    result=$ECANTCLEANUP
631
  fi
632
 
633
  [ $keep -eq 0 -a -f "./$stream_file" ] &&
634
  {
635
    echo -n "  ${extd}Subtitle stream file '${stream_file}' ... $norm"
636
    rm ./"$stream_file"
637
 
638
    if [ $? -eq 0 ]; then
639
      echo "${extd}done.$norm"
640
    else
641
      echo "${extd}failed.$norm"
642
      result=$ECANTCLEANUP
643
    fi
644
  }
645
 
646
  exit $result
647
}