View Issue Details

IDProjectCategoryView StatusLast Update
00007941003.1(2013)/Issue7+TC1System Interfacespublic2014-04-11 06:57
Reportersteffen Assigned Toajosey  
PrioritynormalSeverityEditorialTypeEnhancement Request
Status ClosedResolutionRejected 
Namesteffen
Organization
User Reference
SectionVol. 1. 13., Vol. 2 (new)
Page Number234, 775
Line Number7718, 25933
Interp Status---
Final Accepted Text
Summary0000794: Add a function series for formatted error messages
DescriptionEven though these functions provide only very simple operations that can be
easily implemented by using functionality that is yet covered by POSIX it makes
sense to include them in the standard for two reasons:

(1) SysV and BSD derived Unix both provide them in an identical fashion for
    one, if not multiple decades (except for the *c() series),
(2) because they are not part of the POSIX standard unnecessary code
    duplication occurs in a vast majority of libraries and programs and
(3) the chosen names for the duplicated functionality isn't unique -- i've seen
    bail(), error(), panic() and i think i recall series of #undef to be able
    to use the names that hopefully become standard.
Desired Action- Vol. 1: Base Definitions, Chapter 13, «Headers».

  On page 234, line 7718
  add (insert before)

    NAME
      err.h - formatted error messages

    SYNOPSIS
      #include <err.h>

    DESCRIPTION
      The <err.h> header shall declare the following as functions or define
      them as macros. Function prototypes shall be provided.

      void err(int, const char *, ...);
      void verr(int, const char *, va_list);
      void errx(int, const char *, ...);
      void verrx(int, const char *, va_list);
      void warn(const char *, ...);
      void vwarn(const char *, va_list);
      void warnx(const char *, ...);
      void vwarnx(const char *, va_list);

    APPLICATION USAGE
      None.

    RATIONALE
      After a long deserted period added to POSIX. Jay!
    FUTURE DIRECTIONS
      None.

    SEE ALSO
      XSH err()

- Vol. 2: System Interfaces.

  On page 775, line 25933
  add (insert before)

    NAME
      err, verr, errx, verrx, warn, vwarn, warnx, vwarnx -
      formatted error messages

    SYNOPSIS
      #include <err.h>

      void err(int eval, const char *fmt, ...);
      void verr(int eval, const char *fmt, va_list);
      void errx(int eval, const char *fmt, ...);
      void verrx(int eval, const char *fmt, va_list);
      void warn(const char *fmt, ...);
      void vwarn(const char *fmt, va_list);
      void warnx(const char *fmt, ...);
      void vwarnx(const char *fmt, va_list);

    DESCRIPTION
      The err() and warn() family of functions display a formatted error
      message to the standard error output. If the fmt argument is not NULL,
      the formatted error message, a colon character, and a space are output.
      In the case of the err(), verr(), warn() and vwarn() functions, the error
      message string affiliated with the current value of the global variable
      errno is output. In all cases, the output is followed by a newline
      character.

      The err(), verr(), errx() and verrx() functions do not return a value,
      but exit with the value of the argument eval.

    RETURN VALUE
      None.

    ERRORS
      None.

    EXAMPLES
      Display the current errno information string and exit:
      if ((p = malloc(size)) == NULL)
              err(1, NULL);
      if ((fd = open(file_name, O_RDONLY, 0)) == -1)
              err(1, "%s", file_name);

      Display an error message and exit:
      if (tm.tm_hour < START_TIME)
              errx(1, "too early, wait until %s", start_time_string);

      Warn of an error:
      if ((fd = open(raw_device, O_RDONLY, 0)) == -1)
              warnx("%s: %s: trying the block device",
                  raw_device, strerror(errno));
      if ((fd = open(block_device, O_RDONLY, 0)) == -1)
              warn("%s", block_device);

    APPLICATION USAGE
      None.

    RATIONALE
      None.

    FUTURE DIRECTIONS
      None.

    SEE ALSO
      XBD <err.h>
