Files
Arquivotheca.SunOS-4.1.4/usr.lib/libcgi/metanew.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

1390 lines
43 KiB
C

#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 <errno.h>
#include <signal.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sun/fbio.h>
#include <sun/gpio.h>
#include <sys/ioctl.h>
#include <sunwindow/cms.h>
#include <sunwindow/cms_rgb.h>
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);
}