summaryrefslogtreecommitdiff
path: root/docs/tutorials/011/combine.shar
blob: 4796dd523f205dbcab4667ea224f6d3bf9dc08ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1999-09-21 22:49 EDT by <jcej@chiroptera.tragus.org>.
# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/011'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#    442 -rw-rw-r-- hdr
#     48 -rw-rw-r-- bodies
#    869 -rw-rw-r-- page01.pre
#    164 -rw-rw-r-- page02.pre
#    174 -rw-rw-r-- page03.pre
#    127 -rw-rw-r-- page04.pre
#   2691 -rw-rw-r-- page05.pre
#    707 -rw-rw-r-- page06.pre
#    351 -rw-rw-r-- page02.pst
#    366 -rw-rw-r-- page03.pst
#    129 -rw-rw-r-- page04.pst
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh04967; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= hdr ==============
if test -f 'hdr' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'hdr' '(file already exists)'
else
  $echo 'x -' extracting 'hdr' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'hdr' &&
<HTML>
<HEAD>
X   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
X   <META NAME="Author" CONTENT="James CE Johnson">
X   <TITLE>ACE Tutorial 011</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">
X
<CENTER><B><FONT SIZE=+2>ACE Tutorial 011</FONT></B></CENTER>
X
<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER>
X
X
<P>
<HR WIDTH="100%">
SHAR_EOF
  $shar_touch -am 0124154699 'hdr' &&
  chmod 0664 'hdr' ||
  $echo 'restore of' 'hdr' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'hdr:' 'MD5 check failed'
cf10a170c9ca8512b7051526e2dcf83c  hdr
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`"
    test 442 -eq "$shar_count" ||
    $echo 'hdr:' 'original size' '442,' 'current size' "$shar_count!"
  fi
fi
# ============= bodies ==============
if test -f 'bodies' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'bodies' '(file already exists)'
else
  $echo 'x -' extracting 'bodies' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'bodies' &&
PAGE=2
message_queue.cpp
task.h task.cpp
data.h
SHAR_EOF
  $shar_touch -am 0124155199 'bodies' &&
  chmod 0664 'bodies' ||
  $echo 'restore of' 'bodies' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'bodies:' 'MD5 check failed'
db3ba3829b49952c833adb921acd3d3f  bodies
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`"
    test 48 -eq "$shar_count" ||
    $echo 'bodies:' 'original size' '48,' 'current size' "$shar_count!"
  fi
fi
# ============= page01.pre ==============
if test -f 'page01.pre' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page01.pre' '(file already exists)'
else
  $echo 'x -' extracting 'page01.pre' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page01.pre' &&
<P>
In the previous tutorial we learned how to put text into a message queue.
While that may be useful, it isn't very exciting or realistic.  In most
cases you'll need to move complex data structures between your threads.
<P>
In this tutorial I'll expand the previous by moving not only a text string
but also a more complex object.  In the next tutorial I'll change things
again so that we move the complex object a bit more efficiently.
<P>
A simple abstract for a simple tutorial:
<UL>
In this tutorial, we put some data into the blocks of the message queue.
We copy the data from a Data object into the block and put it on the
queue. The block is then dequeued by the thread which picks it up and
processes it. This tutorial is very similar to the previous
one with the extra touch being population of the blocks with data.
</UL>
(Abstract by Kirthika, as always.)
SHAR_EOF
  $shar_touch -am 0126201399 'page01.pre' &&
  chmod 0664 'page01.pre' ||
  $echo 'restore of' 'page01.pre' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page01.pre:' 'MD5 check failed'
58768929bbe513a9fa2302b1fe3170be  page01.pre
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
    test 869 -eq "$shar_count" ||
    $echo 'page01.pre:' 'original size' '869,' 'current size' "$shar_count!"
  fi
fi
# ============= page02.pre ==============
if test -f 'page02.pre' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page02.pre' '(file already exists)'
else
  $echo 'x -' extracting 'page02.pre' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page02.pre' &&
We'll look first at <A HREF="message_queue.cpp">main()</A>.  A large part of this is
the same as before, so I've only commented the changes.
<P>
X
<HR WIDTH="100%">
SHAR_EOF
  $shar_touch -am 0124154699 'page02.pre' &&
  chmod 0664 'page02.pre' ||
  $echo 'restore of' 'page02.pre' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page02.pre:' 'MD5 check failed'
ccd60d44cf4f9730aa16ff042f324c8e  page02.pre
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`"
    test 164 -eq "$shar_count" ||
    $echo 'page02.pre:' 'original size' '164,' 'current size' "$shar_count!"
  fi
fi
# ============= page03.pre ==============
if test -f 'page03.pre' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page03.pre' '(file already exists)'
else
  $echo 'x -' extracting 'page03.pre' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page03.pre' &&
X
Our Task object <A HREF="task.h">declaration</a> and <A HREF="task.cpp">definition</a>.
X  As with message_queue.cpp,
I've only commented the changes.
<P>
X
<HR WIDTH="100%">
SHAR_EOF
  $shar_touch -am 0124155099 'page03.pre' &&
  chmod 0664 'page03.pre' ||
  $echo 'restore of' 'page03.pre' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page03.pre:' 'MD5 check failed'
e99896d191834752e7e07317af06ea0c  page03.pre
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`"
    test 174 -eq "$shar_count" ||
    $echo 'page03.pre:' 'original size' '174,' 'current size' "$shar_count!"
  fi
