Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!hsdndev!wuarchive!zaphod.mps.ohio-state.edu!rpi!clarkson!grape.ecs.clarkson.edu!towfiq From: towfiq@FTP.COM (Mark Towfiq) Newsgroups: comp.os.os2.programmer Subject: Re: Porting from Unix to OS/2 Message-ID: Date: 24 Jun 91 19:41:44 GMT References: <3126@public.BTR.COM> Sender: usenet@grape.ecs.clarkson.edu Reply-To: towfiq@FTP.COM Organization: FTP Software, Inc., Wakefield, MA Lines: 215 In-Reply-To: car@public.BTR.COM's message of 19 Jun 91 22:47:05 GMT >>>>> On 19 Jun 91 22:47:05 GMT, car@public.BTR.COM (Carlos >>>>> Rimola-Sarti car@btr.com) said: Carlos> I am in the process of porting a large piece of code from Unix Carlos> to OS/2 and I was wondering if anyone has had similar Carlos> experiences to mine. I am sure we have! :-) Carlos> 1) Has anyone had a similar experience? what did you do? YES! I have included the README.BSD file from FTP's development kit below; it is something I wrote when I was encountering the same problems as you. Carlos> 2) Is there a way in OS/2 to start a second process without Carlos> having to specify an executable file that the OS will have to Carlos> load from disk? In other words, why can't I just tell the OS Carlos> where the code is? It makes sense to me, but for some reason they did not want to provide this functionality. I suppose with successive versions, they eventually will do just that (I hope so! It would make life much easier). Carlos> 4) I would also like to hear about any other things to watch Carlos> out for in porting code from one OS to the other and general Carlos> comments on what others may have experienced. I hope what follows will help answer this... ------------------------------------------------------------------------------ PORTING TO OS/2 FROM UNIX There are several issues to consider when porting programs from Unix to OS/2. One is about fork() and execl() on the Unix side, and execl(), spawnl(), and _beginthread() on the OS/2 side. OS/2 has no fork() call, for some reason. Fortunately, most often (about 80% of the time) in a Unix program, a fork() is quickly followed by an execl()-type call, to spawn another process. Microsoft has provided this functionality in their spawnl() family of functions -- the only trick is piping. The Unix calls pipe(), popen() and pclose() are called _pipe(), _popen() and _pclose() in OS/2. However, there is one catch. You must mark file handles you do *NOT* want inherited by the child process before you call the spawn() or _popen(), using the OS/2 call DosSetFhandState, with the parameter NOINHERIT. You certainly do not want the server side of the pipe to be inherited by the child. Another 10% of the time, fork() is used in a server or daemon to split off an identical copy of the running program to handle a user, while the original still listens for incoming connections. There are two ways to handle this in OS/2. One is to write an inetd-type program, which will listen on all incoming sockets for a connection, and upon receiving one, spawn() the appropriate daemon, passing on the command line the socket #. (This inetd would be best written with a separate thread for each incoming socket). The second solution is to modify the daemon so that it calls _beginthread() instead of fork() to kick off the client handler. This takes more redesigning, however, as the client routines must then be callable as one function with one parameter (this is a restriction of _beginthread()). The remaining 10% of the time, fork()) is used to split a process into two tasks, for example a reader and a writer on a socket. This is an instance where using threads is clearly superior, as the reader and writer usually are just functions, easily handled by _beginthread(). In general, if you decide to use threads, you have to watch out that different threads do not try to modify global variables without some sort of locking. Oftentimes, Unix programs were written sloppily, and some variables shouldn't be global anyway. Another issue is files; OS/2 has two modes in which one can open files: text-mode and binary-mode. Unix uses the equivalent of binary-mode for all files. This means that text files taken from Unix must be converted to text-mode in OS/2, or many OS/2 applications will not work. On the other hand, this means that binary files must be pulled over in binary-mode, or things will be even worse. Since there is no sure way of how to do this, programs must provide a way for the user to specify what type of file they are manipulating, with the default being binary-mode. Another issue with files is namespace -- you have to make sure that your program can handle long filenames, by either truncating them (on a FAT file system) or properly creating them. File locking also must be handled in tricky ways sometimes, as to open a file for exclusive access, you must use the sopen() call, followed by fdopen() to just get a FILE *. The following is a summary of issues in Unix (BSD mostly) and their resolutions in OS/2. Feel free to make changes and additions. Most of the solutions rely on either the header file, BSD.H, which maps the more System V-type MS C runtime calls to Bezerkelyisms, or BSD.LIB, our BSD Unix compatability library. Others are implemented in separate header file/library combinations. Problem Solution ------- -------- filenames too long truncate or mark program LFNS fork() + detach from terminal DETACH command fork() + execl() spawnl() fork() + handle connection in child _beginthread() fork() + other situations panic, eliminate from program UNIX domain sockets named pipes shared memory DosAllocShrSeg(), DosGetShrSeg() Many other calls are also handled by just #include'ing and linking in BSD.DLL; the following BSD calls are supported in the PC/TCP for OS/2 devkit (these are the non-networking calls; all the Berkeley socket calls are also supported): alarm() alphasort() bcmp() bcopy() bzero() closedir() closelog() crypt() dbm_close() dbm_delete() dbm_fetch() dbm_firstkey() dbm_nextkey() dbm_open() dbm_store() dbmend() dbminit() delete() endgrent() endpwent() fetch() ffs() fsync() ftruncate() getgid() getgrent() getgrgid() getgrnam() getlogin() getpass() getppid() getpwent() getpwnam() getpwuid() gettimeofday() getuid() getwd() index() kill() killpg() lstat() opendir() openlog() pclose() pipe() popen() psignal() random() readdir() rindex() scandir() setbuffer() setenv() setgrent() setgrfile() setgroupent() setlinebuf() setlogmask() setpwent() setpwfile() signal() sleep() srandom() store() strcasecmp() strncasecmp() strsep() syslog() tgetent() tgetflag() tgetnum() tgetstr() tgoto() tputs() utimes() There are also calls which have no analogy in OS/2; we map these to no-ops, some of which return an error, because their non-existance would prevent the program from working as written. chown() fchown() flock() getegid() geteuid() getgroups() link() setegid() seteuid() setgid() setpgrp() setpriority() setregid() setreuid() setuid() sigsetmask() symlink() ulimit() -- Mark Towfiq towfiq@FTP.COM Work: +1 617 246 0900 Home: +1 617 488 2818 FTP Software, Wakefield, MA 51 Harvard Avenue, West Medford, MA 02155 "The Earth is but One Country, and Mankind its Citizens" -- Baha'u'llah