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