void _sprintf(char *s, const char *fmt, ...) { va_list va; _sprintf_dst = s; va_start(va, fmt); _vfprintf(_sprintf_write, fmt, va); va_end(va); *_sprintf_dst = '\0'; }
static void nprintf(char *errcode, ...) { va_list a; char s[80]; char *p = s; start_string_char(errcode); /* * Convert error code into a string so that it can be printed. I expect * all strings used to be less than 80 characters long. */ while ((*p++ = fetch_string_char()) != 0); va_start(a, errcode); _vfprintf(stderr, s, a); va_end(a); }
static void errprintf(char *s, ...) { va_list a; va_start(a, s); _vfprintf(stderr, s, a); va_end(a); #ifndef NO_LISTING_OUTPUT if (listingstream != NULL) { check_error_buffer(); va_start(a, s); errsavep += (_vsprintf(&errsaves[errsavep], s, a), strlen(&errsaves[errsavep])); va_end(a); } #endif }
/* * Logs an DEBUG message on stdout */ static void debug(const char * format, ...) { va_list args; va_start(args,format); _vfprintf(stdout,"DEBUG",format,args); va_end(args); }
/* * Logs an ERROR message on stderr */ static void error(const char * format, ...) { va_list args; va_start(args,format); _vfprintf(stderr,"ERROR",format,args); va_end(args); }
/* * Logs an INFO message on stdout */ static void info(const char * format, ...) { va_list args; va_start(args,format); _vfprintf(stdout,"INFO",format,args); va_end(args); }
int com_vfprintf(const char *fncName, FILE *stream, const char *format, va_list ap) { // Get libc syscall function pointer & offset in image libc_func(vfprintf, int, FILE *, const char *, va_list); if (plr_checkInsidePLR()) { // If already inside PLR code, just call original syscall & return return _vfprintf(stream, format, ap); } else { plr_setInsidePLR(); int fn = fileno(stream); if (plrlogIsEnabled(LOG_SYSCALL)) { char *formatFmt = str_expandEscapes(format); plrlog(LOG_SYSCALL, "[%d:%s] Fileno %d, format '%s'\n", getpid(), fncName, fn, formatFmt); free(formatFmt); } // Use vasprintf to compute final string so that arguments can be checked // in addition to format va_list apCopy; va_copy(apCopy, ap); char *resStr; int vasRet = vasprintf(&resStr, format, apCopy); va_end(apCopy); if (plrlogIsEnabled(LOG_DEBUG)) { char *resStrFmt = str_expandEscapes(resStr); plrlog(LOG_DEBUG, "[%d:%s] Str = '%s'\n", getpid(), fncName, resStrFmt); free(resStrFmt); } syscallArgs_t args = { .addr = _off_vfprintf, .arg[0] = crc32(0, fncName, strlen(fncName)), .arg[1] = fn, .arg[2] = ((vasRet) ? crc32(0, resStr, strlen(resStr)) : 0), }; plr_checkSyscallArgs(&args); if (vasRet != -1) { free(resStr); } // Nested function actually performed by master process only ssize_t ret; int masterAct() { // Call original libc function ret = _vfprintf(stream, format, ap); // Store return value in shared memory for slave processes printfShmData_t shmDat = { .err = errno, .ret = ret }; plr_copyToShm(&shmDat, sizeof(shmDat), 0); return 0; } // All processes call plr_masterAction() to synchronize at this point plr_masterAction(masterAct); if (!plr_isMasterProcess()) { // Slaves copy return values from shared memory printfShmData_t shmDat; plr_copyFromShm(&shmDat, sizeof(shmDat), 0); // Return same value & errno as master ret = shmDat.ret; errno = shmDat.err; } plr_clearInsidePLR(); return ret; } }