fi
# ============= page04.pre ==============
if test -f 'page04.pre' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page04.pre' '(file already exists)'
else
  $echo 'x -' extracting 'page04.pre' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page04.pre' &&
X
Before we go further, let's look at this <A HREF="data.h">Data</A> object
that's causing all the fuss.
X
<P>
<HR WIDTH="100%">
SHAR_EOF
  $shar_touch -am 0124154699 'page04.pre' &&
  chmod 0664 'page04.pre' ||
  $echo 'restore of' 'page04.pre' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page04.pre:' 'MD5 check failed'
4fe23822fef63921fa81cbf97e25bd5e  page04.pre
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`"
    test 127 -eq "$shar_count" ||
    $echo 'page04.pre:' 'original size' '127,' 'current size' "$shar_count!"
  fi
fi
# ============= page05.pre ==============
if test -f 'page05.pre' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page05.pre' '(file already exists)'
else
  $echo 'x -' extracting 'page05.pre' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page05.pre' &&
X
Let's take a look at this new program's output:
X
<P>
<HR WIDTH="100%">
<PRE>
[jcej@chiroptera 011]$./message_queue 4 2
(12108|1024) Task ctor 0xbffff9c8
(12108|2050) Task 0xbffff9c8 starts in thread 2050
(12108|1025) Task 0xbffff9c8 starts in thread 1025
(12108|1024) DataBase ctor 0xbffff9c0
(12108|1024) Data ctor 0xbffff9c0 for message 0
(12108|1024) Block ctor 0x8052d08
(12108|1024) Data dtor 0xbffff9c0
(12108|1024) DataBase dtor 0xbffff9c0
(12108|1024) DataBase ctor 0xbffff9c0
(12108|1024) Data ctor 0xbffff9c0 for message 1
(12108|1024) Block ctor 0x8052e00
(12108|1024) Data dtor 0xbffff9c0
(12108|1024) DataBase dtor 0xbffff9c0
(12108|1024) DataBase ctor 0xbffff9c0
(12108|1024) Data ctor 0xbffff9c0 for message 2
(12108|1024) Block ctor 0x8052ef8
(12108|1024) Data dtor 0xbffff9c0
(12108|1024) DataBase dtor 0xbffff9c0
(12108|1024) DataBase ctor 0xbffff9c0
(12108|1024) Data ctor 0xbffff9c0 for message 3
(12108|1024) Block ctor 0x8052ff0
(12108|1024) Data dtor 0xbffff9c0
(12108|1024) DataBase dtor 0xbffff9c0
(12108|1024) Block ctor 0x80530e8
(12108|1025) Block 0x8052d08 contains (This is message 0.)
(12108|1025) DataBase ctor 0xbf9ffe20
(12108|1025) Data ctor 0xbf9ffe20
(12108|1025) DataBase instance 0xbf9ffe20
(12108|1025) I am a Data object for message 0
(12108|1025) Block dtor 0x8052d08
(12108|1025) Data dtor 0xbf9ffe20
(12108|1025) DataBase dtor 0xbf9ffe20
(12108|1025) Block 0x8052e00 contains (This is message 1.)
(12108|1025) DataBase ctor 0xbf9ffe20
(12108|1025) Data ctor 0xbf9ffe20
(12108|1025) DataBase instance 0xbf9ffe20
(12108|1025) I am a Data object for message 1
(12108|1025) Block dtor 0x8052e00
(12108|1025) Data dtor 0xbf9ffe20
(12108|1025) DataBase dtor 0xbf9ffe20
(12108|1025) Block 0x8052ef8 contains (This is message 2.)
(12108|1025) DataBase ctor 0xbf9ffe20
(12108|1025) Data ctor 0xbf9ffe20
(12108|1025) DataBase instance 0xbf9ffe20
(12108|1025) I am a Data object for message 2
(12108|1025) Block dtor 0x8052ef8
(12108|1025) Data dtor 0xbf9ffe20
(12108|1025) DataBase dtor 0xbf9ffe20
(12108|1025) Block 0x8052ff0 contains (This is message 3.)
(12108|1025) DataBase ctor 0xbf9ffe20
(12108|1025) Data ctor 0xbf9ffe20
(12108|1025) DataBase instance 0xbf9ffe20
(12108|1025) I am a Data object for message 3
(12108|2050) Task close 0xbffff9c8
(12108|1025) Block dtor 0x8052ff0
(12108|1025) Data dtor 0xbf9ffe20
(12108|1025) DataBase dtor 0xbf9ffe20
(12108|1025) Task close 0xbffff9c8
(12108|1024) Task dtor 0xbffff9c8
(12108|1024) Block dtor 0x80530e8
(12108|1024) Application exiting
[jcej@chiroptera 011]$
</PRE>
<HR WIDTH="100%">
<P>
Other than being more verbose because of the Data object, this shows us
the same thing we've seen before.
<P>
SHAR_EOF
  $shar_touch -am 0124154699 'page05.pre' &&
  chmod 0664 'page05.pre' ||
  $echo 'restore of' 'page05.pre' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page05.pre:' 'MD5 check failed'
b95ed571240b8383db0e0c0b07d04971  page05.pre
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`"
    test 2691 -eq "$shar_count" ||
    $echo 'page05.pre:' 'original size' '2691,' 'current size' "$shar_count!"
  fi
