]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/cvs/contrib/rcs2log.sh
This commit was generated by cvs2svn to compensate for changes in r55357,
[FreeBSD/FreeBSD.git] / contrib / cvs / contrib / rcs2log.sh
1 #! /bin/sh
2
3 # RCS to ChangeLog generator
4
5 # Generate a change log prefix from RCS files (perhaps in the CVS repository)
6 # and the ChangeLog (if any).
7 # Output the new prefix to standard output.
8 # You can edit this prefix by hand, and then prepend it to ChangeLog.
9
10 # Ignore log entries that start with `#'.
11 # Clump together log entries that start with `{topic} ',
12 # where `topic' contains neither white space nor `}'.
13
14 Help='The default FILEs are the files registered under the working directory.
15 Options:
16
17   -c CHANGELOG  Output a change log prefix to CHANGELOG (default ChangeLog).
18   -h HOSTNAME  Use HOSTNAME in change log entries (default current host).
19   -i INDENT  Indent change log lines by INDENT spaces (default 8).
20   -l LENGTH  Try to limit log lines to LENGTH characters (default 79).
21   -R  If no FILEs are given and RCS is used, recurse through working directory.
22   -r OPTION  Pass OPTION to subsidiary log command.
23   -t TABWIDTH  Tab stops are every TABWIDTH characters (default 8).
24   -u "LOGIN<tab>FULLNAME<tab>MAILADDR"  Assume LOGIN has FULLNAME and MAILADDR.
25   -v  Append RCS revision to file names in log lines.
26   --help  Output help.
27   --version  Output version number.
28
29 Report bugs to <bug-gnu-emacs@gnu.org>.'
30
31 Id='$Id: rcs2log,v 1.45 1998/08/12 22:33:01 eggert Exp $'
32
33 # Copyright 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
34
35 # This program is free software; you can redistribute it and/or modify
36 # it under the terms of the GNU General Public License as published by
37 # the Free Software Foundation; either version 2, or (at your option)
38 # any later version.
39 #
40 # This program is distributed in the hope that it will be useful,
41 # but WITHOUT ANY WARRANTY; without even the implied warranty of
42 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
43 # GNU General Public License for more details.
44 #
45 # You should have received a copy of the GNU General Public License
46 # along with this program; see the file COPYING.  If not, write to the
47 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
48 # Boston, MA 02111-1307, USA.
49
50 Copyright='Copyright 1998 Free Software Foundation, Inc.
51 This program comes with NO WARRANTY, to the extent permitted by law.
52 You may redistribute copies of this program
53 under the terms of the GNU General Public License.
54 For more information about these matters, see the files named COPYING.
55 Author: Paul Eggert <eggert@twinsun.com>'
56
57 tab='   '
58 nl='
59 '
60
61 # Parse options.
62
63 # defaults
64 : ${AWK=awk}
65 : ${TMPDIR=/tmp}
66 changelog=ChangeLog # change log file name
67 datearg= # rlog date option
68 hostname= # name of local host (if empty, will deduce it later)
69 indent=8 # indent of log line
70 length=79 # suggested max width of log line
71 logins= # login names for people we know fullnames and mailaddrs of
72 loginFullnameMailaddrs= # login<tab>fullname<tab>mailaddr triplets
73 logTZ= # time zone for log dates (if empty, use local time)
74 recursive= # t if we want recursive rlog
75 revision= # t if we want revision numbers
76 rlog_options= # options to pass to rlog
77 tabwidth=8 # width of horizontal tab
78
79 while :
80 do
81         case $1 in
82         -c)     changelog=${2?}; shift;;
83         -i)     indent=${2?}; shift;;
84         -h)     hostname=${2?}; shift;;
85         -l)     length=${2?}; shift;;
86         -[nu])  # -n is obsolescent; it is replaced by -u.
87                 case $1 in
88                 -n)     case ${2?}${3?}${4?} in
89                         *"$tab"* | *"$nl"*)
90                                 echo >&2 "$0: -n '$2' '$3' '$4': tabs, newlines not allowed"
91                                 exit 1
92                         esac
93                         case $loginFullnameMailaddrs in
94                         '') loginFullnameMailaddrs=$2$tab$3$tab$4;;
95                         ?*) loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$2$tab$3$tab$4
96                         esac
97                         shift; shift; shift;;
98                 -u)
99                         # If $2 is not tab-separated, use colon for separator.
100                         case ${2?} in
101                         *"$nl"*)
102                                 echo >&2 "$0: -u '$2': newlines not allowed"
103                                 exit 1;;
104                         *"$tab"*)
105                                 t=$tab;;
106                         *)
107                                 t=:
108                         esac
109                         case $2 in
110                         *"$t"*"$t"*"$t"*)
111                                 echo >&2 "$0: -u '$2': too many fields"
112                                 exit 1;;
113                         *"$t"*"$t"*)
114                                 ;;
115                         *)
116                                 echo >&2 "$0: -u '$2': not enough fields"
117                                 exit 1
118                         esac
119                         case $loginFullnameMailaddrs in
120                         '') loginFullnameMailaddrs=$2;;
121                         ?*) loginFullnameMailaddrs=$loginFullnameMailaddrs$nl$2
122                         esac
123                         shift
124                 esac
125                 case $logins in
126                 '') logins=$login;;
127                 ?*) logins=$logins$nl$login
128                 esac
129                 ;;
130         -r)
131                 case $rlog_options in
132                 '') rlog_options=${2?};;
133                 ?*) rlog_options=$rlog_options$nl${2?}
134                 esac
135                 shift;;
136         -R)     recursive=t;;
137         -t)     tabwidth=${2?}; shift;;
138         -v)     revision=t;;
139         --version)
140                 set $Id
141                 rcs2logVersion=$3
142                 echo >&2 "rcs2log (GNU Emacs) $rcs2logVersion$nl$Copyright"
143                 exit 0;;
144         -*)     echo >&2 "Usage: $0 [OPTION]... [FILE ...]$nl$Help"
145                 case $1 in
146                 --help) exit 0;;
147                 *) exit 1
148                 esac;;
149         *)      break
150         esac
151         shift
152 done
153
154 month_data='
155         m[0]="Jan"; m[1]="Feb"; m[2]="Mar"
156         m[3]="Apr"; m[4]="May"; m[5]="Jun"
157         m[6]="Jul"; m[7]="Aug"; m[8]="Sep"
158         m[9]="Oct"; m[10]="Nov"; m[11]="Dec"
159 '
160
161
162 # Put rlog output into $rlogout.
163
164 # If no rlog options are given,
165 # log the revisions checked in since the first ChangeLog entry.
166 # Since ChangeLog is only by date, some of these revisions may be duplicates of
167 # what's already in ChangeLog; it's the user's responsibility to remove them.
168 case $rlog_options in
169 '')
170         if test -s "$changelog"
171         then
172                 e='
173                         /^[0-9]+-[0-9][0-9]-[0-9][0-9]/{
174                                 # ISO 8601 date
175                                 print $1
176                                 exit
177                         }
178                         /^... ... [ 0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]+ /{
179                                 # old-fashioned date and time (Emacs 19.31 and earlier)
180                                 '"$month_data"'
181                                 year = $5
182                                 for (i=0; i<=11; i++) if (m[i] == $2) break
183                                 dd = $3
184                                 printf "%d-%02d-%02d\n", year, i+1, dd
185                                 exit
186                         }
187                 '
188                 d=`$AWK "$e" <"$changelog"` || exit
189                 case $d in
190                 ?*) datearg="-d>$d"
191                 esac
192         fi
193 esac
194
195 # Use TZ specified by ChangeLog local variable, if any.
196 if test -s "$changelog"
197 then
198         extractTZ='
199                 /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*"\([^"]*\)".*/{
200                         s//\1/; p; q
201                 }
202                 /^.*change-log-time-zone-rule['"$tab"' ]*:['"$tab"' ]*t.*/{
203                         s//UTC0/; p; q
204                 }
205         '
206         logTZ=`tail "$changelog" | sed -n "$extractTZ"`
207         case $logTZ in
208         ?*) TZ=$logTZ; export TZ
209         esac
210 fi
211
212 # If CVS is in use, examine its repository, not the normal RCS files.
213 if test ! -f CVS/Repository
214 then
215         rlog=rlog
216         repository=
217 else
218         rlog='cvs -q log'
219         repository=`sed 1q <CVS/Repository` || exit
220         test ! -f CVS/Root || CVSROOT=`cat <CVS/Root` || exit
221         case $CVSROOT in
222         *:/*)
223                 # remote repository
224                 ;;
225         *)
226                 # local repository
227                 case $repository in
228                 /*) ;;
229                 *) repository=${CVSROOT?}/$repository
230                 esac
231                 if test ! -d "$repository"
232                 then
233                         echo >&2 "$0: $repository: bad repository (see CVS/Repository)"
234                         exit 1
235                 fi
236         esac
237 fi
238
239 # Use $rlog's -zLT option, if $rlog supports it.
240 case `$rlog -zLT 2>&1` in
241 *' option'*) ;;
242 *)
243         case $rlog_options in
244         '') rlog_options=-zLT;;
245         ?*) rlog_options=-zLT$nl$rlog_options
246         esac
247 esac
248
249 # With no arguments, examine all files under the RCS directory.
250 case $# in
251 0)
252         case $repository in
253         '')
254                 oldIFS=$IFS
255                 IFS=$nl
256                 case $recursive in
257                 t)
258                         RCSdirs=`find . -name RCS -type d -print`
259                         filesFromRCSfiles='s|,v$||; s|/RCS/|/|; s|^\./||'
260                         files=`
261                                 {
262                                         case $RCSdirs in
263                                         ?*) find $RCSdirs \
264                                                         -type f \
265                                                         ! -name '*_' \
266                                                         ! -name ',*,' \
267                                                         ! -name '.*_' \
268                                                         ! -name .rcsfreeze.log \
269                                                         ! -name .rcsfreeze.ver \
270                                                         -print
271                                         esac
272                                         find . -name '*,v' -print
273                                 } |
274                                 sort -u |
275                                 sed "$filesFromRCSfiles"
276                         `;;
277                 *)
278                         files=
279                         for file in RCS/.* RCS/* .*,v *,v
280                         do
281                                 case $file in
282                                 RCS/. | RCS/.. | RCS/,*, | RCS/*_) continue;;
283                                 RCS/.rcsfreeze.log | RCS/.rcsfreeze.ver) continue;;
284                                 RCS/.\* | RCS/\* | .\*,v | \*,v) test -f "$file" || continue;;
285                                 RCS/*,v | RCS/.*,v) ;;
286                                 RCS/* | RCS/.*) test -f "$file" || continue
287                                 esac
288                                 case $files in
289                                 '') files=$file;;
290                                 ?*) files=$files$nl$file
291                                 esac
292                         done
293                         case $files in
294                         '') exit 0
295                         esac
296                 esac
297                 set x $files
298                 shift
299                 IFS=$oldIFS
300         esac
301 esac
302
303 llogout=$TMPDIR/rcs2log$$l
304 rlogout=$TMPDIR/rcs2log$$r
305 trap exit 1 2 13 15
306 trap "rm -f $llogout $rlogout; exit 1" 0
307
308 case $datearg in
309 ?*) $rlog $rlog_options "$datearg" ${1+"$@"} >$rlogout;;
310 '') $rlog $rlog_options ${1+"$@"} >$rlogout
311 esac || exit
312
313
314 # Get the full name of each author the logs mention, and set initialize_fullname
315 # to awk code that initializes the `fullname' awk associative array.
316 # Warning: foreign authors (i.e. not known in the passwd file) are mishandled;
317 # you have to fix the resulting output by hand.
318
319 initialize_fullname=
320 initialize_mailaddr=
321
322 case $loginFullnameMailaddrs in
323 ?*)
324         case $loginFullnameMailaddrs in
325         *\"* | *\\*)
326                 sed 's/["\\]/\\&/g' >$llogout <<EOF || exit
327 $loginFullnameMailaddrs
328 EOF
329                 loginFullnameMailaddrs=`cat $llogout`
330         esac
331
332         oldIFS=$IFS
333         IFS=$nl
334         for loginFullnameMailaddr in $loginFullnameMailaddrs
335         do
336                 case $loginFullnameMailaddr in
337                 *"$tab"*) IFS=$tab;;
338                 *) IFS=:
339                 esac
340                 set x $loginFullnameMailaddr
341                 login=$2
342                 fullname=$3
343                 mailaddr=$4
344                 initialize_fullname="$initialize_fullname
345                         fullname[\"$login\"] = \"$fullname\""
346                 initialize_mailaddr="$initialize_mailaddr
347                         mailaddr[\"$login\"] = \"$mailaddr\""
348         done
349         IFS=$oldIFS
350 esac
351
352 case $llogout in
353 ?*) sort -u -o $llogout <<EOF || exit
354 $logins
355 EOF
356 esac
357 output_authors='/^date: / {
358         if ($2 ~ /^[0-9]*[-\/][0-9][0-9][-\/][0-9][0-9]$/ && $3 ~ /^[0-9][0-9]:[0-9][0-9]:[0-9][0-9][-+0-9:]*;$/ && $4 == "author:" && $5 ~ /^[^;]*;$/) {
359                 print substr($5, 1, length($5)-1)
360         }
361 }'
362 authors=`
363         $AWK "$output_authors" <$rlogout |
364         case $llogout in
365         '') sort -u;;
366         ?*) sort -u | comm -23 - $llogout
367         esac
368 `
369 case $authors in
370 ?*)
371         cat >$llogout <<EOF || exit
372 $authors
373 EOF
374         initialize_author_script='s/["\\]/\\&/g; s/.*/author[\"&\"] = 1/'
375         initialize_author=`sed -e "$initialize_author_script" <$llogout`
376         awkscript='
377                 BEGIN {
378                         alphabet = "abcdefghijklmnopqrstuvwxyz"
379                         ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
380                         '"$initialize_author"'
381                 }
382                 {
383                         if (author[$1]) {
384                                 fullname = $5
385                                 if (fullname ~ /[0-9]+-[^(]*\([0-9]+\)$/) {
386                                         # Remove the junk from fullnames like "0000-Admin(0000)".
387                                         fullname = substr(fullname, index(fullname, "-") + 1)
388                                         fullname = substr(fullname, 1, index(fullname, "(") - 1)
389                                 }
390                                 if (fullname ~ /,[^ ]/) {
391                                         # Some sites put comma-separated junk after the fullname.
392                                         # Remove it, but leave "Bill Gates, Jr" alone.
393                                         fullname = substr(fullname, 1, index(fullname, ",") - 1)
394                                 }
395                                 abbr = index(fullname, "&")
396                                 if (abbr) {
397                                         a = substr($1, 1, 1)
398                                         A = a
399                                         i = index(alphabet, a)
400                                         if (i) A = substr(ALPHABET, i, 1)
401                                         fullname = substr(fullname, 1, abbr-1) A substr($1, 2) substr(fullname, abbr+1)
402                                 }
403
404                                 # Quote quotes and backslashes properly in full names.
405                                 # Do not use gsub; traditional awk lacks it.
406                                 quoted = ""
407                                 rest = fullname
408                                 for (;;) {
409                                         p = index(rest, "\\")
410                                         q = index(rest, "\"")
411                                         if (p) {
412                                                 if (q && q<p) p = q
413                                         } else {
414                                                 if (!q) break
415                                                 p = q
416                                         }
417                                         quoted = quoted substr(rest, 1, p-1) "\\" substr(rest, p, 1)
418                                         rest = substr(rest, p+1)
419                                 }
420
421                                 printf "fullname[\"%s\"] = \"%s%s\"\n", $1, quoted, rest
422                                 author[$1] = 0
423                         }
424                 }
425         '
426
427         initialize_fullname=`
428                 {
429                         (getent passwd $authors) ||
430                         (
431                                 cat /etc/passwd
432                                 for author in $authors
433                                 do NIS_PATH= nismatch $author passwd.org_dir
434                                 done
435                                 ypmatch $authors passwd
436                         )
437                 } 2>/dev/null |
438                 $AWK -F: "$awkscript"
439         `$initialize_fullname
440 esac
441
442
443 # Function to print a single log line.
444 # We don't use awk functions, to stay compatible with old awk versions.
445 # `Log' is the log message (with \n replaced by \001).
446 # `files' contains the affected files.
447 printlogline='{
448
449         # Following the GNU coding standards, rewrite
450         #       * file: (function): comment
451         # to
452         #       * file (function): comment
453         if (Log ~ /^\([^)]*\): /) {
454                 i = index(Log, ")")
455                 files = files " " substr(Log, 1, i)
456                 Log = substr(Log, i+3)
457         }
458
459         # If "label: comment" is too long, break the line after the ":".
460         sep = " "
461         if ('"$length"' <= '"$indent"' + 1 + length(files) + index(Log, SOH)) sep = "\n" indent_string
462
463         # Print the label.
464         printf "%s*%s:", indent_string, files
465
466         # Print each line of the log, transliterating \001 to \n.
467         while ((i = index(Log, SOH)) != 0) {
468                 logline = substr(Log, 1, i-1)
469                 if (logline ~ /[^'"$tab"' ]/) {
470                         printf "%s%s\n", sep, logline
471                 } else {
472                         print ""
473                 }
474                 sep = indent_string
475                 Log = substr(Log, i+1)
476         }
477 }'
478
479 # Pattern to match the `revision' line of rlog output.
480 rlog_revision_pattern='^revision [0-9]+\.[0-9]+(\.[0-9]+\.[0-9]+)*(['"$tab"' ]+locked by: [^'"$tab"' $,.0-9:;@]*[^'"$tab"' $,:;@][^'"$tab"' $,.0-9:;@]*;)?['"$tab"' ]*$'
481
482 case $hostname in
483 '')
484         hostname=`(
485                 hostname || uname -n || uuname -l || cat /etc/whoami
486         ) 2>/dev/null` || {
487                 echo >&2 "$0: cannot deduce hostname"
488                 exit 1
489         }
490
491         case $hostname in
492         *.*) ;;
493         *)
494                 domainname=`(domainname) 2>/dev/null` &&
495                 case $domainname in
496                 *.*) hostname=$hostname.$domainname
497                 esac
498         esac
499 esac
500
501
502 # Process the rlog output, generating ChangeLog style entries.
503
504 # First, reformat the rlog output so that each line contains one log entry.
505 # Transliterate \n to \001 so that multiline entries fit on a single line.
506 # Discard irrelevant rlog output.
507 $AWK <$rlogout '
508         BEGIN { repository = "'"$repository"'" }
509         /^RCS file:/ {
510                 if (repository != "") {
511                         filename = $3
512                         if (substr(filename, 1, length(repository) + 1) == repository "/") {
513                                 filename = substr(filename, length(repository) + 2)
514                         }
515                         if (filename ~ /,v$/) {
516                                 filename = substr(filename, 1, length(filename) - 2)
517                         }
518                         if (filename ~ /(^|\/)Attic\/[^\/]*$/) {
519                                 i = length(filename)
520                                 while (substr(filename, i, 1) != "/") i--
521                                 filename = substr(filename, 1, i - 6) substr(filename, i + 1)
522                         }
523                 }
524                 rev = "?"
525         }
526         /^Working file:/ { if (repository == "") filename = $3 }
527         /'"$rlog_revision_pattern"'/, /^(-----------*|===========*)$/ {
528                 line = $0
529                 if (line ~ /'"$rlog_revision_pattern"'/) {
530                         rev = $2
531                         next
532                 }
533                 if (line ~ /^date: [0-9][- +\/0-9:]*;/) {
534                         date = $2
535                         if (date ~ /\//) {
536                                 # This is a traditional RCS format date YYYY/MM/DD.
537                                 # Replace "/"s with "-"s to get ISO format.
538                                 newdate = ""
539                                 while ((i = index(date, "/")) != 0) {
540                                         newdate = newdate substr(date, 1, i-1) "-"
541                                         date = substr(date, i+1)
542                                 }
543                                 date = newdate date
544                         }
545                         time = substr($3, 1, length($3) - 1)
546                         author = substr($5, 1, length($5)-1)
547                         printf "%s %s %s %s %s %c", filename, rev, date, time, author, 1
548                         rev = "?"
549                         next
550                 }
551                 if (line ~ /^branches: /) { next }
552                 if (line ~ /^(-----------*|===========*)$/) { print ""; next }
553                 if (line == "Initial revision" || line ~ /^file .+ was initially added on branch .+\.$/) {
554                         line = "New file."
555                 }
556                 printf "%s%c", line, 1
557         }
558 ' |
559
560 # Now each line is of the form
561 # FILENAME REVISION YYYY-MM-DD HH:MM:SS[+-TIMEZONE] AUTHOR \001LOG
562 #       where \001 stands for a carriage return,
563 #       and each line of the log is terminated by \001 instead of \n.
564 # Sort the log entries, first by date+time (in reverse order),
565 # then by author, then by log entry, and finally by file name and revision
566 # (just in case).
567 sort +2 -4r +4 +0 |
568
569 # Finally, reformat the sorted log entries.
570 $AWK '
571         BEGIN {
572                 logTZ = "'"$logTZ"'"
573                 revision = "'"$revision"'"
574
575                 # Some awk variants do not understand "\001", so we have to
576                 # put the char directly in the file.
577                 SOH="\ 1" # <-- There is a single SOH (octal code 001) here.
578
579                 # Initialize the fullname and mailaddr associative arrays.
580                 '"$initialize_fullname"'
581                 '"$initialize_mailaddr"'
582
583                 # Initialize indent string.
584                 indent_string = ""
585                 i = '"$indent"'
586                 if (0 < '"$tabwidth"')
587                         for (;  '"$tabwidth"' <= i;  i -= '"$tabwidth"')
588                                 indent_string = indent_string "\t"
589                 while (1 <= i--)
590                         indent_string = indent_string " "
591         }
592
593         {
594                 newlog = substr($0, 1 + index($0, SOH))
595
596                 # Ignore log entries prefixed by "#".
597                 if (newlog ~ /^#/) { next }
598
599                 if (Log != newlog || date != $3 || author != $5) {
600
601                         # The previous log and this log differ.
602
603                         # Print the old log.
604                         if (date != "") '"$printlogline"'
605
606                         # Logs that begin with "{clumpname} " should be grouped together,
607                         # and the clumpname should be removed.
608                         # Extract the new clumpname from the log header,
609                         # and use it to decide whether to output a blank line.
610                         newclumpname = ""
611                         sep = "\n"
612                         if (date == "") sep = ""
613                         if (newlog ~ /^\{[^'"$tab"' }]*}['"$tab"' ]/) {
614                                 i = index(newlog, "}")
615                                 newclumpname = substr(newlog, 1, i)
616                                 while (substr(newlog, i+1) ~ /^['"$tab"' ]/) i++
617                                 newlog = substr(newlog, i+1)
618                                 if (clumpname == newclumpname) sep = ""
619                         }
620                         printf sep
621                         clumpname = newclumpname
622
623                         # Get ready for the next log.
624                         Log = newlog
625                         if (files != "")
626                                 for (i in filesknown)
627                                         filesknown[i] = 0
628                         files = ""
629                 }
630                 if (date != $3  ||  author != $5) {
631                         # The previous date+author and this date+author differ.
632                         # Print the new one.
633                         date = $3
634                         time = $4
635                         author = $5
636
637                         zone = ""
638                         if (logTZ && ((i = index(time, "-")) || (i = index(time, "+"))))
639                                 zone = " " substr(time, i)
640
641                         # Print "date[ timezone]  fullname  <email address>".
642                         # Get fullname and email address from associative arrays;
643                         # default to author and author@hostname if not in arrays.
644                         if (fullname[author])
645                                 auth = fullname[author]
646                         else
647                                 auth = author
648                         printf "%s%s  %s  ", date, zone, auth
649                         if (mailaddr[author])
650                                 printf "<%s>\n\n", mailaddr[author]
651                         else
652                                 printf "<%s@%s>\n\n", author, "'"$hostname"'"
653                 }
654                 if (! filesknown[$1]) {
655                         filesknown[$1] = 1
656                         if (files == "") files = " " $1
657                         else files = files ", " $1
658                         if (revision && $2 != "?") files = files " " $2
659                 }
660         }
661         END {
662                 # Print the last log.
663                 if (date != "") {
664                         '"$printlogline"'
665                         printf "\n"
666                 }
667         }
668 ' &&
669
670
671 # Exit successfully.
672
673 exec rm -f $llogout $rlogout
674
675 # Local Variables:
676 # tab-width:4
677 # End: