1: #include <X/mit-copyright.h> 2: /* $Header: XOpenDisplay.c,v 10.8 86/02/01 15:37:30 tony Rel $ */ 3: /* Copyright Massachusetts Institute of Technology 1985 */ 4: 5: #include "XlibInternal.h" 6: #include <sys/socket.h> 7: #include <strings.h> 8: #include <sys/un.h> 9: 10: /* 11: * Connects to a server, creates a Display object and returns a pointer to 12: * the newly created Display back to the caller. 13: */ 14: Display *XOpenDisplay (display) 15: register char *display; 16: { 17: register Display *dpy; /* New Display object being created. */ 18: char displaybuf[256]; /* Display string buffer. */ 19: register char *displayptr; /* Display string buffer pointer. */ 20: char buf[3]; /* place to form display string */ 21: struct sockaddr_in inaddr; /* INET socket address. */ 22: struct sockaddr_un unaddr; /* UNIX socket address. */ 23: struct sockaddr *addr; /* address to connect to */ 24: int addrlen; /* length of address */ 25: int dispnum; /* display number. */ 26: int indian; /* to determine which indian. */ 27: struct hostent *host_ptr; 28: #ifdef DNETCONN 29: char objname[20]; /* Object name buffer */ 30: int dnet = 0; /* flag to indicate DECnet connect */ 31: #endif 32: 33: register XReq *req; /* XReq request packet pointer. */ 34: XRep rep; /* XRep reply packet. */ 35: 36: /* External declarations. */ 37: extern char *getenv(); 38: extern char *malloc(); 39: extern struct hostent *gethostbyname(); 40: 41: /* 42: * Extract the host name and display number from the display 43: * specifier string. The display specifier string is supplied 44: * as an argument to this routine. If it is NULL or a pointer 45: * to NULL 46: */ 47: if (display == NULL || *display == '\0') { 48: char *disp; 49: /* No display given check the DISPLAY environment variable. */ 50: if ((disp = getenv("DISPLAY")) == NULL) { 51: /* Oops! No DISPLAY environment variable - error. */ 52: return(NULL); 53: } 54: strncpy(displaybuf, disp, sizeof(displaybuf)); 55: } 56: else { 57: /* Display is non-NULL, copy it into the display buffer. */ 58: strncpy(displaybuf, display, sizeof(displaybuf)); 59: } 60: /* 61: * Find the ':' seperator and cut out the hostname and the 62: * display number. 63: * NOTE - if DECnet is to be used, the display name is formated 64: * as "host::number" 65: */ 66: if ((displayptr = index(displaybuf,':')) == NULL) return (NULL); 67: #ifdef DNETCONN 68: if (*(displayptr + 1) == ':') { 69: dnet++; 70: *(displayptr++) = '\0'; 71: } 72: #endif 73: *(displayptr++) = '\0'; 74: 75: /* displaybuf now contains only a null-terminated host name; 76: * displayptr points to the display number */ 77: 78: /* If the display number is missing there is an error. 79: * Otherwise, convert string to an integer we can use */ 80: if (*displayptr == '\0') return(NULL); 81: dispnum = atoi(displayptr); 82: 83: if (strcmp("unix", displaybuf) == 0) { 84: /* Connect locally using Unix domain. */ 85: unaddr.sun_family = AF_UNIX; 86: strcpy(unaddr.sun_path, X_UNIX_PATH); 87: strcat(unaddr.sun_path, displayptr); 88: addr = (struct sockaddr *) &unaddr; 89: addrlen = strlen(unaddr.sun_path) + 2; 90: } else { 91: #ifdef DNETCONN 92: if (!dnet) { 93: #endif 94: /* If the hostname is missing default to the local host. */ 95: if (displaybuf[0] == '\0') 96: gethostname (displaybuf, sizeof (displaybuf)); 97: /* Get the statistics on the specified host. */ 98: if ((host_ptr = gethostbyname(displaybuf)) == NULL) { 99: /* No such host! */ 100: errno = EINVAL; 101: return(NULL); 102: } 103: /* Check the address type to see if it is an internet host. */ 104: if (host_ptr->h_addrtype != AF_INET) { 105: /* Not an Internet host! */ 106: errno = EPROTOTYPE; 107: return(NULL); 108: } 109: 110: /* Set up the socket data. */ 111: inaddr.sin_family = AF_INET; 112: inaddr.sin_port = dispnum; 113: indian = 1; 114: if (*(char *) &indian) 115: inaddr.sin_port += X_TCP_LI_PORT; 116: else 117: inaddr.sin_port += X_TCP_BI_PORT; 118: inaddr.sin_port = htons(inaddr.sin_port); 119: bcopy((char *)host_ptr->h_addr, &inaddr.sin_addr, sizeof(inaddr.sin_addr)); 120: addr = (struct sockaddr *) &inaddr; 121: addrlen = sizeof (struct sockaddr_in); 122: #ifdef DNETCONN 123: } else { 124: /* If the nodename is missing default to the local node. */ 125: if (displaybuf[0] == '\0') 126: strcpy (displaybuf, "0"); 127: /* build the target object name. */ 128: sprintf (objname, "X%d", dispnum); 129: } 130: #endif 131: } 132: 133: /* Malloc the new Display. */ 134: if ((dpy = (Display *)malloc(sizeof(Display))) == NULL) { 135: /* Malloc call failed! */ 136: errno = ENOMEM; 137: return(NULL); 138: } 139: 140: dpy->height = dpy->width = 0; 141: /* If DisplayWidth or DisplayWidth is subsequently called, 142: these will be replaced by "real" values. */ 143: 144: /* Open the network socket. */ 145: #ifdef DNETCONN 146: if (!dnet) { 147: #endif 148: if ((dpy->fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { 149: /* Socket call failed! */ 150: /* errno set by system call. */ 151: free (dpy); 152: return(NULL); 153: } 154: 155: /* Open the connection to the specified X server. */ 156: if (connect(dpy->fd, addr, addrlen) == -1) { 157: /* Connection call failed! */ 158: /* errno set by system call. */ 159: close (dpy->fd); 160: free (dpy); 161: return(NULL); 162: } 163: #ifdef DNETCONN 164: } else { 165: if ((dpy->fd = dnet_conn(displaybuf, objname, SOCK_STREAM, 0, 0, 0, 0)) < 0) { 166: /* connect failed! */ 167: /* errno set by dnet_conn. */ 168: free (dpy); 169: return(NULL); 170: } 171: } 172: #endif 173: 174: /* Salt away the host:display string for later use */ 175: buf[0] = ':'; 176: buf[2] = '\0'; 177: buf[1] = '0' + dispnum; 178: strcat(displaybuf, buf); 179: if ((dpy->displayname = malloc(strlen(displaybuf) + 1)) == NULL) { 180: close (dpy->fd); 181: free (dpy); 182: errno = ENOMEM; 183: return(NULL); 184: } 185: strcpy (dpy->displayname, displaybuf); 186: 187: /* Set up the output buffers. */ 188: if ((dpy->bufptr = dpy->buffer = malloc(BUFSIZE)) == NULL) { 189: /* Malloc call failed! */ 190: close (dpy->fd); 191: free (dpy); 192: errno = ENOMEM; 193: return(NULL); 194: } 195: dpy->bufmax = dpy->buffer + BUFSIZE; 196: 197: /* Set up the input event queue and input event queue parameters. */ 198: dpy->head = dpy->tail = NULL; 199: dpy->qlen = 0; 200: /* Initialize MouseMoved event squishing. */ 201: dpy->squish = 1; 202: 203: _XlibCurrentDisplay = dpy; 204: 205: /* Send an X_SetUp request to the server. */ 206: GetReq(X_SetUp, 0); 207: 208: /* Send X_MakePixmap requests to get black and white 209: * constant tile Pixmaps */ 210: GetReq(X_MakePixmap, 0); 211: req->param.l[0] = 0; /* no bitmap */ 212: req->param.u[2] = BlackPixel; 213: GetReq(X_MakePixmap, 0); 214: req->param.l[0] = 0; 215: req->param.u[2] = WhitePixel; 216: 217: /* The following is needed to synchronize properly with errors, 218: * since three requests are outstanding and no replies have 219: * yet been read 220: */ 221: dpy->request = 1; 222: 223: /* Get reply to X_SetUp */ 224: if (!_XReply(dpy, &rep)) { 225: /* There was an error in retrieving the reply. */ 226: close (dpy->fd); 227: free (dpy->buffer); 228: free (dpy); 229: return(NULL); 230: } 231: 232: /* Set the Display data returned by the X_SetUp call. */ 233: dpy->root = rep.param.l[0]; /* Root window id. */ 234: dpy->vnumber = rep.param.s[2]; /* X protocol version number. */ 235: dpy->dtype = rep.param.s[3]; /* Server's display type. */ 236: dpy->dplanes = rep.param.s[4]; /* Number of display bit planes. */ 237: dpy->dcells = rep.param.u[5]; /* Number of display color map cell. */ 238: 239: /* Get reply to MakePixmap (black) */ 240: dpy->request++; 241: if (!_XReply (dpy, &rep)) { 242: close (dpy->fd); 243: free (dpy->buffer); 244: free (dpy); 245: return (NULL); 246: } 247: dpy->black = rep.param.l[0]; 248: 249: /* Get reply to MakePixmap (white) */ 250: dpy->request++; 251: if (!_XReply (dpy, &rep)) { 252: close (dpy->fd); 253: free (dpy->buffer); 254: free (dpy); 255: return (NULL); 256: } 257: dpy->white = rep.param.l[0]; 258: 259: return(dpy); 260: }