[comp.lang.icon] VMS Shell Archive Facility

TENAGLIA@mis.mcw.edu (Chris Tenaglia - 257-8765) (01/13/91)

Below is a shell archive that contains itself. I wrote it because I wanted
to extract some of the archived goodies that get posted here. I made it
for VMS and MS-DOS. I haven't tested the MS-DOS ;-) parts yet. I also can't
test the builder part as I have no unix system yet to test it. Maybe
someone can let me know if it works. Maybe someone will want to add support
for MACintosh, AMIGA, etc,... Maybe we should have an icon archiver, that's
hardware/os independent? Any comments?

Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd.     | Milwaukee, WI 53226
(414)257-8765                   | tenaglia@mis.mcw.edu, mcwmis!tenaglia

#!/bin/sh
# This is shar.sh, a shell archive (sh.icn 1.0)
# made Sunday, January 13, 1991  7:47 am by tenaglia@mis.mcw.edu
# Source directory /usr53/tenaglia/i/
#
# existing files will Not be overwritten, hopefully
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------

#   7556 -rw-r--r-- sh.icn
#    928 -rw-r--r-- sh.txt
#
# Test of VMS Shell Archive Facility
# Does everything extract properly under unix?
#
# ============== sh.icn ==============
if test X"$1" != X"-c" -a -f 'sh.icn'; then
	echo "File already exists: skipping 'sh.icn'"
