Useful scripts

graudeejs

Son of Beastie

Reaction score: 694
Messages: 4,615

Code:
#!/usr/bin/perl

use warnings;
use strict;
package wrapper;

if (defined $ARGV[0]) {
    $ARGV[0] =~ s/%([[:xdigit:]]{2})/pack('c', hex($1))/ge;
    if ($ARGV[0] =~ /^mailto:/) {
        my $email;
        my $subject;
        if ($ARGV[0] =~ /\?subject=.*/) {
            ($email, $subject) = $ARGV[0] =~ /^mailto:(.*)\?subject=(.*)/;
#            system("FvwmCommand \"Function Start_Mailer -s '$subject' -- '$email'\"");
            system("urxvtc -e mutt -s '$subject' -- '$email'");
        } else {
            ($email) = $ARGV[0] =~ /^mailto:(.*)/;
#            system("FvwmCommand \"Function Start_Mailer -- '$email'\"");
            system("urxvtc -e mutt -- '$email'");
        }
    }   
    elsif ($ARGV[0] =~ /^irc:\/\//) {
        my $addr;
        my $port;
        ($addr, $port) = $ARGV[0] =~ /^irc:\/\/(.*):\+(\d{1,5})/;
#        system("FvwmCommand 'Function Start_chat --connect=$addr --port=$port '");
        system("urxvtc -e irssi --connect=$addr --port=$port");
    }   
}   
exit;
Here's my little wrapper scipt I just wrote.
I commented out original lines that I use (fvwm & my config specific) and replaced them with more generic lines

replace urxvtc with any terminal that you use.

you can use this wrapper with firefox. In Application preferences, where you can select default apps for various things, for mailto: and irc: you can select this wrapper script.
It will launch mutt or irssi in virtual terminal on X, when you click on link (either mailto:... or irc:...)

I think it's pretty useful.
Of course you can customize to use it for other email/irc clients, and even extend it's usage to IM....

Hope you like it ;)


P.S.
Thanks to SirDice for this post

EDIT:
one more thing... Why I like it?
Because If I have to reply to some pr, I don't have to fill to: and subject lines....
subject line was pain for me with previous wrapper


EDIT:
fixed bug
 

pat

New Member

Reaction score: 1
Messages: 11

tangram said:
Do you use this as a standalone script that you run before rebuilding your kernel or world? Or do place this on make.conf?

I'm asking this because I also apply 2 patches to /usr/src and wanted to reapply the patches whenever I synchronize sources.
Actually it's only a shell function (minus the header).
I would just love to see something like this properly implemented in make.conf.
 

Ruler2112

Well-Known Member

Reaction score: 25
Messages: 422

I'm cross-posting to this thread, as the script I wrote may well be of use to somebody for a different purpose. I intentionally wrote it to be as generic as possible. Basically, it will update a local file to that of a network copy, based on whatever you set the variables to. It'll also keep the n most recent backups of the file downloaded. You can see it as part of the 'Emerging Threats' thread.
 

ohauer

Active Member

Reaction score: 17
Messages: 127

DutchDaemon said:
/usr/sbin/portsnap update || exit 1
cd /usr/ports || exit 1
make fetchindex || exit 1
Is there a special reason for
Code:
cd /usr/ports || exit 1
make fetchindex || exit 1
since portsnap has already updated the index file to match the current portsnap.
 

DutchDaemon

Administrator
Staff member
Administrator
Moderator
Developer

Reaction score: 2,792
Messages: 11,283

Yeah, that script has seen quite a few lifecycles and organic development (cvsup -> csup -> portsnap, portupgrade -> portmaster), and there may be some superfluous stuff in it. I'll give it a slight overhaul.
 

tuan

New Member


Messages: 6

Hello,

I tried to reuse your script, and changed just one thing, but for some reason, my modification is not correct: I need to su on the remote machine before copying the keys, but when I enter the password for su, the remote machine does not accept it. Does anyone have an idea by chance ?

Your original script was :

Code:
#!bin/sh

