Linux to Windows Migration

Linux to Windows 2000 Scripting Portability

By S. Caraveo, J. Hobbs, P. Prescod, G. Sarathy

ActiveState Corporation

Abstract

This white paper discusses issues involved with porting your Perl, Python, Tcl, and PHP scripts from the Linux environment to Microsoft Windows 2000, with a focus on Web-based CGI applications and services. While we address four scripting languages specifically in our examples, many issues presented in this paper are common across languages and can be applied to most, if not all, of them. We will first discuss general issues and differences of the platforms and porting scripts, and then we will discuss language-specific issues and examples. This paper is intended for developers familiar with script-based development.

On This Page

Acknowledgements
Glossary
Introduction
Fundamental Platform Differences
Platform Integration
Language Notes: Tcl
Language Notes: Perl
Language Notes: Python
Language Notes: PHP
Other Resources and References

Acknowledgements

Shane Caraveo, Senior Developer, ActiveState, ported PHP3 to Windows

Jeff Hobbs, Senior Developer, ActiveState, Tcl Core Release Manager

Paul Prescod, Senior Developer, ActiveState, Co-author The XML Handbook

Gurusamy Sarathy, Senior Developer, ActiveState, Release Manager for Perl 5.005/5.6, Perl to Windows port

Glossary

This is a glossary of common terms in the Windows environment to be discussed in this paper that you may not be familiar with. The terms are defined in the order in which they first appear in the paper.

**Remote Procedure Call (RPC):**A protocol that allows a program on one computer to execute a program on a server computer. Using RPC, a system developer need not develop specific procedures for the server. The client program sends a message to the server with appropriate arguments and the server returns a message containing the results of the program executed.

**Simple Object Access Protocol (SOAP):**SOAP provides a way for applications to communicate with each other over the Internet in a platform-independent manner. It relies on a simple XML over HTTP solution for communication.

**Internet Information Server (IIS):**Microsoft's brand of Web server software, utilizing Hypertext Transfer Protocol to deliver World Wide Web documents. It incorporates various functions for security, allows for CGI programs, and also provides for Gopher and FTP servers.

**Common Gateway Interface (CGI):**A specification for transferring information between a Web server and a CGI program. A CGI program is any program designed to accept and return data that conforms to the CGI specification. The program could be written in any programming language.

**Lightweight Directory Access Protocol (LDAP):**A set of protocols for accessing information directories. LDAP is based on the standards contained within the X.500 standard, but is significantly simpler. LDAP supports TCP/IP, allowing for any type of Internet access. It is commonly used for address books and in user authentication.

**Structured Query Language (SQL):**A standardized query language for requesting information from a database.

**Secure Sockets Layer (SSL):**A protocol for transmitting private documents via the Internet. SSL works by using a public key to encrypt data that's transferred over the SSL connection.

**Active Server Pages (ASP):**A specification for a dynamically created Web page that utilizes ActiveX scripting. ASP pages are similar to CGI scripts, except they are usually written in VB Script or Jscript. However, they can be written in any language that can act as an ActiveX scripting host.

Introduction

Scripting languages tend to be more portable than compiled languages such as C/C++, and often require few or no changes to run properly on new platforms. However, even with scripting languages, cross-platform compatibility can be an issue. Ideally, the language would handle all platform specifics for you; in reality, some things are easier or faster to script when using platform-specific features, or cross-platform compatibility was not taken into consideration when the script was originally written. One thing to remember is that the first port is always the hardest; with every script you port, the process becomes easier.

Before you port, you should consider the necessity of porting your software to a new platform. Does the program belong on the new platform? Is the change of platform an occasion to rewrite? Is there a "quick and dirty" port that can be done now, with a rewrite later? Do you understand the original code enough to quickly locate the issues, and make the changes necessary to port to a new platform? Are there "show stoppers" to the port? Read this paper before you start, as it will hopefully help you answer some of these questions and plan the migration.

When it comes to porting any type of program from one platform to another, you need a firm grasp of the differences between the operating systems to identify potential problems for portability. To identify some possible problem areas, ask yourself:

Do the scripts

interact with other programs or external libraries?

use file I/O?

access system devices (modems, printers, and so on)?

fork or spawn threads?

communicate via sockets?

use signals, IPC or spawn other executables?

generate graphical user interfaces?

use security features of the platform?

These are some of the areas where Linux and Windows systems can differ significantly. Scripting languages abstract differences between platforms to ease - or even do away with - portability issues, but even a simple file access can create a portability issue if it was written for specific paths. The level of portability will depend on how your scripts are written, for what purpose, and what features the scripting language supports. Over time, scripting languages have significantly improved platform independence. If you are running an old version of your scripting language, simply upgrading to a current version may solve some portability issues for you, or at least provide portable methods that can be used to replace nonportable code. This paper discusses how to address the above issues, focusing on the higher-level scripting languages Tcl, Perl, Python and PHP. While this paper discusses porting from Linux to Windows 2000, the same concepts apply for porting from most UNIX-based systems.

Many scripting languages have been developed with consideration for cross-platform portability. When porting your scripts from Linux to Windows 2000, you will not need to worry about many of the issues you would face porting programs developed in lower-level languages. For instance, you generally do not need to worry about compiler configurations and bugs, memory issues, system libraries, component models, and other system-level details. Scripting languages effectively deal with those issues for you.

The real work of moving scripts to a new platform begins before you move even the first script over to the new platform. You need to analyze your needs and define a process to guide you through your porting your scripts. Several basic processes include:

  • Identifying software requirements and making sure they are available on the new platform.

  • Developing test procedures for each application, module and script that will be ported.

  • Testing software, scripting engines, and so on, prior to moving scripts to the new system.

  • Moving files from a Linux system to the Windows system.

  • Identifying and fixing problem areas in the code.

  • Testing, Testing, Testing!

You will want to move your scripts over in a controlled fashion, perhaps moving one "module" at a time, and testing it thoroughly with the procedures and test suites you have developed. Porting small amounts of your scripts at a time can often be more manageable. You should also become familiar with tools and utilities available on the new platform to aid you in the process of porting. There are large libraries of free and evaluation software available on the Internet, such as the collection available at https://www.winfiles.com/. Many Linux applications and utilities are available, but in some instances you may need to find a Windows replacement for software that has not been ported.

Using editors that are already cross-platform may greatly help your porting efforts. There are several free editing environments that are available on both platforms, such as Emacs and Vi. Commercial software is also available, such as ActiveState's Komodo IDE, which provides cross-platform editing and debugging support for many languages, including Perl, Python, PHP and Tcl. See the reference information for software links.

Fundamental Platform Differences

