Never been to CodeSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

About this user

jvscode [[at]] fastmail [[dot]] fm

Sorting arrays in Bash


# get a sort command that will sort -print0 output (sort0 below)

#  requires Xcode on Mac OS X
open http://developer.apple.com/technology/Xcode.html

cd ~/Desktop

# Improved GNU sort (from textutils-1.22)
open http://attractivechaos.wordpress.com/2008/08/22/improved-gnu-sort-from-textutils-122/

curl -L -O http://www.freewebs.com/attractivechaos/sort-1.22a.tar.bz2

tar -xjf sort-1.22a.tar.bz2

cd sort-1.22a


# replace
#             int eolchar = '\n';
# with
#             int eolchar = '\0';

cat <<-'EOF' | sed -e 's/^ *//' -e 's/ *$//' | ed -s ~/Desktop/sort-1.22a/sort.c
   H
   /int eolchar = '\\n';/s/\\n/\\0/
   wq
EOF


make


alias sort0=~/Desktop/sort-1.22a/sort


ar1=('g h c' abc def 123)
ar2=('1 2 3' ABC ghc DEF)
ar3=('-x' '! & ?' $'a test\nsentence' $'another test\nsentence\n.' a64bitapp a32bitapp)

printf "%s\n" "${#ar1[@]}" "${#ar2[@]}" "${#ar3[@]}"  

printf "%s\000" "${ar1[@]}" | sort0 | tr '\0' '\n'
printf "%s\000" "${ar1[@]}" | sort0 | while read -d $'\0' item; do echo "index $[i++]:   ${item}"; done

printf "%s\000" "${ar2[@]}" | sort0 | while read -d $'\0' item; do echo "index $[i++]:   ${item}"; done

printf "%s\000" "${ar3[@]}" | sort0 | while read -d $'\0' item; do echo "index $[i++]:   ${item}"; done



# sort & uniq filename suffixes

# encode \n as \777 within the find command, then sort and finally decode \777 as \n again with the tr command
# (also an exercise in single quote usage)

man ruby | less -p 777
find . -type f -name '[^.]*.*' -exec bash -c 'basename=( "${@##*.}" ); printf "%s\n" "${basename[@]//''$'"'\n'"'''/''$'"'\777'"'''}"'  _ '{}' + | \
     sort -u | nl | tr $'\777' '\n'


# same, but using sort0

find . -type f -name '[^.]*.*' -exec bash -c 'printf "%s\000" "${@##*.}"' _ '{}' + | sort0 -u | tr '\0' '\n'

find . -type f -name '[^.]*.*' -exec bash -c 'printf "%s\000" "${@##*.}"' _ '{}' + | \
         sort0 -u | while read -d $'\0' suffix; do echo "$[i++]:   ${suffix}"; done



#----------------------------------------------------------------------------



export PATH="$(/usr/sbin/sysctl -n user.cs_path)"

export IFS=$'\n'
#export IFS=$' \t\n'

ar1=('g h c' abc def 123)
ar2=('1 2 3' ABC ghc DEF)
ar3=('-x' '! & ?' $'a test\nsentence' $'another test\nsentence\n.' a64bitapp a32bitapp)

printf "%s\n" "${#ar1[@]}" "${#ar2[@]}" "${#ar3[@]}"  


# ar3
for ((i=0; i < "${#ar3[@]}"; i++)); do echo "${ar3[$i]}"; done | sort | nl
for ((i=0; i < "${#ar3[@]}"; i++)); do echo ${ar3[$i]}; done | sort | nl
for ((i=0; i < "${#ar3[@]}"; i++)); do echo "${ar3[$i]}" | ruby -0777 -n -e 'p $_.to_s'; done | nl
for ((i=0; i < "${#ar3[@]}"; i++)); do printf -- "${ar3[$i]}\n" | ruby -0777 -n -e 'p $_.to_s'; done | nl