TagsNo tags attached.
Attached Files
posix-err.diff (4,279 bytes)   
--- /dev/null	2014-01-16 12:45:53.000000000 +0100
+++ err.h	2014-01-16 12:14:10.000000000 +0100
@@ -0,0 +1,39 @@
+
+#ifndef	_ERR_H
+#define	_ERR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+
+#ifndef _Noreturn
+# define __ERR_H_DEFINED_NORETURN
+# define _Noreturn
+#endif
+
+/* Program exit and warning calls */
+_Noreturn void	err(int, const char *, ...);
+_Noreturn void	verr(int, const char *, va_list);
+_Noreturn void	errc(int, int, const char *, ...);
+_Noreturn void	verrc(int, int, const char *, va_list);
+_Noreturn void	errx(int, const char *, ...);
+_Noreturn void	verrx(int, const char *, va_list);
+
+void		warn(const char *, ...);
+void		vwarn(const char *, va_list);
+void		warnc(int, const char *, ...);
+void		vwarnc(int, const char *, va_list);
+void		warnx(const char *, ...);
+void		vwarnx(const char *, va_list);
+
+#ifdef __ERR_H_DEFINED_NORETURN
+# undef _Noreturn
+# undef __ERR_H_DEFINED_NORETURN
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ERR_H */
--- /dev/null	2014-01-16 12:45:57.000000000 +0100
+++ err.c	2014-01-16 12:44:52.000000000 +0100
@@ -0,0 +1,174 @@
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+/* Thread-safe locked with multiple I/Os, or a single output?
+ * Is used as the stack buffer size if defined */
+/*#define __PREPARE_STACK_BUFFER	1024*/
+
+/* Get the program name as a const char* */
+#define __PROGRAM_NAME()	getprogname()
+
+/* The shared workhorse */
+static void	_errwarn(FILE *fp, int doerr, int code, const char *fmt,
+			va_list args);
+
+static void
+_errwarn(FILE *fp, int doerr, int code, const char *fmt, va_list args)
+{
+#ifdef __PREPARE_STACK_BUFFER
+	char buffer[__PREPARE_STACK_BUFFER];
+	size_t len;
+	int i;
+
+	i = snprintf(buffer, sizeof buffer, "%s: ", __PROGRAM_NAME());
+	if (i < 0)
+		goto jleave;
+	len = i;
+	if (len >= sizeof buffer)
+		goto jprint;
+
+	if (fmt != NULL) {
+		i = vsnprintf(buffer + len, sizeof(buffer) - len, fmt, args);
+		if (i < 0)
+			goto jleave;
+		len += i;
+		if (len >= sizeof buffer)
+			goto jprint;
+	}
+
+	if (doerr) {
+		i = snprintf(buffer + len, sizeof(buffer) - len, ": %s",
+			strerror(code));
+		if (i < 0)
+			goto jleave;
+		len += i;
+	}
+jprint:
+	if (len >= sizeof buffer)
+		len = sizeof(buffer) - 2;
+	buffer[len++] = '\n';
+	buffer[len] = '\0';
+	fputs(buffer, fp);
+	fflush(fp);
+jleave:
+	;
+
+#else /* __PREPARE_STACK_BUFFER */
+	flockfile(fp);
+	fprintf(fp, "%s: ", __PROGRAM_NAME());
+	if (fmt != NULL)
+		vfprintf(fp, fmt, args);
+	if (doerr)
+		fprintf(fp, ": %s", strerror(code));
+	fputc('\n', fp);
+	fflush(fp);
+	funlockfile(fp);
+#endif
+}
+
+void
+err(int status, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	_errwarn(stderr, 1, errno, fmt, args);
+	va_end(args);
+	exit(status);
+}
+
+void
+verr(int status, const char *fmt, va_list args)
+{
+	_errwarn(stderr, 1, errno, fmt, args);
+	exit(status);
+}
+
+void
+errc(int status, int code, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	_errwarn(stderr, 1, code, fmt, args);
+	va_end(args);
+	exit(status);
+}
+
+void
+verrc(int status, int code, const char *fmt, va_list args)
+{
+	_errwarn(stderr, 1, code, fmt, args);
+	exit(status);
+}
+
+void
+errx(int status, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	_errwarn(stderr, 0, 0, fmt, args);
+	va_end(args);
+	exit(status);
+}
+
+void
+verrx(int status, const char *fmt, va_list args)
+{
+	_errwarn(stderr, 0, 0, fmt, args);
+	exit(status);
+}
+
+void
+warn(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	_errwarn(stderr, 1, errno, fmt, args);
+	va_end(args);
+}
+
+void
+vwarn(const char *fmt, va_list args)
+{
+	_errwarn(stderr, 1, errno, fmt, args);
+}
+
+void
+warnc(int code, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	_errwarn(stderr, 1, code, fmt, args);
+	va_end(args);
+}
+
+void
+vwarnc(int code, const char *fmt, va_list args)
+{
+	_errwarn(stderr, 1, code, fmt, args);
+}
+
+void
+warnx(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	_errwarn(stderr, 0, 0, fmt, args);
+	va_end(args);
+}
+
+void
+vwarnx(const char *fmt, va_list args)
+{
+	_errwarn(stderr, 0, 0, fmt, args);
+}
posix-err.diff (4,279 bytes)   

