標準入力がファイルからのリダイレクトだと、statやmmapが効いて便利である。しかし、標準入力がパイプだとそういった機能は使えない。
ファイルでなかった場合はファイルに書き出してからexecすることで、標準入力がファイルであることを保証できると思った。
※ただし後始末の関係上開いているファイルを削除するのでWindowsではうまく動きません
stdinasfile.c
#include "../compat.h"
#ifdef STANDALONE
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
unsigned char buf[BUFLEN];
#else
#include "../cielbox.h"
#endif
//#include <errno.h>
#ifdef STANDALONE
int main(const int argc, const char **argv){
initstdio();
#else
int stdinasfile(const int argc, const char **argv){
#endif
if(argc<2){
fprintf(stderr,"cmd | stdinasfile program/interpreter...\n");
fprintf(stderr,"in this way program can \"stat\" previous pipe.\n");
return 0;
}
struct stat st;
int status = fstat(0,&st);
if(status || !S_ISREG(st.st_mode)){
//fprintf(stderr,"running stdinasfile %d %d %x\n",status,errno,st.st_mode);
char template[]="/tmp/stdinasfileXXXXXX";
int fd = mkstemp(template);
unlink(template);
int len;
for(;(len=fread(buf,1,BUFLEN,stdin))>0;){
write(fd,buf,len);
}
lseek(fd,0,SEEK_SET);
close(0);
dup2(fd,0);
close(fd);
}
const char *cmd=argv[1];
char **args=(char**)malloc(sizeof(char*)*(argc));
for(int i=1;i<argc;i++)args[i-1]=(char*)argv[i];
args[argc-1]=NULL;
execvp(cmd,args); //execvp is required; cmd might be interpreter name
free(args);
return 0;
}