# sort a single array
ar3sorted=( $(for ((i=0; i < "${#ar3[@]}"; i++)); do echo ${ar3[$i]}; done | sort) )
for ((i=0; i < "${#ar3sorted[@]}"; i++)); do echo "${ar3sorted[$i]}" | ruby -0777 -n -e 'p $_.to_s'; done | nl
for ((i=0; i < "${#ar3sorted[@]}"; i++)); do printf "%s\n" "${ar3sorted[$i]}" | ruby -0777 -n -e 'p $_.to_s'; done | nl


# adding \000\n as array item delimiter
printf "%s\000\n" "${ar3[@]}"  | sed -n -e 'l'
printf "%s\000\n" "${ar3[@]}"  | ruby -n -e 'p $_.to_s'
printf "%s\000\n" "${ar3[@]}"  | ruby -0777 -n -e 'p $_.to_s'
printf "%s\000\n" "${ar3[@]}" | sed -e :a -e '$!N; s/\n/NEWLINE/g; ta' | ruby -n -e 'p $_.to_s'
printf "%s\000\n" "${ar3[@]}" | sed -e :a -e '$!N; s/\n/NEWLINE/g; ta' | tr '\000' '\n' | sed -e 's/^NEWLINE//' | ruby -n -e 'p $_.to_s'


ar3sorted=( $(printf "%s\000\n" "${ar3[@]}" | sed -e :a -e '$!N; s/\n/NEWLINE/g; ta' | tr '\000' '\n' | sed -e 's/^NEWLINE//' | sort) )
for ((i=0; i < "${#ar3sorted[@]}"; i++)); do printf -- "${ar3sorted[$i]//NEWLINE/\n}" | ruby -0777 -n -e 'p $_.to_s'; done | nl


# sort multiple arrays; convert embedded newline characters into single spaces
ar4=( $(printf "%s\n\000" "${ar1[@]}" "${ar2[@]}" "${ar3[@]}" | tr '\n' ' ' | tr '\000' '\n' | sort) )

# sort multiple arrays; preserve embedded newline characters as NEWLINE
ar4=( $(printf "%s\000\n" "${ar1[@]}" "${ar2[@]}" "${ar3[@]}" | sed -e :a -e '$!N; s/\n/NEWLINE/g; ta' | tr '\000' '\n' | sed -e 's/^NEWLINE//' | sort) )


printf "%s\n" "${#ar4[@]}"  
printf "%s\n" "${ar4[@]}" | nl  

for ((i=0; i < "${#ar4[@]}"; i++)); do echo ${ar4[$i]//NEWLINE/\\n}; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do echo -e ${ar4[$i]//NEWLINE/\\n}; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do printf -- ${ar4[$i]//NEWLINE/\\n}"\n"; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do printf -- "${ar4[$i]//NEWLINE/\n}\n"; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do printf "%s\n" ${ar4[$i]//NEWLINE/\\n}; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do printf -- "${ar4[$i]//NEWLINE/\n}\n" | ruby -0777 -n -e 'p $_.to_s'; done | nl
for ((i=0; i < "${#ar4[@]}"; i++)); do printf "%s\n" "${ar4[$i]//NEWLINE/\n}" | ruby -0777 -n -e 'p $_.to_s'; done | nl

Switch to the login window from the command line

# cf. http://www.mactipper.com/2008/07/securely-lock-your-mac-system.html,
# http://www.macosxhints.com/article.php?story=20040724203315798 and
# http://www.apple.com/downloads/macosx/automator/lockdesktop.html

/System/Library/CoreServices/"Menu Extras"/User.menu/Contents/Resources/CGSession -suspend

/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID username


alias lo='/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend'

# <ctrl> + l
help bind
bind -P | grep -i c-l
bind -x '"\C-l"':'/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend'

# <esc> + l
#bind -x '"\M-l"':'/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend'
bind -x '"\el"':'/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend'


#---------------------------------------------


open -a 'Keychain Access'

# go to  Keychain Access > Preferences ... > General > activate "Show Status in Menu Bar" 
# now you can use "Lock Screen" via the Keychain Access menu bar item

Password request dialog from the command line with AppleScript

unset -v input

#input="$(/usr/bin/osascript <<-'__HEREDOC__'
input="$(/usr/bin/osascript 2>/dev/null <<-'__HEREDOC__'
   with timeout of 300 seconds
      tell application "Finder"
--      tell application "System Events"
         activate
         set Input to display dialog "Please enter your password:" \
            with title "Password" \
            with icon caution \
            default answer "" \
            buttons {"Cancel", "OK"} \
            default button 2 \
            with hidden answer \
            giving up after 295
         return text returned of Input as string
      end tell
   end timeout
__HEREDOC__
)"