Activities

shware_systems

2013-12-18 20:46

reporter   bugnote:0002084

Last edited: 2013-12-18 20:55

The warning interfaces should return 0 on success, and something else on I/O or format error, IMO. It could happen, and they do return. Also, it's not clear what is the difference between err and errx, or warn and warnx, it looks. Is one locale sensitive and the other not? Should there be _l versions for an arbitray locale? Shouldn't one return errno as exit value, not an arbitrary eval (I'd use errval to avoid confusion with eval utility)? Does the standard string only get used when fmt is NULL, or is it always a prefix or suffix? Is a standard errno string also allowed to have locale specific format specifiers to establish context and require more arguments? Does the standard provide a fixed body of messages for the C locale per error number, so each implementation consistent in its output?

The Rationale bit is not that rational, also, from a technical standpoint.

steffen

2013-12-21 16:48

reporter   bugnote:0002090

0000794:0002084:

 |The warning interfaces should return 0 on success, and something else on I/O or format error, IMO.

I think you have to cut complexity at some point. Our own logging facility (that could have several output Log::Domain's, IO::TextWriter * or IO::Device * based, thus there also was Unix syslogd(8) Domain) did not do so either:

  pub void write(Priority _prio, const char *_fmt, ...);
  pub void vWrite(Priority _prio, const char *_fmt, void *_valistp);

but the actual Domain:: I/O method said:

                /*!
                * \brief Actual log method, all arguments are verified.
                * \return Wether an I/O error occurred.
                * \note This is never called again if you indicate I/O error.
                */
                pro virtual boolean doWrite(Priority _prio,
                                                const char *_fmt,
                                                void *_valistp) = 0;

But you can query wether a Domain is in error state (pub boolean isError(void) const), though it can't be helped anyway.

I think if you need a *really* reliable logging facility, for a 24/7 service or something similar, you have to be very careful, signal-resistant etc. Then this is not for you.

On the other hand, most POSIX tools could (have) very well use(d) (or, in real implementation, do use) the interface from err.h for their diagnostic STDERR uses (since the standard says "The standard error shall be used only for diagnostic messages." for most, faulty unbuffered writes to STDERR can simply be ignored, and in fact often are).

It should be mentioned that the already POSIX-included syslog(3) interface, that most likely includes interprocess communication etc., doesn't indicate success at all. Many servers use syslog(3), at least optional. But of course, it is too late to modify that.

I think in the end this is a quality of implementation, again.
For example, many implementations of exit(3) work like this:

  {
    xy_finalize();
    syscall_exit()
  }

What if there are registered signal handlers and jump buffers, and before the system call a jump happens to occur? The standard says this is undefined behaviour, it doesn't say that signals shall be blocked / signal handlers shall be reset / implementations have to ensure that signal / jumping behaviour of the program changes to something predictable once exit() is entered (though this would be possible by changing entry points for several functions).

I think for the STDERR warn() and STDERR/exit(3) err() function family a best-effort implementation is good enough.
If it's really necessary then i think the corresponding paragraph from exit(3) documentation should either be referenced or included.

 |Also, it's not clear what is the difference between err and errx, or warn and warnx, it looks.

So, then let's change

       In the case of the err(), verr(), warn() and vwarn() functions, the error
       message string affiliated with the current value of the global variable
       errno is output. In all cases, the output is followed by a newline
       character.

to

       In the case of the err(), verr(), warn() and vwarn() functions, the error
       message string affiliated with the current value of the variable
       errno is output, whereas errx(), verrx(), warnx() and vwarnx() don't.
       In all cases, the output is followed by a newline character.

 |Shouldn't one return errno as exit value, not an arbitrary eval (I'd use errval to avoid confusion with eval utility)?

I've taken the text from an existing implementation.
The 'eval' parameter can be named 'exit_status' if you want.

 |Does the standard string only get used when fmt is NULL, or is it always a prefix or suffix?

Which string you are referring to here?
Again, the text is from a real implementation.
I don't think it is a good idea to clamp the format, especially if..

 |Is a standard errno string also allowed to have locale specific format specifiers to establish context and require more arguments?

I'm inclined to change the text of

       In the case of the err(), verr(), warn() and vwarn() functions, the error
       message string affiliated with the current value of the global variable
       errno is output.

to

       In the case of the err(), verr(), warn() and vwarn() functions, the error
       message string affiliated with the current value of the variable
       errno, as if it would have been obtained via the function strerror(3), is output.

I think addition of _l() versions is beyond the scope of this issue, since i don't no of any implementation which provides them.
Also it is hard to imagine that an utility which uses warn() and err() deals with multiple locales at a time and in addition wants to use one of those locales to print an error message (and abort the program).
I think it's far more likely that the final message interacts with the user in the LC_MESSAGES locale.

..[but] you seem to want to open an issue for localized versions.

 |Does the standard provide a fixed body of messages for the C locale per error number, so each implementation consistent in its output?

No, i don't think the standard supports that for strerror(3).
Note that some systems define error messages that others don't know about, so that would be true for a subset only and anyway.

 |The Rationale bit is not that rational, also, from a technical standpoint.

There are many applications which use syslog(3), and there are many applications which want to provide the user with some feedback on error conditions. System implementors have given an answer for this a long time ago, and it'd be a-good-thing if it were part of the standard, so that people can rely on it being available, not hacking together over and over again stuff just because there may be one or two systems which actually don't have it.

Which technical standpoint you are referring to?
Yay! (Is that better?)

Don Cragun

2013-12-21 20:39

manager   bugnote:0002091

I have moved this from the 2008-TC1 project with category Rationale to the 1003.1(2013)/Issue7+TC1 project with category System Interfaces.

msbrown

2014-01-09 17:19

manager   bugnote:0002097

Steffen, where did you get the text for this (for copyright review purposes)?

steffen

2014-01-09 18:00

reporter   bugnote:0002098

That is a good question, regarding the draft text in `Desired Action': And i cannot answer it!

However: i should have used the text from the NetBSD or OpenBSD manual ([1], [2]) at first glance, or once shware_systems raised valid concerns -- not only because of Copyright issues, but also because they are clearer; e.g., the misconstructable term "eval" is replaced with "status", and the example uses EXIT_FAILURE for it instead of simply using the value 1.

 [1] http://netbsd.gw.com/cgi-bin/man-cgi?err+3.NONE+NetBSD-current
 [2] http://www.openbsd.org/cgi-bin/man.cgi?query=err&manpath=OpenBSD+Current&format=txt

So, a version that should *definetely* be freely usable by POSIX would be (only changing the doubtful new entry of Vol. 2, Vol.1 contains only prototypes, to a freely new interpretation of the two linked manuals):

- Vol. 2: System Interfaces.

   On page 775, line 25933
   add (insert before)

     NAME
       err, verr, errx, verrx, warn, vwarn, warnx, vwarnx -
       formatted error messages

     SYNOPSIS
       #include <err.h>

       void err(int status, const char *fmt, ...);
       void verr(int status, const char *fmt, va_list);
       void errx(int status, const char *fmt, ...);
       void verrx(int status, const char *fmt, va_list);
       void warn(const char *fmt, ...);
       void vwarn(const char *fmt, va_list);
       void warnx(const char *fmt, ...);
       void vwarnx(const char *fmt, va_list);

     DESCRIPTION
       The err() and warn() family of functions display a formatted error
       message on the standard error output. In all cases, the last component
       of the program name, followed by a colon (`:') character and a space, are
       output. The text that follows depends on the function being called. The
       fmt specification (and associated arguments) may be any format allowed by
       printf(3), a simple string, or NULL. If the fmt argument is not NULL,
       the formatted error message is output.

       In the case of the err(), verr(), warn(), and vwarn() functions only, the
       error message string affiliated with the current value of the global
       variable errno is output (see strerror(3)), preceded by a colon character
       and a space if fmt is not NULL.
       The counterpart functions, errx(), verrx(), warnx(), and vwarnx(), do not
       output the error message string.
       The err(), verr(), errx(), and verrx() functions do not return, but exit
       with the value of the argument status.

     RETURN VALUE
       None.

     ERRORS
       None.

     EXAMPLES
       Display the current errno information string and exit:
       if ((p = malloc(size)) == NULL)
               err(EXIT_FAILURE, NULL);
       if ((fd = open(file_name, O_RDONLY, 0)) == -1)
               err(EXIT_FAILURE, "%s", file_name);

       Display an error message and exit:
       if (tm.tm_hour < START_TIME)
               errx(EXIT_FAILURE, "too early, wait until %s", start_time_string);

       Warn of an error:
       if ((fd = open(raw_device, O_RDONLY, 0)) == -1)
               warnx("%s: %s: trying the block device",
                   raw_device, strerror(errno));
       if ((fd = open(block_device, O_RDONLY, 0)) == -1)
               warn("%s", block_device);

     APPLICATION USAGE
       None.

     RATIONALE
       None.

     FUTURE DIRECTIONS
       None.

     SEE ALSO
       XBD <err.h>

steffen

2014-01-13 12:38

reporter   bugnote:0002101

To address also the other remarks from the teleconference summary regarding this issue i've integrated some paragraphs from the POSIX perror() manual.

(One may allow me also doubts on wether all this duplication of -- mostly implied -- documentation is useful ([stream orientation,] stream error indication, stream I/O caused file timestamp updates); i'd hope that's accomplished with a simple roff macro, but it doesn't seem so! Of course, an official standard has to face freshly divorced and highly indebted lawyers, which make a living from that.)

For simplicity the following is an update of all the desired actions' content.
I hope it is now sufficient from the documtentation point of view.
Thank you.

- Vol. 1: Base Definitions, Chapter 13, «Headers».

  On page 234, line 7718
  add (insert before)

    NAME
      err.h - formatted error messages

    SYNOPSIS
      #include <err.h>

    DESCRIPTION
      The <err.h> header shall declare the following as functions or
      define them as macros. Function prototypes shall be provided.

        void err(int, const char *, ...);
        void verr(int, const char *, va_list);
        void errx(int, const char *, ...);
        void verrx(int, const char *, va_list);
        void warn(const char *, ...);
        void vwarn(const char *, va_list);
        void warnx(const char *, ...);
        void vwarnx(const char *, va_list);

    APPLICATION USAGE
      None.

    RATIONALE
      None.

    FUTURE DIRECTIONS
      None.

    SEE ALSO
      XSH err()

- Vol. 2: System Interfaces.

   On page 775, line 25933
   add (insert before)

    NAME
      err, verr, errx, verrx, warn, vwarn, warnx, vwarnx -
      formatted error messages

    SYNOPSIS
      #include <err.h>

        void err(int status, const char *fmt, ...);
        void verr(int status, const char *fmt, va_list);
        void errx(int status, const char *fmt, ...);
        void verrx(int status, const char *fmt, va_list);
        void warn(const char *fmt, ...);
        void vwarn(const char *fmt, va_list);
        void warnx(const char *fmt, ...);
        void vwarnx(const char *fmt, va_list);

    DESCRIPTION
      The err() and warn() family of functions display a formatted error
      message on the standard error output. In all cases, the last
      component of the program name, followed by a colon (`:') character
      and a space, are output. The text that follows depends on the
      function being called.
      The fmt specification (and associated arguments) may be any format
      allowed by printf(3), a simple string, or NULL. If the fmt argument
      is not NULL, the formatted error message is output.

      In the case of the err(), verr(), warn(), and vwarn() functions
      only, the error message string affiliated with the current value
      of the global variable errno is output (as obtained via a call to
      strerror(3)), preceded by a colon character and a space if fmt is
      not NULL. The counterpart functions, errx(), verrx(), warnx(),
      and vwarnx() do not output the error message string. The err(),
      verr(), errx() and verrx() functions do not return, but exit with
      the value of the argument status.

      The err() and warn() family of functions shall not change the
      orientation of the standard error stream.


      The warn() family of functions shall mark for update the last data
      modification and last file status change timestamps of the file
      associated with the standard error stream at some time between
      their successful completion and exit(), abort(), or the completion
      of fflush() or fclose() on stderr. The err() family of functions
      differs insofar as program termination is part of their business.

      On error, the warn() family of functions shall set the error
      indicator for the stream to which stderr points, and shall set
      errno to indicate the error.

      Since no value is returned, an application wishing to check for
      error situations should call clearerr(stderr) before calling any
      function from the warn() family of functions, then if
      ferror(stderr) returns non-zero, the value of errno indicates which
      error occurred.

    RETURN VALUE
      None.
      The err() family of functions does not return.

    ERRORS
      Refer to fprintf()[REF].

    EXAMPLES
      Display the current errno information string and exit:

        if ((p = malloc(size)) == NULL)
          err(EXIT_FAILURE, NULL);
        if ((fd = open(file_name, O_RDONLY, 0)) == -1)
          err(EXIT_FAILURE, "%s", file_name);

      Display an error message and exit:

        if (tm.tm_hour < START_TIME)
          errx(EXIT_FAILURE, "too early, wait until %s",
            start_time_string);

      Warn of an error:

        if ((fd = open(raw_device, O_RDONLY, 0)) == -1)
          warnx("%s: %s: trying the block device",
            raw_device, strerror(errno));
        if ((fd = open(block_device, O_RDONLY, 0)) == -1)
          warn("%s", block_device);

    APPLICATION USAGE
      None.

    RATIONALE
      None.

    FUTURE DIRECTIONS
      None.

    SEE ALSO
      fprintf, perror, psiginfo, strerror
      XBD <err.h>

joerg

2014-01-13 15:48

reporter   bugnote:0002102

Last edited: 2014-01-13 15:53

The proposal contains some problems and misses some information:

The proposed DESCRIPTION is hard to read and I am not sure whether
it correctly and completely describes the intended behavior.
But even when you read the implementation source code, it is hard
to understand the intended purpose of the various slightliy
differing interfaces.

If we include the %r format to printf() (see Bugid: 800), there
is no need for the v*() type functions. This could help to make
the proposal easier to read.

The proposal misses a drecription of the output format.

The proposal looks like a variant of what has been implemented in 1980
on the UNIX clone UNOS. UNOS seems to have a benefit in the way it
prints the message. On UNOS, the printed error message looks like:

variant a)

"%s: %r", progname, msg, args

variant b)

"%s: %s. %r", progname, strerror(err), msg, args


progname is the name of the program (typically av[0])
strerror(err) represents either the strerror() output or "Error %d"
msg is the message format from the error function
args is the va_list from the error function.

Variant (a) is printed in case that errno is negative
Variant (b) is printed in case that errno is non-negative


UNOS offers the following basic functions:

errmsg(fmt, args);
errmsgno(err, fmt, args);
comerr(fmt, args);
comerrno(err, fmt, args);

the errmsg*() functions just print the error message
the comerr*() functions print the error message and exit.

errmsg()/comerr() use the global errno, errmsgno()/comerrno() use the err
argument as the errno code.

exit() code is errno for the exiting functions, this is why I
added a new set of functions:

xcomerr(xcode, msg, args);
xcomerrno(xcode, err, msg, args);

That use xcode as the exit code.

steffen

2014-01-13 17:43

reporter   bugnote:0002103

0000794:0002102

  If we include the %r format to printf() (see Bugid: 800),
  there is no need for the v*() type functions.

I think offering the v*() family would still be a benefit given how expensive in respect to ressources format string parsing is implemented in all operating system implementations i know of (with the single exception Research POSIX a.k.a. Plan9).

In fact not offering them seems to countradict the introduction of some new interfaces for low-end hosts.

Moreover, given that most format-string related facilities are provided in v* and v-less versions it would introduce a interface disparity, imho.

  Variant (a) is printed in case that errno is negative
  Variant (b) is printed in case that errno is non-negative

To me who was not part of the good old days this must sound as if some (error-indicating) systemcall return value is treated in a special way. If that is the case here, i don't think it should be part of such an interface since POSIX only uses errno and doesn't itself define any negative error return value (unless i'm mistaken).

  errmsg()/comerr() use the global errno, errmsgno()/comerrno() use the err
  argument as the errno code

I deliberately left off the errc()/warnc()/verrc()/vwarnc() family, which takes an additional 'int code' argument (as the second argument after 'int status'), because it is not implemented everywhere.

That is a pity, i'd love to see them, too, not at last because the implementation of these functions is so easy (i think a maximum of two non-almost-stub functions), but i didn't dare to add them because of the above reason.

  The proposed DESCRIPTION is hard to read and I am not sure whether
  it correctly and completely describes the intended behavior.

  The proposal misses a drecription of the output format.

I look into this again soon and try to find less blown words.

steffen

2014-01-16 11:51

reporter   bugnote:0002104

Next iteration, hopefully addressing the concerns from 0000794:0002102, too.
As a small last-minute addition i've taken the freedom and include the *c() family of functions as well.

- Vol. 1: Base Definitions, Chapter 13, «Headers».

   On page 234, line 7718
   add (insert before)

     NAME
       err.h - formatted error messages

     SYNOPSIS
       #include <err.h>

     DESCRIPTION
       The <err.h> header shall declare the following as functions or
       define them as macros. Function prototypes shall be provided.

         void err(int, const char *, ...);
         void verr(int, const char *, va_list);
         void errc(int, int, const char *, ...);
         void verrc(int, int, const char *, va_list);
         void errx(int, const char *, ...);
         void verrx(int, const char *, va_list);
         void warn(const char *, ...);
         void vwarn(const char *, va_list);
         void warnc(int, const char *, ...);
         void vwarnc(int, const char *, va_list);
         void warnx(const char *, ...);
         void vwarnx(const char *, va_list);

     APPLICATION USAGE
       None.

     RATIONALE
       None.

     FUTURE DIRECTIONS
       None.

     SEE ALSO
       XSH err()

 - Vol. 2: System Interfaces.

    On page 775, line 25933
    add (insert before)

     NAME
       err, verr, errc, verrc, errx, verrx,
       warn, vwarn, warnc, vwarnc, warnx, vwarnx -
       formatted error messages

     SYNOPSIS
       #include <err.h>

         void err(int status, const char *fmt, ...);
         void verr(int status, const char *fmt, va_list);
         void errc(int status, int code, const char *fmt, ...);
         void verrc(int status, int code, const char *fmt, va_list);
         void errx(int status, const char *fmt, ...);
         void verrx(int status, const char *fmt, va_list);
         void warn(const char *fmt, ...);
         void vwarn(const char *fmt, va_list);
         void warnc(int code, const char *fmt, ...);
         void vwarnc(int code, const char *fmt, va_list);
         void warnx(const char *fmt, ...);
         void vwarnx(const char *fmt, va_list);

     DESCRIPTION
       The err() and warn() family of functions display a formatted error
       message on the standard error output. In all cases, the last
       component of the program name, a colon character (`:') and a space
       are output. If the fmt argument is not NULL, the printf(3)-like
       formatted error message is output.

       The err(), errc(), verr(), verrc(), warn(), warnc(), vwarn() and
       vwarnc() functions append an error message obtained from
       strerror(3) based on a supplied error code value or the global
       variable errno, preceded by another colon and space unless the fmt
       argument is NULL.

       In the case of the errc(), verrc(), warnc() and vwarnc() functions,
       the code argument is used to look up the error message.

       The errx(), verrx(), warnx() and vwarnx() functions do not append
       an error message.

       In all cases the output is terminated by a newline character.

       The err() and warn() family of functions shall not change the
       orientation of the standard error stream.

       It shall be guarenteed that the output produced by the err() and
       warn() family of functions is generated as a contiguous unit.

       The warn() family of functions shall mark for update the last data
       modification and last file status change timestamps of the file
       associated with the standard error stream at some time between
       their successful completion and exit(), abort(), or the completion
       of fflush() or fclose() on stderr. The err() family of functions
       differs insofar as program termination is part of their business.

       On error, the warn() family of functions shall set the error
       indicator for the stream to which stderr points, and shall set
       errno to indicate the error.

       Since no value is returned, an application wishing to check for
       error situations should call clearerr(stderr) before calling any
       function from the warn() family of functions, then if
       ferror(stderr) returns non-zero, the value of errno indicates which
       error occurred.

     RETURN VALUE
       None.
       The err() family of functions does not return.

     ERRORS
       Refer to fprintf()[REF].

     EXAMPLES
       Display the current errno information string and exit:

         if ((p = malloc(size)) == NULL)
           err(EXIT_FAILURE, NULL);
         if ((fd = open(file_name, O_RDONLY, 0)) == -1)
           err(EXIT_FAILURE, "%s", file_name);

       Display an error message and exit:

         if (tm.tm_hour < START_TIME)
           errx(EXIT_FAILURE, "too early, wait until %s",
             start_time_string);

       Warn of an error:

         if ((fd = open(raw_device, O_RDONLY, 0)) == -1)
           warnx("%s: %s: trying the block device",
             raw_device, strerror(errno));
         if ((fd = open(block_device, O_RDONLY, 0)) == -1)
           warn("%s", block_device);

     APPLICATION USAGE
       None.

     RATIONALE
       None.

     FUTURE DIRECTIONS
       None.

     SEE ALSO
       fprintf, perror, psiginfo, strerror
       XBD <err.h>

steffen

2014-01-16 11:56

reporter   bugnote:0002105

I've also attached a complete default implementation.
It's two implementations in one (choosable by preprocessor switch) -- the option is to prepare a single stack buffer and dump that in one go, instead of using flockfile(3) to protect multiple adjacent I/O operations.
I.e., what i've forgot -- i've added the requirement that the I/O shall form a contiguous block.

carlos

2014-03-04 05:44

reporter   bugnote:0002173

Adding the *c() variants to glibc would be a natural extension of the existing BSD-originating functions that have been in glibc for 12 years now. I would be willing to implement them in glibc on behalf of Red Hat.

I can't guarantee their inclusion since that would require final consensus from upstream. I doubt that there would be strong sustained opposition given the existing set of functions and the fact that the *c() variants exist in other OSs e.g. Mac OS X, but not glibc, and would therefore aid in porting.

ajosey

2014-04-11 06:57

manager   bugnote:0002224

This defect report raises the possibility of new interfaces
for inclusion, and as such it is out of scope of maintenance of the Austin Group
specifications for either a TC or Interpretation. If it were to meet the criteria
in SD6 for new work items then it may be considered for inclusion in a
future revision subject to the agreed scope determined at that time,
although there is no guarantee.

We have had to mark this defect report rejected for now, since we have been unable to find a sponsor for these interfaces.

The Austin Group is not a development body for new material apart from
integration issues arising from the merger of the approved standards
that were the Base documents into the revision.

See
http://www.opengroup.org/austin/docs/austin_sd6.txt for details on how
new work items are addressed and the sponsorship requirements.

Issue History

Date Modified Username Field Change
2013-11-15 20:40 steffen New Issue
2013-11-15 20:40 steffen Status New => Under Review
2013-11-15 20:40 steffen Assigned To => ajosey
2013-11-15 20:40 steffen Name => steffen
2013-11-15 20:40 steffen Section => Vol. 1. 13., Vol. 2 (new)
2013-11-15 20:40 steffen Page Number => 234, 775
2013-11-15 20:40 steffen Line Number => 7718, 25933
2013-12-18 20:46 shware_systems Note Added: 0002084
2013-12-18 20:55 shware_systems Note Edited: 0002084
2013-12-21 16:48 steffen Note Added: 0002090
2013-12-21 20:35 Don Cragun Project 2008-TC1 => 1003.1(2013)/Issue7+TC1
2013-12-21 20:39 Don Cragun Interp Status => ---
2013-12-21 20:39 Don Cragun Note Added: 0002091
2013-12-21 20:39 Don Cragun Category Rationale => System Interfaces
2014-01-09 17:19 msbrown Note Added: 0002097
2014-01-09 18:00 steffen Note Added: 0002098
2014-01-13 12:38 steffen Note Added: 0002101
2014-01-13 15:48 joerg Note Added: 0002102
2014-01-13 15:51 joerg Note Edited: 0002102
2014-01-13 15:53 joerg Note Edited: 0002102
2014-01-13 17:43 steffen Note Added: 0002103
2014-01-16 11:51 steffen Note Added: 0002104
2014-01-16 11:52 steffen File Added: posix-err.diff
2014-01-16 11:56 steffen Note Added: 0002105
2014-03-04 05:44 carlos Note Added: 0002173
2014-04-11 06:57 ajosey Note Added: 0002224
2014-04-11 06:57 ajosey Status Under Review => Closed
2014-04-11 06:57 ajosey Resolution Open => Rejected