OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [peripheral/] [channels/] [xterm.c] - Blame information for rev 82

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jeremybenn
/* xterm.c -- Definition of functions and structures for
2
   peripheral to communicate with host through an xterm.
3
   Inspired from SWI-Prolog by Jan Wielemaker (GPL too)
4
   even if there is really few in common.
5
 
6
   Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
7
   Copyright (C) 2008 Embecosm Limited
8
 
9
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
10
 
11
   This file is part of OpenRISC 1000 Architectural Simulator.
12
 
13
   This program is free software; you can redistribute it and/or modify it
14
   under the terms of the GNU General Public License as published by the Free
15
   Software Foundation; either version 3 of the License, or (at your option)
16
   any later version.
17
 
18
   This program is distributed in the hope that it will be useful, but WITHOUT
19
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
21
   more details.
22
 
23
   You should have received a copy of the GNU General Public License along
24
   with this program.  If not, see <http://www.gnu.org/licenses/>. */
25
 
26
 
27
/* This program is commented throughout in a fashion suitable for processing
28
   with Doxygen. */
29
 
30
 
31
/* Autoconf and/or portability configuration */
32
#include "config.h"
33
#include "port.h"
34
 
35
/* System includes */
36
#if defined(HAVE_GRANTPT) && defined(HAVE_UNLOCKPT) && defined(HAVE_PTSNAME)
37
#endif
38
 
39
#include <stdlib.h>
40
#include <unistd.h>
41
#include <signal.h>
42
#include <termios.h>
43
#include <errno.h>
44
#include <stdio.h>
45
#include <fcntl.h>
46
#include <sys/types.h>
47
#include <sys/wait.h>
48
 
49
#if HAVE_SYS_STROPTS_H
50
#include <sys/stropts.h>        /* I_PUSH ioctl */
51
#endif
52
 
53
#if HAVE_BASENAME
54
#include <libgen.h>             /* basename() */
55
#endif
56
 
57
/* Package includes */
58
#include "channel.h"
59
#include "generic.h"
60
#include "fd.h"
61
 
62
/*! Data structure to represent the connection to the xterm */
63
struct xterm_channel
64
{
65
  struct fd_channel fds;
66
  int pid;
67
  char **argv;
68
};
69
 
70
/* Forward declaration of static functions */
71
static void  xterm_close (void *data);
72
static void *xterm_init (const char *input);
73
static int   xterm_open (void *data);
74
 
75
/*! Global data structure with the xterm interface functions */
76
struct channel_ops  xterm_channel_ops = {
77
        .init  = xterm_init,
78
        .open  = xterm_open,
79
        .close = xterm_close,
80
        .read  = fd_read,
81
        .write = fd_write,
82
        .free  = generic_free,
83
};
84
 
85
 
86
#if !(HAVE_BASENAME)
87
static char *
88
basename (const char *filename)
89
{
90
  char *p = strrchr (filename, '/');
91
 
92
  return p ? p + 1 : (char *) filename;
93
}
94
#endif /* HAVE_BASENAME */
95
 
96
static void
97
xterm_close (void *data)
98
{
99
  struct xterm_channel *xt = data;
100
 
101
  if (!xt)
102
    return;
103
 
104
  if (xt->fds.fdin != -1)
105
    close (xt->fds.fdin);
106
 
107
  if (xt->pid != -1)
108
    {
109
      kill (xt->pid, SIGKILL);
110
      waitpid (xt->pid, NULL, 0);
111
    }
112
 
113
  if (xt->argv)
114
    free (xt->argv);
115
 
116
  xt->fds.fdin = -1;
117
  xt->fds.fdout = -1;
118
  xt->pid = -1;
119
  xt->argv = NULL;
120
 
121
}
122
 
123
#if defined(HAVE_ON_EXIT)
124
static void
125
xterm_exit (int i, void *data)
126
{
127
  xterm_close (data);
128
}
129
#endif
130
 
