🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.os.os2.programmer
9 messages
9 total messages Started by Carlos Rimola-Sarti car Wed, 19 Jun 1991 22:47
Porting from Unix to OS/2
#3223
Author: Carlos Rimola-Sarti car
Date: Wed, 19 Jun 1991 22:47
42 lines
2640 bytes
I am in the process of porting a large piece of code from Unix to OS/2
and I was wondering if anyone has had similar experiences to mine.

For background, the code that I am porting consists of a device driver, 
a daemon and an application.  They all talk to each other via named
pipes and/or device open/close/read/write/ioctl. 

One of the first things that I had to decide was what to do about 
the Unix fork() call.  The application makes use of fork to spawn off
background processes.  The "right" thing to do is probably to redesign
the app to use threads instead of fork().  However, the app will be
thrown away and I only needed to verify that the other pieces are
working.  Because of this, I thought that moving the application to
OS/2 would be made a lot easier if I could emulate fork.  

After thinking about it I decided that fork() could not be easily emulated
using threads.  A forked process inherits its own copy of the data
segment (with current values) and also inherits other context like
installed signal handlers (which this application makes use of).  All
of these characteristics convinced me that it would be easier to
simulate fork() by spawning an OS/2 process.  I have been able to
come up with a scheme (hack?) that works but I still have a few 
questions:

1) Has anyone had a similar experience?  what did you do?

2) Is there a way in OS/2 to start a second process without having
to specify an executable file that the OS will have to load from disk?
In other words,  why can't I just tell the OS where the code is?

3) Is there a clean way for a process to determine that IT is the
first process in a session?  i.e., one that was not spawned off by
another process in the same session.

4) I would also like to hear about any other things to watch out for
in porting code from one OS to the other and general comments on
what others may have experienced.

+---------------------------------------+-----------------------------------+
| Carlos Rimola-Sarti			|		email: car@btr.com  |
| Communications Solutions, Inc.	|		phone: 415-903-2585 |
+---------------------------------------+-----------------------------------+
Re: Porting from Unix to OS/2
#3224
Author: Ramesh_Rama_Pendakur
Date: Thu, 20 Jun 1991 23:30
7 lines
825 bytes
It has been mentioned on this BBS before, but ARGOSOFT Corp. has made a 
development tool kit for C with BSD 4.3 run time library. You might give
them a call at (415)795-7921. From what I know, it is not too expensive, and
you might even get it for free. Also, I know for a fact that they have 
successfully resolved issues like implementing fork(2). Good Luck.

	- Alex -
Re: Porting from Unix to OS/2
#3229
Author: larrys
Date: Fri, 21 Jun 1991 15:41
24 lines
1769 bytes
In <3126@public.BTR.COM>, car@public.BTR.COM (Carlos Rimola-Sarti  car@btr.com) writes:
>
>One of the first things that I had to decide was what to do about
>the Unix fork() call.  The application makes use of fork to spawn off
>background processes.  The "right" thing to do is probably to redesign
>the app to use threads instead of fork().  However, the app will be
>thrown away and I only needed to verify that the other pieces are
>working.  Because of this, I thought that moving the application to
>OS/2 would be made a lot easier if I could emulate fork.

You're creating more trouble than you would be saving by not redesigning
the application.  I thought I read (some time ago) that one of the Unix
companies (MKS?) wrote a fork() for OS/2, but I can't remember for sure.

Cheers,
Larry Salomon, Jr. (aka 'Q')            LARRYS@YKTVMV.BITNET
OS/2 Applications and Tools             larrys@ibmman.watson.ibm.com
IBM T.J. Watson Research Center         larrys@eng.clemson.edu
Yorktown Heights, NY

Disclaimer:  The statements and/or opinions stated above are strictly my
own and do not reflect the views of my employer.  Additionally, I have a
reputation for being obnoxious, so don't take any personal attacks too
seriously.
Re: Porting from Unix to OS/2
#3231
Author: Dan Zimmerman
Date: Fri, 21 Jun 1991 18:13
8 lines
717 bytes
I am very interested in this topic, specifically whether or not and
where I can grab a Bourne shell or C shell ( ftp, source, etc. )
Please mail responses to dfz@cypress.cray.com.

-dfz

