1 /*****
2  ** ** Module Header ******************************************************* **
3  ** 									     **
4  **   Modules Revision 3.0						     **
5  **   Providing a flexible user environment				     **
6  ** 									     **
7  **   File:		cmdUname.c					     **
8  **   First Edition:	1991/10/23					     **
9  ** 									     **
10  **   Authors:	John Furlan, jlf@behere.com				     **
11  **		Jens Hamisch, jens@Strawberry.COM			     **
12  ** 									     **
13  **   Description:	Provides fast aquisition of the information available**
14  **			via uname.  This shows a 10x improvement over having **
15  **			to exec the actual uname program from within a	     **
16  **			modulefile.					     **
17  ** 									     **
18  **   Exports:		cmdUname					     **
19  ** 									     **
20  **   Notes:								     **
21  ** 									     **
22  ** ************************************************************************ **
23  ****/
24 
25 /** ** Copyright *********************************************************** **
26  ** 									     **
27  ** Copyright 1991-1994 by John L. Furlan.                      	     **
28  ** see LICENSE.GPL, which must be provided, for details		     **
29  ** 									     **
30  ** ************************************************************************ **/
31 
32 static char Id[] = "@(#)$Id: 986c78c90605e7e69e905b4bdd447fe724954a3d $";
33 static void *UseId[] = { &UseId, Id };
34 
35 /** ************************************************************************ **/
36 /** 				      HEADERS				     **/
37 /** ************************************************************************ **/
38 
39 #include "modules_def.h"
40 
41 #ifdef HAVE_UNAME
42 #include <sys/utsname.h>
43 #endif
44 
45 /** ************************************************************************ **/
46 /** 				  LOCAL DATATYPES			     **/
47 /** ************************************************************************ **/
48 
49 #ifndef HAVE_UNAME
50 
51 typedef	struct	utsname {
52 	char	sysname[ NAMELEN];	/** System name			     **/
53 	char	nodename[ NAMELEN];	/** Node name			     **/
54 	char	release[ NAMELEN];	/** OS Release			     **/
55 	char	version[ NAMELEN];	/** OS Version			     **/
56 	char	machine[ NAMELEN];	/** Machine type		     **/
57 } UTS_NAME;
58 
59 #endif
60 
61 /** ************************************************************************ **/
62 /** 				     CONSTANTS				     **/
63 /** ************************************************************************ **/
64 
65 /** not applicable **/
66 
67 /** ************************************************************************ **/
68 /**				      MACROS				     **/
69 /** ************************************************************************ **/
70 
71 #define	NAMELEN		(8 + 1)		/** 8 chars + 1 terminator	     **/
72 #define	DOMAINLEN	(64 + 1)	/** 8 chars + 1 terminator	     **/
73 
74 /** ************************************************************************ **/
75 /** 				    LOCAL DATA				     **/
76 /** ************************************************************************ **/
77 
78 static	char	module_name[] = "cmdUname.c";	/** File name of this module **/
79 
80 #if WITH_DEBUGGING_CALLBACK
81 static	char	_proc_cmdUname[] = "cmdUname";
82 #endif
83 
84 static	struct	utsname	 namestruct = {
85 	UNAME_SYSNAME, UNAME_NODENAME, UNAME_RELEASE, UNAME_VERSION,
86 	UNAME_MACHINE
87 };
88 
89 static	char	domain[ DOMAINLEN] = UNAME_DOMAIN;
90 
91 static	int	namestruct_init = 0;
92 
93 /** ************************************************************************ **/
94 /**				    PROTOTYPES				     **/
95 /** ************************************************************************ **/
96 
97 /** not applicable **/
98 
99 
100 /*++++
101  ** ** Function-Header ***************************************************** **
102  ** 									     **
103  **   Function:		cmdUname					     **
104  ** 									     **
105  **   Description:	Callback function for  the commands 'sysname',	     **
106  **			'nodename', 'release', 'version' and 'machine'       **
107  ** 									     **
108  **   First Edition:	1991/10/23					     **
109  ** 									     **
110  **   Parameters:	ClientData	 client_data			     **
111  **			Tcl_Interp	*interp		According Tcl interp.**
112  **			int		 argc		Number of arguments  **
113  **			char		*argv[]		Argument array	     **
114  ** 									     **
115  **   Result:		int	TCL_OK		Successful completion	     **
116  **				TCL_ERROR	Any error		     **
117  ** 									     **
118  **   Attached Globals:	flags		These are set up accordingly before  **
119  **					this function is called in order to  **
120  **					control everything		     **
121  ** 									     **
122  ** ************************************************************************ **
123  ++++*/
124 
cmdUname(ClientData client_data,Tcl_Interp * interp,int argc,CONST84 char * argv[])125 int	cmdUname(	ClientData	 client_data,
126 	  		Tcl_Interp	*interp,
127 	  		int		 argc,
128 	  		CONST84 char	*argv[])
129 {
130     int  length;
131 #ifdef PHOSTNAME
132 #ifndef HAVE_GETHOSTNAME
133     FILE* hname;
134 #endif
135 #endif
136 
137 #if WITH_DEBUGGING_CALLBACK
138     ErrorLogger( NO_ERR_START, LOC, _proc_cmdUname, NULL);
139 #endif
140 
141     /**
142      **  Parameter check. One parameter should be given providing a selector
143      **  do differ between:
144      **/
145 
146     if( argc != 2) {
147 	if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], "member", NULL))
148 	    return( TCL_ERROR);		/** -------- EXIT (FAILURE) -------> **/
149     }
150 
151 #ifdef HAVE_UNAME
152 
153     /**
154      **  Proceed the system call
155      **/
156 
157     if( !namestruct_init && uname( &namestruct) < 0) {
158 	if( OK != ErrorLogger( ERR_UNAME, LOC, NULL))
159 	    return( TCL_ERROR);		/** -------- EXIT (FAILURE) -------> **/
160     }
161 
162 #else /* not HAVE_UNAME */
163 
164     /**
165      **  If we do not have the uname system call, fixed values defined
166      **  at compile time will be returned. The only differenc is the
167      **  nodename, which may be seeked for using 'gethostname' or the
168      **  PHOSTNAME file.
169      **/
170 
171 #ifdef HAVE_GETHOSTNAME
172 
173     if( -1 == gethostname( namestruct.nodename, NAMELEN))
174 	if( OK != ErrorLogger( ERR_GETHOSTNAME, LOC, NULL))
175 	    return( TCL_ERROR);		/** -------- EXIT (FAILURE) -------> **/
176 
177 #else /* not HAVE_GETHOSTNAME */
178 
179 #ifdef PHOSTNAME
180 
181     if( NULL == (hname = popen( PHOSTNAME, "r"))) {
182 	if( OK != ErrorLogger( ERR_POPEN, LOC, PHOSTNAME, "reading", NULL))
183 	    return( TCL_ERROR);		/** -------- EXIT (FAILURE) -------> **/
184     }
185 
186     fgets( namestruct.nodename, NAMELEN, hname);
187     namestruct.nodename[ strlen( namestruct.nodename)-1] = '\0';
188 
189     if( -1 == pclose( hname))
190 	if( OK != ErrorLogger( ERR_PCLOSE, LOC, PHOSTNAME, NULL))
191 	    return( TCL_ERROR);		/** -------- EXIT (FAILURE) -------> **/
192 
193 #endif /* not PHOSTNAME */
194 #endif /* not HAVE_GETHOSTNAME */
195 
196 #endif /* not HAVE_UNAME */
197 
198     /**
199      **  Set up the domain name
200      **/
201 
202 #ifdef HAVE_GETDOMAINNAME
203     if( !namestruct_init)
204         if( -1 == getdomainname( domain, DOMAINLEN))
205 	    if( OK != ErrorLogger( ERR_GETDOMAINNAME, LOC, NULL))
206 		return( TCL_ERROR);	/** -------- EXIT (FAILURE) -------> **/
207 #endif
208 
209     /**
210      **  Now the name structure surely IS initialized
211      **/
212 
213     namestruct_init = 1;
214 
215     /**
216      **  Return the selected value
217      **/
218 
219     length = strlen( argv[1]);
220 
221     if( !strncmp( argv[1], "sysname", length)) {
222         Tcl_SetResult( interp, namestruct.sysname, TCL_VOLATILE);
223     } else if( !strncmp( argv[1], "nodename", length)) {
224         Tcl_SetResult( interp, namestruct.nodename, TCL_VOLATILE);
225     } else if( !strncmp( argv[1], "release", length)) {
226         Tcl_SetResult( interp, namestruct.release, TCL_VOLATILE);
227     } else if( !strncmp( argv[1], "version", length)) {
228         Tcl_SetResult( interp, namestruct.version, TCL_VOLATILE);
229     } else if( !strncmp( argv[1], "machine", length)) {
230         Tcl_SetResult( interp, namestruct.machine, TCL_VOLATILE);
231     } else if( !strncmp( argv[1], "domain", length)) {
232         Tcl_SetResult( interp, domain, TCL_VOLATILE);
233     } else {
234 	if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], "{sysname|nodename|"
235 	    "release|version|machine|domain}", NULL))
236 	    return( TCL_ERROR);		/** -------- EXIT (FAILURE) -------> **/
237     }
238 
239 #if WITH_DEBUGGING_CALLBACK
240     ErrorLogger( NO_ERR_END, LOC, _proc_cmdUname, NULL);
241 #endif
242 
243     return( TCL_OK);			/** -------- EXIT (SUCCESS) -------> **/
244 
245 } /** End of 'cmdUname' **/
246