Imported Upstream version 2.5.2
[debian/dds2tar] / zf-cre-open.c
1
2 /*
3  * This file is part of dds2tar.
4  * Copyright by J"org Weule
5  *
6  * Copyright: GPL
7  */
8
9 /*
10  * If you compile this file with -DTEST, you will get a test program:
11  *
12  *     cc dds_fio.c -DTEST -o dds_fio && dds_fio
13  *
14  * The test shows the use of ccopen(...) to pipe stdout through /bin/grep.
15  *
16  * The interface should be useful in many cases.
17  */
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <sys/mtio.h>
22 #include <string.h>
23 #include <unistd.h>             /* pipe() ... */
24 #include <sys/types.h>          /* size_t, open() */
25 #include <sys/wait.h>           /* wait() */
26 #include <sys/stat.h>           /* open() */
27 #include <fcntl.h>              /* open() */
28
29 #include "zf-cre-open.h"
30
31 #define streq(a,b) (!strcmp((a),(b)))
32
33 FILE   *
34 zfopen(
35               char const *const name,
36               int const compressed,
37               char const *const open_mode
38 )
39 {
40
41         FILE   *fp;
42         char   *b;
43
44         b = malloc(1024);
45         if (b == NULL)
46                 exit(20);
47
48         if (compressed == T_MODE) {
49                 if ((name != NULL) && (strcmp(name, "-"))) {
50                         fp = fopen(name, open_mode);
51                         if (fp == NULL) {
52                                 perror("dds2tar");
53                                 exit(21);
54                         }
55                 } else if (streq(open_mode, "w")) {
56                         fp = stdout;
57                 } else {
58                         fp = stdin;
59                 }
60                 return fp;
61         }
62         if (streq(open_mode, "w")) {
63                 strcpy(b, "gzip ");
64                 if ((name != NULL) && (strcmp(name, "-"))) {
65                         strcat(b, " > ");
66                         strcat(b, name);
67                 }
68         } else if (streq(open_mode, "r")) {
69                 strcpy(b, "gunzip --force --decompress --stdout ");
70                 if ((name != NULL) && (strcmp(name, "-"))) {
71                         strcat(b, name);
72                 }
73         }
74         fp = popen(b, open_mode);
75         if (fp == NULL) {
76                 perror("dds2tar");
77                 exit(22);
78         }
79         free(b);
80         return fp;
81 }
82
83
84 int
85 cclose(int const fd)
86 {
87         int     status = 0;
88
89         close(fd);
90         wait(&status);
91         return status;
92 }
93
94 int
95 reopen(
96               int const stdfd,
97               char const *const output_file,
98               int const mode,
99               int const flags
100 )
101 {
102         int     fd;
103
104         if (!strcmp(output_file, "-")) {
105                 /* use stdout */
106                 fd = 1;
107         } else {
108                 /* open file */
109                 if ((fd = open(output_file, mode, flags)) == -1) {
110                         perror("dds2tar");
111                         exit(23);
112                 }
113                 /* don't know why this happens. Any idea? */
114                 if (fd == 0) {  /* normally 0 is stdin!! */
115                         perror("dds2tar");
116                         exit(24);
117                 }
118         }
119         if (0 <= stdfd) {
120                 dup2(fd, stdfd);
121                 close(fd);
122                 fd = stdfd;
123         }
124         return fd;
125 }
126
127 /*
128  * creopen opens a pipe to a child process with the file number 'stdfd'
129  * on file number 'stdfd_child' of the child.
130  * The files are close as needed (see dup2(2)).
131  */
132
133 int
134 creopen(
135                int const stdfd_parent,  /* stdfd should not be == 3 */
136                int const stdfd_child,   /* stdfd_child must be 1 or 2 */
137                char const *const filename,
138                char const *const *argv
139 )
140 {
141         int     fd;
142         int     pid;
143         int     pipefd[2];
144         int     pipe_parent;
145
146         if ((stdfd_child & 0xfffffffe) != 0 || stdfd_child == stdfd_parent) {
147                 fprintf(stderr, "creopen not useful with that parameters\n");
148                 exit(25);
149         }
150         pipe_parent = stdfd_child ^ 1;
151         if (pipe(pipefd) < 0) { /* create pipe with two fd's */
152                 perror("dds2tar");
153                 exit(26);
154         }
155         if ((pid = fork()) == 0) {      /* we are the child process */
156                 /* reconnect pipe to child */
157                 dup2(pipefd[stdfd_child], stdfd_child);
158                 close(pipefd[0]);       /* close input of pipe */
159                 close(pipefd[1]);       /* close output of pipe */
160                 /* the prototype of execv is wrong */
161                 execv(filename, (char *const *) argv);
162                 perror("dds2tar");
163                 exit(27);
164         }
165         if (pid <= 0) {
166                 perror("dds2tar");
167                 exit(28);
168         }
169         /*
170          * We are the parent process.
171          */
172         close(stdfd_child);
173         fd = pipefd[pipe_parent];
174         if ((0 <= stdfd_parent) && (stdfd_parent <= 1)) {
175                 dup2(fd, stdfd_parent);
176                 close(fd);
177                 fd = stdfd_parent;
178                 close(pipefd[0]);
179                 close(pipefd[1]);
180         }
181         return fd;
182 }
183
184 #ifdef TEST
185
186 static char *a[] =
187 {"grep", "allo", NULL};
188
189 main(int argc, char **argv, char **envp)
190 {
191
192         int     status;
193         int     pid;
194         int     fd;
195
196         if (!strcmp(argv[1], "-p")) {
197         } else {
198                 if (!strcmp(argv[1], "-o"))
199                         reopen(1, argv[2], O_RDONLY, 0);
200                 else
201                         creopen(1, 0, "/usr/bin/grep", a);
202                 write(1, "Hallo World -1- \n", 17);
203                 write(1, "Hi    World -2- \n", 17);
204                 write(1, "Hallo World -3- \n", 17);
205                 write(1, "Morgen Welt -4- \n", 17);
206                 write(1, "Hallo World -5- \n", 17);
207                 printf("Hallo World =1= \n");
208                 printf("Hi    World =2= \n");
209                 printf("Hallo World =3= \n");
210                 printf("Morgen Welt =4= \n");
211                 printf("Hallo World =5= \n");
212                 fflush(stdout);
213                 if (!strcmp(argv[1], "-o")) {
214                         close(1);
215                 } else {
216                         cclose(1);
217                 }
218         }
219 }
220
221 #endif