Disclaimer: these ideas are solely my own.
Re: Porting from Unix to OS/2
#3232
Author: Carlos Rimola-Sarti car
Date: Sat, 22 Jun 1991 01:09
39 lines
2373 bytes
In article <1991Jun21.144327.18895@watson.ibm.com> larrys@ibmman writes:
>
>You're creating more trouble than you would be saving by not redesigning
>the application.  I thought I read (some time ago) that one of the Unix
>companies (MKS?) wrote a fork() for OS/2, but I can't remember for sure.
>

You can't say which way is more or less trouble without looking at
the code.  Each application will have different OS dependencies.

In general, yes - redesigning the application is the way to go.  As I
stated, in my case the application is throw away code and I just wanted
to get it running quickly and with minimal effort.  Emulating fork()
helped me accomplish this.  

In any case, my posting was mainly due to my interest in the general 
subject of porting between Unix <-> OS/2 and/or writing code that 
is easily portable between the two.  A discussion comparing interfaces
and how they map to each other should be helpful to anyone who has
to deal with developing for both systems.  (see followup article).

I don't think MKS has such product.  Someone else mentioned a company
called ARGOSOFT that does.  I plan to give them a call soon. 

>Cheers,
>Larry Salomon, Jr. (aka 'Q')            LARRYS@YKTVMV.BITNET
>OS/2 Applications and Tools             larrys@ibmman.watson.ibm.com
>IBM T.J. Watson Research Center         larrys@eng.clemson.edu
>Yorktown Heights, NY
>
>Disclaimer:  The statements and/or opinions stated above are strictly my
>own and do not reflect the views of my employer.  Additionally, I have a
>reputation for being obnoxious, so don't take any personal attacks too
>seriously.

+---------------------------------------+-----------------------------------+
| Carlos Rimola-Sarti			|		email: car@btr.com  |
| Communications Solutions, Inc.	|		phone: 415-903-2585 |
+---------------------------------------+-----------------------------------+
Re: Porting from Unix to OS/2
#3233
Author: Carlos Rimola-Sarti car
Date: Sat, 22 Jun 1991 01:15
164 lines
7974 bytes
I got the following response from Kai-Uwe Rommmel regarding my
questions about porting between OS/2 <-> Unix.  Since most of his
comments are of general interest and a couple of other people
have expressed interest in the subject, I am posting my reply
to Kai-Uwe:

In his reply Kai-Uwe Rommel <rommel@dssiegert4.informatik.tu-muenchen.de>
writes:
-
-In article <3126@public.BTR.COM> you <car@btr.com> write:
-
->One of the first things that I had to decide was what to do about 
->the Unix fork() call.  The application makes use of fork to spawn off
->background processes.  The "right" thing to do is probably to redesign
->the app to use threads instead of fork().  However, the app will be
->thrown away and I only needed to verify that the other pieces are
->working.  Because of this, I thought that moving the application to
->OS/2 would be made a lot easier if I could emulate fork.  
-
-I am not shure what you need fork() for. Do you need only to fork off a
-background process to execute a new program or do you need the forked
-child to continue execution on the same image with the inherited data?
-

The latter.  I need the forked process to continue the execution path
of the parent w/ retcode=0 (indicating child) and, very importantly,
inheriting the current state of the parent's data space.

->After thinking about it I decided that fork() could not be easily emulated
->using threads.  A forked process inherits its own copy of the data
->segment (with current values) and also inherits other context like
->installed signal handlers (which this application makes use of).  All
->of these characteristics convinced me that it would be easier to
->simulate fork() by spawning an OS/2 process.  I have been able to
->come up with a scheme (hack?) that works but I still have a few 
->questions:
-
-How did you manage to simulate the inherited data? Sometimes I started
-porting a korn shell to OS/2 which uses fork() often and needs to
-continue work in the child on the inherited data segment. I did not find
-a solution (but have to tried much since then).
-

What I did was not very clean at all but it works.  The fork() routine
does the following:

1) Gets the return address off the stack.  This is where the child
needs to start executing.

2) Calculates the size of the data seg, allocates a shared data seg
and copies the current data to it.

3) Using info from DosGetInfo starts a copy of itself via DosExecPgm.

4) Waits on a semaphore.  Both the shared memory and semaphore use
the parent pid as part of their name.

5) The child process is now started.  At the start of main I need to
have a fork_setup() call.  In this routine, I create a semaphore.
This will only be successful for the first process.  Thereafter, it
is an indication that the process is a "forked" one.  This is why
I asked the question re a cleaner way to determin process identity.