printf "%s\n" "${input}"


open -a 'Script Editor'

# copy & paste the following snippet into Script Editor 

with timeout of 300 seconds
	tell application "Finder"
		activate
		set Input to display dialog "Please enter your password:" with title "Password" with icon caution default answer "" buttons {"Cancel", "OK"} default button 2 giving up after 295 with hidden answer
		return text returned of Input as string
	end tell
end timeout


#---------------------------------------


unset -v input name
#export name="$(/usr/bin/logname)"
export name="$(/usr/bin/whoami)"

input="$(/usr/bin/osascript 2>/dev/null <<-__HEREDOC__
   with timeout of 300 seconds
      tell application "Finder"
--      tell application "System Events"
         activate
         set my_name to "${name}"
         set my_pass to display dialog "Enter password for " & quoted form of my_name \
            with title "Login Window" \
            with icon note \
            default answer "" \
            buttons {"Cancel", "OK"} \
            default button 2 \
            with hidden answer \
            giving up after 295
            return text returned of my_pass as string
      end tell
   end timeout
__HEREDOC__
)"


printf "%s\n" "${input}"

mycmds

help set
set -xv

#echo $-
#shopt -u
#shopt -s
#shopt -s | grep expand_aliases
#shopt -q expand_aliases; echo $?
#help shopt
#shopt -p
#shopt -s expand_aliases   

unalias mycmds1 mycmds2 mycmds3  2>/dev/null
alias mycmds1="declare -F | /usr/bin/awk '{print \$NF}' | /usr/bin/sort"
alias mycmds2="declare -F | /usr/bin/awk '{print $NF}' | /usr/bin/sort"
alias mycmds3='declare -F | /usr/bin/awk "{print $NF}" | /usr/bin/sort'

mycmds1
mycmds2
mycmds3


alias mycmds="alias -p | /usr/bin/awk -F= '{print \$1}' | /usr/bin/sort; \
              declare -F | /usr/bin/awk '{print \$NF }' | /usr/bin/sort"

mycmds

ANSI terminal color chart

1.
#!/bin/bash
#
#   This file echoes a bunch of color codes to the 
#   terminal to demonstrate what's available.  Each 
#   line is the color code of one forground color,
#   out of 17 (default + 16 escapes), followed by a 
#   test use of that color on all nine background 
#   colors (default + 8 escapes).
#
#   Author: Giles Orr
#   URL: http://gilesorr.com/bashprompt/howto/c350.html
#   License: GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation;
#            http://gilesorr.com/bashprompt/howto/a1004.html


T='gYw'   # The test text

echo -e "\n                 40m     41m     42m     43m\
     44m     45m     46m     47m";

