findfp.c revision 90792
190792Sgshapiro/*
290792Sgshapiro * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers.
390792Sgshapiro *      All rights reserved.
490792Sgshapiro * Copyright (c) 1990, 1993
590792Sgshapiro *	The Regents of the University of California.  All rights reserved.
690792Sgshapiro *
790792Sgshapiro * This code is derived from software contributed to Berkeley by
890792Sgshapiro * Chris Torek.
990792Sgshapiro *
1090792Sgshapiro * By using this file, you agree to the terms and conditions set
1190792Sgshapiro * forth in the LICENSE file which can be found at the top level of
1290792Sgshapiro * the sendmail distribution.
1390792Sgshapiro */
1490792Sgshapiro
1590792Sgshapiro#include <sm/gen.h>
1690792SgshapiroSM_RCSID("@(#)$Id: findfp.c,v 1.62 2002/01/11 16:33:03 ca Exp $")
1790792Sgshapiro#include <stdlib.h>
1890792Sgshapiro#include <unistd.h>
1990792Sgshapiro#include <sys/param.h>
2090792Sgshapiro#include <errno.h>
2190792Sgshapiro#include <string.h>
2290792Sgshapiro#include <syslog.h>
2390792Sgshapiro#include <sm/io.h>
2490792Sgshapiro#include <sm/assert.h>
2590792Sgshapiro#include <sm/heap.h>
2690792Sgshapiro#include <sm/string.h>
2790792Sgshapiro#include <sm/conf.h>
2890792Sgshapiro#include "local.h"
2990792Sgshapiro#include "glue.h"
3090792Sgshapiro
3190792Sgshapirobool	Sm_IO_DidInit;	/* IO system has been initialized? */
3290792Sgshapiro
3390792Sgshapiroconst char SmFileMagic[] = "sm_file";
3490792Sgshapiro
3590792Sgshapiro/* An open type to map to fopen()-like behavior */
3690792SgshapiroSM_FILE_T SmFtStdio_def =
3790792Sgshapiro    {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0,
3890792Sgshapiro	sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite,
3990792Sgshapiro	sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER,
4090792Sgshapiro	SM_TIME_BLOCK, "stdio" };
4190792Sgshapiro
4290792Sgshapiro/* An open type to map to fdopen()-like behavior */
4390792SgshapiroSM_FILE_T SmFtStdiofd_def =
4490792Sgshapiro    {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0,
4590792Sgshapiro	sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite,
4690792Sgshapiro	sm_stdfdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER,
4790792Sgshapiro	SM_TIME_BLOCK, "stdiofd" };
4890792Sgshapiro
4990792Sgshapiro/* A string file type */
5090792SgshapiroSM_FILE_T _SmFtString_def =
5190792Sgshapiro    {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0,
5290792Sgshapiro	sm_strclose, sm_strread, sm_strseek, sm_strwrite,
5390792Sgshapiro	sm_stropen, sm_strsetinfo, sm_strgetinfo, SM_TIME_FOREVER,
5490792Sgshapiro	SM_TIME_BLOCK, "string" };
5590792Sgshapiro
5690792Sgshapiro#if 0
5790792Sgshapiro/* A file type for syslog communications */
5890792SgshapiroSM_FILE_T SmFtSyslog_def =
5990792Sgshapiro    {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0,
6090792Sgshapiro	sm_syslogclose, sm_syslogread, sm_syslogseek, sm_syslogwrite,
6190792Sgshapiro	sm_syslogopen, sm_syslogsetinfo, sm_sysloggetinfo, SM_TIME_FOREVER,
6290792Sgshapiro	SM_TIME_BLOCK, "syslog" };
6390792Sgshapiro#endif /* 0 */
6490792Sgshapiro
6590792Sgshapiro#define NDYNAMIC 10		/* add ten more whenever necessary */
6690792Sgshapiro
6790792Sgshapiro#define smio(flags, file, name)						\
6890792Sgshapiro    {SmFileMagic, 0, 0, 0, flags, file, {0}, 0, SmIoF+file, 0,		\
6990792Sgshapiro	sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite,		\
7090792Sgshapiro	sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER,	\
7190792Sgshapiro	SM_TIME_BLOCK, name}
7290792Sgshapiro
7390792Sgshapiro/* sm_magic p r w flags file bf lbfsize cookie ival */
7490792Sgshapiro#define smstd(flags, file, name)					\
7590792Sgshapiro    {SmFileMagic, 0, 0, 0, flags, -1, {0}, 0, 0, file,			\
7690792Sgshapiro	sm_stdioclose, sm_stdioread, sm_stdioseek, sm_stdiowrite,	\
7790792Sgshapiro	sm_stdioopen, sm_stdiosetinfo, sm_stdiogetinfo, SM_TIME_FOREVER,\
7890792Sgshapiro	SM_TIME_BLOCK, name}
7990792Sgshapiro
8090792Sgshapiro/* A file type for interfacing to stdio FILE* streams. */
8190792SgshapiroSM_FILE_T SmFtRealStdio_def = smstd(SMRW|SMNBF, -1, "realstdio");
8290792Sgshapiro
8390792Sgshapiro				/* the usual - (stdin + stdout + stderr) */
8490792Sgshapirostatic SM_FILE_T usual[SM_IO_OPEN_MAX - 3];
8590792Sgshapirostatic struct sm_glue smuglue = { 0, SM_IO_OPEN_MAX - 3, usual };
8690792Sgshapiro
8790792Sgshapiro/* List of builtin automagically already open file pointers */
8890792SgshapiroSM_FILE_T SmIoF[6] =
8990792Sgshapiro{
9090792Sgshapiro	smio(SMRD|SMLBF, SMIOIN_FILENO, "smioin"),	/* smioin */
9190792Sgshapiro	smio(SMWR|SMLBF, SMIOOUT_FILENO, "smioout"),	/* smioout */
9290792Sgshapiro	smio(SMWR|SMNBF, SMIOERR_FILENO, "smioerr"),	/* smioerr */
9390792Sgshapiro	smstd(SMRD|SMNBF, SMIOIN_FILENO, "smiostdin"),	/* smiostdin */
9490792Sgshapiro	smstd(SMWR|SMNBF, SMIOOUT_FILENO, "smiostdout"),/* smiostdout */
9590792Sgshapiro	smstd(SMWR|SMNBF, SMIOERR_FILENO, "smiostderr") /* smiostderr */
9690792Sgshapiro};
9790792Sgshapiro
9890792Sgshapiro/* Structure containing list of currently open file pointers */
9990792Sgshapirostruct sm_glue smglue = { &smuglue, 3, SmIoF };
10090792Sgshapiro
10190792Sgshapiro/*
10290792Sgshapiro**  SM_MOREGLUE -- adds more space for open file pointers
10390792Sgshapiro**
10490792Sgshapiro**	Parameters:
10590792Sgshapiro**		n -- number of new spaces for file pointers
10690792Sgshapiro**
10790792Sgshapiro**	Returns:
10890792Sgshapiro**		Raises an exception if no more memory.
10990792Sgshapiro**		Otherwise, returns a pointer to new spaces.
11090792Sgshapiro*/
11190792Sgshapiro
11290792Sgshapirostatic struct sm_glue *sm_moreglue_x __P((int));
11390792Sgshapirostatic SM_FILE_T empty;
11490792Sgshapiro
11590792Sgshapirostatic struct sm_glue *
11690792Sgshapirosm_moreglue_x(n)
11790792Sgshapiro	register int n;
11890792Sgshapiro{
11990792Sgshapiro	register struct sm_glue *g;
12090792Sgshapiro	register SM_FILE_T *p;
12190792Sgshapiro
12290792Sgshapiro	g = (struct sm_glue *) sm_pmalloc_x(sizeof(*g) + ALIGNBYTES +
12390792Sgshapiro					    n * sizeof(SM_FILE_T));
12490792Sgshapiro	p = (SM_FILE_T *) ALIGN(g + 1);
12590792Sgshapiro	g->gl_next = NULL;
12690792Sgshapiro	g->gl_niobs = n;
12790792Sgshapiro	g->gl_iobs = p;
12890792Sgshapiro	while (--n >= 0)
12990792Sgshapiro		*p++ = empty;
13090792Sgshapiro	return g;
13190792Sgshapiro}
13290792Sgshapiro
13390792Sgshapiro/*
13490792Sgshapiro**  SM_FP -- allocate and initialize an SM_FILE structure
13590792Sgshapiro**
13690792Sgshapiro**	Parameters:
13790792Sgshapiro**		t -- file type requested to be opened.
13890792Sgshapiro**		flags -- control flags for file type behavior
13990792Sgshapiro**		oldfp -- file pointer to reuse if available (optional)
14090792Sgshapiro**
14190792Sgshapiro**	Returns:
14290792Sgshapiro**		Raises exception on memory exhaustion.
14390792Sgshapiro**		Aborts if type is invalid.
14490792Sgshapiro**		Otherwise, returns file pointer for requested file type.
14590792Sgshapiro*/
14690792Sgshapiro
14790792SgshapiroSM_FILE_T *
14890792Sgshapirosm_fp(t, flags, oldfp)
14990792Sgshapiro	const SM_FILE_T *t;
15090792Sgshapiro	const int flags;
15190792Sgshapiro	SM_FILE_T *oldfp;
15290792Sgshapiro{
15390792Sgshapiro	register SM_FILE_T *fp;
15490792Sgshapiro	register int n;
15590792Sgshapiro	register struct sm_glue *g;
15690792Sgshapiro
15790792Sgshapiro	SM_REQUIRE(t->f_open && t->f_close && (t->f_read || t->f_write));
15890792Sgshapiro
15990792Sgshapiro	if (!Sm_IO_DidInit)
16090792Sgshapiro		sm_init();
16190792Sgshapiro
16290792Sgshapiro	if (oldfp != NULL)
16390792Sgshapiro	{
16490792Sgshapiro		fp = oldfp;
16590792Sgshapiro		goto found; /* for opening reusing an 'fp' */
16690792Sgshapiro	}
16790792Sgshapiro
16890792Sgshapiro	for (g = &smglue;; g = g->gl_next)
16990792Sgshapiro	{
17090792Sgshapiro		for (fp = g->gl_iobs, n = g->gl_niobs; --n >= 0; fp++)
17190792Sgshapiro			if (fp->sm_magic == NULL)
17290792Sgshapiro				goto found;
17390792Sgshapiro		if (g->gl_next == NULL)
17490792Sgshapiro			g->gl_next = sm_moreglue_x(NDYNAMIC);
17590792Sgshapiro	}
17690792Sgshapirofound:
17790792Sgshapiro	fp->sm_magic = SmFileMagic; /* 'fp' now valid and in-use */
17890792Sgshapiro	fp->f_p = NULL;		/* no current pointer */
17990792Sgshapiro	fp->f_w = 0;		/* nothing to write */
18090792Sgshapiro	fp->f_r = 0;		/* nothing to read */
18190792Sgshapiro	fp->f_flags = flags;
18290792Sgshapiro	fp->f_file = -1;		/* no file */
18390792Sgshapiro	fp->f_bf.smb_base = NULL;	/* no buffer */
18490792Sgshapiro	fp->f_bf.smb_size = 0;	/* no buffer size with no buffer */
18590792Sgshapiro	fp->f_lbfsize = 0;	/* not line buffered */
18690792Sgshapiro	fp->f_flushfp = NULL;	/* no associated flush file */
18790792Sgshapiro
18890792Sgshapiro	fp->f_cookie = fp;	/* default: *open* overrides cookie setting */
18990792Sgshapiro	fp->f_close = t->f_close;	/* assign close function */
19090792Sgshapiro	fp->f_read = t->f_read;		/* assign read function */
19190792Sgshapiro	fp->f_seek = t->f_seek;		/* assign seek function */
19290792Sgshapiro	fp->f_write = t->f_write;	/* assign write function */
19390792Sgshapiro	fp->f_open = t->f_open;		/* assign open function */
19490792Sgshapiro	fp->f_setinfo = t->f_setinfo;	/* assign setinfo function */
19590792Sgshapiro	fp->f_getinfo = t->f_getinfo;	/* assign getinfo function */
19690792Sgshapiro	fp->f_type = t->f_type;		/* file type */
19790792Sgshapiro	fp->f_self = fp;		/* self reference for future use */
19890792Sgshapiro
19990792Sgshapiro	fp->f_ub.smb_base = NULL;	/* no ungetc buffer */
20090792Sgshapiro	fp->f_ub.smb_size = 0;		/* no size for no ungetc buffer */
20190792Sgshapiro
20290792Sgshapiro	fp->f_lb.smb_base = NULL;	/* no line buffer */
20390792Sgshapiro	fp->f_lb.smb_size = 0;		/* no size for no line buffer */
20490792Sgshapiro	if (fp->f_timeout == SM_TIME_DEFAULT)
20590792Sgshapiro		fp->f_timeout = SM_TIME_FOREVER;
20690792Sgshapiro	else
20790792Sgshapiro		fp->f_timeout = t->f_timeout; /* traditional behavior */
20890792Sgshapiro	fp->f_timeoutstate = SM_TIME_BLOCK; /* by default */
20990792Sgshapiro
21090792Sgshapiro	return fp;
21190792Sgshapiro}
21290792Sgshapiro
21390792Sgshapiro/*
21490792Sgshapiro**  SM_CLEANUP -- cleanup function when exit called.
21590792Sgshapiro**
21690792Sgshapiro**	This function is registered via atexit().
21790792Sgshapiro**
21890792Sgshapiro**	Parameters:
21990792Sgshapiro**		none
22090792Sgshapiro**
22190792Sgshapiro**	Returns:
22290792Sgshapiro**		nothing.
22390792Sgshapiro**
22490792Sgshapiro**	Side Effects:
22590792Sgshapiro**		flushes open files before they are forced closed
22690792Sgshapiro*/
22790792Sgshapiro
22890792Sgshapirovoid
22990792Sgshapirosm_cleanup()
23090792Sgshapiro{
23190792Sgshapiro	int timeout = SM_TIME_DEFAULT;
23290792Sgshapiro
23390792Sgshapiro	(void) sm_fwalk(sm_flush, &timeout); /* `cheating' */
23490792Sgshapiro}
23590792Sgshapiro
23690792Sgshapiro/*
23790792Sgshapiro**  SM_INIT -- called whenever sm_io's internal variables must be set up.
23890792Sgshapiro**
23990792Sgshapiro**	Parameters:
24090792Sgshapiro**		none
24190792Sgshapiro**
24290792Sgshapiro**	Returns:
24390792Sgshapiro**		none
24490792Sgshapiro**
24590792Sgshapiro**	Side Effects:
24690792Sgshapiro**		Registers sm_cleanup() using atexit().
24790792Sgshapiro*/
24890792Sgshapiro
24990792Sgshapirovoid
25090792Sgshapirosm_init()
25190792Sgshapiro{
25290792Sgshapiro	if (Sm_IO_DidInit)	/* paranoia */
25390792Sgshapiro		return;
25490792Sgshapiro
25590792Sgshapiro	/* more paranoia: initialize pointers in a static variable */
25690792Sgshapiro	empty.f_type = NULL;
25790792Sgshapiro	empty.sm_magic = NULL;
25890792Sgshapiro
25990792Sgshapiro	/* make sure we clean up on exit */
26090792Sgshapiro	atexit(sm_cleanup);		/* conservative */
26190792Sgshapiro	Sm_IO_DidInit = true;
26290792Sgshapiro}
26390792Sgshapiro
26490792Sgshapiro/*
26590792Sgshapiro**  SM_IO_SETINFO -- change info for an open file type (fp)
26690792Sgshapiro**
26790792Sgshapiro**	The generic SM_IO_WHAT_VECTORS is auto supplied for all file types.
26890792Sgshapiro**	If the request is to set info other than SM_IO_WHAT_VECTORS then
26990792Sgshapiro**	the request is passed on to the file type's specific setinfo vector.
27090792Sgshapiro**	WARNING: this is working on an active/open file type.
27190792Sgshapiro**
27290792Sgshapiro**	Parameters:
27390792Sgshapiro**		fp -- file to make the setting on
27490792Sgshapiro**		what -- type of information to set
27590792Sgshapiro**		valp -- structure to obtain info from
27690792Sgshapiro**
27790792Sgshapiro**	Returns:
27890792Sgshapiro**		0 on success
27990792Sgshapiro**		-1 on error and sets errno:
28090792Sgshapiro**			- when what != SM_IO_WHAT_VECTORS and setinfo vector
28190792Sgshapiro**				not set
28290792Sgshapiro**			- when vectored setinfo returns -1
28390792Sgshapiro*/
28490792Sgshapiro
28590792Sgshapiroint
28690792Sgshapirosm_io_setinfo(fp, what, valp)
28790792Sgshapiro	SM_FILE_T *fp;
28890792Sgshapiro	int what;
28990792Sgshapiro	void *valp;
29090792Sgshapiro{
29190792Sgshapiro	SM_FILE_T *v = (SM_FILE_T *) valp;
29290792Sgshapiro
29390792Sgshapiro	SM_REQUIRE_ISA(fp, SmFileMagic);
29490792Sgshapiro	switch (what)
29590792Sgshapiro	{
29690792Sgshapiro	  case SM_IO_WHAT_VECTORS:
29790792Sgshapiro
29890792Sgshapiro		/*
29990792Sgshapiro		**  This is the "generic" available for all.
30090792Sgshapiro		**  This allows the function vectors to be replaced
30190792Sgshapiro		**  while the file type is active.
30290792Sgshapiro		*/
30390792Sgshapiro
30490792Sgshapiro		fp->f_close = v->f_close;
30590792Sgshapiro		fp->f_read = v->f_read;
30690792Sgshapiro		fp->f_seek = v->f_seek;
30790792Sgshapiro		fp->f_write = v->f_write;
30890792Sgshapiro		fp->f_open = v->f_open;
30990792Sgshapiro		fp->f_setinfo = v->f_setinfo;
31090792Sgshapiro		fp->f_getinfo = v->f_getinfo;
31190792Sgshapiro		sm_free(fp->f_type);
31290792Sgshapiro		fp->f_type = sm_strdup_x(v->f_type);
31390792Sgshapiro		return 0;
31490792Sgshapiro	  case SM_IO_WHAT_TIMEOUT:
31590792Sgshapiro		fp->f_timeout = *((int *)valp);
31690792Sgshapiro		return 0;
31790792Sgshapiro	}
31890792Sgshapiro
31990792Sgshapiro	/* Otherwise the vector will check it out */
32090792Sgshapiro	if (fp->f_setinfo == NULL)
32190792Sgshapiro	{
32290792Sgshapiro		errno = EINVAL;
32390792Sgshapiro		return -1;
32490792Sgshapiro	}
32590792Sgshapiro	else
32690792Sgshapiro		return (*fp->f_setinfo)(fp, what, valp);
32790792Sgshapiro}
32890792Sgshapiro
32990792Sgshapiro/*
33090792Sgshapiro**  SM_IO_GETINFO -- get information for an active file type (fp)
33190792Sgshapiro**
33290792Sgshapiro**  This function supplies for all file types the answers for the
33390792Sgshapiro**		three requests SM_IO_WHAT_VECTORS, SM_IO_WHAT_TYPE and
33490792Sgshapiro**		SM_IO_WHAT_ISTYPE. Other requests are handled by the getinfo
33590792Sgshapiro**		vector if available for the open file type.
33690792Sgshapiro**	SM_IO_WHAT_VECTORS returns information for the file pointer vectors.
33790792Sgshapiro**	SM_IO_WHAT_TYPE returns the type identifier for the file pointer
33890792Sgshapiro**	SM_IO_WHAT_ISTYPE returns >0 if the passed in type matches the
33990792Sgshapiro**		file pointer's type.
34090792Sgshapiro**	SM_IO_IS_READABLE returns 1 if there is data available for reading,
34190792Sgshapiro**		0 otherwise.
34290792Sgshapiro**
34390792Sgshapiro**	Parameters:
34490792Sgshapiro**		fp -- file pointer for active file type
34590792Sgshapiro**		what -- type of information request
34690792Sgshapiro**		valp -- structure to place obtained info into
34790792Sgshapiro**
34890792Sgshapiro**	Returns:
34990792Sgshapiro**		-1 on error and sets errno:
35090792Sgshapiro**			- when valp==NULL and request expects otherwise
35190792Sgshapiro**			- when request is not SM_IO_WHAT_VECTORS and not
35290792Sgshapiro**				SM_IO_WHAT_TYPE and not SM_IO_WHAT_ISTYPE
35390792Sgshapiro**				and getinfo vector is NULL
35490792Sgshapiro**			- when getinfo type vector returns -1
35590792Sgshapiro**		>=0 on success
35690792Sgshapiro*/
35790792Sgshapiro
35890792Sgshapiroint
35990792Sgshapirosm_io_getinfo(fp, what, valp)
36090792Sgshapiro	SM_FILE_T *fp;
36190792Sgshapiro	int what;
36290792Sgshapiro	void *valp;
36390792Sgshapiro{
36490792Sgshapiro	SM_FILE_T *v = (SM_FILE_T *) valp;
36590792Sgshapiro
36690792Sgshapiro	SM_REQUIRE_ISA(fp, SmFileMagic);
36790792Sgshapiro
36890792Sgshapiro	switch (what)
36990792Sgshapiro	{
37090792Sgshapiro	  case SM_IO_WHAT_VECTORS:
37190792Sgshapiro
37290792Sgshapiro		/* This is the "generic" available for all */
37390792Sgshapiro		v->f_close = fp->f_close;
37490792Sgshapiro		v->f_read = fp->f_read;
37590792Sgshapiro		v->f_seek = fp->f_seek;
37690792Sgshapiro		v->f_write = fp->f_write;
37790792Sgshapiro		v->f_open = fp->f_open;
37890792Sgshapiro		v->f_setinfo = fp->f_setinfo;
37990792Sgshapiro		v->f_getinfo = fp->f_getinfo;
38090792Sgshapiro		v->f_type = fp->f_type;
38190792Sgshapiro		return 0;
38290792Sgshapiro
38390792Sgshapiro	  case SM_IO_WHAT_TYPE:
38490792Sgshapiro		if (valp == NULL)
38590792Sgshapiro		{
38690792Sgshapiro			errno = EINVAL;
38790792Sgshapiro			return -1;
38890792Sgshapiro		}
38990792Sgshapiro		valp = sm_strdup_x(fp->f_type);
39090792Sgshapiro		return 0;
39190792Sgshapiro
39290792Sgshapiro	  case SM_IO_WHAT_ISTYPE:
39390792Sgshapiro		if (valp == NULL)
39490792Sgshapiro		{
39590792Sgshapiro			errno = EINVAL;
39690792Sgshapiro			return -1;
39790792Sgshapiro		}
39890792Sgshapiro		return strcmp(fp->f_type, valp) == 0;
39990792Sgshapiro
40090792Sgshapiro	  case SM_IO_IS_READABLE:
40190792Sgshapiro
40290792Sgshapiro		/* if there is data in the buffer, it must be readable */
40390792Sgshapiro		if (fp->f_r > 0)
40490792Sgshapiro			return 1;
40590792Sgshapiro
40690792Sgshapiro		/* otherwise query the underlying file */
40790792Sgshapiro		break;
40890792Sgshapiro
40990792Sgshapiro	   case SM_IO_WHAT_TIMEOUT:
41090792Sgshapiro		*((int *) valp) = fp->f_timeout;
41190792Sgshapiro		return 0;
41290792Sgshapiro
41390792Sgshapiro	  case SM_IO_WHAT_FD:
41490792Sgshapiro		if (fp->f_file > -1)
41590792Sgshapiro			return fp->f_file;
41690792Sgshapiro
41790792Sgshapiro		/* try the file type specific getinfo to see if it knows */
41890792Sgshapiro		break;
41990792Sgshapiro	}
42090792Sgshapiro
42190792Sgshapiro	/* Otherwise the vector will check it out */
42290792Sgshapiro	if (fp->f_getinfo == NULL)
42390792Sgshapiro	{
42490792Sgshapiro		errno = EINVAL;
42590792Sgshapiro		return -1;
42690792Sgshapiro	}
42790792Sgshapiro	return (*fp->f_getinfo)(fp, what, valp);
42890792Sgshapiro}
429