HOSTS="host1 host2 host3"

KEYFILE=id_rsa # careful, change to not overwrite default!
PRVKEYFILE=~/.ssh/${KEYFILE}
PUBKEYFILE=${PRVKEYFILE}.pub
TMPKEY=${KEYFILE}.tmp

ssh-keygen -b 2048 -t rsa -f $PRVKEYFILE

for HOST in $HOSTS; do
  echo $HOST ###
  scp ${PUBKEYFILE} ${HOST}:~/${TMPKEY} && echo OK && \
    ssh ${HOST} "cat ${TMPKEY} >> ~/.ssh/authorized_keys && rm ~/${TMPKEY}" && echo OK
done
and I just added (in bold) :

Code:
for HOST in $HOSTS; do
  echo $HOST ###
  scp ${PUBKEYFILE} ${HOST}:~/${TMPKEY} && echo OK && \
    ssh ${HOST} [B]"su" && echo OK[/B] && "cat ${TMPKEY} >> ~/.ssh/authorized_keys && rm ~/${TMPKEY}" && echo OK
 

Ruler2112

Well-Known Member

Reaction score: 25
Messages: 422

I just posted a script I wrote intended to be used by people who run mail servers to detect when somebody tries a brute-force method to guess passwords. Thought I should link it in here for completeness.
 

ta0kira

Active Member

Reaction score: 22
Messages: 157

In bash I use alias recall='history | egrep' so that I can do something like recall ssh. Not sure if there's a build-in way to do that.
Kevin barry
 

DutchDaemon

Administrator
Staff member
Administrator
Moderator
Developer

Reaction score: 2,792
Messages: 11,283

ta0kira said:
In bash I use alias recall='history | egrep' so that I can do something like recall ssh. Not sure if there's a build-in way to do that.
Kevin barry
Bash has reverse history searching:

ctl-r ssh

will give you the last history entry containing 'ssh', and every subsequent ctl-r will give you the one before that.
 

ta0kira

Active Member

Reaction score: 22
Messages: 157

DutchDaemon said:
Bash has reverse history searching:

ctl-r ssh

will give you the last history entry containing 'ssh', and every subsequent ctl-r will give you the one before that.
Thanks. I use ! quite a bit, but I ssh to a lot of different places, calling a lot of different remote commands, so it's nice to see all of them at once.
Kevin Barry
 

graudeejs

Son of Beastie

Reaction score: 694
Messages: 4,615

I wrote this script to scan files MUCH faster....
It was inspired by one-liner that I wrote for my GF to scan 47 pages.
She scanned them in about 15 min

You can export files to different format, and set starting counter... Very useful if you scan more than 2 days same book for example

I think many of you will find this script very useful

Code:
#!/bin/sh

if [ "$1" = "--help" ]; then
	cat << EOF
USAGE: 
  `basename $0` [file_format [start_page]]

WHERE:
  file_format   is any format supported by ImageMagick (default jpg)
  start_page    is used to set counter (default 0)
EOF
	exit 0
fi

Format=${1:-"jpg"}
i=${2:-"0"}

while read -p 'Press Enter to scan. Press q and then Enter to stop  ' a && [ "$a" != "q" ] && [ "$a" != "Q" ]; do
	echo "  Scanning..."
	scanimage | convert - `printf "%0.3d.$Format" $i`
	i=`expr $i + 1`
done

if [ "$Format" = "pdf" ]; then
	echo "TIP: you can use print/pdftk to convert all scanned pdf's to singe file:"
	echo "  pdftk \`ls *.pdf\` output output_file_name.pdf"
fi

exit 0
EDIT
latest version available at
http://aldis.git.bsdroot.lv/scan/
 

LeFroid

Member

Reaction score: 1
Messages: 40

Heres a few simple scripts I wrote.

Heres a basic script to play any video in your ~/Videos dir