for FGs in '    m' '   1m' '  30m' '1;30m' '  31m' '1;31m' '  32m' \
           '1;32m' '  33m' '1;33m' '  34m' '1;34m' '  35m' '1;35m' \
           '  36m' '1;36m' '  37m' '1;37m';
  do FG=${FGs// /}
  echo -en " $FGs \033[$FG  $T  "
  for BG in 40m 41m 42m 43m 44m 45m 46m 47m;
    do echo -en "$EINS \033[$FG\033[$BG  $T  \033[0m";
  done
  echo;
done
echo

2.
#!/bin/sh
#
#  colors v1.03
#
#  A simple shell script to output an ANSI terminal color chart.
#  It may be useful when trying to customize your ANSI terminal
#  color scheme!
#
#  Written and placed in the public domain by Ian Abbott <ian@abbott.org>
#
#  ANSI terminal color chart generator
#  Author: Ian Abbott
#  License: BSD License, http://www.opensource.org/licenses/bsd-license.php
#  URL: http://www.snippetcenter.org/de/ansi-terminal-color-chart-generator-s1346.aspx

for h in 0 1; do
  echo -e "\\033[0;${h}m\\c"
  case $h in
  0) echo -e "Normal\\c" ;;
  1) echo -e "High\\c" ;;
  esac
  echo -e " intensity foreground (background color in parentheses)\\033[m"
  for f in 0 1 2 3 4 5 6 7; do
    for b in 0 1 2 3 4 5 6 7 8; do
      echo -e "\\033[${h};3${f}\\c"
      if [ $b -lt 8 ]; then
        echo -e ";4${b}m\\c"
      else
        echo -e "m\\c"
      fi
      case $f in
      0) echo -e " BLACK \\c" ;;
      1) echo -e "  RED  \\c" ;;
      2) echo -e " GREEN \\c" ;;
      3) echo -e " YELLOW\\c" ;;
      4) echo -e "  BLUE \\c" ;;
      5) echo -e "MAGENTA\\c" ;;
      6) echo -e "  CYAN \\c" ;;
      7) echo -e " WHITE \\c" ;;
      esac
      case $b in
      8) echo -e "\\033[m" ;;
      *) echo -e " \\033[m \\c" ;;
      esac
    done
  done
  echo -e "\\033[${h}m\\c"
  for b in 0 1 2 3 4 5 6 7 8; do
    case $b in
    0) echo -e "(black)  \\c" ;;
    1) echo -e " (red)   \\c" ;;
    2) echo -e "(green)  \\c" ;;
    3) echo -e "(yellow) \\c" ;;
    4) echo -e " (blue)  \\c" ;;
    5) echo -e "(magenta)\\c" ;;
    6) echo -e " (cyan)  \\c" ;;
    7) echo -e "(white)  \\c" ;;
    8) echo -e " (none)\\c" ;;
    esac
  done
  echo -e "\\033[m\\n"
done

Screensaver as desktop background

# cf. http://digg.com/apple/Top_15_Terminal_Commands_for_Hidden_Mac_OS_X_Settings

function sadb() {
# cf. /usr/bin/locate '*ScreenSaverEngine'
/usr/bin/screen -d -m /System/Library/Frameworks/ScreenSaver.framework/Resources/ScreenSaverEngine.app/Contents/MacOS/ScreenSaverEngine -background 
return 0
}

function sadb_stop() {
#/usr/bin/killall -d ScreenSaverEngine
#/usr/bin/killall -v ScreenSaverEngine
/usr/bin/killall -HUP ScreenSaverEngine
return 0
}

sadb
sleep 30
sadb_stop

Flushing routing tables on Mac OS X

# cf. http://ola-bini.blogspot.com/2008/05/faulty-routes-on-macos-x.html
/usr/bin/sudo /sbin/route flush

Using PlistBuddy to customize syslogd


# Inspired by: http://www.maciverse.com/the-case-of-the-slow-mac-and-how-to-fix-it.html

# cf. man syslog, man syslogd and http://developer.apple.com/documentation/Darwin/Reference/ManPages/man8/syslogd.8.html
/usr/bin/open -a Console   # system.log
/usr/bin/tail -n 50 /private/var/log/system.log

help declare
declare -x sudo=/usr/bin/sudo plistbuddy=/usr/libexec/PlistBuddy defaults=/usr/bin/defaults
/usr/bin/env | /usr/bin/grep -E 'sudo=|plistbuddy=|defaults='

# create a symbolic link (on Mac OS X 10.4)
help test
/usr/bin/locate PlistBuddy
if [[ ! -e /usr/libexec/PlistBuddy ]]; then $sudo /bin/ln -s "/Library/Receipts/AdditionalEssentials.pkg/Contents/Resources/PlistBuddy" /usr/libexec/PlistBuddy; fi