6) Having determined that it is a child process, it gets the parent's
pid, accesses the shared memory, copies to its data seg, clears
the semaphore on which the parent is waiting and lastly jumps to 
the return address which was saved in step 1.

Other setup can be done in the fork_setup routine.  For example, I
enable a couple of signals handlers.  

I would not use this code for anything that would be used long term but
as I said before I just need it to get an application running asap and
both will be thrown away.

->1) Has anyone had a similar experience?  what did you do?
-
-As said, nothing yet.
-
->2) Is there a way in OS/2 to start a second process without having
->to specify an executable file that the OS will have to load from disk?
->In other words,  why can't I just tell the OS where the code is?
-
-Not as far as I know. DosExecPgm() or DosStartSession() are the calls I
-know that can be used to start a new process.
-

Judging from the responses I have received, I think you are right.

->3) Is there a clean way for a process to determine that IT is the
->first process in a session?  i.e., one that was not spawned off by
->another process in the same session.
-
-Hmm, I don't have the docs here and I am not shure if it is possible to
-determine the screen session of the parent process by a documented call.
-But there is an undocumented call DosQProcInfo() which is used by the
-PSTAT utility of OS/2 and that can be used to get the whole process tree
-of the system. I posted some documentation about it in
-comp.os.os2.programmer long time ago and have used it in the port of
-MS-SH 1.6 to OS/2.
-

It sounds useful.  Could you please email or repost this info?  Does
anyone know if this interface is been documented in OS/2 2.0?

->4) I would also like to hear about any other things to watch out for
->in porting code from one OS to the other and general comments on
->what others may have experienced.
-
-- Signal handling. SIGINT is associated with ^C, SIGBREAK is associated
-with ^BREAK and SIGTERM is generated if another process tries to kill
-the process (yes, this can be catched !).
-

SIGUSR1, SIGUSR2 and SIGUSR3 can also be used with signal() to setup
a signal handler.  However, the raise() function can only be used
within the same process.  I don't know how the MS C signal() function
implements signal().  I emulated signal() and kill() using PFLG_A-PFLG_C
in place of SIGUSR1-SIGUSR3.

-- File handle inheriting when using _pipe() (and perhaps _popen() and
-_pclose()) from the C 6.0 libraries. 
-

A named pipe can be open, read, written, closed by a process using
MS C library calls but I don't think they can be created.  This
would require the library function to perform DosMakeNmPipe and
DosConnectNmPipe.

Note here a difference between Unix and OS/2 named pipes.  When a
client closes the named pipe in OS/2, the server must issue a 
DosDisconnectNmPipe followed by a DosConnectNmPipe to enable a new
client to open the same pipe.

Another difference if I am not mistaken in Unix several clients can
open the same pipe with their written messages all going to the
server end (in sequence).  In OS/2, if you want the pipe to serve
multiple clients, it seems like you have to create multiple instances
of that pipe and create a thread for each instance to "listen" on.
You can probably use just one thread but it will need to determine
on which instance of the pipe data has arrived.  In any case it still
differs from Unix pipes.

-- When doing character mode screen output interactively, good old
-termcap and ANSI sequences are much better than VIO and easier to get
-working. STDOUT should be set to binary mode and output should be
-buffered with about 1k before writing it with write() to stdout.
-
-- Keyboard inbut with getch() from the C lib is not sufficient for all
-purposes because of ^S, ^Q, ^P handling. KbdCharin() is better, when the
-keyboard is set to binary mode (raw mode).
-
-Kai Uwe Rommel
-
-/* Kai Uwe Rommel, Munich ----- rommel@lan.informatik.tu-muenchen.dbp.de */
-
-DOS ... is still a real mode only non-reentrant interrupt
-handler, and always will be.                -Russell Williams
-

+ ---------------------------------------+-----------------------------------+
| Carlos Rimola-Sarti			|		email: car@btr.com  |
| Communications Solutions, Inc.	|		phone: 415-903-2585 |
+---------------------------------------+-----------------------------------+
DosQProcInfo() (Was Re: Porting from Unix to OS/2)
#3234
Author: Kai-Uwe Rommel
Date: Sat, 22 Jun 1991 21:22
625 lines
15355 bytes
This is a repost of an earlier article on the undocumented (but
sometimes needed) DosQProcInfo() system call. It includes a small
sample. PSTAT uses this call and my program MAP (was posted to
comp.binaries.os2) uses it too.