play.py
Code:
 #!/usr/bin/env python

 import sys
 import os

 # what to play the video with
 player = "vlc"
 # arguments, ex 'play "myvid.avi"'
 video = sys.argv[1]
 # home dir
 home = os.path.expanduser('~')

 # combine strings
 execStr = player+" "+home+"/Videos/"+video
 # run execStr
 os.system(execStr)
this one is a simple c++ tool to install a port (as root). i'm still not good at c++ so this probably should be written better

you use it like "./port_tool MYPORT" as root

sysinfo.h (i copied this from somewhere)
Code:
#ifndef SYSINFO_H
#define SYSINFO_H

#define WINDOWS 0
#define BSD 1
#define APPLE 2
#define INTEL 3

#if defined( _WIN64 )
  #define PLATFORM WINDOWS
#elif defined ( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 )
  #define PLATFORM WINDOWS
#elif defined( __APPLE_CC__ )
  #define PLATFORM APPLE
#elif defined( __INTEL_COMPILER )
  #define PLATFORM INTEL
#else
  #define PLATFORM BSD
#endif

#endif
ports.h
Code:
 #ifndef PORTS_H
 #define PORTS_H
 #include <iostream>
 using namespace std;

 class Ports
 {
   public:
       void SearchPort(string pName);
       void InstallPort(string pName);
 };
 #endif
ports.cpp
Code:
#include "ports.h"
#include "sysinfo.h"

 void Ports::SearchPort(string pName)
 {
 #if PLATFORM == BSD
  string install;
  cout << "Locations: " << endl;
  string cmd = "/usr/bin/whereis " +  pName;
  system(cmd.c_str());
  cout << "Would you like to install? (y/n) ";
  cin >> install;
  if ( install == "y"|| install == "Y" || install == "yes" || install == "YES
  {
     InstallPort(pName);
  }else{
     exit(EXIT_SUCCESS);
  }
 #else
   cout << "What are you thinking??" << endl;
 #endif
 }

 void Ports::InstallPort(string pName)
 {
  #if PLATFORM == BSD
     string install = "cd /usr/ports/*/"+pName+" && make install clean";
     system(install.c_str());
  #else
    cout << "Install FreeBSD!" << endl;
  #endif
 }

int main(int argc, char *argv[])
 {
  Ports pt;
  if(argc < 2)
  {
     cout << "Usage: " << argv[0] << " PORTNAME" << endl;
  }else{
     cout << "NOTICE: must be root to install any ports" << endl;
     string prog = argv[1];
     pt.SearchPort(prog);
   }
 }
 

idle

Member

Reaction score: 8
Messages: 64

LeFroid said:
this one is a simple c++ tool to install a port (as root). i'm still not good at c++ so this probably should be written better
That is a big one. :D

What is the difference from code below?

Code:
#!/bin/sh
make install clean -C /usr/ports/$1
 

sixtydoses

Well-Known Member

Reaction score: 59
Messages: 400

Scripts were inspired by DD's portupdater script. DD is using # portmaster and am using # portupgrade, hence the modification. Else I'd be more than happy just to use his original script. Probably one day I'll switch to # portmaster and DD's original script will come in handy. Thanks much, Dutch.

Requires ports-mgmt/portupgrade, ports-mgmt/portaudit and x11/zenity (optional).

# updatetree - Run as cronjob every night at 0300.
If portsnap is already running, portsnapcron will only update its compressed snapshot and the INDEX files. Applies the same if portupgrade or some other 'make' process is running. Else, portsnap will fetch and update the ports tree.

Code:
#!/bin/sh

hostname=$(hostname)
date=$(/bin/date)

echo "
Portupdater for ${hostname} started at ${date}
"

running=`/bin/ps auxww | /usr/bin/grep -E "portsnap|portupgrade|make" | /usr/bin/grep -v grep`


if [ -n "$running" ]
    then
    echo "
    ========== Fetching and update latest ports snapshot from server. ==================
    "
    portvar="-I cron update"
else
    echo "
    ========== Fetching and update ports tree in ${hostname}. ==================
    "
    portvar="cron update"
fi

/usr/sbin/portsnap ${portvar} || exit 1


echo "
    ========== Portupdater done. ============================================
"

# portupdater - Run as cronjob once a week at 0400.
Will run portaudit, portsclean, update the ports database and check which ports that need updating. I included a dialog box (x11/zenity) to display the number of ports that need updates and remind me to read /usr/ports/UPDATING because sometimes my fingers are faster than my brain..

Code:
#!/bin/sh

hostname=$(hostname)
date=$(/bin/date)


echo "
Updating portaudit first.
"
/usr/local/etc/periodic/security/410.portaudit


echo "
======================= Cleaning out all obsolete distfiles. =======================
"

/usr/local/sbin/portsclean -CDDLP || exit 1



echo "
======================= Update ports database file. =======================
"

/usr/local/sbin/portsdb -u || exit 1


echo "
======================= See which ports need updating. =======================
"

OIFS=$IFS
IFS='
'

oldports=$(/usr/local/sbin/portversion -vl '<')

count=0

for i in $oldports
do
        count=`/bin/expr "$count" + 1`
        echo $i
done

IFS=$OIFS


echo "
Number of ports need to be updated: $count.
"


echo "
======================= Warnings from /usr/ports/UPDATING. =======================
"

/usr/bin/grep -B 1 AFFECTS: /usr/ports/UPDATING | /usr/bin/head -20


echo "
See /usr/ports/UPDATING for further details.

============================== Portupdater done. ==============================
"

/usr/local/bin/odmsg ''"$count"' ports need updating. Read /usr/ports/UPDATING before upgrading.' & 2>/dev/null

./odmsg
I've always had this script in my box for quite sometime so that my remote user can get my attention by prompting me a message.
e.g.: odmsg 'Tada!'

Code:
#!/bin/sh


# Set up the Display
export DISPLAY=:0

# Wake up the screen because it has probably fallen asleep
/usr/local/bin/xset s off
/usr/local/bin/xset -dpms
/usr/local/bin/xset s reset
/usr/local/bin/xscreensaver-command -deactivate > /dev/null


/usr/local/bin/zenity --info --text="$1" 2>/dev/null &


# Allow the screensaver and power saving mode to take effect now that the message has been acknowledged.
/usr/local/bin/xset s on
/usr/local/bin/xset +dpms
 

graudeejs

Son of Beastie

Reaction score: 694
Messages: 4,615

Here's script to make Really Big screenshots.
This can be used only in FVWM, you need to load FvwmCommandS module
This script will switch to each page and create screenshot, after I created screenshot of each page, it will merge them into one big screenshot, containing virtual desk.

Note don't confuse virtual pages with virtual desks :D
virtual pages are in virtual desks :)