# make a backup
$sudo /bin/cp -p /System/Library/LaunchDaemons/com.apple.syslogd.plist /System/Library/LaunchDaemons/com.apple.syslogd.plist.orig

# cf. http://developer.apple.com/documentation/Darwin/Reference/ManPages/man8/PlistBuddy.8.html
$plistbuddy -h   

$plistbuddy -c Print /System/Library/LaunchDaemons/com.apple.syslogd.plist
$plistbuddy -c "Print :ProgramArguments" /System/Library/LaunchDaemons/com.apple.syslogd.plist

# compare
$defaults read /System/Library/LaunchDaemons/com.apple.syslogd
$defaults read /System/Library/LaunchDaemons/com.apple.syslogd ProgramArguments

$sudo /usr/bin/nano /System/Library/LaunchDaemons/com.apple.syslogd.plist

$sudo $plistbuddy -c "Delete :ProgramArguments" /System/Library/LaunchDaemons/com.apple.syslogd.plist
$sudo $plistbuddy -c "Add :ProgramArguments array" /System/Library/LaunchDaemons/com.apple.syslogd.plist
$sudo $plistbuddy -c "Add :ProgramArguments:0 string '/usr/sbin/syslogd'" /System/Library/LaunchDaemons/com.apple.syslogd.plist
$sudo $plistbuddy -c "Add :ProgramArguments:1 string '-c'" /System/Library/LaunchDaemons/com.apple.syslogd.plist
$sudo $plistbuddy -c "Add :ProgramArguments:2 integer 3" /System/Library/LaunchDaemons/com.apple.syslogd.plist

# Mac OS X 10.5
#$sudo $plistbuddy -c "Add :ProgramArguments:3 string '-a'" /System/Library/LaunchDaemons/com.apple.syslogd.plist
#$sudo $plistbuddy -c "Add :ProgramArguments:4 string '-db_max'" /System/Library/LaunchDaemons/com.apple.syslogd.plist
#$sudo $plistbuddy -c "Add :ProgramArguments:5 integer 5000000" /System/Library/LaunchDaemons/com.apple.syslogd.plist

$plistbuddy -c "Print :ProgramArguments" /System/Library/LaunchDaemons/com.apple.syslogd.plist
$defaults read /System/Library/LaunchDaemons/com.apple.syslogd ProgramArguments
$sudo /usr/bin/nano /System/Library/LaunchDaemons/com.apple.syslogd.plist

# reset com.apple.syslogd.plist
#if [[ -n $(/usr/bin/sw_vers -productVersion | /usr/bin/grep '^10.5') ]]; then exit; fi   # exit if on Mac OS X 10.5.x
$sudo /bin/rm -f /System/Library/LaunchDaemons/com.apple.syslogd.plist
$sudo /bin/cp -p /System/Library/LaunchDaemons/com.apple.syslogd.plist.orig /System/Library/LaunchDaemons/com.apple.syslogd.plist

$sudo /usr/bin/nano /System/Library/LaunchDaemons/com.apple.syslogd.plist

# restart syslogd
#$sudo /bin/launchctl unload -w /System/Library/LaunchDaemons/com.apple.syslogd.plist 2>/dev/null
#/bin/sleep 3
#$sudo /bin/launchctl load -w /System/Library/LaunchDaemons/com.apple.syslogd.plist 2>/dev/null
#$sudo /usr/bin/killall -HUP syslogd   # alternative

newfolder contextual menu item with Automator

Right-click on a folder in a Finder window and select Automator -> newfolder to create a "NewFolder".


open -a Automator

#--------------------------------------------------

Drag or add actions here to build your workflow:
Library: Finder -> Action: Get Selected Finder Items
Library: Automator -> Action: Run Shell Script
                                 - Shell: /bin/sh
                                 - Pass input: as arguments

current_dir="$@"
name_of_new_dir="NewFolder"

if [[ -d "${current_dir}" ]] && [[ -w "${current_dir}" ]]; then
   /bin/mkdir -p "${current_dir}${name_of_new_dir}"
