#ifndef lint static char sccsid[] = "@(#)metanew.c 1.1 94/10/31 Copyr 1985-9 Sun Micro"; #endif /* * Copyright (c) 1985, 1986, 1987, 1988, 1989 by Sun Microsystems, Inc. * Permission to use, copy, modify, and distribute this software for any * purpose and without fee is hereby granted, provided that the above * copyright notice appear in all copies and that both that copyright * notice and this permission notice are retained, and that the name * of Sun Microsystems, Inc., not be used in advertising or publicity * pertaining to this software without specific, written prior permission. * Sun Microsystems, Inc., makes no representations about the suitability * of this software or the interface defined in this software for any * purpose. It is provided "as is" without express or implied warranty. */ /* * CGI viewsurface initialization & termination functions */ /* open_vws _cgi_new_vwsurf_name _cgi_get_dev _cgi_get_device_vwsurf _cgi_initialize_gp1 _cgi_chkdev _cgi_getfb _cgi_shared_screen _cgi_color_init _cgi_get_window_vwsurf chkscreen blanket_a_window open_gfx_window fbtype_colorflag_check _cgi_fb_colorflag_mismatch open_vws_special close_vws _cgi_free_name _cgi_bump_vws _cgi_bump_all_vws _cgi_context */ #include "cgipriv.h" #include #include #include #include #include #include #include #include #include Gstate _cgi_state; /* CGI global state */ View_surface *_cgi_view_surfaces[MAXVWS]; /* view surface information */ View_surface *_cgi_vws; /* current view surface */ int _cgi_vwsurf_count; /* num. of view surfaces ever opened */ int _cgi_gfxenvfd = -1; /* to be fd of WINDOW_GFX envir. var. */ Outatt *_cgi_att; /* structure containing current attributes */ int _cgi_retained; /* Bears user request to SIGWINCH handler */ int _cgi_criticalcnt; /* critical region protection */ Notify_value _cgi_sigchild(); extern char **environ; extern int errno; extern char *getenv(); int (*win_errorhandler()) (); extern char *strcpy(), *strncpy(); extern char *rindex(), *sprintf(); Outatt *_cgi_alloc_output_att(); int _cgi_shared_screen(); int _cgi_shared_screen_state; static char *srchptr; static struct screen *scrptr; static int foundscreen; typedef enum { ANY = PIXWINDD, MONO = BWPIXWINDD, COLOR = CGPIXWINDD, } colorflag_enum; /****************************************************************************/ /* */ /* FUNCTION: open_vws */ /* */ /* Opens and activiates a view surface. */ /* Pertainent view surface information is stored */ /* and the view surface is added to the list of view surfaces.*/ /****************************************************************************/ Cerror open_vws(name, devdd) Cint *name; /* internal name */ Cvwsurf *devdd; /* view surface descriptor */ { register View_surface *cur_vws = NULL; int err = NO_ERROR; int new_name; START_CRITICAL(); if (_cgi_state.cgipw_mode) /* opened via open_pw_cgi? */ err = ENOTCCPW; /* Function not compatible with CGIPW mode */ else { err = _cgi_check_state_5(); if (!err) { new_name = _cgi_new_vwsurf_name(); if (new_name < 0) err = EMAXVSOP; /* Max no. of view surfaces already open. */ else { /* Don't malloc unless everything else is OK */ cur_vws = (View_surface *) calloc(1, sizeof(View_surface)); if (cur_vws == (View_surface *) NULL) err = EMEMSPAC; } } } if (!err) { cur_vws->att = _cgi_att = _cgi_state.common_att; _cgi_vws = _cgi_view_surfaces[new_name] = cur_vws; _cgi_retained = (devdd->retained); err = _cgi_get_dev(devdd); /* get actual device */ (void) fcntl(cur_vws->sunview.windowfd, F_SETFL, FASYNC | FNDELAY); } if (!err) { Cos incoming_cgi_state = _cgi_state.state; _cgi_state.state = VSAC; cur_vws->active = 1; /* * if first view surface opened, set defaults, initialize input stats, * and clear screen. Hard_reset does _cgi_windowset via vdc_extent. */ if (incoming_cgi_state == CGOP) (void) hard_reset(); else (void) _cgi_windowset(cur_vws); *name = new_name; } else { if (new_name >= 0) { /* Make surface as if it didn't exist */ _cgi_free_name(new_name); } _cgi_vws = (View_surface *) NULL; } END_CRITICAL(); return (_cgi_errhand(err)); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_new_vwsurf_name */ /* */ /* Returns available view surface "name" (or -1 failure). */ /* A "name" is an index into the _cgi_view_surfaces array. */ /* see also _cgi_free_name, which frees up the "name". */ /****************************************************************************/ int _cgi_new_vwsurf_name() { int i, index = -1; if (_cgi_vwsurf_count < MAXVWS) /* OK to give out MAXVWS-1 */ index = _cgi_vwsurf_count++; /* Now count may be MAXVWS. */ else { for (i = 0; i < MAXVWS; i++) { if (!_cgi_view_surfaces[i]) /* Reuse this closed vws */ { index = i; break; } } } return (index); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_get_dev */ /* */ /* sets the current device */ /****************************************************************************/ static int _cgi_get_dev(devdd) Cvwsurf *devdd; /* view surface descriptor */ { register View_surface *cur_vws = _cgi_vws; int err = NO_ERROR; int gp_flag; /* returned gp1 existence proof */ int dd = devdd->dd; /* static int bcolor = 0; */ /* set device internals */ cur_vws->sunview.pw = (Pixwin *) NULL; switch (devdd->dd) { case BW1DD: { static char bwonedev[] = "/dev/bwone?"; char devstring[sizeof(bwonedev)]; (void) strcpy(devstring, bwonedev); err = _cgi_get_device_vwsurf(devstring, devdd, FBTYPE_SUN1BW, &gp_flag); cur_vws->sunview.depth = 1; break; } case BW2DD: { static char bwtwodev[] = "/dev/bwtwo?"; char devstring[sizeof(bwtwodev)]; (void) strcpy(devstring, bwtwodev); err = _cgi_get_device_vwsurf(devstring, devdd, FBTYPE_SUN2BW, &gp_flag); cur_vws->sunview.depth = 1; break; } case CG1DD: { static char cgonedev[] = "/dev/cgone?"; char devstring[sizeof(cgonedev)]; (void) strcpy(devstring, cgonedev); err = _cgi_get_device_vwsurf(devstring, devdd, FBTYPE_SUN1COLOR, &gp_flag); cur_vws->sunview.depth = 8; break; } case CG2DD: { static char cgtwodev[] = "/dev/cgtwo?"; char devstring[sizeof(cgtwodev)]; (void) strcpy(devstring, cgtwodev); err = _cgi_get_device_vwsurf(devstring, devdd, FBTYPE_SUN2COLOR, &gp_flag); cur_vws->sunview.depth = 8; break; } case CG3DD: { static char cgthreedev[] = "/dev/cgthree?"; char devstring[sizeof(cgthreedev)]; (void) strcpy(devstring, cgthreedev); err = _cgi_get_device_vwsurf(devstring, devdd, FBTYPE_SUN3COLOR, &gp_flag); cur_vws->sunview.depth = 8; break; } case CG4DD: { static char cgfourdev[] = "/dev/cgfour?"; char devstring[sizeof(cgfourdev)]; (void) strcpy(devstring, cgfourdev); err = _cgi_get_device_vwsurf(devstring, devdd, FBTYPE_SUN4COLOR, &gp_flag); cur_vws->sunview.depth = 8; break; } #ifndef NO_CG6 case CG6DD: { static char cgsixdev[] = "/dev/cgsix?"; char devstring[sizeof(cgsixdev)]; (void) strcpy(devstring, cgsixdev); err = _cgi_get_device_vwsurf(devstring, devdd, FBTYPE_SUNFAST_COLOR, &gp_flag); cur_vws->sunview.depth = 8; break; } /* This define is used later in this file */ #define FBTYPE_IS_COLOR(fbtype) ( ((fbtype) == FBTYPE_SUN1COLOR) \ || ((fbtype) == FBTYPE_SUN2COLOR) \ || ((fbtype) == FBTYPE_SUN3COLOR) \ || ((fbtype) == FBTYPE_SUN4COLOR) \ || ((fbtype) == FBTYPE_SUNFAST_COLOR) \ || ((fbtype) == FBTYPE_SUN2GP) ) #else NO_CG6 /* This define is used later in this file */ #define FBTYPE_IS_COLOR(fbtype) ( ((fbtype) == FBTYPE_SUN1COLOR) \ || ((fbtype) == FBTYPE_SUN2COLOR) \ || ((fbtype) == FBTYPE_SUN3COLOR) \ || ((fbtype) == FBTYPE_SUN4COLOR) \ || ((fbtype) == FBTYPE_SUN2GP) ) #endif NO_CG6 case GP1DD: { static char gponedev[] = "/dev/gpone?@"; /* e.g., /dev/gpone0a */ char devstring[sizeof(gponedev)]; (void) strcpy(devstring, gponedev); err = _cgi_get_device_vwsurf(devstring, devdd, FBTYPE_SUN2GP, &gp_flag); cur_vws->sunview.depth = 8; break; } case BWPIXWINDD: { colorflag_enum colorflg = MONO; err = _cgi_get_window_vwsurf(&cur_vws->sunview.windowfd, &cur_vws->sunview.tool_pid, &colorflg, devdd, &gp_flag); if (colorflg == MONO) cur_vws->sunview.depth = 1; break; } case CGPIXWINDD: { colorflag_enum colorflg = COLOR; cur_vws->sunview.depth = 8; err = _cgi_get_window_vwsurf(&cur_vws->sunview.windowfd, &cur_vws->sunview.tool_pid, &colorflg, devdd, &gp_flag); if (colorflg == COLOR) cur_vws->sunview.depth = 8; break; } default: { if ((devdd->windowname != '\0') || (devdd->screenname != '\0')) { dd = PIXWINDD; goto case_PIXWINDD; } else err = ENOWSTYP; break; } case PIXWINDD: case_PIXWINDD: { colorflag_enum colorflg = ANY; err = _cgi_get_window_vwsurf(&cur_vws->sunview.windowfd, &cur_vws->sunview.tool_pid, &colorflg, devdd, &gp_flag); if (colorflg == MONO) cur_vws->sunview.depth = 1; else cur_vws->sunview.depth = 8; break; } } if (!err) { if (cur_vws->sunview.pw) { pw_writebackground(cur_vws->sunview.pw, 0, 0, cur_vws->vport.r_width, cur_vws->vport.r_height, PIX_COLOR(0) | PIX_SRC); } else err = ENOWSTYP; } /* * Duplicate cases of gp init from _cgi_get_device_vwsurf and * _cgi_get_window_vwsurf were consolidated here. wcl860919 */ if (!err) { if (gp_flag) { /* wds: better than no test at all */ if (_cgi_initialize_gp1(cur_vws) != 0) cur_vws->sunview.gp_att = (Gp1_attr *) NULL; } cur_vws->device = dd; } return (err); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_get_device_vwsurf */ /* */ /* Opens a view surface on a "raw device". */ /* Tries (in order) user's screenname (if any), */ /* /dev/fb, devstring (iterated over possible values). */ /* Will not run on a raw device already running windows. */ /* Should allow some value of fbtype to mean "use devstring". */ /****************************************************************************/ static int _cgi_get_device_vwsurf(devstring, vsurfp, fbtype, gpflg) char *devstring; Cvwsurf *vsurfp; int fbtype; int *gpflg; { struct screen screen; int oldsigmask; int err = NO_ERROR; static char default_fb_string[] = "/dev/fb"; static char none_string[] = "NONE"; win_initscreenfromargv(&screen, (char **) NULL); /* get default screen * struct */ if (*vsurfp->screenname != '\0') { if ((_cgi_chkdev(vsurfp->screenname, fbtype)) >= 0) (void) strncpy(screen.scr_fbname, vsurfp->screenname, SCR_NAMESIZE); else err = ENOWSTYP; } else { if ((_cgi_chkdev(default_fb_string, fbtype)) >= 0) (void) strncpy(screen.scr_fbname, default_fb_string, SCR_NAMESIZE); else if ((_cgi_getfb(devstring, fbtype)) >= 0) (void) strncpy(screen.scr_fbname, devstring, SCR_NAMESIZE); else err = ENOWSTYP; } if (getenv("WINDOW_ME")) { (void) strncpy(screen.scr_kbdname, none_string, SCR_NAMESIZE); /* Related to core's _core_setadjacent for moving mouse among screens */ _cgi_vws->sunview.windowfd = 99; /* Need to fool test in * _cgi_new_window_init? */ oldsigmask = sigblock((1 << (SIGWINCH - 1)) | (1 << (SIGCHLD - 1))); if ((_cgi_vws->sunview.windowfd = win_screennew(&screen)) < 0) err = ENOWSTYP; else win_screenget(_cgi_vws->sunview.windowfd, &screen); (void) sigsetmask(oldsigmask); } else /* Really shouldn't be "else": should always * test the device? */ { /* Refuse to use a device that is already running windows. */ { int (*olderr) (); _cgi_vws->sunview.windowfd = 99; /* Need to fool test in * _cgi_new_window_init? */ _cgi_shared_screen_state = 0; (void) strncpy(screen.scr_kbdname, none_string, SCR_NAMESIZE); /*** (void) strncpy(screen.scr_msname, none_string, SCR_NAMESIZE); ***/ oldsigmask = sigblock((1 << (SIGWINCH - 1)) | (1 << (SIGCHLD - 1))); olderr = win_errorhandler(_cgi_shared_screen); /* * Apparently, we catch errors so we can determine if window was * shared, and to avoid "an error message is displayed to indicate * ... problem" */ if ((_cgi_vws->sunview.windowfd = win_screennew(&screen)) >= 0) /* Was < 0 */ { if (_cgi_shared_screen_state) err = ENOWSTYP; else { /* screen ok: not shared */ /* * if _cgi_vws->sunview.windowfd above was < 0, the fd is * no good for the win_screenget below */ win_screenget(_cgi_vws->sunview.windowfd, &screen); err = NO_ERROR; } } (void) win_errorhandler(olderr); (void) sigsetmask(oldsigmask); } } if (!err) { /* * _cgi_new_window_init sets _cgi_vws->sunview.pw from * _cgi_vws->sunview.windowfd */ err = _cgi_new_window_init(_cgi_vws); } if (!err) { if (FBTYPE_IS_COLOR(fbtype)) _cgi_color_init(vsurfp); if (fbtype == FBTYPE_SUN2GP) *gpflg = 1; else *gpflg = 0; } return (err); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_initialize_gp1 */ /* */ /* sets up Graphics Processor structures for CGI use */ /* wds Pulled out of _cgi_get_device_vwsurf_gp1dd, 850611 */ /* Returns 0 if it succeeds, nonzero if fails. */ /****************************************************************************/ int _cgi_initialize_gp1(vws) View_surface *vws; /* view surface for output */ { int planes; if ((vws == (View_surface *) NULL) || vws->sunview.pw == (Pixwin *) NULL || vws->sunview.gp_att == (Gp1_attr *) NULL || _cgi_gp1_attr_init(vws->sunview.pw, &vws->sunview.gp_att) < 0) return 1; /* Note that the return code is not checked. */ _cgi_update_gp1_xform(vws); pw_getattributes(vws->sunview.pw, &planes); _cgi_gp1_set_pixplanes(planes, vws->sunview.gp_att); if (ioctl(((struct gp1pr *) (vws->sunview.pw->pw_pixrect->pr_data))->ioctl_fd, GP1IO_GET_RESTART_COUNT, (char *) &_cgi_state.gp1resetcnt)) { _cgi_gp1_attr_close(vws->sunview.pw, &vws->sunview.gp_att); return 1; } else { vws->sunview.gp_att->resetcnt = _cgi_state.gp1resetcnt; /* wds 851009: Maybe _cgi_gp1_snd_attr should be called? */ /* I think that we just delay sending the attrs until first primitive */ return 0; } } /****************************************************************************/ /* */ /* FUNCTION: _cgi_chkdev */ /* */ /* Checks the device dev's frame buffer */ /* After checking its type against the one input. */ /* Return the fd for the device dev's frame buffer */ /* After checking its type against the one input. */ /****************************************************************************/ static int _cgi_chkdev(dev, type) char *dev; int type; { int fbfd, fbtype; if ((fbfd = open(dev, O_RDWR, 0)) < 0) return (-1); if ((fbtype = pr_getfbtype_from_fd(fbfd)) == -1 || (fbtype != type)) { (void) close(fbfd); return (-1); } (void) close(fbfd); return (1); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_getfb */ /* */ /* Return the fd for the device with correct frame buffer type */ /* Possible device names are formed from devstring: */ /* Rightmost ? may be replaced by any digit 0-9. @ with a-d. */ /* If 1 is returned, devstring is the one that worked. */ /* -1 is returned for failure & devstring has been changed. */ /****************************************************************************/ static int _cgi_getfb(devstring, type) char *devstring; int type; { char *zero_ptr, digit, *at_ptr, letter; zero_ptr = rindex(devstring, '?'); at_ptr = rindex(devstring, '@'); /* Pointer {zero,at}_ptr either position to iterate, or NULL pointer */ digit = '0'; do { if (zero_ptr) *zero_ptr = digit; letter = 'a'; do { if (at_ptr) *at_ptr = letter; if ((_cgi_chkdev(devstring, type)) >= 0) return (1); } while ((++letter <= 'd') && at_ptr); /* Once through is enough, if (at_ptr == NULL) */ } while ((++digit <= '9') && zero_ptr); return (-1); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_shared_screen */ /* */ /* if called, the screen is shared */ /* */ /****************************************************************************/ static int _cgi_shared_screen() { if (errno == EBUSY) _cgi_shared_screen_state = EBUSY; return (0); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_color_init */ /* */ /* _cgi_color_init initializes the colormap */ /****************************************************************************/ _cgi_color_init(vsurf) Cvwsurf *vsurf; { register View_surface *vwsP = _cgi_vws; u_char red[256], green[256], blue[256]; int cmapsize; char cmsname[DEVNAMESIZE]; struct colormapseg cms; struct cms_map cmap; cmapsize = vsurf->cmapsize; if (cmapsize == 0) cmapsize = 2; /* Use monochrome by default */ if (vsurf->cmapname[0] == '\0') { /* Build unique color map segment name */ (void) sprintf(cmsname, "cmap%10D%5D", getpid(), vwsP->sunview.windowfd); cmap.cm_red = red; cmap.cm_green = green; cmap.cm_blue = blue; cms.cms_size = CMS_RGBSIZE; cms_rgbsetup(cmap.cm_red, cmap.cm_green, cmap.cm_blue); cmapsize = cms.cms_size; pw_setcmsname(vwsP->sunview.pw, cmsname); pw_putcolormap(vwsP->sunview.pw, 0, cmapsize, cmap.cm_red, cmap.cm_green, cmap.cm_blue); if (vwsP->sunview.orig_pw != vwsP->sunview.pw) { pw_setcmsname(vwsP->sunview.orig_pw, cmsname); pw_putcolormap(vwsP->sunview.orig_pw, 0, cmapsize, cmap.cm_red, cmap.cm_green, cmap.cm_blue); } } else { (void) strncpy(cmsname, vsurf->cmapname, DEVNAMESIZE); /* necessary? */ if (_cgi_sharedcmap(vwsP->sunview.windowfd, cmsname, &cms, &cmap)) { pw_setcmsname(vwsP->sunview.pw, cmsname); if (vwsP->sunview.orig_pw != vwsP->sunview.pw) pw_setcmsname(vwsP->sunview.orig_pw, cmsname); } else { pw_setcmsname(vwsP->sunview.pw, cmsname); /* cms_rgbsetup (cmap.cm_red, cmap.cm_green, cmap.cm_blue); */ /* * wds 850626: Turned back on (was previously commented out) needed * so upcoming pw_writebackground will refill the "screen" with * color zero of new color map size, not merely default size. Note: * color map is the correct size, but values may be trash, * depending on whether this is the first window using the cmsname. */ pw_putcolormap(vwsP->sunview.pw, 0, cmapsize, red, green, blue); if (vwsP->sunview.orig_pw != vwsP->sunview.pw) { pw_setcmsname(vwsP->sunview.orig_pw, cmsname); pw_putcolormap(vwsP->sunview.orig_pw, 0, cmapsize, red, green, blue); } } } } /****************************************************************************/ /* */ /* FUNCTION: _cgi_get_window_vwsurf */ /* */ /* Opens a view surface in a window. */ /* Tries (in order): */ /* view_surface (tool) on user's screenname (if any), */ /* blanketing window* in environment variable WINDOW_GFX, */ /* view_surface (tool) on same screen* as WINDOW_GFX, */ /* Idea: Could also try a view_surface (tool) on /dev/fb*. */ /* */ /* * above only if colorflg matches color attribute of screen. */ /* */ /****************************************************************************/ static int _cgi_get_window_vwsurf(pw_fdp, pidp, colorflg, vsurfp, gpflg) int *pw_fdp, *pidp; colorflag_enum *colorflg; Cvwsurf *vsurfp; int *gpflg; { int i1, i2; static char name[DEVNAMESIZE]; static char *argvarray[] = { "view_surface", name, 0 }; static char initstring[80] = "WINDOW_INITIALDATA="; static char *envparray[] = { initstring, 0 }; char **childenvp, *pname; int fd, pipefd[2]; int pid = -1; struct screen screen; int chkscreen(); Cerror err; /* * Old test: if ((_cgi_gfxenvfd == -1) && !(vsurfp->flags & VWSURF_NEWFLG) * && (*vsurfp->screenname == '\0')) */ /* Set pw to 0 so we can tell later if somebody successfully opened it */ _cgi_vws->sunview.pw = (Pixwin *) 0; /* User has demanded a "new" view surface, so fork 'em */ if (vsurfp->flags & VWSURF_NEWFLG) goto fork_vwsurftool; /* User has NOT demanded a "new" view surface */ if (vsurfp->windowname[0] != '\0') { /* Try to open user-specified windowname */ if (we_getgfxwindow(name) == 0 && strcmp(name, vsurfp->windowname) == 0) { if (_cgi_gfxenvfd != -1) return (ENOWSTYP); /* WINDOW_GFX==windowname & is already * in use */ else if ((fd = blanket_a_window(vsurfp->windowname, colorflg)) < 0) return (ENOWSTYP); else _cgi_gfxenvfd = *pw_fdp = fd; /* Give caller the fd to use */ /* * _cgi_new_window_init call below sets _cgi_vws->sunview.pw from * _cgi_vws->sunview.windowfd */ } else if ((*pw_fdp = blanket_a_window(vsurfp->windowname, colorflg)) < 0) return (ENOWSTYP); pid = 0; /* no view_surface "tool" forked, so there is * no "tool" pid */ } else if ((_cgi_gfxenvfd == -1) && (vsurfp->screenname[0] == '\0')) { /* If user specified no screen, try WINDOW_GFX * environment variable */ if (we_getgfxwindow(name)) return (ENOWSTYP); /* WINDOW_GFX environment value could not be * found */ if ((fd = blanket_a_window(name, colorflg)) < 0) return (ENOWSTYP); else _cgi_gfxenvfd = *pw_fdp = fd; /* Let the caller know what fd * to use */ /* * _cgi_new_window_init below sets _cgi_vws->sunview.pw from * _cgi_vws->sunview.windowfd */ pid = 0; /* no view_surface "tool" forked, so there is * no "tool" pid */ } else /* we'll have to make a view_surface tool, but * on what screen? */ { fork_vwsurftool: /* If the user is specifying what view surface he wants, try to find it */ if (vsurfp->screenname[0] != '\0') { foundscreen = FALSE; srchptr = vsurfp->screenname; scrptr = &screen; win_enumall(chkscreen); if (!foundscreen) return (ENOWSTYP); /* No such screen running windows */ /* Core goes on to demand that the screen found matches "colorflg" */ if (*colorflg == ANY) { /* set *colorflg from fbtype & set *gpflg if GP1. */ if (fbtype_colorflag_check(screen.scr_fbname, colorflg, gpflg) < 0) return (ENOWSTYP); } } else /* * Use the same screen as vsurfp->windowname, if the user gave us * one. Otherwise, use the same screen as WINDOW_GFX. Core tries to * reopen _cgi_gfxenvfd & check it against colorflg. */ { /* open_gfx_window demands the correct colorflg. */ if ((fd = open_gfx_window(vsurfp->windowname, colorflg)) < 0) return (ENOWSTYP); /* else try to open /dev/fb perhaps? */ /* _cgi_vws->sunview.windowfd = fd; necessary? */ /* _cgi_new_window_init should set _cgi_vws->sunview.pw */ win_screenget(fd, &screen); (void) close(fd); } /* we know what screen, now we have to fork the view_surface tool */ if (pipe(pipefd) < 0) return (ENOWSTYP); /* (void) fprintf (stderr,"BEFORE errno=%d \n", errno); */ errno = 0; if ((pid = vfork()) == 0) { /* child process */ (void) strncpy(name, screen.scr_rootname, DEVNAMESIZE); /* e.g., /dev/cgtwo0 */ if (vsurfp->ptr == 0) childenvp = environ; /* core uses NULL envir. ptr. here */ else { childenvp = envparray; (void) strncpy(initstring + 19, *vsurfp->ptr, 60); initstring[sizeof(initstring)-1] = '\0'; } if (dup2(pipefd[1], 1) < 0) _exit(0); (void) close(0); /* assume fds 0,1,2 are left */ /* Other file descripters not needed by view_surface, so close them */ i2 = getdtablesize(); for (i1 = 3; i1 < i2; i1++) (void) fcntl(i1, F_SETFD, 1); /* close on exec */ if (access((pname="/usr/bin/view_surface"), F_OK|X_OK)) pname ="/usr/lib/view_surface"; execve(pname, argvarray, childenvp); _exit(0); /* only return if unable to exec */ } notify_set_wait3_func(_cgi_state.notifier_client_handle, _cgi_sigchild, pid); (void) close(pipefd[1]);/* parent process */ if (pid < 0) { (void) close(pipefd[0]); return (ENOWSTYP); } i1 = read(pipefd[0], name, DEVNAMESIZE); /* e.g., /dev/win23 */ (void) close(pipefd[0]); if ((i1 < DEVNAMESIZE) || ((fd = open(name, O_RDWR, 0)) < 0)) { (void) kill(pid, 9); return (ENOWSTYP); } *pw_fdp = fd; _cgi_vws->sunview.windowfd = fd; win_setowner(fd, getpid()); } /* end making a view_surface tool */ /* * _cgi_new_window_init sets _cgi_vws->sunview.pw from * _cgi_vws->sunview.windowfd */ if ((err = _cgi_new_window_init(_cgi_vws)) != NO_ERROR) return (err); if (_cgi_vws->sunview.pw == (Pixwin *) 0) { if (pid > 0) (void) kill(pid, 9); return (ENOWSTYP); } else { *pidp = pid; } /* Finish off window viewsurface initialization */ if (*colorflg == COLOR) { _cgi_color_init(vsurfp); } return (NO_ERROR); } /****************************************************************************/ /* */ /* FUNCTION: chkscreen */ /* */ /* */ /****************************************************************************/ static int chkscreen(windowfd) int windowfd; { win_screenget(windowfd, scrptr); if (strcmp(srchptr, scrptr->scr_fbname) == 0) { foundscreen = TRUE; return (TRUE); } return (FALSE); } /****************************************************************************/ /* */ /* FUNCTION: blanket_a_window */ /* */ /* Tries to open windowname given. */ /* Checks frame buffer's capabilities against "colorflag". */ /* If colorflag == ANY, it is replaced with MONO or COLOR. */ /* Returns nonnegative open window fd if OK, -1 for failure. */ /****************************************************************************/ static int blanket_a_window(windowname, colorflg) char *windowname; colorflag_enum *colorflg; { int parentfd, fd; if (!windowname || *windowname == '\0') return (-1); /* WINDOW_GFX environment value could not be * found */ if ((parentfd = open_gfx_window(windowname, colorflg)) < 0) return (-1); if ((fd = win_getnewwindow()) < 0) /* get another /dev/winXX */ { (void) close(parentfd); return (-1); } _cgi_vws->sunview.windowfd = fd; /* * _cgi_new_window_init (called from this function's caller) sets * _cgi_vws->sunview.pw from _cgi_vws->sunview.windowfd */ if (win_insertblanket(fd, parentfd)) { (void) close(parentfd); (void) close(fd); return (-1); } (void) close(parentfd); return (fd); } /****************************************************************************/ /* */ /* FUNCTION: open_gfx_window */ /* */ /* If windowname is given, try to open it, else WINDOW_GFX. */ /* Checks frame buffer's capabilities against "colorflag". */ /* If colorflag == ANY, it is replaced with MONO or COLOR. */ /* Returns nonnegative open window fd if OK, -1 for failure. */ /****************************************************************************/ static int open_gfx_window(windowname, colorflg) char *windowname; colorflag_enum *colorflg; { int gwfd; char name[DEVNAMESIZE]; int gp_flag; struct screen screen; if (windowname && *windowname) { } /* Then use windowname as is */ else { if (we_getgfxwindow(windowname = name)) return (-1); /* WINDOW_GFX environment value could not be * found */ } if ((gwfd = open(windowname, O_RDWR, 0)) < 0) /* get window fd */ return (-1); win_screenget(gwfd, &screen); /* get screen structure */ if (fbtype_colorflag_check(screen.scr_fbname, colorflg, &gp_flag) < 0) { (void) close(gwfd); return (-1); } return (gwfd); /* return window fd */ } /****************************************************************************/ /* */ /* FUNCTION: fbtype_colorflag_check(screenname, colorflg) */ /* */ /* Checks a frame buffer's inherent capabilities against */ /* the input "colorflag" demands. */ /* If colorflag == ANY, it is replaced with MONO or COLOR. */ /* If fbtype == FBTYPE_SUN2GP, sets global *gpflg. */ /* Returns nonnegative fbtype code if OK, -1 for failure. */ /****************************************************************************/ /* * ## If this is called from both _cgi_get_window_vwsurf and * _cgi_get_device_vwsurf, then _cgi_get_dev also does the test and * sets *gpflg superfluously. */ static int fbtype_colorflag_check(screenname, colorflg, gpflg) char *screenname; colorflag_enum *colorflg; int *gpflg; { int fbtype, fbfd; if ((fbfd = open(screenname, O_RDWR, 0)) < 0) /* get FB fd */ return (-1); if ((fbtype = _cgi_fb_colorflag_mismatch(fbfd, colorflg)) < 0) { (void) close(fbfd); return (-1); } if (fbtype == FBTYPE_SUN2GP) *gpflg = 1; else *gpflg = 0; (void) close(fbfd); /* close FB fd */ return (fbtype); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_fb_colorflag_mismatch */ /* */ /* Checks a frame buffer's inherent capabilities against */ /* the input "colorflag" demands. */ /* If colorflag == ANY, it is replaced with MONO or COLOR. */ /* Returns nonnegative fbtype code if OK, -1 for failure. */ /****************************************************************************/ static int _cgi_fb_colorflag_mismatch(fbfd, colorflg) int fbfd; colorflag_enum *colorflg; { int fbtype; int returnvalue = -1; /* Assume the worst */ if ((fbtype = pr_getfbtype_from_fd(fbfd)) == -1) return (-1); else switch (fbtype) { case FBTYPE_SUN1BW: case FBTYPE_SUN2BW: switch (*colorflg) { default: case ANY: *colorflg = MONO; /* continue thru next case */ case MONO: returnvalue = fbtype; break; case COLOR: break; } break; case FBTYPE_SUN1COLOR: case FBTYPE_SUN2COLOR: case FBTYPE_SUN3COLOR: case FBTYPE_SUN4COLOR: #ifndef NO_CG6 case FBTYPE_SUNFAST_COLOR: #endif NO_CG6 case FBTYPE_SUN2GP: switch (*colorflg) { case MONO: break; default: case ANY: *colorflg = COLOR; /* continue thru next case */ case COLOR: returnvalue = fbtype; break; } break; } return (returnvalue); } /****************************************************************************/ /* */ /* FUNCTION: open_vws_special */ /* */ /* Opens, but does not activiate, a view surface. All */ /* pertainent view surface information is stored and the view */ /* surface is added to the list of view surfaces */ /****************************************************************************/ Cerror open_vws_special(name, devdd, atarg) Cint *name; /* internal name */ Cvwsurf *devdd; /* view surface descriptor */ Ccgiwin *atarg; /* returned descriptor of new view surface */ { register View_surface *cur_vws = 0; /* ptr to current view surface info */ register Outatt *cur_att = 0; /* ptr to current attribute info */ int err; int new_name; /* newly allocated view surface */ START_CRITICAL(); /* Don't malloc unless everything else is OK */ err = _cgi_check_state_5(); if (!err) { new_name = _cgi_new_vwsurf_name(); if (new_name < 0) err = EMAXVSOP; /* Maximum no. of view surfaces already open. */ } if (!err) { cur_vws = (View_surface *) calloc(1, sizeof(View_surface)); _cgi_view_surfaces[new_name] = cur_vws; if (!cur_vws) err = EMEMSPAC; } if (!err) { cur_att = _cgi_alloc_output_att(_cgi_state.common_att); if (cur_att == (Outatt *) 0) { /* malloc failed */ err = EMEMSPAC; _cgi_free_name(new_name); } } if (!err) { /* if malloc worked */ _cgi_vws = cur_vws; cur_vws->att = _cgi_att = cur_att; _cgi_retained = (devdd->retained); err = _cgi_get_dev(devdd); /* get actual device */ (void) fcntl(cur_vws->sunview.windowfd, F_SETFL, FASYNC | FNDELAY); } if (!err) /* (no err from _cgi_get_dev) */ { Cos incoming_cgi_state = _cgi_state.state; if (_cgi_state.state != VSAC) _cgi_state.state = VSOP; cur_vws->active = 0; /* * if first view surface opened, set defaults, initialize input stats, * and clear screen. Hard_reset does _cgi_windowset via vdc_extent. */ if (incoming_cgi_state == CGOP) (void) hard_reset(); else (void) _cgi_windowset(cur_vws); /* Return handles for new view surface */ *name = new_name; /* Only if no errors */ atarg->vws = cur_vws; } else { if (new_name >= 0) { /* Make surface as if it didn't exist */ _cgi_free_name(new_name); } /* * Explicitly invalidate the contents of the descriptor being returned * to forestall later segmentation violations when the client calls * CGIPW functions with this bogus descriptor. */ *name = -1; _cgi_vws = atarg->vws = (View_surface *) NULL; } END_CRITICAL(); return (_cgi_errhand(err)); } /****************************************************************************/ /* */ /* FUNCTION: close_vws */ /* */ /* deselects viewsurface */ /****************************************************************************/ Cerror close_vws(name) Cint name; /* view surface name */ { register View_surface *vwsP; int err; /* * Can't detect error 112, ENOTCCPW, not compatible with Standard CGI, * since close_vws is called by close_cgi_pw, without setting another * global. */ err = _cgi_check_state_5(); if (!err) err = _cgi_context(name); if (!err) { vwsP = _cgi_vws; if (vwsP->sunview.gp_att != (Gp1_attr *) NULL) { _cgi_gp1_attr_close(vwsP->sunview.pw, &vwsP->sunview.gp_att); } if (vwsP->sunview.pw != vwsP->sunview.orig_pw) { pw_close(vwsP->sunview.orig_pw); vwsP->sunview.orig_pw = (Pixwin *) NULL; } /* * If this view surface had its own attribute set allocated, then free * it. Common attribute structure is freed in close_cgi. */ if (vwsP->att != _cgi_state.common_att) { _cgi_free_output_att(vwsP->att); vwsP->att = (Outatt *) NULL; } /* * ## WCL860925: is this true?? This should hold off SIGWINCH & * SIGCHILD handling, which could cause errors after closing the fd. */ _cgi_free_name(name); if (!_cgi_state.cgipw_mode) { /* wds 860513: don't clear cgipw user's pw or close his windowfd */ pw_close(vwsP->sunview.pw); if (_cgi_gfxenvfd == vwsP->sunview.windowfd) /* WDS: was != before * 860104 */ { win_removeblanket(vwsP->sunview.windowfd); (void) close(_cgi_gfxenvfd); /* WDS: was commented out. */ _cgi_gfxenvfd = -1; } else if (vwsP->sunview.tool_pid > 0) /* 0 is not a valid PID */ { win_setowner(vwsP->sunview.windowfd, vwsP->sunview.tool_pid); (void) close(vwsP->sunview.windowfd); (void) kill(vwsP->sunview.tool_pid, 9); vwsP->sunview.tool_pid = 0; } else { if (win_isblanket(vwsP->sunview.windowfd)) win_removeblanket(vwsP->sunview.windowfd); (void) close(vwsP->sunview.windowfd); } } _cgi_vws = (View_surface *) NULL; _cgi_att = _cgi_state.common_att; } return (_cgi_errhand(err)); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_free_name */ /* */ /* frees up a viewsurface "name" (_cgi_view_surfaces index). */ /* see also _cgi_new_vwsurf_name, which allocates names. */ /* _cgi_vwsurf_count is index such that it and all entries */ /* above it are definitely NULL. Lower indices may be NULL. */ /****************************************************************************/ Cerror _cgi_free_name(name) Cint name; /* view surface name */ { View_surface *cur_vws = _cgi_view_surfaces[name]; if (cur_vws != (View_surface *) 0) { free((char *) cur_vws); _cgi_view_surfaces[name] = (View_surface *) 0; } /* If name is highest in array, find new highest entry in array */ if (name == _cgi_vwsurf_count - 1) { while (--name >= 0 && _cgi_view_surfaces[name] == (View_surface *) 0) ; _cgi_vwsurf_count = name + 1; /* * If there are still view surfaces open, set global pointers * to point to an open one. */ if (_cgi_vwsurf_count > 0) { _cgi_vws = _cgi_view_surfaces[name]; _cgi_att = _cgi_vws->att; } } _cgi_reset_vws_based_state(); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_bump_vws */ /* */ /* gets next active view surface */ /****************************************************************************/ int _cgi_bump_vws(num) int *num; { int i = *num; int ret = 0; for (; i < _cgi_vwsurf_count; i++) { ret = _cgi_context(i); if ((ret == 0) && _cgi_view_surfaces[i]->active) { ret = 1; break; } } *num = i + 1; /* Caller should try next surface next time */ return (ret); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_bump_all_vws */ /* */ /* gets next open view surface */ /****************************************************************************/ int _cgi_bump_all_vws(num) int *num; { int i; int ret = 0; for (i = *num; i < _cgi_vwsurf_count; i++) { if (_cgi_context(i) == 0) { ret = 1; break; } } *num = i + 1; /* Caller should try next surface next time */ return (ret); } /****************************************************************************/ /* */ /* FUNCTION: _cgi_context */ /* */ /* changes context of view surface. */ /****************************************************************************/ int _cgi_context(num) int num; { int err; err = _cgi_legal_winname(num); /* check num, _cgi_view_surfaces[num] */ if (!err) { _cgi_vws = _cgi_view_surfaces[num]; _cgi_att = _cgi_vws->att; } return (err); }