1{ 2 pkgs, 3 buildEnv, 4 runCommand, 5 lib, 6 stdenv, 7 freebsd, 8 binlore, 9}: 10 11# These are some unix tools that are commonly included in the /usr/bin 12# and /usr/sbin directory under more normal distributions. Along with 13# coreutils, these are commonly assumed to be available by build 14# systems, but we can't assume they are available. In Nix, we list 15# each program by name directly through this unixtools attribute. 16 17# You should always try to use single binaries when available. For 18# instance, if your program needs to use "ps", just list it as a build 19# input, not "procps" which requires Linux. 20 21let 22 inherit (lib) 23 getBin 24 getOutput 25 mapAttrs 26 platforms 27 ; 28 29 version = "1003.1-2008"; 30 31 singleBinary = 32 cmd: providers: 33 let 34 provider = providers.${stdenv.hostPlatform.parsed.kernel.name} or providers.linux; 35 bin = "${getBin provider}/bin/${cmd}"; 36 manDir = "${getOutput "man" provider}/share/man"; 37 in 38 runCommand "${cmd}-${provider.name}" 39 { 40 meta = { 41 mainProgram = cmd; 42 priority = 10; 43 platforms = platforms.${stdenv.hostPlatform.parsed.kernel.name} or platforms.all; 44 }; 45 passthru = { 46 inherit provider; 47 inherit (provider) version; 48 } 49 // lib.optionalAttrs (builtins.hasAttr "binlore" providers) { 50 binlore.out = (binlore.synthesize (getBin bins.${cmd}) providers.binlore); 51 }; 52 preferLocalBuild = true; 53 } 54 '' 55 if ! [ -x ${bin} ]; then 56 echo Cannot find command ${cmd} 57 exit 1 58 fi 59 60 mkdir -p $out/bin 61 ln -s ${bin} $out/bin/${cmd} 62 63 if [ -d ${manDir} ]; then 64 manpages=($(cd ${manDir} ; find . -name '${cmd}*')) 65 for manpage in "''${manpages[@]}"; do 66 mkdir -p $out/share/man/$(dirname $manpage) 67 ln -s ${manDir}/$manpage $out/share/man/$manpage 68 done 69 fi 70 ''; 71 72 # more is unavailable in darwin 73 # so we just use less 74 more_compat = runCommand "more-${pkgs.less.name}" { } '' 75 mkdir -p $out/bin 76 ln -s ${pkgs.less}/bin/less $out/bin/more 77 ''; 78 79 bins = mapAttrs singleBinary { 80 # singular binaries 81 arp = { 82 linux = pkgs.net-tools; 83 darwin = pkgs.darwin.network_cmds; 84 freebsd = pkgs.freebsd.arp; 85 }; 86 col = { 87 linux = pkgs.util-linux; 88 darwin = pkgs.darwin.text_cmds; 89 }; 90 column = { 91 linux = pkgs.util-linux; 92 darwin = pkgs.darwin.text_cmds; 93 }; 94 eject = { 95 linux = pkgs.util-linux; 96 }; 97 getconf = { 98 linux = if stdenv.hostPlatform.libc == "glibc" then pkgs.libc else pkgs.netbsd.getconf; 99 darwin = pkgs.darwin.system_cmds; 100 # I don't see any obvious arg exec in the doc/manpage 101 binlore = '' 102 execer cannot bin/getconf 103 ''; 104 }; 105 getent = { 106 linux = if stdenv.hostPlatform.libc == "glibc" then pkgs.libc.getent else pkgs.netbsd.getent; 107 darwin = pkgs.netbsd.getent; 108 freebsd = pkgs.freebsd.getent; 109 openbsd = pkgs.openbsd.getent; 110 }; 111 getopt = { 112 linux = pkgs.util-linux; 113 darwin = pkgs.getopt; 114 }; 115 fdisk = { 116 linux = pkgs.util-linux; 117 darwin = pkgs.darwin.diskdev_cmds; 118 freebsd = pkgs.freebsd.fdisk; 119 }; 120 fsck = { 121 linux = pkgs.util-linux; 122 darwin = pkgs.darwin.diskdev_cmds; 123 }; 124 hexdump = { 125 linux = pkgs.util-linuxMinimal; 126 darwin = pkgs.darwin.shell_cmds; 127 }; 128 hostname = { 129 linux = pkgs.hostname-debian; 130 darwin = pkgs.darwin.shell_cmds; 131 freebsd = pkgs.freebsd.bin; 132 openbsd = pkgs.openbsd.hostname; 133 }; 134 ifconfig = { 135 linux = pkgs.net-tools; 136 darwin = pkgs.darwin.network_cmds; 137 freebsd = pkgs.freebsd.ifconfig; 138 openbsd = pkgs.openbsd.ifconfig; 139 }; 140 killall = { 141 linux = pkgs.psmisc; 142 darwin = pkgs.darwin.shell_cmds; 143 }; 144 locale = { 145 linux = pkgs.glibc; 146 darwin = pkgs.darwin.adv_cmds; 147 freebsd = pkgs.freebsd.locale; 148 # technically just targeting glibc version 149 # no obvious exec in manpage 150 binlore = '' 151 execer cannot bin/locale 152 ''; 153 }; 154 logger = { 155 linux = pkgs.util-linux; 156 }; 157 more = { 158 linux = pkgs.util-linux; 159 darwin = more_compat; 160 }; 161 mount = { 162 linux = pkgs.util-linux; 163 darwin = pkgs.darwin.diskdev_cmds; 164 freebsd = freebsd.mount; 165 openbsd = pkgs.openbsd.mount; 166 # technically just targeting the darwin version; binlore already 167 # ids the util-linux copy as 'cannot' 168 # no obvious exec in manpage args; I think binlore flags 'can' 169 # on the code to run `mount_<filesystem>` variants 170 binlore = '' 171 execer cannot bin/mount 172 ''; 173 }; 174 netstat = { 175 linux = pkgs.net-tools; 176 darwin = pkgs.darwin.network_cmds; 177 freebsd = pkgs.freebsd.netstat; 178 }; 179 ping = { 180 linux = pkgs.iputils; 181 darwin = pkgs.darwin.network_cmds; 182 freebsd = freebsd.ping; 183 }; 184 ps = { 185 linux = pkgs.procps; 186 darwin = pkgs.darwin.ps; 187 freebsd = pkgs.freebsd.bin; 188 openbsd = pkgs.openbsd.ps; 189 # technically just targeting procps ps (which ids as can) 190 # but I don't see obvious exec in args; have yet to look 191 # for underlying cause in source 192 binlore = '' 193 execer cannot bin/ps 194 ''; 195 }; 196 quota = { 197 linux = pkgs.linuxquota; 198 darwin = pkgs.darwin.diskdev_cmds; 199 }; 200 route = { 201 linux = pkgs.net-tools; 202 darwin = pkgs.darwin.network_cmds; 203 freebsd = pkgs.freebsd.route; 204 openbsd = pkgs.openbsd.route; 205 }; 206 script = { 207 linux = pkgs.util-linux; 208 darwin = pkgs.darwin.shell_cmds; 209 }; 210 sysctl = { 211 linux = pkgs.procps; 212 darwin = pkgs.darwin.system_cmds; 213 freebsd = pkgs.freebsd.sysctl; 214 openbsd = pkgs.openbsd.sysctl; 215 }; 216 top = { 217 linux = pkgs.procps; 218 darwin = pkgs.darwin.top; 219 freebsd = pkgs.freebsd.top; 220 openbsd = pkgs.openbsd.top; 221 # technically just targeting procps top; haven't needed this in 222 # any scripts so far, but overriding it for consistency with ps 223 # override above and in procps. (procps also overrides 'free', 224 # but it isn't included here.) 225 binlore = '' 226 execer cannot bin/top 227 ''; 228 }; 229 umount = { 230 linux = pkgs.util-linux; 231 darwin = pkgs.darwin.diskdev_cmds; 232 }; 233 whereis = { 234 linux = pkgs.util-linux; 235 darwin = pkgs.darwin.shell_cmds; 236 }; 237 wall = { 238 linux = pkgs.util-linux; 239 }; 240 watch = { 241 linux = pkgs.procps; 242 243 # watch is the only command from procps that builds currently on 244 # Darwin/FreeBSD. Unfortunately no other implementations exist currently! 245 darwin = pkgs.callPackage ../os-specific/linux/procps-ng { }; 246 freebsd = pkgs.callPackage ../os-specific/linux/procps-ng { }; 247 openbsd = pkgs.callPackage ../os-specific/linux/procps-ng { }; 248 }; 249 write = { 250 linux = pkgs.util-linux; 251 darwin = pkgs.darwin.basic_cmds; 252 }; 253 xxd = { 254 linux = pkgs.tinyxxd; 255 darwin = pkgs.tinyxxd; 256 freebsd = pkgs.tinyxxd; 257 }; 258 }; 259 260 makeCompat = 261 pname: paths: 262 buildEnv { 263 name = "${pname}-${version}"; 264 inherit paths; 265 }; 266 267 # Compatibility derivations 268 # Provided for old usage of these commands. 269 compat = 270 with bins; 271 mapAttrs makeCompat { 272 procps = [ 273 ps 274 sysctl 275 top 276 watch 277 ]; 278 util-linux = [ 279 fsck 280 fdisk 281 getopt 282 hexdump 283 mount 284 script 285 umount 286 whereis 287 write 288 col 289 column 290 ]; 291 net-tools = [ 292 arp 293 hostname 294 ifconfig 295 netstat 296 route 297 ]; 298 }; 299in 300bins // compat