Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4973 right-hear 1
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
2
/*
3
   This is popen() and pclose() for MSDOS.  They were developed using
4
   Microsoft C, but should port easily to DOS C any compiler.
5
 
6
   Original author: pacetti@fl-ngnet.army.mil
7
 
8
   These routines are hacks, that is they SIMULATE thier UNIX
9
   counterparts.  Since MSDOS and won't allow concurrent process spawning,
10
   you can't really pipe.  I came up with this nearly stupid way around
11
   piping because I wanted to have some portability between UNIX and MSDOS.
12
   I'm probably not the first person to have this idea or implement it, but
13
   I think I'm the first to give it away for free (no points?!).
14
 
15
   The functions simulate popen() and pclose() by redirecting stdin or
16
   stdout, then spawning a child processes via system().
17
 
18
   If you popen() for read, the stdout is redirected to a temporary
19
   file, and the child is spawned.  The stdout is reopened via dup2(), the
20
   temporary file is opened for read and a file pointer to it is returned.
21
 
22
   If you popen() for write, a temporary file is opened for write, and
23
   a file pointer to it is returned.  When you pclose(), the stdin is
24
   redirected to the temporary file and the child is spawned.
25
 
26
   In both cases, pclose() closes and unlinks the temporary file.
27
 
28
   A static linked list of C structures is built to store necessary
29
   info for all popen()ed files so you can popen() more than one file at
30
   a time.
31
 
32
   The popen() function will return NULL on an error, or a valid FILE
33
   *pointer on a successful open.  The pclose() function will return
34
   negative one (-1) on an error or zero (0) on a successful close.
35
 
36
   The function prototypes are:
37
 
38
   FILE *popen(command, mode)
39
        char *command, char *mode;
40
 
41
   int pclose(pp)
42
       FILE *pp;
43
 
44
   Where command is a character string equivilant to a MSDOS command
45
   line, mode is "r" for read or "w" for write, and pp is a pointer to a
46
   file opened through popen().
47
 
48
   A main() function has been included for testing purposes, to compile
49
   it define the preprocessor token TEST at compile time.
50
 */
51
 
52
#include 
53
#include 
54
#include 
55
#include 
56
#include 
57
#include 
58
#include 
59
#include 
60
 
61
/* hold file pointer, descriptor, command, mode, temporary file name */
62
struct pipe_list {
63
  FILE *fp;
64
  int fd;
65
  char *command, mode[10], temp_name[FILENAME_MAX];
66
  struct pipe_list *next;
67
};
68
 
69
/* static, global list pointer */
70
static struct pipe_list *pl = NULL;
71
 
72
FILE *
73
popen (const char *cm, const char *md) /* program name, pipe mode */
74
{
75
  struct pipe_list *l1, *l2;
76
  static char *tn = NULL;       /* temporary file basename */
77
 
78
  if (!tn)
79
    if ((tn = tmpnam(0)) == NULL)
80
      return NULL;
81
 
82
  /* make new node */
83
  if ((l1 = (struct pipe_list *) malloc (sizeof (struct pipe_list))) == NULL)
84
    return NULL;
85
 
86
  /* zero out elements to we'll get here */
87
  l1->fd = 0;
88
  l1->fp = NULL;
89
  l1->next = NULL;
90
 
91
  /* if empty list - just grab new node */
92
  if (!pl)
93
    pl = l1;
94
  else
95
  {
96
    /* otherwise, find last node in list */
97
    ++(l1->fd);
98
    l2 = pl;
99
    while (l2->next)
100
    {
101
      ++(l1->fd);
102
      l2 = l2->next;
103
    };
104
    /* add new node to list */
105
    l2->next = l1;
106
  }
107
 
108
  /* stick in elements we know already */
109
  strcpy (l1->mode, md);
110
  sprintf (l1->temp_name, "%s.%d", tn, l1->fd);
111
 
112
  /* if can save the program name, build temp file */
113
  if ((l1->command = malloc(strlen(cm)+1)))
114
  {
115
    strcpy(l1->command, cm);
116
    /* if caller wants to read */
117
    if (l1->mode[0] == 'r')
118
    {
119
      /* dup stdout */
120
      if ((l1->fd = dup (fileno (stdout))) == EOF)
121
	l1->fp = NULL;
122
      else if (!(l1->fp = freopen (l1->temp_name, "wb", stdout)))
123
	l1->fp = NULL;
124
      else
125
	/* exec cmd */
126
	if (system (cm) == EOF)
127
	  l1->fp = NULL;
128
      /* reopen real stdout */
129
      if (dup2 (l1->fd, fileno (stdout)) == EOF)
130
      {
131
	l1->fp = NULL;
132
	close(l1->fd);
133
      }
134
      else
135
	/* open file for reader */
136
	l1->fp = fopen (l1->temp_name, l1->mode);
137
    }
138
    else
139
      /* if caller wants to write */
140
      if (l1->mode[0] == 'w')
141
        /* open temp file */
142
        l1->fp = fopen (l1->temp_name, l1->mode);
143
      else
144
        /* unknown mode */
145
        l1->fp = NULL;
146
  }
147
  return l1->fp;              /* return == NULL ? ERROR : OK */
148
}
149
 
150
int
151
pclose (FILE *pp)
152
{
153
  struct pipe_list *l1, *l2;    /* list pointers */
154
  int retval=0;			/* function return value */
155
 
156
  /* if pointer is first node */
157
  if (pl->fp == pp)
158
  {
159
    /* save node and take it out the list */
160
    l1 = pl;
161
    pl = l1->next;
162
  }
163
  else
164
    /* if more than one node in list */
165
    if (pl->next)
166
    {
167
      /* find right node */
168
      for (l2 = pl, l1 = pl->next; l1; l2 = l1, l1 = l2->next)
169
        if (l1->fp == pp)
170
          break;
171
 
172
      /* take node out of list */
173
      l2->next = l1->next;
174
    }
175
    else
176
      return -1;
177
 
178
  /* if FILE not in list - return error */
179
  if (l1->fp == pp)
180
  {
181
    /* close the (hopefully) popen()ed file */
182
    fclose (l1->fp);
183
 
184
    /* if pipe was opened to write */
185
    if (l1->mode[0] == 'w')
186
    {
187
      /* dup stdin */
188
      if ((l1->fd = dup (fileno (stdin))) == EOF)
189
	retval = -1;
190
      else
191
	/* open temp stdin */
192
	if (!(l1->fp = freopen (l1->temp_name, "rb", stdin)))
193
	  retval = -1;
194
	else
195
	  /* exec cmd */
196
          if (system (l1->command) == EOF)
197
            retval = -1;
198
          else
199
	  {
200
            /* reopen stdin */
201
	    if (dup2 (l1->fd, fileno (stdin)) == EOF)
202
	      retval = -1;
203
	    close(l1->fd);
204
	  }
205
    }
206
    else
207
      /* if pipe was opened to read */
208
      if (l1->mode[0] == 'r')
209
        retval = 0;
210
      else
211
        /* invalid mode */
212
        retval = -1;
213
  }
214
  remove (l1->temp_name);       /* remove temporary file */
215
  free (l1->command);           /* dealloc memory */
216
  free (l1);                    /* dealloc memory */
217
  l1 = NULL;                    /* make pointer bogus */
218
 
219
  return retval;              /* retval==0 ? OK : ERROR */
220
}