Code:
#!/bin/sh

# this script will create screenshot of each virtual page in fvwm
#   then it will merge them into one big jpg
#   then it will switch to Sx Sy page and open screenshot with Start_viewer
#   fvwm function
#
# this script requires fvwm module FvwmCommandS to be loaded
# 
# To integrate in Fvwm, you can do something like this
# 
# Exec exec $[FVWM_SCRIPTS]/RealBigScreenshot.sh $[desk.pagesx] $[desk.pagesy] $[page.nx] $[page.ny]

X=${1:-"1"}	# page count X
Y=${2:-"1"} # page count Y
Sx=${3:-"0"}	# from which pagex we ran this scipt
Sy=${4:-"0"}	# from which pagey we ran this scipt

for y in `jot $Y 0`; do
	for x in `jot $X 0`; do
		FvwmCommand "GotoPage $x $y"
		import -quality 95 -window root /tmp/$$_x${x}_y${y}.jpg
		xnames="$xnames /tmp/$$_x${x}_y${y}.jpg"
	done

	convert +append $xnames /tmp/$$_y${y}.jpg
	rm -f $xnames
	xnames=""
	ynames="$ynames /tmp/$$_y${y}.jpg"
done

if [ ! -d ${HOME}/pic/screenshots ]; then
	mkdir -pf ${HOME}/pic/screenshots
