1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/wait.h>
5 #include <string.h>
6 
7 #include "autoOpen.h"
8 
9 // Implementation of "popen" that ignores stderr
popenNoStderr(const char * exe,const char * const argv[],int * retPid)10 static FILE* popenNoStderr(const char *exe, const char *const argv[], int* retPid)
11 {
12 	int out[2];
13 	int pid;
14 	int rc;
15 
16 	rc = pipe(out);
17 	if (rc<0)
18 		goto error_out;
19 
20 	pid = fork();
21 	if (pid > 0) { // parent
22 		close(out[1]);
23                 *retPid = pid;
24                 return fdopen(out[0], "r");
25 	} else if (pid == 0) { // child
26 		close(out[0]);
27 		close(1);
28 		dup(out[1]);
29 
30 		close(0);   // Don't let child inherit stdin, nor stderr
31 		close(2);
32 
33 		execvp(exe, (char**)argv);
34 		exit(1);
35 	} else
36 		goto error_fork;
37 
38 	return NULL;
39 
40 error_fork:
41 	close(out[0]);
42 	close(out[1]);
43 error_out:
44 	return NULL;
45 }
46 
pcloseNoStderr(int pid,FILE * out)47 static int pcloseNoStderr(int pid, FILE* out)
48 {
49 	int rc, status;
50         fclose(out);
51 	rc = waitpid(pid, &status, 0);
52 	return status;
53 }
54 
55 
56 static const char const* decompressors[] = {"","pigz", "gunzip", "pbunzip2", "bunzip2", NULL};
57 
openFileAuto(char * filename)58 AutoFile* openFileAuto(char*filename)
59 {
60 	AutoFile* seqFile = calloc(1, sizeof(AutoFile));
61   	int i;
62 
63 	if (strcmp(filename, "-")==0)
64 		  exitErrorf(EXIT_FAILURE, false, "Cannot read from stdin in auto mode\n");
65 
66 	for (i=0; decompressors[i] ; i++) {
67 		if (strlen(decompressors[i])==0) {
68 			seqFile->file = fopen(filename, "r");
69 			seqFile->pid = 0;
70 			seqFile->decompressor = "Raw read";
71 		} else {
72 			//printf("Trying : %s\n", decompressors[i]);
73 			char const* args[] = {decompressors[i], "-c", "-d", filename, NULL};
74 			seqFile->file = popenNoStderr(args[0], args, &(seqFile->pid));
75 			seqFile->decompressor = decompressors[i];
76 		}
77 
78 		if (!seqFile->file)
79 			continue;
80 
81 		int c = fgetc(seqFile->file);
82 		if (c=='>' || c=='@') {
83 			// Ok, looks like FASTA or FASTQ
84                 	ungetc(c, seqFile->file);
85                         seqFile->first_char = c;
86 			return seqFile;
87 		} else {
88 			if (seqFile->pid)
89 				pcloseNoStderr(seqFile->pid, seqFile->file);
90 			else
91 				fclose(seqFile->file);
92 		}
93 	}
94 	//printf("Unable to determine file type\n");
95 	return NULL;
96 }
97 
closeFileAuto(AutoFile * seqFile)98 void closeFileAuto(AutoFile* seqFile)
99 {
100 	if (!seqFile)
101 		return;
102 
103 	if (seqFile->pid)
104 		pcloseNoStderr(seqFile->pid, seqFile->file);
105 	else
106 		fclose(seqFile->file);
107 }
108