On Error Resume Next
Const ADS_SCOPE_SUBTREE = 2
Set WshNetwork = WScript.CreateObject("WScript.Network")
set objOU = GetObject(LDAP://ou=localComputers,ou=SOME_OU,dc=domain,dc=local)
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
objCommand.CommandText = _"SELECT ADsPath FROM 'LDAP://dc=domain,dc=local' WHERE objectCategory='computer' " & _"AND Name='" & wshNetwork.ComputerName & "'"
'Wscript.Echo " " & wshNetwork.ComputerName
Set objRecordSet = objCommand.Execute objRecordSet.MoveFirst
Do Until objRecordSet.EOF
strADsPath = objRecordSet.Fields("ADsPath").Value objOU.MoveHere strADsPath, vbNullString
objRecordSet.MoveNext
Loop
In the void is virtue, and no evil. Wisdom has existance, principle has existance, the Way has existance, spirit is nothingness.
Image
Search This Blog
Saturday, February 02, 2013
Wednesday, January 02, 2013
Tehnium 08-09/1995 (romanian language) :)
Yes, there was a time when I was doing everything analog. Then it came a time when even my audio amplifiers where "Class D" and I designed way smarter digital security systems based on real microcontrollers (among many other things), but I will always remember with pleasure my first successful (as in "I sold more than 10" :) ) product:
Friday, December 07, 2012
Add all Domain Users to Local Administrators (French or English)
Option Explicit
Dim owShell, oWMI, colOperatingSystems, oOS, strComputer, strUser, strDomain, objLocalAdminGroup, sComputer, iOSLang, strAdmins
On Error Resume Next
Set oWShell = CreateObject("Wscript.Shell")
strComputer = oWShell.ExpandEnvironmentStrings("%computername%")
strDomain = oWShell.ExpandEnvironmentStrings("%userdomain%")
'strUser = strDomain & "\" & oWShell.ExpandEnvironmentStrings("%username%")
strUser = strDomain & "\Domain Users"
Set oWMI = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer _
& "\root\cimv2")
Set colOperatingSystems = oWMI.ExecQuery _
("Select * from Win32_OperatingSystem")
For Each oOS in colOperatingSystems
iOSLang = oOS.OSLanguage
Next
If iOSLang = "1033" Then
strAdmins = "/Administrators"
Else
strAdmins = "/Administrateurs"
End if
Set objLocalAdminGroup = GetObject("WinNT://" & strComputer & strAdmins)
objLocalAdminGroup.Add("WinNT://" & Chr(34) & strUser & Chr(34))
Set objLocalAdminGroup = Nothing
Dim owShell, oWMI, colOperatingSystems, oOS, strComputer, strUser, strDomain, objLocalAdminGroup, sComputer, iOSLang, strAdmins
On Error Resume Next
Set oWShell = CreateObject("Wscript.Shell")
strComputer = oWShell.ExpandEnvironmentStrings("%computername%")
strDomain = oWShell.ExpandEnvironmentStrings("%userdomain%")
'strUser = strDomain & "\" & oWShell.ExpandEnvironmentStrings("%username%")
strUser = strDomain & "\Domain Users"
Set oWMI = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer _
& "\root\cimv2")
Set colOperatingSystems = oWMI.ExecQuery _
("Select * from Win32_OperatingSystem")
For Each oOS in colOperatingSystems
iOSLang = oOS.OSLanguage
Next
If iOSLang = "1033" Then
strAdmins = "/Administrators"
Else
strAdmins = "/Administrateurs"
End if
Set objLocalAdminGroup = GetObject("WinNT://" & strComputer & strAdmins)
objLocalAdminGroup.Add("WinNT://" & Chr(34) & strUser & Chr(34))
Set objLocalAdminGroup = Nothing
Saturday, November 17, 2012
BES - enable http auth
Because the BlackBerry browser uses the BES server to render the pages, the default user for integrated authentication is always "besadmin" In order to allow the user to authentify itself, we must enable Authentication support on the MDS. Follow KB15642 on bb site or just For BlackBerry Enterprise Server 4.1: 1. In BlackBerry Manager, select <BlackBerry_Enterprise_Server_name>_MDS-CS_1. 2. Click Edit Properties. 3. In the Properties window, click HTTP. 4. Under Authentication set the Support HTTP Authentication to True. For BlackBerry Enterprise Server 5.0 1. Open the BlackBerry Administration Service. 2. Expand the BlackBerry Solution topology. 3. Expand the component view. 4. Select MDS connection service. 5. Select the http tab. 6. Set authentication support enabled to yes. 7. If you change this configuration, you will need to restart the BlackBerry MDS service in the Windows Services window. Configure the MDSLogin.conf file to include your domain name. This will populate the domain field for the BlackBerry smartphone user when they are prompted for credentials on their BlackBerry smartphone. Complete the following steps: 1.On the BlackBerry Enterprise Server, go to C:\Program Files\Research In Motion\BlackBerry Enterprise Server\MDS\Servers\servername\config. 2.Open the MDSLogin.conf file in a text editor. 3.Edit the MDS_Default section by replacing COMPANY.COM with your domain name. Note: If the domain name starts with a number, surround the domain name with quotes ("") 4.If you wish to force a particular authentication type you can change the relevant optional entry to required. Save and close the file. C. Configure the krb5.conf file to include details relevant to your specific Microsoft Active Directory environment as follows: On the BlackBerry Enterprise Server navigate to C:\Program Files\Research In Motion\BlackBerry Enterprise Server\MDS\Servers\servername\config. 1.Open and edit the krb5.conf in a text editor. The default sections and entries contained within this file are as follows: [libdefaults] default_tkt_enctypes = des-cbc-md5 ; or des-cbc-crc default_tgs_enctypes = des-cbc-md5 ; or des-cbc-crc [realms] # change COMPANY.COM to your Kerberos realm # change KDC:88 to the hostname:port of KDC COMPANY.COM = { kdc = your_kdc.your_domain.com:88} 2.Replace the COMPANY.COM entry under the [realms] section with your domain name. Ensure this entry is in UPPER case. 3.Enter the Fully Qualified Domain Name (FQDN) of the KDC within your Microsoft Active Directory environment and port number (if changed from the default of 88). Ensure host names and domain names are in lower case. 4.Restart the BlackBerry MDS Connection Server service in Windows Services
Wednesday, October 17, 2012
Saturday, October 06, 2012
Remove weird characters from filenames
paste <(find . -print | awk '{print "\042"$0"\042"}') <(find . -print | sed -e 's/\o300/A/g' -e 's/\o301/A/g' -e 's/\o302/A/g' -e 's/\o340/a/g' -e 's/\o341/a/g' -e 's/\o342/a/g' -e 's/\o307/C/g' -e 's/\o347/c/g' -e 's/\o310/E/g' -e 's/\o311/E/g' -e 's/\o312/E/g' -e 's/\o350/e/g' -e 's/\o351/e/g' -e 's/\o352/e/g' -e 's/\o316/I/g' -e 's/\o356/i/g' -e 's/\o322/O/g' -e 's/\o323/O/g' -e 's/\o324/O/g' -e 's/\o362/o/g' -e 's/\o363/o/g' -e 's/\o364/o/g' -e 's/\o331/N/g' -e 's/\o361/n/g' -e 's/\o331/U/g' -e 's/\o332/U/g' -e 's/\o333/U/g' -e 's/\o371/u/g' -e 's/\o372/u/g' -e 's/\o373/u/g' -e 's/\o357/i/g' -e 's/\o317/I/g' -e 's/\o264/_/g' -e 's/\o250/_/g' -e 's/[)(]/-/g' -e 's/^\(.*\)$/"\1"/') | sed -e 's/^/mv /'
pretty neat, heh?
I'm using awk when I define the source because sed -e 's/.*/"&"/' or 's/^\(.*\)$/"\1"/' fails in the weird characters.
And while being there, find . -type f -regextype posix-extended ! -iregex '.*.(mp3|avi|mkv|wmv|mp4|mp5|flv|M4V|mpeg|mov|m1v|m2v|3gp|avchd)$' -delete will nicely clean up the music folders :)
the characters definitions are found in /usr/share/X11/locale/iso8859-1/Compose
Monday, September 17, 2012
Clear Win7 UserProfile
' Clear Win7/Win2008 User Profile and registry
' to be executed on each Terminal Server
'(c)2012-2014 sorinakis@gmail
Set WshShell = CreateObject("WScript.Shell")
Set WshNet = WScript.CreateObject("WScript.Network")
Set WMIService = GetObject("winmgmts:\\.\root\cimv2")
Set objRegistry = GetObject("winmgmts:\\.\root\default:StdRegProv")
set WshFSO = CreateObject("Scripting.FileSystemObject")
const HKEY_LOCAL_MACHINE = &H80000002
dim strUser
Do
strUser = InputBox(vbCrLf & "Please enter the username you wish to reset: ", "Profile Cleaner")
If TypeName(strUser) = "Empty" Then
WScript.Quit
End If
If Len(Trim(strUser)) = 0 Then
MsgBox "You have to Enter Username To Reset",48
End If
Loop While Len(Trim(strUser)) = 0
'' debug
'with createobject("wscript.shell")
'.popup "User: " & strUser , 5 , "Info"
'end with
'' end debug
if CStr(CheckUser(strUser)) then
Set Account = WMIService.Get("Win32_UserAccount.Name='" & strUser & "',Domain='" & WshNet.UserDomain & "'")
strRegKey = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\" + Account.SID
if CheckRegKey(strRegKey) then
strUserProfile = WshShell.ExpandEnvironmentStrings(WshShell.RegRead("HKEY_LOCAL_MACHINE\" + strRegKey + "\ProfileImagePath"))
strRmtFldr = WshShell.ExpandEnvironmentStrings(WshShell.RegRead("HKEY_LOCAL_MACHINE\" + strRegKey + "\CentralProfile"))
Else
MsgBox " The registry key for user " & strUser & " does not exist! Can NOT backup and clean anything!" & vbCrLf & vbCrLf & "Please manually check for and rename the USERPROFILE and ROAMINGPROFILE Folders.",16
wscript.quit
End If
strRegFile = strUserProfile & "\reg_backup.reg"
regCmd = "regedit.exe /E """ & strRegFile & """ " & """HKEY_LOCAL_MACHINE\" & strregKey & """"
If WshFSO.FolderExists (strUserProfile) Then
'' debug
'with createobject("wscript.shell")
'.popup "Backup: " & strUserProfile , 5 , "Info"
'end with
'' end debug
WshShell.Run regCmd, 0, True
WshFSO.MoveFolder strUserProfile , strUserProfile & ".backup"
End If
If WshFSO.FolderExists (strRmtFldr) Then
'' debug
'with createobject("wscript.shell")
'.popup "Backup: " & strRmtFldr , 5 , "Info"
'end with
'' end debug
WshFSO.MoveFolder strRmtFldr , strRmtFldr & ".backup"
End If
'' debug
'with createobject("wscript.shell")
'.popup "Removing: HKEY_LOCAL_MACHINE\" & strRegKey , 5 , "Info"
'end with
'' end debug
DeleteSubkeys HKEY_LOCAL_MACHINE, strRegKey
Sub DeleteSubkeys(HKEY_LOCAL_MACHINE, strRegKey)
objRegistry.EnumKey HKEY_LOCAL_MACHINE, strRegKey, arrSubkeys
If IsArray(arrSubkeys) Then
For Each strSubkey In arrSubkeys
DeleteSubkeys HKEY_LOCAL_MACHINE, strRegKey & "\" & strSubkey
Next
End If
objRegistry.DeleteKey HKEY_LOCAL_MACHINE, strRegKey
End Sub
' Open the backed up profile it in explorer...
'strPath = "explorer.exe /e, strRmtFldr" & ".backup"
'WshShell.Run strPath
'debug
with createobject("wscript.shell")
.popup "Profile of " & strUser & " has been processed.", 5 , "Info"
end with
'' end debug
wscript.quit
Else
MsgBox "USER " & strUser & " NOT FOUND!", 16
wscript.quit
End If
Function CheckRegKey(strRegKey)
On Error Resume next
strUserProfile = WshShell.ExpandEnvironmentStrings(WshShell.RegRead("HKEY_LOCAL_MACHINE\" + strRegKey + "\ProfileImagePath"))
If Err.Number <> 0 Then
Err.Clear
CheckRegKey = false
else
Err.Clear
CheckRegKey = true
End If
end function
Function CheckUser(user)
On Error Resume next
with CreateObject("WScript.Shell")
Set Account = WMIService.Get("Win32_UserAccount.Name='" & User & "',Domain='" & WshNet.UserDomain & "'")
end with
CheckUser = (Err.Number = 0)
On Error Goto 0
end function
' to be executed on each Terminal Server
'(c)2012-2014 sorinakis@gmail
Set WshShell = CreateObject("WScript.Shell")
Set WshNet = WScript.CreateObject("WScript.Network")
Set WMIService = GetObject("winmgmts:\\.\root\cimv2")
Set objRegistry = GetObject("winmgmts:\\.\root\default:StdRegProv")
set WshFSO = CreateObject("Scripting.FileSystemObject")
const HKEY_LOCAL_MACHINE = &H80000002
dim strUser
Do
strUser = InputBox(vbCrLf & "Please enter the username you wish to reset: ", "Profile Cleaner")
If TypeName(strUser) = "Empty" Then
WScript.Quit
End If
If Len(Trim(strUser)) = 0 Then
MsgBox "You have to Enter Username To Reset",48
End If
Loop While Len(Trim(strUser)) = 0
'' debug
'with createobject("wscript.shell")
'.popup "User: " & strUser , 5 , "Info"
'end with
'' end debug
if CStr(CheckUser(strUser)) then
Set Account = WMIService.Get("Win32_UserAccount.Name='" & strUser & "',Domain='" & WshNet.UserDomain & "'")
strRegKey = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\" + Account.SID
if CheckRegKey(strRegKey) then
strUserProfile = WshShell.ExpandEnvironmentStrings(WshShell.RegRead("HKEY_LOCAL_MACHINE\" + strRegKey + "\ProfileImagePath"))
strRmtFldr = WshShell.ExpandEnvironmentStrings(WshShell.RegRead("HKEY_LOCAL_MACHINE\" + strRegKey + "\CentralProfile"))
Else
MsgBox " The registry key for user " & strUser & " does not exist! Can NOT backup and clean anything!" & vbCrLf & vbCrLf & "Please manually check for and rename the USERPROFILE and ROAMINGPROFILE Folders.",16
wscript.quit
End If
strRegFile = strUserProfile & "\reg_backup.reg"
regCmd = "regedit.exe /E """ & strRegFile & """ " & """HKEY_LOCAL_MACHINE\" & strregKey & """"
If WshFSO.FolderExists (strUserProfile) Then
'' debug
'with createobject("wscript.shell")
'.popup "Backup: " & strUserProfile , 5 , "Info"
'end with
'' end debug
WshShell.Run regCmd, 0, True
WshFSO.MoveFolder strUserProfile , strUserProfile & ".backup"
End If
If WshFSO.FolderExists (strRmtFldr) Then
'' debug
'with createobject("wscript.shell")
'.popup "Backup: " & strRmtFldr , 5 , "Info"
'end with
'' end debug
WshFSO.MoveFolder strRmtFldr , strRmtFldr & ".backup"
End If
'' debug
'with createobject("wscript.shell")
'.popup "Removing: HKEY_LOCAL_MACHINE\" & strRegKey , 5 , "Info"
'end with
'' end debug
DeleteSubkeys HKEY_LOCAL_MACHINE, strRegKey
Sub DeleteSubkeys(HKEY_LOCAL_MACHINE, strRegKey)
objRegistry.EnumKey HKEY_LOCAL_MACHINE, strRegKey, arrSubkeys
If IsArray(arrSubkeys) Then
For Each strSubkey In arrSubkeys
DeleteSubkeys HKEY_LOCAL_MACHINE, strRegKey & "\" & strSubkey
Next
End If
objRegistry.DeleteKey HKEY_LOCAL_MACHINE, strRegKey
End Sub
' Open the backed up profile it in explorer...
'strPath = "explorer.exe /e, strRmtFldr" & ".backup"
'WshShell.Run strPath
'debug
with createobject("wscript.shell")
.popup "Profile of " & strUser & " has been processed.", 5 , "Info"
end with
'' end debug
wscript.quit
Else
MsgBox "USER " & strUser & " NOT FOUND!", 16
wscript.quit
End If
Function CheckRegKey(strRegKey)
On Error Resume next
strUserProfile = WshShell.ExpandEnvironmentStrings(WshShell.RegRead("HKEY_LOCAL_MACHINE\" + strRegKey + "\ProfileImagePath"))
If Err.Number <> 0 Then
Err.Clear
CheckRegKey = false
else
Err.Clear
CheckRegKey = true
End If
end function
Function CheckUser(user)
On Error Resume next
with CreateObject("WScript.Shell")
Set Account = WMIService.Get("Win32_UserAccount.Name='" & User & "',Domain='" & WshNet.UserDomain & "'")
end with
CheckUser = (Err.Number = 0)
On Error Goto 0
end function
Friday, April 06, 2012
Cyclic paging script
Let's say that we have an emergency voicemail box where our clients can leave us messages if they have a contract for extended hours or a limited response time contract. Let's also suppose that we have a shitty mobile phone provider, whose signal does no goes higher that 3000ft and is not available too far in wilderness, but we still have those old pagers, able to receive the signal even on top of mount Everest. And let's say that we have a bunch of unfortunate enough bastards on call that are supposed to respond to those calls. Now, every week it's some other poor bastard turn to be on call, but just in case he's not available, we might be force to page the other unfortunates, even when it is not their week of duty. And we page them in order, one after another, until one of them login the web interface of our asterisk server or call the emergency mailbox and acknowledge the message.
This is the script that have to be run from cron every */10 minutes on the asterisk server:
#!/bin/bash
# A script that checks for new messages on emergency voicemail and send messages to pagers
# (c) 2012 sorin@xxxxxxxx.com under the terms of GNU GPL
#
# 2012/06/23 v0.5 neXt (sorin@xxxxxxxx.com) - Add names to email
# 2012/06/09 v0.4 neXt (sorin@xxxxxxxx.com) - Don't send pages during the night
# 2012/05/10 v0.3 neXt (sorin@xxxxxxxx.com) - Monday morning warn the user on duty
# 2012/04/09 v0.2 neXt (sorin@xxxxxxxx.com) - Verify if the cycle has been done today
# 2012/04/06 v0.1 neXt (sorin@xxxxxxxx.com) - Initial release
# Voicemail location
voicemail=/var/spool/asterisk/voicemail/default/911/INBOX/
# Paging provider
provider=paging.xxxxxxxx.com
# Working directory
working=/var/emergency
if [ ! -d $working ] ; then
mkdir -p $working
fi
# Location of the file containing the pager numbers
pagers=$working/pager_numbers
if [ ! -f $pagers ] ; then
# If the pager file does not exist define the defaults - We need a NEW-LINE at the end of the file!
echo "5140000000 John Doe john@xxxxxxxx.com
5140000001 Jane Doe jane@xxxxxxxx.com
5140000002 Jack Doe jack@xxxxxxxx.com
" > $pagers
fi
# A temporary file containing a volatile data
runvars=$working/tmpvars
if [ ! -f $runvars ] ; then
# If the variables file does not exist define some sane defaults
echo "current=1" > $runvars
echo "oldday=0" > $runvars
fi
# Cycle pager numbers every Monday, the first number will become the last
today=`date +%w`
day=`date +%d%m`
# read the variables
. $runvars 1>&2>/dev/null
# If today is Monday (weekday 1) and the numbers were not already cycled
if [ $today = 1 ] && [ ! $day = $oldday ]; then
# copy pager numbers to a new file, deleting the first line of this file
sed -n "2,\$ p;/^ *$/d" $pagers > $pagers.new
# read the first line of the old file and put that line at the end of the new file
head -1 $pagers >> $pagers.new
# replace the old file with the new one
mv -f $pagers.new $pagers
# send an email with the name and number of the current guy on duty
guy=`head -n1 $pagers | tail -n1
recipients=`cat $pagers | sed 's/[^@]* \([a-zA-Z0-9.]*@[^ ]*\).*/\1/' | sed ':a;N;$!ba;s/\n/ /g'`
echo "This week the main pager is $guy" | mail -s "Pager $guy" $recipients
# page this new guy with a test message, but not in the middle of the night, 07:30AM seems like OK-ish...
guynr=`echo "$guy" | cut -f1 -d" "`
wrn="echo '00 10-86 00' | mail -s911 $guynr@$provider"
echo $wrn | at 07:30
# keep the today's date into variable oldday - used to see if we've already processed the cycle today
sed -i "/oldday/d" $runvars
echo "oldday=$day" >> $runvars
fi
# We DO NOT send paging messages between 10PM and 7AM - there are no contracts between those hours
if [ $((10#$(date +%H%M))) -gt 700 ] && [ $((10#$(date +%H%M))) -lt 2200 ]; then
# Let's see if there are new messages in the emergency voicemail
messages=`ls -l $voicemail | wc -l`
if [ $messages -gt 1 ]; then
# There is something in the voicemail, read the already defined variables to see to whom we have to send the page
. $runvars 1>&2>/dev/null
# If we are aleady at the end of the paging list, we have to restart from the beginning and annoy everybody again
max_current=`wc -l $pagers | cut -f1 -d" "`
if [ $current -gt $max_current ]; then
current=1
fi
# Hell, let's send a page to the sucker that is on duty today. Extract only the phone number from file.
current_page=`head -n$current $pagers | tail -n1 | cut -f1 -d" "`
# echo "msg=$messages max=$max_current cn=$current cur=$current_page" # This line is here for debugging
echo "10-78 911" | mail -s911 $current_page@$provider
# Now remember, we've already sent a page to this unfortunate, if he's not available, we'll have to move to the next in line
current=`expr $current + 1`
sed -i "/current/d" $runvars
echo "current=$current" >> $runvars
else
# Cleanup the variables, some poor bastard took the message, we reset the counter
sed -i "/current/d" $runvars
echo "current=1" >> $runvars
fi
fi
---------------------------------------------------------------------------------------------
Note: This is work in progress. I'll update changes during time.
Sunday, November 06, 2011
IP Changing notification
Because sometimes the dyndns updater goes to hell, a little crontab script executed every couple of hours it's a life saver:
#!/bin/sh
#
# Send an email message to notify about the external IP.
#
#set a file where we can store the ip
logfile=/var/log/extip
#to whom we send the email
recipient="my_account@provider.tld"
#if we are using an external smtp relay
smtp=relay.smtp.provider.tld
export smtp=$smtp
#put a nice sender address on the email
sender="IP Checker<ipcheck@server.tld>"
#find the name of of this server
HOSTNAME=`hostname -a | cut -f1 -d" "`
# format a nice subject
subj="Change of IP on $HOSTNAME"
#now let's get the external ip
ip=`/usr/bin/lynx -dump 'http://whatismyip.org'`
#and create a message body
mesg="$HOSTNAME IP address on `date +%a' '%b' '%e' '%H.%M.%S' '%Z' '%Y` is $ip"
#see if the ip has changed
oldip=`cat $logfile`
#or if the last message has been sent more than one week ago
age=`find $logfile -mtime +7`
if [ ! "$oldip" == "$ip" ] || [ ! "$age" == "" ]
then
#keep the new ip into the logfile
echo $ip > $logfile
#send email about it
echo "$mesg" | mail -r"$sender" -s"$subj" "$recipient"
fi
exit 0
Of course, having an external web server, capable of running a little php script will allow us to replace http://whatismyip.org with our own webserver. The php script is really simple:
#!/bin/sh
#
# Send an email message to notify about the external IP.
#
#set a file where we can store the ip
logfile=/var/log/extip
#to whom we send the email
recipient="my_account@provider.tld"
#if we are using an external smtp relay
smtp=relay.smtp.provider.tld
export smtp=$smtp
#put a nice sender address on the email
sender="IP Checker
#find the name of of this server
HOSTNAME=`hostname -a | cut -f1 -d" "`
# format a nice subject
subj="Change of IP on $HOSTNAME"
#now let's get the external ip
ip=`/usr/bin/lynx -dump 'http://whatismyip.org'`
#and create a message body
mesg="$HOSTNAME IP address on `date +%a' '%b' '%e' '%H.%M.%S' '%Z' '%Y` is $ip"
#see if the ip has changed
oldip=`cat $logfile`
#or if the last message has been sent more than one week ago
age=`find $logfile -mtime +7`
if [ ! "$oldip" == "$ip" ] || [ ! "$age" == "" ]
then
#keep the new ip into the logfile
echo $ip > $logfile
#send email about it
echo "$mesg" | mail -r"$sender" -s"$subj" "$recipient"
fi
exit 0
Of course, having an external web server, capable of running a little php script will allow us to replace http://whatismyip.org with our own webserver. The php script is really simple:
<?php
$ip = getenv('REMOTE_ADDR');
#$ip = $_SERVER['REMOTE_ADDR'];
echo '
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
' . $ip . '
</body>
</html>';
?>
Sunday, October 16, 2011
Sunday, August 07, 2011
AUTOTBACK 3.0
A new version of the backup utility.
This is an evolution of the old AUTOTBACK script.
If the script is called without any command-line parameters it will check if "dialog" is installed on the system and it will start the "semi-graphical" interface, otherwise it will display the "usage parameters" and it will exit.
The command line parameters are still the same:
$autotback ACTION DIRECTORY ARCHIVE MAIL PRINTER, where
- ACTION is backup or restore
- DIRECTORY represent, in case of ACTION=backup the source (what we will backup), or the destination (where the backup will be restored) when ACTION=restore. The default value is "/".
- ARCHIVE represent the location of backup. It is usually the tape device (by default is /dev/st0), but it can also be a simple file (/mnt/disk/archive_name.cpio - if we use an external drive mounted on /mnt/disk)
- MAIL represent the email address(es) that will receive the backup report. If more than one email address is required, then, on the command line, those must be surrounded by double quotes ("aa@bb.c dd@ee.f gg@hh.i"). The default emails are "backupreport@xxxxxxxx.com root@localhost"
-PRINTER represents the name of the printer used for the report. The default value is empty. The printer MUST be already installed on the system!
This is an evolution of the old AUTOTBACK script.
If the script is called without any command-line parameters it will check if "dialog" is installed on the system and it will start the "semi-graphical" interface, otherwise it will display the "usage parameters" and it will exit.
The command line parameters are still the same:
$autotback ACTION DIRECTORY ARCHIVE MAIL PRINTER, where
- ACTION is backup or restore
- DIRECTORY represent, in case of ACTION=backup the source (what we will backup), or the destination (where the backup will be restored) when ACTION=restore. The default value is "/".
- ARCHIVE represent the location of backup. It is usually the tape device (by default is /dev/st0), but it can also be a simple file (/mnt/disk/archive_name.cpio - if we use an external drive mounted on /mnt/disk)
- MAIL represent the email address(es) that will receive the backup report. If more than one email address is required, then, on the command line, those must be surrounded by double quotes ("aa@bb.c dd@ee.f gg@hh.i"). The default emails are "backupreport@xxxxxxxx.com root@localhost"
-PRINTER represents the name of the printer used for the report. The default value is empty. The printer MUST be already installed on the system!
#!/bin/sh # @(#) AUTOTBACK 3.4 08/09/12 # # 08/06/2012 (sorin@xxxxxxxx.com) add pre/post actions, embedd dialog # 17/10/2011 (sorin@xxxxxxxx.com) modify to use tar # 18/07/2011 (sorin@xxxxxxxx.com) add the restore section, add command-line parmeters # 10/08/2010 (sorin@xxxxxxxx.com) autoremove lock after 8hrs and reenable backup. remove hit report # 28/08/2008 (sorin@xxxxxxxx.com) modified for rhel5. skip /proc /sys /tmp. send mail with the result # modified 9/14/2000 to provide hit reporting on web site # # Usage: $0 backup /source /dev/destination email@notification.address (printer) # if no source nor destination is provided, / will be saved to /dev/st0 # $0 restore /destination /dev/source email@notification.address (printer) # when restore is called, the script will ask you to select a partial restore # by typing a file mask. Just type Enter to do a full restore. # if no destination is provided, the restore is performed on / from /dev/st0 # All the reports and temp files are kept in the /var/autotback directory # # # Exit Codes: 0 - OK # 1 - [ESC] pressed # 2 - A lockfile exists # 3 - Can't create dir (am I root? is it /var mounted rw?) # # # If not provided on the commandline, set local Variables. Must specify at least the main action (backup/restore) unset SRC DES REC PRN #if [ "$1" = "" ]; then echo "Usage: $0 {backup|restore} (files) (archive) (email) (printer)"; fi # if dialog exists start anyway if [ ! "$2" = "" ]; then SRC=$2; else SRC=/; fi if [ ! "$3" = "" ]; then DES=$3; else DES=/dev/st0; fi if [ ! "$4" = "" ]; then REC=$4; else REC="backupreport@xxxxxxxx.com root@localhost"; fi if [ ! "$5" = "" ]; then PRN=$5; fi # System variables #PRECOMMAND='/bin/mount -t cifs -o guest //192.168.1.16/images /mnt' #POSTCOMMAND='/bin/umount /mnt' ARCHIVER=tar DEFAULTDIR=/var/autotback LOCK=$DEFAULTDIR/backlock REPORTFILE=$DEFAULTDIR/backrep$$ TEMPFILE=$DEFAULTDIR/backtmp$$ TEMPFILE2=$DEFAULTDIR/backtemp$$ TEMPFILEV=$DEFAULTDIR/vertmp$$ TEMPFILEV2=$DEFAULTDIR/vertemp$$ LIST=$DEFAULTDIR/list$$ TITLE="AUTOTBACK 3.4" BACKTITLE="A dialog driven backup utility (press [ESC] twice to exit)" INTERRUPT="echo -en [ESC] Pressed, exiting... " HEADER="Backup Report for $HOSTNAME (c)1991-2012 xxxxxxxx Inc. =============================================================================== `date` " ######################### # Define main functions # ######################### ######## # lock # ######## lock () { # Check if another job is running if [ -r $LOCK ] then # if we have wall, announce the trouble if [ ! "$(whereis wall | cut -d: -f2)" = "" ]; then wall " We have a little issue with the BACKUP ! Please verify $DEFAULTDIR"; fi echo "`date` - Another job is running or the last backup did not finished well. Please check $DEFAULTDIR !" >> $REPORTFILE # check the age of the lockfile, if it is older then 23 hrs, chances are that nobody checked the log ((DIFF=`date +%s`-`cat $LOCK`)) if [ $DIFF -gt 82800 ]; then echo "`date` - Lockfile more than 23 hours old, autocleaning... the backup will run!" >> $REPORTFILE; rm -f $LOCK; fi if [ -r $LOCK ] then if [ ! "$(whereis mail | cut -d: -f2)" = "" ]; then cat $REPORTFILE | mail -s "$0 Warning from $HOSTNAME" $REC 2>/dev/null; fi if [ "$PRN" = "" ]; then echo "Skip print, no printer defined" >> $REPORTFILE; elif [ ! "$(whereis lp |cut -d: -f2)" = "" ]; then lp -d $PRN $REPORTFILE; fi exit 2 fi fi # Cleanup obsolete traces and create defaultdir rm -rf $DEFAULTDIR 2> /dev/null mkdir -p $DEFAULTDIR 2> /dev/null if [ ! -d $DEFAULTDIR ] ; then echo "CAN'T MAKE $DEFAULTDIR"; exit 3; fi touch $REPORTFILE $TEMPFILE $TEMPFILE2 $TEMPFILEV $TEMPFILEV2 $LIST # Create lockfile echo "`date +%s`">$LOCK } ################## # extract dialog # ################## extract_dialog () { # If dialog is not in path and the system is linux - !!! TBD - NOT USED IN v3.4 !!! if [ ! "`uname -a | grep Linux`" == "" ]; then echo "Dialog not found, Do you want to try to extract our own dialog? y/n" read extract if [ "$extract" = "y" ] || [ "$extract" = "Y" ]; then # Find the tar archive at the end of this script. It starts after the line "---DEMARK---" # It was added there with a simple 'cat binary.tar.bz2 >> $this_script' binstart=`expr $(grep --text --line-number '^---DEMARK---$' $0 | cut -f1 -d:) + 1` # Extract the tar archive on /tmp tail -n +$binstart $0 | tar -C/tmp -xjvf - fi fi } ##################### # graphic interface # ##################### void () { # Make the TERM display white on blue setterm -clear all -foreground white -background blue # Check if another job is running lock # present the user the choice of backup, resctore or scheduler dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel --menu "Choose an Option" 11 30 3 1 "Create a Backup" 2 "Restore from Backup" 3 "Schedule a Backup" 2>/tmp/input.$$ sel=$? choice=`cat /tmp/input.$$` rm -f /tmp/input.$$ case $sel in 0) if [ "$choice" = "1" ]; then #dialog choose what, where, to backup, to whom we send email, where we print (if we print) dialog --title "$TITLE (SPACE to select what to save)" --backtitle "$BACKTITLE" --nocancel \ --fselect "/" 12 46 2>/tmp/input.$$ sel=$? SRC=`cat /tmp/input.$$` rm -f /tmp/input.$$ case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --inputbox "Select the destination device" 8 25 /dev/st0 2>/tmp/input.$$ sel=$? DES=`cat /tmp/input.$$` rm -f /tmp/input.$$ case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --inputbox "Type the notification emails" 8 47 "backupreport@xxxxxxxx.com root@localhost" 2>/tmp/input.$$ sel=$? REC=`cat /tmp/input.$$` rm -f /tmp/input.$$ REC=\"$REC\" case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --inputbox "Type the Printer name (if any)" 8 25 2>/tmp/input.$$ sel=$? PRN=`cat /tmp/input.$$` rm -f /tmp/input.$$ case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --infobox "Performing the Backup procedure. Please wait..." 6 25 # call the backup function with the right command line options. Remove lock before rm -f $LOCK && backup fi if [ $choice = 2 ]; then ##dialog choose where to restore, from where, to whom we send email, where we print (if we print) dialog --title "$TITLE (SPACE to select where to save)" --backtitle "$BACKTITLE" --nocancel \ --fselect "/" 12 47 2>/tmp/input.$$ sel=$? SRC=`cat /tmp/input.$$` rm -f /tmp/input.$$ case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --inputbox "Select the source device" 8 25 /dev/st0 2>/tmp/input.$$ sel=$? DES=`cat /tmp/input.$$` rm -f /tmp/input.$$ case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --inputbox "Type the notification emails" 8 47 "backupreport@xxxxxxxx.com root@localhost" 2>/tmp/input.$$ sel=$? REC=`cat /tmp/input.$$` rm -f /tmp/input.$$ REC=\"$REC\" case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --inputbox "Type the Printer name (if any)" 8 25 2>/tmp/input.$$ sel=$? PRN=`cat /tmp/input.$$` rm -f /tmp/input.$$ case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --infobox "Performing the Restore procedure. Please wait..." 6 25 # call the restore function with the right command line options. remove lock before rm -f $LOCK && restore fi if [ $choice = 3 ]; then # before schedule a new backup, check is there is another one already programmed myname=`echo $0 | sed -e's/\.\///'` # Remove ./ from $0 if [ ! `crontab -l | grep -c $myname` = 0 ]; then dialog --title "$TITLE" --backtitle "$BACKTITLE" --yes-label "Keep" --no-label "Delete" --yesno "A backup is alredy scheduled, What do you want to do with it? \n `crontab -l | grep $myname`" 10 46 sel=$? case $sel in 0) # keep the old scheduled backups in crontab, nothing to do ;; 1) # delete old backup from crontab crontab -l | sed -e "/$myname/d" > /tmp/tmpcron.$$ /usr/bin/crontab < /tmp/tmpcron.$$ rm -f /tmp/tmpcron.$$ ;; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac fi ##start to schedule. choose days of week (MON-FRI preselected) dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel --checklist "Choose days of Backup (Use SPACE to select)" 18 26 12 0 Sunday off 1 Monday on 2 Tuesday on 3 Wednesday on 4 Thursday on 5 Friday on 6 Saturday off --and-widget 2>/tmp/input.$$ sel=$? sed -i -e 's/\"//g' -e 's/\ /\,/g' /tmp/input.$$ week=`cat /tmp/input.$$` rm -f /tmp/input.$$ case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac ##choose time of backup (23:30 seems to be a good default choice) dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel --timebox "Choose time for Backup (Use arrows to modify)" 5 26 23 30 00 2>/tmp/input.$$ sel=$? hr=`cat /tmp/input.$$ | cut -f1 -d:` min=`cat /tmp/input.$$ | cut -f2 -d:` rm -f /tmp/input.$$ case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac # choose what, where, to whom we send email, where we print (if we print) dialog --title "$TITLE (SPACE to select what to save)" --backtitle "$BACKTITLE" --nocancel \ --fselect "/" 12 46 2>/tmp/input.$$ sel=$? SRC=`cat /tmp/input.$$` rm -f /tmp/input.$$ case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --inputbox "Select the destination device" 8 25 /dev/st0 2>/tmp/input.$$ sel=$? DES=`cat /tmp/input.$$` rm -f /tmp/input.$$ case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --inputbox "Type the notification emails" 8 47 "backupreport@xxxxxxxx.com root@localhost" 2>/tmp/input.$$ sel=$? REC=`cat /tmp/input.$$` rm -f /tmp/input.$$ REC=\"$REC\" case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --inputbox "Type the Printer name (if any)" 8 25 2>/tmp/input.$$ sel=$? PRN=`cat /tmp/input.$$` rm -f /tmp/input.$$ case $sel in 0);; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac #insert the line in crontab crontab -l > /tmp/tmpcrontab.$$ echo "$min $hr * * $week $myname backup $SRC $DES $REC $PRN" >> /tmp/tmpcrontab.$$ /usr/bin/crontab < /tmp/tmpcrontab.$$ rm -f /tmp/tmpcrontab.$$ dialog --title "$TITLE" --backtitle "$BACKTITLE" --nocancel \ --infobox "New crontab is installed...\n `crontab -l | grep $myname`" 10 45 fi ;; 255) $INTERRUPT && rm -f $LOCK && exit 1;; esac # end of graphical part, restore TERM setterm -default # remove lock sleep 1 rm $LOCK } ################### # backup & verify # ################### backup () { # Check if another job is running lock # Start backup if [ ! "$PRECOMMAND" == "" ]; then $PRECOMMAND >>$REPORTFILE fi echo "$HEADER Backup of $HOSTNAME started The command line was: $0 backup $SRC $DES $REC $PRN ">>$REPORTFILE # Start saving cd $SRC echo "Start WRITING $SRC to $DES on `date`">>$REPORTFILE # In any case exclude /proc /sys /tmp /mnt if [ "$ARCHIVER" == "tar" ] then tar --verbose --exclude=/proc --exclude=/sys --exclude=/tmp --exclude=/mnt --totals -b2048 -cpvf $DES $SRC >>$TEMPFILE 2>$TEMPFILE2 else echo "Enumerating the list of files and removing special folders ">>$REPORTFILE find . -depth -print | grep -v "./sys/" | grep -v "./proc/" | grep -v "./tmp/" | grep -v "./mnt/" >$LIST cat $LIST | cpio -ocvB >$DES 2>>$TEMPFILE fi backstat=$? echo " Following are the last lines recorded during saving:" >>$REPORTFILE tail $TEMPFILE | head -9 >>$REPORTFILE tail -n1 $TEMPFILE >>$REPORTFILE echo " WRITE exit status = $backstat ">> $REPORTFILE if [ $backstat -ne 0 ] then if [ $backstat -eq 1 ] then echo "*** Backup may be incomplete or have missing files ***">>$REPORTFILE elif [ $backstat -eq 2 ] then if [ `grep "Error exit delayed from previous errors" $TEMPFILE2` ] then echo "*** Backup may be incomplete or have missing files ***">>$REPORTFILE else echo "*** Backup has encounter a fatal ERROR. Please check ***">>$REPORTFILE fi else echo "*** Backup may contain an ERROR ***">>$REPORTFILE fi else echo "*** Backup COMPLETED OK ***">>$REPORTFILE fi echo "Tape WRITING completed on `date`">>$REPORTFILE if [ ! "$ARCHIVER" == "tar" ] then set `tail -1 $TEMPFILE | cut -d: -f2 | cut -d" " -f2` BACKTOT=$1 else BACKTOT=`grep "Total bytes" $TEMPFILE2 | cut -d: -f2 | cut -d" " -f2` fi echo " Total of amount of saved bytes was $BACKTOT ">>$REPORTFILE #Tape Verify echo "Starting VERIFY on $DES `date`">>$REPORTFILE if [ "$ARCHIVER" == "tar" ] then tar --verbose --exclude=/proc --exclude=/sys --exclude=/tmp --exclude=/mnt --totals -b2048 -tpvf $DES >>$TEMPFILEV 2>>$TEMPFILEV2 else cpio -icvtB <$DES >>$TEMPFILEV 2>>$TEMPFILEV2 fi verstat=$? echo " Following are the last lines recorded during verify:" >>$REPORTFILE tail $TEMPFILEV | head -9 >>$REPORTFILE tail $TEMPFILEV2 | head -9 >>$REPORTFILE echo " VERIFY exit status = $verstat ">>$REPORTFILE if [ $verstat -ne 0 ] then echo "*** Verify may contain an ERROR *** ">>$REPORTFILE fi echo "Verify completed for $HOSTNAME on `date` ">>$REPORTFILE if [ ! "$ARCHIVER" == "tar" ] then set `tail -1 $TEMPFILEV2 | cut -d: -f2 | cut -d" " -f2` VERTOT=$1 else VERTOT=`grep "Total bytes" $TEMPFILEV2 | cut -d: -f2 | cut -d" " -f2` fi echo "Total of amount of verified bytes was $VERTOT ">>$REPORTFILE if [[ $backstat -ne 0 || ($verstat -ne 0 || "$BACKTOT" != "$VERTOT") ]] then if [ $verstat -eq 1 ] then echo "*** Verify may be incomplete ***">>$REPORTFILE elif [ $verstat -eq 2 ] then echo "*** Verify has encounter a fatal ERROR. Please check ***">>$REPORTFILE else echo "*** The backup may contain an ERROR ***">>$REPORTFILE fi # put a warning echo "*** WARNING!!! BACKUP TRANSFER TOTALS DID NOT MATCH *** *** PLEASE VERIFY *** ">>$REPORTFILE # Send the report if [ ! "$(whereis mail | cut -d: -f2)" = "" ]; then cat $REPORTFILE | mail -s "Backup ERROR on $HOSTNAME" $REC 2>/dev/null; fi else # Gives the OK echo "*** Transfer Totals Concur *** ">>$REPORTFILE # Send the report if [ ! "$(whereis mail | cut -d: -f2)" = "" ]; then cat $REPORTFILE | mail -s "Backup OK on $HOSTNAME" $REC 2>/dev/null; fi fi # Print the report if [ "$PRN" = "" ]; then echo "Skip print, no printer defined" >> $REPORTFILE; elif [ ! "$(whereis lp |cut -d: -f2)" = "" ]; then lp -d $PRN $REPORTFILE; fi # Eject if mt is installed if [ ! "$(whereis mt |cut -d: -f2)" = "" ]; then mt -f $DES rewoffl; fi # remove lock sleep 1 rm $LOCK if [ ! "$POSTCOMMAND" == "" ]; then $POSTCOMMAND >>$REPORTFILE fi } ########### # restore # ########### restore () { # Check if another job is running lock # Start restore if [ ! "$PRECOMMAND" == "" ]; then $PRECOMMAND >>$REPORTFILE fi echo "$HEADER Restore started on `date` The command line was: $0 restore $SRC $DES $REC $PRN Choosing the files to restore...">>$REPORTFILE #choose the files to restore echo "Type the name of the files you want to restore (CR = all the archive) (ex: to restore everything from /etc/sysconfig type etc/sysconfi*):" read RES echo "Restoring $RES from $DES to $SRC." >> $REPORTFILE mkdir -p $SRC 2>/dev/null cd $SRC if [ "$ARCHIVER" == "tar" ] then tar --exclude=/proc --exclude=/sys --exclude=/tmp --exclude=/mnt --totals -b2048 -xpvf $DES $RES >>$TEMPFILE 2>>$TEMPFILE2 else cpio -icvdmB $RES < $DES >>$TEMPFILE 2>>$TEMPFILE2 fi resstat=$? echo "RESTORE exit status = $resstat ">>$REPORTFILE if [ $resstat -ne 0 ] then echo "*** RESTORE may contain an ERROR *** ">>$REPORTFILE fi # Prepare the report echo "Following are the special cases reported during restore:" >>$REPORTFILE tail $TEMPFILE | head -9 >> $REPORTFILE tail $TEMPFILE2 | head -9 >> $REPORTFILE set `tail -1 $TEMPFILE2 | cut -d: -f2 | cut -d" " -f2` RESTOT=$1 echo "Total of amount of restored bytes was $RESTOT ">>$REPORTFILE # Send the report if [ ! "$(whereis mail | cut -d: -f2)" = "" ]; then cat $REPORTFILE | mail -s "Restore report for $HOSTNAME" $REC 2>/dev/null; fi # Print the report if [ "$PRN" = "" ]; then echo "Skip print, no printer defined">> $REPORTFILE; elif [ ! "$(whereis lp |cut -d: -f2)" = "" ]; then lp -d $PRN $REPORTFILE; fi # Eject if mt is installed if [ ! "$(whereis mt |cut -d: -f2)" = "" ]; then mt -f $DES rewoffl; fi # remove lock sleep 1 rm $LOCK if [ ! "$POSTCOMMAND" == "" ]; then $POSTCOMMAND >>$REPORTFILE fi } ################### # Starting script # ################### case "$1" in backup) backup;; restore) restore;; *) # If it was called without parameters check if dialog exist and call the interface if [ "$(whereis dialog | cut -d: -f2)" = "" ]; then extract_dialog echo "Usage: $0 backup (source) (destination) (email) (printer) $0 restore (destination) (source) (email) (printer) " else void fi ;; esac # ensure a safe exit exit 0 ---DEMARK---
Monday, July 11, 2011
rotate kde cube using the accelerometer
ain't that fun? tilt the laptop and the cube rotates :) all thanks to the ST LIS3LV02DL Accelerometer
#!/bin/bash
# kde-cube-rotate
#
while true ; do
# vertical axis
#POS1=`cat /sys/devices/platform/lis3lv02d/position | awk -F , '{print$2}'`
#sleep .1
#POS2=`cat /sys/devices/platform/lis3lv02d/position | awk -F , '{print$2}'`
#horizontal axis
POS1=`cat /sys/devices/platform/lis3lv02d/position | awk -F , '{print$1}' | awk -F "(" '{print$2}'`
#sleep .1
POS2=`cat /sys/devices/platform/lis3lv02d/position | awk -F , '{print$1}' | awk -F "(" '{print$2}'`
DIS=$( wmctrl -d | grep "*" | awk '{sub(/x[0-9]+/, "", $1); print $1}'| tail -n1)
((POS=$POS1-$POS2))
#echo "pos1=$POS1 pos2=$POS2 pos=$POS display=$DIS"
if [ $POS -ge 20 ]; then
wmctrl -s $(( ${DIS} - 1 )) 2>/dev/null
sleep 1
elif [ $POS -le -20 ]; then
wmctrl -s $(( ${DIS} + 1 )) 2>/dev/null
sleep 1
fi
done
Saturday, May 28, 2011
/etc/udev/rules.d/80-automount.rules
KERNEL=="sd[a-z]", NAME="%k", SYMLINK+="usb%m", GROUP="users", OPTIONS="last_rule"
ACTION=="add", KERNEL=="sd[a-z][0-9]", SYMLINK+="usb%n", GROUP="users", NAME="%k"
ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mkdir -p /mnt/usb%n"
ACTION=="add", KERNEL=="sd[a-z][0-9]", PROGRAM=="/lib/udev/vol_id -t %N", RESULT=="vfat", RUN+="/bin/mount -t vfat -o rw,noauto,flush,quiet,nodev,nosuid,noexec,noatime,dmask=000,fmask=111 /dev/%k /mnt/usb%n", OPTIONS="last_rule"
ACTION=="add", KERNEL=="sd[a-z][0-9]", PROGRAM=="/lib/udev/vol_id -t %N", RESULT=="ntfs", RUN+="/bin/mount -t ntfs-3g -o rw,noauto,flush,quiet,nodev,nosuid,noexec,noatime,dmask=000,fmask=111 /dev/%k /mnt/usb%n", OPTIONS="last_rule"
ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mount -t auto -o rw,noauto,sync,dirsync,noexec,nodev,noatime /dev/%k /mnt/usb %n", OPTIONS="last_rule"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/umount -l /mnt/usb%n"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/rmdir /mnt/usb%n", OPTIONS="last_rule"
ACTION=="add", KERNEL=="sd[a-z][0-9]", SYMLINK+="usb%n", GROUP="users", NAME="%k"
ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mkdir -p /mnt/usb%n"
ACTION=="add", KERNEL=="sd[a-z][0-9]", PROGRAM=="/lib/udev/vol_id -t %N", RESULT=="vfat", RUN+="/bin/mount -t vfat -o rw,noauto,flush,quiet,nodev,nosuid,noexec,noatime,dmask=000,fmask=111 /dev/%k /mnt/usb%n", OPTIONS="last_rule"
ACTION=="add", KERNEL=="sd[a-z][0-9]", PROGRAM=="/lib/udev/vol_id -t %N", RESULT=="ntfs", RUN+="/bin/mount -t ntfs-3g -o rw,noauto,flush,quiet,nodev,nosuid,noexec,noatime,dmask=000,fmask=111 /dev/%k /mnt/usb%n", OPTIONS="last_rule"
ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mount -t auto -o rw,noauto,sync,dirsync,noexec,nodev,noatime /dev/%k /mnt/usb %n", OPTIONS="last_rule"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/umount -l /mnt/usb%n"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/rmdir /mnt/usb%n", OPTIONS="last_rule"
Sunday, April 24, 2011
VPN to Sonicwall's Virtual Office
#!/bin/bash
# 2011/04/22 sorin@XXXXXXXX.com
# A script to start the Sonicwall netExtender and create the necessary routes
# Sonicwall's netExtender binary is available from the VirtualOffice web interface.
#
# Define variables. In the config file the data format is TAB separated as follow:
# username password domainname ExternalIP port
#testusr tespassword LocalDomain 123.45.67.89 443
#
# Alternatively, you can define $user $pass $dom $ip $port here
prog="/usr/sbin/netExtender"
conf="/etc/sysconfig/gvpn.conf"
log="/dev/null"
if [ ! -f $prog ]; then
echo "No binary - fatal!"
exit 2
fi
if [ ! -f $conf ]; then
echo "No config, trying to set some defaults"
user=testusr
pass=testpassword
dom=LocalDomain
ip=123.45.67.89
port=443
fi
# Let's see how this script has been called
case "$1" in
start)
# if we have a conf file read the data from there
if [ -f $conf ]; then val=`sed '/^ *#/d;s/#.*//' $conf`; read user pass dom ip port < <( echo $val ); fi echo -e "Starting $prog..." $prog -u $user -p $pass -d $dom $ip:$port & >$log 2>&1
sleep 3
# after a few seconds we can try to add the route, but first \
# if we're in the same IP range, die gracefully, otherwise add the route
routenet=`sudo ifconfig | grep P-t-P | cut -d: -f2 | cut -d. -f1-3` >$log 2>&1
grp=`sudo ifconfig | grep -v P-t-P | grep '$routenet.255'` >$log 2>&1
if [ -z "$grp" ]; then
# mac users does not have "dev" in route's options, so let's add the route via a gateway
# routedev=`sudo ifconfig | grep ppp | cut -dL -f1` >$log 2>&1
# sudo route add -net $routenet netmask 255.255.255.0 dev $routedev >$log 2>&1
newip=`sudo ifconfig | grep P-t-P | cut -d: -f2 | cut -d" " -f1` >$log 2>&1
sudo route add -net $routenet.0 netmask 255.255.255.0 gw $newip >$log 2>&1
else
echo "We are in the same IP range, can't assign a route to the remote network!"
$0 stop
exit 1
fi
;;
stop)
echo -e "Stopping $prog..."
# first let's bring down the ppp interface
routedev=`sudo ifconfig | grep ppp | cut -dL -f1` >$log 2>&1
sudo ifconfig $routedev down >$log 2>&1
# then ask the pogram to terminate
sudo killall $prog >$log 2>&1
sleep 5
# if netExtender is still alive after 5 sec, force kill
if [ `ps xau | grep -v grep | grep $prog | awk '{print $2}' | wc -l` -ne "0" ]; then
sudo killall -9 $prog >$log 2>&1
fi
;;
status)
if [ `ps xau | grep -v grep | grep $prog | awk '{print $2}' | wc -l` -ne "0" ]; then
echo "$prog running with pid(s) `ps xau | grep -v grep | grep $prog | awk '{print $2}' | tr '
' ', '`"
echo "Showing route via ppp devices..." ; sudo route | grep ppp | grep -v 255.255.255.255
else
echo "$prog NOT running"
fi
;;
restart)
$0 stop
sleep 3
$0 start
;;
*)
printf "Usage: %s\n" "$(basename $0) {start|stop|status|restart}"
exit 1
esac
exit 0
# 2011/04/22 sorin@XXXXXXXX.com
# A script to start the Sonicwall netExtender and create the necessary routes
# Sonicwall's netExtender binary is available from the VirtualOffice web interface.
#
# Define variables. In the config file the data format is TAB separated as follow:
# username password domainname ExternalIP port
#testusr tespassword LocalDomain 123.45.67.89 443
#
# Alternatively, you can define $user $pass $dom $ip $port here
prog="/usr/sbin/netExtender"
conf="/etc/sysconfig/gvpn.conf"
log="/dev/null"
if [ ! -f $prog ]; then
echo "No binary - fatal!"
exit 2
fi
if [ ! -f $conf ]; then
echo "No config, trying to set some defaults"
user=testusr
pass=testpassword
dom=LocalDomain
ip=123.45.67.89
port=443
fi
# Let's see how this script has been called
case "$1" in
start)
# if we have a conf file read the data from there
if [ -f $conf ]; then val=`sed '/^ *#/d;s/#.*//' $conf`; read user pass dom ip port < <( echo $val ); fi echo -e "Starting $prog..." $prog -u $user -p $pass -d $dom $ip:$port & >$log 2>&1
sleep 3
# after a few seconds we can try to add the route, but first \
# if we're in the same IP range, die gracefully, otherwise add the route
routenet=`sudo ifconfig | grep P-t-P | cut -d: -f2 | cut -d. -f1-3` >$log 2>&1
grp=`sudo ifconfig | grep -v P-t-P | grep '$routenet.255'` >$log 2>&1
if [ -z "$grp" ]; then
# mac users does not have "dev" in route's options, so let's add the route via a gateway
# routedev=`sudo ifconfig | grep ppp | cut -dL -f1` >$log 2>&1
# sudo route add -net $routenet netmask 255.255.255.0 dev $routedev >$log 2>&1
newip=`sudo ifconfig | grep P-t-P | cut -d: -f2 | cut -d" " -f1` >$log 2>&1
sudo route add -net $routenet.0 netmask 255.255.255.0 gw $newip >$log 2>&1
else
echo "We are in the same IP range, can't assign a route to the remote network!"
$0 stop
exit 1
fi
;;
stop)
echo -e "Stopping $prog..."
# first let's bring down the ppp interface
routedev=`sudo ifconfig | grep ppp | cut -dL -f1` >$log 2>&1
sudo ifconfig $routedev down >$log 2>&1
# then ask the pogram to terminate
sudo killall $prog >$log 2>&1
sleep 5
# if netExtender is still alive after 5 sec, force kill
if [ `ps xau | grep -v grep | grep $prog | awk '{print $2}' | wc -l` -ne "0" ]; then
sudo killall -9 $prog >$log 2>&1
fi
;;
status)
if [ `ps xau | grep -v grep | grep $prog | awk '{print $2}' | wc -l` -ne "0" ]; then
echo "$prog running with pid(s) `ps xau | grep -v grep | grep $prog | awk '{print $2}' | tr '
' ', '`"
echo "Showing route via ppp devices..." ; sudo route | grep ppp | grep -v 255.255.255.255
else
echo "$prog NOT running"
fi
;;
restart)
$0 stop
sleep 3
$0 start
;;
*)
printf "Usage: %s\n" "$(basename $0) {start|stop|status|restart}"
exit 1
esac
exit 0
Tuesday, April 19, 2011
VT6421 IDE RAID Controller "hotswap"
#!/bin/bash
case "$1" in
start)
echo "Starting sata-via module..."
modprobe sata_via
echo "sleep 5 sec..."
sleep 5
lsmod | if grep sata_via; then echo -e "sata-via module \e[01;32mIS\e[00m inserted"; else echo -e "sata-via module \e[01;31mNOT\e[00m loaded"; fi
echo -e "Module inserted. HDD \e[01;32mavailable\e[00m"
cat /proc/partitions
;;
stop)
echo "Removing sata-via module..."
rmmod sata_via 2>/dev/null
echo "sleep 5 sec..."
sleep 5
lsmod | if grep sata_via; then echo -e "sata-via module \e[01;32mIS\e[00m inserted"; else echo -e "sata-via module \e[01;31mNOT\e[00m loaded"; fi
echo -e "Module removed. \e[01;32mSafe\e[00m to extract HDD."
cat /proc/partitions
;;
status)
lsmod | if grep sata_via; then echo -e "sata-via module \e[01;32mIS\e[00m inserted"; else echo -e "sata-via module \e[01;31mNOT\e[00m loaded"; fi
;;
restart|reload)
$0 stop
$0 start
;;
*)
printf $"Usage: %s {start|stop|restart|status}\n"
exit 1
esac
case "$1" in
start)
echo "Starting sata-via module..."
modprobe sata_via
echo "sleep 5 sec..."
sleep 5
lsmod | if grep sata_via; then echo -e "sata-via module \e[01;32mIS\e[00m inserted"; else echo -e "sata-via module \e[01;31mNOT\e[00m loaded"; fi
echo -e "Module inserted. HDD \e[01;32mavailable\e[00m"
cat /proc/partitions
;;
stop)
echo "Removing sata-via module..."
rmmod sata_via 2>/dev/null
echo "sleep 5 sec..."
sleep 5
lsmod | if grep sata_via; then echo -e "sata-via module \e[01;32mIS\e[00m inserted"; else echo -e "sata-via module \e[01;31mNOT\e[00m loaded"; fi
echo -e "Module removed. \e[01;32mSafe\e[00m to extract HDD."
cat /proc/partitions
;;
status)
lsmod | if grep sata_via; then echo -e "sata-via module \e[01;32mIS\e[00m inserted"; else echo -e "sata-via module \e[01;31mNOT\e[00m loaded"; fi
;;
restart|reload)
$0 stop
$0 start
;;
*)
printf $"Usage: %s {start|stop|restart|status}\n"
exit 1
esac
Saturday, March 05, 2011
clear tempfiles for winXP
usually I call this script at shutdown, gpedit.msc is the name!
@echo off
::Set Search directory to "Documents and Settings" folder
(Set Target=%AllUsersProfile:~0,-10%)
title,Finding the Temp subfolders in %Target%&COLOR 9E
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Local Settings\Temp" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%target%\%%*\Local Settings\Temp"
)
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Local Settings\Temporary Internet Files" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%target%\%%*\Local Settings\Temporary Internet Files"
)
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Local Settings\history\history.ie5" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%target%\%%*\Local Settings\history\history.ie5"
)
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Application Data\Sun\Java\Deployment\cache" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%target%\%%*\Application Data\Sun\Java\Deployment\cache"
)
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Local Settings\Application Data\Apple Computer\QuickTime\downloads" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md %target%\%%*\Local Settings\Application Data\Apple Computer\QuickTime\downloads
)
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Application Data\Macromedia\Flash Player" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%target%\%%*\Application Data\Macromedia\Flash Player"
)
For /f "Tokens=*" %%* in ('dir "%SystemRoot%\Temp" /B') Do (
cd /D "%SystemRoot%\Temp" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%SystemRoot%\Temp"
For /f "Tokens=*" %%* in ('dir "%SystemRoot%\prefetch" /B') Do (
cd /D "%SystemRoot%\prefetch" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%SystemRoot%\prefetch"
exit
@echo off
::Set Search directory to "Documents and Settings" folder
(Set Target=%AllUsersProfile:~0,-10%)
title,Finding the Temp subfolders in %Target%&COLOR 9E
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Local Settings\Temp" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%target%\%%*\Local Settings\Temp"
)
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Local Settings\Temporary Internet Files" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%target%\%%*\Local Settings\Temporary Internet Files"
)
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Local Settings\history\history.ie5" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%target%\%%*\Local Settings\history\history.ie5"
)
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Application Data\Sun\Java\Deployment\cache" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%target%\%%*\Application Data\Sun\Java\Deployment\cache"
)
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Local Settings\Application Data\Apple Computer\QuickTime\downloads" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md %target%\%%*\Local Settings\Application Data\Apple Computer\QuickTime\downloads
)
If EXIST "%Target%",(
For /f "Tokens=*" %%* in ('dir "%Target%" /B') Do (
cd /D "%target%\%%*\Application Data\Macromedia\Flash Player" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%target%\%%*\Application Data\Macromedia\Flash Player"
)
For /f "Tokens=*" %%* in ('dir "%SystemRoot%\Temp" /B') Do (
cd /D "%SystemRoot%\Temp" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%SystemRoot%\Temp"
For /f "Tokens=*" %%* in ('dir "%SystemRoot%\prefetch" /B') Do (
cd /D "%SystemRoot%\prefetch" && (
ATTRIB -S -H -R -A /D /S >nul & (
For /f "Tokens=*" %%* in ('dir /B') Do (
RD "%%*" /S /Q ||Del /F "%%*" )))>nul)
md "%SystemRoot%\prefetch"
exit
Tuesday, January 18, 2011
Install Windows printers
' replacepr.vbs - Windows NT Logon Script. (c) 2008-2010 sorin@xxxxxxx Inc.
' VBScript - Silently remove ALL network printers, install new ones with default
' this script require 2 additional files: one defining the printers we need to
' install, one printer per line and a second file defining what default printer
' we use, depending on what IP range this computer belongs the format of this
' file is IP_Range, Default_Printer (IP_Range is defined as, ex: 10.0.IP_Range.9)
' -----------------------------------------------------------------------'
Dim printer, sServer, i, l, default
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objNet = CreateObject("WScript.Network")
Set WshShell = CreateObject("WScript.Shell")
Set wmiLocator = CreateObject("WbemScripting.SWbemLocator")
Set wmiNameSpace = wmiLocator.ConnectServer(objNet.ComputerName, "root\default")
Set objRegistry = wmiNameSpace.Get("StdRegProv")
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
strComputer = "."
'Define the server where printers reside
sServer = "\\sqlsrv"
'If the OS is win7 we need to install printers from a win 2008 server
Set objWMIService = GetObject("winmgmts:" &_
"{impersonationLevel=impersonate}!\\" & strComputer & _
"\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colOperatingSystems
if objOperatingSystem.Caption = "Microsoft Windows 7 " then sServer = "\\2k8srv"
'wscript.echo sServer
Next
' If this script alredy run once for this user, then EXIT
userprrf = WshShell.Environment("PROCESS")("UserProfile")
'wscript.Echo userprrf
If (objFSO.FileExists(userprrf & "\sctwashere.txt")) Then
Wscript.Quit
Else
blah = "let's have some fun"
End If
' Deletes RegistryKey with all subkeys in Network printers
sPath = "Printers\Connections"
lRC = DeleteRegEntry(HKEY_CURRENT_USER, sPath)
Function DeleteRegEntry(sHive, sEnumPath)
' Attempt to delete key. If it fails, start the subkey enumration process.
lRC = objRegistry.DeleteKey(sHive, sEnumPath)
' The deletion failed, start deleting subkeys.
If (lRC <> 0) Then
' Subkey Enumerator
On Error Resume Next
lRC = objRegistry.EnumKey(HKEY_CURRENT_USER, sEnumPath, sNames)
For Each sKeyName In sNames
If Err.Number <> 0 Then Exit For
lRC = DeleteRegEntry(sHive, sEnumPath & "\" & sKeyName)
Next
On Error Goto 0
' At this point we should have looped through all subkeys, trying to delete the key again.
lRC = objRegistry.DeleteKey(sHive, sEnumPath)
End If
End Function
'Now let's recreate the "root" Key we deleted before
objRegistry.CreateKey HKEY_CURRENT_USER,sPath
'Tell something to the user
'with createobject("wscript.shell")
' .popup "All Printers are now erased, Reinstalling...",5, "Printers Manager"
'end with
'Let's see in what ip range we are, so we can choose a default printer
Set objWMIService = GetObject( _
"winmgmts:\\" & strComputer & "\root\cimv2")
Set IPConfigSet = objWMIService.ExecQuery _
("Select IPAddress from Win32_NetworkAdapterConfiguration ")
For Each IPConfig in IPConfigSet
If Not IsNull(IPConfig.IPAddress) Then
For i=LBound(IPConfig.IPAddress) _
to UBound(IPConfig.IPAddress)
strArray=Split(IPConfig.IPAddress(i),".")
if ubound(strArray) > 2 Then
'WScript.Echo strArray(2)
if strArray(0) = 192 And strArray(1) = 168 Then
Exit For
End if
End If
Next
End If
Next
' Read the file containig the pair ip-range, default-printer
'(the ip range is the 3rd digit in the ip - 10.0.X.3 - gives X as range)
Set objFile = objFSO.OpenTextFile("defaultlist.txt", ForReading)
'WScript.Echo strArray(2)
Do Until objFile.AtEndOfStream
defaultArray = split(objFile.ReadLine,",")
if defaultArray(0) = strArray(2) Then
defaultprt=defaultArray(1)
'wscript.Echo defaultArray(1)
exit do
end if
Loop
objFile.Close
default = sServer & "\" & defaultArray(1)
'wscript.Echo default
'Now let's start installing the printers listed in plist.txt
Set objFile = objFSO.OpenTextFile("plist.txt", ForReading)
Do Until objFile.AtEndOfStream
printer = objFile.ReadLine
printer = sServer & "\" & printer
if printer = default then
strCmd = "rundll32 printui.dll,PrintUIEntry /in /n """ & printer & """ /u /q /Gw"
WshShell.Run strCmd,,true
strCmd = "rundll32 printui.dll,PrintUIEntry /y /n """ & printer & ""
else
strCmd = "rundll32 printui.dll,PrintUIEntry /in /n """ & printer & """ /u /q /Gw"
end if
WshShell.Run strCmd
Loop
objFile.Close
with createobject("wscript.shell")
.popup "All Printers Are Now ReInstalled",15, "Printers Management"
end with
'We're done, let's leave a trace in userprofile, so at next login this script will exit
Set objFile1 = objFSO.CreateTextFile(userprrf & "\sctwashere.txt")
Wscript.Quit
' VBScript - Silently remove ALL network printers, install new ones with default
' this script require 2 additional files: one defining the printers we need to
' install, one printer per line and a second file defining what default printer
' we use, depending on what IP range this computer belongs the format of this
' file is IP_Range, Default_Printer (IP_Range is defined as, ex: 10.0.IP_Range.9)
' -----------------------------------------------------------------------'
Dim printer, sServer, i, l, default
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objNet = CreateObject("WScript.Network")
Set WshShell = CreateObject("WScript.Shell")
Set wmiLocator = CreateObject("WbemScripting.SWbemLocator")
Set wmiNameSpace = wmiLocator.ConnectServer(objNet.ComputerName, "root\default")
Set objRegistry = wmiNameSpace.Get("StdRegProv")
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
strComputer = "."
'Define the server where printers reside
sServer = "\\sqlsrv"
'If the OS is win7 we need to install printers from a win 2008 server
Set objWMIService = GetObject("winmgmts:" &_
"{impersonationLevel=impersonate}!\\" & strComputer & _
"\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colOperatingSystems
if objOperatingSystem.Caption = "Microsoft Windows 7 " then sServer = "\\2k8srv"
'wscript.echo sServer
Next
' If this script alredy run once for this user, then EXIT
userprrf = WshShell.Environment("PROCESS")("UserProfile")
'wscript.Echo userprrf
If (objFSO.FileExists(userprrf & "\sctwashere.txt")) Then
Wscript.Quit
Else
blah = "let's have some fun"
End If
' Deletes RegistryKey with all subkeys in Network printers
sPath = "Printers\Connections"
lRC = DeleteRegEntry(HKEY_CURRENT_USER, sPath)
Function DeleteRegEntry(sHive, sEnumPath)
' Attempt to delete key. If it fails, start the subkey enumration process.
lRC = objRegistry.DeleteKey(sHive, sEnumPath)
' The deletion failed, start deleting subkeys.
If (lRC <> 0) Then
' Subkey Enumerator
On Error Resume Next
lRC = objRegistry.EnumKey(HKEY_CURRENT_USER, sEnumPath, sNames)
For Each sKeyName In sNames
If Err.Number <> 0 Then Exit For
lRC = DeleteRegEntry(sHive, sEnumPath & "\" & sKeyName)
Next
On Error Goto 0
' At this point we should have looped through all subkeys, trying to delete the key again.
lRC = objRegistry.DeleteKey(sHive, sEnumPath)
End If
End Function
'Now let's recreate the "root" Key we deleted before
objRegistry.CreateKey HKEY_CURRENT_USER,sPath
'Tell something to the user
'with createobject("wscript.shell")
' .popup "All Printers are now erased, Reinstalling...",5, "Printers Manager"
'end with
'Let's see in what ip range we are, so we can choose a default printer
Set objWMIService = GetObject( _
"winmgmts:\\" & strComputer & "\root\cimv2")
Set IPConfigSet = objWMIService.ExecQuery _
("Select IPAddress from Win32_NetworkAdapterConfiguration ")
For Each IPConfig in IPConfigSet
If Not IsNull(IPConfig.IPAddress) Then
For i=LBound(IPConfig.IPAddress) _
to UBound(IPConfig.IPAddress)
strArray=Split(IPConfig.IPAddress(i),".")
if ubound(strArray) > 2 Then
'WScript.Echo strArray(2)
if strArray(0) = 192 And strArray(1) = 168 Then
Exit For
End if
End If
Next
End If
Next
' Read the file containig the pair ip-range, default-printer
'(the ip range is the 3rd digit in the ip - 10.0.X.3 - gives X as range)
Set objFile = objFSO.OpenTextFile("defaultlist.txt", ForReading)
'WScript.Echo strArray(2)
Do Until objFile.AtEndOfStream
defaultArray = split(objFile.ReadLine,",")
if defaultArray(0) = strArray(2) Then
defaultprt=defaultArray(1)
'wscript.Echo defaultArray(1)
exit do
end if
Loop
objFile.Close
default = sServer & "\" & defaultArray(1)
'wscript.Echo default
'Now let's start installing the printers listed in plist.txt
Set objFile = objFSO.OpenTextFile("plist.txt", ForReading)
Do Until objFile.AtEndOfStream
printer = objFile.ReadLine
printer = sServer & "\" & printer
if printer = default then
strCmd = "rundll32 printui.dll,PrintUIEntry /in /n """ & printer & """ /u /q /Gw"
WshShell.Run strCmd,,true
strCmd = "rundll32 printui.dll,PrintUIEntry /y /n """ & printer & ""
else
strCmd = "rundll32 printui.dll,PrintUIEntry /in /n """ & printer & """ /u /q /Gw"
end if
WshShell.Run strCmd
Loop
objFile.Close
with createobject("wscript.shell")
.popup "All Printers Are Now ReInstalled",15, "Printers Management"
end with
'We're done, let's leave a trace in userprofile, so at next login this script will exit
Set objFile1 = objFSO.CreateTextFile(userprrf & "\sctwashere.txt")
Wscript.Quit
Saturday, January 15, 2011
Monitor windows logs
Thanks to Stefan Plattner (http://twitter.com/splattne)
Considering that Intel's Matrix Raid does not have a way to send emails
in case of a HDD failure, I've searched for a way of monitoring the
Windows system log and send a mail in case of an event. The monitoring
part can be solved with a simple vbs script (made by splattne), this
script being run as service by the "Non-Sucking Service Manager"
( http://iain.cx/src/nssm/ ).
You can define the events you want to be alerted on, in the vbs script
with the "PushEventToMonitor" call. The arguments are: event ID, event
log name, source, category, type, user, and a regular expression that
can be matched against the log message. We have an example in the vbs
script that matches the start / stop of the TELNET service, as well as
one that will match the startup of the script itself (which logs an
event out to the Application Log) and a real case for Intel MatrixRaid.
In order to install the service, run in a command prompt: "nssm install
SimpleEventLogMonitor" and in the following window choose
"%SystemRoot%\System32\cscript.exe" as Application and
"c:\Path\to\eventmonitor.vbs" as Option.
To uninstall run: "nssm remove SimpleEventLogMonitor confirm" (Warning:
you can uninstall any service with this command!)
vbs script starts here:
Option Explicit
' Main
Dim objShell, objWMIService, objEventSink, dictEventsToMonitor, eventToMonitor
' =====================( Configuration )=====================
' Set to 0 to disable event log reporting of bans / unbans
Const USE_EVENTLOG = 0
Const EVENTLOG_SOURCE = "SimpleEventMonitor"
' SMTP configuration
Const EMAIL_SENDER = "EventLogMonitor@xxxxxxxxxxxx.ca"
Const EMAIL_RECIPIENT = "sorin@xxxxxxxx.com"
Const EMAIL_SMTP_SERVER = "relais.xxxxxxxxxx.ca"
Const EMAIL_SMTP_PORT = 25
Const EMAIL_TIMEOUT = 20
Set dictEventsToMonitor = CreateObject("Scripting.Dictionary")
' Define events that should be monitored. Matches are based on exact matches of all non-NULL fields
' Order: event ID, event log name, source, category, type, user, and a regular expression
'PushEventToMonitor "100", "Application", EVENTLOG_SOURCE, NULL, NULL, NULL, NULL
'PushEventToMonitor "7036", "System", "Service Control Manager", NULL, NULL, NULL, "Telnet service.*(running|stopped).*state"
' Monitor my Intel service
PushEventToMonitor "7202", "System", " IAANTmon", NULL, "Warning", NULL, NULL
' ===================( End Configuration )===================
Set objShell = CreateObject("WScript.Shell")
' Create event sink to catchevents
Set objWMIService = GetObject("winmgmts:{(security)}!root/cimv2")
Set objEventSink = WScript.CreateObject("WbemScripting.SWbemSink", "eventSink_")
objWMIService.ExecNotificationQueryAsync objEventSink, "SELECT * FROM __InstanceCreationEvent WHERE TargetInstance ISA 'Win32_NTLogEvent'"
' Loop sleeping for one week, logging an event each week to say we're still alive
While (True)
LogEvent 100, "INFORMATION", "Simple Event Log Monitor started"
WScript.Sleep(7 * 24 * 60 * 60 * 1000)
Wend
' Fires each time new events are generated
Sub eventSink_OnObjectReady(objEvent, objWbemAsyncContext)
Dim evt, field, boolAlert, regexpMessage
For Each evt In dictEventsToMonitor.Keys
boolAlert = True
For Each field In dictEventsToMonitor.Item(evt).Keys
If UCase(Field) = "MESSAGE" Then
Set regexpMessage = new Regexp
regexpMessage.Pattern = dictEventsToMonitor.Item(evt).Item(Field)
regexpMessage.IgnoreCase = True
If NOT regexpMessage.Test(objEvent.TargetInstance.Properties_(Field)) then boolAlert = False
Else
If UCase(objEvent.TargetInstance.Properties_(Field)) <> UCase(dictEventsToMonitor.Item(evt).Item(field)) Then boolAlert = False
End If
Next ' field
if boolAlert = True Then
SendMessage "Simple Event Log Monitor notification from " & objEvent.TargetInstance.ComputerName, _
"Event ID: " & objEvent.TargetInstance.EventCode & VbCrLf _
& "Date/Time: " & Mid(objEvent.TargetInstance.TimeGenerated, 5, 2) & "/" & Mid(objEvent.TargetInstance.TimeGenerated, 7, 2) & "/" & Mid(objEvent.TargetInstance.TimeGenerated, 1, 4) & " " & Mid(objEvent.TargetInstance.TimeGenerated, 9, 2) & ":" & Mid(objEvent.TargetInstance.TimeGenerated, 11, 2) & ":" & Mid(objEvent.TargetInstance.TimeGenerated, 13, 2) & VbCrLf _
& "Computer: " & objEvent.TargetInstance.ComputerName & vbCrLf _
& "Event Log: " & objEvent.TargetInstance.LogFile & vbCrLf _
& "Event Source: " & objEvent.TargetInstance.SourceName & vbCrLf _
& "Event Category: " & objEvent.TargetInstance.CategoryString & vbCrLf _
& "Event Type: " & objEvent.TargetInstance.Type & vbCrLf _
& "User Name: " & objEvent.TargetInstance.User & vbCrLf _
& "Message:" & vbCrLf & vbCrLF _
& objEvent.TargetInstance.Message
Exit Sub
End If
Next ' evt
End Sub
Sub LogEvent(ID, EventType, Message)
' Log an event to the Windows event log
If USE_EVENTLOG Then objShell.Exec "EVENTCREATE /L APPLICATION /SO " & EVENTLOG_SOURCE & " /ID " & ID & " /T " & EventType & " /D """ & Message & """"
End Sub
Sub SendMessage(strSubject, strBody)
Dim objCDOMessage
Set objCDOMessage = CreateObject("CDO.Message")
objCDOMessage.From = EMAIL_SENDER
objCDOMessage.To = EMAIL_RECIPIENT
objCDOMessage.Subject = strSubject
objCDOMessage.Textbody = strBody
objCDOMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = EMAIL_SMTP_SERVER
objCDOMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = EMAIL_SMTP_PORT
objCDOMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = EMAIL_TIMEOUT
objCDOMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objCDOMessage.Configuration.Fields.Update
objCDOMessage.send
End Sub
Sub PushEventToMonitor(strID, strLog, strSource, strCategory, strType, strUser, strMessagePattern)
Dim x
x = dictEventsToMonitor.Count
Set dictEventsToMonitor.Item(x) = CreateObject("Scripting.Dictionary")
If NOT IsNull(strID) Then dictEventsToMonitor.Item(x).Add "EventCode", strID
If NOT IsNull(strLog) Then dictEventsToMonitor.Item(x).Add "LogFile", strLog
If NOT IsNull(strSource) Then dictEventsToMonitor.Item(x).Add "SourceName", strSource
If NOT IsNull(strCategory) Then dictEventsToMonitor.Item(x).Add "CategoryString", strCategory
If NOT IsNull(strType) Then dictEventsToMonitor.Item(x).Add "Type", strType
If NOT IsNull(strType) Then dictEventsToMonitor.Item(x).Add "User", strUser
If NOT IsNull(strMessagePattern) Then dictEventsToMonitor.Item(x).Add "Message", strMessagePattern
End Sub
Considering that Intel's Matrix Raid does not have a way to send emails
in case of a HDD failure, I've searched for a way of monitoring the
Windows system log and send a mail in case of an event. The monitoring
part can be solved with a simple vbs script (made by splattne), this
script being run as service by the "Non-Sucking Service Manager"
( http://iain.cx/src/nssm/ ).
You can define the events you want to be alerted on, in the vbs script
with the "PushEventToMonitor" call. The arguments are: event ID, event
log name, source, category, type, user, and a regular expression that
can be matched against the log message. We have an example in the vbs
script that matches the start / stop of the TELNET service, as well as
one that will match the startup of the script itself (which logs an
event out to the Application Log) and a real case for Intel MatrixRaid.
In order to install the service, run in a command prompt: "nssm install
SimpleEventLogMonitor" and in the following window choose
"%SystemRoot%\System32\cscript.exe" as Application and
"c:\Path\to\eventmonitor.vbs" as Option.
To uninstall run: "nssm remove SimpleEventLogMonitor confirm" (Warning:
you can uninstall any service with this command!)
vbs script starts here:
Option Explicit
' Main
Dim objShell, objWMIService, objEventSink, dictEventsToMonitor, eventToMonitor
' =====================( Configuration )=====================
' Set to 0 to disable event log reporting of bans / unbans
Const USE_EVENTLOG = 0
Const EVENTLOG_SOURCE = "SimpleEventMonitor"
' SMTP configuration
Const EMAIL_SENDER = "EventLogMonitor@xxxxxxxxxxxx.ca"
Const EMAIL_RECIPIENT = "sorin@xxxxxxxx.com"
Const EMAIL_SMTP_SERVER = "relais.xxxxxxxxxx.ca"
Const EMAIL_SMTP_PORT = 25
Const EMAIL_TIMEOUT = 20
Set dictEventsToMonitor = CreateObject("Scripting.Dictionary")
' Define events that should be monitored. Matches are based on exact matches of all non-NULL fields
' Order: event ID, event log name, source, category, type, user, and a regular expression
'PushEventToMonitor "100", "Application", EVENTLOG_SOURCE, NULL, NULL, NULL, NULL
'PushEventToMonitor "7036", "System", "Service Control Manager", NULL, NULL, NULL, "Telnet service.*(running|stopped).*state"
' Monitor my Intel service
PushEventToMonitor "7202", "System", " IAANTmon", NULL, "Warning", NULL, NULL
' ===================( End Configuration )===================
Set objShell = CreateObject("WScript.Shell")
' Create event sink to catchevents
Set objWMIService = GetObject("winmgmts:{(security)}!root/cimv2")
Set objEventSink = WScript.CreateObject("WbemScripting.SWbemSink", "eventSink_")
objWMIService.ExecNotificationQueryAsync objEventSink, "SELECT * FROM __InstanceCreationEvent WHERE TargetInstance ISA 'Win32_NTLogEvent'"
' Loop sleeping for one week, logging an event each week to say we're still alive
While (True)
LogEvent 100, "INFORMATION", "Simple Event Log Monitor started"
WScript.Sleep(7 * 24 * 60 * 60 * 1000)
Wend
' Fires each time new events are generated
Sub eventSink_OnObjectReady(objEvent, objWbemAsyncContext)
Dim evt, field, boolAlert, regexpMessage
For Each evt In dictEventsToMonitor.Keys
boolAlert = True
For Each field In dictEventsToMonitor.Item(evt).Keys
If UCase(Field) = "MESSAGE" Then
Set regexpMessage = new Regexp
regexpMessage.Pattern = dictEventsToMonitor.Item(evt).Item(Field)
regexpMessage.IgnoreCase = True
If NOT regexpMessage.Test(objEvent.TargetInstance.Properties_(Field)) then boolAlert = False
Else
If UCase(objEvent.TargetInstance.Properties_(Field)) <> UCase(dictEventsToMonitor.Item(evt).Item(field)) Then boolAlert = False
End If
Next ' field
if boolAlert = True Then
SendMessage "Simple Event Log Monitor notification from " & objEvent.TargetInstance.ComputerName, _
"Event ID: " & objEvent.TargetInstance.EventCode & VbCrLf _
& "Date/Time: " & Mid(objEvent.TargetInstance.TimeGenerated, 5, 2) & "/" & Mid(objEvent.TargetInstance.TimeGenerated, 7, 2) & "/" & Mid(objEvent.TargetInstance.TimeGenerated, 1, 4) & " " & Mid(objEvent.TargetInstance.TimeGenerated, 9, 2) & ":" & Mid(objEvent.TargetInstance.TimeGenerated, 11, 2) & ":" & Mid(objEvent.TargetInstance.TimeGenerated, 13, 2) & VbCrLf _
& "Computer: " & objEvent.TargetInstance.ComputerName & vbCrLf _
& "Event Log: " & objEvent.TargetInstance.LogFile & vbCrLf _
& "Event Source: " & objEvent.TargetInstance.SourceName & vbCrLf _
& "Event Category: " & objEvent.TargetInstance.CategoryString & vbCrLf _
& "Event Type: " & objEvent.TargetInstance.Type & vbCrLf _
& "User Name: " & objEvent.TargetInstance.User & vbCrLf _
& "Message:" & vbCrLf & vbCrLF _
& objEvent.TargetInstance.Message
Exit Sub
End If
Next ' evt
End Sub
Sub LogEvent(ID, EventType, Message)
' Log an event to the Windows event log
If USE_EVENTLOG Then objShell.Exec "EVENTCREATE /L APPLICATION /SO " & EVENTLOG_SOURCE & " /ID " & ID & " /T " & EventType & " /D """ & Message & """"
End Sub
Sub SendMessage(strSubject, strBody)
Dim objCDOMessage
Set objCDOMessage = CreateObject("CDO.Message")
objCDOMessage.From = EMAIL_SENDER
objCDOMessage.To = EMAIL_RECIPIENT
objCDOMessage.Subject = strSubject
objCDOMessage.Textbody = strBody
objCDOMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = EMAIL_SMTP_SERVER
objCDOMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = EMAIL_SMTP_PORT
objCDOMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = EMAIL_TIMEOUT
objCDOMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objCDOMessage.Configuration.Fields.Update
objCDOMessage.send
End Sub
Sub PushEventToMonitor(strID, strLog, strSource, strCategory, strType, strUser, strMessagePattern)
Dim x
x = dictEventsToMonitor.Count
Set dictEventsToMonitor.Item(x) = CreateObject("Scripting.Dictionary")
If NOT IsNull(strID) Then dictEventsToMonitor.Item(x).Add "EventCode", strID
If NOT IsNull(strLog) Then dictEventsToMonitor.Item(x).Add "LogFile", strLog
If NOT IsNull(strSource) Then dictEventsToMonitor.Item(x).Add "SourceName", strSource
If NOT IsNull(strCategory) Then dictEventsToMonitor.Item(x).Add "CategoryString", strCategory
If NOT IsNull(strType) Then dictEventsToMonitor.Item(x).Add "Type", strType
If NOT IsNull(strType) Then dictEventsToMonitor.Item(x).Add "User", strUser
If NOT IsNull(strMessagePattern) Then dictEventsToMonitor.Item(x).Add "Message", strMessagePattern
End Sub
Friday, August 27, 2010
Print to fax
print to a network printer and the fax is sent! At the top of the page put the destination fax, recipient name, subject...; in order to hide those you need a mask.pdf file that contain just some white spaces that will be overlay-ed
#!/usr/bin/perl -w
# This perl script routes postscript printerdata from printerspooler to fax
#
# copy to /usr/lib/cups/backends/ and run this script from the commandline: echo blah | ./netfax
# it will tell if there are any dependancies unsolved: this tool is dependant upon the following:
# perl (we tested with v5.6 and its likely any v5 will do)
# perl modules Getopt-Long-2.32 and Mail-Sendmail-0.78
# sendfax (from the hylafax package)
# ps2ascii ps2pdf pdf2ps (comes with the ghostscript package)
# pdftk http://www.accesspdf.com/pdftk/
# a mask.pdf file that will hide the command parameters sent at the begining of your page by overlaying a white image
#
# After that you can add new printer to cups: lpadmin -p NetFax -E -v netfax.pl:
# Share the printer in samba and, if your fax server joined the domain, run:
# net -S localhost -U administrator rpc rights grant 'administrator' SePrintOperatorPrivilege
# in smb.conf [printers] section add -J %m to print command (tipically: lpr-cups -P %p -J %m -o raw $s)
# or add cups option = "%m" in the same section and make the drivers share [print$] writable
# Now from windows machine browse the fax server printers, right-click NetFax, choose properties,
# say NO when asked to install drivers, go to Advanced tab, and choose "New Driver". Choose
# some plain PS printer line Apple LaserWriter 12/640 PS and push the drivers to server.
# Now your printer can now be install on all workstations by a vbs script or by using printUI.dll.
#
# The accepted commands, placed at the begining of your faxed document are:
# 'Fax-Nr : XXX-XXXXX;(XXX)XXXXX~' the number can contain dashes or paranthesis. multiple numbers are separated by ;
# 'Clientid : AAAAAA AAAA~' the recipient name
# 'Subjectid : AAAA AAAAAAA~' the message subject
# 'E-m@il : AAA@BBBBBBB~' sender's email. if BBBBBBB matches a different windows machine name
# a winpopup message will be sent to that machine instead of originating machine
#
# Please note that every command line ends by a ~ character!
#
# in order to send a winpopup message add the following lines to notify_mail() function in /var/spool/fax/bin/notify
# HST = `echo $2 | sed -e 's/[^>]*@\([^ ]*\).*/\1/' -e '2.$d'`
# echo $1 | /usr/bin/smbclient -M $HST
#
# neXt - sorin@xxxxxxxx.com - June-2010
#
use strict;
use Getopt::Long;
use Mail::Sendmail;
# constants you must check if they are ok
my $ALLOWMULTIFAX = 1; # allow (1) or not (0) multiple faxdestinations
my $EMAILFROMDOC = 1; # get the emailaddress from samba (0) or the doc (1)
my $SENDFAX = "/usr/bin/sendfax"; # the command to send a fax
my $PS2ASCII = "/usr/bin/ps2ascii"; # the command to convert postscript to readable text
my $PS2PDF = "/usr/bin/ps2pdf"; # transform ps to pdf
my $PDFTK = "/usr/bin/pdftk"; # modify pdfs - used to overlay the mask over commands section
my $PDF2PS = "/usr/bin/pdf2ps"; # transform pdf back to ps
my $WATERMARK = "/etc/initsetup/mask.pdf"; # location of the overlay mask
# constants you can alter but should consider not to
my $TMPDIR = "/tmp/"; # the directory to store temporary files
my $MYNAME = "netfax"; # the name of this tool
my $LOGFILE = $TMPDIR . $MYNAME . ".log"; # the name of the logfile - debugging sessions only
my $PSFILE = $TMPDIR . $MYNAME . $$ . ".ps" ; # the name of the postscript temporary file
my $PSTMPFILE = $TMPDIR . $MYNAME . $$ . "work.ps" ; # the name of the postscript temporary file
my $MAILADDRESS = 'faxadmin@hfax'; # the default mailaddress for errormessages
my $MULTISEP = ";"; # if you have more than 1 faxnr on a line, they are seperated by ;
# this character should NOT appear in $DIGITS
my $DEBUG=0;
# constants you really should not touch !!!
my $FAXID = 'Fax-Nr[s]{0,1}\s*:\s*'; # search string for fax-nr
my $FAXIDS = 'Fax-Nrs\s*:\s*'; # search string for fax-nrs ( for multifax }
my $DIGITS = '0123456789+( ),-'; # digits allowed in the faxnr
my $MODEMLIKES = '0123456789+,'; # digits my modem will not reject: ,=wait +=int.access
# this should be a subset of $DIGITS
my $EMAILDOC = 'E-m@il :'; # the string to look for an emailaddress
my $CLIENTID = 'Clientid :'; # this is the recipient name
my $SUBJECTID = 'Subjectid :'; # the line with subject must contain this
########## from here on, leave the code alone, unless you are really sure ############
#variables
my @faxlines; # stores the raw faxlines
my @faxdest; # stores the faxnumbers
my $MultiFax = 0; # determines if ENDuser specified to multifax
my $mailaddress = ""; # how do we treat the errormessages
my $lpuser = ""; # username retrieved from lprng or lpd commandline
my $lphost = ""; # hostname retrieved from lprng or lpd commandline
my $client = " "; # the client name
my $subject = " "; # the message subject
my @emaillines; # stores the documentlines containing EMAILDOC
my @clienthost; # stores the temporary sender hostname
my @clientline; # stores the client name line
my @subjectline; # stores the subject line
#Check for arguments - if none, cups is initialising
if (@ARGV == 0) {
exit 0;
}
# check some dependencies
if ( ! -d $TMPDIR ) {
print("Error: temporary directory not found: ", $TMPDIR );
exit 1;
}
if ( ! -e $SENDFAX ) {
Log("Error: sendfax command not found: ", $SENDFAX );
exit 1;
}
if ( ! -e $PS2ASCII ) {
Log("Error: ghostscript command not found: ", $PS2ASCII );
exit 1;
}
# get usefull parameters
my $cupsfile = $ARGV[5]; # CUPS parses a filename with the printdata as the 6th parameer
# this could be undef (after lpr -d blah) or a filename (after a samba action)
my $cupsuser = $ARGV[1]; # CUPS paresed the username with the printdata as the 2nd parameter
# this is usually a user from localhost
GetOptions( 'h=s' => \$lphost, # LPD and LPRng parse host and user name under the -h and -n parameter
'n=s' => \$lpuser); # the postscript is parsed to it in a pipe - to be found in STDIN
my $fullhost = $ARGV[4]; #hostname is found here because in smb.conf I've added -P %m on print command
# let's extract the hostname in order to be added to email address
@clienthost = split(/\s+/,$fullhost);print $clienthost[0];
my $finalhost = $clienthost[0];
# ok lets find out where we can send the mail to
if ( ( $lphost ) and ( $lpuser ) ) { #if the user and host can be found on the commandline
$mailaddress = $lpuser . '@' . $lphost ;
} elsif ( $cupsuser) {
$mailaddress = $cupsuser . '@' . $finalhost ; # create "email" from user+hostname
} else {
$mailaddress = $MAILADDRESS; # or use the E-m@il defined in doc
}
# where is the printerdata?
if ( ( $cupsfile ) and ( -e $cupsfile ) ) {
$PSFILE = $cupsfile;
} else {
&SavePostscriptdata;
}
if ($DEBUG) {
Log("");
Log("------------------------------------------");
Log("");
}
# ok we have a postscriptfile, now
if ( &RetrieveRawFaxline ) { # we found one ore more lines
if ( &ExtractFaxnumber ) { # we could extract a real faxnumber
$client = &GetClientFromDoc; # get the Client Id
$subject = &GetSubjectFromDoc; # Get the Subject
if ($EMAILFROMDOC) {
$mailaddress = &GetEmailFromDoc; # Get the email from doc
}
if ($DEBUG) {
Log("Debug: email address = ",$mailaddress);
Log("Debug: postscript file = ",$PSFILE);
Log("Debug: cups file = ",$cupsfile);
}
&TrySending; # mask the header and send the fax
} else { # no real faxnumber could be extracted
&SendErrorMail;
Log("No Fax Number extracted");
}
} else { # no lines with faxnr found
&SendErrorMail;
Log("No Fax-Nr found");
}
# delete the temporary printfiles in case DEBUG is off
if (!$DEBUG) {
unlink $PSFILE;
unlink $PSTMPFILE;
unlink $PSTMPFILE . ".pdf";
unlink $PSTMPFILE . "clean.pdf";
}
Log("End of task");
# always exit gracefully.
exit 0;
# sub #################################################
# save the information in the pipe to the ps tmp file
sub SavePostscriptdata {
Log("sub SavePostscriptData");
open PS, ">".$PSFILE or die("Sorry, cannot open temporary postscript file $PSFILE .\n");
while () {
print PS $_ ;
}
close PS;
}
# sub #################################################
sub RetrieveRawFaxline {
my $CL = $PS2ASCII . " " . $PSFILE . " |";
my $ret = 0;
open CL, $CL; # carry out ps2ascii on the ps-file and return the output into perl
while (my $line=) {
chomp $line;
if ($line =~ /$FAXID/i) { # if the rawline matches with fax-nr
push @faxlines, $line ; # add it to the stack of matching lines
$ret++;
}
if ($line =~ /$FAXIDS/i) { # if the rawline matches with fax-nrs
$MultiFax = 1; # the userties to multifax
}
if ($line =~ /$CLIENTID/i) { # if the rawline matches with clientid
push @clientline, $line ; # add it to the stack of matching lines
if ($DEBUG) {
Log("Debug: clientline added - ",$line);
}
}
if ($line =~ /$SUBJECTID/i) { # if the rawline matches with subjectid
push @subjectline, $line ; # add it to the stack of matching lines
if ($DEBUG) {
Log("Debug: subjectline added - ",$line);
}
}
if ($line =~ /$EMAILDOC/i) { # if the rawline matches with "email"
push @emaillines, $line; # add it to the emailstack
if ($DEBUG) {
Log("Debug: emailline added - ",$line);
}
}
}
close CL;
# check the multifax setting
$MultiFax = $ALLOWMULTIFAX if $MultiFax; # ALLOWMULTIFAX overrides Multifax
return $ret;
}
# sub #################################################
sub ExtractFaxnumber {
my $ret = 0; # return value: 0=nothing found, more=ok
if ( $MultiFax ) { # extract all the faxnumbers you can find
for ( my $i=0; $i<@faxlines; $i++) { # for all the rawline push @faxdest, &GetFaxNumbersFrom($faxlines[$i]); #extract the numbers } $ret = @faxdest; } else { # just extract the first faxnumber in the first line my @fns = &GetFaxNumbersFrom($faxlines[0]); # extract the numbers from the first raw line if ( defined $fns[0] ) { # if it exists push @faxdest, $fns[0]; # put it on the return stack $ret++; } } return $ret; } # sub ################################################# sub GetFaxNumbersFrom { my @ret = (); my $rawline = shift; if ( defined $rawline ) { my $ModemRejects = "[^" . $MODEMLIKES . "]"; # regexp with non-modem chars if ( $rawline =~ /$FAXIDS/i ) { #line contains fax-nrs $rawline =~ s/$FAXID/;/gi ; # substitute all the Fax-Nr with an ; my @fnrs = split(/;/, $rawline); # split the line up between non-allowed digits for ( my $i=0; $i<@fnrs; $i++) { # for all the splitups my $f = $fnrs[$i]; my $goodpart = '([' . $DIGITS . ']*)[^' . $DIGITS . ']*.*$'; $f =~ s/$goodpart/$1/ ; # keep the goodpart $f =~ s/$ModemRejects//g; # remove all the non-modem characters if ( $f gt "" ) { # and if anything is left push @ret, $f; # add it to the return stack } } } else { # if we find a faxnr, take special care my $re = '^.*' . $FAXID; # search for fax-nr $re .= "("; $re .= "[" . $DIGITS . "]*"; # followed by allowed digits $re .= ")"; $re .= "[^" . $DIGITS . ']*.*$'; # followed by non-allowed digits $rawline =~ s/$re/$1/i ; # and extract the allowed part from it $rawline =~ s/$ModemRejects//g; # then remove all the non-modem characters if ( $rawline gt "" ) { # and if anything is left push @ret, $rawline; # add it to the return stack } } } return @ret; } # sub ################################################# sub GetEmailFromDoc { my $result = $mailaddress; # the default return is the existing mailaddress if (@emaillines > 0) { # if there are any emailsadresses found
# take the 1st found only, ignore the rest
# anything after the : is the emailaddress
#(undef, my $em) = split(/$EMAILDOC/, $emaillines[0]);
(undef, my $em1) = split(/$EMAILDOC/, $emaillines[0]);
#Log("pre space em1=",$em1);
# remove trailing and leading spaces
$em1 =~ s/^\s+//, $em1 =~ s/\s+$//;
# $em1 =~ s/^\s*(\S*)\s*$/$1/;
if ($DEBUG) {
Log("Debug: post space strip em1=",$em1);
}
# Log(" second split of em1=",$em1);
(my $em, my $em2) = split(/~/,$em1);
if ($DEBUG) {
Log("Debug: final em = ",$em);
}
# if there is a @ in the middle consider the email address valid
if ($em =~ /\w+@\w+/) {
$result = $em;
}
}
return $result;
}
# sub #################################################
sub GetClientFromDoc {
my $result = $client; # the default return is the existing client name
if (@clientline > 0) { # if there are any client lines found
# take the 1st found only, ignore the rest
# anything after the : is the clientname
#(undef, my $em) = split(/$EMAILDOC/, $emaillines[0]);
(undef, my $cl1) = split(/$CLIENTID/, $clientline[0]);
#Log("pre space cl1=",$cl1);
# remove trailing and leading spaces
$cl1 =~ s/^\s+//, $cl1 =~ s/\s+$//;
# $cl1 =~ s/^\s*(\S*)\s*$/$1/;
if ($DEBUG) {
Log("Debug: post space strip cl1=",$cl1);
}
# The line ends at ~
(my $cl, my $cl2) = split(/~/,$cl1);
if ($DEBUG) {
Log("Debug: final cl = ",$cl);
}
$result = $cl;
}
return $result;
}
# sub #################################################
sub GetSubjectFromDoc {
my $result = $subject; # the default return is the existing subject
if (@subjectline > 0) { # if there are any subject lines found
# take the 1st found only, ignore the rest
# anything after the : is the subject
(undef, my $su1) = split(/$SUBJECTID/, $subjectline[0]);
#Log("pre space su1=",$su1);
# remove trailing and leading spaces.
$su1 =~ s/^\s+//, $su1 =~ s/\s+$//;
# $su1 =~ s/^\s*(\S*)\s*$/$1/;
if ($DEBUG) {
Log("Debug: post space strip su1=",$su1);
}
# The line ends at ~
(my $su, my $su2) = split(/~/,$su1);
if ($DEBUG) {
Log("Debug: final su = ",$su);
}
$result = $su;
}
return $result;
}
# sub #################################################
sub TrySending {
for ( my $i=0; $i<@faxdest; $i++ ) { # for every found faxnumber # compile a commandline # check if file exists if (-e $PSFILE) { my $fcp = "cp " . $PSFILE . " " . $PSTMPFILE; system $fcp; } # transform to pdf, my $pspdf = $PS2PDF . " " . $PSTMPFILE . " " . $PSTMPFILE . ".pdf"; system $pspdf; # execute if ($DEBUG) { # and log it Log($pspdf); } # apply mask, my $wmark = $PDFTK . " " . $WATERMARK . " background " . $PSTMPFILE . ".pdf output " . $PSTMPFILE . "clean.pdf"; system $wmark; #execute if ($DEBUG) { # and log it Log($wmark); } # transform back to ps my $pdfps = $PDF2PS . " " . $PSTMPFILE . "clean.pdf " . $PSFILE; system $pdfps; # execute if ($DEBUG) { # and log it Log($pdfps); } # now send the fax my $fc = $SENDFAX . " -n -R -f " . $mailaddress . " -i \"" . $subject . "\" -d \"" . $client . "@" . $faxdest[$i] . "\" " . $PSFILE ; # my $fc = $SENDFAX . " -n -D -f " . $mailaddress . " -d " . $faxdest[$i] . " " . $PSFILE ; system $fc; # execute it if ($DEBUG) { # and log it Log($fc); } } } # sub ################################################# sub SendErrorMail { my $mh = "\n"; $mh .= "The faxnumber is not recognized in your fax of " . localtime() . "\n"; $mh .= "\n"; $mh .= "The faxnumber is recognised via this text:\n"; $mh .= " Fax-Nr : \n";
$mh .= "\n";
if ( $ALLOWMULTIFAX ) {
$mh .= " or\n";
$mh .= " Fax-Nrs : ; ; ... \n";
$mh .= "\n";
}
$mh .= "The 'Fax-Nr' part is not case sensitive.\n";
$mh .= "The characters allowed in the are: '" . $DIGITS . "'.\n";
$mh .= "\n";
$mh .= "Please correct and retry.\n";
sendmail( To => $mailaddress ,
From => 'Your hylafax gateway',
Subject => 'Your facsimile request failed.',
Message => $mh
);
Log("sent errormail to $mailaddress");
}
# sub #################################################
sub Log {
open LG, ">>" . $LOGFILE;
print LG join(" ", @_), "\n";
close LG;
}
#!/usr/bin/perl -w
# This perl script routes postscript printerdata from printerspooler to fax
#
# copy to /usr/lib/cups/backends/ and run this script from the commandline: echo blah | ./netfax
# it will tell if there are any dependancies unsolved: this tool is dependant upon the following:
# perl (we tested with v5.6 and its likely any v5 will do)
# perl modules Getopt-Long-2.32 and Mail-Sendmail-0.78
# sendfax (from the hylafax package)
# ps2ascii ps2pdf pdf2ps (comes with the ghostscript package)
# pdftk http://www.accesspdf.com/pdftk/
# a mask.pdf file that will hide the command parameters sent at the begining of your page by overlaying a white image
#
# After that you can add new printer to cups: lpadmin -p NetFax -E -v netfax.pl:
# Share the printer in samba and, if your fax server joined the domain, run:
# net -S localhost -U administrator rpc rights grant 'administrator' SePrintOperatorPrivilege
# in smb.conf [printers] section add -J %m to print command (tipically: lpr-cups -P %p -J %m -o raw $s)
# or add cups option = "%m" in the same section and make the drivers share [print$] writable
# Now from windows machine browse the fax server printers, right-click NetFax, choose properties,
# say NO when asked to install drivers, go to Advanced tab, and choose "New Driver". Choose
# some plain PS printer line Apple LaserWriter 12/640 PS and push the drivers to server.
# Now your printer can now be install on all workstations by a vbs script or by using printUI.dll.
#
# The accepted commands, placed at the begining of your faxed document are:
# 'Fax-Nr : XXX-XXXXX;(XXX)XXXXX~' the number can contain dashes or paranthesis. multiple numbers are separated by ;
# 'Clientid : AAAAAA AAAA~' the recipient name
# 'Subjectid : AAAA AAAAAAA~' the message subject
# 'E-m@il : AAA@BBBBBBB~' sender's email. if BBBBBBB matches a different windows machine name
# a winpopup message will be sent to that machine instead of originating machine
#
# Please note that every command line ends by a ~ character!
#
# in order to send a winpopup message add the following lines to notify_mail() function in /var/spool/fax/bin/notify
# HST = `echo $2 | sed -e 's/[^>]*@\([^ ]*\).*/\1/' -e '2.$d'`
# echo $1 | /usr/bin/smbclient -M $HST
#
# neXt - sorin@xxxxxxxx.com - June-2010
#
use strict;
use Getopt::Long;
use Mail::Sendmail;
# constants you must check if they are ok
my $ALLOWMULTIFAX = 1; # allow (1) or not (0) multiple faxdestinations
my $EMAILFROMDOC = 1; # get the emailaddress from samba (0) or the doc (1)
my $SENDFAX = "/usr/bin/sendfax"; # the command to send a fax
my $PS2ASCII = "/usr/bin/ps2ascii"; # the command to convert postscript to readable text
my $PS2PDF = "/usr/bin/ps2pdf"; # transform ps to pdf
my $PDFTK = "/usr/bin/pdftk"; # modify pdfs - used to overlay the mask over commands section
my $PDF2PS = "/usr/bin/pdf2ps"; # transform pdf back to ps
my $WATERMARK = "/etc/initsetup/mask.pdf"; # location of the overlay mask
# constants you can alter but should consider not to
my $TMPDIR = "/tmp/"; # the directory to store temporary files
my $MYNAME = "netfax"; # the name of this tool
my $LOGFILE = $TMPDIR . $MYNAME . ".log"; # the name of the logfile - debugging sessions only
my $PSFILE = $TMPDIR . $MYNAME . $$ . ".ps" ; # the name of the postscript temporary file
my $PSTMPFILE = $TMPDIR . $MYNAME . $$ . "work.ps" ; # the name of the postscript temporary file
my $MAILADDRESS = 'faxadmin@hfax'; # the default mailaddress for errormessages
my $MULTISEP = ";"; # if you have more than 1 faxnr on a line, they are seperated by ;
# this character should NOT appear in $DIGITS
my $DEBUG=0;
# constants you really should not touch !!!
my $FAXID = 'Fax-Nr[s]{0,1}\s*:\s*'; # search string for fax-nr
my $FAXIDS = 'Fax-Nrs\s*:\s*'; # search string for fax-nrs ( for multifax }
my $DIGITS = '0123456789+( ),-'; # digits allowed in the faxnr
my $MODEMLIKES = '0123456789+,'; # digits my modem will not reject: ,=wait +=int.access
# this should be a subset of $DIGITS
my $EMAILDOC = 'E-m@il :'; # the string to look for an emailaddress
my $CLIENTID = 'Clientid :'; # this is the recipient name
my $SUBJECTID = 'Subjectid :'; # the line with subject must contain this
########## from here on, leave the code alone, unless you are really sure ############
#variables
my @faxlines; # stores the raw faxlines
my @faxdest; # stores the faxnumbers
my $MultiFax = 0; # determines if ENDuser specified to multifax
my $mailaddress = ""; # how do we treat the errormessages
my $lpuser = ""; # username retrieved from lprng or lpd commandline
my $lphost = ""; # hostname retrieved from lprng or lpd commandline
my $client = " "; # the client name
my $subject = " "; # the message subject
my @emaillines; # stores the documentlines containing EMAILDOC
my @clienthost; # stores the temporary sender hostname
my @clientline; # stores the client name line
my @subjectline; # stores the subject line
#Check for arguments - if none, cups is initialising
if (@ARGV == 0) {
exit 0;
}
# check some dependencies
if ( ! -d $TMPDIR ) {
print("Error: temporary directory not found: ", $TMPDIR );
exit 1;
}
if ( ! -e $SENDFAX ) {
Log("Error: sendfax command not found: ", $SENDFAX );
exit 1;
}
if ( ! -e $PS2ASCII ) {
Log("Error: ghostscript command not found: ", $PS2ASCII );
exit 1;
}
# get usefull parameters
my $cupsfile = $ARGV[5]; # CUPS parses a filename with the printdata as the 6th parameer
# this could be undef (after lpr -d blah) or a filename (after a samba action)
my $cupsuser = $ARGV[1]; # CUPS paresed the username with the printdata as the 2nd parameter
# this is usually a user from localhost
GetOptions( 'h=s' => \$lphost, # LPD and LPRng parse host and user name under the -h and -n parameter
'n=s' => \$lpuser); # the postscript is parsed to it in a pipe - to be found in STDIN
my $fullhost = $ARGV[4]; #hostname is found here because in smb.conf I've added -P %m on print command
# let's extract the hostname in order to be added to email address
@clienthost = split(/\s+/,$fullhost);print $clienthost[0];
my $finalhost = $clienthost[0];
# ok lets find out where we can send the mail to
if ( ( $lphost ) and ( $lpuser ) ) { #if the user and host can be found on the commandline
$mailaddress = $lpuser . '@' . $lphost ;
} elsif ( $cupsuser) {
$mailaddress = $cupsuser . '@' . $finalhost ; # create "email" from user+hostname
} else {
$mailaddress = $MAILADDRESS; # or use the E-m@il defined in doc
}
# where is the printerdata?
if ( ( $cupsfile ) and ( -e $cupsfile ) ) {
$PSFILE = $cupsfile;
} else {
&SavePostscriptdata;
}
if ($DEBUG) {
Log("");
Log("------------------------------------------");
Log("");
}
# ok we have a postscriptfile, now
if ( &RetrieveRawFaxline ) { # we found one ore more lines
if ( &ExtractFaxnumber ) { # we could extract a real faxnumber
$client = &GetClientFromDoc; # get the Client Id
$subject = &GetSubjectFromDoc; # Get the Subject
if ($EMAILFROMDOC) {
$mailaddress = &GetEmailFromDoc; # Get the email from doc
}
if ($DEBUG) {
Log("Debug: email address = ",$mailaddress);
Log("Debug: postscript file = ",$PSFILE);
Log("Debug: cups file = ",$cupsfile);
}
&TrySending; # mask the header and send the fax
} else { # no real faxnumber could be extracted
&SendErrorMail;
Log("No Fax Number extracted");
}
} else { # no lines with faxnr found
&SendErrorMail;
Log("No Fax-Nr found");
}
# delete the temporary printfiles in case DEBUG is off
if (!$DEBUG) {
unlink $PSFILE;
unlink $PSTMPFILE;
unlink $PSTMPFILE . ".pdf";
unlink $PSTMPFILE . "clean.pdf";
}
Log("End of task");
# always exit gracefully.
exit 0;
# sub #################################################
# save the information in the pipe to the ps tmp file
sub SavePostscriptdata {
Log("sub SavePostscriptData");
open PS, ">".$PSFILE or die("Sorry, cannot open temporary postscript file $PSFILE .\n");
while (
print PS $_ ;
}
close PS;
}
# sub #################################################
sub RetrieveRawFaxline {
my $CL = $PS2ASCII . " " . $PSFILE . " |";
my $ret = 0;
open CL, $CL; # carry out ps2ascii on the ps-file and return the output into perl
while (my $line=
chomp $line;
if ($line =~ /$FAXID/i) { # if the rawline matches with fax-nr
push @faxlines, $line ; # add it to the stack of matching lines
$ret++;
}
if ($line =~ /$FAXIDS/i) { # if the rawline matches with fax-nrs
$MultiFax = 1; # the userties to multifax
}
if ($line =~ /$CLIENTID/i) { # if the rawline matches with clientid
push @clientline, $line ; # add it to the stack of matching lines
if ($DEBUG) {
Log("Debug: clientline added - ",$line);
}
}
if ($line =~ /$SUBJECTID/i) { # if the rawline matches with subjectid
push @subjectline, $line ; # add it to the stack of matching lines
if ($DEBUG) {
Log("Debug: subjectline added - ",$line);
}
}
if ($line =~ /$EMAILDOC/i) { # if the rawline matches with "email"
push @emaillines, $line; # add it to the emailstack
if ($DEBUG) {
Log("Debug: emailline added - ",$line);
}
}
}
close CL;
# check the multifax setting
$MultiFax = $ALLOWMULTIFAX if $MultiFax; # ALLOWMULTIFAX overrides Multifax
return $ret;
}
# sub #################################################
sub ExtractFaxnumber {
my $ret = 0; # return value: 0=nothing found, more=ok
if ( $MultiFax ) { # extract all the faxnumbers you can find
for ( my $i=0; $i<@faxlines; $i++) { # for all the rawline push @faxdest, &GetFaxNumbersFrom($faxlines[$i]); #extract the numbers } $ret = @faxdest; } else { # just extract the first faxnumber in the first line my @fns = &GetFaxNumbersFrom($faxlines[0]); # extract the numbers from the first raw line if ( defined $fns[0] ) { # if it exists push @faxdest, $fns[0]; # put it on the return stack $ret++; } } return $ret; } # sub ################################################# sub GetFaxNumbersFrom { my @ret = (); my $rawline = shift; if ( defined $rawline ) { my $ModemRejects = "[^" . $MODEMLIKES . "]"; # regexp with non-modem chars if ( $rawline =~ /$FAXIDS/i ) { #line contains fax-nrs $rawline =~ s/$FAXID/;/gi ; # substitute all the Fax-Nr with an ; my @fnrs = split(/;/, $rawline); # split the line up between non-allowed digits for ( my $i=0; $i<@fnrs; $i++) { # for all the splitups my $f = $fnrs[$i]; my $goodpart = '([' . $DIGITS . ']*)[^' . $DIGITS . ']*.*$'; $f =~ s/$goodpart/$1/ ; # keep the goodpart $f =~ s/$ModemRejects//g; # remove all the non-modem characters if ( $f gt "" ) { # and if anything is left push @ret, $f; # add it to the return stack } } } else { # if we find a faxnr, take special care my $re = '^.*' . $FAXID; # search for fax-nr $re .= "("; $re .= "[" . $DIGITS . "]*"; # followed by allowed digits $re .= ")"; $re .= "[^" . $DIGITS . ']*.*$'; # followed by non-allowed digits $rawline =~ s/$re/$1/i ; # and extract the allowed part from it $rawline =~ s/$ModemRejects//g; # then remove all the non-modem characters if ( $rawline gt "" ) { # and if anything is left push @ret, $rawline; # add it to the return stack } } } return @ret; } # sub ################################################# sub GetEmailFromDoc { my $result = $mailaddress; # the default return is the existing mailaddress if (@emaillines > 0) { # if there are any emailsadresses found
# take the 1st found only, ignore the rest
# anything after the : is the emailaddress
#(undef, my $em) = split(/$EMAILDOC/, $emaillines[0]);
(undef, my $em1) = split(/$EMAILDOC/, $emaillines[0]);
#Log("pre space em1=",$em1);
# remove trailing and leading spaces
$em1 =~ s/^\s+//, $em1 =~ s/\s+$//;
# $em1 =~ s/^\s*(\S*)\s*$/$1/;
if ($DEBUG) {
Log("Debug: post space strip em1=",$em1);
}
# Log(" second split of em1=",$em1);
(my $em, my $em2) = split(/~/,$em1);
if ($DEBUG) {
Log("Debug: final em = ",$em);
}
# if there is a @ in the middle consider the email address valid
if ($em =~ /\w+@\w+/) {
$result = $em;
}
}
return $result;
}
# sub #################################################
sub GetClientFromDoc {
my $result = $client; # the default return is the existing client name
if (@clientline > 0) { # if there are any client lines found
# take the 1st found only, ignore the rest
# anything after the : is the clientname
#(undef, my $em) = split(/$EMAILDOC/, $emaillines[0]);
(undef, my $cl1) = split(/$CLIENTID/, $clientline[0]);
#Log("pre space cl1=",$cl1);
# remove trailing and leading spaces
$cl1 =~ s/^\s+//, $cl1 =~ s/\s+$//;
# $cl1 =~ s/^\s*(\S*)\s*$/$1/;
if ($DEBUG) {
Log("Debug: post space strip cl1=",$cl1);
}
# The line ends at ~
(my $cl, my $cl2) = split(/~/,$cl1);
if ($DEBUG) {
Log("Debug: final cl = ",$cl);
}
$result = $cl;
}
return $result;
}
# sub #################################################
sub GetSubjectFromDoc {
my $result = $subject; # the default return is the existing subject
if (@subjectline > 0) { # if there are any subject lines found
# take the 1st found only, ignore the rest
# anything after the : is the subject
(undef, my $su1) = split(/$SUBJECTID/, $subjectline[0]);
#Log("pre space su1=",$su1);
# remove trailing and leading spaces.
$su1 =~ s/^\s+//, $su1 =~ s/\s+$//;
# $su1 =~ s/^\s*(\S*)\s*$/$1/;
if ($DEBUG) {
Log("Debug: post space strip su1=",$su1);
}
# The line ends at ~
(my $su, my $su2) = split(/~/,$su1);
if ($DEBUG) {
Log("Debug: final su = ",$su);
}
$result = $su;
}
return $result;
}
# sub #################################################
sub TrySending {
for ( my $i=0; $i<@faxdest; $i++ ) { # for every found faxnumber # compile a commandline # check if file exists if (-e $PSFILE) { my $fcp = "cp " . $PSFILE . " " . $PSTMPFILE; system $fcp; } # transform to pdf, my $pspdf = $PS2PDF . " " . $PSTMPFILE . " " . $PSTMPFILE . ".pdf"; system $pspdf; # execute if ($DEBUG) { # and log it Log($pspdf); } # apply mask, my $wmark = $PDFTK . " " . $WATERMARK . " background " . $PSTMPFILE . ".pdf output " . $PSTMPFILE . "clean.pdf"; system $wmark; #execute if ($DEBUG) { # and log it Log($wmark); } # transform back to ps my $pdfps = $PDF2PS . " " . $PSTMPFILE . "clean.pdf " . $PSFILE; system $pdfps; # execute if ($DEBUG) { # and log it Log($pdfps); } # now send the fax my $fc = $SENDFAX . " -n -R -f " . $mailaddress . " -i \"" . $subject . "\" -d \"" . $client . "@" . $faxdest[$i] . "\" " . $PSFILE ; # my $fc = $SENDFAX . " -n -D -f " . $mailaddress . " -d " . $faxdest[$i] . " " . $PSFILE ; system $fc; # execute it if ($DEBUG) { # and log it Log($fc); } } } # sub ################################################# sub SendErrorMail { my $mh = "\n"; $mh .= "The faxnumber is not recognized in your fax of " . localtime() . "\n"; $mh .= "\n"; $mh .= "The faxnumber is recognised via this text:\n"; $mh .= " Fax-Nr :
$mh .= "\n";
if ( $ALLOWMULTIFAX ) {
$mh .= " or\n";
$mh .= " Fax-Nrs :
$mh .= "\n";
}
$mh .= "The 'Fax-Nr' part is not case sensitive.\n";
$mh .= "The characters allowed in the
$mh .= "\n";
$mh .= "Please correct and retry.\n";
sendmail( To => $mailaddress ,
From => 'Your hylafax gateway
Subject => 'Your facsimile request failed.',
Message => $mh
);
Log("sent errormail to $mailaddress");
}
# sub #################################################
sub Log {
open LG, ">>" . $LOGFILE;
print LG join(" ", @_), "\n";
close LG;
}
Saturday, June 19, 2010
Replacing a failing software raid drive in 10 easy steps
Un post de acum 3-4 ani pe care unul din amicii de la birou n-a fost in stare sa-l gasesca pe board-ul intern:
1 - cat /proc/mdstat and check for referrences to failing device
(sda = first sata hdd, sdb = the second one, so on...) the failed
partition should be something like /dev/sdb5 (I'm goin to refer to this
partition as /dev/sdYn and I'm going to call the good one /dev/sdXn)
2 - fdkisk -l /dev/sdX (where sdX is the GOOD hdd); fdisk -l /dev/sdY
- take a note of all partition configuration
3 - remove failed hdd: mdadm --manage /dev/md0 --fail /dev/sdYn ;
mdadm --manage /dev/md0 --remove /dev/sdYn (/dev/sdYn is the failed device!)
4 - phisically replace hdd (maybe with a shutdown before? :-) )
5 - sfdisk -d /dev/sdX | sfdisk /dev/sdY will create identical partitions
on the new hdd, similar to the ones on the good hdd (usually a /boot
of 100MB as primary partition and the rest as extended type FD "Linux
raid autodetect")
6 - check if the partitions are identical: fdkisk -l /dev/sdY
(compare with what you read at step 2)
7 - mdadm --manage /dev/md0 --add /dev/sdYn will add the new
partition tothe raid array
8 - watch the rebuid procedure: watch -n 10 cat /proc/mdstat (if
you are bored type ^C - the rebuid is done anyway)
9 - in order to make a copy of the boot partition too, do a mount
/dev/sdY1 /boot2 (the first partition is usually the 100MB /boot), then
do acd /boot ; find . -depth -print | cpio -padmV /boot2 ; grub-install /dev/sdY
10 - enjoy a beer, you have a working raid again!
1 - cat /proc/mdstat and check for referrences to failing device
(sda = first sata hdd, sdb = the second one, so on...) the failed
partition should be something like /dev/sdb5 (I'm goin to refer to this
partition as /dev/sdYn and I'm going to call the good one /dev/sdXn)
2 - fdkisk -l /dev/sdX (where sdX is the GOOD hdd); fdisk -l /dev/sdY
- take a note of all partition configuration
3 - remove failed hdd: mdadm --manage /dev/md0 --fail /dev/sdYn ;
mdadm --manage /dev/md0 --remove /dev/sdYn (/dev/sdYn is the failed device!)
4 - phisically replace hdd (maybe with a shutdown before? :-) )
5 - sfdisk -d /dev/sdX | sfdisk /dev/sdY will create identical partitions
on the new hdd, similar to the ones on the good hdd (usually a /boot
of 100MB as primary partition and the rest as extended type FD "Linux
raid autodetect")
6 - check if the partitions are identical: fdkisk -l /dev/sdY
(compare with what you read at step 2)
7 - mdadm --manage /dev/md0 --add /dev/sdYn will add the new
partition tothe raid array
8 - watch the rebuid procedure: watch -n 10 cat /proc/mdstat (if
you are bored type ^C - the rebuid is done anyway)
9 - in order to make a copy of the boot partition too, do a mount
/dev/sdY1 /boot2 (the first partition is usually the 100MB /boot), then
do acd /boot ; find . -depth -print | cpio -padmV /boot2 ; grub-install /dev/sdY
10 - enjoy a beer, you have a working raid again!
Saturday, March 13, 2010
Spamfilter 2.0 - teoria initiala
Se implinesc in curand 4 ani de cand a inceput istoria asta. Acum 4 ani m-am apucat sa fac primul filtru antispam si habar n-aveam la ce ma inham (nu ca celelalte proiecte, care au venit dupa ar fi fost mai usoare, dimpotriva, da' inceputu' e intotdeauna mai greu). Dupa 4 ani filtru' meu inca e in topul celor mai bune din lume, blocand in medie cam 97% din spam, dar pe masura ce trece timpul, apar tot mai evidente limitarile versiunii 1,x, printre care lipsa unei metode de a permite fiecarui user sa-si gereze individual propriile mesaje, fara necesitatea unui admin, viteza foarte mica de raspuns in cazul cautarilor in mesajele din carantina, structura multi-layer, data de faptul ca am tot facut adaugiri la software-ul initial, dar nu am facut o reala integrare, ci am tot adaugat filtre unul in fata celuilalt - care poate induce intarzieri de pana la 5 minute in prelucrare (cu tot cu greylisting) si nu permite managementul centralizat al exceptiilor. Astfel, in versiunea 1.x, am ajuns sa am o lista de exceptii in postgrey, una in postfix si alta in spamd, iar lista din postgrey nici macar nu are o interfata web de management! Foarte important e si suportul de solidstate disk, care in v1 o cam suge rau de tot (se vede clar ca e adaugat dupa si mi-a dat cele mai multe batai de cap dealtfel).
Sigur, am si parti bune in 1.x, pe care le voi copia in v2, printre care: autoupdate/push updates, remote services monitoring, redir, call-home licensing...
Voi pastra combinatia postfix-spamassassin ca si structura de baza, dar proabil ca voi muta toata configuratia si storage-ul intr-o baza de date. Bazat pe scriptul de getuser probabil, voi crea o metoda autentificare a userilor la serverul principal de mail daca e exchange, iar pentru un server unix va trebui sa descopar cum imi pot autentifica userii la serverul pop3 - in felul asta nu am nevoie de alte combinatii user/parola pentru managementul mesajelor in carantina.
Trebuie sa fie posibil sa transfer bazele de date postgey si baesyan (actualmente berkleydb) in noul sistem, pen' ca sigur o sa trebuiasca sa upgradez din vechile sisteme sia ar fi bine sa pastrez rata mare de detectie pe care o am deja.
Trebuie sa investighez daca nu cumva cramfs/alt_filesystem_read_only in combinatie cu unionfs nu e o solutie mai buna pentru SSD-uri sau USB-flashuri (care actualmente sunt super-lente, iar pe masini cu >1mil de spamuri/luna crapa execrabil cu ext3fs chiar daca am mutat /tmp in ram si am limitat drastic scrierile pe disk).
Ca o ultima idee ar fi sa mut /etc/initsetup-ul intr-o interfata web, scapand astfel de nevoia initiala de a avea kbd+screen pentru instatalare si permitandu-mi poate sa modific cutia in ceva gen router cu doar un port rj45, un powercord si un powerbutton.
Edit: beta 1 is out! working on bug fixes now.
Edit2: spamfilter2, codename "miserable failure" is retired. let's welcome SpamFilter3!
Sigur, am si parti bune in 1.x, pe care le voi copia in v2, printre care: autoupdate/push updates, remote services monitoring, redir, call-home licensing...
Voi pastra combinatia postfix-spamassassin ca si structura de baza, dar proabil ca voi muta toata configuratia si storage-ul intr-o baza de date. Bazat pe scriptul de getuser probabil, voi crea o metoda autentificare a userilor la serverul principal de mail daca e exchange, iar pentru un server unix va trebui sa descopar cum imi pot autentifica userii la serverul pop3 - in felul asta nu am nevoie de alte combinatii user/parola pentru managementul mesajelor in carantina.
Trebuie sa fie posibil sa transfer bazele de date postgey si baesyan (actualmente berkleydb) in noul sistem, pen' ca sigur o sa trebuiasca sa upgradez din vechile sisteme sia ar fi bine sa pastrez rata mare de detectie pe care o am deja.
Trebuie sa investighez daca nu cumva cramfs/alt_filesystem_read_only in combinatie cu unionfs nu e o solutie mai buna pentru SSD-uri sau USB-flashuri (care actualmente sunt super-lente, iar pe masini cu >1mil de spamuri/luna crapa execrabil cu ext3fs chiar daca am mutat /tmp in ram si am limitat drastic scrierile pe disk).
Ca o ultima idee ar fi sa mut /etc/initsetup-ul intr-o interfata web, scapand astfel de nevoia initiala de a avea kbd+screen pentru instatalare si permitandu-mi poate sa modific cutia in ceva gen router cu doar un port rj45, un powercord si un powerbutton.
Edit: beta 1 is out! working on bug fixes now.
Edit2: spamfilter2, codename "miserable failure" is retired. let's welcome SpamFilter3!
Sunday, February 14, 2010
Laptop brightness
Elitebook-ul meu nu vrea sa mapeze Fn+F9 / Fn+F10 pentru brightness down/up. Fn+F11 merge (light sensor), dar F9 si F10 nu. Nici macar in xev nu apare nimic. Kde power management in schimb modifica brightness-ul in functie de power-profile pe care il aplica, e doar o problema de key-mapping. Mai mult, un echo 1-10 in /sys/class/backlight/acpi_video0/brightness imi schimba brightness-ul, deci tot ce am de facut e sa mapez miste taste care sa trimita un +1 / -1 in /sys/class/backlight/acpi_video0/brightness Nu pot face asta direct dintr-un script pentru ca va trebui sa-l fac suid root, iar mai nou (http://en.wikipedia.org/wiki/Setuid#setuid_on_executables ) nu prea mai poti sa suid un script. Sa scriem deci un programel care sa poata fi suid root.
sa-l salvam undeva in path cu numele brightness si acum putem mapa niste taste in kde care sa-l apeleze:

Iar ca si command scriem:


Evident, trebuie mapata o combinatie si pentru Brightness up, care va face +1 in loc de -1 in comanda.
#include
void usage()
{
fprintf(stderr, "Usage: lcd-brightness [value]\n");
}
int main(int argc, char *argv[])
{
FILE *fp;
int bright = 0;
const char *kFileName =
"/sys/class/backlight/acpi_video0/brightness";
switch (argc) {
case 1:
fp = fopen(kFileName, "r");
fscanf(fp, "%d", &bright);
printf("%d\n", bright);
break;
case 2:
fp = fopen(kFileName, "w");
bright = atoi(argv[1]);
fprintf(fp, "%d\n", bright);
break;
default:
usage();
return -1;
}
fclose(fp);
return 0;
}
sa-l salvam undeva in path cu numele brightness si acum putem mapa niste taste in kde care sa-l apeleze:

Iar ca si command scriem:
brightness $(expr $(brightness) - 1); kdialog
--passivepopup "Decrease Brightness to `cat
/sys/class/backlight/acpi_video0/brightness`" 1
- asta va da un frumos notification pop-up cand este apelat:

Evident, trebuie mapata o combinatie si pentru Brightness up, care va face +1 in loc de -1 in comanda.
Sunday, February 07, 2010
Another Backup
Versiunea care foloseste tar (pentru ca cpio din debilian moare cand ti-e lumea mai draga si nu vreau sa pun cpio din surse)
#!/bin/sh # @(#) AUTOTBACK 2.8 09/12/09 # # 09/12/2009 (sorin@xxxxxxxx.com) mod for debian5. remove hit report. changed to use TAR # 28/08/2008 (sorin@xxxxxxxx.com) modified for rhel5. skip /proc /sys /tmp # modified 9/14/2000 to provide hit reporting on web site # # Usage -Command to be incorporated in cron of root for off Peak # automatic system TAR Backup. # Generates report in /var/autotback directory, mail and prints it. # # ####### Define Local Variables ################ RECIPIENT1=service@xxxxxxxx.com RECIPIENT2=sorin@xxxxxxxx.com PRINTER=HP4050 TAPE=/dev/st0 BACKDIR=/ EXCLUDE=/sys/* EXCLUDE1=/proc/* EXCLUDE2=/dev/* EXCLUDE3=/var/run/* EXCLUDE4=/tmp/* ############################################### # System variables LOCK=/var/autotback/backlock DEFAULTDIR=/var/autotback REPORTFILE=/var/autotback/backrep TEMPFILE=/var/autotback/backtmp TEMPFILE2=/var/autotback/backtmp2 ALLIST=/var/autotback/allist LIST=/var/autotback/list ERRORMSG="Another backup is running or the last backup has not finished well. Please check" DELIMIT="================================================================================" # define a remove lock and set a trap on exit remove_lock() { rm -f $LOCK } # make sure we release the lock no matter how we exit, when we exit trap remove_lock 0 # Check if another backup is running or if the script crashed in such way that the lock is still there, clear the lock if [ -r $LOCK ] then DIFF=`echo "\`date +%s\`-\`cat $LOCK\`" | bc` if [ $DIFF -gt 86400 ]; then echo "More than one day since backup is NOT running, autoclean..." >> $REPORTFILE; rm -f $LOCK; fi sed -i -e "1i\ $ERRORMSG" -e "1i\ $DELIMIT" -e "1i\ " $REPORTFILE echo $ERRORMSG >> $REPORTFILE echo $REPORTFILE | mail -s "Backup Failure on $HOSTNAME" $RECIPIENT1 $RECIPIENT2 lp -d $PRINTER $REPORTFILE exit 5 fi # Cleanup obsolete traces cd $BACKDIR rm -rf $DEFAULTDIR if [ ! -d $DEFAULTDIR ] then mkdir -p $DEFAULTDIR fi # Create lockfile echo "`date +%s`">$LOCK # Start backup echo " Automatic Backup Report (c)1991-2010 Xxxxxxxx Xxxxxxxxx Inc. $DELIMIT Backup of $BACKDIR on $HOSTNAME started at `date` ">>$REPORTFILE # Create a list of what we have to backup and exclude #cd $BACKDIR #find . -depth -print >$ALLIST #grep -vE ".$EXCLUDE|.$EXCLUDE1|.$EXCLUDE2|.$EXCLUDE3|.$EXCLUDE4" $ALLIST >$LIST echo "BACKUP started on `date`">$TEMPFILE # Start saving at the begining of the tape mt -f $TAPE rewind 2>>$TEMPFILE2 #cat $LIST | cpio -ocvB >$TAPE 2>>$TEMPFILE tar --exclude=$EXCLUDE --exclude=$EXCLUDE1 --exclude=$EXCLUDE2 --exclude=$EXCLUDE3 --exclude=$EXCLUDE4 -cvpf $TAPE $BACKDIR >>$TEMPFILE 2>>$TEMPFILE2 backstat=$? tail $TEMPFILE2 >>$REPORTFILE echo " Exit status = $backstat ">>$REPORTFILE if [ $backstat -eq 0 ] then echo "*** Backup COMPLETED OK ***">>$REPORTFILE fi if [ $backstat -eq 1 ] then echo "*** Backup may be incomplete or have missing files ***">>$REPORTFILE fi if [ $backstat -eq 2 ] then echo "*** Backup has encounter a fatal error. Please check ***">>$REPORTFILE fi echo "Tape Save finished on `date` $DELIMIT ">>$REPORTFILE # Check total nr of blocks reported by cpio #set `tail -1 $TEMPFILE` #BACKTOT=$1 #echo "Total of amount of Backup was $1 blocks. echo "Verify of $BACKDIR on $HOSTNAME started at `date` ">>$REPORTFILE # Tape rewind / Verify mt -f $TAPE rewind 2>>$TEMPFILE2 # cpio -icvtB <$TAPE >>$TEMPFILE 2>>$TEMPFILE2 tar --exclude=$EXCLUDE --exclude=$EXCLUDE1 --exclude=$EXCLUDE2 --exclude=$EXCLUDE3 --exclude=$EXCLUDE4 --exclude=$EXCLUDE -tpvf $TAPE >>$TEMPFILE 2>>$TEMPFILE2 verstat=$? tail $TEMPFILE2 >>$REPORTFILE echo " Exit status = $verstat ">>$REPORTFILE if [ $verstat -eq 0 ] then echo "*** Verify COMPLETED OK *** ">>$REPORTFILE if [ $verstat -eq 1 ] then echo "*** Verify may be incomplete *** ">>$REPORTFILE if [ $verstat -eq 2 ] then echo "*** Verify has encounter a fatal error. Please check *** ">>$REPORTFILE cat $TEMPFILE >> $REPORTFILE fi echo "Tape Verify finished on `date` ">>$REPORTFILE # Check nr of verified blocks reported by cpio and send warning if not ok #set `tail -1 $TEMPFILE2` #VERTOT=$1 #if [ "$BACKTOT" != "$VERTOT" -o $backstat -ne 0 -o $verstat -ne 0 ] #then # echo "*** WARNING BACKUP TRANSFER TOTALS DID NOT MATCH ***">>$REPORTFILE # echo "*** PLEASE VERIFY *** # ">>$REPORTFILE #else # echo "*** Transfer Totals Concur *** # ">>$REPORTFILE #fi echo $DELIMIT >>$REPORTFILE # Send / Print the report cat $REPORTFILE | mail -s "Backup Report $HOSTNAME" $RECIPIENT1 $RECIPIENT2 lp -d $PRINTER $REPORTFILE # Remove lock, eject and exit sleep 5 rm -f $LOCK mt -f $TAPE rewoffl 2>>$TEMPFILE2 exit 0
Subscribe to:
Posts (Atom)