fi

fileName="${HOME}/pic/screenshots/$(date '+%Y.%m.%d_at_%H.%M.%S')-RealBig.jpg"
convert -append $ynames $fileName
rm -f $ynames

FvwmCommand "GotoPage $Sx $Sy"

exec FvwmCommand "Function Start_viewer $fileName"

exit
here's example screenshot ([red]Warning this jpg is 1.9MB[/red])



I needed this for my homework in databases :D
The database data in screenshot are all fake

EDIT:
latest script version can be found at
http://aldis.git.bsdroot.lv/fvwm-bluth/
 

rambetter

Member

Reaction score: 8
Messages: 88

Hi, I have a couple of scripts that I'm proud of.

The first is similar to ``pkg_delete'', but it also performs a ``make rmconfig'' on the package you are removing. I call this script ``pkg_clean_delete'':

Code:
#!/bin/sh

if [ $# -ne 1 ]; then
  echo "Exactly one argument must be specified" 1>&2
  exit 1
fi
PACKAGE=$1
if [ -e "$PACKAGE" ]; then
  echo "'$PACKAGE' is a file; avoid that" 1>&2
  exit 1
fi
ORIGIN=`pkg_info -qo "$PACKAGE"`
if [ $? -ne 0 ]; then
  exit 1
fi
if pkg_delete "$PACKAGE"; then
  cd "/usr/ports/$ORIGIN"
  make clean
  make rmconfig
  exit 0
fi
exit 1

I have another script that addresses a real problem I've had. My servers are in a data center, and for some reason, when I reboot my servers, it sometimes takes 60 seconds or so for the network to start working. I run ntpd on my servers. My /etc/ntp.conf file uses DNS names that need to be resolved to IP addresses when ntpd starts. The problem is that usually, the network is not working by the time ntpd starts, and ntpd cannot perform the DNS resolution. ntpd then gets into a funny state where two of its processes show up in ps, yet it never finishes resolving DNS, and never works. I need to shut down ntpd and then restart it after the system comes up in order for it to work.

To fix this issue, I wrote a script that waits for the network to become functional before continuing in the startup scripts. The file is ``/usr/local/etc/rc.d/waitfornetwork'' and its contents are:

Code:
#!/bin/sh

# PROVIDE: waitfornetwork
# REQUIRE: NETWORKING
# BEFORE:  named

. /etc/rc.subr

: ${waitfornetwork_enable:=NO}
name=waitfornetwork
rcvar=`set_rcvar`
stop_cmd=":"
start_cmd="waitfornetwork_start"

waitfornetwork_start()
{
  echo "Waiting for network to initialize."
  for i in 0 1 2 3 4 5 6 7 8 9; do
    if ping -c 1 192.203.230.10 | grep -q "^1 packets transmitted, 1 packets received, 0\.0% packet loss$"; then
      return 0
    fi
  done
  warn "Network still seems bo be down."
  return 1
}

load_rc_config ${name}
run_rc_command "$1"
The IP address that I'm pinging is one of the root name servers on the West Coast (U.S.A.). This forces services such as named and ntpd to wait until the network comes up before they start. If the network never comes up, the script exits after a few ping attempts.
 

morbit

Well-Known Member

Reaction score: 34
Messages: 258

Extremely simple port updating/cleaning "script".

HTML:
#!/bin/sh

portsnap fetch update && portmaster -a && \
pkg_cleanup && portmaster --check-port-dbdir && \
portmaster --check-depends && echo removed distfiles: && \
rm -vrf /usr/ports/distfiles/* && echo removed workfiles: && \
rm -vrf /usr/ports/*/*/work && portmaster -l | grep installed
Suitable to be terminated at pkg_cleanup stage if no fresh ports were built.

I like to be reminded which ports are leaves.

rm /usr/ports/*/*/work is redundant, if portmaster is always used.

PS. "portmaster --packages-build --delete-build-only -a" combination is extremely useful, it uses packages for build dependencies, and deletes them afterward.
 

ckester

Well-Known Member

Reaction score: 38
Messages: 288

cd to directory with source for given command

This began in the thread about favorite aliases, but it's really more about the simple script I wrote to cd to the directory containing the source for a given command.

I setup the following alias

~/.cshrc
Code:
alias src       source $HOME/bin/cdsrc
which uses this script

~/bin/cdsrc
Code:
#!/bin/csh

set PORTSDIR = /usr/ports

set d = `whereis -sq $1`

if ( "X$d" == "X" ) then
        set d = `pkg_info -q -W $1`
        if ( "X$d" == "X" ) then
                echo "No source directory found for $1"
        else
                set p = `pkg_info -q -o $d`
                if ( "X$p" == "X" ) then
                        echo "No source directory found for $1"
                else
                        cd ${PORTSDIR}/$p
                endif
        endif
else
        cd $d
endif
It works whether the command is from ports or the system.

It also uses pkg_info's origin switch to find the correct port directory if the command was installed by a package whose name is not the same as the command's.

So src top will take you to /usr/src/usr.bin/top, and src sponge will take you to /usr/ports/sysutils/moreutils.
 

graudeejs

Son of Beastie

Reaction score: 694
Messages: 4,615

ipfw scripting

I use this function in my fpfw scripts to add new rules.
The advantage is that it's easier to find which rule wasn't added if there was problem.
This function should be used to only add rules with numbers

Code:
#!/bin/sh
cmd="/sbin/ipfw -q"

# add rule to ipfw
# arguments:
# $1 = rule number
# rest args = rule itself
add_rule() {
    no=$1
    shift
    $cmd add $no $* || echo "ERR add_rule:  '$cmd add $no $*'" >&2
}
example usage
Code:
add_rule 00030 fwd 127.0.0.1,spamd tcp from any to me smtp 'in'
example output
Code:
ipfw: getsockopt(IP_FW_ADD): Invalid argument
ERR add_rule:  '/sbin/ipfw -q add 00030 fwd 127.0.0.1,spamd tcp from any to me smtp in'
 

graudeejs

Son of Beastie

Reaction score: 694
Messages: 4,615

sh addressbook

I had to write simple bash {ye, right} addressbook for university.
Well I brought this to brand new level :D
This is like 100 times more complex than it was required, but it was fun

This script is only 159 lines of code (including license), 129 lines without license

ladies and gentleman, let me introduce you to my very simple address book written entirely in sh.
Current limitations:
* no spaces in values (even if you quote them). Comment is exception
* can't use | character

~/bin/ashbook:
Code:
#!/bin/sh

# Copyright (c) 2010, Aldis Berjoza <aldis@bsdroot.lv>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# 
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above
#    copyright notice, this list of conditions and the following disclaimer
#    in the documentation and/or other materials provided with the
#    distribution.
# 3. Neither the name of the  nor the names of its
#    contributors may be used to endorse or promote products derived from
#    this software without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

address_book="$HOME/.ashbook"
save_backup=1	# saves backup when removing record if set

awk_output_format='
{
	split($0, f, "|");
	if( f[1] ) print " name:     " f[1];
	if( f[2] ) print " surname:  " f[2];
	if( f[3] ) print " email:    " f[3];
	if( f[4] ) print " phone:    " f[4];
	if( f[5] ) print " address:  " f[5];
	if( f[6] ) print " date:     " f[6];
	if( f[7] ) print " homepage: " f[7];
	if( f[8] ) print " code:     " f[8];
	if( f[9] ) print " comment:  " f[9];
	print "";
}'


if [ ! -f $address_book ]; then
	touch $address_book
	if [ $? -ne 0 ]; then
		echo "ERR: can't create file $address_book" >&2
		exit 1
	fi
fi

help() {
	version=1.0
	prog_name=$(basename $0)
	cat >&2 << EOF
$prog_name v$version is a very simple addressbook written in sh

$prog_name usage:
  $prog_name {add | find | rm} key1=value1 [key2=value2 [...]]
  $prog_name list

    Where key can be any of are:
      name, surname, code, phone, address, position, email, homepage, date,
      comment

    Comment key is special and must be last key used. Comment value may
    contain spaces.
    
    Values and commands are case sensetive, keys are not.

    Use of | character is forbidden as it's used as field seperator in
    addressbook.

EOF
	exit 1
}


if [ "$1" = 'add' ]; then
	func='add'
elif [ "$1" = 'find' ]; then
	func='find'
elif [ "$1" = 'list' ]; then
	awk "$awk_output_format" $address_book
	exit 0
elif [ "$1" = 'rm' ]; then
	func='rm'
else
	help
fi
shift

if [ $# -eq 0 ]; then
	help
	exit 1
fi


while [ $# -gt 0 ]; do
	key=$(echo $1 | sed 's/=.*//' | tr 'QWERTYUIOPASDFGHJKLZXCVBNM' 'qwertyuiopasdfghjklzxcvbnm')
	value=$(echo $1 | sed 's/.*=//')

	case $key in
		'name' | 'surname' | 'code' | 'phone' | 'address' | 'position' | 'email' | 'date' | 'homepage' )
			eval `echo "$key=$value"`;
		;;

		'comment' )
			comment=$(echo $* | sed 's/.*=//')
			break
		;;

		*)
			echo "ERR: key '$key' invalid. Ignoring" >&2
		;;
	esac
	shift