When porting scripts, there are some inevitable fundamental differences that will likely need to be handled with conditional code. Each language will have its own way of indicating the current platform, as well as handling the issues in its own manner. As issues are discussed, footnotes to the appendixes are provided for you to obtain the language specific solution to the problem. Each language has a separate appendix with identically numbered footnotes for easy cross-reference. The red footnote markers indicated as numbers in brackets (like [#]) indicate a reference to the language specific sections. Refer now to [1] for determining the current platform in your language.

File System and Environment

The most likely difference between Linux and Windows systems that will have to be accounted for is interaction with the file system. On Linux, the path separator is '/', whereas Windows uses '\'. Furthermore, all files in Linux are rooted at '/', but Windows has the locally mounted drives (denoted with '[A-Z]:\') and network accessible drives (i.e. \\servername\sharepoint\dir\).

The first thing to correct in any program is any reference to hard-coded file paths. These are commonly used to find initialization or configuration files. One frequently made mistake when doing initial porting work is to refer to a Windows file in native form. The problem is that '\' is also the common escape character, and specifying a path like:

"C:\dir\text.txt"

will be translated as (the white space is a single tab character):

"C:dir ext.txt"

In most cases, Windows is also able to handle the Linux '/' as a path separator, but languages have a way of gleaning the correct file path separator or methods to build up pathnames in a cross-platform manner [2]. It is also important to note that Windows file systems are not case sensitive. They may preserve the case of files you create, but you cannot create separate files named file.txt and FILE.txt in the same directory as is possible on Linux. It is also not possible on Windows to create in the same directory a file and directory with the same name.

If you do happen to require the hard coding of some paths in your script, remember that certain directories on Windows will change depending on the type of installation. For example, the "standard" directory "C:/Program Files/" is "C:/Programme/" on a machine installed with the German version of Windows. The exact names for such paths and other information that may be critical in porting your code are often found in the Windows registry [3]. For example, the correct path for the Program Files directory can be found in the key HKEY_LOCAL_MACHINE \SOFTWARE \Microsoft \Windows \CurrentVersion \ProgramFilesDir. While the registry may not seem pertinent to cross-platform programming, it is a centralize database of information about your Windows system. The registry contains a wealth of information about the Windows system, and must often be referred to when other platform-independent methods are not available. You can peruse the Windows registry to get a feel for the basic structure by running the regedit command. Some of this information is available using language APIs, which should be preferred when available.

Windows also implicitly locks files that are in use, so it is important to make sure that you close files that are in use before attempting to delete them.

Another commonly used mechanism is the environment array. Windows also maintains an environment array, but do not expect any similarity in the contents [4]. The Windows environment array is also not case-sensitive, so the keys "PATH", "path" and "PaTh" all refer to the same item. One of the keys that can be relied on is PATH, but on Windows it is separated by a semicolon (;), whereas Linux uses a colon (:). Again, the language usually helps in abstracting PATH handling [5].

Commonly used Linux environment variables are HOME, PATH, USER, and sometimes TEMP. Windows will also have the PATH and TEMP variables, and may have the others. Your language may provide abstractions to get the same information, or you can access the Windows registry for this information. To see the full contents of the environment, select the Properties option of "My Computer". Under the Advanced notebook tab, you will see the "Environment Variables" button. When selecting this, you will have the dialog which allows you to view and modify the environment. Note that Windows has separate User and System environments. You must have administrator privileges to modify the System environment.

Scripts commonly require a temporary data file, which is usually hard-coded to reside in /tmp on Linux. On Windows, use the TEMP environment variable instead to refer to an acceptable temporary file directory. Your scripts may also rely on the environment variables beginning with LC_, which indicate the locale information for that system. See the localization notes later inOther Issuesfor more information on acquiring such information when porting.

Do not expect files to always be the same at the binary level either. Windows uses CRLF (carriage return / linefeed or characters \015\012) at the end of a line as opposed to only LF on Linux. The language provides methods for handling this in a transparent manner [6]. Another nuance is that ^Z (character \032) represents the end of file character. This can be useful, but when a Linux script happens to have one of these embedded in code it may just ignore it, whereas Windows may stop reading the file at that point [7].

Shell and Console

The Linux console shell is an omnipresent facet of the Linux desktop. Windows provides a command shell as well (on Windows 2000 the path to the shell is found in the COMSPEC key of the environment array). You will likely interact with this in your language testing, but you may find that it interferes or does not otherwise act as expected during the normal operation of your script. Some languages also have ways of running without any attachment to a console, or specifically connecting to it, depending on your needs. Refer to the language specifics for how to make the console behave as required [8].

Oftentimes people resort to calling the shell to reuse existing commands. Relying on the shell is not recommended, as it not only wastes processing power with the external process execution overhead, but it is also highly nonportable. It is possible to obtain the Bourne shell for Windows (via Microsoft Interix or other similar toolkit), but it is better to rely on the methods that the language provides to avoid any portability issues [9]. If you are trying to port a build system from Linux to Windows, toolsets like Interix contains much more than a port of the Bourne shell. Most of the tools needed for replicating a Linux build system on Windows (autoconf, m4, sh, make) are available in these systems. In fact, Interix contains over 300 familiar UNIX commands ported for Windows. Also note that invoking commands via the shell always does file globbing automatically, so if you were relying on this behavior, make sure to use the language methods for file globbing to expand filenames.

In case it is unavoidable to call the shell, it is important to note that the Windows command shell has different native commands and quoting rules. See the "Windows 2000 commands" section in Windows Help for a detailed command listing.

Process and Thread Execution

A common model on Linux is to take advantage of standard external programs to prevent rewriting the same functionality in your scripts. While many of the standard Linux tools can be obtained for Windows, they are not standard on Windows. The use of any external system calls must be examined for portability potential. It is unlikely that any system calls will port straight across. Many common system calls can be replaced with methods provided by the language or an associated extension [10]. The list of external commands is infinite, but often so are the capabilities of your language. Always make sure to read the full language documentation in order not to overlook simple language methods that replace the need for external commands.

You may also have to deal with process manipulation, especially in the event that the need for external system calls is unavoidable. If your language supports process manipulation, the features are usually portable to Windows 2000 [11]. However, all use of process manipulation should be evaluated to ensure that the correct processes are being manipulated on Windows.

Managing process by passing signals is common on Linux, especially for daemon processes and system administration tasks. Signal handling, where handled by the language, is similar to process manipulation. Some uses of signal handling are portable from Linux to Windows 2000, but not all signals are relevant [12]. Windows uses an event passing model, and if you are porting a Linux daemon process to Windows, it will need to respond to these events. If you need to port a Linux daemon on Windows, you want to create a Windows "service", which provides essentially the same functionality.

If you have made use of the fork command in your scripts, it is important to note that this can have different behavior on Windows, depending on the language [13]. If you have made use of fork in a Web application, it is highly recommended that you look at alternative techniques for achieving the same result on Windows. The best solution is to switch to using threads.

Programming with threads has become more prevalent in the last few years. Threads on Windows use an entirely different model, and are generally "lighter-weight" in comparison with most UNIX operating systems, notably Linux. If your language has thread support, it likely has an abstracted thread layer, but it may have several thread extensions. Refer to the language notes for the specifics of using threads across platforms and an understanding of what defines a "thread" for the language [14].

Device and Network Programming

Many applications built today use a client/server model, or have some requirement on network or inter-process communications (HTTP, TCP/IP, UDP, and so on). Scripting languages provide varying levels of abstraction over the standard system mechanism for communicating with files and sockets. Some of these will be more portable than others [15], so it is important to examine socket handling when porting code. Other methods for inter-process communication outside of socket programming or communicating via a pipe are normally non-portable and should be avoided [16]. A well-known remote procedure call (RPC) mechanism that works well across platforms and fits well into Web server applications is Simple Object Access Protocol (SOAP), which most scripting languages already support [17].

If your application communicates with the serial port or other system device, the protocol for interacting with the device may be the same, but often addressing the device changes. For example, a serial device on Linux may be addressed as the special file /dev/ttya, whereas this would be COM1: on Windows.

User Interfaces

Many scripting languages have access to one or more graphical user interface (GUI) toolkits. If your script has a GUI, it is important to determine the portability of that toolkit across platforms [18]. Interix, the UNIX portability layer, provides a port of the curses terminal user interface library.

Tk is a GUI toolkit that is common to Tcl, Perl and Python (called Tkinter) and is fully cross-platform compatible between Linux and Windows. Some of the finer points of cursor and font handling can vary between these systems due to underlying operating system differences. See the reference information for links to the Tk documentation and usage FAQs that details how to avoid any cross-platform pitfalls with Tk.

Other Issues

One would think that dates and time are universal. That may be true, but the handling and interpretation of them is not. The epoch on Windows began on 1970-01-01 00:00:00 UTC, which is the same as Linux. The language provides abstractions to time and date handling [19], but it is important to note that not all of these methods are cross-platform.

Another possible issue to be aware of is the varying endianness between machines. If this is the first time you are porting an application to any other architecture and you store numeric or other multibyte data, you may encounter endianness issues. The Intel IA-64 and x86 family of CPUs are little-endian, whereas CPUs common for certain Linux hardware platforms like the PowerPC and Sparc CPUs are big-endian. This means a number stored as 0x12345678 on a Sparc CPU will be viewed as 0x78563412 on an x86 CPU (note the swapped order). The language provides general techniques and methods for avoiding getting caught in the endian trap [20].

Many system administrators find themselves dealing with systems users and groups. The Windows security model differs from the Linux model, but the concept of users and groups still exists. Refer to the language notes for details on how to access this information on Windows [21].

If your script tries to work with Unicode, and perhaps even when it doesn't, it is important to note that Windows 2000 is a fully Unicode-aware operating system. There may be instances where calls to Windows functions will return a Unicode string that the language must handle correctly. It is not within the scope of this paper to discuss the full realm of internationalization issues; refer to the language notes [22] for some pointers on avoiding certain gotchas that can arise from the use of Unicode, or the need to be aware of it.

In addition to internationalization, localization is often an issue that scriptwriters have had to deal with. On Linux, this information is stored in the environment variable LANG and those beginning with LC_ (i.e. LC_ALL, LC_COLLATE, LC_TIME, and so on). Windows handles locale and localization differently, but where necessary the language likely provides the necessary abstraction techniques and methods to handle this [23].

In addition to all the above notable issues, there are numerous popular extensions that make use of specific features of an operating system (they may be Linux specific or general to UNIX) that will not be directly portable to Windows. While it is not possible to account for them all, we want to address some of the most popular ones, and give pointers on porting code written with them [24].

Platform Integration

Many people porting scripts from Linux to Windows will be doing so to use Internet Information Service (IIS) 5.0, the primary Internet server for Windows. These scripts are generally run as Common Gateway Interface (CGI) scripts, or sometimes with a languages Web server plug-in. Porting CGI scripts to Windows is just like porting other types of scripts, with a few added issues you will need to pay attention to. For porting of CGI applications written in C/C++, many of the issues discussed in this paper apply equally well.

In addition to porting your scripts you will also have to consider the services and applications that your scripts may use. While simple scripts may simply run, if your applications use any services outside the scripting language, you will need to provide those services on Windows. This may be as simple as installing a Windows version of those applications onto your Windows server - or it may be as involved as changing parts of your scripts to use services available under Windows, or actually porting those applications to Windows. Many Linux programs have already been ported to Windows.

Scripting Language Engines

Most major scripting languages are available on Windows. You will need to download and install any language engines your scripts will require. Binaries for the languages this white paper covers are available at the following locations:

You should download and install any necessary languages, and test them with simple scripts before you begin porting your scripts to Windows. If you are porting scripts to run under a Web server, test some sample scripts you know will run under the new Web server prior to beginning your porting work.

CGI Scripts and Applications

The CGI protocol is the standard interface used by Web servers to execute programs and scripts that handle dynamic content. Any language can be used as a CGI language if it supports reading and writing STDOUT and STDIN console handles, and chances are that many of your scripts will be CGI-based. In recent years, many Web server plug-ins have been written for scripting languages to work around performance limitations in CGI, though using these plug-ins sometimes requires minor changes to the CGI script itself. We suggest you utilize the Web server plug-ins for your languages if they are available. Apache has direct language plug-ins for Perl (mod_perl), PHP (mod_php) and Tcl (mod_tcl). Through the Internet Server API (ISAPI), IIS has a direct language plug-in for Perl called PerlEx. The other languages can be used via CGI. You can find more information about these here:

For the most part, you should not need to worry about CGI portability issues - since CGI is a standardized interface available under all major Web servers - as long as you follow installation guidelines for the language you are working with.

Web Server Portability

One of the biggest changes that will occur in moving Web scripts from Linux to Windows will be the Web server your scripts run under. The most common Web server on Linux is Apache, on Windows, IIS. You can always use the Apache Windows NT port, but at the time of this writing the Windows port is not considered to be up-to-par with the Linux versions. While there are many differences, both Web servers are quite feature-rich and extendable. The following links provide in-depth information into web server specifics outside of the scope of porting scripting languages:

The security models of IIS and Apache differ significantly. Apache's default security model (htaccess) uses text files to describe users and groups. IIS integrates its security with the operating system's security model, using the NTFS access control lists. If you want to use the security features of IIS, you will have to port your users and groups over to Windows to gain effective security. Some applications may use LDAP, SQL databases, or other technologies for defining user security. These can often easily be ported over to Windows to allow your scripts to continue using the same security methods they were originally written for, but you will need to be very careful with this since IIS relies on Windows security for its security. Overriding the default security mechanism of IIS may require writing a custom filter extension for IIS. Some custom filters are available commercially, such as newObjects ISAPI Authenticator, which provides authentication more similar to that of Apache's. Good references for Web server security information are:

If you use SSL (Secure Socket Layers) on your Linux Web server, you may need to obtain a new certificate compatible with IIS. Apache on Linux will generally use code from the OpenSSL project. You can consult the OpenSSL documentation to see if you can move your certificate over to IIS. You may also need to adjust some code in your scripts if they are written to use any SSL environment variables. Typically, under Apache, mod_ssl is used. Mod_ssl provides several environment variables that describe the SSL connection that are not available under IIS; however, what IIS does provide should be suitable for any application. For more information on SSL specifics, see:

There are other small differences in Web server operations that can cause problems in some application designs. For instance, under Apache you can set a cookie and redirect the browser to another URL within the same response. IIS appears to strip out the cookie header and send the headers to handle the redirect. Some Web applications may also depend on features implemented in other server extensions, many of which are not available under both Web servers. If your scripts depend on the operation of certain server extensions, you will need to port those extensions, or make the necessary changes to your scripts.

While Microsoft's primary scripting technology under IIS is Active Server Pages (ASP), it takes longer to port scripts to ASP than to simply port your scripts to work under IIS using CGI.

System Services (Database Servers, Email Servers, etc.)

Most Web applications communicate with and use many other types of system services, such as SQL database servers, LDAP, e-mail servers and much more. Successfully porting your scripts involves making these services available under Windows, converting them to use Windows services that provide the same or similar functionality, or running additional Linux-based servers on the network. Most popular services are available on both platforms, which will simplify porting your scripts.

Some scripting languages depend on external programs for various services, such as sending email, though most now provide platform-independent ways of sending messages. Sendmail is one of the most popular programs for e-mail delivery under Linux and is not distributed with Windows, though a commercial Windows Sendmail port is available. There are also several open source e-mail delivery programs that could be used in place of Sendmail, such as Blat or wSendmail. These utilities have different command-line options than Sendmail under Linux, but a few simple modifications will make your scripts work with them. You can obtain more information on the mail tools at one of the following URLs:

If your application absolutely depends on a Linux-based program, and changing your script is not an option, you might find porting your Linux-based program fairly easy with Microsoft's Interix tools. These tools are a collection of popular Linux utilities and development tools ported to the Windows platform. While this solution offers the ability to quickly port some of your more Linux-specific scripts, you will want to eventually finish a complete port using Windows utilities to provide better platform integration.

Language Notes: Tcl

[1] Determining platform:

Use the global tcl_platform array to obtain platform information. This contains the key platform that can have the value windows, unix or macintosh. See the special Tcl variables documentation at https://aspn.activestate.com/ASPN/Products/ActiveTcl/ActiveTcl8.4.1.0-html/tcl/TclCmd/tclvars.htm for details.

[2] Handling paths across platforms:

Tcl understands the use of '/' as the platform separator equally well across Windows and Linux. The best way to build up or split paths across platforms is to use 'file join' and 'file split'. The 'file' command contains numerous methods for cross-platform handling of paths. See https://aspn.activestate.com/ASPN/Products/ActiveTcl/ActiveTcl8.4.1.0-html/tcl/TclCmd/file.htm for details.

[3] Accessing the registry:

Use the 'registry' module (via 'package require registry') to access the Windows registry. This is part of the Tcl core on Windows. For example, to get the Program Files directory location, the code is:

package require registry 
set dir [registry get \ 
{HKEY_LOCAL_MACHINE \SOFTWARE \Microsoft \Windows \CurrentVersion} \ 
ProgramFilesDir]

See https://aspn.activestate.com/ASPN/Products/ActiveTcl/ActiveTcl8.4.1.0-html/tcl/TclCmd/registry.htm for details.

[4] The environment:

The environment is maintained in the global 'env' array. Changes made to this array will affect the current process and be propagated to child processes, but not the parent. If you use multiple interpreters in the same Tcl processes, they all share this array, even across threads. Keys of this array are case-sensitive on Linux, but not Windows. You can rely on the PATH and USER keys to be set; all other keys are inherited from the parent process's environment. On Windows, the 'env' array has the special characteristic of removing elements for which the value is the empty string. This is a feature you'll find reflected by the DOS shell.

[5] Handling the path:

The 'exec' command will launch applications that it finds anywhere on your path on either Linux of Windows. Tcl provides the 'auto_execok' command to walk the path, trying to find an executable on the system (similar to 'where' in the Linux shell). It returns the empty string when it cannot find the named executable on your path.

[6] EOL handling:

Tcl attempts to auto-detect the line ending of files being read, and uses the system line ending by default when outputting data. Internally, all data will simply have one LF (\n) character to represent the end of the line. You can force a particular line ending for input or output using the fconfigure command's translation option. See https://aspn.activestate.com/ASPN/Products/ActiveTcl/ActiveTcl8.4.1.0-html/tcl/TclCmd/fconfigure.htm for details.

[7] EOF handling:

Tcl uses the system end-of-file character by default, but you can force another character for input or output using the fconfigure command's eofchar option. If you set the translation option to binary, then the behavior is the same as for Linux.

[8] Console handling:

The tclsh executable is a console application under both Linux and Windows, and has access to the three standard handles associated with console I/O, namely, stdin, stdout, and stderr. The wish executable, which includes the Tk UI toolkit extension, is also a console application on Linux, but on it is a GUI (i.e. non-console) executable that does not require an associated console to run and does not have access to the standard handles. If you wish to have access to the console channels when running wish, you can run it from the MS-DOS console with input and output pipes.

[9] Replacing standard shell commands:

Simple commands like date can be replaced with the Tcl core clock command. Other commands are available in the standard Tcl library [https://tcllib.sf.net/] or the TclX extension [https://sf.net/projects/tclx/]. Use the glob command when you need file pathname expansion. If you must run a Windows console command, the location of the Windows console is in the variable $::env(COMSPEC).

[10] Replacing standard system commands:

See [9]

[11] Process manipulation:

Process creation code is portable in Tcl, as are the core Tcl process handling commands. The kill command is part of the TclX extension and is portable to Windows as well.

[12] Signal handling:

Signal handling is provided by the Expect [https://expect.nist.gov/] and TclX extensions. Only TclX provides cross-platform handling of signals. If you wish to handle Windows service events, you will need the tclsvc extension [https://www.sensus.org/tcl/].

[13] Fork:

The fork command provided by the TclX extension is not available on Windows.

[14] Threads programming:

Threads programming provided by the threads extension is portable across platforms. However, Tcl must be built with threads-enabled. This is not the default, since - while Tcl and Tk are thread-safe - many extensions have not been confirmed to be thread-safe. For more information about the Tcl threading model, see https://tcl.activestate.com/doc/howto/thread_model.html.

[15] Socket programming:

All commands for creating and communicating with sockets and pipes are portable, from the low-level socket and open commands to the high-level http package. When dealing with serial ports, certain fconfigure command options are only available on Windows. See https://aspn.activestate.com/ASPN/Products/ActiveTcl/ActiveTcl8.4.1.0-html/tcl/TclCmd/open.htm for details.

[16] Cross-platform IPC:

Tcl provides portable support for sockets and pipes.

[17] SOAP functionality:

There is a SOAP package provided in the ActiveTcl distribution based of the SOAP package at https://tclsoap.sourceforge.net/.

[18] GUI toolkit bindings:

Tk is the predominant UI toolkit binding for Tcl, and it is fully cross-platform. All other toolkit bindings are platform-dependent.

[19] Date and time handling:

All date and time handling is done with the Tcl clock command. The only area to watch out for is which % substitutions are passed to clock format, as some are only valid on Linux. See https://aspn.activestate.com/ASPN/Products/ActiveTcl/ActiveTcl8.4.1.0-html/tcl/TclCmd/clock.htm for details.

[20] Handling endianness issues:

The binary command handles packing or unpacking of data in a specific endian manner, depending on the scan or format string used. See https://aspn.activestate.com/ASPN/Products/ActiveTcl/ActiveTcl8.4.1.0-html/tcl/TclCmd/binary.htm for details.

[21] Handling of users and groups:

Tcl identifies the current user in the $::env(USER) variable, but otherwise there is no core support for modifying the user and group information on the computer. TclX provides this for Linux, and NTtcl [https://zazu.maxwell.syr.edu/nt-tcl/] provides this functionality on Windows. The file command will give certain platform-specific information about a file, including user and group.

[22] Unicode gotchas:

Tcl has full support of Unicode, encoding data in UTF-8 internally, and all use of Unicode or other encoding by the system is completely abstracted. You can make use of the encoding command if you wish to enforce a particular encoding in your scripts. See https://aspn.activestate.com/ASPN/Products/ActiveTcl/ActiveTcl8.4.1.0-html/tcl/TclCmd/encoding.htm for details.

[23] Locale and localization:

Tcl does not currently provide the functionality to modify the locale in a script. It tries to work based on the locale information provided by the system. For language localization in scripts, Tcl provides the msgcat command for creating message catalogs, and supports XPG3 position specifiers in the scan command for locale specific data output. See https://aspn.activestate.com/ASPN/Products/ActiveTcl/ActiveTcl8.4.1.0-html/tcl/TclCmd/msgcat.htm and https://aspn.activestate.com/ASPN/Products/ActiveTcl/ActiveTcl8.4.1.0-html/tcl/TclCmd/scan.htm for details.

[24] Common platform-specific extensions:

The expect extension [https://expect.nist.gov/] is only available on UNIX. Some of its functionality is available in recent Tcl versions or other cross-platform extensions, but the ability to control any tty-based application or spawn and interact with console applications is currently limited to UNIX. Most other common extensions are cross-platform. When you want to take advantage of the Windows environment more fully, there are several Windows-only extensions available in addition to the core dde and registry extensions.

Language Notes: Perl

[1] Determining platform:

The canonical platform name is in the special variable $^O. For example, this value is linux for Linux, and MSWin32 or MSWin64 for Windows). The standard Config module exposes more fine-grained information about the platform on which the Perl executable was built. See https://aspn.activestate.com/ASPN/Reference/Products/ActivePerl/lib/Config.html for details.

[2] Handling paths across platforms:

Perl understands the use of '/' as the platform separator equally well across Windows and Linux. The best way to build up or split paths across platforms is to use the standard File::Spec module. File::Spec exposes various methods of handling file-system objects in a portable, independent way. See https://aspn.activestate.com/ASPN/Reference/Products/ActivePerl/lib/File/Spec.html for details.

[3] Accessing the registry:

Use the Win32::TieRegistry extension to access the Windows registry. This is a part of the libwin32 suite available on Windows. For example, to get the Program Files directory location, one can use:

use Win32::TieRegistry; 
$Registry->Delimiter("/"); 
my $dir = $Registry->{'HKEY_LOCAL_MACHINE/Software/ActiveState/ActivePerl/'} 
->{'/CurrentVersion'};

See https://aspn.activestate.com/ASPN/Reference/Products/ActivePerl/site/lib/Win32/TieRegistry.html for details.

[4] The environment:

The special hash variable %ENV holds the current environment. Changes made to this hash will affect the current process environment and that of child processes. Keys of the %ENV hash are case-sensitive on Linux, but aren't on Windows. Values may also be specified differently on different platforms. For instance, the value of $ENV{PATH} is a list of directories separated by a colon (:) on Linux, but a semicolon (;) on Windows.

[5] Handling the path:

The path separator used in $ENV{PATH} may be found from $Config{path_sep}, and may be used to walk the path as follows:

use Config; 
foreach my $dir (split $Config{path_sep}, $ENV{PATH}) { 
print "$dir/foo.exe" if f "$dir/foo.exe"; 
}

[6] EOL handling:

Windows distinguishes between "text" mode and "binary" mode for file I/O, whereas Linux does not. Perl exposes this distinction to scripts on Windows by handling all default file I/O in "text" mode, meaning that '\n' characters will be translated to '\r\n' on output, and '\r\n' will be translated to '\n' on input. binmode(FILEHANDLE) can be used to avoid this translation on a particular FILEHANDLE. binmode does nothing under Linux. Socket handles are always implicitly opened in "binary" mode, even under Windows. See https://aspn.activestate.com/ASPN/Reference/Products/ActivePerl/lib/Pod/perlfunc.html#item_binmode for more information.

[7] EOF handling:

Perl uses the Windows-specific notion of ^Z as an end-of-file character in "text" mode. In "binary" mode, the behavior is identical to that of Linux. binmode can be used to switch a filehandle between "text" and "binary" modes.

[8] Console handling:

The perl executable is a console application under both Linux and Windows, and has access to the three standard handles associated with console I/O, namely, STDIN, STDOUT, and STDERR. In addition, on Windows, there exists a wperl executable that is a GUI (i.e. non-console) executable that does not require an associated console to run and does not have access to the standard handles.

[9] Replacing standard shell commands:

The standard ExtUtils::Command module provides many common Linux shell built-ins and commands as functions, and that can be used portably. See https://aspn.activestate.com/ASPN/docs/ActivePerl-5.6/site/lib/Win32/OLE.html

[10] Replacing standard system commands:

See [9]

[11] Process manipulation:

The kill operator can be used to portably terminate processes, but cannot be used to deliver signals in general under Windows. See https://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/lib/Pod/perlfunc.html#item_kill

[12] Signal handling:

The special %SIG hash variable can be used to install global signal handlers on Linux. Such handlers are currently not executed in a reliable fashion because they may be serviced in a critical operation such as when Perl is allocating memory. For this reason, use of %SIG is strongly discouraged. %SIG is enabled, but not supported on Windows. In addition the alarm builtin is unavailable under Windows.

[13] Fork:

The fork operator calls the native system call of the same name on Linux, but is emulated using multiple interpreters under Windows. While the emulated version attempts to maintain compatibility with the native one, there are important differences, such as restrictions on the use of thread-safe extension modules. See https://aspn.activestate.com/ASPN/Reference/Products/ActivePerl/lib/Pod/perlfork.html for details.

[14] Threads programming:

Support for creating threads at the Perl level is considered experimental, and Perl must be specifically built in a certain way to enable it. Once built this way, however, scripts that create threads are portable between Linux and Windows. See https://aspn.activestate.com/ASPN/Reference/Products/ActivePerl/lib/Pod/perlthrtut.html for details.

[15] Socket programming:

Most operators that create and manipulate socket handles are portable between Linux and Windows. The four-argument form of the select operator only works on socket handles under Windows, while it works on all types of handles under Linux. The following socket related functions are unsupported under Windows:

socketpair 
gethostent 
sethostent 
endhostent 
getnetent 
setnetent 
endnetent 
getprotoent 
setprotoent 
endprotoent 
getservent 
setservent 
endservent 
getnetbyname 
getnetbyaddr

[16] Cross-platform IPC:

Usual idioms for opening pipe and socket handles are portable. However, inheriting or passing handles across processes is not supported under Windows. For this reason, use of fork and exec to share handles between related processes is considered unportable. Use IPC::Open2 and IPC::Open3 instead. For more details, see: https://aspn.activestate.com/ASPN/Reference/Products/ActivePerl/lib/Pod/perlipc.htmlttp://aspn.activestate.com/ASPN/Reference/Products/ActivePerl/lib/IPC/Open2.htmlhttps://aspn.activestate.com/ASPN/Reference/Products/ActivePerl/lib/IPC/Open3.html

[17] SOAP functionality:

Modules that implement SOAP functionality, such as SOAP::Lite, are portable between Linux and Windows as long as use of non-portable pathnames and similar factors are considered in their use.

[18] GUI toolkit bindings:

Various UI toolkits are available for Perl including Tk and Gtk. Tk is highly portable between Linux and Windows. Most others are not portable.

[19] Date and time handling:

The time, localtime, and gmtime operators are portable. The standard Time::Local module can be used to portably compute the absolute time in seconds based on the epoch. See ttp://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/lib/Pod/perlfunc.html#item_localtimetp://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/lib/Pod/perlfunc.html#item_gmtimehttps://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/lib/Pod/perlfunc.html#item_timehttps://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/lib/Time/Local.html

[20] Handling endianness issues:

The pack and unpack operators provide portable ways to inspect and produce binary data in various formats. In addition, $Config{byteorder} reflects the native byteorder of the system on which Perl was built. See https://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/lib/Pod/perlfunc.html#item_packhttps://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/lib/Pod/perlfunc.html#item_unpackhttps://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/lib/Config.html#b

[21] Handling of users and groups:

The getlogin operator will provide the current user name on both Linux and Windows. Other primitives that provide information on "real" or "effective" user and group ids under Linux are not portable to Windows. This includes the special variables $<, $>, $(, and $). For more details, see: https://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/lib/Pod/perlvar.html#item_%24%3C

[22] Unicode gotchas:

Support for Unicode is portable between Linux and Windows, but is considered experimental. Access to Unicode system calls is currently only implemented under Windows. For details, see: https://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/lib/Pod/perlunicode.html

[23] Locale and localization:

Support for locales is fairly well abstracted, but the availability and behavior of certain locales is platform dependent. In particular, setting locales or specifying locale names are not standardized, and may differ between Linux and Windows. For details of locale handling, see: https://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/lib/Pod/perllocale.html

[24] Common platform-specific extensions:

The libwin32 suite of extensions is only available under Windows, and provides access to Windows-specific functionality. For example, Win32::OLE can be used to access COM components available in the system. The standard IPC::SysV and Sys::Syslog extensions are only available on Linux platforms. See https://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/site/lib/Win32/OLE.html

Language Notes: Python

[1] Determining platform:

Use the sys.platform value to the platform name. It will return "win32" on Windows and some string starting with "linux" on Linux. For compatibility with wince, win64 and so forth, it is common to check for Windows based on the first three characters. For example:

>>>import sys 
>>> print sys.platform 
win32 
>>> print sys.platform.startswith("win") 
1 
>>> print sys.platform.startswith("linux") 
0

See https://aspn.activestate.com/ASPN/Reference/Products/ActivePython/python/lib/module-sys.html for more information.

[2] Handling paths across platforms:

Python understands the use of '/' as the platform separator equally well across Windows and Linux. The best way to build up or split paths across platforms is to use 'os.path.join' and 'os.path.split'. The 'os.path' module contains numerous functions for cross-platform handling of paths. See https://aspn.activestate.com/ASPN/Python/Products/ActivePython/python/lib/module-os.path.html for details.

[3] Accessing the registry:

The _winreg module provides access to the Windows registry. You can use this to find the user's home directory and other special directories.

>>>import _winreg 
>>> key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current 
                                                                       Version") 
>>> _winreg.QueryValueEx(key, "MediaPath") 
'C:\\WINNT\\Media'

See https://aspn.activestate.com/ASPN/Reference/Products/ActivePython/python/lib/module--winreg.html for details.

[4] The environment:

The environment is maintained in the os.environ dictionary. Changes made to the dictionary are respected for the rest of the current program and are passed to child processes but not to the parent. If you use multiple Python interpreters in the same process, they all share the same environment. Initial values for all environment variables are inherited from the parent process' environment at startup.

>>>import os 
>>> os.environ["ABC"]="def" 
>>> print os.environ["ABC"] def

If you are working with an environment variable that represents a list of paths, the path separator is a colon (:) on Linux and a semicolon (;) on Windows. The value "os.pathsep" always has the correct separator for the current platform.

See https://aspn.activestate.com/ASPN/Reference/Products/ActivePython/python/lib/os-procinfo.html for more information.

[5] Handling the path:

The os.system command will launch applications on your path on either Linux or Windows.

>>>import os 
>>> os.system("notepad")

Sometimes you want to simulate a path lookup without running the program. You can do this on Win32 using the win32api.SearchPath function. The return value is a tuple of (string, int) where string is the full path name located and int is the offset in the string of the base name of the file.

>>>import 
win32api >>> 
win32api.SearchPath(None, "notepad.exe") 
('C:\\WINNT\\System32\\notepad.exe', 18)

See https://aspn.activestate.com/ASPN/Reference/Products/ActivePython/python/lib/os-procinfo.html for more information.

[6] EOL handling:

Python inherits the end-of-line handling from the underlying C library and operating system. On Windows this means that if a file is read in text mode, carriage return/line feed pairs are translated into a single newline character internally. Linux-style files with a single newline character are also read appropriately.

When text files are written on Windows, newlines are converted into carriage return/line feed pairs, which is the convention on Windows. You should be careful about the extra carriage returns if you move these files to the Linux version of your program.

[7] EOF handling:

Python inherits end-of-file handling from the underlying C library and operating system. On Windows this means that a Control-Z character is considered to end a text file but not a binary file. Linux does not treat "text" and "binary" modes differently, so there is no end-of-file character on Linux. If you want the behavior to be absolutely consistent across platforms, you should open your files in binary mode:

>>>file = open("filename", "rb")

[8] Console handling:

The "python" command launches a Python program with a console. The console is displayed as a black "dos box" window. This console allows stdin and stdout to be provided interactively. If the application does not require interactive use, this extra window may confuse users. "pythonw" launches a Python program without a console. "pythonw" is useful for running graphical Python programs or for running "invisible" Python programs from within graphical applications.

[9] Replacing standard shell commands:

Most of the common Linux shell commands can be replaced with functionality in the built-in Python "os" module. For instance the "ls" command can be replaced with os.listdir. There is also a module called "shutil" with portable shell utilities such as "copyfile" and "copytree". See also https://aspn.activestate.com/ASPN/Python/Reference/Products/ActivePython/python/lib/module-os.html and https://aspn.activestate.com/ASPN/Reference/Products/ActivePython/python/lib/module-shutil.html.

[10] Replacing standard system commands:

See [9]

[11] Process manipulation:

Process creation code is portable in Python. The os.exec, os.spawn and os.system functions work identically on Linux and Windows platforms. Process destruction code is not typically portable. You will have to port code that uses "kill", "nice", and so on to the win32process module. It has functions to create processes (win32process.CreateProcess()) and destroy them (win32process.TerminateProcess()). See https://aspn.activestate.com/ASPN/Python/Reference/Products/ActivePython/PythonWin32Extensions/win32process.html

[12] Signal handling:

Signal handling is not portable between Linux and Windows. Signal handling code should be changed to use window messages. It is also possible to use some other form of IPC such as SOAP, although this method is much more heavyweight.

[13] Fork:

Python does not have a fork function in win32. Applications that use fork should be changed either to use threads or to launch separate programs using os.exec or os.system.

[14] Threads programming:

Python provides the same threading abstraction on Linux and Windows. The threading module is implemented in a manner that hides the differences between the platforms. See https://aspn.activestate.com/ASPN/Python/Reference/Products/ActivePython/python/lib/module-threading.html

[15] Socket programming:

Python offers several methods for socket programming, from high-level functions for retrieving files via various protocols such as HTTP or FTP, to lower-level socket functions. Overall, the behavior is highly consistent between platforms. The higher the abstraction level you use, the less subtle platform differences will influence your code. For instance:

>>>import urllib 
>>> file = urllib.urlopen("https://www.activestate.com") 
>>> file.read()

See https://aspn.activestate.com/ASPN/Python/Reference/Products/ActivePython/python/lib/module-urllib.html and https://aspn.activestate.com/ASPN/Python/Reference/Products/ActivePython/python/lib/module-socket.html.

[16] Cross-platform IPC:

Python provides portable support for sockets and anonymous pipes. Anonymous pipes can be created in Python by using the "popen2" module. One high-level way to do IPC within and between machines is by using an RPC library like XML-RPC or SOAP. See https://aspn.activestate.com//ASPN/Python/Reference/Products/ActivePython/python/lib/module-popen2.html.

[17] SOAP functionality:

SOAP is available as a highly flexible form of inter-process and inter-machine communication. For more information, see https://www-106.ibm.com/developerworks/library/ws-pyth1.html.

[18] GUI toolkit bindings:

Many graphical environments have been ported from Linux to Windows, but not all of the Windows ports are of high quality. Tk and WxWindows are two safe bets for portable GUIs. It is also possible to build portable applications around the Mozilla GUI framework using Python's xpcom bindings.

[19] Date and time handling:

All date and time handling should be done with the Python "time" module. Portability of most time handling between Linux and Windows is automatic. See https://aspn.activestate.com/ASPN/Reference/Products/ActivePython/python/lib/module-time.html for more details. One function that is not available on Windows is called strptime and is used for parsing times passed in as text. A Windows-compatible implementation is available here: https://aspn.activestate.com/ASPN/Python/Cookbook/Recipe/56036.

There is also an extension to Python with extremely sophisticated date handling called mxDateTime.

[20] Handling endianness issues:

Python programmers do not usually work with binary data directly, so byte ordering is not typically a problem. If you do work with binary data, you should use the "struct" module. It will automatically interpret binary data according to the byte order of the platform. If you want to have complete control over its interpretation, the module provides options for doing so.

If you need to know the native byte order of the platform, the sys.byteorder value will tell you. Possible values are "little" and "big".

[21] Handling of users and groups:

Python has no portable abstraction for users and groups. The win32security module has features for working with users and security in Win32, but there are no direct mappings from Linux security to Windows security because the security models are very different. See https://aspn.activestate.com/ASPN/Python/Reference/Products/ActivePython/PythonWin32Extensions/win32security.html.

For simple cases, the os.access and os.chmod functions may do everything you need. os.access checks whether the user has permission to work with a file. os.chmod will attempt to change the file's associated permissions.

[22] Unicode gotchas:

Python's basic string type is not Unicode. There is a Unicode type in Python, however. If you want to read or write Unicode data from a file, you should use one of the "encoder"/"decoders" from the codec module. Python 2.1 does not have built-in support for file systems that support Unicode characters. If your program must be able to read and write file names with Unicode characters in them, you should encode the file name using MCBS on Windows and UTF-8 on Linux:

>>>path = u"\u00EE" 
>>> if sys.platform.startswith("win"): 
...     encoding = "MBCS" 
... else: 
...     encoding = "UTF-8" 
>>> open(path.encode(encoding), "w").write("some text")

Filenames will often have non-ASCII characters in them when they are the home directories of people with non-English names. See https://aspn.activestate.com/ASPN/Python/Reference/Products/ActivePython/python/lib/module-codecs.html.

[23] Locale and localization:

Python provides a locale module with support for reporting the user's location settings. It is based upon the ANSI C locale library and is thus portable to both Windows and Linux.

Python provides a portable system for program localization. Pygettext allows you to translate your program's error messages, prompts and other strings into multiple human languages. For more information, see https://aspn.activestate.com/ASPN/Python/Reference/Products/ActivePython/python/lib/module-locale.html and https://aspn.activestate.com/ASPN/docs/ActivePython/2.3/python/lib/module-gettext.html.

[24] Common platform-specific extensions:

The vast majority of Python extensions are portable. The ones that are not are typically related to user interface development. For example Python's curses module does not work on Windows. Typically Python extensions wrap components coded in another language. Typically, when the underlying components are portable, the extensions are equally portable.

Language Notes: PHP

Cross-platform development has been a major goal in the development of PHP since the days of version 3. For the most part, PHP scripts should be easily ported from Linux to Windows with few problems. However, there are several instances where you can run into roadblocks when porting your scripts. The hardest part of porting PHP scripts will be dependent on the extensions you have used in your scripts (see section 24 below).

Console issues under PHP are far more rare than they may appear, since PHP is not generally used for console scripting. PHP was designed from the start for embedded HTML scripting, and thus often lacks support for the console that is common in other scripting languages. However, PHP can be used for console scripting, and will face many of the same issues found in other languages.

PHP development is largely a community effort. Much of the functionality that is available in PHP was developed out of the need of one or more developers. The development community involved with PHP is largely a Linux community and most PHP development occurs on Linux first, then on other platforms as people find the time to port their work. This can often lead to a disparity in functionality between various operating systems.

The PHP dynamic manual is an excellent source of user-contributed information. If you run into problems with any given function, you should review the PHP manual to see if anyone else has run into the same, and possibly contributed a workaround.

Some important resources for PHP scripting include:

  1. PHP.net

  2. PHP Documentation

  3. Other PHP Sites

Common Platform Portability Issues in PHP

There are a few items that are common issues in PHP portability that have to do with differences in behavior of some function calls. Some functions that were implemented very early in the life of PHP had to be mimicked for use under Windows. Other functions may be specific to the Web server PHP is running under.

Mail():

One issue is the use of the Mail() function. On Linux systems, you can configure this function to use Sendmail or Qmail to send messages. As of version 4.0.5, this is not available under Windows. The Windows version of PHP includes a built-in implementation for sending e-mails that is limited to simple messaging. See https://www.php.net/manual/en/function.mail.php for more information. If you need more capabilities you may need to script your own Sendmail implementation, though you should be able to find several by searching any of the PHP script repositories.

One way to work around the lack of a full implementation of sendmail in PHP (4.0.6 or higher required) is to use the Microsoft Collaboration Data Objects (CDO) Library (see https://msdn.microsoft.com/library/default.asp?URL=/library/psdk/cdo/_olemsg_introduction.htm

). Here is a short example of its usage:

<? 
$message = new COM("CDO.Message"); 
$message->To = 'receiver@somplace.com'; 
$message->From = 'Sender@MyCompany.com'; 
$message->Subject = "This is a subject line"; 
$message->HTMLBody = "<html><body>This is <b>the</b> body!</body></html>"; 
$message->AddAttachment('https://www.ActiveState.com'); 
$message->Send(); ?>

Apache Specific Functions:

PHP includes several functions that are specific to the Apache Web server, if it is compiled as a plug-in for Apache. If you use these functions, and are porting your scripts to run under IIS, you will need to re-implement those areas that use these functions. For more information, see https://www.php.net/manual/en/ref.apache.php. There is also a set of IIS-specific functions, though its purpose is primarily for management of IIS, and is undocumented as of version 4.0.5. Below are the Apache-specific functions and some solutions for replacing them.

Getallheaders():

Fetch all HTTP request headers. You can access the HTTP request headers via the predefined variable $HTTP_ENV_VARS in place of using this function for any Web server, including Apache. See https://www.php.net/manual/language.variables.predefined.php for more information.

Virtual():

Perform an Apache sub-request. This function allows you to include a URI from the local Web server into the PHP script. If the retrieved text includes PHP script, that script will become a part of your current script.While this function is Apache-specific, it is easy to implement:

<?function emulate_virtual($filename) { 
global $HTTP_ENV_VARS;     if ($filename) { 
// build the proper url to retreive via http 
$url = parse_url($filename); 
if ($url['scheme'] == "") { 
$http = ""; 
// assume http scheme 
if ($HTTP_ENV_VARS["SERVER_NAME"]) { 
$http = "https://".$HTTP_ENV_VARS["SERVER_NAME"]; 
} 
if ($HTTP_ENV_VARS["SERVER_PORT"] && $HTTP_ENV_VARS["SERVER_PORT"]!=80) { 
$http.=":".$HTTP_ENV_VARS["SERVER_PORT"]; 
} 
$filename = $http."/".$url['path']; 
if ($url['query']) $filename.="?".$url['query']; 
if ($url['fragment']) $filename.="#".$url['fragment']; 
} 
// get the file 
$data = implode("\n", file($filename)); 
if ($data) { 
$tempfile = tempnam(getenv("TEMP"),"inc"); 
$fp = fopen( $tempfile,"w"); 
fwrite( $fp, "$data"); 
fclose( $fp ); 
return include($tempfile); 
} 
} 
echo "<b>ERROR: Unable to include ".$filename."</b><br>\n"; 
return FALSE; } emulate_virtual("/test.inc"); 
?>

apache_lookup_uri:

Perform a partial request for the specified URI and return all info about it. This function requests Apache to provide information about a URI. No conversion is available for IIS.

apache_note:

Get and set Apache request notes. Used for communication between Apache plug-ins. No conversion is available for IIS.

ascii2ebcdic and ebcdic2ascii:

These functions translate strings to and from ASCII and EBCDIC. Apache must be compiled with EBCDIC support for these functions to work. PHP provides no other means of converting EBCDIC strings. Microsoft provides a C-based API to handle EBCDIC translations (see https://msdn.microsoft.com/library/default.asp?URL=/library/psdk/his/snanls_4w6r.htm) so it would be possible to add this functionality by writing a new extension to PHP.

Remote Files:

Under Linux, PHP is able to retrieve remote files via HTTP or FTP for inclusion in your script via the require() and include() functions. This is not available under Windows as of version 4.0.5. See https://www.php.net/manual/en/features.remote-files.php for more information. If you need to emulate this functionality, you can utilize the above example for emulating the Apache virtual() function, since the functionality is virtually the same.

Syslog reporting:

Under Windows, syslog functions are implemented against the NT Event Log. Currently there is no method of accessing syslog daemons from the Windows version of PHP.

Miscellaneous:

Some functions are simply not available under Windows even though the module as a whole may be, such as checkdnsrr() in the Networking module (see https://www.php.net/manual/en/function.checkdnsrr.php). You can turn on tighter error-checking via the php.ini file (see https://www.php.net/manual/en/configuration.php) while you are in process of porting your scripts, to find where you may run into functions that are not available under Windows.

[1] Determining platform:

PHP defines the constant variable PHP_OS. This variable contains the name of the operating system on which the PHP parser is executing;. Possible values may be: "AIX", "Darwin" (MacOS), "Linux", "SunOS", "WIN32", "WINNT". Note: other values may be available too. (See: https://www.php.net/manual/en/language.constants.php). A good use of this constant would be within a general configuration file for your PHP application. For example:

<? 
if (PHP_OS == "WIN32" || PHP_OS == "WINNT") { 
define("BASE_PATH","c:\\myapps"); } else if (PHP_OS == "Linux") { 
define("BASE_PATH","/usr/local/myapps"); 
} else { 
// some other platform 
} 
define("INCLUDE_DIR",BASE_PATH."/include"); 
?>

An alternate method of identifying the platform exists in the use of the php_uname function (https://www.php.net/manual/en/function.php-uname.php):

<? 
if (substr(php_uname(), 0, 7) == "Windows") { 
//  
} else { 
//  
} 
?>

[2] Handling paths across platforms:

PHP understands the use of either backward or forward slashes on Windows platforms, and can even handle paths that mix the use of the two slashes. However, as of version 4.0.5, when accessing Windows UNC paths, PHP will only recognize the forward slash in the path (i.e. //machine_name/path/to/file).

[3] Accessing the registry:

PHP does not support registry access as of 4.0.5

[4] The environment:

PHP defines a constant array that contains the HTTP environment information, HTTP_ENV_VARS. Additionally, PHP has the getenv() function (https://www.php.net/manual/en/function.getenv.php).

<? 
echo "Windows Directory is ".$HTTP_ENV_VARS["windir"]."\r\n"); 
echo "Windows Directory is ".getenv("windir")."\r\n"); 
?>

[5] Handling the path:

When executing programs from PHP, the path is always utilized if a path is not specified to the executable. There are a couple of configuration variables,safe_modeand*safe_mode_exec_dir,*that may limit the paths in which a program can be executed. See https://www.php.net/manual/en/configuration.php for more information. PHP does not have any equivalent of the "where" command in Linux.

[6] EOL handling:

PHP on Windows sets stdout, stdin and stderr file handles to binary mode and thus does not do any translations for you. This is important for handling binary input often associated with POST messages from Web servers. If you open other files, you can specify the mode you wish to use to obtain the text translations, or you can produce the EOL characters yourself (it may be more reliable to do this). PHP can handle reading files with any End-of-line character. Output to stdout is completely controlled by the script, so you will have to code your EOL characters yourself. One way to handle this would be to define some basic overriding functions that you use as a library.

<? 
if (PHP_OS == "WIN32" || PHP_OS == "WINNT") { 
define("EOL","\r\n"); } else if (PHP_OS == "Linux") { 
define("EOL","\n"); 
} else { 
define("EOL","\n"); 
} function echo_ln($out) { 
echo $out.EOL; 
} 
echo_ln("this line will have the platforms EOL character"); 
?>

[7] EOF handling:

PHP utilizes the EOF character of the platform it is running on. The function feof() can often be used to check for EOF when reading files. See https://www.php.net/manual/en/function.feof.php for more information.

[8] Console handling:

PHP's console handling is rather limited due to its focus as an HTML embedded language. Some additions have been made to PHP to aid in its use for console-based scripts. Much of this is early in its development and may be limited in functionality. There are some areas of PHP's documentation that you can refer to for further information:

STDIN/STDOUT/STDERR

Readline support

Program Execution

[9] Replacing standard shell commands:

See [8]

[10] Replacing standard system commands:

See [8]

[11] Process manipulation:

PHP uses the default command shell of Windows for process manipulation.

[12] Signal handling:

PHP does not support signal handling.

[13] Fork:

PHP does not support forking.

[14] Threads programming:

PHP does not support multithreaded scripts.

[15] Socket programming:

PHP offers several methods for socket programming, from high-level functions for retrieving files via various protocols such as HTTP or FTP, to lower-level socket functions that implement a subset of winsock functions. On Windows, PHP supports accessing sockets via standard file functions such as fread and fwrite, though the socket must be initiated with fsockopen(). Documentation: https://www.php.net/manual/en/function.fsockopen.php

[16] Cross-platform IPC:

PHP includes support for SystemV Shared Memory and Semaphores (https://www.php.net/manual/en/ref.sem.php). XML-RPC has also been implemented as a script-based extension in PEAR (PHP Extension and Application Repository).

[17] SOAP functionality:

Script-based extensions are available that implement SOAP for PHP at https://www.gigaideas.com.cn/phpsoap/.

[18] GUI toolkit bindings:

As of PHP 4.0.5 there is an experimental GTK extension available for PHP.

[19] Date and time handling:

PHP includes an extensive set of functions for date and time handling that are cross-platform compatible.

[20] Handling endianness issues:

Endian issues are normally handled internally with PHP, with the exception of the Pack() and Unpack() functions (see https://www.php.net/manual/en/function.pack.php). If your script accesses data directly that is endian-specific you will need to make the proper adjustments.

[21] Handling of users and groups:

PHP does not include support for handling users and groups on Windows. The POSIX extension to PHP provides that functionality under POSIX-compliant systems, though this is a relatively new extension and is not in wide use at this time.

[22] Unicode gotchas:

PHP does not include full support for Unicode as of version 4.0.5. However, some modules do utilize UTF-8 (e.q. XML, see https://www.php.net/manual/en/function.utf8-encode.php), and there have been some PHP patches to enable multibyte characters in PHP (see PHP source code for the experimental extension in the ext/iconv directory).

[23] Locale and localization:

PHP supports setting the locale in a script. Several functions are effected by the Locale, such as strcoll(), strtoupper(), localeconv() and strftime(). See https://www.php.net/manual/en/html/function.setlocale.html for more information.

[24] Common platform-specific extensions:

There are currently over 80 extensions for PHP, covering a wide range of services and functionality. Only about half of these are available on both platforms. Only a handful of extensions, such as the COM, .Net and IIS extensions, are specific to Windows. If an extension you use in your scripts is not currently available under Windows, you will need to look at either porting that extension or converting your scripts to utilize functionality that is available under Windows. Another issue that you may face in using extensions on Windows will be the form in which you use PHP. If you use PHP as a Web server plug-in (i.e. the ISAPI plug-in), the extensions must be thread-safe. Some extensions depend on third-party libraries that may not be thread-safe, thus making the extension incompatible with the ISAPI plug-in. Unfortunately, the level of thread safety in PHP extensions is poorly documented, and it will require testing on your part to discover where you may run into difficulty. Fortunately, the more popular an extension is, the greater chance there is of that extension being available on Windows.

Other Resources and References

Microsoft TechNet

Microsoft Internix

Microsoft Interix 2.2 is the easiest way for customers to take advantage of their previous investments in UNIX-based legacy applications as they move to the Windows operating system.

Windows Services for UNIX version 2

The Microsoft Windows NT Platform: Enterprise Interoperability with UNIX

UWIN

The UWIN package provides a mechanism for building and running UNIX applications on Windows NT, Windows 98, and Windows 95 with few, if any, changes necessary.

Portable Perl Programs

This document is meant to help you to find out what constitutes portable Perl code, so that once you have made your decision to write portably, you know where the lines are drawn, and you can stay within them.

How to Remove Linux and Install Windows 2000 or Windows NT on Your Computer

For in-depth information on the low-level differences between Windows and UNIX, see: Porting UNIX Applications to Windows NT, Andrew Lowe, Macmillan Technical Publishing, ISBN 1-57870-004-3

Some popular cross-platform editors are:

For information on porting CGI programs to mod_perl see https://perl.apache.org/guide/porting.html

For the latest information on Windows 2000, check out the Microsoft Web site at https://www.microsoft.com/windows2000

The complete Perl documentation is available at https://aspn.activestate.com/ASPN/Products/ASPNTOC-ACTIVEPERL

The complete PHP documentation is available at https://www.php.net/

The complete Python documentation is available at https://aspn.activestate.com/ASPN/Reference/Products/ActivePython/python/lib/

The complete Tcl documentation is available at https://tcl.activestate.com/doc/