What is the difference between various implementations of dc? - gnu

dc is the Unix standard desktop calculator. AFAIK, there are different implementations (like Solaris or GNU for instance).
What is the exact difference between these implementations and what is the minimal subset of operations you can be sure a dc implementation has?

As far as I could find, at least FreeBSD used to use the GNU-Implementation as well,1 but doesn't do so anymore. Solaris seems to have a different Implementation.2 From my first read, I mentiones these things:
Solaris dc lacks these commands |, a, ~, n,
Solaris lacks the commands !=, !> and !<. This is important, because it changes the way shell commands are evaluated. In GNU dc, the sequence !>... is applying the comparison, but in Solaris this would execute the rest of the line as a shell command.
Solaris lacks support of # comments.
In Solaris, Y prints additional debuging information.
Solaris does not accept any command-line arguments.
GNU dc accepts input radices up to 16, Solaris seems to be unlimited (unshure).

Related

What are the differences bettween linux system call mmap(2) and posix mmap(3) function?

What are the differences bettween linux system call mmap(2) and posix mmap(3) function?
How to distinguish which one is used when broswing the source code,since they have the same header file.For details, see below.
I am running on Ubuntu.I do not think it matters what operating system you are using.The mannual page really does not supply much useful information indeed.
As per the reply of Jörg W Mittag, I think the mmap must be posix function when i am broswing the source code.But i wonder that why i need not to explicitly link to posix library when using the mmamp(3) function .I mean no extra link flag is needed when complie the source code.
As per the reply of Faschingbauer,some question arise if we make the conclusion that no posix mmap is implenmented.You see, there are some posix function implemented(eg, shm_opn、sem_open, mq_open).In the mean time,there are corresponding ones with the same functions(eg, shmget,semget, msgget).How to explain it?At least, I think some posix functions are implemented by linux.
#log for "man 2 mmap"
MMAP(2) Linux Programmer's Manual
NAME
mmap, munmap - map or unmap files or devices into memory
SYNOPSIS
#include <sys/mman.h>
#log for "man 3 mmap"
MMAP(3POSIX) POSIX Programmer's Manual
PROLOG
This manual page is part of the POSIX Programmer's Manual. The Linux implementation of this interface may differ (consult the corresponding Linux manual page for details of Linux behavior), or the interface may not be implemented on Linux.
NAME
mmap — map pages of memory
SYNOPSIS
#include <sys/mman.h>
POSIX vs. Linux
First, some facts:
POSIX is a standard, made by a standards body. POSIX does not
implement anything, but rather define feature set and behavior of
interfaces. Part of this definition is a number of man pages - the
"POSIX Programmer's Manual"
Linux implements the POSIX standard, just like other UNIX
operating systems do. (I do not know if Linux is "POSIX certified",
nor do I care.) In implementing the POSIX standard, Linux takes the
freedom to extend the standard with Linux specific features; hence
it brings its own set of manual pages, the "Linux Programmer's
Manual".
Looking at the Linux ("man 2 mmap") man page, you can see that it
defines, for example, the MAP_LOCKED bit in the flags argument
(btw. MAP_LOCKED makes a separate call to mlock() unnecessary). This
flag does not appear in the POSIX man page ("man 3 mmap"), because it
is not required by the POSIX standard for a conforming implementation.
That said, there is no way to use an alternative implementation of
mmap() in Linux. If some source code that you are reading uses mmap(),
and you are on Linux, then the Linux implementation of mmap() is used, simply
because there is no POSIX implementation of it.
Respectively, the POSIX version is contained in the Linux
implementation. Linux is "compatible" with POSIX, so to say - it does
not redefine any feature required by POSIX (this would mean to violate the standard), but only adds extensions
like the MAP_LOCKED above.
Manual Pages
Hm. My personal opinion is that the POSIX version of, say, the mmap
man page is only there to confuse users. If you inadvertently hit the
section "3" mmap() man page, and you don't know what the relationship
is between POSIX and Linux, then you are indeed seriously confused at
best, or on the wrong track at worst.
I suggest you omit the section number and just say "man mmap" - this searches all the manual
sections for occurences of "mmap" and stops at the first (see "man man" for the exact definition).
(This does not work as envisioned with "man write" when you are
searching for the definition of the write() system call, because there
is a command "write" with the same same in section "1" :-) )
System Calls
As stated by "man man", manual section "2" contains system call
documentation. Knowing that mmap() is implemented by the Linux kernel
(because it is the kernel who implements core OS functionality like
memory management) can only help to clear up the confusion as to
whether the documentation you are reading is what you want.
What are the differences bettween linux system mmap(2) and posix mmap(3) function?
Section 2 documents syscalls. Section 3 documents functions. Therefore, mmap(2) is not a function at all, it is a syscall.
How to distinguish which one is used when broswing the source code?
If it is a function call, it is mmap(3). If it is a syscall, it is mmap(2). Since it is impossible to portably call syscalls from C, there will always be some sort of macro or wrapper function for the syscall.
Also, unless you are reading the source code of the runtime library for a C compiler (e.g. GCC's) or the source code of a POSIX library (such as Glibc, dietlibc, µClibc, or musl), it is highly unlikely that you will find any syscalls in the code.
But i wonder that why i need not to explicitly link to posix library when using the mmamp(3) function .
You need not link another library because mmap is contained in GLIBC; you can see this e. g. with
nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep mmap
00000000000e4610 W mmap
00000000000e4610 W mmap64

Why are some Bash commands both built-in and external?

Some commands are internal built-in Bash commands while others are external (other programs). I see why certain commands need to be built-in. Some of the reasons are:
If a command needs to change the internal state of the shell process.
If a command performs a very basic operation in the shell.
If a command is called often and needs to be made fast. An external command is executed by loading an external program and hence is slower.
But why are some commands both built-in and external, for example echo and test? I understand echo is used a lot and thus is built-in (Reason 3). But then why also have it as an external command and have a binary for it in /bin/echo? The built-in version of echo will always take precedence over the external version and thus, the external version is hardly ever used. So, why then have an external version of it at all?
It's exactly your point 3. When a command does very little (echo is a good example), spawning a new process dominates the run time behavior. With growing disks and bandwidth and code bases you always reach a spot when you have so much data and so many files (our code base at work has 100k files!!) that one less spawn per file makes a difference of minutes.
That's also why the typical built-in is a drop-in replacement which takes (perhaps a superset of) the same arguments as the binary.
You also ask why the old binary is still retained even though Bash has it as a built-in — the answer is that a lot of programs rely on the existence of that /bin/echo. It's actually standardized.
Bash is only one of many user interfaces and offline command interpreters. They all have different sets of built-ins. Some shells are purposefully small and rely a lot on what you could call "legacy" binaries. One example is ash and its successor, Dash. Dash is now the default /bin/sh in Ubuntu and Debian due to its speed, and is popular for embedded systems due to its small size. (But even Dash has builtins for echo, test and dozens of other commands, and provides a command history for interactive use.)

Which shell should be used for Linux/MacOS/UNIX best compatibility?

My question may seem related to SO question "What Linux shell should I use?", but my problem is to know which shell shall be used to write an application start script, knowing that this is a cross-platform Java application (almost all Linux distributions, MacOS, Solaris, ...). So i'm adding compatibility concerns here.
Please note that i'm not asking "which is the best shell to use" in general (which may have no sense in my opinion: subjective, depends on needs), but I'd like to know, which shell has the best chance, today, to be available (and suitable for Java application start) on most operating systems.
Also, may I simply have to use the shebang #!/bin/bash to "use bash"? (or for example #!/bin/ksh for Korn shell). What if this shell is not available on this OS?
We're actually using a ".sh" file with the shebang #!/bin/sh (which is Bourne shell I guess) but some users are complaining about errors on some Linux distributions (we don't know yet which one they use, but we would like to have a more global approach instead of fixing errors one by one). MacOS is currently using bash as the default shell but at this time we don't have any issue on MacOS using /bin/sh...
Note: we'd like to avoid having several start scripts (i.e. using different shells)
For maximum portability, your best bet is /bin/sh using only POSIX sh features (no extensions). Any other shell you pick might not be installed on some system (BSDs rarely have bash, while Linux rarely has ksh).
The problem you can run into is that frequently, /bin/sh is not actually Bourne sh or a strictly POSIX sh -- it's frequently just a link for /bin/bash or /bin/ksh that runs that other shell in sh-compatibility mode. That means that while any POSIX sh script should run fine, there will also be extensions supported that will cause things that are illegal per POSIX to run as well. So you might have a script that you think is fine (runs fine when you test it), but its actually depending on some bash or ksh extension that other shells don't support.
You can try running your script with multiple shells in POSIX compatibility mode (try say, bash, ksh, and dash) and make sure it runs on all of them and you're not accidentally using some extension that only one supports.
You won't find a shell implementation that will be installed on every of these OSes, however, all of them are either POSIX compliant or more or less close to being compliant.
You should then restrict your shell scripts to stick to the POSIX standard as far as possible.
However, there is no simple way to tell a script is to be executed in a POSIX context, and in particular to specify what shebang to set. I would suggest to use a postinstaller script that would insert the correct shebang on the target platform retrieved using this command:
#!/bin/sh
printf "#!%s\n" `PATH=\`getconf PATH\` command -v sh`
You scripts should also include this instruction once and before calling any external command:
export PATH=$(getconf PATH):$PATH
to make sure the utilities called are the POSIX ones. Moreover, beware that some Unix implementations might require an environment variable to be set for them to behave a POSIX way (eg BIN_SH=xpg4 is required on Tru64/OSF1, XPG_SUS_ENV=ON on AIX, ...).
To develop your script, I would recommend to use a shell that has the less extensions to the standard, like dash. That would help to quickly detect errors caused by bashisms (or kshisms or whatever).
PS: beware that despite popular belief, /bin/sh is not guaranteed to be POSIX compliant even on a POSIX compliant OS.