fi
# ============= page06.pre ==============
if test -f 'page06.pre' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page06.pre' '(file already exists)'
else
  $echo 'x -' extracting 'page06.pre' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page06.pre' &&
So, this time we stuffed an object into the message queue instead of just text
data.  Each time required two object constructions (and subsequent destructions)
and two "deep" copy operations on the object.  There might actually be times when
this is OK for your application but I prefer to keep those things down to a
minimum.  In the next tutorial I'll show you a way to do that.
<P>
X
<UL>
<LI><A HREF="Makefile">Makefile</A>
<LI><A HREF="block.h">block.h</A>
<LI><A HREF="data.h">data.h</A>*
<LI><A HREF="message_queue.cpp">message_queue.cpp</A>
<LI><A HREF="task.cpp">task.cpp</A>
<LI><A HREF="task.h">task.h</A>
</UL>
X
* data.h hasn't changed at all from Tutorial 7 so I didn't devote a
X    page to it.
SHAR_EOF
  $shar_touch -am 0124155399 'page06.pre' &&
  chmod 0664 'page06.pre' ||
  $echo 'restore of' 'page06.pre' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page06.pre:' 'MD5 check failed'
17d64bbe275773a80d7d767e04e0474c  page06.pre
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`"
    test 707 -eq "$shar_count" ||
    $echo 'page06.pre:' 'original size' '707,' 'current size' "$shar_count!"
  fi
fi
# ============= page02.pst ==============
if test -f 'page02.pst' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page02.pst' '(file already exists)'
else
  $echo 'x -' extracting 'page02.pst' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page02.pst' &&
<HR WIDTH="100%">
<P>
The new trick here is the use of copy() to copy our abstract data object
into the message block memory.  Notice that it's OK to let the Data object
go out of scope at that point since we've got a separate copy.  If you've
got something with a non-trivial ctor/dtor then this won't work.  We'll address
that in the next tutorial.
SHAR_EOF
  $shar_touch -am 0124154699 'page02.pst' &&
  chmod 0664 'page02.pst' ||
  $echo 'restore of' 'page02.pst' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page02.pst:' 'MD5 check failed'
89fa13e74842bc65092e0e6f61fdd889  page02.pst
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`"
    test 351 -eq "$shar_count" ||
    $echo 'page02.pst:' 'original size' '351,' 'current size' "$shar_count!"
  fi
fi
# ============= page03.pst ==============
if test -f 'page03.pst' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page03.pst' '(file already exists)'
else
  $echo 'x -' extracting 'page03.pst' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page03.pst' &&
<HR WIDTH="100%">
<P>
Notice how we had to create a temporary Data object to copy the stuff out
of the message block?  Again, if there were non-trivial ctor/dtors involved
then this wouldn't work at all.
<P>
Again, like <A HREF="../010/page01.html">Tutorial 10</A> we've skipped 
<i>THR_DETACHED</i> because we <i>wait()</i> for the threads to exit
X      elsewhere.
SHAR_EOF
  $shar_touch -am 0921223499 'page03.pst' &&
  chmod 0664 'page03.pst' ||
  $echo 'restore of' 'page03.pst' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page03.pst:' 'MD5 check failed'
ae1320ae6609c684317a5895f69bf47d  page03.pst
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pst'`"
    test 366 -eq "$shar_count" ||
    $echo 'page03.pst:' 'original size' '366,' 'current size' "$shar_count!"
  fi
fi
# ============= page04.pst ==============
if test -f 'page04.pst' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page04.pst' '(file already exists)'
else
  $echo 'x -' extracting 'page04.pst' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page04.pst' &&
<HR WIDTH="100%">
<P>
Ok, no mysterious magic on this one.  Just a simple object and derivative
that report their existence.
<P>
SHAR_EOF
  $shar_touch -am 0124154699 'page04.pst' &&
  chmod 0664 'page04.pst' ||
  $echo 'restore of' 'page04.pst' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page04.pst:' 'MD5 check failed'
777ab8789fb82b1e280b9e127983c4b0  page04.pst
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`"
    test 129 -eq "$shar_count" ||
    $echo 'page04.pst:' 'original size' '129,' 'current size' "$shar_count!"
  fi
fi
rm -fr _sh04967
exit 0