The Process Environment


The process environment includes several key elements, which are explainedhere. The notable differences between these elements in Windows are also described briefly . This section discusses only POSIX.

Environment Variables

Every process has an environment block associated with it. An environment block is a block of memory allocated within the process s address space. Each block contains a set of name value pairs. Both UNIX and Windows support process environment blocks. The particular differences may vary depending on what supplier and version of UNIX you are dealing with. For information you can useto conduct your own comparison, see the MSDN article, Changing Environment Variables, at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/prothred_529f.asp

A summary of the notable differences between environment variables in Win32 and POSIX is also provided.

Differences Between POSIX and Win32 Environment Variables

Win32 supports an ANSI version of the environment functions as well as a Unicode variant. The Unicode variants are preceded by a _w prefix. Using the _w prefix in your application helps to ensure that the application is linked withthe correct variant when compiled with _UNICODE or _MBCS preprocessor strings. In addition to the ANSI functions putenv and getenv , Win32 also supports the GetEnvironmentVariable , ExpandEnvironmentStrings , and SetEnvironmentVariable functions. This example shows only the ANSI functions. Using the ANSI functions provides you with the simplest method of converting your code from UNIX to Win32.

The following is a simple example of accessing the environment block. This example works equally well in POSIX and Win32.

 #include <stdlib.h> #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) {     char *var, *value;     if(argc == 1  argc > 3) {         fprintf(stderr,"usage: environ var [value]\n");         exit(1);     }     var = argv[1];     value = getenv(var);     if(value)         printf("Variable %s has value %s\n", var, value);     else         printf("Variable %s has no value\n", var);     if(argc == 3) {         char *string;         value = argv[2];         string = (char *)malloc(strlen(var)+strlen(value)+2);         if(!string) {             fprintf(stderr,"out of memory\n");             exit(1);         }         strcpy(string,var);         strcat(string,"=");         strcat(string,value);         printf("Calling putenv with: %s\n",string);         if(putenv(string) != 0) {             fprintf(stderr,"putenv failed\n");             free(string);             exit(1);         }         value = getenv(var);         if(value)             printf("New value of %s is %s\n", var, value);         else             printf("New value of %s is null??\n", var);     }     exit(0);  } 

Temporary Files

Both UNIX and Win32 support functions that create temporary files. The following example works equally well in UNIX and Win32; no modifications are required.

The tmpnam() function returns a pointer to a temporary file name. The _tempname() function does this as well, but you can also use it to specify the directory and file name prefix.

 #include <stdlib.h> #include <stdio.h> int main() {     char tmpname[L_tmpnam];     char *filename;      FILE *tmpfp;     filename = tmpnam(tmpname);     printf("Temporary file name is: %s\n", filename);     tmpfp = tmpfile();     if(tmpfp) {         printf("Opened a temporary file OK\n"); exit(1); }     else {         perror("tmpfile"); exit(0); } } 

Computer Information

At times, it is necessary to obtain information about a computer. This is particularly important when an application is designed to support multiple users or different types of hardware and operating systems. Some of the pieces of information that applications require are:

  • The host name

  • The operating system name

  • The network name of the computer

  • The release level of the operating system

  • The version number of the operating system

  • The hardware platform name

In UNIX, you would use a combination of gethostname and uname functionsto obtain this information. When using Windows, you have the option of using gethostname, but uname is not available as standard in the Win32 API. It is possible to add uname using a POSIX layer. Applications that use this function need to be rewritten to use a different set of services.

The Platform SDK has functionality for obtaining a set of information similar to that provided by the uname function. The Platform SDK mappings are covered in this text, but it is recommended that you consider using the Windows Management Instrumentation (WMI) API. The WMI interface is a superset to the Win32API for obtaining information about the computer. It is highly extensible and supports not only static information about a platform, but also dynamic information such as configuration and performance data. Another source to consider is the Active Directory Services Interface (ADSI), a COM interface that facilitates access to information stored in Microsoft Active Directory directory-service database for the enterprise. Both of these interfaces represent the preferred mechanism for gathering information on Microsoft Windows 2000 and later computers and networks.

For a complete list of the system-information functions provided by the platform SDK, you can refer to the System Information Functions in the online platform SDK documentation. Two functions that are not used in the following Win32 example, but are also useful, are GetVersionEx and VerifyVersionInfo.

UNIX Example: Using System Information

 #include <unistd.h> #include <stdio.h> #include <sys/utsname.h> int main() {     char computer[256];     struct utsname uts;     if(gethostname(computer, 255) != 0  uname(&uts) < 0) {         fprintf(stderr, "Could not get host information\n");         exit(1);     }     printf("Computer host name is %s\n", computer);     printf("System is %s on %s hardware\n", uts.sysname, uts.machine);     printf("Nodename is %s\n", uts.nodename);     printf("Version is %s, %s\n", uts.release, uts.version);     exit(0); } 