131
#define MAX_XTERM_ARGS 100
132
static void *
133
xterm_init (const char *input)
134
{
135
  struct xterm_channel *retval = malloc (sizeof (struct xterm_channel));
136
  if (retval)
137
    {
138
      int i;
139
      char *arglist;
140
 
141
      retval->fds.fdin = -1;
142
      retval->fds.fdout = -1;
143
      retval->pid = -1;
144
 
145
#if defined(HAVE_ON_EXIT)
146
      /* reset cause exit(1), leaving an xterm opened */
147
      on_exit (xterm_exit, retval);
148
#endif
149
 
150
      i = 2;
151
      arglist = (char *) input;
152
      retval->argv = malloc (sizeof (char *) * MAX_XTERM_ARGS);
153
      if (!retval->argv)
154
        {
155
          free (retval);
156
          return NULL;
157
        }
158
      /* Assume xterm arguments are separated by whitespace */
159
      while ((retval->argv[i++] = strtok (arglist, " \t\n")))
160
        {
161
          arglist = NULL;
162
          if (i == MAX_XTERM_ARGS - 1)
163
            {
164
              free (retval);
165
              return NULL;
166
            }
167
        }
168
 
169
    }
170
  return (void *) retval;
171
}
172
 
173
 
174
 
175
static int
176
xterm_open (void *data)
177
{
178
#if defined(HAVE_GRANTPT) && defined(HAVE_UNLOCKPT) && defined(HAVE_PTSNAME)
179
  struct xterm_channel *xt = data;
180
  int master, retval;
181
  char *slavename;
182
  struct termios termio;
183
  char arg[64], *fin;
184
 
185
  if (!data)
186
    {
187
      errno = ENODEV;
188
      return -1;
189
    }
190
 
191
  master = open ("/dev/ptmx", O_RDWR);
192
 
193
  if (master < 0)
194
    return -1;
195
 
196
  grantpt (master);
197
  unlockpt (master);
198
  slavename = (char *) ptsname (master);
199
 
200
  if (!slavename)
201
    {
202
      errno = ENOTTY;
203
      goto closemastererror;
204
    }
205
 
206
  xt->fds.fdout = xt->fds.fdin = open (slavename, O_RDWR);
207
  if (xt->fds.fdout < 0)
208
    goto closemastererror;
209
 
210
#if HAVE_DECL_I_PUSH
211
  /* These modules must be pushed onto the stream for some non-Linux and
212
     non-Cygwin operating systems. */
213
  retval = ioctl (xt->fds.fdin, I_PUSH, "ptem");
214
  if (retval < 0)
215
    goto closeslaveerror;
216
 
217
  retval = ioctl (xt->fds.fdin, I_PUSH, "ldterm");
218
  if (retval < 0)
219
    goto closeslaveerror;
220
#endif
221
 
222
  retval = tcgetattr (xt->fds.fdin, &termio);
223
  if (retval < 0)
224
    goto closeslaveerror;
225
  termio.c_lflag &= ~ECHO;
226
  retval = tcsetattr (xt->fds.fdin, TCSADRAIN, &termio);
227
  if (retval < 0)
228
    goto closeslaveerror;
229
 
230
  xt->pid = fork ();
231
 
232
  if (xt->pid == -1)
233
    goto closeslaveerror;
234
 
235
  if (xt->pid == 0)
236
    {
237
      /* Ctrl-C on sim still kill the xterm, grrr */
238
      signal (SIGINT, SIG_IGN);
239
 
240
      fin = slavename + strlen (slavename) - 2;
241
      if (strchr (fin, '/'))
242
        {
243
          sprintf (arg, "-S%s/%d", basename (slavename), master);
244
        }
245
      else
246
        {
247
          sprintf (arg, "-S%c%c%d", fin[0], fin[1], master);
248
        }
249
      xt->argv[0] = "xterm";
250
      xt->argv[1] = arg;
251
      execvp ("xterm", xt->argv);
252 82 jeremybenn
      if (write (master, "\n", 1) < 0)   /* Don't ignore result */
253
        {
254
          printf ("ERROR: xterm: write failed\n");
255
        }
256 19 jeremybenn
      exit (1);
257
    }
258
 
259
  do
260
    retval = read (xt->fds.fdin, &arg, 1);
261
  while (retval >= 0 && arg[0] != '\n');
262
  if (retval < 0)
263
    goto closeslaveerror;
264
 
265
  termio.c_lflag |= ECHO;
266
  retval = tcsetattr (xt->fds.fdin, TCSADRAIN, &termio);
267
 
268
  if (retval < 0)
269
    goto closeslaveerror;
270
 
271
  return 0;
272
 
273
closeslaveerror:
274
  close (xt->fds.fdin);
275
 
276
closemastererror:
277
  close (master);
278
  xt->pid = xt->fds.fdin = xt->fds.fdout = -1;
279
  return -1;
280
 
281
#else
282
  /* I don't see how this stuff should be working on a system that doesn't know
283
     grantpt(), unlockpt(), ptsname(). Mac OS X also does not have /dev/ptmx.
284
     -hpanther
285
   */
286
  return -1;
287
#endif
288
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.