- Ispravak za cp_mail gdje je zalutao whitespace i uzrokovao blacklisting od
[carnet-tools-cn.git] / functions.sh
1 # Initialize "public" CP_ECHO_RETURN variable once
2 if [ -z "$_CP_INIT_ECHO_RETURN" ]; then
3   _CP_INIT_ECHO_RETURN=1
4   CP_ECHO_RETURN=""
5 fi
6
7 # by ddzeko & ico, Fri, 18 Mar 2005 14:44:08 +0100
8 cp_get_ifaddr() {
9   [ "$CP_SCRIPT_DEBUG" ] && set -vx
10
11   local ifaddr interface echo_return
12   echo_return="$CP_ECHO_RETURN" # since we're making our own calls
13   # in our own way we need to set CP_ECHO_RETURN the way we want it
14   # but preserving initial state so it could be used afterwards
15   CP_ECHO_RETURN=""
16
17   interface="$1"
18   if [ -z "$interface" ]; then
19     cp_get_ifdefault dev
20     interface="$RET"
21     [ -z "$interface" ] && interface=lo
22   fi
23
24   if ! ifconfig $interface 2> /dev/null >> /dev/null; then
25     echo "cp_get_ifaddr: $interface: No such interface" 1>&2
26     CP_ECHO_RETURN="$echo_return"
27     return 2
28   fi
29
30   ifaddr="`/sbin/ifconfig $interface | awk '/inet/{ printf("%s\n",substr($2,index($2,":")+1)) }'`"
31
32   if [ -z $ifaddr ]; then
33     echo "cp_get_ifaddr: $interface: No ip address found" 1>&2
34     CP_ECHO_RETURN="$echo_return"
35     return 1
36   fi
37
38   RET="$ifaddr"
39   [ -z "$echo_return" ] || echo $RET
40   CP_ECHO_RETURN="$echo_return"
41 }
42
43 # by ddzeko & ico, Fri, 18 Mar 2005 14:44:08 +0100
44 cp_get_ifmask() {
45   [ "$CP_SCRIPT_DEBUG" ] && set -vx
46
47   local ifmask interface echo_return
48   echo_return="$CP_ECHO_RETURN" # since we're making our own calls
49   # in our own way we need to set CP_ECHO_RETURN the way we want it
50   # but preserving initial state so it could be used afterwards
51   CP_ECHO_RETURN=""
52
53   interface="$1"
54   if [ -z "$interface" ]; then
55     cp_get_ifdefault dev
56     interface="$RET"
57     [ -z "$interface" ] && interface=lo
58   fi
59
60   if ! ifconfig $interface 2> /dev/null >> /dev/null; then
61     echo "cp_get_ifmask: $interface: No such interface" 1>&2
62     CP_ECHO_RETURN="$echo_return"
63     return 1
64   fi
65
66   ifmask="`/sbin/ifconfig $interface | awk '/Mask/{if($3~/Mask/)a=$3;else if ($4~/Mask/)a=$4;printf ("%s\n", substr(a,index(a,":")+1))}'`"
67
68   if [ -z "$ifmask" ]; then
69     echo "cp_get_ifmask: $interface: No netmask found" 1>&2
70     CP_ECHO_RETURN="$echo_return"
71     return 1
72   fi
73
74   RET="$ifmask"
75   [ -z "$echo_return" ] || echo $RET
76   CP_ECHO_RETURN="$echo_return"
77 }
78
79 # by ddzeko, Mon, 21 Mar 2005 07:00:22 +0100
80 cp_get_ifdefault() {
81   [ "$CP_SCRIPT_DEBUG" ] && set -vx
82
83   local echo_return
84   echo_return="$CP_ECHO_RETURN" # since we're making our own calls
85   # in our own way we need to set CP_ECHO_RETURN the way we want it
86   # but preserving initial state so it could be used afterwards
87   CP_ECHO_RETURN=""
88
89   RET=""
90   case $1 in
91     dev)
92       RET=`route -n | awk 'BEGIN {m = 2^32}
93                     /^0\.0\.0\.0[ \t]/ {if ($5 < m) {r = $8; m = $5}}
94                              END {print r}'`
95       ;;
96     addr)
97       RET=`route -n | awk 'BEGIN {m = 2^32}
98                     /^0\.0\.0\.0[ \t]/ {if ($5 < m) {r = $2; m = $5}}
99                              END {print r}'`
100       ;;
101     *)
102       echo "cp_get_ifdefault: Argument required (dev or addr)" >&2
103       ;;
104   esac
105
106   [ -z "$RET" -a "$1" ] && echo "cp_get_ifdefault: No default route" >&2
107
108   [ -z "$echo_return" ] || echo $RET
109   CP_ECHO_RETURN="$echo_return"
110   [ -n "$RET" ] || return 1
111 }
112
113 # by ico, Tue, 15 Mar 2005 14:04:21 +0100
114 cp_get_netaddr() {
115   [ "$CP_SCRIPT_DEBUG" ] && set -vx
116
117   local netmask ipaddress interface cidr echo_return
118   echo_return="$CP_ECHO_RETURN" # since we're making our own calls
119   # in our own way we need to set CP_ECHO_RETURN the way we want it
120   # but preserving initial state so it could be used afterwards
121   CP_ECHO_RETURN=""
122
123   interface="$1"
124   if [ -z "$interface" ]; then
125     cp_get_ifdefault dev
126     interface="$RET"
127     [ -z "$interface" ] && interface=lo
128   fi
129
130   if ! ifconfig $interface 2> /dev/null >> /dev/null; then
131     echo "cp_get_netaddr: $interface: No such interface" 1>&2
132     CP_ECHO_RETURN="$echo_return"
133     return 1
134   fi
135
136   cp_get_ifaddr "$interface"
137   ipaddress="$RET"
138   if [ -z $ipaddress ]; then
139     echo "cp_get_netaddr: $interface: No IP address found" 1>&2
140     CP_ECHO_RETURN="$echo_return"
141     return 1
142   fi
143   cp_get_ifmask "$interface"
144   netmask="$RET"
145   if [ -z $netmask ]; then
146     echo "cp_get_netaddr: $interface: No netmask found" 1>&2
147     CP_ECHO_RETURN="$echo_return"
148     return 1
149   fi
150
151   if [ "$netmask" = "255.255.255.255" ]; then
152     cidr="$ipaddress/32"
153   else 
154     cidr="`ipcalc -nb $ipaddress $netmask | awk '/^Network:/{print $2}'`"
155   fi
156   
157   RET="$cidr"
158   [ -z "$echo_return" ] || echo $RET
159   CP_ECHO_RETURN="$echo_return"
160 }
161
162 cp_check_and_backup() {
163   [ "$CP_SCRIPT_DEBUG" ] && set -vx
164
165   cp_backup_conffile -r "$@"
166 }
167
168 # by ico, Tue, 15 Mar 2005 14:04:21 +0100
169 cp_backup_conffile() {
170   [ "$CP_SCRIPT_DEBUG" ] && set -vx
171
172   local dir ext file_bak check did opt_p opt_d
173   
174   dir=/var/backups
175   ext=.bak
176   
177   while echo "x$1" |grep -q '^x-'; do
178     case "$1" in
179     -r)
180       shift
181       check=1
182       ;;
183     -p)
184       shift
185       opt_p=1
186       ;;
187     -d)
188       shift
189       opt_d=1
190       # Is argument to -d full path or relative?
191       if echo "$1" |grep -q '^/'; then
192         dir="$1"
193       else
194         dir="$dir/$1"
195       fi
196       shift
197       ;;
198     -n)
199       shift
200       ext=
201       ;;
202     esac
203   done
204   if [ "$opt_d" ]; then
205     if [ ! -e "$dir" -a "$opt_p" ]; then
206       mkdir "$dir"
207     fi
208     if [ $? -ne 0 ]; then
209       echo "cp_backup_conffile: Error creating backup directory $dir" 1>&2
210       return 3
211     fi
212   fi
213   if [ ! -d "$dir" ]; then
214     echo "cp_backup_conffile: Invalid backup directory $dir" 1>&2
215     return 3
216   fi
217   if [ -z "$1" ]; then
218     return 1
219   fi
220   if [ ! -f "$1" ]; then
221     echo "cp_backup_conffile: $1: No such file" 1>&2
222     return 2
223   fi
224   if [ -z "$2" ]; then
225     file_bak="$dir/`basename $1`$ext"
226   else
227     file_bak="$dir/`basename $2`$ext"
228   fi
229
230   if [ ! -f "$file_bak" ]; then
231     cp -pf "$1" "$file_bak"
232     did=1
233   else
234     if ! cmp -s "$1" "$file_bak"; then
235       /usr/bin/savelog -p -c 7 "$file_bak" > /dev/null 2> /dev/null
236       cp -pf "$1" "$file_bak"
237       did=1
238     fi
239   fi
240
241   [ -z "$check" ] && return 0
242
243   if [ "$check" -a ! "$did" ]; then
244     return 3
245   else
246     return 0
247   fi
248 }
249
250 # by jelly, Tue, 15 Mar 2005 14:04:21 +0100
251 # modified by ico, Mon,  6 Jun 2005 11:58:08 +0200
252 # A sed wrapper, to use instead of perl -pi -e
253 #  - relatively safe in-place s///g
254 #  - takes care of symlinks and ownership
255 # returns true if changed, false if nothing happened
256 #
257 cp_check_and_sed() {
258   [ "$CP_SCRIPT_DEBUG" ] && set -vx
259
260   local s sedcmd grepret ret i
261   if [ -z "$3" ]; then
262     return 1
263   fi
264   s="$1"
265   shift
266   sedcmd="$1"
267   shift
268   ret=2
269   for i in "$@"
270   do
271     [ -e "$i" ]        || continue
272     if ! egrep -q "$s" "$i"; then
273       grepret=1
274       continue
275     fi
276     [ -h "$i" ]        && i=$(readlink -f "$i")
277     sed "$sedcmd" "$i" > "$i.dpkg-tmp"
278     if [ $? -ne 0 ]; then
279       rm "$i.dpkg-tmp"
280       echo "cp_check_and_sed: Problem with sed" 1>&2
281       return 5
282     fi
283     if ! cmp -s "$i" "$i.dpkg-tmp" 2>&1 >/dev/null; then
284       cp_mv "$i.dpkg-tmp" "$i"
285     else
286       rm "$i.dpkg-tmp"
287     fi
288     ret=0
289   done
290   [ "$ret" -eq 2 -a "$grepret" ] && ret=1
291   return $ret
292 }
293
294 # by jelly, Sun, 20 Mar 2005 20:12:19 +0100
295 cp_echo () {
296   [ "$CP_SCRIPT_DEBUG" ] && set -vx
297
298   if [ "x$1" = "x-mailonly" -o "x$1" = "x-m" ]; then
299     shift
300   else   
301     echo "$*"
302   fi
303   CP_NOTICE="$CP_NOTICE$1"
304   if [ `echo -n "$*" | wc -l` -eq 0 ]; then
305     CP_NOTICE="$CP_NOTICE
306 "
307   fi
308 }   
309
310 # by jelly, Sun, 20 Mar 2005 20:12:19 +0100
311 cp_mail () {
312   [ "$CP_SCRIPT_DEBUG" ] && set -vx
313
314   local pkg version quiet
315   if [ "x$1" = "x-q" ]; then
316     quiet=1
317     shift
318   fi
319   if [ -n "$1" ]; then
320     pkg="$1"
321   else
322     return 1 # must have at least the package name as argument
323   fi
324   [ -n "$2" ] && version=" $2"
325   if [ "$(echo $CP_NOTICE|wc -w)" -gt 0 ]; then
326     [ -n "$quiet" ] || echo "Mailing upgrade output to root."
327     CP_NOTICE="From: $pkg postinst script <root>
328 To: root
329 Subject: $pkg$version package install log
330 Date: $(LC_ALL=C /bin/date --rfc-2822)
331
332 Hello!
333
334 The $pkg package has been successfully installed on your computer.
335 For your convenience, a partial output of the last $pkg installation
336 is included below.
337
338 ----------
339 ${CP_NOTICE}----------"
340   
341     echo "$CP_NOTICE" | /usr/sbin/sendmail -t -oi &
342     sleep 1
343   fi
344 }
345
346 # by ddzeko, Mon, 21 Mar 2005 11:31:59 +0100
347 cp_mv () {
348   [ "$CP_SCRIPT_DEBUG" ] && set -vx
349
350   local new old
351   if [ -z "$2" ]; then
352     return 1
353   fi
354   new="$1"
355   old="$2"
356   if [ -e "$old" ]; then
357     chown --reference "$old" "$new"
358     chmod --reference "$old" "$new"
359     cp -pf "$old" "$old.cn-old"
360   fi
361   mv "$new" "$old"
362 }
363
364 # by ddzeko, Mon, 21 Mar 2005 13:35:42 +0100
365 cp_yes_no () {
366   [ "$CP_SCRIPT_DEBUG" ] && set -vx
367   local prompt answer
368   prompt="$1"
369   [ "$prompt" ] || prompt="Are you sure?"
370   RET=""
371
372   # check to prevent user from using this when debconf is active
373   # (it would break communication with its backend - uses stdin/out)
374   if [ "$DEBCONF_REDIR" ]; then
375     echo "cp_yes_no: debconf redirection detected" >&2
376     return 1
377   fi
378
379   echo -n "$prompt (y)es/(n)o: "
380   read answer
381   case "$answer" in
382     Y*)
383       echo
384       RET=y
385       ;;
386     N*)
387       echo
388       RET=n
389       ;;
390     y*)
391       echo
392       RET=y
393       ;;
394     n*)
395       echo
396       RET=n
397       ;;
398     *)
399       echo
400       echo "Please read the message and choose y or n"
401       cp_yes_no "$prompt"
402       ;;
403   esac
404 }
405
406 # by ddzeko, Tue, 29 Mar 2005 17:37:52 +0200
407 #
408 # db_get seems to return error messages if the requested variable 
409 # is not found - we do not find that desirable, and checking $? with
410 # set -e turned on seems to be a bit of a problem
411 # --> that's why we wrap the db_get call to return unset RET variable
412 #     instead of some gibberish error message that our script does
413 #     not expect
414 cp_db_get() {
415   [ "$CP_SCRIPT_DEBUG" ] && set -vx
416
417   local var
418   var="$1"
419   
420   # check to prevent user from using this before activating debconf
421   # confmodule needs to be loaded before accessing db_* functions
422   if [ -z "$DEBCONF_REDIR" ]; then
423     echo "cp_db_get: debconf not activated!" >&2
424     return 1
425   fi
426  
427   if ! db_get "$var"; then
428     case "$RET" in
429         *doesn\'t\ exist)
430           RET=""
431           ;;
432         [0-9][0-9]\ ?*) # other errors
433           RET=""
434           ;;
435     esac
436   fi
437 }
438
439 # by ico, Wed, 20 Apr 2005 21:09:54 +0200
440 cp_get_ldap_suffix() {
441   [ "$CP_SCRIPT_DEBUG" ] && set -vx
442
443   local echo_return
444   echo_return="$CP_ECHO_RETURN" # since we're making our own calls
445   # in our own way we need to set CP_ECHO_RETURN the way we want it
446   # but preserving initial state so it could be used afterwards
447   CP_ECHO_RETURN=""
448
449   if [ ! -f /etc/ldap/slapd.conf ]; then
450     echo "cp_get_ldap_suffix: /etc/ldap/slapd.conf: No such file" >&2
451     return 2
452   fi
453   
454   RET="`awk  '/^suffix/      { exit }
455               END            { gsub(/"/, "", $2); print $2 }' \
456              < /etc/ldap/slapd.conf`"
457
458   if [ "`echo $RET | sed 's/,/ /g' | wc -w`" -gt 2 ]; then
459     RET=""
460     echo "cp_get_ldap_suffix: Invalid LDAP suffix in /etc/ldap/slapd.conf" >&2
461     return 2
462   fi
463     
464   [ -z "$RET" ] && echo "cp_get_ldap_suffix: No LDAP suffix in /etc/ldap/slapd.conf" >&2
465   [ -z "$echo_return" ] || echo $RET
466   CP_ECHO_RETURN="$echo_return"
467 }
468
469 # by ico, Wed, 20 Apr 2005 21:09:54 +0200
470 cp_get_ldap_realm() {
471   [ "$CP_SCRIPT_DEBUG" ] && set -vx
472
473   local echo_return
474   echo_return="$CP_ECHO_RETURN" # since we're making our own calls
475   # in our own way we need to set CP_ECHO_RETURN the way we want it
476   # but preserving initial state so it could be used afterwards
477   CP_ECHO_RETURN=""
478
479   if [ ! -f /etc/ldap/slapd.conf ]; then
480     echo "cp_get_ldap_realm: /etc/ldap/slapd.conf: No such file" >&2
481     return 2
482   fi
483  
484   cp_get_ldap_suffix || true
485   RET="`echo $RET | awk -F, '{print $1}' | awk -F= '{print $2}'`"
486
487   [ -z "$RET" ] && echo "cp_get_ldap_realm: No LDAP REALM in /etc/ldap/slapd.conf" >&2
488 }
489
490 # if fqdn is name.dom3.dom2.dom1.hr, check if this host is MX for
491 # either dom3.dom2.dom1.hr, dom2.dom1.hr or dom1.hr and dump highest level
492 # domain on stdout
493 cp_get_mx_domain() {
494   [ "$CP_SCRIPT_DEBUG" ] && set -vx
495
496   local domains d host
497
498   host=$(hostname -f)
499   RET="$host"
500   if ! echo "$host" | grep -q '\.'; then
501     return
502   fi
503   if [ ! -x /usr/bin/host ]; then
504     # no host command
505     return
506   fi
507   domains=$(/bin/hostname -f | awk -F. '
508     {
509       for (i=2; i<NF; i++) { 
510         for (j=i; j<NF; j++) {
511           printf "%s", $(j)"."
512         };
513         print $NF
514       }
515     }'    )
516   for d in $domains
517   do
518     mxes=$(/usr/bin/host -t mx $d)
519     # handle output of both /usr/bin/host providers
520     mxes=$(echo "$mxes"|\
521            awk '/mail is handled by/ || /MX/ {print $NF}'|sed 's/\.$//')
522     if echo "$mxes" |egrep -q "^$host$"; then
523       RET="$d"
524     fi
525   done
526
527   [ -z "$CP_ECHO_RETURN" ] || echo "$RET"
528 }
529
530 _cp_customize() {
531   [ "$CP_SCRIPT_DEBUG" ] && set -vx
532   # < input functions > output_functions
533   # new-prefix list-of-functions
534   perl -e '
535     $prefix = shift; %keep = (); $output = "";
536     $keep{$_} = 1 for @ARGV;
537     # add dependent functions
538     %deps = (
539       get_ifaddr       => [ "get_ifdefault" ],
540       get_netaddr      => [ "get_ifdefault", "get_ifaddr", "get_ifmask" ],
541       check_and_backup => [ "backup_conffile" ],
542       check_and_sed    => [ "mv" ],
543       get_ldap_realm   => [ "get_ldap_suffix" ],
544     );
545     foreach my $f (keys(%keep)) {
546       if (exists($deps{$f})) {
547         $keep{$_} = 1 for (@{$deps{$f}});
548       }
549     }
550     while (<STDIN>) {
551       if (/^_?cp_(\w+) *\(\) *\{/) {
552         if (! exists($keep{$1})) {
553           while (<STDIN>) { last if /^\}/; } # skip it
554           next;
555         } else {
556           $output .= "\n";
557         }
558       }
559       next if /^\s*(\#|$)/;
560       $output .= $_;
561     }
562     $output =~ s/\b(_?)cp_/$1${prefix}_/sg;
563     $prefix = uc($prefix);
564     $output =~ s/\b(_?)CP_/$1${prefix}_/sg;
565     print $output;
566   ' -- $*
567 }