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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [expect/] [exp_pty.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* exp_pty.c - generic routines to allocate and test ptys
2
 
3
Written by: Don Libes, NIST,  3/9/93
4
 
5
Design and implementation of this program was paid for by U.S. tax
6
dollars.  Therefore it is public domain.  However, the author and NIST
7
would appreciate credit if this program or parts of it are used.
8
 
9
*/
10
 
11
#include "expect_cf.h"
12
#ifdef HAVE_UNISTD_H
13
#  include <unistd.h>
14
#endif
15
#ifdef HAVE_SYS_FCNTL_H
16
#  include <sys/fcntl.h>
17
#else
18
#  include <fcntl.h>
19
#endif
20
#include <sys/types.h>
21
#include <sys/stat.h>
22
 
23
#ifdef TIME_WITH_SYS_TIME
24
# include <sys/time.h>
25
# include <time.h>
26
#else
27
# if HAVE_SYS_TIME_H
28
#  include <sys/time.h>
29
# else
30
#  include <time.h>
31
# endif
32
#endif
33
 
34
#include <signal.h>
35
#include <setjmp.h>
36
#include <sys/file.h>
37
#define EXP_AVOID_INCLUDING_TCL_H 1
38
#include "expect_comm.h"
39
#include "exp_rename.h"
40
#include "exp_pty.h"
41
 
42
#include <errno.h>
43
 
44
void debuglog();
45
 
46
#ifndef TRUE
47
#define TRUE 1
48
#define FALSE 0
49
#endif
50
 
51
#ifdef O_NOCTTY
52
#define RDWR ((O_RDWR)|(O_NOCTTY))
53
#else
54
#define RDWR O_RDWR
55
#endif
56
 
57
static int locked = FALSE;
58
static char lock[] = "/tmp/ptylock.XXXX";       /* XX is replaced by pty id */
59
static char locksrc[50] = "/tmp/expect.pid"; /* pid is replaced by real pid */
60
        /* locksrc is used as the link source, i.e., something to link from */
61
 
62
static int i_read_errno;/* place to save errno, if i_read() == -1, so it
63
                           doesn't get overwritten before we get to read it */
64
static jmp_buf env;             /* for interruptable read() */
65
static int env_valid = FALSE;   /* whether we can longjmp or not */
66
 
67
/* sigalarm_handler and i_read are here just for supporting the sanity */
68
/* checking of pty slave devices.  I have only seen this happen on BSD */
69
/* systems, but it may need to be done to the other pty implementations */
70
/* as well. */
71
 
72
/* Note that this code is virtually replicated from other code in expect */
73
/* At some point, I'll dump one, but not until I'm satisfied no other */
74
/* changes are needed */
75
 
76
/*ARGSUSED*/
77
static RETSIGTYPE
78
sigalarm_handler(n)
79
int n;          /* unused, for compatibility with STDC */
80
{
81
#ifdef REARM_SIG
82
        signal(SIGALRM,sigalarm_handler);
83
#endif
84
 
85
        /* check env_valid first to protect us from the alarm occurring */
86
        /* in the window between i_read and alarm(0) */
87
        if (env_valid) longjmp(env,1);
88
}
89
 
90
/* interruptable read */
91
static int
92
i_read(fd,buffer,length,timeout)
93
int fd;
94
char *buffer;
95
int length;
96
int timeout;
97
{
98
        int cc = -2;
99
 
100
        /* since setjmp insists on returning 1 upon longjmp(,0), */
101
        /* longjmp(,2) instead. */
102
 
103
        /* restart read if setjmp returns 0 (first time) or 2. */
104
        /* abort if setjmp returns 1. */
105
 
106
        alarm(timeout);
107
 
108
        if (1 != setjmp(env)) {
109
                env_valid = TRUE;
110
                cc = read(fd,buffer,length);
111
        }
112
        env_valid = FALSE;
113
        i_read_errno = errno;   /* errno can be overwritten by the */
114
                                /* time we return */
115
        alarm(0);
116
        return(cc);
117
}
118
 
119
static RETSIGTYPE (*oldAlarmHandler)();
120
static RETSIGTYPE (*oldHupHandler)();
121
static time_t current_time;     /* time when testing began */
122
 
123
/* if TRUE, begin testing, else end testing */
124
/* returns -1 for failure, 0 for success */
125
int
126
exp_pty_test_start()
127
{
128
        int lfd;        /* locksrc file descriptor */
129
 
130
        oldAlarmHandler = signal(SIGALRM,sigalarm_handler);
131
#ifndef O_NOCTTY
132
        /* Ignore hangup signals generated by pty testing */
133
        /* when running in background with no control tty. */
134
        /* Very few systems don't define O_NOCTTY.  Only one */
135
        /* I know of is Next. */
136
        oldAlarmHandler = signal(SIGHUP,SIG_IGN);
137
#endif
138
 
139
        time(&current_time);
140
 
141
        /* recreate locksrc to prevent locks from 'looking old', so */
142
        /* that they are not deleted (later on in this code) */
143
        sprintf(locksrc,"/tmp/expect.%d",getpid());
144
        (void) unlink(locksrc);
145
        if (-1 == (lfd = creat(locksrc,0777))) {
146
                static char buf[256];
147
                exp_pty_error = buf;
148
                sprintf(exp_pty_error,"can't create %s, errno = %d\n",locksrc, errno);
149
                return(-1);
150
        }
151
        close(lfd);
152
        return 0;
153
}
154
 
155
void
156
exp_pty_test_end()
157
{
158
        signal(SIGALRM,oldAlarmHandler);
159
#ifndef O_NOCTTY
160
        signal(SIGALRM,oldHupHandler);
161
#endif
162
        (void) unlink(locksrc);
163
}
164
 
165
/* returns non-negative if successful */
166
int
167
exp_pty_test(master_name,slave_name,bank,num)
168
char *master_name;
169
char *slave_name;
170
int bank;
171
char *num;      /* string representation of number */
172
{
173
        int master, slave;
174
        int cc;
175
        char c;
176
 
177
        /* make a lock file to prevent others (for now only */
178
        /* expects) from allocating pty while we are playing */
179
        /* with it.  This allows us to rigorously test the */
180
        /* pty is usable. */
181
        if (exp_pty_lock(bank,num) == 0) {
182
                debuglog("pty master (%s) is locked...skipping\r\n",master_name);
183
                return(-1);
184
        }
185
        /* verify no one else is using slave by attempting */
186
        /* to read eof from master side */
187
        if (0 > (master = open(master_name,RDWR))) return(-1);
188
 
189
#ifdef __QNX__
190
 
191
        /* QNX ptys don't have a lot of the same properties such as
192
           read 0 at EOF, etc */
193
        /* if 1 should pacify C compiler without using nested ifdefs */
194
        if (1) return master;
195
#endif
196
 
197
#ifdef HAVE_PTYTRAP
198
        if (access(slave_name, R_OK|W_OK) != 0) {
199
                debuglog("could not open slave for pty master (%s)...skipping\r\n",
200
                        master_name);
201
                (void) close(master);
202
                return -1;
203
        }
204
        return(master);
205
#else
206
        if (0 > (slave = open(slave_name,RDWR))) {
207
                (void) close(master);
208
                return -1;
209
        }
210
        (void) close(slave);
211
        cc = i_read(master,&c,1,10);
212
        (void) close(master);
213
        if (!(cc == 0 || cc == -1)) {
214
                debuglog("%s slave open, skipping\r\n",slave_name);
215
                locked = FALSE; /* leave lock file around so Expect's avoid */
216
                                /* retrying this pty for near future */
217
                return -1;
218
        }
219
 
220
        /* verify no one else is using master by attempting */
221
        /* to read eof from slave side */
222
        if (0 > (master = open(master_name,RDWR))) return(-1);
223
        if (0 > (slave = open(slave_name,RDWR))) {
224
                (void) close(master);
225
                return -1;
226
        }
227
        (void) close(master);
228
        cc = i_read(slave,&c,1,10);
229
        (void) close(slave);
230
        if (!(cc == 0 || cc == -1)) {
231
                debuglog("%s master open, skipping\r\n",master_name);
232
                return -1;
233
        }
234
 
235
        /* seems ok, let's use it */
236
        debuglog("using master pty %s\n",master_name);
237
        return(open(master_name,RDWR));
238
#endif
239
}
240
 
241
void
242
exp_pty_unlock()
243
{
244
        if (locked) {
245
                (void) unlink(lock);
246
                locked = FALSE;
247
        }
248
}
249
 
250
/* returns 1 if successfully locked, 0 otherwise */
251
int
252
exp_pty_lock(bank,num)
253
int bank;
254
char *num;      /* string representation of number */
255
{
256
        struct stat statbuf;
257
 
258
        if (locked) {
259
                unlink(lock);
260
                locked = FALSE;
261
        }
262
 
263
        sprintf(lock,"/tmp/ptylock.%c%s",bank,num);
264
 
265
        if ((0 == stat(lock,&statbuf)) &&
266
            (statbuf.st_mtime+3600 < current_time)) {
267
                (void) unlink(lock);
268
        }
269
 
270
        if (-1 == (link(locksrc,lock))) locked = FALSE;
271
        else locked = TRUE;
272
 
273
        return locked;
274
}
275
 

powered by: WebSVN 2.1.0

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