fi

exit 0


# now save the newfolder Automator workflow as a contextual menu item
Automator -> File -> Save As Plug-in ... -> Save Plug-in As: newfolder -> Plug-in for: Finder -> Save

#--------------------------------------------------

open ~/Library/Workflows/Applications/Finder/newfolder.workflow

# now open your Home directory, right-click on a folder and select Automator -> newfolder to create a "NewFolder" 
open ~

Run ClamAV from a system service agent account

The following instructions on how to run ClamAV from a system service agent account (non-root) require an admin user account, a ClamAV setup as described here and the creation of a clamavadmin system service agent account as described here.

Use at your own risk!


First uncomment the following lines of code in the first script at http://textsnippets.com/posts/show/1405:

# create further subdirectories if necessary
...
#fi
#
#fi


Then save the file, start the script and enter the following:

You are going to create a system service agent account!

Enter first name: clamavadmin

Note: The last name is optional and defaults to "agent" if you just press <return>!
Enter last name: 

Note: The user shell is optional and defaults to "/usr/bin/false" if you just press <return>!
Enter user shell: /bin/bash

Note: The home directory is optional and defaults to "/private/var/empty" if you just press <return>!
Enter home directory: /private/var/clamavadmin

System service agent account:  clamavadmin  successfully created!



# test
dscl . -read /Users/clamavadmin
dscl . -read /Groups/clamavadmin
dscl . list /Groups GroupMembership
dscl . read /Groups/clamavadmin GroupMembership
dscl . -search /Groups GroupMembership clamavadmin
echo $(dscl . -search /Groups GroupMembership clamavadmin | awk '{print $1}' | tr '\n' ' ')
printf -- "$(dscl . -search /Groups GroupMembership clamavadmin | awk '{print $1}' | tr '\n' ' ')\n"

sudo ls -ld /private/var/clamavadmin
sudo ls -l /private/var/clamavadmin/log/clamd.log
sudo ls -ld /private/var/clamavadmin/tmp
#sudo ls -l /private/var/clamavadmin/tmp/clamd   # will be created later by man clamd
sudo find /private/var/clamavadmin \( -type f -or -type d -or -type s \) -print0 | xargs -0 sudo ls -ldG



# add clamavadmin to group admin and group $(logname)
# add $(logname) to group clamavadmin
sudo dscl . -append /Groups/admin GroupMembership clamavadmin
sudo dscl . -append /Groups/$(logname) GroupMembership clamavadmin
sudo dscl . -append /Groups/clamavadmin GroupMembership $(logname)

#sudo dscl . -delete /Groups/admin GroupMembership clamavadmin 
#sudo dscl . -delete /Groups/$(logname) GroupMembership clamavadmin  
#sudo dscl . -delete /Groups/clamavadmin GroupMembership $(logname)   

# cf. http://textsnippets.com/posts/show/1402
dirmodes ~/Documents/ClamAV/Downloads/QueueDirectory


# copy update_clamd_db.sh
sudo cp /usr/local/sbin/update_clamd_db.sh /private/var/clamavadmin/update_clamd_db.sh
sudo chown clamavadmin:clamavadmin /private/var/clamavadmin/update_clamd_db.sh
sudo chmod 0750 /private/var/clamavadmin/update_clamd_db.sh
ls -l /private/var/clamavadmin/update_clamd_db.sh

# then change the following line in sudo nano  /private/var/clamavadmin/update_clamd_db.sh
/opt/local/bin/freshclam -u root
# ... to read ...
/opt/local/bin/freshclam -u clamavadmin


# get an overview of your ClamAV file & folder permissions in /opt
sudo find /opt \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo ls -ldG

# set new ClamAV file & folder permissions
sudo find /opt  \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo chown clamavadmin:clamavadmin
sudo find /opt  \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo chmod 0750

# reset permissions
#sudo find /opt  \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo chown root:wheel  
#sudo find /opt  \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo chmod 0755


# test
sudo find /opt \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo ls -ldG
sudo find /opt -not -user clamavadmin \( -type f -or -type d \) -iregex ".*clam.*" -print0 | xargs -0 sudo ls -ldG