done

find_record="${name:-.*}|${surname:-.*}|${email:-.*}|${phone:-.*}|${address:-.*}|${date:-.*}|${homepage:-.*}|${code:-.*}|${comment:-.*}"

if [ $func = 'add' ]; then
	if [ $(grep -e "$find_record" $address_book) ]; then
		echo 'ERR: looks like this record already exists' >&2
		exit 1
	fi;
	echo "$name|$surname|$email|$phone|$address|$date|$homepage|$code|$comment" >> $address_book
	echo "INFO: Record added"
	exit 0
elif [ $func = 'find' ]; then
	grep -e "$find_record" -x $address_book | awk "$awk_output_format"
	exit 0
elif [ $func = 'rm' ]; then
	found=`grep -e "$find_record" -x $address_book`
	if [ "$found" != "" ]; then
		echo "$found" | awk "$awk_output_format"
		echo "Do you really want to delete above entries? [y|n]"
		read delete
		if [ "$delete" = 'y' ] || [ "$delete" = 'Y' ]; then
			cp -f $address_book ${address_book}.bak
			grep -e "$find_record" -x -v ${address_book}.bak > ${address_book}
			if [ ! $save_backup ]; then
				rm -f ${address_book}.bak
			fi
			echo
			echo "INFO: Record(s) deleted"
		fi
	else
		echo "INFO: No match found"
	fi
	exit 0
fi


exit 1

# vim:tabstop=4:shiftwidth=4:
if you think this is any good, please let me know (via pm) and I'll consider improving it and maybe even creating port

Latest version available at:
http://aldis.git.bsdroot.lv/ashbook/
 

ckester

Well-Known Member

Reaction score: 38
Messages: 288

killasmurf86 said:
I had to write simple bash {ye, right} addressbook for university.
Well I brought this to brand new level :D
This is like 100 times more complex than it was required, but it was fun
One of the first lessons I learned when I began my software career many years ago is to never add features that aren't in the spec -- at least, not unless you get the client's agreement and understanding that the project might be delayed or have additional bugs as a result.

Even if it's an in-house job. My first programming job (late 80's) was at an avionics company. I spent a lot of time adding bells and whistles to what was expected to be a quick and dirty program. It was a lot of fun, and I was sure it would impress my boss and anyone else who saw it. But as a result, I missed out on another assignment that I really really wanted. When I asked why he hadn't given it to me, my boss said it was because I was still busy on that other thing. He'd thought I'd have the first job done in a day or two, freeing me up in plenty of time to do the plum assignment. :x
 
Top