3 # this is a line editor using only /bin/sh, /bin/dd and /bin/rm
5 # /bin/rm is not really required, but it is nice to clean up temporary files
11 # temporary files we might need
14 trap "$rm -f $tmp $tmp.1 $tmp.2 $tmp.3 $tmp.4 $tmp.5 $tmp.6 $ed.a $ed.b $ed.c; exit" 0 1 2 3
16 # from now on, no more rm - the above trap is enough
19 # we do interesting things with IFS, but better save it...
22 # in case "echo" is not a shell builtin...
27 $dd of
=$tmp 2>/dev
/null
<<EOF
31 set `$dd if=$tmp bs=1 of=/dev/null skip=1 2>&1`
33 $dd if=$tmp bs
=1 count
=$1 2>/dev
/null
35 *) $dd 2>/dev
/null
<<EOF
42 # this is used to generate garbage files
66 # arithmetic using dd!
68 # add variable n1 n2 n3...
69 # assigns n1+n2+n3+... to variable
74 $dd if=/dev
/null of
=$tmp bs
=1 2>/dev
/null
79 *) zero |
$dd of
=$tmp.1 bs
=1 "count=$n" 2>/dev
/null
80 ( $dd if=$tmp; $dd if=$tmp.1 ) 2>/dev
/null |
$dd of
=$tmp.2 2>/dev
/null
81 $dd if=$tmp.2 of
=$tmp 2>/dev
/null
86 set `$dd if=$tmp bs=1 of=/dev/null 2>&1`
91 # subtract variable n1 n2
92 # subtracts n2 from n1, assigns result to variable
96 zero |
$dd of
=$tmp bs
=1 "count=$2" 2>/dev
/null
98 set `$dd if=$tmp bs=1 of=/dev/null "skip=$3" 2>&1`
106 # multiply variable n1 n2
111 zero |
$dd "bs=$2" of
=$tmp "count=$3" 2>/dev
/null
113 set `$dd if=$tmp bs=1 of=/dev/null 2>&1`
118 # divide variable n1 n2
119 # variable = int( n1 / n2 )
123 zero |
$dd bs
=1 of
=$tmp "count=$2" 2>/dev
/null
125 set `$dd if=$tmp "bs=$3" of=/dev/null 2>&1`
130 # compare variable n1 n2 sets variable to lt if n1<n2, gt if n1>n2, eq if n1==n2
136 subtract somename
"$n1" "$n2"
139 *) eval $res=gt
; return;
141 subtract somename
"$n2" "$n1"
144 *) eval $res=lt
; return;
149 # lt n1 n2 returns true if n1 < n2
154 subtract somename
"$n2" "$n1"
161 # le n1 n2 returns true if n1 <= n2
166 subtract somename
"$n1" "$n2"
173 # gt n1 n2 returns true if n1 > n2
178 subtract somename
"$n1" "$n2"
185 # ge n1 n2 returns true if n1 >= n2
190 subtract somename
"$n2" "$n1"
197 # useful functions for the line editor
199 # open a file - copy it to the buffers
203 set `$dd "if=$file" of=/dev/null 2>&1`
207 # copy the first line to $ed.c
212 case "`$dd "if=$file" bs=1 skip=$len count=1 2>/dev/null`" in
218 # now $len is the length of the first line (including newline)
219 $dd "if=$file" bs
=1 count
=$len of
=$ed.c
2>/dev
/null
220 $dd "if=$file" bs
=1 skip
=$len of
=$ed.b
2>/dev
/null
221 $dd if=/dev
/null of
=$ed.a
2>/dev
/null
225 # save a file - copy the buffers to the file
228 # make a backup copy of the original
229 $dd "if=$1" "of=$1.bak" 2>/dev
/null
231 ( $dd if=$ed.a
; $dd if=$ed.c
; $dd if=$ed.b
) > "$1" 2>/dev
/null
234 # replace n1 n2 bla replaces n2 chars of current line, starting n1-th
237 $dd if=$ed.c of
=$tmp.1 bs
=1 "count=$1" 2>/dev
/null
238 ( $dd if=$ed.c
"skip=$1" bs
=1 |
$dd of
=$tmp.2 bs
=1 "skip=$2" ) 2>/dev
/null
241 ( $dd if=$tmp.1; Echo
-n "$@"; $dd if=$tmp.2 ) > $tmp.3 2>/dev
/null
242 $dd if=$tmp.3 of
=$ed.c
2>/dev
/null
246 # replace the n-th occurence of s with bla
251 # first we have to find it - this is fun!
252 # we have $tmp.4 => text before string, $tmp.5 => text after
253 $dd if=/dev
/null of
=$tmp.4 2>/dev
/null
254 $dd if=$ed.c of
=$tmp.5 2>/dev
/null
257 $dd of
=$tmp.6 2>/dev
/null
<<EOF
262 case "`$dd if=$tmp.5 2>/dev/null`" in
266 # now we want to replace the string
267 Echo
-n "$@" > $tmp.2
268 Echo
-n "$string" > $tmp.1
270 set `$dd bs=1 if=$tmp.1 of=/dev/null 2>&1`
274 ( $dd if=$tmp.4; $dd if=$tmp.2; $dd if=$tmp.5 bs
=1 skip
=$slen ) \
276 $dd if=$tmp of
=$ed.c
2>/dev
/null
280 ( $dd if=$tmp.4; $dd if=$tmp.5 bs
=1 count
=1 ) > $tmp 2>/dev
/null
281 $dd if=$tmp of
=$tmp.4 2>/dev
/null
282 # and remove it from $tmp.5
283 $dd if=$tmp.5 of
=$tmp bs
=1 skip
=1 2>/dev
/null
284 $dd if=$tmp of
=$tmp.5 2>/dev
/null
287 ?
*) # add one more byte...
288 ( $dd if=$tmp.4; $dd if=$tmp.5 bs
=1 count
=1 ) > $tmp 2>/dev
/null
289 $dd if=$tmp of
=$tmp.4 2>/dev
/null
290 # and remove it from $tmp.5
291 $dd if=$tmp.5 of
=$tmp bs
=1 skip
=1 2>/dev
/null
292 $dd if=$tmp of
=$tmp.5 2>/dev
/null
304 ( $dd if=$ed.a
; $dd if=$ed.c
) 2>/dev
/null
> $tmp.3
305 $dd if=$ed.b of
=$tmp.4 2>/dev
/null
307 $dd if=$tmp.3 of
=$ed.a
2>/dev
/null
311 # delete current line
314 $dd if=$ed.a
2>/dev
/null
> $tmp.1
315 $dd if=$ed.b of
=$tmp.2 2>/dev
/null
317 $dd if=$tmp.1 of
=$ed.a
2>/dev
/null
321 # insert before current line (without changing current)
323 ( $dd if=$ed.a
; Echo
"$@" ) 2>/dev
/null
> $tmp.1
324 $dd if=$tmp.1 of
=$ed.a
2>/dev
/null
332 *) subtract lineno
$lineno 1
333 # read last line of $ed.a
335 set `$dd if=$ed.a of=/dev/null bs=1 2>&1`
342 subtract size
$size 1
346 *) subtract size1
$size 1
347 case "`$dd if=$ed.a bs=1 skip=$size count=1 2>/dev/null`" in
358 *) case "`$dd if=$ed.a bs=1 skip=$size count=1 2>/dev/null`" in
359 ?
*) go
=true
; subtract size
$size 1 ;;
360 *) go
=false
; add size
$size 1 ;;
365 # now $size is the size of the first n-1 lines
367 ( $dd if=$ed.c
; $dd if=$ed.b
) 2>/dev
/null
> $tmp.5
368 $dd if=$tmp.5 of
=$ed.b
2>/dev
/null
371 0) $dd if=$ed.a of
=$ed.c
2>/dev
/null
372 $dd if=/dev
/null of
=$tmp.5 2>/dev
/null
374 *) $dd if=$ed.a of
=$ed.c bs
=1 skip
=$size 2>/dev
/null
375 $dd if=$ed.a of
=$tmp.5 bs
=1 count
=$size 2>/dev
/null
379 $dd if=$tmp.5 of
=$ed.a
2>/dev
/null
384 # goes to a given line
387 compare bla
"$rl" $lineno
391 gt
) while gt
"$rl" $lineno
396 lt
) while lt
"$rl" $lineno
406 $dd if=$ed.c
2>/dev
/null
417 case "$cmd:$state" in
418 open
:open
) Echo
"There is a file open already" ;;
419 open
:*) if open
"$arg"
420 then state
=open
; name
="$arg"; $autoprint
421 else Echo
"Cannot open $arg"
424 new
:open
) Echo
"There is a file open already" ;;
430 close
:changed
) Echo
"Use 'discard' or 'save'" ;;
431 close
:closed
) Echo
"Closed already" ;;
432 close
:*) state
=closed
;;
433 save
:closed
) Echo
"There isn't a file to save" ;;
434 save
:*) case "$arg" in
440 discard
:changed
) Echo
"Your problem!"; state
=closed
;;
441 discard
:*) state
=closed
;;
442 print
:closed
) Echo
"No current file" ;;
444 goto
:closed
) Echo
"No current file" ;;
445 goto
:*) goto
"$arg"; $autoprint ;;
446 next
:closed
) Echo
"No current file" ;;
447 next
:*) next
; $autoprint ;;
448 prev
:closed
) Echo
"No current file" ;;
449 prev
:*) prev
; $autoprint ;;
450 name
:closed
) Echo
"No current file" ;;
451 name
:*) name
="$arg" ;;
452 replace
:closed
) Echo
"No current file" ;;
453 replace
:*) if rstring
1 $arg
454 then state
=changed
; $autoprint
455 else Echo
"Not found"
458 nreplace
:closed
) Echo
"No current file" ;;
459 nreplace
:*) if rstring
$arg
460 then state
=changed
; $autoprint
461 else Echo
"Not found"
464 delete
:closed
) Echo
"No current file" ;;
465 delete
:*) delete
; state
=changed
; $autoprint ;;
466 insert
:closed
) Echo
"No current file" ;;
467 insert
:*) insert
"$arg"; prev
; state
=changed
; $autoprint ;;
468 quit
:changed
) Echo
"Use 'save' or 'discard'" ;;
469 quit
:*) Echo
"bye"; exit;;
470 autoprint
:*) autoprint
="lineout" ;;
471 noprint
:*) autoprint
="" ;;
473 *) Echo
"Command not understood" ;;