Kai Uwe Rommel

/* Kai Uwe Rommel, Munich ----- rommel@lan.informatik.tu-muenchen.dbp.de */

DOS ... is still a real mode only non-reentrant interrupt
handler, and always will be.                -Russell Williams

Some information about the DosQProcStatus()

Kai Uwe Rommel, rommel@lan.informatik.tu-muenchen.dbp.de
08/19/90

This is a message which I found in some PD software from
listserv@blekul11.bitnet:

Date:  10-19-89  00:29
From:  Franz Krainer
To:    All
Subj:  More About The Function Behind Ps.exe And Pstat.exe

The undocumented function in OS/2 v1.2 which is used by PSTAT.EXE and PS.EXE
to get system information about processes, threads etc. has to be declared in
the following way:

/***   DosQProcStatus
 *
 *   Fills a buffer with system information about threads, processes,
 *   dynylink-libraries, system semaphores and named shared segments.
 *
 */
USHORT APIENTRY DosQProcStatus(
        PVOID pBuf,               /* address of a transfer buffer  */
        USHORT cbBuf);            /* size of buffer in bytes       */

pBuf is the adress of a buffer, cbBuf is the size of the buffer. OS/2
fills this buffer with system information. The amount of information
you will get depends on how many system resources are actually used.
The size of the buffer (and therefore the value of cbBuf) should be
around 4 kBytes. This should be enough, even in the case of a heavy
loaded system. The data you will get back is structured as a linked
list. Each entry starts with a 16-bit code (0001 = thread information
entry, 0004 = named shared segment etc.). The second 16-bit value is
the pointer to the next entry followed by specific information about
the entry. Franz. --- FD 2.00 * Origin: Ockham's Razor
(Vienna/Austria) (2:310/11.17)

[End of message]

There was other information about the structure of the buffer.
I had to correct it at some points. Here is a summary of what I know.

The buffer is a sequence of USHORT values, a (varying) number of them
builds each record. These records are ordered in a linked list. The
first USHORT of each records is it's type:

  0      process record
  1      thread record
  2      module record
  3      system semaphore record
  4      shared memory record
  FFFF   end of buffer

The buffer contains records for each process, thread, module, semaphore
and shared memory segment currently known by the system. The term
module refers to a EXE or DLL module here.

The second USHORT of each record is the offset of the next record and
thus establishes the forward link in the list. The offset is NOT from
the beginning of the buffer but is the offset of the next record from
the beginning of the segment in which the buffer is located!

All other USHORT's contain information specific to the record types.
The offset in the structures listed below is the number of the USHORT
from the beginning of the record.


type 0 (process record):

0 - type (process = 0)
1 - offset to next record
2 - PID
3 - parent PID
4 - screen session ID
5 - module handle of the EXE running for this process
(other unknown information)


type 1 (thread record)

0 - type (thread = 1)
1 - offset to next record
2 - some handle number ?
3 - PID of process to which this thread belongs
4 - thread ID
(other unknown information)


type 2 (module record)
These are records for modules (EXE and DLL) loaded either by
DosExecPgm (EXE) or DosLoadModule(DLL).

0 - type (module = 2)
1 - offset to next record
2 - module handle
3 - number of dependencies
4 - offset to list of dependencies (offset of the 6th word below)
5 - offset to module name
6 - list of dependent module handles
..
  - module name (null-terminated string)
(other unknown information)


type 3 (systen semaphore record)

0 - type (semaphore = 3)
1 - offset to next record
2 - index ? (seems to refer to owner)
3 - two bytes (low = number of references, high = number of requests)
4 - flag ?
6 - semaphore name (null-terminated string)


type 4 (shared memory record)

0 - type (shared memory = 4)
1 - offset to next record
2 - handle
3 - segment selector
4 - number of references
6 - name of segment (null-terminated string)
(other unknown information)


Semaphore information is still a bit unclear.


The following sample program demonstrates how to use the information
about processes, threads and modules. The analyzing code in
parse_processes() was based on the code of the program RUNNING which I
got from listserv@blekul11 but I corrected and rearranged the code.

/* PROCS.C
 *
 * Sample program using the DosQPocStatus() function
 * Kai Uwe Rommel - Sat 04-Aug-1990
 */

