00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "defs.h"
00022 #include "ptutil.h"
00023
00024 #if defined(SOLARIS)
00025 #define NEED_STREAM_SETUP
00026 #endif
00027
00028 #if defined(FREEBSD)
00029 #define NEED_TIOCSCTTY
00030 #endif
00031
00032 #ifndef _XOPEN_UNIX
00033 #define MASTER_NAME_SEARCH
00034 #endif
00035
00036 #ifdef _XOPEN_UNIX
00037 #include <stropts.h>
00038 #endif
00039 #ifdef NEED_TIOCSCTTY
00040 #include <sys/ttycom.h>
00041 #endif
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #if defined(MASTER_NAME_SEARCH)
00054 #define PTY_RANGE \
00055 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
00056 #define PTY_PROTO "/dev/ptyXY"
00057 #define PTY_X 8
00058 #define PTY_Y 9
00059 #define PTY_MS 5
00060 #endif
00061
00062 static bool find_and_open_master(PTINFO *p)
00063 {
00064 #if defined(_XOPEN_UNIX)
00065 #if _XOPEN_VERSION >= 600
00066 p->pt_name_m[0] = '\0';
00067 ec_neg1( p->pt_fd_m = posix_openpt(O_RDWR | O_NOCTTY) )
00068 #else
00069 strcpy(p->pt_name_m, "/dev/ptmx");
00070 ec_neg1( p->pt_fd_m = open(p->pt_name_m, O_RDWR) )
00071 #endif
00072 #elif defined(MASTER_NAME_SEARCH)
00073 int i, j;
00074 char proto[] = PTY_PROTO;
00075
00076 if (p->pt_fd_m != -1) {
00077 (void)close(p->pt_fd_m);
00078 p->pt_fd_m = -1;
00079 }
00080 for (i = 0; i < sizeof(PTY_RANGE) - 1; i++) {
00081 proto[PTY_X] = PTY_RANGE[i];
00082 proto[PTY_Y] = PTY_RANGE[0];
00083 if (access(proto, F_OK) == -1) {
00084 if (errno == ENOENT)
00085 continue;
00086 EC_FAIL
00087 }
00088 for (j = 0; j < sizeof(PTY_RANGE) - 1; j++) {
00089 proto[PTY_Y] = PTY_RANGE[j];
00090 if ((p->pt_fd_m = open(proto, O_RDWR)) == -1) {
00091 if (errno == ENOENT)
00092 break;
00093 }
00094 else {
00095 strcpy(p->pt_name_m, proto);
00096 break;
00097 }
00098 }
00099 if (p->pt_fd_m != -1)
00100 break;
00101 }
00102 if (p->pt_fd_m == -1) {
00103 errno = EAGAIN;
00104 EC_FAIL
00105 }
00106 #else
00107 errno = ENOSYS;
00108 EC_FAIL
00109 #endif
00110 return true;
00111
00112 EC_CLEANUP_BGN
00113 return false;
00114 EC_CLEANUP_END
00115 }
00116
00117 PTINFO *pt_open_master(void)
00118 {
00119 PTINFO *p = NULL;
00120 #ifdef _XOPEN_UNIX
00121 char *s;
00122 #endif
00123
00124 ec_null( p = calloc(1, sizeof(PTINFO)) )
00125 p->pt_fd_m = -1;
00126 p->pt_fd_s = -1;
00127 ec_false( find_and_open_master(p) )
00128 #ifdef _XOPEN_UNIX
00129 ec_neg1( grantpt(p->pt_fd_m) )
00130 ec_neg1( unlockpt(p->pt_fd_m) )
00131 ec_null( s = ptsname(p->pt_fd_m) )
00132 if (strlen(s) >= PT_MAX_NAME) {
00133 errno = ENAMETOOLONG;
00134 EC_FAIL
00135 }
00136 strcpy(p->pt_name_s, s);
00137 #elif defined(MASTER_NAME_SEARCH)
00138 strcpy(p->pt_name_s, p->pt_name_m);
00139 p->pt_name_s[PTY_MS] = 't';
00140 #else
00141 errno = ENOSYS;
00142 EC_FAIL
00143 #endif
00144 return p;
00145
00146 EC_CLEANUP_BGN
00147 if (p != NULL) {
00148 (void)close(p->pt_fd_m);
00149 (void)close(p->pt_fd_s);
00150 free(p);
00151 }
00152 return NULL;
00153 EC_CLEANUP_END
00154 }
00155
00156
00157
00158
00159
00160
00161 bool pt_open_slave(PTINFO *p)
00162 {
00163 ec_neg1( setsid() )
00164 if (p->pt_fd_s != -1)
00165 ec_neg1( close(p->pt_fd_s) )
00166 ec_neg1( p->pt_fd_s = open(p->pt_name_s, O_RDWR) )
00167 #if defined(NEED_TIOCSCTTY)
00168 ec_neg1( ioctl(p->pt_fd_s, TIOCSCTTY, 0) )
00169 #endif
00170 #if defined(NEED_STREAM_SETUP)
00171 ec_neg1( ioctl(p->pt_fd_s, I_PUSH, "ptem") )
00172 ec_neg1( ioctl(p->pt_fd_s, I_PUSH, "ldterm") )
00173 #endif
00174
00175
00176
00177
00178 if (fchmod(p->pt_fd_s, PERM_FILE) == -1 && errno != EPERM)
00179 EC_FAIL
00180 return true;
00181
00182 EC_CLEANUP_BGN
00183 return false;
00184 EC_CLEANUP_END
00185 }
00186
00187 bool pt_wait_master(PTINFO *p)
00188 {
00189 fd_set fd_set_write;
00190
00191 FD_ZERO(&fd_set_write);
00192 FD_SET(PT_GET_MASTER_FD(p), &fd_set_write);
00193 ec_neg1( select(PT_GET_MASTER_FD(p) + 1, NULL, &fd_set_write, NULL,
00194 NULL) )
00195 return true;
00196
00197 EC_CLEANUP_BGN
00198 return false;
00199 EC_CLEANUP_END
00200 }
00201
00202 bool pt_close_master(PTINFO *p)
00203 {
00204 ec_neg1( close(p->pt_fd_m) )
00205 free(p);
00206 return true;
00207
00208 EC_CLEANUP_BGN
00209 return false;
00210 EC_CLEANUP_END
00211 }
00212
00213 bool pt_close_slave(PTINFO *p)
00214 {
00215 (void)close(p->pt_fd_s);
00216 free(p);
00217 return true;
00218 }
00219