else
echo "x - extracting sh.icn (Text)"
sed 's/^X//' << 'SHEOF' > sh.icn &&
X##################################################################
X#                                                                #
X# SH.ICN                 01/11/91          BY TENAGLIA           #
X#                                                                #
X# PROGRAM HANDLES  UNIX SHELL ARCHIVES                           #
X# USAGE : sh archive [action] [target]                           #
X#         Where action is extract(default) list or build         #
X#         If action is list, target is ignored.                  #
X#         If action is extract (""), target is ignored           #
X#         If action id build, target is filespec to archive      #
X# NOTE :  Does not make split archives yet.                      #
X# NOTE :  Extraction doesn't check for overwrite, just does it.  #
X# NOTE :  shar 3.xx lengths include the leading X, and don't     #
X#         match here. This uses their real lengths.              #
X#                                                                #
X##################################################################
Xglobal os, files
Xprocedure main(param)
X  source := param[1]          | input("_Source:")
X  option := param[2]          | "extract"
X  target := param[3]          | "!nill"
X  work   := case option of
X    {
X    "list" : " Lister\n"
X    "build": " Builder\n"
X    default: " Extractor\n"
X    }
X  write("sh : Unix Shell Archive",work)
X  os     := getsys()
X  sum    := 0
X  if option == "build" then build(source)
X  (in    := open(source))     | stop("Can't open ",source)
X  while line := read(in) do
X    {
X    stuff := parse(line,'\"\'\t ')
X    if stuff[1] == "sed" & stuff[2] == "s/^X//" then
X      {
X      every i := 1 to *stuff do
X        {
X        if stuff[i] == "<<" then     { eof  := stuff[i+1] ; next }
X        if match("<<",stuff[i]) then { eof  := stuff[i][3:0] ; next }
X        if stuff[i] == ">>" then
X          {
X          name   := stuff[i+1]
X          method := "a"                # append
X          what   := "appended."
X          next
X          }
X        if match(">>",stuff[i]) then
X          {
X          name   := stuff[i][2:0]
X          method := "a"                # append
X          what   := "appended."
X          next
X          }
X        if stuff[i] == ">"  then
X          {
X          name   := stuff[i+1]
X          method := "w"                # create
X          what   := "written."
X          next
X          }
X        if match(">",stuff[i]) then
X          {
X          name   := stuff[i][2:0]
X          method := "w"                # create
X          what   := "written."
X          next
X          }
X        }
X      prog := extract(in,eof)
X      } else next
X    directory := if target == "!nill" then "" else target
X    (out := open(target||name,method)) | stop("Can't write ",name)
X    every stmt := !prog do
X      {
X      if option == "extract" then write(out,stmt)
X      sum +:= *stmt
X      }
X    if option == "extract"
X      then write(name," : ",sum," bytes ",what)
X      else write(name," : contains ",sum," bytes.")
X    sum := 0
X    close(out)
X    }
X  close(in)
X  end
X
X#
X# This routine extracts the shell archive for a module. It returns
X# the module in a list structure.
X#
Xprocedure extract(file,eofstr)
X  lst := []
X  until match(eofstr,(str := read(file))) do
X    put(lst,str[2:0])
X  return lst
X  end
X
X#
X# This routine builds a shell archive. archive is the archive to be made.
X# The rest of this is interactive.
X#
Xprocedure build(archive)
X  username  := input("Username  :")
X  directory := input("Directory :")
X  modules   := table([])
X  find(".",archive) | (archive ||:= ".sh")
X  (output   := open(archive,"w")) | stop("Can't write to ",archive)
X  comments  := ["#"] ; write("Enter Comments (blank line when done)")
X  repeat {
X  comment := input("Comment :")
X  if trim(comment) == "" then break
X  put(comments,"# " || comment) }
X  put(comments,"#")
X  begin := ["#!/bin/sh",
X            "# This is " || archive || ", a shell archive (sh.icn 1.0)",
X            "# made " || &dateline  || " by " || username,
X            "# Source directory "   || fsmap(directory),
X            "#", "# existing files will Not be overwritten, hopefully","#",
X            "# This shar contains:",
X            "# length  mode       name",
X            "# ------ ---------- ------------------------------------------",
X           ]
X  namelist := []
X  repeat {
X  name := input("File (blank when done) :")
X  if trim(name) == "" then break
X  (infile := open(directory||name)) | { write("Can't open ",directory,name) ; next }
X  code := [ "# ============== " || name || " ==============",
X            "if test X\"$1\" != X\"-c\" -a -f '" || name || "'; then",
X            "	echo \"File already exists: skipping '"  || name || "'\"",
X            "else",
X            "echo \"x - extracting " || name || " (Text)\"",
X            "sed 's/^X//' << 'SHEOF' > " || name || " &&" ]
X  measure := 0
X  while text := read(infile) do
X    {
X    measure +:= *text
X    put(code,"X" || text)
X    }
X  put(code,"SHEOF") ; close(infile)
X  put(begin,"# " || right(measure,6) || " -rw-r--r-- " || name)
X  insert(modules,name,copy(code)) ; put(namelist,name) }
X  output := open(archive,"a")
X  every write(output,!begin)
X  every write(output,!comments)
X  every file := !namelist do every write(output,!(modules[file]))
X  write(output,"#")
X  write(output,"# End of sh archive.")
X  close(output)
X  stop("sh archive written to ",archive)
X  end
X
X# # ============= README ==============                  this is what the
X# if test X"$1" != X"-c" -a -f 'README'; then            beginning of a shell
X#  echo "File already exists: skipping 'README'"         archive body should
X# else                                                   look like.
X# echo "x - extracting README (Text)"
X# sed 's/^X//' << 'SHAR_EOF' > README &&
X
X#
X# This routine parses a string with respect to some delimiter.
X# It returns the tokens in a list structure.
X#
Xprocedure parse(line,delims)
X  static chars
X  chars  := &cset -- delims
X  tokens := []
X  line ? while tab(upto(chars)) do put(tokens,tab(many(chars)))
X  return tokens
X  end
X
X#
X# This routine prompts for a string input. The entered string is returned.
X#
Xprocedure input(prompt)
X  writes(prompt)
X  return read()
X  end
X
X#
X# This procedure determines the os by examining &features.
X#
Xprocedure getsys()
X  files := "DIR "             # most logical initially
X  if &host == "MS-DOS" then
X    return &host
X  tmp := []
X  every feature := &features do
X    put(tmp,feature)
X  if tmp[1] ~== "VMS" then files := "ls "
X  return tmp[1]
X  end
X
X#
X# This routine maps the directory spec to unix style notation
X#
Xprocedure fsmap(spec)
X  if spec == "" then return spec
X  case os of
X    {
X    "VMS"    : { if (i := find(":",spec)) then
X                   {
X                   path := "/usr" || ord(spec[i-1]) || "/"
X                   if (x := find("[",spec)) then
X                     {
X                     y := find("]",spec)
X                     path ||:= map(spec[x+1:y],".","/") || "/"
X                     } else path ||:= spec[i+1:0] || "/"
X                   } else {
X                   if (x := find("[",spec)) then
X                     {
X                     y := find("]",spec)
X                     path := map(spec[x+1:y],".","/") || "/"
X                     } else path ||:= spec || "/"
X                   }
X                 return path
X               }
X    "MS-DOS" : { if find(":",spec) then
X                   {
X                   path := "/usr" || ord(map(spec[1])) - 96 || "/" ||
X                           map(spec[3:0],"\\","/")
X                   } else {
X                   path := map(spec,"\\","/")
X                   }
X                 (path[-1] == "/") | (path ||:= "/")
X               }
X    default  : { return spec }
X    }
X  end
X
SHEOF
# ============== sh.txt ==============
if test X"$1" != X"-c" -a -f 'sh.txt'; then
	echo "File already exists: skipping 'sh.txt'"
else
echo "x - extracting sh.txt (Text)"
sed 's/^X//' << 'SHEOF' > sh.txt &&
X
XThis is a shell archive utility for non-unix hosts. It can extract from
Xshell archives (no overwrite checking done). It can list archives. And
Xit can create archives. No actual shell script interpretation is done.
XFor extraction it reads the important stuff and extracts the files. For
Xbuilding, it runs through an interactive dialog.
X
XExamples : sh termlib1.sh             Extracts by default
X           sh mystuff build           Builds mystuff.sh archive
X           sh mgale.sh list           Lists modules of mgale archive
X
XI've written it primarily for VMS and MS-DOS. I haven't tested the MS-DOS
Xpart yet. Also since I don't have unix out there, someone out there in
Xunixland can test it to make sure that what it builds is extractable.
X
XYours truly,
X
XChris Tenaglia (System Manager) | Medical College of Wisconsin
X8701 W. Watertown Plank Rd.     | Milwaukee, WI 53226
X(414)257-8765                   | tenaglia@mis.mcw.edu, mcwmis!tenaglia
X
SHEOF
#
# End of sh archive.