#define INCL_NOPM
#define INCL_DOSPROCESS
#define INCL_DOSMODULEMGR
#define INCL_DOSMEMMGR
#include <os2.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


extern USHORT APIENTRY DosQProcStatus(PVOID pBuf, USHORT cbBuf);


struct process
{
  USHORT pid;
  USHORT ppid;
  USHORT session;
  USHORT threads;
  USHORT children;
  USHORT modhandle;
  USHORT module;
};


struct module
{
  USHORT modhandle;
  USHORT max_dependents;
  USHORT *dependents;
  UCHAR  *name;
  USHORT listed;
};


struct semaphore
{
  USHORT refs;
  USHORT requests;
  UCHAR  *name;
};


struct shmem
{
  USHORT handle;
  USHORT selector;
  USHORT refs;
  UCHAR  *name;
};


struct process   **proc = NULL;
struct module    **mod  = NULL;
struct semaphore **sem  = NULL;
struct shmem     **shm  = NULL;

USHORT max_proc = 0;
USHORT cur_proc = 0;
USHORT max_mod  = 0;
USHORT cur_mod  = 0;
USHORT max_sem  = 0;
USHORT cur_sem  = 0;
USHORT max_shm  = 0;
USHORT cur_shm  = 0;


int compare_proc(struct process **p1, struct process **p2)
{
  return (*p1) -> pid - (*p2) -> pid;
}


int compare_mod(struct module **m1, struct module **m2)
{
  return (*m1) -> modhandle - (*m2) -> modhandle;
}


int parse_buffer(UCHAR * bBuf)
{
  USHORT type, tpid, seminf;
  USHORT count, kount;
  UCHAR buffer[256];
  UCHAR *cptr, *ptr;
  UCHAR *next;

  ptr = bBuf;

  while ( (type = *(USHORT *) ptr) != 0xFFFFU )
  {
    ptr += 2;
    next = *(UCHAR **) ptr;
    ptr += 2;

    switch ( type )
    {

    case 0: /* process */

      if ( cur_proc >= max_proc )
      {
        max_proc += 50;

	if ( !(proc = realloc(proc, max_proc * sizeof(struct process *))) )
          return 1;
      }

      if ( !(proc[cur_proc] = calloc(1, sizeof(struct process))) )
        return 1;

      proc[cur_proc] -> pid = *(USHORT *) ptr;
      ptr += 2;
      proc[cur_proc] -> ppid = *(USHORT *) ptr;
      ptr += 2;
      proc[cur_proc] -> session = *(USHORT *) ptr;
      ptr += 2;
      proc[cur_proc] -> modhandle = *(USHORT *) ptr;

      proc[cur_proc] -> threads = 0;
      proc[cur_proc] -> module  = -1;
      ++cur_proc;

      break;

    case 1: /* thread */

      ptr += 2;
      tpid = *(USHORT *) ptr;

      for ( count = 0; count < cur_proc; count++ )
	if ( proc[count] -> pid == tpid )
	{
	  ++proc[count] -> threads;
	  break;
	}

      break;

    case 2: /* module */

      if ( cur_mod >= max_mod )
      {
        max_mod += 50;

	if ( !(mod = realloc(mod, max_mod * sizeof(struct module *))) )
          return 1;
      }

      if ( !(mod[cur_mod] = calloc(1, sizeof(struct module))) )
        return 1;

      mod[cur_mod] -> modhandle = *(USHORT *) ptr;
      ptr += 2;
      mod[cur_mod] -> max_dependents = *(USHORT *) ptr;
      ptr += 2;
      ptr += 2;
      ptr += 2;

      if ( mod[cur_mod] -> max_dependents )
      {
	if ( !(mod[cur_mod] -> dependents = calloc(mod[cur_mod] -> max_dependents, sizeof(USHORT))) )
          return 1;

	for ( count = 0; count < mod[cur_mod] -> max_dependents; count++ )
	{
	  mod[cur_mod] -> dependents[count] = *(USHORT *) ptr;
	  ptr += 2;
	}
      }

      for ( cptr = buffer; *cptr++ = *ptr++; );

      if ( !(mod[cur_mod] -> name = strdup(buffer)) )
        return 1;

      ++cur_mod;

      break;

    case 3: /* system semaphore */

      if ( cur_sem >= max_sem )
      {
        max_sem += 50;

	if ( !(sem = realloc(sem, max_sem * sizeof(struct semaphore *))) )
          return 1;
      }

      if ( !(sem[cur_sem] = calloc(1, sizeof(struct semaphore))) )
        return 1;

      ptr += 2;
      seminf = *(USHORT *) ptr;
      sem[cur_sem] -> refs = seminf & 0xFF;
      sem[cur_sem] -> requests = seminf >> 8;
      ptr += 2;
      ptr += 2;

      for ( cptr = buffer; *cptr++ = *ptr++; );

      if ( !(sem[cur_sem] -> name = strdup(buffer)) )
        return 1;

      ++cur_sem;

      break;

    case 4: /* shared memory */

      if ( cur_shm >= max_shm )
      {
        max_shm += 50;

	if ( !(shm = realloc(shm, max_shm * sizeof(struct shmem *))) )
          return 1;
      }

      if ( !(shm[cur_shm] = calloc(1, sizeof(struct shmem))) )
        return 1;

      shm[cur_shm] -> handle = *(USHORT *) ptr;
      ptr += 2;
      shm[cur_shm] -> selector = *(USHORT *) ptr;
      ptr += 2;
      shm[cur_shm] -> refs = *(USHORT *) ptr;
      ptr += 2;

      for ( cptr = buffer; *cptr++ = *ptr++; );

      if ( !(shm[cur_shm] -> name = strdup(buffer)) )
        return 1;

      ++cur_shm;

      break;

    default: /* other ? */
      break;

    }

    ptr = next;
  }

  qsort(proc, cur_proc, sizeof(struct process *), compare_proc);
  qsort(mod, cur_mod, sizeof(struct module *), compare_mod);

  for ( count = 0; count < cur_proc; count++ )
    for ( kount = 0; kount < cur_mod; kount++ )
      if ( proc[count] -> modhandle == mod[kount] -> modhandle )
      {
        proc[count] -> module = kount;
	break;
      }

  for ( count = 0; count < cur_proc; count++ )
    for ( kount = 0; kount < cur_proc; kount++ )
      if ( proc[count] -> pid == proc[kount] -> ppid )
	(proc[count] -> children)++;

  return 0;
}


