├── .gitignore ├── PGP-KEY ├── README.md ├── doinst.sh ├── etc ├── 15.0.new │ ├── blacklist │ ├── filter │ ├── protect │ └── scan └── current.new │ ├── blacklist │ ├── filter │ ├── protect │ └── scan ├── man ├── slackscan.8 ├── slackscan_update_generator.8 └── slackup.8 ├── sbin ├── slackscan ├── slackscan_update_generator └── slackup └── slackscan.Slackbuild /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore editor backup files: 2 | *~ 3 | \#*# 4 | -------------------------------------------------------------------------------- /PGP-KEY: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | mQENBFXfEX0BCAC38W1svO/2LIK2INm5YjtutRZ5wvNXndPsPZbOPIPW8VK2G/Ww 4 | AfDbziDbPcbp1UQ03TZ83+huHP2OCHQ03uiAumGTtLbFdi10q3K2H+01Ep0ml8V9 5 | KyH0Eg1hrWNvCms0UeWnDoLtj6tg+6pPvE8NVna7S87Lwu9L6HqAynFIES3Po167 6 | c4Z3+YcmKV1krCJreods0WiYGvOdeCEQa392ydKf6dBTRXLrYo02M2cnlerBZBNo 7 | CgJO1si+ZPnorMc3anB5AZ/U5Tu5GKomh8ThErkFJRNPXOFb6UYlv2wa8L8tBy/A 8 | HTzHyExPeKDIl70bkvKqyHF2nX5Zizg7szR5ABEBAAG0J0dhcnkgTGFuZ3NoYXcg 9 | PGdhcnkubGFuZ3NoYXdAZ21haWwuY29tPokBOAQTAQIAIgIbAwYLCQgHAwIGFQgC 10 | CQoLBBYCAwECHgECF4AFAloi0kMACgkQsghluZegjMJOogf+OY1wYp7pYI19fQjr 11 | X4lIcRITvyH8ZUS1wOYj8L7wfptOQ3xYmDb3M+chkBVwDcIOOHusdUwbxpV1e1rn 12 | yJ8T9RWvBmCzqOJFxT4QWiT9mt3QSCwKQBHcWvRwrd35fGdRWU1dO4xqodewvHqj 13 | QKIi06IINCkDuvo1PErQunUTxBqOVZYJkf/GWTE1BtBhQqsioAdinr2FTgQ0kVLp 14 | JFzSYyuDB9qT8YMEXClz2/hS0hqSCLT1n6bv4k5oqYuYMiYKkGb+FBFmak1P6g80 15 | LWBvSA1N5O6zL7VOEUvcby5Lxo+ehhQKewYkmE0WultfEAcfGTC3+ufydPv7XyBY 16 | pGpB9bkBDQRV3xF9AQgAtiMEgrwP7ykTbnER8gnCo4NRSSAqqK6qKCUQWFG7Kd/n 17 | Qb0e1+DQcNIHXw7b934qMrf7Qdf3uUdQR2/NffZGAqIP9VF+bOgp7lN/TM2Pbuu2 18 | oc92f6BDpbdfnQl0iSnuoUcxYdeCzu66OUv8CblfHiW5abOIL7sEWL0+JdRezTbp 19 | rWYawv2g5hlVdXwmjrOgGKimZkUVoW7VzDu94Qj0KXsd1GNnTAjDp4r/FCzHR4iv 20 | du97P9PS7JV9ZpiApBq6VbpzWwl8nBO76MhL+i7Epaq/u9WLLdu9G3lyJ3FQhZ3K 21 | DTbRw8B3/naH5h70rcWv1655eVNqokoazMOtUK5HXwARAQABiQEfBBgBAgAJAhsM 22 | BQJaItKTAAoJELIIZbmXoIzCfeQH/2P8HlIYvDVE+iCh4BmAuU47Or89vWzcFuMX 23 | HPydTu4VAmzy31MaAOI9EeoJC1KNGTTg8z7IiE6JAdGyF9o+I62Wr+rVALsNDAcY 24 | OTlNDECyFf7zoJrjdwM6OIWOpIVfUXPMCGZBLQX67xF0EqT1Ks9jOBO0FXkEM6g/ 25 | qhnfPk/IrhVsivI0UpPvkbmb4097eXz/oj3GFekgYBsbyF4M08lY9BNd9sBfmoB4 26 | tULtleSMWV6eE5m3JJfODtZ6zD4xWuUBgOmqFvsSIDqzNhvr0O38ZR6TWfGSoCuW 27 | zXap3NQuNsCmRNh/DVMAjuu604vh12n1jnyQ6Zn2do+XctsMH0Q= 28 | =RUj8 29 | -----END PGP PUBLIC KEY BLOCK----- 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Slackscan and Slackup 2 | 3 | ## Introduction 4 | 5 | The primary location of this project is: 6 | https://github.com/glangshaw/slackscan 7 | 8 | If you find any bugs/issues with any of them, please drop a note 9 | to me at: gary.langshaw@gmail.com. 10 | 11 | 12 | ## slackscan 13 | 14 | 'slackscan' is a bash script that will recursively search the 15 | locations specified in its config file for files matching the 16 | Slackware package file naming conventions. It will then compare the 17 | installed packages of the host system to those found in the configured 18 | locations and will generate lists of packages that should be 19 | installed, upgraded or removed in order to bring the installed system 20 | in sync with the packages available. 21 | 22 | 'slackscan' makes no changes to the installed system, its role is to 23 | generate lists, which are written to the files specified by the -i, -u 24 | and -r options. 25 | 26 | Adhering to "The UNIX Philosophy", these lists may then in turn be 27 | acted upon by other utilities. 28 | 29 | One such utility is provied with slackscan and is named 30 | slackscan_update_generator, another is slackup. 31 | 32 | 33 | ### slackup 34 | 35 | 'slackup' is a front-end for slackscan which invokes slackscan and 36 | generates on stdout, the stream of package-management commands 37 | necessary to action any identified changes. If asked, it can also 38 | directly execute the generated commands, but a prudent user will 39 | likely want to examine them first. 40 | 41 | 'slackup' adds additional functionality such as command-line pattern 42 | matching to limit operation to a subset of packages, and support for 43 | the automated running of post-install scripts. 44 | 45 | An update run using slackup might look like this: 46 | ``` 47 | slackup -sic | tee updates.sh 48 | sh updates.sh 49 | ``` 50 | 51 | Or, if you like living dangerously, and don't want to check what is 52 | about to be done to your system, just: `slackup -six` 53 | 54 | 55 | ### slackscan_update_generator 56 | 57 | Unlike 'slackup' which is a front-end, this is a simple awk-script 58 | that will take the already generated output of slackscan's -i or -u 59 | options and convert them into a list of Slackware's 'pkgtools' 60 | upgradepkg commands. The output of this awk-script may then be passed 61 | to the shell for execution. 62 | 63 | When remote package URLS are encountered, 'curl' commands will be 64 | added to the output stream in order to fetch them. gpg --verify 65 | commands will also be included in the stream. 66 | 67 | Package removals are not catered for since they can be easily actioned 68 | without any further modification using something like xargs. 69 | 70 | An example update run using slackscan and slackscan_update_generator 71 | might look something like this: 72 | ``` 73 | slackscan -i install.list -u update.list -r remove.list 74 | cat install.list update.list | slackscan_update_generator | sh 75 | xargs -r removepkg < remove.list 76 | ``` 77 | 78 | 79 | # PGP-KEY 80 | 81 | All tags in this repo are signed with the following pgp-key, which is 82 | available in the [PGP-KEY](PGP-KEY) file in this repo. 83 | ``` 84 | pub 2048R/97A08CC2 2015-08-27 85 | Key fingerprint = A497 723B 3AC6 8724 BB8D BBC6 B208 65B9 97A0 8CC2 86 | uid Gary Langshaw 87 | sub 2048R/1BB01B7E 2015-08-27 88 | ``` 89 | 90 | It would be better if you could get the key from somewhere else, but 91 | with all the keyservers shutting down over GDPR "Right to be 92 | forgotten" abuses, it'll have to do for now. 93 | 94 | 95 | # Final words 96 | 97 | I hope other Slackware users may find these useful, but if not, that's 98 | ok. I wrote them for my own use. 99 | -------------------------------------------------------------------------------- /doinst.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for dir in etc/slackscan/*.new 4 | do 5 | [ -d "$dir" ] && [ ! -d "${dir%.new}" ] && mv "${dir}" "${dir%.new}" 6 | done 7 | 8 | -------------------------------------------------------------------------------- /etc/15.0.new/blacklist: -------------------------------------------------------------------------------- 1 | # /etc/slackscan/15.0/blacklist 2 | # Format: basic-regex 3 | # 4 | # This file is the 'blacklist' file for the 'slackscan' utility. 5 | # Package files matching one of the following patterns will 6 | # be excluded from install and upgrade actions. 7 | # 8 | # Caution! 9 | # Remember these are regexes. Watch out for partial matches 10 | # e.g. 11 | # '/pan' would blacklist both 'pan' and 'pango' which is likely 12 | # not what your intended. I would suggest sticking with patterns 13 | # like: 14 | # /xap/pan- 15 | # 16 | 17 | ## Uncomment to prevent accidentally installing 32bit packages 18 | ## on a 64bit system: 19 | #-i[456]86-[^-\.]\+\.t.z$ 20 | 21 | ## Uncomment to exclude kernel source: 22 | # /kernel-source- 23 | 24 | ## Uncomment to exclude the 'huge' kernel: 25 | # /kernel-huge- 26 | -------------------------------------------------------------------------------- /etc/15.0.new/filter: -------------------------------------------------------------------------------- 1 | # /etc/slackscan/15.0/filter 2 | # Format: basic-regex 3 | # 4 | # This file is the 'filter' file for the 'slackscan' utility. 5 | # Package files not matching one of the following patterns will 6 | # be excluded from install and upgrade actions. 7 | # 8 | # Patterns passed on the command line will be appended to those 9 | # in this file when processing the filters at run-time. 10 | # 11 | # Patterns in the blacklist file are processed after these 12 | # filters are applied. 13 | # 14 | 15 | ## The following example when uncommented would limit matches to 16 | ## packages found in slackware64-current and 'xv' from extra/ 17 | #/slackware64-current/slackware64/ 18 | #/slackware64-current/extra/xv 19 | -------------------------------------------------------------------------------- /etc/15.0.new/protect: -------------------------------------------------------------------------------- 1 | # /etc/slackscan/15.0/protect 2 | # Format: basic-regex 3 | # 4 | # This file is the 'protect' file for the 'slackscan' utility. 5 | # 6 | # This is essentially a blacklist specific to removal operations 7 | # and should be used to prevent the removal of packages whose 8 | # package file is no longer available in any configured location. 9 | # 10 | # Important Note: 11 | # unlike the blacklist file which matches the full path of the package file, 12 | # this file matches only package names, so there is no path components or 13 | # \.t.z suffix to match. 14 | # 15 | 16 | ## uncomment the following to protect any packages tagged _local: 17 | # _local$ 18 | 19 | ## uncomment the following to protect any packages tagged _SBo (slackbuilds.org): 20 | # _SBo$ 21 | -------------------------------------------------------------------------------- /etc/15.0.new/scan: -------------------------------------------------------------------------------- 1 | # /etc/slackscan/15.0/scan 2 | # 3 | # List of locations where 'slackscan' can recursively find 4 | # slackware packages. 5 | # 6 | # Each line may contain the path of a local directory, or 7 | # the URL of a remote CHECKSUMS.md5 file. 8 | # 9 | 10 | # These entries below use the mirrors.slackware.com redirector to 11 | # find a nearby mirror. If you have a preferred mirror then 12 | # adjust accordingly. 13 | 14 | # slackware64-15.0 and patches: 15 | https://mirrors.slackware.com/slackware/slackware64-15.0/patches/CHECKSUMS.md5 16 | https://mirrors.slackware.com/slackware/slackware64-15.0/slackware64/CHECKSUMS.md5 17 | 18 | # Uncomment to include a local directory of packages as an additional 19 | # package source: 20 | # /local/slackware/packages/ 21 | -------------------------------------------------------------------------------- /etc/current.new/blacklist: -------------------------------------------------------------------------------- 1 | # /etc/slackup/current/blacklist 2 | # Format: basic-regex 3 | # 4 | # This file is the 'blacklist' file for the 'slackscan' utility. 5 | # Package files matching one of the following patterns will 6 | # be excluded from install and upgrade actions. 7 | # 8 | # Caution! 9 | # Remember these are regexes. Watch out for partial matches 10 | # e.g. 11 | # '/pan' would blacklist both 'pan' and 'pango' which is likely 12 | # not what your intended. I would suggest sticking with patterns 13 | # like: 14 | # /xap/pan- 15 | # 16 | 17 | ## Uncomment to prevent accidentally installing 32bit packages 18 | ## on a 64bit system: 19 | #-i[456]86-[^-\.]\+\.t.z$ 20 | 21 | ## Uncomment to exclude kernel source: 22 | # /kernel-source- 23 | 24 | ## Uncomment to exclude the 'huge' kernel: 25 | # /kernel-huge- 26 | -------------------------------------------------------------------------------- /etc/current.new/filter: -------------------------------------------------------------------------------- 1 | # /etc/slackup/current/filter 2 | # Format: basic-regex 3 | # 4 | # This file is the 'filter' file for the 'slackscan' utility. 5 | # Package files not matching one of the following patterns will 6 | # be excluded from install and upgrade actions. 7 | # 8 | # Patterns passed on the command line will be appended to those 9 | # in this file when processing the filters at run-time. 10 | # 11 | # Patterns in the blacklist file are processed after these 12 | # filters are applied. 13 | # 14 | 15 | ## The following example when uncommented would limit matches to 16 | ## packages found in slackware64-current and 'xv' from extra/ 17 | #/slackware64-current/slackware64/ 18 | #/slackware64-current/extra/xv 19 | -------------------------------------------------------------------------------- /etc/current.new/protect: -------------------------------------------------------------------------------- 1 | # /etc/slackscan/current/protect 2 | # Format: basic-regex 3 | # 4 | # This file is the 'protect' file for the 'slackscan' utility. 5 | # 6 | # This is essentially a blacklist specific to removal operations 7 | # and should be used to prevent the removal of packages whose 8 | # package file is no longer available in any configured location. 9 | # 10 | # Important Note: 11 | # unlike the blacklist file which matches the full path of the package file, 12 | # this file matches only package names, so there is no path components or 13 | # \.t.z suffix to match. 14 | # 15 | 16 | ## uncomment the following to protect any packages tagged _local: 17 | # _local$ 18 | 19 | ## uncomment the following to protect any packages tagged _SBo (slackbuilds.org): 20 | # _SBo$ 21 | -------------------------------------------------------------------------------- /etc/current.new/scan: -------------------------------------------------------------------------------- 1 | # /etc/slackscan/current/scan 2 | # 3 | # List of locations where 'slackscan' can recursively find 4 | # slackware packages. 5 | # 6 | # Each line may contain the path of a local directory, or 7 | # the URL of a remote CHECKSUMS.md5 file. 8 | # 9 | 10 | # These entries below use the mirrors.slackware.com redirector to 11 | # find a nearby mirror. If you have a preferred mirror then 12 | # adjust accordingly. 13 | 14 | https://mirrors.slackware.com/slackware/slackware64-current/slackware64/CHECKSUMS.md5 15 | 16 | # Uncomment to include a local directory of packages as an additional 17 | # package source: 18 | # /local/slackware/packages/ 19 | -------------------------------------------------------------------------------- /man/slackscan.8: -------------------------------------------------------------------------------- 1 | .TH SLACKSCAN 8 2025-05-26 "slackscan 3.8.1" 2 | .SH NAME 3 | slackscan \- Slackware Package Repository difference scanner 4 | .SH SYNOPSIS 5 | .B slackscan 6 | [ \fB-NBFIRSPq\fR ] [ \fB\-p \fIPROFILE\fR ] 7 | [ \fB\-i \fIFILENAME\fR ] [ \fB\-u \fIFILENAME\fR ] [ \fB\-r \fIFILENAME\fR ] 8 | .SH DESCRIPTION 9 | .B slackscan 10 | will scan the locations specified in its configuration profile for 11 | available Slackware package files. filter and blacklists are then 12 | applied and any package files that have not been excluded are compared 13 | to the packages installed on the host system. It will then write a 14 | list of packages or package files to the \fIFILENAME\fR(s) specified with 15 | the \fB\-i\fR, \fB\-u\fR, and \fB\-r\fR options. These output files 16 | many then be passed to other utility programs for action. 17 | .PP 18 | .TP 19 | .I PROFILE 20 | name of the slackscan configuration profile to be used. 21 | .TP 22 | .I FILENAME 23 | output filename. '\fB\-\fR' can be used to specify \fBstdout\fR. 24 | .SH OPTIONS 25 | .TP 26 | .BI \-p " PROFILE" 27 | use the config file contained in the specified \fBslackscan\fR(8) \fIPROFILE\fR. 28 | .TP 29 | .BI \-i " FILENAME" 30 | specify output \fIFILENAME\fR to hold the list of package files that need to be installed. 31 | .TP 32 | .BI \-u " FILENAME" 33 | specify output \fIFILENAME\fR to hold the list of package files that need to be updated. 34 | .TP 35 | .BI \-r " FILENAME" 36 | specify output \fIFILENAME\fR to hold the list of packages that need to be removed. 37 | .TP 38 | .B \-N 39 | do not gpg verify any \fBCHECKSUMS.md5\fR files specified as package 40 | source locations. 41 | .TP 42 | .B \-B 43 | ignore any blacklist file that is part of the configuration profile. 44 | .TP 45 | .B \-F 46 | ignore any filter file that is part of the configuration profile. 47 | .TP 48 | .B \-I 49 | ignore the contents of the package database directory. 50 | All available packages not blacklisted or filtered will be treated 51 | as new. 52 | .TP 53 | .B \-R 54 | ignore the version of installed packages. 55 | All available packages not blacklisted or filtered will be treated 56 | as outdated. 57 | .TP 58 | .B \-S 59 | add match patterns to the protect file for all the currently 60 | installed packages. 61 | 62 | .TP 63 | .B \-P 64 | ignore any protect file that is part of the configuration profile 65 | while scanning for removals. 66 | .TP 67 | .B \-h 68 | show usage text. 69 | .TP 70 | .B \-q 71 | quiet: do not print statistics to stdout on exit. 72 | .SH EXIT VALUES: 73 | .TP 74 | 0 75 | successful run, changes were found. 76 | .TP 77 | 2 78 | successful run, no changes were found. 79 | .TP 80 | 8 81 | gpg verify failed on md5sums file. 82 | .TP 83 | 16 84 | a critical failure occurred. 85 | .SH ENVIRONMENT 86 | .TP 87 | .B SLACKSCAN_PROFILE 88 | may be set to override the default profile name. A profile name 89 | specified with the \fB\-p\fR option on the command line will have 90 | precedence over this environment variable. When unset, the default 91 | is: '\fIdefault\fR'. 92 | .TP 93 | .B ROOT 94 | specifies an alternative root directory, as used in the pkgtools: 95 | .BR installpkg (8), 96 | .BR upgradepkg (8), 97 | .BR removepkg (8). 98 | .B slackscan 99 | will apply this prefix when locating the pkgtools package database 100 | directory that it will use to identify installed packages. 101 | .SH FILES 102 | .B slackscan 103 | is configured through the use of configuration 'profiles'. Each 104 | profile comprises of a set of files stored in a common profile 105 | directory located at: \fB/etc/slackscan/\fIPROFILE\fB/\fR, where 106 | \fIPROFILE\fR is the name of the profile. 107 | .PP 108 | Within each profile directory there will be one to four files, 109 | of which only the 'scan' file is mandatory: 110 | .TP 111 | .BI /etc/slackscan/ PROFILE /scan 112 | contains a list of package locations, one per line, which are to 113 | be scanned for packages. A package location may be one of: 114 | .RS 115 | .IP 116 | The absolute path of a directory on the filesystem. 117 | .IP 118 | The absolute path of a \fBCHECKSUMS.md5\fR in a directory on the 119 | filesystem. 120 | .IP 121 | The URL of a \fBCHECKSUMS.md5\fR file on a remote http(s) web-server. 122 | .RE 123 | .TP 124 | .BI /etc/slackscan/ PROFILE /filter 125 | A set of \fBregex\fR(7) that will be applied to the list of available 126 | package files. Only matching package files will be included in the 127 | comparision to the installed system. 128 | .TP 129 | .BI /etc/slackscan/ PROFILE /blacklist 130 | A set of \fBregex\fR(7) that will be applied to the list of available 131 | package files. Matching package files will be excluded from the 132 | comparision to the installed system.. 133 | .TP 134 | .BI /etc/slackscan/ PROFILE /protect 135 | A set of \fBregex\fR(7) to be applied to the list of packages that 136 | have been identified for removal owing to their package file nolonger 137 | being avaiable. Matching packages will be excluded from the output. 138 | A new protect file containing matching patterns for all installed 139 | packages may be generated by using the \fB\-S\fR option. 140 | .PP 141 | By default the patterns in the filter, blacklist and protect files 142 | will be interpreted as \fBbasic-regex\fR. To have \fBslackscan\fR 143 | interpret them as \fBextended-regex\fR include a comment line as 144 | follows: 145 | .RS 146 | \fB 147 | .nf 148 | # Format: extended-regex 149 | .fi 150 | \fR 151 | ..RE 152 | .SH NOTES 153 | Duplicate package files found while scanning package locations are 154 | handled in one of two ways, depending on whether the duplicate is found 155 | within the same package location, or across separate package locations. 156 | .PP 157 | When a duplicated package name is encountered across two separate package 158 | source locations then the first to be encountered will be used for any 159 | comparisions. 160 | .PP 161 | Within a single package source location the file with the highest version 162 | number will be compared. 163 | .PP 164 | When two versions of the same package are already installed, slackscan 165 | will compare available packages to the highest version installed, ignoring 166 | any lower numbered versions of the package. Note however that 167 | .BR upgradepkg (8) 168 | will remove all older versions of a package when upgrading them, so it is 169 | probably best to add \fIblacklist\fR and \fIprotect\fR file entries for 170 | any such packages and control them manually with 171 | .BR installpkg (8) 172 | and 173 | .BR removepkg (8)\fR. 174 | 175 | .SH EXAMPLES 176 | A basic invocation using the default profile might look like this: 177 | .RS 178 | .nf 179 | .B slackscan -i install.list -u update.list -r remove.list 180 | .fi 181 | .RE 182 | .SH SEE ALSO 183 | .BR slackup (8) 184 | .BR installpkg (8) 185 | .BR removepkg (8) 186 | .BR upgradepkg (8) 187 | -------------------------------------------------------------------------------- /man/slackscan_update_generator.8: -------------------------------------------------------------------------------- 1 | .TH SLACKSCAN_UPDATE_GENERATOR 8 2025-05-25 "slackscan 3.8.1" 2 | .SH NAME 3 | slackscan_update_generator \- formats slackscan output into shell commands 4 | .SH SYNOPSIS 5 | .B slackscan_update_generator 6 | .SH DESCRIPTION 7 | .B slackscan_update_generator 8 | will read, on stdin, the output of a slackscan -i or -u run and will write 9 | to stdout a sequence of shell commands to run the curl and pkgtools' 10 | upgradepkg commands. 11 | .PP 12 | .SH EXAMPLES 13 | .nf 14 | slackscan -i - -u - \\ 15 | | slackscan_update_generator > update_script.sh 16 | bash update_script.sh 17 | .fi 18 | .SH SEE ALSO 19 | .BR slackscan (8) 20 | -------------------------------------------------------------------------------- /man/slackup.8: -------------------------------------------------------------------------------- 1 | .TH SLACKUP 8 2025-05-26 "slackscan 3.8.1" 2 | .SH NAME 3 | slackup \- Slackware package update assistant 4 | .SH SYNOPSIS 5 | .B slackup 6 | [ \fIOPTIONS\fR ] [ \fB\-l\fR | \fB\-x\fR ] [ \fB\-p \fIPROFILE\fR ] 7 | [ \fIPATTERN\fR ...] 8 | .TP 9 | .I PROFILE 10 | configuration profile to be used. 11 | .TP 12 | .I PATTERN 13 | \fBregex\fR(7) pattern. Limit output to matching files or packagess. 14 | .SH DESCRIPTION 15 | .B slackup 16 | will invoke 17 | .BR slackscan (8) 18 | in order to determine which packages on a Slackware system need to 19 | be installed, updated or removed, and generate either: a 20 | list of packages requiring action; or a stream of POSIX shell commands 21 | that, when executed, would bring the installed system inline with the 22 | list of packages identified by 23 | .BR slackscan (8). 24 | .PP 25 | unless invoked with the \fB\-x\fR option, 26 | .B slackup 27 | will only writes to \fBstdout\fR, and makes no changes itself. 28 | .SH OPTIONS 29 | .TP 30 | .B \-l 31 | list package/pkgfile names only. Do not generate shell-commands. 32 | .TP 33 | .B \-x 34 | execute generated shell-commands automatically. Downloaded files 35 | will be stored in \fBSLACKUP_CACHE_DIR\fR or its default location: 36 | \fI/var/cache/packages\fR. 37 | .TP 38 | .B \-i 39 | include invocation of post-install scripts. 40 | .TP 41 | .B \-s 42 | include gpg signature verification of package files. 43 | .TP 44 | .B \-c 45 | add comment lines to the output to be more readable. 46 | .TP 47 | .B \-h 48 | show usage text. 49 | .TP 50 | .B \-E 51 | interpret PATTERN as extended-regex. The default is to interpret them 52 | as basic-regex. This option applies only to patterns specified on the 53 | command-line. 54 | .TP 55 | .B \-N 56 | do not gpg verify any CHECKSUMS.md5 files used. This is potentially 57 | insecure. 58 | .TP 59 | .B \-I 60 | ignore new packages. 61 | .TP 62 | .B \-U 63 | ignore updated packages. 64 | .TP 65 | .B \-R 66 | ignore removed packages. 67 | .TP 68 | .B \-B 69 | ignore the 'blacklist' file. 70 | .TP 71 | .B \-F 72 | ignore the 'filter' file. 73 | .TP 74 | .B \-P 75 | ignore the 'protect' file. 76 | .SH ENVIRONMENT 77 | .TP 78 | .B SLACKSCAN_PROFILE 79 | may be set to override the default profile name. A profile name 80 | specified with the \fB\-p\fR option on the command line will have 81 | precedence over this environment variable. When unset, the default 82 | is: '\fIdefault\fR'. 83 | .TP 84 | .B SLACKUP_CACHE_DIR 85 | may be set to override the default location in which downloaded 86 | packages are stored when \fBslackup\fR is used with the \fB\-x\fR 87 | option. When unset, the default is: \fI/var/cache/packages\fR. 88 | .SH FILES 89 | .TP 90 | .BR /etc/slackup/post-install/ 91 | A directory containing post-install scripts to be run after a package 92 | is installed or upgraded. To supply a post-install script, install it 93 | into this directory with the name of the package to which it 94 | applies. 95 | .SH EXAMPLES 96 | When the output of slackup is passed to a shell for execution, either 97 | through a pipeline or a file, any remote package files will be 98 | downloaded to the current directory. For this reason it's a good idea 99 | to make a dedicated directory and use that when invoking slackup in 100 | this manner, e.g. 101 | .PP 102 | .RS 103 | \fB 104 | .nf 105 | mkdir my_updates 106 | cd my_updates 107 | slackup -si > updates.sh 108 | sh ./updates.sh 109 | .fi 110 | \fR 111 | .RE 112 | .PP 113 | It would also be prudent to review the contents of \fIupdates.sh\fR 114 | prior to running it. 115 | .PP 116 | As this is a little awkward, the \fB\-x\fR option can be used to 117 | automatically execute the generated commands. When \fB\-x\fR is used, 118 | any downloaded files will be put in the directory specified by the 119 | \fBSLACKUP_CACHE_DIR\fR environment variable, or its default location: 120 | \fI/var/cache/packages\fR, but see \fBNOTES\fR below. 121 | .SH NOTES 122 | .PP 123 | Since using '\fB\-x\fR' doesn't give the user the chance to review 124 | what changes are about to be applied, running \fBslackup\fR without 125 | the \fB\-x\fR option prior to running it with \fB\-x\fR is a wise 126 | precaution. However, even then, there is still a window of exposure 127 | between the running of the two commands where changes to the list of 128 | available packages might occur. Using \fB\-x\fR is not recommended if 129 | this possibility is a concern. 130 | .PP 131 | When \fB\-x\fR is used the contents of the directory specified in 132 | \fBSLACKUP_CACHE_DIR\fR are not removed, neither before or after the 133 | generated commands are executed. The user may want to clear this 134 | periodically to reclaim diskspace. 135 | .PP 136 | .B Post-install scripts: 137 | .RS 138 | When invoked with the \fB\-i\fR option, \fBslackup\fR will look in the 139 | post-install directory for an executable/shell-script with the same 140 | name as the package. If found, an invocation of that executable will 141 | be included. \fBslackup\fR passes a single argument to the executable 142 | which will be the full pathname of the package-file that has just been 143 | installed or upgraded. 144 | .PP 145 | For example: if one wanted a 146 | .BR mkinitrd (8) 147 | command to be executed after installing or upgrading the 148 | \fIkernel-modules\fR package then it can be placed in a script named: 149 | \fI/etc/slackup/post-install/kernel-modules\fR 150 | .RE 151 | .SH SEE ALSO 152 | .BR slackscan (8) 153 | -------------------------------------------------------------------------------- /sbin/slackscan: -------------------------------------------------------------------------------- 1 | #!/bin/bash -p 2 | # 3 | # slackscan 4 | version='3.8.1' 5 | 6 | # Copyright (c) 2013-2023, Gary Langshaw. 7 | # Permission to use, copy, modify, and/or distribute this software for any 8 | # purpose with or without fee is hereby granted, provided that the above 9 | # copyright notice and this permission notice appear in all copies. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | 19 | set -o pipefail 20 | 21 | unset IFS 22 | PATH='/usr/bin' 23 | LC_ALL=C 24 | 25 | ######################################################################## 26 | # Defaults: 27 | 28 | SLACKSCAN_DIR='/etc/slackscan' 29 | 30 | ######################################################################## 31 | # Globals 32 | 33 | count_u=0 34 | count_i=0 35 | count_r=0 36 | 37 | ######################################################################## 38 | # functions: 39 | 40 | function die() 41 | { 42 | 1>&2 printf "%s: %s\n" "${0##*/}" "${2:-aborted.}" 43 | exit ${1:-16} 44 | } 45 | 46 | remove_comments() 47 | { 48 | grep -v -E '^ *(#|$)' "${1:--}" 49 | } 50 | 51 | file_regex_type() 52 | { 53 | grep -q '^[[:space:]]*# Format: extended-regex' ${1:--} \ 54 | && printf '-E' 55 | } 56 | 57 | function reformat_available() 58 | { 59 | # format: short-name long-name filename 60 | sed -e 's|^\(.*/\)\([^/]\+\)-\([^-/]\+\)-\([^-/]\+\)-\([0-9]\+\)\([^-/]*\)\(\.t[^-/]z\)$|\2 \2-\3-\4-\5\6 \1\2-\3-\4-\5\6\7| ; t ; d ' 61 | } 62 | 63 | function find_in_dir() 64 | { 65 | if [ ! -d "$1" ]; then 66 | die 16 "slackscan: directory not found, $1" 67 | fi 68 | 69 | find -L "$1" -type f -name "*.t?z" \ 70 | | reformat_available \ 71 | | sort -Vr -k 2,2 \ 72 | | sort -u -k 1,1 73 | 74 | if [ $? -ne 0 ]; then 75 | die 16 "error in find_in_dir()" 76 | fi 77 | } 78 | 79 | function fetch_md5() 80 | { 81 | local fd_sig 82 | 83 | exec {fd_sig}<> "${workdir:-${TMPDIR:-/tmp}}/signature" \ 84 | || die 16 "could not create 'signature' file" 85 | 86 | if curl --retry 3 -s -f -o /dev/fd/$fd_checksums "$1" ; then 87 | if [ ${o_skip_verify:-0} -ne 1 ]; then 88 | curl --retry 3 -s -f -o /dev/fd/$fd_sig "$1.asc" \ 89 | && $gpg_verify_cmd /dev/fd/$fd_sig /dev/fd/$fd_checksums >/dev/null 2>&1 \ 90 | || { die 8 "gpg verification failed on $1" ; } 91 | fi 92 | else 93 | die 16 "Aborted - could not fetch $1" 94 | fi 95 | 96 | exec {fd_sig}>&- 97 | } 98 | 99 | function reformat_md5() 100 | { 101 | # extracts filepaths matching .t?z, prefixing with path to CHECKSUMS.md5 102 | local prefix="${1%/}" 103 | sed -e "s|\([[:alnum:]]\{32\} \)\(\./\)\?\(.\+-[^-/]\+-[^-/]\+-[0-9]\+[^-/]*\.t[^-/]z\$\)|${prefix}/\3| ;t ;d" 104 | } 105 | 106 | function find_in_md5() 107 | { 108 | local prefix=${1%/*} 109 | local filename 110 | 111 | exec {fd_checksums}<> "${workdir:-${TMPDIR:-/tmp}}/checksums" \ 112 | || die 16 "could not create checksums file" 113 | 114 | case "$1" in 115 | http://*|https://*) fetch_md5 "$1" 116 | filename=/dev/fd/$fd_checksums 117 | ;; 118 | 119 | file://*|/* ) filename=${1#file://} ;; 120 | *) die 16 "unsupported: $1" ;; 121 | esac 122 | 123 | if [ ! -r "$filename" ]; then 124 | die 16 "slackscan: file not found, $filename" 125 | fi 126 | 127 | reformat_md5 "$prefix" < "$filename" \ 128 | | reformat_available \ 129 | | sort -Vr -k 2,2 \ 130 | | sort -u -k 1,1 131 | 132 | exec {fd_checksums}>&- 133 | } 134 | 135 | function find_available() 136 | { 137 | local pkg_source pkg_sources 138 | 139 | mapfile -t pkg_sources < <( remove_comments "$conf" ) \ 140 | || die 16 "could not read configuration file" 141 | 142 | if [ ${#pkg_sources[@]} -eq 0 ]; then 143 | die 16 "no package source locations found" 144 | fi 145 | 146 | for pkg_source in ${pkg_sources[@]} 147 | do 148 | case "$pkg_source" in 149 | *.md5|*.MD5) find_in_md5 "$pkg_source" ;; 150 | *) find_in_dir "$pkg_source" ;; 151 | esac 152 | done 153 | } 154 | 155 | function get_pkgdb_dir() 156 | { 157 | local dir 158 | 159 | for dir in "$ROOT/var/lib/pkgtools/packages" "$ROOT/var/log/packages" '' 160 | do 161 | [ -d "$dir" ] && break 162 | done 163 | 164 | [ -n "$dir" ] && printf "%s" "$dir" 165 | } 166 | 167 | function reformat_installed() 168 | { 169 | # format: short-name long-name 170 | sed -e 's|^\(.*/\)\([^/]\+\)-\([^-/]\+\)-\([^-/]\+\)-\([0-9]\+\)\([^-]*\)$|\2 \2-\3-\4-\5\6| ; t ; d' 171 | } 172 | 173 | function list_installed() 174 | { 175 | local pkgdatadir=$( get_pkgdb_dir ) 176 | 177 | if [ "${o_ignore_database:-0}" -eq 1 ]; then 178 | return 0 179 | fi 180 | 181 | find -H "$pkgdatadir" -type f \ 182 | | reformat_installed \ 183 | | sort -k 1,1 184 | 185 | if [ $? -ne 0 ]; then 186 | die 16 "error in list_installed()" 187 | fi 188 | } 189 | 190 | function run_file_filter() 191 | { 192 | local infile=$1 grep_opt=$2 193 | local fd_temp1 filter_cmd 194 | local count regex_type 195 | 196 | if [ -e "$infile" ]; then 197 | regex_type=$( file_regex_type "$infile") 198 | exec {fd_temp1}<> "$( mktemp -p "$workdir" temp1.XXXXXX )" 199 | remove_comments "$infile" >&$fd_temp1 200 | count=$( wc -l &- 212 | } 213 | 214 | function apply_filter() 215 | { 216 | if [ ${o_ignore_filter:-0} -eq 1 ]; then 217 | cat 218 | else 219 | run_file_filter "$filter_file" 220 | fi 221 | } 222 | 223 | function apply_blacklist() 224 | { 225 | if [ ${o_ignore_blacklist:-0} -eq 1 ]; then 226 | cat 227 | else 228 | run_file_filter "$blacklist_file" -v 229 | fi 230 | } 231 | 232 | function list_available_filtered() 233 | { 234 | find_available \ 235 | | apply_filter \ 236 | | apply_blacklist \ 237 | | sort -u -k 1,1 238 | 239 | if [ $? -ne 0 ]; then 240 | die 16 "error in list_available_filtered()" 241 | fi 242 | } 243 | 244 | function apply_protect() 245 | { 246 | if [ ${o_ignore_protect:-0} -eq 1 ]; then 247 | cat 248 | else 249 | run_file_filter "$protect_file" -v 250 | fi 251 | } 252 | 253 | function create_table 254 | { 255 | local dups fd_available fd_installed 256 | 257 | exec {fd_available}<> "${workdir:-${TNPDIR:-/tmp}}/available" \ 258 | || die 16 "could not open 'available' file." 259 | 260 | exec {fd_installed}<> "${workdir:-${TMPDIR:-/tmp}}/installed" \ 261 | || die 16 "could not open 'installed' file." 262 | 263 | list_available_filtered >&$fd_available 264 | 265 | list_installed | sort -Vr -k 2,2 | sort -u -k 1,1 >&$fd_installed 266 | 267 | 268 | sort -u -k 1,1 <( cut -f1 -d ' ' /dev/fd/$fd_installed ) \ 269 | <( cut -f1 -d ' ' /dev/fd/$fd_available ) \ 270 | | join -a 1 -e 'not-installed' -o 1.1,2.2 - /dev/fd/$fd_installed \ 271 | | join -a 1 -e 'not-available' -o 1.1,1.2,2.2,2.3 - /dev/fd/$fd_available 272 | 273 | if [ $? -ne 0 ]; then 274 | die 16 "error in create_table()" 275 | fi 276 | 277 | exec {fd_available}>&- 278 | exec {fd_installed}>&- 279 | } 280 | 281 | function report() 282 | { 283 | local package installed available pkgpath 284 | local fd_rep_i fd_rep_u fd_rep_r 285 | 286 | [ "$o_install" = "-" ] && o_install=/dev/fd/1 287 | [ "$o_upgrade" = "-" ] && o_upgrade=/dev/fd/1 288 | [ "$o_remove" = "-" ] && o_remove=/dev/fd/1 289 | 290 | if [ ! -z "$o_install" ]; then 291 | exec {fd_rep_i}<> "$o_install" || die 16 "could not open -i file" 292 | fi 293 | 294 | if [ ! -z "$o_upgrade" ]; then 295 | exec {fd_rep_u}<> "$o_upgrade" || die 16 "could not open -u file" 296 | fi 297 | 298 | if [ ! -z "$o_remove" ]; then 299 | exec {fd_rep_r}<> "$o_remove" || die 16 "could not open -r file" 300 | fi 301 | 302 | while read package installed available pkgpath 303 | do 304 | if [ "$installed" != 'not-installed' ] && \ 305 | [ "$available" != 'not-available' ] && \ 306 | [ "$available" != "$installed" -o "${o_reinstall:-0}" -eq 1 ] 307 | then 308 | (( count_u++ )) 309 | [ "$o_upgrade" ] && echo "$pkgpath" >&$fd_rep_u 310 | fi 311 | if [ "$installed" == 'not-installed' ] 312 | then 313 | (( count_i++ )) 314 | [ "$o_install" ] && echo "$pkgpath" >&$fd_rep_i 315 | fi 316 | if [ "$installed" != 'not-installed' ] && \ 317 | [ "$available" == 'not-available' ] 318 | then 319 | (( count_r++ )) 320 | [ "$o_remove" ] && echo "$installed" | apply_protect >&$fd_rep_r 321 | fi 322 | done 323 | 324 | [ -n "$fd_rep_i" ] && exec {fd_rep_i}>&- 325 | [ -n "$fd_rep_u" ] && exec {fd_rep_u}>&- 326 | [ -n "$fd_rep_r" ] && exec {fd_rep_r}>&- 327 | } 328 | 329 | function print_stats() 330 | { 331 | printf "%s\n" \ 332 | "# Package Installs: $count_i" \ 333 | "# Package Upgrades: $count_u" \ 334 | "# Package Removals: $count_r" 335 | } 336 | 337 | function populate_protect() 338 | { 339 | if ! cmp -s "${protect_file}" "${protect_file}~" ; then 340 | cp "${protect_file}" "${protect_file}~" 341 | fi 342 | 343 | printf '%s\n' \ 344 | "# ${protect_file}" \ 345 | '# Format: basic-regex' \ 346 | '#' \ 347 | "# This file is the 'protect' file for the 'slackscan' utility." \ 348 | '# It was autogenerated by "slackscan -S".' \ 349 | '#' \ 350 | '# This is essentially a blacklist specific to removal operations' \ 351 | '# and should be used to prevent the removal of packages whose' \ 352 | '# package file is no longer available in any configured location.' \ 353 | '#' \ 354 | '# Important Note:' \ 355 | '# unlike the blacklist file which matches the full path of the package file,' \ 356 | '# this file matches only package names, so there is no path components or' \ 357 | '# \.t.z suffix to match.' \ 358 | '#' \ 359 | '' \ 360 | '## uncomment the following to protect any packages tagged _local:' \ 361 | '# _local$' \ 362 | '' \ 363 | '## uncomment the following to protect any packages tagged _SBo (slackbuilds.org):' \ 364 | '# _SBo$' \ 365 | '## Autogenerated list:' \ 366 | '' \ 367 | > "${protect_file}" 368 | 369 | list_installed \ 370 | | sort -Vr -k 2,2 | sort -u -k 1,1 \ 371 | | sed 's/\([^ ]\+\)\(.*\)/^\1-/' >> "${protect_file}" 372 | } 373 | 374 | ######################################################################## 375 | # parse arguments 376 | 377 | unset o_install o_remove o_upgrade \ 378 | o_ignore_blacklist o_ignore_filter o_ignore_protect \ 379 | o_populate_protect o_ignore_database o_reinstall \ 380 | o_config o_profile o_usage o_skip_verify o_quiet 381 | 382 | while getopts ':p:i:u:r:hqBFINPRS' opt 383 | do 384 | case "$opt" in 385 | p) o_profile=$OPTARG ;; 386 | h) o_usage=1 ;; 387 | q) o_quiet=1 ;; 388 | i) o_install=$OPTARG ;; 389 | r) o_remove=$OPTARG ;; 390 | u) o_upgrade=$OPTARG ;; 391 | B) o_ignore_blacklist=1 ;; 392 | F) o_ignore_filter=1 ;; 393 | I) o_ignore_database=1 ;; 394 | N) o_skip_verify=1 ;; 395 | P) o_ignore_protect=1 ;; 396 | S) o_populate_protect=1 ;; 397 | R) o_reinstall=1 ;; 398 | \?) die 16 "Unexpected option: -$OPTARG" ;; 399 | :) die 16 "Missing operand for option -$OPTARG" ;; 400 | esac 401 | done 402 | shift $(( OPTIND - 1 )) 403 | 404 | if [ -z "$o_profile" ]; then 405 | o_profile="${SLACKSCAN_PROFILE:-default}" 406 | fi 407 | 408 | conf="${SLACKSCAN_DIR%/}/${o_profile}/scan" 409 | filter_file="${SLACKSCAN_DIR%/}/${o_profile}/filter" 410 | blacklist_file="${SLACKSCAN_DIR%/}/${o_profile}/blacklist" 411 | protect_file="${SLACKSCAN_DIR%/}/${o_profile}/protect" 412 | 413 | ######################################################################## 414 | 415 | if [ "$o_usage" ]; then 416 | printf '%s\n' \ 417 | 'Usage:' \ 418 | ' slackscan [ -NBFIPSq ] [ [ -p profile ]' \ 419 | ' [-i filename ] [ -u filename ] [ -r filename ] ' \ 420 | '' \ 421 | ' where, ' \ 422 | ' -p : specifies profile name.' \ 423 | ' -q : quiet: do not print statistics.' \ 424 | ' -i : specifies file to hold list of packages to be installed. ' \ 425 | ' -u : specifies file to hold list of packages to be upgraded. ' \ 426 | ' -r : specifies file to hold list of packages to be removed. ' \ 427 | " -N : skip gpg verify of downloaded CHECKSUMS.md5 files. " \ 428 | ' (INSECURE). ' \ 429 | ' -B : ignore the blacklist file.' \ 430 | ' -F : ignore the filter file.' \ 431 | ' -I : ignore the package database. ' \ 432 | ' All available packages will be treated as new.' \ 433 | ' -R : ignore package versions. ' \ 434 | ' All installed packages will be treated as outdated.' \ 435 | ' -P : ignore the protect file.' \ 436 | ' -S : Store currently installed package names in protect file.' \ 437 | '' 438 | exit 0 439 | fi 440 | 441 | ######################################################################## 442 | # check availability of external utilities: 443 | 444 | type mktemp find grep sed cut cmp sort join uniq curl >/dev/null \ 445 | || die 16 "external utilties not found" 446 | 447 | unset gpg_verify_cmd 448 | 449 | if [ "${o_skip_verify:-0}" -eq 0 ]; then 450 | for file in gpgv1 gpgv gpgv2 gpg1 gpg gpg2 "" 451 | do 452 | gpg=$(type -p "$file") && break 453 | done 454 | 455 | case "$gpg" in 456 | */gpgv* ) gpg_verify_cmd="$gpg --keyring pubring.gpg" ;; 457 | */gpg* ) gpg_verify_cmd="$gpg --verify" ;; 458 | * ) die 16 "Could not find gpg command" ;; 459 | esac 460 | unset gpg file 461 | fi 462 | 463 | ######################################################################## 464 | # If '-S' was specified store the list of installed packages into 465 | # the protect file. Useful for preventing accidental package removals. 466 | 467 | if [ ${o_populate_protect:-0} -eq 1 ]; then 468 | populate_protect 469 | fi 470 | 471 | ######################################################################## 472 | 473 | workdir="$( mktemp -d /tmp/slackscan.XXXXXX )" \ 474 | && cd "$workdir" || die 16 "could not create workdir" 475 | 476 | exec {table}<> "$workdir/table" \ 477 | || die 16 "could not create table file" 478 | 479 | create_table >&$table 480 | 481 | report < /dev/fd/$table 482 | 483 | if [ ${o_quiet:-0} -eq 0 ]; then 484 | print_stats 485 | fi 486 | 487 | if (( count_i + count_u + count_r > 0 )); then 488 | rc=0 489 | else 490 | rc=2 491 | fi 492 | 493 | exec {table}>&- 494 | 495 | ######################################################################## 496 | # clean-up 497 | 498 | cd /tmp 499 | rm -r "$workdir" 500 | 501 | exit $rc 502 | 503 | ################################################################# End. # 504 | -------------------------------------------------------------------------------- /sbin/slackscan_update_generator: -------------------------------------------------------------------------------- 1 | #!/bin/awk -f 2 | # 3 | # slackscan_update_generator.awk, 4 | # Version 2.4 5 | # 6 | # This awk-script takes a list of Slackware packages on stdin and 7 | # converts them to a stream of pkgtools updatepkg commands. It is 8 | # intended for use with the output generated with slackscan's -i and 9 | # -u options. 10 | # 11 | 12 | BEGIN { 13 | FS="/" 14 | url = 0 15 | 16 | print "# Package update commands generated by slackscan_update_generator.awk" 17 | print "#" 18 | } 19 | 20 | /^https?:\/\/.*\/[^/]+-[^-/]+-[^-/]+-[0-9]+[^-/.]*\.t[^-/.]z$/ { 21 | print "curl --retry 3 -O '"$0"'" 22 | print "curl --retry 3 -O '"$0".asc'" 23 | url = 1 24 | } 25 | 26 | /^(.*\/)*[^/]+-[^-/]+-[^-/]+-[0-9]+[^-/.]*\.t[^-/.]z$/ { 27 | if ( url == 1 ) 28 | f = $NF 29 | else 30 | f = $0 31 | 32 | print "gpgv --keyring pubring.gpg \\" 33 | print " '"f".asc' \\" 34 | print " '"f"' \\" 35 | print "&& upgradepkg --install-new '"f"' " 36 | print "" 37 | 38 | url = 0 39 | } 40 | -------------------------------------------------------------------------------- /sbin/slackup: -------------------------------------------------------------------------------- 1 | #!/bin/bash -p 2 | # 3 | # slackup 4 | version=3.8.1 5 | # 6 | # Script to generate the sequence of package-management commands 7 | # needed to syncronize the state of the installed system with the 8 | # contents of a local package repository. 9 | # 10 | # Copyright (c) 2021, Gary Langshaw. 11 | # Permission to use, copy, modify, and/or distribute this software for any 12 | # purpose with or without fee is hereby granted, provided that the above 13 | # copyright notice and this permission notice appear in all copies. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | 23 | set -o pipefail 24 | 25 | PATH=/usr/bin:/usr/sbin:/bin:/sbin:/usr/local/bin:/usr/local/sbin: 26 | LC_ALL=C 27 | unset IFS 28 | umask 022 29 | 30 | ######################################################################## 31 | # Defaults: 32 | 33 | SLACKUP_DIR='/etc/slackup' 34 | POST_INSTALL_DIR="$SLACKUP_DIR/post-install" 35 | 36 | : ${SLACKUP_CACHE_DIR:=/var/cache/packages} 37 | 38 | ######################################################################## 39 | # functions: 40 | 41 | die() 42 | { 43 | 2>&1 printf "%s: %s\n" "${0##*/}" "${2:-aborted.}" 44 | exit ${1:-1} 45 | } 46 | 47 | remove_comments() 48 | { 49 | grep -v -E '^ *(#|$)' "${1:--}" 50 | } 51 | 52 | cleanup() 53 | { 54 | cd /tmp && [ -d "$workdir" ] && rm -r "$workdir" 55 | } 56 | 57 | ######################################################################## 58 | # Parse options: 59 | 60 | unset o_usage o_verify_pkg_sig 61 | unset o_regex_type o_comment 62 | unset o_profile 63 | unset o_post_install 64 | unset o_list_only 65 | unset o_execute 66 | unset o_ignore_blacklist 67 | unset o_ignore_filter 68 | unset o_ignore_protect 69 | o_verify_checksums=1 70 | o_do_install=1 71 | o_do_upgrade=1 72 | o_do_remove=1 73 | 74 | while getopts ':chilsxNPBFEIURb:p:' opt 75 | do 76 | case "$opt" in 77 | I) o_do_install=0 ;; 78 | U) o_do_upgrade=0 ;; 79 | R) o_do_remove=0 ;; 80 | E) o_regex_type='-E' ;; 81 | B) o_ignore_blacklist='-B' ;; 82 | F) o_ignore_filter='-F' ;; 83 | P) o_ignore_protect='-P' ;; 84 | N) o_verify_checksums=0 ;; 85 | c) o_comment=1 ;; 86 | h) o_usage=1 ;; 87 | i) o_post_install=1 ;; 88 | l) o_list_only=1 ;; 89 | x) o_execute=1 ;; 90 | p) o_profile=$OPTARG ;; 91 | s) o_verify_pkg_sig=1 ;; 92 | \?) die 1 "Unexpected option: -$OPTARG" ;; 93 | :) die 1 "Missing operand for option -$OPTARG" ;; 94 | esac 95 | done 96 | shift $(( OPTIND - 1 )) 97 | 98 | ######################################################################## 99 | # Usage: 100 | 101 | show_usage() 102 | { 103 | printf '%s\n' \ 104 | "slackup: write a sequence of package update commands to stdout" \ 105 | '' \ 106 | 'Usage:' \ 107 | ' slackup [ OPTIONS ] [ -l | -x ] [ -p PROFILE ] [ PATTERN ... ]' \ 108 | ' slackup -h' \ 109 | '' \ 110 | " PROFILE: configuration profile. DEFAULT=$DEFAULT_PROFILE" \ 111 | ' PATTERN: regex pattern: limit output to matching files or packages.' \ 112 | '' \ 113 | ' OPTIONS:' \ 114 | ' -l list package/pkgfile names only.' \ 115 | ' -x execute generated commands instead of writing them to stdout. ' \ 116 | ' -c add comment lines to output to be more readable.' \ 117 | ' -i include invocation of post-install scripts. ' \ 118 | ' -s include gpg verify of package files. ' \ 119 | ' -h show usage text.' \ 120 | ' -E interpret PATTERN as extended-regex.' \ 121 | ' -N do not gpg verify CHECKSUMS.md5 files.' \ 122 | ' -I ignore new packages.' \ 123 | ' -U ignore updated packages.' \ 124 | ' -R ignore removed packages.' \ 125 | ' -B ignore the blacklist file.' \ 126 | ' -F ignore the filter file.' \ 127 | ' -P ignore the protect file.' \ 128 | '' 129 | exit ${1:-0} 130 | } 131 | 132 | if [ "$o_usage" ]; then 133 | show_usage 134 | fi 135 | 136 | if [ ${o_execute:-0} -eq 1 ] && [ ${o_list_only:-0} -eq 1 ]; then 137 | die 1 "-l and -x are mutually exclusive." 138 | fi 139 | 140 | ######################################################################## 141 | # check availability of external utilities: 142 | 143 | if ! type mktemp xargs grep sed >/dev/null ; then 144 | die 1 "external dependencies missing." 145 | fi 146 | 147 | unset gpg_verify_cmd 148 | 149 | for file in gpgv1 gpgv gpgv2 gpg1 gpg gpg2 "" 150 | do 151 | gpg=$(type -p "$file") && break 152 | done 153 | 154 | case "$gpg" in 155 | */gpgv* ) gpg_verify_cmd="$gpg --keyring pubring.gpg" ;; 156 | */gpg* ) gpg_verify_cmd="$gpg --verify" ;; 157 | * ) if [ "${o_verify_checksums:-1}" -eq 1 ] \ 158 | [ "${o_verify_pkg_sig:-0}" -eq 1 ] ; then 159 | die 16 "Could not find gpg command" 160 | fi 161 | ;; 162 | esac 163 | unset gpg file 164 | 165 | ######################################################################## 166 | # temporary workdir/files: 167 | 168 | workdir="$( mktemp -d /tmp/slackup.XXXXXX )" \ 169 | && cd "$workdir" || die 1 "could not create workdir" 170 | 171 | exec {install}<> "$workdir/install.list" \ 172 | || die 1 "could not create workfile" 173 | exec {upgrade}<> "$workdir/upgrade.list" \ 174 | || die 1 "could not create workfile" 175 | exec {remove}<> "$workdir/remove.list" \ 176 | || die 1 "could not create workfile" 177 | exec {filter_cli}<> "$workdir/filter_cli" \ 178 | || die 1 "could not create workfile" 179 | exec {fl_install}<> "$workdir/fl_install.list" \ 180 | || die 1 "could not create workfile" 181 | exec {fl_upgrade}<> "$workdir/fl_upgrade.list" \ 182 | || die 1 "could not create workfile" 183 | exec {fl_remove}<> "$workdir/fl_remove.list" \ 184 | || die 1 "could not create workfile" 185 | 186 | ######################################################################## 187 | # Generate lists: 188 | 189 | [ ${o_verify_checksums:-1} -eq 0 ] && slackscan_opt='-N' 190 | 191 | /usr/sbin/slackscan \ 192 | -q \ 193 | ${slackscan_opt} \ 194 | ${o_ignore_filter} ${o_ignore_blacklist} ${o_ignore_protect} \ 195 | ${o_profile:+-p $o_profile} \ 196 | -i /dev/fd/$install \ 197 | -u /dev/fd/$upgrade \ 198 | -r /dev/fd/$remove 199 | 200 | case "$?" in 201 | 0) : ;; 202 | 2) cleanup ; exit 0 ;; 203 | *) die 1 "slackscan exited rc=$?." ;; 204 | esac 205 | 206 | ######################################################################## 207 | # Apply filters the command-line: 208 | 209 | if [ $# -gt 0 ]; then 210 | while [ $# -gt 0 ] 211 | do 212 | if [ "$1" = '-' ]; then 213 | remove_comments /dev/stdin >&$filter_cli 214 | else 215 | printf "%s\n" "$1" >&$filter_cli 216 | fi 217 | shift 218 | done 219 | fi 220 | 221 | filter_cli_count=$( wc -l /dev/fd/$fl_install 229 | $filter_cli_cmd /dev/fd/$fl_upgrade 230 | $filter_cli_cmd /dev/fd/$fl_remove 231 | 232 | exec {install}<&- {upgrade}<&- {remove}<&- 233 | install=$fl_install 234 | upgrade=$fl_upgrade 235 | remove=$fl_remove 236 | 237 | ######################################################################## 238 | # Generate update command stream: 239 | 240 | if [ ${o_comment:-0} -eq 1 ]; then 241 | printf '%s\n' \ 242 | "#!/bin/sh" \ 243 | "# Generated by slackup on host: $(hostname), $(date)" 244 | fi 245 | 246 | gen_up() 247 | { 248 | local pkg_opt="$1" 249 | while read pkgfile 250 | do 251 | pkgfile=$( sed 's/\([^-+/_.:@[:alnum:]]\)/\\\1/g' <<< "$pkgfile" ) # sanitise 252 | if [ ${o_comment:-0} -eq 1 ]; then 253 | printf '#\n# %s\n#\n' "${pkgfile##*/}" 254 | fi 255 | case "$pkgfile" in 256 | http://* | https://* ) 257 | printf 'curl --retry 3 -C - -O %s\n' "$pkgfile" 258 | [ ${o_verify_pkg_sig:-0} -eq 1 ] && printf 'curl --retry 3 -O %s.asc\n' "$pkgfile" 259 | pkgfile=${pkgfile##*/} 260 | ;; 261 | esac 262 | if [ ${o_verify_pkg_sig:-0} -eq 1 ]; then 263 | printf '%s \\\n %s \\\n %s \\\n&& ' \ 264 | "$gpg_verify_cmd" "$pkgfile.asc" "$pkgfile" 265 | fi 266 | printf 'upgradepkg %s %s' "$pkg_opt" "$pkgfile" 267 | if [ ${o_post_install:-0} -eq 1 ]; then 268 | pkgname=${pkgfile##*/} 269 | pkgname=${pkgname%-?*-?*-?*.t?z} 270 | post_cmd="$POST_INSTALL_DIR/$pkgname" 271 | if [ -x "$post_cmd" ]; then 272 | printf ' \\\n&& %s %s' "$post_cmd" "$pkgfile" 273 | fi 274 | fi 275 | printf '\n' 276 | done 277 | } 278 | 279 | gen_rm() 280 | { 281 | while read pkg 282 | do 283 | pkg=$( sed 's/\([^-+/_.@[:alnum:]]\)/\\\1/g' <<< "$pkg" ) # sanitise 284 | if [ ${o_comment:-0} -eq 1 ]; then 285 | printf '#\n# %s\n#\n' "$pkg" 286 | fi 287 | printf 'removepkg %s\n' "$pkg" 288 | done 289 | } 290 | 291 | gen_list() 292 | { 293 | [ ${o_do_install:-1} -eq 1 ] && cat < /dev/fd/$install 294 | [ ${o_do_upgrade:-1} -eq 1 ] && cat < /dev/fd/$upgrade 295 | [ ${o_do_remove:-1} -eq 1 ] && cat < /dev/fd/$remove 296 | } 297 | 298 | gen_shell_commands() 299 | { 300 | [ ${o_do_install:-1} -eq 1 ] && gen_up '--install-new' < /dev/fd/$install 301 | [ ${o_do_upgrade:-1} -eq 1 ] && gen_up < /dev/fd/$upgrade 302 | [ ${o_do_remove:-1} -eq 1 ] && gen_rm < /dev/fd/$remove 303 | } 304 | 305 | if [ ${o_list_only:-0} -eq 1 ]; then 306 | gen_list 307 | elif [ ${o_execute:-0} -eq 1 ]; then 308 | ( cd "${SLACKUP_CACHE_DIR:-.}" && gen_shell_commands | /bin/sh ) 309 | else 310 | gen_shell_commands 311 | fi 312 | 313 | ######################################################################## 314 | # cleanup: 315 | 316 | cleanup 317 | 318 | exit 0 319 | 320 | ################################################################# End. # 321 | -------------------------------------------------------------------------------- /slackscan.Slackbuild: -------------------------------------------------------------------------------- 1 | #!/bin/bash -p 2 | # 3 | # Slackbuild to package slackscan scripts. 4 | 5 | NAME=slackscan 6 | VERSION=3.8.1 7 | ARCH=noarch 8 | BUILD=1 9 | 10 | SLACKBUILD="$( realpath "$0" )" 11 | CWD="$( dirname "$SLACKBUILD" )" 12 | 13 | workdir="$( mktemp -d /tmp/${NAME}_slackbuild.XXXXXX )" || exit 1 14 | PKG="$workdir/pkg" 15 | 16 | mkdir "$PKG" && chmod 755 "$PKG" && cd "$PKG" || exit 1 17 | for dir in \ 18 | install usr/sbin etc/slackscan etc/slackup/post-install usr/man/man8 19 | do 20 | install -o root -g root -m 755 -d "$dir" 21 | done 22 | 23 | cd "$CWD" 24 | 25 | ( cd etc && cp -r * "$PKG/etc/slackscan/" ) 26 | install -t "$PKG/usr/sbin/" -o root -g root -m 755 sbin/* 27 | install -t "$PKG/usr/doc/slackscan-$VERSION" -o root -g root -m 644 README* 28 | install -t "$PKG/usr/doc/slackscan-$VERSION/slackup/post-install" -o root -g root -m 644 samples/post-install/* 29 | 30 | gzip -c man/slackup.8 \ 31 | > "$PKG/usr/man/man8/slackup.8.gz" 32 | gzip -c man/slackscan.8 \ 33 | > "$PKG/usr/man/man8/slackscan.8.gz" 34 | gzip -c man/slackscan_update_generator.8 \ 35 | > "$PKG/usr/man/man8/slackscan_update_generator.8.gz" 36 | 37 | install -t "$PKG/install/" -o root -g root -m 755 doinst.sh 38 | cat <<-_EOF > "$PKG/install/slack-desc" 39 | # HOW TO EDIT THIS FILE: 40 | # The "handy ruler" below makes it easier to edit a package description. Line 41 | # up the first '|' above the ':' following the base package name, and the '|' 42 | # on the right side marks the last column you can put a character in. You must 43 | # make exactly 11 lines for the formatting to be correct. It's also 44 | # customary to leave one space after the ':'. 45 | 46 | |-----handy-ruler--------------------------------------------------------| 47 | slackscan: slackscan (slackscan - package update aid) 48 | slackscan: 49 | slackscan: 'slackscan' is a script to aid the administrator in keeping a 50 | slackscan: Slackware system updated. It compares the installed system to 51 | slackscan: the packages available in its configured locations and generates lists 52 | slackscan: of packages that should be installed, updated or removed in order to 53 | slackscan: bring the host system in-step with the available packages. 54 | slackscan: 55 | slackscan: Multiple local and/or remote package sources (repos) are supported, 56 | slackscan: 57 | slackscan: homepage: https://github.com/glangshaw/slackscan 58 | _EOF 59 | 60 | cd "$PKG" && makepkg -l y -c n "/tmp/$NAME-$VERSION-$ARCH-$BUILD.tgz" 61 | --------------------------------------------------------------------------------