1

I'm trying to wrap a variadic function to validate the input beforehand. To be precise i need to call sd_notifyf(int unset_environment, const char *format, ...).

https://www.freedesktop.org/software/systemd/man/sd_notify.html

But before calling sd_notifyf I want to validate the input for the format and then call sd_notify() in the wrapped function.

Currently I've tried the following:

void wrapperFunc(int unset_environment, const char *format, ...) {
  va_list list;
  va_start(list, format);

  //validation of va_args

  sd_notifyf(unset_environment, format, list);

  va_end(list);
}

int main(int argc, char *argv[]) {
  wrapperFunc(0, "STATUS=args: '%s' : '%s'", "arg1", "arg2");
}

In the real code, wrapperFunc() will be called when starting a service, so you can understand why I'm trying to call sd_notifyf().

With my current implementation the following is returned when checking the status of the service: STATUS=args: '^P' : 'arg2'

Why does it only show the second argument properly? And how can I achieve to wrap sd_notifyf() properly?

Xershy
  • 177
  • 11
  • Sooo, have you heard of `snprintf`? or better `aprintf`? `vsnprintf` and `vasprintf`? and then call `sd_notify` – KamilCuk Jan 17 '22 at 13:03
  • When you say "Why does it only show the second argument properly? " what are you actually getting? – Andrew Jan 17 '22 at 13:07
  • @KamilCuk no not really, it's my first time working with variadic functions, so I'm still learning. Could you perhaps provide a small example how I could achieve this using vsnprintf? – Xershy Jan 17 '22 at 13:07
  • @Andrew the output that i included in my post, the first argument is always reduced to '^P' and the second one is correct, not sure how to debug the output of sd_notifyf so I'm not sure why i receive '^P' for the first arg – Xershy Jan 17 '22 at 13:09

1 Answers1

3

The behaviour of your code is undefined.

sd_notifyf is a variadic function not a function taking as the last parameter va_list

int sd_notifyf( int unset_environment,
    const char *format,
    …);

I am afraid that you can not write the wrapper function as there is no version of the sd_notify function which takes va_list

You can only use the macro definition for that.

#define wrapperMacro(unset_environment, format, ...)\
    do{\
        /* do some stuff */\
         sd_notifyf(unset_environment, format, __VA_ARGS__);\
    }while(0)

You can also use string printf function (in this case vsnprintf):

#define LARGE_ENOUGH_TO_ACCOMODATE_THE_STRING 64

void wrapperFunc(int unset_environment, const char *format, ...) {
  va_list list;
  va_start(list, format);
  char buff[LARGE_ENOUGH_TO_ACCOMODATE_THE_STRING];

  vsnprintf(buff, sizeof(buff), format, list);

  sd_notify(unset_environment, buff);

  va_end(list);
}
0___________
  • 60,014
  • 4
  • 34
  • 74