TCL, Linux, and FLOCK

So I am working with a program written in TCL that uses the FLOCK function to lock files. I am testing it on a newer version of Linux than the one it currently runs on and I found that when the newer machine runs the script, it uses FLOCK from /usr/bin/flock, which differs from the TCL version of FLOCK. The TCL version uses -read -write and such, while the Linux version uses completely different options.
In short, the program stops working and errors out when it gets to any FLOCK call. If I change the options to fit the Linux version, it breaks the program on the other machines.
Is there a way to make it use the TCL version as opposed to the Linux one?
Tcl itself does not come with a flock command, though you might be seeing it automatically trying to use the system command if you're testing interactively. Such automated use of system commands is not done in scripts (that would be hellishly prone to instability due to varying PATHs) so when writing a script you should be explicit as to what you mean.
If you want to use the system command (itself non-portable, especially to non-Linux systems) then just do:
exec flock $options...
Be aware that Tcl uses a different form of argument quoting to the shell. This can sometimes catch people out when writing exec calls.
Alternatively, use the flock Tcl command that is in the TclX package. The syntax is a little different to that of the Linux system utility, in large part because it's a bit lower-level. In its favor, it is rather more portable.

Getting The Full Result from "ps"

How do I get the full width result for the *nix command "ps"?
I know we can specify something like --cols 1000 but is there anyway I can
the columns and just print out everything?
Try ps -w -w aux. The -w option sets the output to wide, and doing it twice makes the width unlimited. The "aux" part makes it show more information, and is (afaik) pretty standard mode to use. This is of course platform-dependant, the above works with procps version 3.2.7 on Linux.
Specify the w option twice, if you're using BSD-style ps. e.g., ps auwwx. A different set of options apply when using System V ps.
There are two different option syntaxes for ps; the standard POSIX one based on SysV, and the BSD one. GNU ps, as used on linux, supports both, which it can do because the POSIX options have dashes in front and the BSD ones don't, as well as some of it's own options in the normal GNU --long-option-name style.
Anyway, to get all processes in POSIX style is -e, in BSD it's ax (a includes other user's processes, x includes processes without a controlling terminal i.e. daemons).
There is no single option that will make it include all the columns. There are a huge number of possible columns. The POSIX options -f, -F and -L all cause it to show different sets of extra columns, as does the BSD option u (hence the "ps aux" mentioned in another answer is a very common command).
If you really want more columns than that you have to name explicitly which ones you want, using the -o (or o) option. See the man page for a list. There's about a hundred different names you can use, but some of them are duplicates, and others display the same info in different ways.

Resources