diff --git a/libmaxsi/Makefile b/libmaxsi/Makefile
index 9e241ce2..9408e50b 100644
--- a/libmaxsi/Makefile
+++ b/libmaxsi/Makefile
@@ -40,6 +40,7 @@ c/h/wctype.h \
c/h/features.h \
c/h/string.h \
c/h/errno.h \
+c/h/error.h \
c/h/sys/readdirents.h \
c/h/sys/stat.h \
c/h/sys/types.h \
diff --git a/libmaxsi/c/hsrc/errno.h b/libmaxsi/c/hsrc/errno.h
index fa35f953..82174679 100644
--- a/libmaxsi/c/hsrc/errno.h
+++ b/libmaxsi/c/hsrc/errno.h
@@ -32,6 +32,8 @@ __BEGIN_DECLS
@include(errno_decl.h)
@include(errno_values.h)
+extern char* program_invocation_name;
+
__END_DECLS
#endif
diff --git a/libmaxsi/c/hsrc/error.h b/libmaxsi/c/hsrc/error.h
new file mode 100644
index 00000000..43ad6467
--- /dev/null
+++ b/libmaxsi/c/hsrc/error.h
@@ -0,0 +1,36 @@
+/******************************************************************************
+
+ COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
+
+ This file is part of LibMaxsi.
+
+ LibMaxsi is free software: you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with LibMaxsi. If not, see .
+
+ error.h
+ Error reporting functions.
+
+******************************************************************************/
+
+#ifndef _ERROR_H
+#define _ERROR_H 1
+
+#include
+
+__BEGIN_DECLS
+
+void error(int status, int errnum, const char *format, ...);
+
+__END_DECLS
+
+#endif
diff --git a/libmaxsi/c/hsrc/stdio.h b/libmaxsi/c/hsrc/stdio.h
index e7e286a5..25aa0a45 100644
--- a/libmaxsi/c/hsrc/stdio.h
+++ b/libmaxsi/c/hsrc/stdio.h
@@ -76,6 +76,7 @@ extern FILE* stderr;
#define stdout stdout
#define stderr stderr
+extern void perror(const char* s);
extern int printf(const char* restrict format, ...);
/* TODO: These are not implemented in libmaxsi/sortix yet. */
@@ -141,7 +142,6 @@ extern ssize_t getline(char** restrict lineptr, size_t* restrict n, FILE* restri
extern void clearerr(FILE* stream);
extern void flockfile(FILE* file);
extern void funlockfile(FILE* file);
-extern void perror(const char* s);
extern void rewind(FILE* stream);
extern void setbuf(FILE* restrict stream, char* restrict buf);
diff --git a/libmaxsi/init.cpp b/libmaxsi/init.cpp
index 7047ec0e..3bf01e2f 100644
--- a/libmaxsi/init.cpp
+++ b/libmaxsi/init.cpp
@@ -25,13 +25,23 @@
#include "platform.h"
#include "signal.h"
+#include "string.h"
+#include "io.h"
namespace Maxsi
{
+ extern "C" { char program_invocation_name_data[256] = ""; }
+ extern "C" { char* program_invocation_name = program_invocation_name_data; }
+
extern "C" void init_error_functions();
- extern "C" void initialize_standard_library()
+ extern "C" void initialize_standard_library(int argc, char* argv[])
{
+ if ( argc )
+ {
+ String::Copy(program_invocation_name, argv[0]);
+ }
+
// Initialize stuff such as errno.
init_error_functions();
diff --git a/libmaxsi/io.cpp b/libmaxsi/io.cpp
index cd907fe1..db95beb6 100644
--- a/libmaxsi/io.cpp
+++ b/libmaxsi/io.cpp
@@ -29,6 +29,10 @@
#include "string.h"
#include
#include
+#include
+#include
+#include
+#include
namespace Maxsi
{
@@ -76,6 +80,24 @@ namespace Maxsi
return (int) result;
}
+ extern "C" void error(int status, int errnum, const char *format, ...)
+ {
+ printf("%s: ", program_invocation_name);
+
+ va_list list;
+ va_start(list, format);
+ size_t result = Maxsi::Format::Virtual(PrintCallback, NULL, format, list);
+ va_end(list);
+
+ printf(": %s\n", strerror(errnum));
+ if ( status ) { exit(status); }
+ }
+
+ extern "C" void perror(const char* s)
+ {
+ error(0, errno, "%s", s);
+ }
+
extern "C" ssize_t read(int fd, void* buf, size_t count)
{
return SysRead(fd, buf, count);
diff --git a/utils/cat.cpp b/utils/cat.cpp
index e98475b5..0b525f8c 100644
--- a/utils/cat.cpp
+++ b/utils/cat.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
int cat(int argc, char* argv[])
@@ -10,14 +11,14 @@ int cat(int argc, char* argv[])
int result = 0;
int outfd = open("/dev/tty", O_WRONLY | O_APPEND);
- if ( outfd < 0 ) { printf("%s: %s: %s\n", argv[0], "/dev/tty", strerror(errno)); return 1; }
+ if ( outfd < 0 ) { error(0, errno, "%s", "/dev/tty"); return 1; }
for ( int i = 1; i < argc; i++ )
{
int fd = open(argv[i], O_RDONLY);
if ( fd < 0 )
{
- printf("%s: %s: %s\n", argv[0], argv[i], strerror(errno));
+ error(0, errno, "%s", argv[i]);
result = 1;
continue;
}
@@ -30,13 +31,13 @@ int cat(int argc, char* argv[])
if ( bytesread == 0 ) { break; }
if ( bytesread < 0 )
{
- printf("%s: %s: %s\n", argv[0], argv[i], strerror(errno));
+ error(0, errno, "read: %s", argv[i]);
result = 1;
break;
}
if ( writeall(outfd, buffer, bytesread) )
{
- printf("%s: /dev/tty: %s\n", argv[0], strerror(errno));
+ error(0, errno, "write: %s", argv[i]);
result = 1;
break;
}
diff --git a/utils/cp.cpp b/utils/cp.cpp
index acbbba4f..912bebbd 100644
--- a/utils/cp.cpp
+++ b/utils/cp.cpp
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include
const char* basename(const char* path)
@@ -20,7 +21,7 @@ int main(int argc, char* argv[])
char tobuffer[256];
int fromfd = open(frompath, O_RDONLY);
- if ( fromfd < 0 ) { printf("%s: %s: %s\n", argv[0], frompath, strerror(errno)); return 1; }
+ if ( fromfd < 0 ) { error(1, errno, "%s", frompath); return 1; }
int tofd = open(topath, O_WRONLY | O_TRUNC | O_CREAT, 0777);
if ( tofd < 0 )
@@ -34,11 +35,7 @@ int main(int argc, char* argv[])
tofd = open(topath, O_WRONLY | O_TRUNC | O_CREAT, 0777);
}
- if ( tofd < 0 )
- {
- printf("%s: %s: %s\n", argv[0], topath, strerror(errno));
- return 1;
- }
+ if ( tofd < 0 ) { error(1, errno, "%s", topath); return 1; }
}
while ( true )
@@ -46,8 +43,8 @@ int main(int argc, char* argv[])
const size_t BUFFER_SIZE = 4096;
char buffer[BUFFER_SIZE];
ssize_t bytesread = read(fromfd, buffer, BUFFER_SIZE);
- if ( bytesread < 0 ) { printf("%s: %s: %s\n", argv[0], frompath, strerror(errno)); return 1; }
+ if ( bytesread < 0 ) { error(1, errno, "read: %s", frompath); return 1; }
if ( bytesread == 0 ) { return 0; }
- if ( writeall(tofd, buffer, bytesread) ) { printf("%s: %s: %s\n", argv[0], topath, strerror(errno)); return 1; }
+ if ( writeall(tofd, buffer, bytesread) ) { error(1, errno, "write: %s", topath); return 1; }
}
}
diff --git a/utils/editor.cpp b/utils/editor.cpp
index 66c325be..bbca7b5c 100644
--- a/utils/editor.cpp
+++ b/utils/editor.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
@@ -202,7 +203,7 @@ unsigned confirmquit()
bool savetofile(const char* path)
{
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0777);
- if ( fd < 0 ) { printf("%s: %s\n", path, strerror(errno)); return false; }
+ if ( fd < 0 ) { error(0, errno, "%s", path); return false; }
for ( unsigned y = 0; y < numlines; y++ )
{
@@ -210,10 +211,10 @@ bool savetofile(const char* path)
buffers[y][len] = '\n';
bool result = !writeall(fd, buffers[y], len+1);
buffers[y][len] = 0;
- if ( !result ) { printf("%s: %s\n", path, strerror(errno)); close(fd); return false; }
+ if ( !result ) { error(0, errno, "write: %s", path); close(fd); return false; }
}
- if ( close(fd) ) { printf("%s: %s\n", path, strerror(errno)); return false; }
+ if ( close(fd) ) { error(0, errno, "close: %s", path); return false; }
return true;
}
@@ -277,7 +278,7 @@ retry:
bool loadfromfile(const char* path)
{
int fd = open(path, O_RDONLY, 0777);
- if ( fd < 0 ) { printf("%s: %s\n", path, strerror(errno)); return false; }
+ if ( fd < 0 ) { error(0, errno, "%s", path); return false; }
clearbuffers();
@@ -288,7 +289,7 @@ bool loadfromfile(const char* path)
while ( !done )
{
ssize_t bytesread = read(fd, buffer, BUFFER_SIZE);
- if ( bytesread < 0 ) { printf("%s: %s\n", path, strerror(errno)); close(fd); return false; }
+ if ( bytesread < 0 ) { error(0, errno, "read: %s", path); close(fd); return false; }
if ( bytesread == 0 ) { break; }
for ( ssize_t i = 0; i < bytesread; i++ )
{
diff --git a/utils/help.cpp b/utils/help.cpp
index c34d3b7d..5668541a 100644
--- a/utils/help.cpp
+++ b/utils/help.cpp
@@ -1,4 +1,6 @@
#include
+#include
+#include
#include
#include
@@ -12,5 +14,7 @@ int main(int argc, char* argv[])
Maxsi::Process::Execute(programname, 2, newargv);
+ error(1, errno, "%s", programname);
+
return 1;
}
diff --git a/utils/init.cpp b/utils/init.cpp
index b9aaf4c4..d9f0b54f 100644
--- a/utils/init.cpp
+++ b/utils/init.cpp
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -23,6 +24,8 @@ int child()
Process::Execute(programname, 1, newargv);
+ error(0, errno, "%s", programname);
+
return 2;
}
@@ -35,13 +38,8 @@ int main(int argc, char* argv[])
// Reset the terminal's color and the rest of it.
printf("\r\e[m\e[J");
- pid_t childpid = Process::Fork();
-
- if ( childpid < 0 )
- {
- printf("init: fork: %s\n", strerror(errno));
- return 2;
- }
+ pid_t childpid = Process::Fork();
+ if ( childpid < 0 ) { perror("fork"); return 2; }
return ( childpid == 0 ) ? child() : parent(childpid);
}
diff --git a/utils/kill.cpp b/utils/kill.cpp
index 08434401..8d46461a 100644
--- a/utils/kill.cpp
+++ b/utils/kill.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
int usage()
{
@@ -29,7 +30,7 @@ int main(int argc, char* argv[])
pid_t pid = atoi(argv[i]);
if ( kill(pid, signum) )
{
- printf("kill: (%u): %s\n", pid, strerror(errno));
+ error(0, errno, "(%u)", pid);
result |= 1;
}
}
diff --git a/utils/ls.cpp b/utils/ls.cpp
index c903359a..8253deef 100644
--- a/utils/ls.cpp
+++ b/utils/ls.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -12,7 +13,7 @@ using namespace Maxsi;
int ls(const char* path)
{
int fd = open(path, O_SEARCH | O_DIRECTORY);
- if ( fd < 0 ) { printf("ls: %s: %s\n", path, strerror(errno)); return 2; }
+ if ( fd < 0 ) { error(2, errno, "%s", path); return 2; }
const size_t BUFFER_SIZE = 512;
char buffer[BUFFER_SIZE];
@@ -25,7 +26,7 @@ int ls(const char* path)
{
if ( readdirents(fd, dirent, BUFFER_SIZE) )
{
- printf("ls: %s: %s\n", path, strerror(errno));
+ error(2, errno, "readdirents: %s", path);
return 1;
}
diff --git a/utils/mxsh.cpp b/utils/mxsh.cpp
index ec4915fb..1bb68619 100644
--- a/utils/mxsh.cpp
+++ b/utils/mxsh.cpp
@@ -4,6 +4,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -95,14 +96,14 @@ void command()
if ( 1 < argc ) { newdir = argv[1]; }
if ( chdir(newdir) )
{
- printf("sh: cd: %s: %s\n", newdir, strerror(errno));
+ error(0, errno, "cd: %s", newdir);
status = 1;
}
return;
}
pid_t child = fork();
- if ( child < 0 ) { printf("sh: fork failed: %s\n", strerror(errno)); return; }
+ if ( child < 0 ) { perror("fork"); status = 1; return; }
if ( child != 0 )
{
pid_t childpid = wait(&status);
@@ -115,7 +116,7 @@ void command()
{
const char* file = argv[argc-1];
int outfd = open(file, O_CREAT | O_WRONLY | O_TRUNC | O_APPEND);
- if ( outfd < 0 ) { printf("%s: %s\n", file, strerror(errno)); exit(127); }
+ if ( outfd < 0 ) { error(127, errno, "%s", file); exit(127); }
close(1);
dup(outfd);
close(outfd);
@@ -127,9 +128,7 @@ void command()
Process::Execute(argv[0], argc, argv);
// This is clever. This only happens if the program didn't change.
- printf("%s: %s\n", argv[0], strerror(errno));
-
- exit(127);
+ error(127, errno, "%s", argv[0]);
}
int main(int argc, char* argv[])
diff --git a/utils/rm.cpp b/utils/rm.cpp
index 0ae402c9..0df66688 100644
--- a/utils/rm.cpp
+++ b/utils/rm.cpp
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
int main(int argc, char* argv[])
{
@@ -13,7 +14,7 @@ int main(int argc, char* argv[])
{
if ( unlink(argv[i]) )
{
- printf("%s: cannot remove %s: %s\n", argv[0], argv[i], strerror(errno));
+ error(0, errno, "cannot remove %s", argv[i]);
result = 1;
}
}