# then modify clamd.conf
sudo nano /opt/local/etc/clamd.conf

LogFileMaxSize 10M
LogTime yes
FixStaleSocket yes
TCPAddr 127.0.0.1
MaxConnectionQueueLength 30
MaxThreads 20
ExitOnOOM yes
ScanOLE2 yes  # Microsoft Office documents and .msi files
ScanPDF yes
ArchiveMaxFileSize 100M
ArchiveMaxCompressionRatio 0
#VirusEvent echo virus: %v >> /path/to/file.txt

DatabaseDirectory /opt/local/share/clamav    # hardcoded
#LogFile /private/var/log/clamd.log
#TemporaryDirectory /private/var/tmp
#DatabaseDirectory /opt/local/share/clamav
#LocalSocket /tmp/clamd

#DatabaseDirectory /private/var/clamavadmin/share/clamav
LogFile /private/var/clamavadmin/log/clamd.log
TemporaryDirectory /private/var/clamavadmin/tmp
LocalSocket /private/var/clamavadmin/tmp/clamd



# modify net.clamav.clamd.plist

sudo launchctl unload -w /Library/LaunchDaemons/net.clamav.clamd.plist 2>/dev/null
sudo cp -p /Library/LaunchDaemons/net.clamav.clamd.plist /Library/LaunchDaemons/net.clamav.clamd.root-wheel

sudo nano /Library/LaunchDaemons/net.clamav.clamd.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.$
<plist version="1.0">
<dict>
        <key>Disabled</key>
        <true/>
        <key>GroupName</key>
        <string>clamavadmin</string>
        <key>Label</key>
        <string>net.clamav.clamd</string>
        <key>ProgramArguments</key>
        <array>
                <string>/opt/local/sbin/clamd</string>
                <string>-c</string>
                <string>/opt/local/etc/clamd.conf</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>UserName</key>
        <string>clamavadmin</string>
</dict>

sudo launchctl load -w /Library/LaunchDaemons/net.clamav.clamd.plist 2>/dev/null



# modify net.clamav.update.clamd.db.plist

sudo launchctl unload -w /Library/LaunchDaemons/net.clamav.update.clamd.db.plist 2>/dev/null
sudo cp -p /Library/LaunchDaemons/net.clamav.update.clamd.db.plist /Library/LaunchDaemons/net.clamav.update.clamd.db.plist.root-wheel

sudo nano /Library/LaunchDaemons/net.clamav.update.clamd.db.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.$
<plist version="1.0">
<dict>
        <key>Disabled</key>
        <true/>
        <key>GroupName</key>
        <string>clamavadmin</string>
        <key>Label</key>
        <string>net.clamav.update.clamd.db</string>
        <key>ProgramArguments</key>
        <array>
                <string>/private/var/clamavadmin/update_clamd_db.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StartInterval</key>
        <integer>20000</integer>
        <key>UserName</key>
        <string>clamavadmin</string>
</dict>


sudo launchctl load -w /Library/LaunchDaemons/net.clamav.update.clamd.db.plist 2>/dev/null



# watch clamd.log in a second Terminal window
open /bin/bash
sudo tail -n 50 -f /private/var/clamavadmin/log/clamd.log


# now restart clamd
if [[ -e "/private/var/clamavadmin/tmp/clamd" ]]; then sudo /bin/rm -f "/private/var/clamavadmin/tmp/clamd" ; fi
sudo /opt/local/sbin/clamd -c /opt/local/etc/clamd.conf


# test
(sleep 3; echo PING; sleep 3; echo exit) | sudo telnet -u /private/var/clamavadmin/tmp/clamd
echo PING | /opt/local/bin/socat - /private/var/clamavadmin/tmp/clamd    # requires: sudo port install socat
sudo find /private/var/clamavadmin \( -type f -or -type d -or -type s \) -print0 | xargs -0 sudo ls -ldG   # /private/var/clamavadmin/tmp/clamd