void free_data()
{
  USHORT count;

  for (count = 0; count < cur_proc; count++)
    free(proc[count]);

  for (count = 0; count < cur_mod; count++)
  {
    if ( mod[count] -> max_dependents )
      free(mod[count] -> dependents);

    free(mod[count] -> name);
    free(mod[count]);
  }

  for (count = 0; count < cur_sem; count++)
  {
    free(sem[count] -> name);
    free(sem[count]);
  }

  for (count = 0; count < cur_shm; count++)
  {
    free(shm[count] -> name);
    free(shm[count]);
  }

  free(proc);
  free(mod);
  free(sem);
  free(shm);

  max_proc = max_mod = cur_proc = cur_mod = 0;
  max_sem  = max_shm = cur_sem  = cur_shm = 0;
  proc = NULL;
  mod  = NULL;
}


void proctree(USHORT pid, USHORT indent)
{
  USHORT count;
  UCHAR *mName, pName[256];

  for (count = 0; count < cur_proc; count++)
    if ( proc[count] -> ppid == pid )
    {
      if ( proc[count] -> module != -1 )
      {
        mName = mod[proc[count] -> module] -> name;
        DosGetModName(proc[count] -> modhandle, sizeof(pName), pName);
      }
      else
      {
        mName = "unknown";  /* Zombie process, i.e. result for DosCwait() */
        pName[0] = 0;       /* or DOS box or swapper (?) */
      }

#ifdef FULL
      printf("%5d  %5d   %02x  %4d  %4d  %-8s %*s%s\n",
        proc[count] -> pid, proc[count] -> ppid, proc[count] -> session,
        proc[count] -> children, proc[count] -> threads,
        mName, indent, "", pName);
#else
      printf("%5d   %02x  %4d  %-8s %*s%s\n",
        proc[count] -> pid, proc[count] -> session,
        proc[count] -> threads, mName, indent, "", pName);
#endif

      proctree(proc[count] -> pid, indent + 2);
    }
}


