POSIX Is Not a Shell

(alganet.github.io)

30 points | by gaigalas 4 hours ago ago

10 comments

  • Muhammad523 2 hours ago

    This post is nice: the writer first explains a problem, using a simple example. In the next section, they reflect a bit about the problem, and then they casually mention two tools they built. In my opinion, this is amazing: you sponsor you project, while also making the problem it solves clear: use their tool to test how portable your code is

  • echoangle 2 hours ago

    Pretty bad argument. If it’s not defined by POSIX, it’s not POSIX compatible if you rely on a specific behavior.

    If you only use defined behavior and it works, it is compatible.

    It’s like saying C99 isn’t a compiler. True, but you can still write C99 code, right?

    • smitty1e 2 hours ago

      > C99 isn’t a compiler.

      Sure, but the pojt here is that if we say "Write in X" we generally understand it to mean "Treat X like a standard and don't get too colloquial with the stylings."

      Pedantry is worthwhile, but it can be a diminishing returns game.

      • eqvinox 21 minutes ago

        Feels like you missed the point.

        On the example of 'echo \n' - it's not defined in POSIX, therefore a script written in "POSIX shell" must simply never hit that case.

        TFA kinda implies you can't target POSIX shell. That's silly, of course you can. The question is, what tools are there to check for compliance. Whether running on 14 shells is a good such tool - idk. Something specifically searching for POSIX violations might be better.

        • Joker_vD 17 minutes ago

          Well, with C language it's pretty much the same. You are supposed to "just" never write (or rather, most of the time, to just not execute) anything that is UB. And lots and lots of people to this day continue to believe that can do this (most of the time, they're wrong).

        • gaigalas 2 minutes ago

          The spec is not that good.

          `local` for example is present in many shells (almost all of them), but they decided to leave it out uniquely because of ksh93 (scope is different).

          When the spec was written, it was important. Since then, it has only been revised but not updated and I consider it to be obsolete.

          So, if you follow POSIX strictly, you then lose local scope on functions, which is more likely to cause bugs and hard to catch with a linter like you suggested. You're left with a broken feature set (on many other angles too) that is not actually practical. Even spellcheck makes concessions.

  • sdovan1 an hour ago

    If your environment is POSIX, testing scripts with tool written in POSIX shell, like shellspec[1], might also be a choice.

    [1] https://shellspec.info/

  • jmclnx an hour ago

    Will not build without docker, so I am out of luck. This tells me this is not portable, even to some Linuxes.

    • Joker_vD 23 minutes ago

      Strict POSIX conformance is arguably worse. I mean, have you seen what it advises for shebangs? First of all:

          The shell reads its input from a file (see sh), from the -c option or from the system() and popen() functions defined in the System Interfaces volume of POSIX.1-2017. If the first line of a file of shell commands starts with the characters "#!", the results are unspecified.
      
      Ah, so shebangs are not required to be supported, already a great start.

          Applications should note that the standard PATH to the shell cannot be assumed to be either /bin/sh or /usr/bin/sh, and should be determined by interrogation of the PATH returned by getconf PATH, ensuring that the returned pathname is an absolute pathname and not a shell built-in. [...]
      
          Furthermore, on systems that support executable scripts (the "#!" construct), it is recommended that applications using executable scripts install them using getconf PATH to determine the shell pathname and update the "#!" script appropriately as it is being installed (for example, with sed). For example:
      
              #
              # Installation time script to install correct POSIX shell pathname
              #
              # Get list of paths to check
              #
              Sifs=$IFS
              Sifs_set=${IFS+y}
              IFS=:
              set -- $(getconf PATH)
              if [ "$Sifs_set" = y ]
              then
                  IFS=$Sifs
              else
                  unset IFS
              fi
              #
              # Check each path for 'sh'
              #
              for i
              do
                  if [ -x "${i}"/sh ]
                  then
                      Pshell=${i}/sh
                  fi
              done
              #
              # This is the list of scripts to update. They should be of the
              # form '${name}.source' and will be transformed to '${name}'.
              # Each script should begin:
              #
              # #!INSTALLSHELLPATH
              #
              scripts="a b c"
              #
              # Transform each script
              #
              for i in ${scripts}
              do
                  sed -e "s|INSTALLSHELLPATH|${Pshell}|" < ${i}.source > ${i}
              done
      
      Marvelous. What a robust foundation of useful and hard-to-misuse utilities.
    • gaigalas 11 minutes ago

      Author here.

      It definitely builds outside docker. It's a musl-cross-make toolchain, you can procure the dependencies locally if you don't like the Docker recipes.

      Feel free to open an issue if you feel like that's a challenge. Likely, you can get it to work but checksum reproducibility will be hard without a controlled environment like docker.