Provide an interface that allows GEOM modules to return multiple messages.

The gctl_error() function provides GEOM modules with the ability
to report only a single message. When running with the verbose
flag, commands that handle multiple devices may want to report a
message for each of the devices on which it operates. This commit
adds the gctl_msg() function that can be called multiple times
to post messages. When finished issuing messages, the application
must either call gctl_post_messages() or call gctl_error() to cause
the messages to be reported to the calling process.

Tested by:    Peter Holm
This commit is contained in:
Kirk McKusick 2022-02-19 21:30:37 -08:00
parent a4a31271cc
commit c8cc568961
2 changed files with 57 additions and 2 deletions

View File

@ -435,6 +435,8 @@ char const *gctl_get_asciiparam(struct gctl_req *req, const char *param);
void *gctl_get_paraml(struct gctl_req *req, const char *param, int len);
void *gctl_get_paraml_opt(struct gctl_req *req, const char *param, int len);
int gctl_error(struct gctl_req *req, const char *fmt, ...) __printflike(2, 3);
void gctl_msg(struct gctl_req *req, const char *fmt, ...) __printflike(2, 3);
void gctl_post_messages(struct gctl_req *req);
struct g_class *gctl_get_class(struct gctl_req *req, char const *arg);
struct g_geom *gctl_get_geom(struct gctl_req *req, struct g_class *mp, char const *arg);
struct g_provider *gctl_get_provider(struct gctl_req *req, char const *arg);

View File

@ -91,18 +91,71 @@ gctl_error(struct gctl_req *req, const char *fmt, ...)
if (sbuf_done(req->serror)) {
if (!req->nerror)
req->nerror = EEXIST;
#ifdef DIAGNOSTIC
printf("gctl_error: buffer closed, message discarded.\n");
#endif
return (req->nerror);
}
if (!req->nerror)
req->nerror = EINVAL;
/* If this is the last of several messages, indent it on a new line */
if (sbuf_len(req->serror) > 0)
sbuf_cat(req->serror, "\n\t");
va_start(ap, fmt);
sbuf_vprintf(req->serror, fmt, ap);
va_end(ap);
gctl_post_messages(req);
return (req->nerror);
}
/*
* The gctl_error() function will only report a single message.
* Commands that handle multiple devices may want to report a
* message for each of the devices. The gctl_msg() function
* can be called multiple times to post messages. When done
* the application must either call gctl_post_messages() or
* call gctl_error() to cause the messages to be reported to
* the calling process.
*/
void
gctl_msg(struct gctl_req *req, const char *fmt, ...)
{
va_list ap;
if (req == NULL)
return;
if (sbuf_done(req->serror)) {
#ifdef DIAGNOSTIC
printf("gctl_msg: buffer closed, message discarded.\n");
#endif
return;
}
/* Put second and later messages indented on a new line */
if (sbuf_len(req->serror) > 0)
sbuf_cat(req->serror, "\n\t");
va_start(ap, fmt);
sbuf_vprintf(req->serror, fmt, ap);
va_end(ap);
}
/*
* Post the messages to the user.
*/
void
gctl_post_messages(struct gctl_req *req)
{
if (sbuf_done(req->serror)) {
#ifdef DIAGNOSTIC
printf("gctl_post_messages: message buffer already closed.\n");
#endif
return;
}
sbuf_finish(req->serror);
if (g_debugflags & G_F_CTLDUMP)
printf("gctl %p error \"%s\"\n", req, sbuf_data(req->serror));
return (req->nerror);
printf("gctl %p message(s) \"%s\"\n", req,
sbuf_data(req->serror));
}
/*