-
Notifications
You must be signed in to change notification settings - Fork 0
/
child_errors.c
125 lines (114 loc) · 3.4 KB
/
child_errors.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
* Copyright (c) 2017 Max Fillinger
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "child_errors.h"
#include "child_messages.h"
void
child_warn(const char *message)
{
/*
* Enqueue a warning message to the parent, formatted similar to
* warn(3): The basename of the program, the message associated with
* the current errno, plus a message supplied by the caller.
*/
char *full_message;
if (asprintf(&full_message, "%s: %s: %s", getprogname(),
strerror(errno), message) == -1) {
child_fatal("asprintf");
}
enqueue_message((u_int32_t)MSG_WARN, full_message);
}
void
child_warnx(const char *message)
{
/* Like child_warn, but omit the message associated with errno. */
char *full_message;
if (asprintf(&full_message, "%s: %s", getprogname(), message) == -1) {
child_fatal("asprintf");
}
enqueue_message((u_int32_t)MSG_WARN, full_message);
}
void
file_err(struct input *in, char *message)
{
char *full_message;
if (asprintf(&full_message, "%s: %s: %s", getprogname(),
strerror(errno), message) == -1) {
ipc_error("asprintf failed.");
}
enqueue_message((u_int32_t)MSG_FILE_ERR, full_message);
if (in->fd != -1 && close(in->fd) != 0)
child_warn("close");
in->fd = -1;
in->fmt = UNKNOWN;
}
void
file_errx(struct input *in, char *message)
{
char *full_message;
if (asprintf(&full_message, "%s: %s", getprogname(), message) == -1) {
ipc_error("asprintf failed.");
}
enqueue_message((u_int32_t)MSG_FILE_ERR, full_message);
if (in->fd != -1 && close(in->fd) != 0)
child_warn("close");
in->fd = -1;
in->fmt = UNKNOWN;
}
__dead void
child_fatal(const char *message)
{
/*
* Send a fatal error message to the parent and exit. The message
* is formatted similar to err(3): The basename of the program, the
* message associated with the current errno, plus a message supplied
* by the caller.
*/
char *full_message;
if (asprintf(&full_message, "%s: %s: %s", getprogname(),
strerror(errno), message) == -1) {
ipc_error("asprintf failed.");
}
enqueue_message((u_int32_t)MSG_WARN, full_message);
send_messages();
_exit(1);
}
__dead void
child_fatalx(const char *message)
{
/* Like child_fatal, but omit the message associated with errno. */
char *full_message;
if (asprintf(&full_message, "%s: %s", getprogname(), message) == -1) {
ipc_error("asprintf failed.");
}
enqueue_message((u_int32_t)MSG_FATAL, full_message);
send_messages();
_exit(1);
}
__dead void
ipc_error(const char *message)
{
/*
* If the child process cannot communicate with the parent anymore,
* try to print an error message to stderr and exit.
*/
dprintf(2, "pnp child: %s: %s\n", strerror(errno), message);
_exit(1);
}