Win32 Example: Using System Information

 #define _WIN32_WINNT 0X0500 #include <windows.h> #include <stdlib.h> #include <stdio.h> void errabt(char *msg) {     fprintf(stderr, msg);  // use GetLastError for more detailed info.     exit(1); } void main() {     DWORD nSize= 255;     char computer[256];     char nodename[256];     SYSTEM_INFO siSysInfo;      // Struct for hardware info     OSVERSIONINFO siVerInfo;    // Struct for version info          GetSystemInfo(&siSysInfo);  // Get hardware OEM     // Get major and minor number     ZeroMemory(&siVerInfo, sizeof(OSVERSIONINFO));     siVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);     if (!GetVersionEx((OSVERSIONINFO *) &siVerInfo))         errabt("Could not get OS Version info\n");     nSize = 255;     if (GetComputerNameEx(ComputerNameNetBIOS, computer, &nSize) == FALSE)         errabt("Could not get NETBIOS name of computer\n");            nSize = 255;     if (GetComputerNameEx(ComputerNameDnsFullyQualified, nodename, &nSize) == FALSE)         errabt("Could not get FQDNS Name of computer\n");              printf("Computer host name is %s\n", computer);     printf("System is %u on %u hardware\n",                    siVerInfo.dwMajorVersion,siSysInfo.dwProcessorType);     printf("Nodename is %s\n", nodename);     printf("Version is %d.%d %s (Build %d)\n",         siVerInfo.dwMajorVersion,         siVerInfo.dwMinorVersion,         siVerInfo.szCSDVersion,         siVerInfo.dwBuildNumber & 0xFFFF);     exit(0); } 

Logging System Messages

Logging diagnostic messages in UNIX, as in the following example, is carried outby writing formatted output to the system logger. The message is written to system log files such as USERS, or forwarded to the appropriate computer. If a log daemon process is not running, the log information may be written to a standard log file such as /var/adm/log/logger.

The daemon syslogd in UNIX contains numerous levels of logged information,as described in Table 9.17.

Table 9.17: UNIX Logging System Messages

Priority

Description

LOG_EMERG

A panic condition.

LOG_ALERT

A condition that should be corrected immediately.

LOG_CRIT

Critical conditions such as hard device errors.

LOG_ERR

Errors.

LOG_WARNING

Warnings.

LOG_NOTICE

Non error related conditions.

LOG_INFO

Informational messages.

LOG_DEBUG

Messages intended for debug purposes.

In contrast, the Windows Event Log also supports logging levels as described in Table 9.18.

Table 9.18: Windows Event Logging Messages

Priority

Description

EVENTLOG_SUCCESS

Information events indicate infrequent but significant successful operations. For example, when Microsoft SQL Server successfully loads, it may be appropriate to log an information event stating that SQL Server has started. Note that while this is appropriate behavior for major server services, it is generally inappropriate for a desktop application (Microsoft Excel, for example) to log an event each time it starts.

EVENTLOG_ERROR_TYPE

Error events indicate significant problems that the user should know about. Error events usually indicate a loss of functionality or data. For example, if a service cannot be loaded as the system boots, it can log an error event.

EVENTLOG_WARNING_TYPE

Warning events indicate problems that are not immediately significant, but that may indicate conditions that could cause future problems. Resource consumption is a good candidate for a warning event. For example, an application can log a warning event if disk space is low. If an application can recover from an event without loss of functionality or data, it will generally classify the event as a warning event.

EVENTLOG_INFORMATION_TYPE

Information events indicate infrequent but significant successful operations. For example, when SQL Server successfully loads,it may be appropriate to log an information event stating that SQL Server has started. Note that while this is appropriate behavior for major server services, it is generally inappropriate for a desktop application (Excel, for example) to log an event each time it starts.

EVENTLOG_AUDIT_SUCCESS

Success audit events are security events that occur whenan audited access attempt is successful. For example,a successful logon attempt is a successful audit event.

EVENTLOG_AUDIT_FAILURE

Failure audit events are security events that occur when an audited access attempt fails. For example, a failed attemptto open a file is a failure audit event.

As you may have observed , the Windows event logging mechanism supports a smaller selection of event priorities. You can augment the priority status of event messages by including category information and binary data in the event log.This additional event information is part of the Win32 example (following theUNIX example).

UNIX Example: System Logging

 #include <syslog.h> #include <stdio.h> int main() {     FILE *fp;     fp = fopen("Bad_File_Name","r");     if(!fp)         syslog(LOG_INFOLOG_USER,"error - %m\n");     exit(0); } 

On a typically configured Linux system, this message would be logged to /var/log/messages, on a Solaris system to /var/adm/messages, and on Interix (when syslogd in running) to /var/adm/log/messages. Consult the /etc/syslog.conf file for more specific information; specifically , a *.info entry will specify the file wherethe preceding message will be logged.

Win32 Example: System Logging

 #include <windows.h> #include <stdlib.h> void main() {     HANDLE h;     LPSTR mstr = "This is an error from my sample app.";       h = RegisterEventSource(NULL,  // uses local computer               TEXT("BILLSamplApp"));     // source name      if (h == NULL)          exit(1);        ReportEvent(h,                // event log handle              EVENTLOG_ERROR_TYPE,  // event type              0,                    // category zero              0,                    // event identifier              NULL,                 // no user security identifier              1,                    // one substitution string              0,                    // no data  (LPCSTR*)&mstr,       // pointer to string array              NULL);                // pointer to data        DeregisterEventSource(h);  exit(0); } 

In the preceding example, the source name to the RegisterEventSource call is not available in the system registry. As a result, you will not see valid mapping or lookup data when you view the event log with the event Viewer. After running this code, Eventvwr.exe should yield something similar to Figure 9.2.

click to expand
Figure 9.2: Windows Event Viewer

Double-clicking the error line opens a detailed view of the event (see Figure 9.3).

click to expand
Figure 9.3: Details of an event in Windows Event Viewer

The preceding is a very simple example of generating log information and postingit to the Windows Event log. A complete application would use more of the Platform SDK facilities to create an application entry in the registry or perhaps create an entirely separate event log file. For a complete discussion of the details and complexitiesof event logging in Windows, see Event Logging on the MSDN Web site.




UNIX Application Migration Guide
Unix Application Migration Guide (Patterns & Practices)
ISBN: 0735618380
EAN: 2147483647
Year: 2003
Pages: 134

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net