home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / osr5 / sco / scripts / admin / mmdf / mkmaillist < prev    next >
Encoding:
Korn shell script  |  1997-08-26  |  8.8 KB  |  321 lines

  1. #!/bin/ksh
  2. # @(#) mkmaillist.ksh 1.2 97/01/19
  3. # 96/09/05 john h. dubois (john@armory.com)
  4. # 96/09/20 Let <listname> and <list-owner> be derived from <listfile>.
  5. #          Added all options.
  6. # 96/10/11 Added cm options.  Format alias file entries by tab padding them.
  7.  
  8. aliasDir=/usr/mmdf/table
  9. defAliasFile=userlist.ali
  10. Tell=false
  11. rcFile=/etc/default/mkmaillist
  12. CreateFile=false
  13. majordomo=false
  14.  
  15. long_name=${0##*/}
  16. Usage="Usage:
  17. $long_name [-chmt] [-a<alias-file>] <listfile> [<listname> [<list-owner>]]"
  18.  
  19. while getopts a:chmt opt; do
  20.     case $opt in
  21.     h)
  22.     print -r -- \
  23. "$long_name: Create an MMDF mailing list.
  24. $long_name builds an alias table entry to set up an included mail alias (an
  25. alias whose contents are read from a file each time the alias is expanded).
  26. The alias is set up in such a way that the MMDF list processor channel is used.
  27. The three aliases that are created for each mailing list have this format:
  28.     listname:        listname-outbound@list-processor
  29.     listname-request:    list-owner
  30.     listname-outbound:    < included-filename
  31. Thus, for each mailing list, three items of information must be known: the
  32. mailing list name, the mailing list owner, and the name of the file to read
  33. when the list is expanded.  All three of these may be given explicitly, or
  34. may be derived from each other.
  35. After the alias entry has been built, it is appended to the appropriate alias
  36. table file and the MMDF dbm database is rebuilt.
  37.  
  38. $Usage
  39.      If <listfile> ends in a /, <listname> is appended to it.  This assumes
  40. that the file takes the same name as the list name.
  41.      If <listfile> does not begin with a /, <list-owner> is taken to be a user
  42. name, and the user's home directory is prepended to <listfile>.
  43.      If <list-owner> is not given, the owner is set to be the user whose home
  44. directory <listfile> is in.  In this case, <listfile> must begin with a '/'.
  45.      If <listname> is also not given (or is given as a '-'), the list name is
  46. set to be the final component of <listfile>.  In this case <listfile> must not
  47. end in a '/'.
  48.      <listfile> must exist at the time the mailing list is made.
  49. Options:
  50. -h: Print this help.
  51. -c: If the named mailing list file doesn't exist, create it, set the owner
  52.     of the file to the list owner, set the group to 'group', and set the
  53.     permissions appropriately.  If the list owner is not a local user, the
  54.     ownership of the file is set to the user under whose home directory it is
  55.     created.
  56. -a<alias-file>: Write aliases to <alias-file>.  If <alias-file> does not begin
  57.     with a '/', it is assumed to be relative to $aliasDir.  The default
  58.     alias file is $aliasDir/$defAliasFile.  This parameter may also be set
  59.     by assigning a value to ALIASFILE in the file $rcFile.
  60.     Example: ALIASFILE=list.ali
  61. -m: Create a majordomo mailing list.  If <listfile> contains no '/' characters,
  62.     it is assumed to reside in the directory ~majordom/Lists.  If the file does
  63.     not exist, it is created, the owner is set to majordom, the group is set to
  64.     majordom, and the mode is set to 664.
  65.     Three additional aliases are set up:
  66.     owner-listname:         list-owner
  67.     listname-approval:      list-owner
  68.     listname-error:         owner-listname
  69. -t: Tell what would be added to the alias file, without doing it."
  70.     exit 0
  71.     ;;
  72.     t)
  73.     Tell=true
  74.     ;;
  75.     a)
  76.     aliasFile=$OPTARG
  77.     ;;
  78.     c)
  79.     CreateFile=true
  80.     ;;
  81.     m)
  82.     majordomo=true
  83.     CreateFile=true
  84.     ;;
  85.     ?)
  86.     print -r -u2 "Use -h for help."
  87.     exit 1
  88.     ;;
  89.     esac
  90. done
  91.  
  92. # Find the user whose home directory the file/directory $1 is in, dealing with
  93. # nested home directories (ick).
  94. # The user name is returned in the global variable getHomeDirUser
  95. function getHomeDirUser {
  96.     # Assume the file is a dir; can't hurt
  97.     awk -v "path=$1/" '
  98. BEGIN {
  99.     mlen = 0
  100.     FS = ":"
  101. }
  102. {
  103.     homedir = $6 "/"
  104.     if (length(homedir) > mlen && index(path,homedir) == 1) {
  105.     user = $1
  106.     mlen = length(homedir)
  107.     }
  108. }
  109. END {
  110.     print user
  111. }
  112. ' /etc/passwd | read getHomeDirUser_ret
  113. }
  114.  
  115. # remove args that were options
  116. let OPTIND=OPTIND-1
  117. shift $OPTIND
  118.  
  119. if [ $# -lt 1 ]; then
  120.     print -r -u2 -- "$Usage
  121. Use -h for help."
  122.     exit 1
  123. fi
  124.  
  125. if [ $# -eq 0 -o $# -gt 3 ]; then
  126.     print -ru2 -- \
  127.     exit 1
  128. fi
  129.  
  130. if [ -z "$aliasFile" -a -f "$rcFile" -a -r "$rcFile" ]; then
  131.     . "$rcFile"
  132.     aliasFile=$ALIASFILE
  133. fi
  134. if [ -z "$aliasFile" ]; then
  135.     aliasFile=$defAliasFile
  136. fi
  137. [[ "$aliasFile" != /* ]] && aliasFile="$aliasDir/$aliasFile"
  138. if [ ! -w "$aliasFile" ]; then
  139.     print -ru2 -- "Cannot write to alias file $aliasFile"
  140.     exit 1
  141. fi
  142.  
  143. file=$1
  144. if [ $# -lt 2 -o "$2" = - ]; then
  145.     listname=${file##*/}
  146.     if [ -z "$listname" ]; then
  147.     print -ru2 \
  148.     "List filename ends in /, so <listname> must be given.  Use -h for help."
  149.     exit 1
  150.     fi
  151. else
  152.     listname=$2
  153. fi
  154. if [ $# -lt 3 ]; then
  155.     if [[ "$file" != /* ]]; then
  156.     print -ru2 \
  157.     "List filename must begin with / if <list-owner> is not given."
  158.     exit 1
  159.     fi
  160.     
  161.  
  162.     getHomeDirUser "$file"
  163.     listOwner=$getHomeDirUser_ret
  164.     if [ -z "$listOwner" -o "$listOwner" = root ]; then
  165.     print -ru2 \
  166. "List filename: $file
  167. is not in any user's home directory.  If the list is to be owned by root, root
  168. must be explicitly given on the command line."
  169.     exit 1
  170.     fi
  171. else
  172.     listOwner=$3
  173. fi
  174.  
  175. if [[ "$listname" != +([-a-zA-Z_0-9]) ]]; then
  176.     print -ru2 "$listname: Bad list name."
  177.     exit 1
  178. fi
  179.  
  180. if [[ "$(/usr/mmdf/bin/malias $listname)" != "no aliases "* ]]; then
  181.     print -ru2 "The mail name '$listname' is already in use.  Aborting."
  182.     exit 1
  183. fi
  184.  
  185. [[ "$file" = */ ]] && file="$file$listname"
  186. if [[ "$file" != /* ]]; then
  187.     if $majordomo; then
  188.     fileOwner=majordom
  189.     else
  190.     fileOwner=$listOwner
  191.     fi
  192.     OIFS=$IFS
  193.     IFS=:
  194.     egrep "^$fileOwner:" /etc/passwd 2>/dev/null |
  195.     read u p uid gid name homeDir shell
  196.     if [ -z "$homeDir" ]; then
  197.     if $majordomo; then
  198.         print -ru2 -- \
  199. "The user majordom does not exist.  A full path must be given
  200. for the list filename."
  201.     else
  202.         print -ru2 -- \
  203. "$listOwner is not a local user, so <listfile> must be given as a full path
  204. from the root directory.  Use -h for help."
  205.     fi
  206.     exit 1
  207.     fi
  208.     $majordomo && file="$homeDir/Lists/$file" || file="$homeDir/$file"
  209.     IFS=$OIFS
  210. fi
  211.  
  212. if [ -f "$file" ]; then
  213.     if $CreateFile; then
  214.     print -ru2 -- \
  215.     "Note: mailing list file already existed; not created: $file"
  216.     fi
  217. else
  218.     if $CreateFile; then
  219.     if $Tell; then
  220.         print -r "Would create mailing list file: $file"
  221.     else
  222.         touch "$file" || {
  223.         print -ru2 -- "Could not create mailing list file: $file"
  224.         exit 1
  225.         }
  226.     fi
  227.     if $majordomo; then
  228.         fileOwner=majordom
  229.         fileGroup=majordom
  230.         mode=664
  231.     else
  232.         if egrep "^$listOwner:" /etc/passwd >/dev/null; then
  233.         fileOwner=$listOwner
  234.         else
  235.         getHomeDirUser "$file"
  236.         fileOwner=$getHomeDirUser_ret
  237.         fi
  238.         mode=644
  239.         fileGroup=group
  240.     fi
  241.     if $Tell; then
  242.         print -r "Would chown file $file to $fileOwner"
  243.         print -r "Would chgrp file $file to $fileGroup"
  244.         print -r "Would chmod $mode file $file"
  245.     else
  246.         if chown "$fileOwner" "$file" &&
  247.         chgrp "$fileGroup" "$file" && chmod $mode "$file"; then
  248.         print -ru2 "Created mailing list file: $file"
  249.         else
  250.         print -ru2 "Could not chown/chmod new mailing list file: $file"
  251.         exit 1
  252.         fi
  253.     fi
  254.     else
  255.     print -ru2 -- \
  256. "No such file: $file.
  257. To automatically create files that do not already exist, use the -c option."
  258.     exit 1
  259.     fi
  260. fi
  261.  
  262. entry="
  263. $listname:        $listname-outbound@list-processor
  264. $listname-request:    $listOwner
  265. $listname-outbound:    < $file"
  266.  
  267. if $majordomo; then
  268.     entry="$entry
  269. owner-$listname:    $listOwner
  270. $listname-approval:    $listOwner
  271. $listname-error:    owner-$listname"
  272. fi
  273.  
  274. padEntry="$(print -r -- "$entry" | awk -vmax="$listname-outbound: " '
  275. # TabPad: pad S to TabLen tabwidths with tabs
  276. # TabInsPad: Replace the leftmost string of tabs in S with a string of tabs
  277. # such that the part of the string to the left of the tabs has been padded to
  278. # TabLen tabwidths.  If the string has no tabs, the entire string is taken to
  279. # be the part to the left of the tabs.  If the part of the string to the left
  280. # of the tabs is already long enough, a single tab is still added.
  281. function TabInsPad(S,TabLen,  left,right,tablen) {
  282.     pos = index(S,"\t")
  283.     if (!pos)
  284.     left = S
  285.     else {
  286.     left = substr(S,1,pos-1)
  287.     right = substr(S,pos+1)
  288.     }
  289.     sub("\t+","",right)        # get rid of prev. tabs
  290.     tabs = TabLen - int(length(left)/8)
  291.     if (tabs == 0)
  292.     tabs = 1
  293.     for (; tabs; tabs--)
  294.     left = left "\t"
  295.     return left right
  296. }
  297. BEGIN {
  298.     n = int((length(max)+7)/8)
  299. }
  300. {
  301.     print TabInsPad($0,n)
  302. }')"
  303.  
  304. if $Tell; then
  305.     print -r "Would append the following to alias file: $aliasFile
  306.     $padEntry"
  307.     exit 0
  308. else
  309.     print -r "Appending the following to alias file: $aliasFile
  310.     $padEntry"
  311. fi
  312.  
  313. print -r "$padEntry" >> $aliasFile &&
  314. cd /usr/mmdf/table &&
  315. su mmdf -c dbmbuild &&
  316. {
  317.     print ""
  318.     # file is no good until it has at least one address in it
  319.     [ -s "$file" ] && /usr/mmdf/bin/checkaddr -w "$listname-outbound"
  320. }
  321.