void modlist(void)
{
  UCHAR pName[256];
  USHORT count;

  for (count = 0; count < cur_mod; count++)
  {
    DosGetModName(mod[count] -> modhandle, sizeof(pName), pName);
    printf("%-8s  %04x  %s\n",
      mod[count] -> name, mod[count] -> modhandle, pName);
  }
}


void modtree(USHORT module, USHORT indent)
{
  UCHAR *mName, pName[256];
  USHORT cnt1, cnt2;

  if ( module == -1 )
    return;

  mName = mod[module] -> name;
  DosGetModName(mod[module] -> modhandle, sizeof(pName), pName);

  if ( mod[module] -> listed )
  {
    printf("%*s%s*\n", indent, "", mName);
    return;
  }
  else
    printf("%*s%-8s%*s%s\n", indent, "", mName, 32 - indent, "", pName);

  mod[module] -> listed = 1;

  for ( cnt1 = 0; cnt1 < mod[module] -> max_dependents; cnt1++ )
    for ( cnt2 = 0; cnt2 < cur_mod; cnt2++ )
      if ( mod[cnt2] -> modhandle == mod[module] -> dependents[cnt1] )
        modtree(cnt2, indent + 2);
}


void semlist(void)
{
  USHORT count;

  for (count = 0; count < cur_sem; count++)
    printf("%4d  %4d  %s\n",
      sem[count] -> refs, sem[count] -> requests, sem[count] -> name);
}


void shmlist(void)
{
  USHORT count;
  ULONG size;
  SEL sel;
  UCHAR name[256];

  for (count = 0; count < cur_shm; count++)
  {
    strcpy(name, "\\SHAREMEM\\");
    strcat(name, shm[count] -> name);

    DosGetShrSeg(name, &sel);
    if ( DosSizeSeg(sel, &size) )
      size = 0L;
    DosFreeSeg(sel);

    printf(" %04x   %04x   %04lx  %4d  %s\n",
      shm[count] -> handle, shm[count] -> selector, size,
      shm[count] -> refs, shm[count] -> name);
  }
}


void main(void)
{
  UCHAR *pBuf;
  USHORT count;

  pBuf = malloc(0x8000);
  DosQProcStatus(pBuf, 0x8000);

  if ( parse_buffer(pBuf) )
  {
    printf("Error: Out of memory!\n");
    DosExit(EXIT_PROCESS, 1);
  }

  free(pBuf);

#ifdef FULL
  printf("\n PID    PPID  SESS CHLDS THRDS MODULE   PROGRAM");
  printf("\n------ ------ ---- ----- ----- -------- ------->\n");
#else
  printf("\n PID   SESS THRDS MODULE   PROGRAM");
  printf("\n------ ---- ----- -------- ------->\n");
#endif

  proctree(0, 0);

  printf("\nMODULE   HANDLE PATH");
  printf("\n-------- ------ ---->\n");

  modlist();

  printf("\nMODULE TREE");
  printf("\n-----------\n");

  for (count = 0; count < cur_proc; count++)
    modtree(proc[count] -> module, 0);

  printf("\n REF   REQ  NAME");
  printf("\n----- ----- ---->\n");

  semlist();

  printf("\nHANDLE  SEL    SIZE   REF  NAME");
  printf("\n------ ------ ------ ----- ---->\n");

  shmlist();

  free_data();

  DosExit(EXIT_PROCESS, 0);
}


/* End of PROCS.C */
Re: Porting from Unix to OS/2
#3236
Author: Mark Towfiq
Date: Mon, 24 Jun 1991 19:41
215 lines
7623 bytes
>>>>> 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 <bsd.h> 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
Re: Porting from Unix to OS/2
#3238
Author: David Scavo
Date: Tue, 25 Jun 1991 13:13
20 lines
1415 bytes
In <TOWFIQ.91Jun24154144@babyoil.FTP.COM> towfiq@FTP.COM (Mark Towfiq) writes:

>>>>>> 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! :-)  

I am also greatly interested in this thread, since in the next two months
I will be porting a multi-threaded task dispatcher to UNIX (from OS/2
obviously). I have been saving all the past articles of this thread,
so keep them coming. :)
-- 
   --------------------------------------------------------------------------
   Internet: dscavo@ncratl.AtlantaGA.NCR.COM              NCR Corporation
   UCCP: ... !gatech!kong!ncratl!dscavo                   2651 Satellite Blvd
    "Bart, you say butt kisser like it is a bad thing"    Duluth, GA 30136
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads