LoginSignup
0
0

More than 3 years have passed since last update.

標準入力がファイルであるようにする

Last updated at Posted at 2021-04-18

標準入力がファイルからのリダイレクトだと、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;
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0