0% found this document useful (0 votes)
182 views

OSS Programmers Guide

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
182 views

OSS Programmers Guide

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 536

Open System Services Programmer’s Guide

HP Part Number: 520574-014


Published: August 2010
Edition: J06.03 and subsequent J-series RVUs, H06.03 and subsequent H-series RVUs, and G06.25 and subsequent G-series RVUs
© Copyright 2010 Hewlett-Packard Development Company, L.P.
Legal Notice
Confidential computer software. Valid license from HP required for possession, use or copying. Consistent with FAR 12.211 and 12.212, Commercial
Computer Software, Computer Software Documentation, and Technical Data for Commercial Items are licensed to the U.S. Government under
vendor’s standard commercial license.

The information contained herein is subject to change without notice. The only warranties for HP products and services are set forth in the express
warranty statements accompanying such products and services. Nothing herein should be construed as constituting an additional warranty. HP
shall not be liable for technical or editorial errors or omissions contained herein.

Export of the information contained in this publication may require authorization from the U.S. Department of Commerce.

Microsoft, Windows, and Windows NT are U.S. registered trademarks of Microsoft Corporation.

Intel, Pentium, and Celeron are trademarks or registered trademarks of Intel Corporation or its subsidiaries in the United States and other
countries.

Java is a U.S. trademark of Sun Microsystems, Inc.

Motif, OSF/1, UNIX, X/Open, and the "X" device are registered trademarks, and IT DialTone and The Open Group are trademarks of The Open
Group in the U.S. and other countries.

Open Software Foundation, OSF, the OSF logo, OSF/1, OSF/Motif, and Motif are trademarks of the Open Software Foundation, Inc. OSF MAKES
NO WARRANTY OF ANY KIND WITH REGARD TO THE OSF MATERIAL PROVIDED HEREIN, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. OSF shall not be liable for errors contained
herein or for incidental consequential damages in connection with the furnishing, performance, or use of this material.

© 1990, 1991, 1992, 1993 Open Software Foundation, Inc. The OSF documentation and the OSF software to which it relates are derived in part
from materials supplied by the following:© 1987, 1988, 1989 Carnegie-Mellon University. © 1989, 1990, 1991 Digital Equipment Corporation. ©
1985, 1988, 1989, 1990 Encore Computer Corporation. © 1988 Free Software Foundation, Inc. © 1987, 1988, 1989, 1990, 1991 Hewlett-Packard
Company. © 1985, 1987, 1988, 1989, 1990, 1991, 1992 International Business Machines Corporation. © 1988, 1989 Massachusetts Institute of
Technology. © 1988, 1989, 1990 Mentat Inc. © 1988 Microsoft Corporation. © 1987, 1988, 1989, 1990, 1991, 1992 SecureWare, Inc. © 1990, 1991
Siemens Nixdorf Informationssysteme AG. © 1986, 1989, 1996, 1997 Sun Microsystems, Inc. © 1989, 1990, 1991 Transarc Corporation.OSF software
and documentation are based in part on the Fourth Berkeley Software Distribution under license from The Regents of the University of California.
OSF acknowledges the following individuals and institutions for their role in its development: Kenneth C.R.C. Arnold, Gregory S. Couch, Conrad
C. Huang, Ed James, Symmetric Computer Systems, Robert Elz. © 1980, 1981, 1982, 1983, 1985, 1986, 1987, 1988, 1989 Regents of the University
of California.
Table of Contents
About This Document.......................................................................................................15
About TNS, TNS/R Native, and TNS/E Native Processes....................................................................15
About the Examples..............................................................................................................................15
About OSS Utilities...............................................................................................................................15
Supported Release Version Updates (RVUs)........................................................................................16
Intended Audience................................................................................................................................16
New and Changed Information............................................................................................................16
Changes made to the 520674-014 Edition........................................................................................16
Changes made to the 520674-013 Edition........................................................................................16
Changes made to the 520674-012 Edition........................................................................................17
Changes Made to the 520674-011 Edition........................................................................................17
Changes Made to the 520674-010 Edition........................................................................................17
Changes Made to the 520674-009 Edition........................................................................................17
Changes Made to the 520674-008 Edition........................................................................................17
Changes Made to the 520674-007 Edition........................................................................................18
Document Organization.......................................................................................................................18
Notation Conventions...........................................................................................................................19
General Syntax Notation.................................................................................................................19
Related Information..............................................................................................................................21
Publishing History................................................................................................................................23
HP Encourages Your Comments..........................................................................................................24

1 Overview of the OSS Programming Environment.....................................................25


The OSS API..........................................................................................................................................25
Standards Conformance..................................................................................................................26
Extensions Based on Standards or Proposed Standards.................................................................27
Two File Systems...................................................................................................................................27
The OSS File System........................................................................................................................27
The Guardian File System...............................................................................................................29
Two Process Types................................................................................................................................31
Process Identification.......................................................................................................................32
Process Groups................................................................................................................................32
Process Ancestors............................................................................................................................33
Process Attributes............................................................................................................................34
Process Environment.......................................................................................................................34
Process Pairs....................................................................................................................................34
Native and TNS Processes...............................................................................................................34
Selecting Source and Target Execution Environments.........................................................................34
The Typical Case..............................................................................................................................35
Special Cases of Cross Compilation................................................................................................35
Calling Functions and Procedures in OSS Programs...........................................................................35
OSS Functions..................................................................................................................................35
Guardian Procedures.......................................................................................................................35
Guardian C Functions.....................................................................................................................40
Refer to Bits From Left to Right.......................................................................................................41
Using the Development Tools...............................................................................................................41
Using Tools in Both Environments..................................................................................................41
OSS Tools.........................................................................................................................................42
Guardian Tools................................................................................................................................47
Using the NonStop Development Environment for Eclipse................................................................49

Table of Contents 3
Using the HP Enterprise Toolkit - NonStop Edition.............................................................................49

2 Managing Files............................................................................................................51
The OSS and Guardian File Systems....................................................................................................51
Physical and Logical Names............................................................................................................51
Filename and Pathname Mappings.................................................................................................52
Obtaining Corresponding Guardian and OSS Filenames...............................................................54
Using Guardian Procedures............................................................................................................55
OSS File-Access Permissions...........................................................................................................60
Safeguard Protection and Disk Volumes.........................................................................................61
OSS ACLs.........................................................................................................................................61
Accessible Files................................................................................................................................62
Using the ANSISTREAMS Pragma (Guardian C Program)............................................................62
Common and Unique Characteristics...................................................................................................62
Features Common to the UNIX and OSS File Systems...................................................................62
Features Unique to the OSS File System.........................................................................................62
Accessing Files From the OSS API........................................................................................................63
Using Functions With Environment-Specific Parameters...............................................................64
Accessing Files From the Guardian API...............................................................................................65
Guardian Procedure Extensions for OSS.........................................................................................65
Using Extended Guardian Procedures............................................................................................69
Accessing OSS Files Larger Than 2 GB.................................................................................................74
Small Files and Large Files..............................................................................................................74
Large File Safe APIs.........................................................................................................................75
Large File Aware APIs.....................................................................................................................76
Interoperability................................................................................................................................77
Common Completion...........................................................................................................................79
Performance Considerations.................................................................................................................82
File Caching.....................................................................................................................................82
Performance and Reliability Tradeoffs............................................................................................84
OSS File-System Functions...................................................................................................................84
Guardian File-System Procedures........................................................................................................94

3 Managing Processes....................................................................................................97
Common and Unique Characteristics...................................................................................................97
Features Common to UNIX and OSS Process Management...........................................................97
Features Unique to OSS Process Management..............................................................................105
Process Attributes...............................................................................................................................105
OSS Attributes in Guardian Processes..........................................................................................105
Guardian Attributes in OSS Processes..........................................................................................105
Comparing OSS and Guardian Process Attributes.......................................................................106
Process-Management Interoperability................................................................................................107
Signals Interoperability..................................................................................................................110
Creating and Controlling Processes....................................................................................................111
Using the OSS API.........................................................................................................................111
Using the Guardian API................................................................................................................115
Querying the Process Environment....................................................................................................121
Using the OSS API.........................................................................................................................121
Using the Guardian API................................................................................................................122
Modifying the Process Environment..................................................................................................127
Using the OSS API.........................................................................................................................127
Using the Guardian API................................................................................................................128
Performance Considerations...............................................................................................................130

4 Table of Contents
Using Dynamic Servers Spread Across Available Processors.......................................................130
Using Static Servers Spread Across Available Processors.............................................................134
OSS Process-Management Functions..................................................................................................141
Guardian Process-Management Procedures.......................................................................................146

4 Managing Memory Segments.................................................................................149


What Is Not in This Section.................................................................................................................149
Common and Unique Characteristics.................................................................................................150
Features Common to UNIX and OSS Memory Management ......................................................150
Features Unique to OSS Memory Management ...........................................................................150
Memory-Management Interoperability..............................................................................................150
Use One API to Manipulate a Memory Segment..........................................................................150
About Extended Data Segments.........................................................................................................150
Flat Segments.................................................................................................................................151
Selectable Segments.......................................................................................................................151
When Processes Share Memory Using Guardian Procedures............................................................151
TNS Processes Should Not Share a Selectable Segment................................................................151
Performance Considerations...............................................................................................................152
OSS Memory-Management Functions................................................................................................152
Guardian Memory-Management Procedures.....................................................................................152

5 Managing Time.........................................................................................................155
Common and Unique Characteristics.................................................................................................155
Features Common to UNIX and OSS Time Management.............................................................155
Features Unique to OSS Time Management..................................................................................156
Time-Management Interoperability....................................................................................................156
Querying the System Clock................................................................................................................156
Querying Process Times......................................................................................................................157
Limiting Processor Time Use..............................................................................................................157
OSS Time-Management Functions.....................................................................................................157
Guardian Time-Management Procedures..........................................................................................160

6 Interprocess Communication....................................................................................163
Available Methods..............................................................................................................................163
Common and Unique Characteristics.................................................................................................164
Features Common to UNIX and OSS Interprocess Communication............................................164
Features Unique to OSS Interprocess Communication.................................................................165
Interprocess-Communication Interoperability...................................................................................165
Using Guardian AF_INET and AF_NET6 Sockets, and OSS AF_INET and AF_INET6 Sockets...165
Using AF_UNIX Sockets.................................................................................................................176
Using FIFOs...................................................................................................................................178
Using Guardian Shared Memory and Semaphores......................................................................178
Using the $RECEIVE File...............................................................................................................179
Performance Considerations...............................................................................................................183
OSS Interprocess-Communication Functions.....................................................................................184
Guardian Interprocess-Communication Procedures..........................................................................191

7 Managing I/O...........................................................................................................195
Common and Unique Characteristics.................................................................................................195
Features Common to UNIX and OSS Terminal I/O Management................................................195
Features Unique to OSS Terminal I/O Management.....................................................................195
I/O Interoperability.............................................................................................................................195

Table of Contents 5
Tape I/O...............................................................................................................................................196
Tape I/O With pax .........................................................................................................................196
Tape I/O With the Guardian API...................................................................................................197
Terminal I/O........................................................................................................................................198
Accessing Terminals From the OSS Environment.........................................................................198
Blocking and Nonblocking Opens.................................................................................................199
Blocking and Nonblocking Terminal I/O.......................................................................................199
Terminal Parameters......................................................................................................................199
Control Characters.........................................................................................................................199
Accessing Terminals From the Guardian Environment................................................................200
Using OSSTTY to Redirect Input and Output to Guardian Objects...................................................202
Starting OSSTTY............................................................................................................................203
Examples of OSSTTY Usage..........................................................................................................205
Printer I/O...........................................................................................................................................214
Printing With the OSS API.............................................................................................................214
Printing OSS Files With the Guardian API....................................................................................215
OSS I/O Management Functions.........................................................................................................221
Guardian I/O Management Procedures..............................................................................................222

8 Using Logging Mechanisms.....................................................................................225


Common and Unique Characteristics.................................................................................................225
Features Common to UNIX and OSS Logging..............................................................................225
Features Unique to OSS Logging...................................................................................................226
Logging Interoperability.....................................................................................................................226
How to Log Information With the OSS API.......................................................................................226
Specifying a Collector ...................................................................................................................227
Specifying the Severity Level of Logged Events............................................................................227
Initializing Logging Parameters....................................................................................................228
Logging a Message........................................................................................................................229
Closing a Collector ........................................................................................................................231
Logging Parameters and EMS Tokens...........................................................................................231
OSS Logging-Mechanism Functions...................................................................................................232

9 Using Subsystems From OSS....................................................................................235


Communications Subsystems.............................................................................................................235
Subsystems Supporting the Subsystem Programmatic Interface (SPI)..............................................235
HP NonStop SQL/MP.........................................................................................................................236
HP NonStop SQL/MX.........................................................................................................................236
HP NonStop TS/MP............................................................................................................................236
HP NonStop TMF................................................................................................................................237
HP NonStop Tuxedo System...............................................................................................................237
HP NonStop Distributed Computing Environment (DCE)................................................................237
Simple Network Management Protocol (SNMP)...............................................................................238

10 Managing OSS Security.........................................................................................239


Common and Unique Characteristics.................................................................................................239
Functions Available for Security Management...................................................................................240
Security Auditing of OSS files.............................................................................................................243
How to Identify an Audited file in Audit Records........................................................................243
What Operations and Objects Are Audited..................................................................................243
Considerations for File Auditing...................................................................................................245
Example of Managing file Ownership................................................................................................246
Using OSS Access Control Lists (ACLs).............................................................................................249
6 Table of Contents
Definitions......................................................................................................................................250
Access Control List Entries............................................................................................................251
ACL Notation.................................................................................................................................251
Types of ACL Entries.....................................................................................................................251
Optional ACL Entries....................................................................................................................252
ACL Uniqueness............................................................................................................................253
ACL Inheritance.............................................................................................................................253
Access Check Algorithm................................................................................................................256
ACL Operations Supported...........................................................................................................256
ACL Interaction with stat().......................................................................................................256
ACL Interaction with chmod().....................................................................................................257
ACL Interaction with chown().....................................................................................................257
OSS Network File System (NFS) and ACLs..................................................................................257
Header file.....................................................................................................................................258
Example Program For ACLs..........................................................................................................258

11 Using the Standard POSIX Threads Library...........................................................261


Standard POSIX Threads....................................................................................................................261
Compiling and Linking Considerations........................................................................................262
Error Reporting Changed From Previous Standard......................................................................262
Attributes Defined by Threads Macros ........................................................................................262
Signal Handling.............................................................................................................................263
Thread-Aware Signal Handling.....................................................................................................265
Threads Portability........................................................................................................................275
Numerical Limits in Standard POSIX Threads.............................................................................275
Keeping Application Design Simple.............................................................................................276
Threading Considerations...................................................................................................................276
Sharing Process Resources.............................................................................................................276
Using Standard Libraries...............................................................................................................276
Addressing the Thread Stack.........................................................................................................277
Making Process-Blocking Calls.....................................................................................................277
Using Nowait Input or Output......................................................................................................277
Yielding Control.............................................................................................................................278
Using Signals.................................................................................................................................278
Spawning a New Process...............................................................................................................279
Isolating Faults...............................................................................................................................279
Single Versus Multiple Application Threads......................................................................................279
Programs With a Single Application Thread.................................................................................279
Programs With Multiple Independent Application Threads........................................................280
Programs With Multiple Interdependent Application Threads....................................................280
Jacket Routines....................................................................................................................................281
SERVERCLASS_SEND and SERVERCLASS_SENDL Jacket Routines.........................................281
SERVERCLASS_DIALOG Jacket Routines....................................................................................281
TMF Transaction Jacket Routines..................................................................................................282
Reference Pages for Thread Functions................................................................................................283
Threaded Application Examples........................................................................................................283
Thread-Aware and Nonblocking OSS Functions................................................................................288
Regular Files..................................................................................................................................289
Non-Regular Files..........................................................................................................................290
Equivalent System, Thread-Aware, and Nonblocking Thread-Aware Functions.........................291
Preprocessor Directives Automatically Map Standard System Calls to Thread-Aware or
Nonblocking Thread-Aware System Calls....................................................................................293
Using Thread-Aware Functions.....................................................................................................296
Reentrant OSS Functions....................................................................................................................313

Table of Contents 7
Example Program Using Reentrant Functions..............................................................................315
Thread-Aware Toolkit Functions and Types.................................................................................316
Using Thread-Aware Toolkit Functions........................................................................................317
Caveats to Using the Thread-Aware Toolkit .................................................................................320
Thread-Aware $RECEIVE I/O Functions.......................................................................................320
Using Thread-Aware $RECEIVE Functions..................................................................................321
Caveats to Using Thread-Aware $RECEIVE.................................................................................324
Thread-Aware Enscribe Functions......................................................................................................324
Using Thread-Aware Enscribe Functions......................................................................................325
OSS File Descriptor and Timer Callbacks...........................................................................................326
Using OSS and Timer Callbacks....................................................................................................327
Caveat to Using Callbacks.............................................................................................................327

12 Using the POSIX User Thread (PUT) Model Library ............................................329


Compiling and Linking Considerations.............................................................................................329
Header Files...................................................................................................................................329
Linking to the POSIX User Thread Model Library........................................................................329
Defines...........................................................................................................................................329
Environment Variables..................................................................................................................330
Standards Conformance......................................................................................................................330
Error Reporting Changed From Draft 4 Standard.........................................................................330
Exceptions and Extensions to the Standard Document.................................................................330
Attributes Defined by Threads Macros ..............................................................................................331
Process Resources................................................................................................................................332
Numerical Limits in the POSIX User Thread Model Library.............................................................332
Protected Stack Limits...................................................................................................................332
Limits Imposed by the Standard...................................................................................................333
Signals and Signal Handling...............................................................................................................334
Types of Signals.............................................................................................................................334
Using Signals.................................................................................................................................335
Thread-Aware Signal Handling.....................................................................................................337
Thread-Aware and Nonblocking OSS Functions................................................................................345
Regular Files..................................................................................................................................345
Non-Regular Files..........................................................................................................................346
Equivalent System, Thread-Aware, and Nonblocking Thread-Aware Functions.........................346
The Set of Thread-Aware I/O Functions Must Be Used Together.................................................348
Using Thread-Aware Functions.....................................................................................................348
Threads Portability..............................................................................................................................356
Thread Safety......................................................................................................................................356
Functions That Are Not Thread Safe.............................................................................................357
Cancellation Points........................................................................................................................357
Potential Cancellation Points.........................................................................................................358
Reentrant OSS Functions....................................................................................................................358
Example Program Using Reentrant Functions..............................................................................359
Thread-Aware Toolkit Functions and Types.................................................................................360
Using Thread-Aware Toolkit Functions........................................................................................361
Caveats to Using the Thread-Aware Toolkit .................................................................................364
Thread-Aware $RECEIVE I/O Functions.......................................................................................364
Using Thread-Aware $RECEIVE Functions..................................................................................365
Caveats to Using Thread-Aware $RECEIVE.................................................................................368
Jacket Routines (Nonblocking Versions of SEVERCLASS_ and TMF System Calls).........................368
SERVERCLASS_SEND and SERVERCLASS_SENDL Jacket Routines.........................................368
SERVERCLASS_DIALOG Jacket Routines....................................................................................368
TMF Transaction Jacket Routines..................................................................................................369

8 Table of Contents
Thread-Aware Enscribe Functions......................................................................................................370
Using Thread-Aware Enscribe Functions......................................................................................371
OSS File Descriptor and Timer Callbacks...........................................................................................372
Using OSS and Timer Callbacks....................................................................................................373
Caveat to Using Callbacks.............................................................................................................373
Converting Applications that use the SPT Library.............................................................................373
Build Scripts...................................................................................................................................374
Header Files...................................................................................................................................374
Standard and Nonstandard Pthread Types...................................................................................375
Global Variables.............................................................................................................................375
Concurrency Level Defaults..........................................................................................................375
Differences in Functions and Function Behavior..........................................................................375
Threaded Application Programming.................................................................................................378
Keeping Application Design Simple.............................................................................................378
Threading Considerations.............................................................................................................378
Single Versus Multiple Application Threads.................................................................................381
Threaded Application Examples...................................................................................................382

A Documented OSS Functions.....................................................................................389

B API Interoperability in TNS Processes......................................................................427


Calling Functions and Macros............................................................................................................427
Environment of the Module..........................................................................................................427
Environment of the Process...........................................................................................................427
Function and Macro Behavior.......................................................................................................428
Using the API Interoperability Table..................................................................................................428
G and O Notation..........................................................................................................................429
Specified By....................................................................................................................................429
Defining Parameters and Objects..................................................................................................429
Usage Notes...................................................................................................................................429
Examples........................................................................................................................................430

C API Interoperability in Native Processes.................................................................451


Comparing API Interoperability in TNS and Native Processes.........................................................451
Calling Functions and Macros............................................................................................................451
Environment of the Module..........................................................................................................452
Environment of the Process...........................................................................................................452
Function and Macro Behavior.......................................................................................................452
Internationalization Functions.......................................................................................................452
Using the API Interoperability Tables.................................................................................................452
G and O Notation..........................................................................................................................453
Specified By....................................................................................................................................453
Defining Parameters and Objects..................................................................................................454
Usage Notes...................................................................................................................................454
Examples........................................................................................................................................456

Glossary.........................................................................................................................515

Index...............................................................................................................................523

Table of Contents 9
List of Figures
1-1 The Operating Environment for NonStop Systems......................................................................26
1-2 OSS Filenames and Disks..............................................................................................................28
1-3 Components of Guardian File Names...........................................................................................29
1-4 Guardian File Names and Disks...................................................................................................30
1-5 Guardian Files in the OSS File System..........................................................................................31
7-1 OSSTTY Interaction With OSS and Guardian Environments.....................................................203
10-1 Major Components and Interfaces for OSS Security Management.............................................241

10 List of Figures
List of Tables
1 Related Manuals............................................................................................................................22
1-1 OSS and Guardian Process Identifiers .........................................................................................32
1-2 Sample c89 Commands ................................................................................................................44
2-1 OSS Pathname to Guardian Filename Translation Examples.......................................................53
2-2 Guardian Filename to OSS Pathname Translation Examples ......................................................53
2-3 Mappings of Guardian Security to OSS File-Access Permissions ................................................60
2-4 I/O Buffering, Fault Tolerance, and Performance.........................................................................83
2-5 OSS File-System Functions ...........................................................................................................85
2-6 Guardian File-System Procedures ................................................................................................94
3-1 OSS and Guardian Process Attribute Comparison ....................................................................106
3-2 Guardian Process-Management Procedures That Can Access OSS Processes ..........................107
3-3 OSS Process-Management Functions That Can Access Guardian Processes .............................108
3-4 OSS Process-Management Functions..........................................................................................141
3-5 Guardian Process-Management Procedures...............................................................................147
4-1 OSS Memory Management Functions.........................................................................................152
4-2 Guardian Memory Management Functions................................................................................153
5-1 Guardian and OSS Timestamps .................................................................................................156
5-2 OSS Time-Management Functions .............................................................................................159
5-3 Guardian Time-Management Procedures ..................................................................................161
6-1 Interprocess Communication Using OSS APIs...........................................................................163
6-2 Interprocess Communication Using OSS and Guardian APIs ...................................................164
6-3 OSS Interprocess-Communication Functions.............................................................................185
6-4 OSS Interprocess-Communication-Related Functions................................................................188
6-5 Guardian Interprocess-Communication Procedures..................................................................191
6-6 Guardian Interprocess-Communication-Related Procedures.....................................................193
7-1 Canonical Mode Control Characters and Associated Flags in termios.h ...................................200
7-2 Noncanonical Mode Control Characters and Associated Flags in termios.h ............................200
7-3 OSS I/O Functions........................................................................................................................221
7-4 Guardian I/O Procedures............................................................................................................223
8-1 OSS Logging Functions ..............................................................................................................226
8-2 OSS Logging Function Parameters and Default Values .............................................................227
8-3 Logging Level Event Numbers and Strings ...............................................................................228
8-4 openlog() Parameters Used by OSS Logging Mechanism ..........................................................228
8-5 OSS Logging Facilities ................................................................................................................228
8-6 OSS Logging Options .................................................................................................................229
8-7 OSS Logging Function Parameters and Corresponding EMS Tokens .......................................232
8-8 OSS Logging-Mechanism Functions...........................................................................................232
10-1 OSS Security-Related Functions .................................................................................................241
10-2 OSS Function Calls Audited When Used With Audited filesets ................................................243
10-3 Guardian Procedure Calls Audited When Used With Audited filesets ....................................245
10-4 Guardian Procedure Calls Audited When Used for Process Control ........................................245
10-5 Base ACL Entries.........................................................................................................................252
10-6 Actual (Nondefault) Optional ACL Entries................................................................................252
10-7 Default ACL Entries....................................................................................................................253
11-1 Process Resources........................................................................................................................261
11-2 Attributes of Standard POSIX Threads Defined by Macros........................................................263
11-3 Signals Processed by Threads......................................................................................................264
11-4 Numerical Limits in Standard POSIX Threads ..........................................................................275
11-5 Comparison of spt_*, spt_*x, and spt_*z Functions...........................................................291
11-6 System and Equivalent Thread-Aware Functions ......................................................................292
11-7 System and Equivalent Reentrant Functions ..............................................................................314

11
11-8 Thread-Aware Toolkit Functions and Types...............................................................................317
11-9 Thread-Aware $RECEIVE Functions and Types.........................................................................321
11-10 Thread-Aware Enscribe Functions .............................................................................................324
11-11 Thread-Aware Callback Functions and Types............................................................................327
12-1 Attributes of the POSIX User Thread Model Library Defined by Macros..................................331
12-2 Process Resources........................................................................................................................332
12-3 Numerical Limits in the POSIX User Thread Model Library .....................................................333
12-4 Signals Processed by Threads......................................................................................................334
12-5 System and Equivalent Thread-Aware Functions ......................................................................346
12-6 Thread-Aware Toolkit Functions and Types...............................................................................361
12-7 Thread-Aware $RECEIVE Functions and Types.........................................................................365
12-8 Thread-Aware Enscribe Functions .............................................................................................370
12-9 Thread-Aware Callback Functions and Types............................................................................373
12-10 Standard header files included in spthread.h and pthread.h header files..................................374
12-11 SPT Library Nonstandard Types and Corresponding PUT Model Library Standard Types.....375
12-12 Nonstandard pthread_ functions replaced by standard versions............................................376
B-1 API Interoperability in TNS Processes........................................................................................431
C-1 API Interoperability in Native Processes (Functions a through m)............................................457
C-2 API Interoperability in Native Processes (Functions n through z).............................................478

12 List of Tables
List of Examples
1-1 Using Some OSS Group Information Functions...........................................................................33
1-2 Calling a Guardian Procedure That Returns a Return Value .......................................................37
1-3 Calling a Guardian Procedure That Returns a Condition Code ..................................................39
1-4 Specifying the systype Option to the c89 Utility...........................................................................41
1-5 Linking Guardian Modules to OSS Programs..............................................................................41
1-6 Using gtacl to Run a TACL Command..........................................................................................42
1-7 Using gtacl to Pipe TACL Command Output to an OSS Utility...................................................42
1-8 Starting the Inspect or Native Inspect Debugger by Itself............................................................46
1-9 Starting the Inspect or Native Inspect Debugger and a Program at the Same Time....................46
1-10 Starting the Visual Inspect Debugger............................................................................................47
1-11 Convert Type 180 File to Type 101 File..........................................................................................47
1-12 Convert Type 101 File to Type 180 File..........................................................................................47
2-1 Using gname to Obtain a Guardian Filename..............................................................................54
2-2 Using pname to Obtain an OSS Pathname....................................................................................55
2-3 FUP INFO DETAIL Display With an OSS File..............................................................................55
2-4 Using the Guardian PATHNAME_TO_FILENAME_ Procedure.................................................56
2-5 Using the Guardian FILENAME_TO_PATHNAME_ Procedure.................................................57
2-6 Using FILE_COMPLETE_SET, FILE_COMPLETE_, and FILE_COMPLETE_GETINFO_ ..........58
2-7 Reading a Guardian File With an OSS Function Call ...................................................................64
2-8 Using fopen_guardian() in an OSS Module..................................................................................65
2-9 Reading an OSS File in Nowait Mode With Guardian Procedures .............................................67
2-10 Reading an OSS File With Guardian Procedures .........................................................................69
2-11 Using a Guardian Procedure to Get OSS File Information by Name ..........................................71
2-12 Using a Guardian Procedure to Get OSS File Information by Number .......................................73
2-13 Using select() on FIFOs...........................................................................................................80
3-1 Dynamic Launcher Program ........................................................................................................99
3-2 Dynamic Echo Server Program ..................................................................................................102
3-3 Determining and Changing Process Priority using getpriority() and nice() ..............................104
3-4 Creating an OSS Process Using tdm_fork() and tdm_execvep() ................................................112
3-5 Creating an OSS Process Using tdm_spawnp() .........................................................................114
3-6 Creating and Controlling a Guardian Process Using Guardian Procedures .............................116
3-7 Creating an OSS Process Using PROCESS_SPAWN_ ................................................................119
3-8 Getting Information About System Limits Using sysconf() .......................................................122
3-9 Getting Information About a Process Using PROCESS_GETINFO_ .........................................124
3-10 Getting Information About a Process Using PROCESS_GETINFOLIST_ .................................126
3-11 Setting the User ID of the Current Process Using setuid() .........................................................128
3-12 Modifying Information About the Current Process Using PROCESS_SETINFO_ and
PROCESS_SETSTRINGINFO_ ..................................................................................................129
3-13 Dynamic Launcher Program to Spawn Dynamic Server ...........................................................132
3-14 Launcher Program to Spawn Static Servers ...............................................................................135
3-15 Static Echo Server .......................................................................................................................139
5-1 Using SETLOOPTIMER in an OSS Program...............................................................................157
5-2 Using gettimeofday()...................................................................................................................159
6-1 Using AF_INET in an OSS Server Process..................................................................................168
6-2 Using AF_INET in an OSS Requester Process.............................................................................171
6-3 Using AF_INET in a Guardian Server Process............................................................................174
6-4 Using $RECEIVE in an OSS Server Process................................................................................180
6-5 Using $RECEIVE in an OSS Requester Process...........................................................................182
7-1 Using the pax Utility From a Program .......................................................................................197
7-2 Accessing an OSS Terminal With Guardian Procedures in the OSS API ...................................201
7-3 Example Logger Program Used With OSSTTY ..........................................................................207

13
7-4 Running an Interactive OSS Session From the Guardian Environment ....................................211
7-5 Printing an OSS File With the lp Utility .....................................................................................215
7-6 Sending an OSS File to the Guardian Spooler.............................................................................217
7-7 Sending an OSS File Directly to a Printer Using the Guardian API ...........................................220
8-1 Calling syslog() With Formatting Codes ....................................................................................230
8-2 Calling syslog() With the %m Formatting Code ........................................................................230
8-3 Use of System Logging Functions ..............................................................................................231
10-1 Using OSS Security Functions ....................................................................................................247
10-2 Using acl() and aclsort()....................................................................................................259
11-1 Handling the Synchronous Signal SIGFPE.................................................................................268
11-2 Handling the Synchronous Signal SIGINT.................................................................................270
11-3 Handling the SIGCHLD Signal...................................................................................................272
11-4 Handling SIGALRM Signals.......................................................................................................274
11-5 Threaded Time-of-Day Server Socket .........................................................................................284
11-6 Threaded Time-of-Day Server Socket Using $RECEIVE.............................................................287
11-7 File Stream Thread-Aware Function Usage.................................................................................297
11-8 File Descriptor Thread-Aware Function Usage...........................................................................297
11-9 Open File Descriptor Thread-Aware Function Usage.................................................................297
11-10 Pthreads Nonblocking Disk File I/O (SPT_THREAD_AWARE_NONBLOCK version) ............299
11-11 Pthreads Thread-Aware Disk File I/O Using SPT_THREAD_AWARE_XNONBLOCK ............309
11-12 Using the Reentrant Function strtok_r........................................................................................316
11-13 Thread-Aware Toolkit Program Flow.........................................................................................318
11-14 Simplified Program Flow For a Thread-Aware Function............................................................318
11-15 Thread-Aware read() Function....................................................................................................318
11-16 Nonblocking Thread-Aware read() Function..............................................................................319
11-17 Example READX() Function Used In Thread-Aware Manner....................................................320
11-18 Thread-Aware $RECEIVE Program Flow...................................................................................321
11-19 Function with spt_RECEIVEREAD() and spt_REPLYX()............................................................322
11-20 $RECEIVE Server.........................................................................................................................323
11-21 Using the Thread-Aware SPT_FILE_OPEN Function.................................................................326
11-22 OSS File Descriptor Callback.......................................................................................................327
11-23 Timer Callback Program Flow....................................................................................................327
12-1 Handling the Synchronous Signal SIGFPE.................................................................................339
12-2 Handling the Synchronous Signal SIGINT.................................................................................341
12-3 Handling the SIGCHLD Signal...................................................................................................342
12-4 Handling SIGALRM Signals.......................................................................................................344
12-5 File Stream Thread-Aware Function Usage.................................................................................348
12-6 File Descriptor Thread-Aware Function Usage...........................................................................348
12-7 Open File Descriptor Thread-Aware Function Usage.................................................................349
12-8 Pthreads Thread-Aware Disk File I/O Using PUT Model Library..............................................350
12-9 Using the Reentrant Function strtok_r........................................................................................360
12-10 Thread-Aware Toolkit Program Flow.........................................................................................362
12-11 Simplified Program Flow For a Thread-Aware Function............................................................362
12-12 Nonblocking Thread-Aware read() Function..............................................................................363
12-13 Example READX() Function Used In Thread-Aware Manner....................................................364
12-14 Thread-Aware $RECEIVE Program Flow...................................................................................365
12-15 Function with put_RECEIVEREAD() and put_REPLYX()..........................................................366
12-16 $RECEIVE Server.........................................................................................................................367
12-17 Using the Thread-Aware PUT_FILE_OPEN Function................................................................372
12-18 OSS File Descriptor Callback.......................................................................................................373
12-19 Timer Callback Program Flow....................................................................................................373
12-20 Threaded Time-of-Day Server Socket .........................................................................................383
12-21 Threaded Time-of-Day Server Socket Using $RECEIVE.............................................................386

14 List of Examples
About This Document
The Open System Services Programmer’s Guide describes how to write application programs in C
for the OSS environment. This guide includes information about:
• How the OSS environment differs from the standard UNIX programming environment
• When you need to use the Guardian application program interface (API) in OSS C programs
• Which tasks can be performed only from the Guardian or OSS API
• Performance considerations
The basics of how to program in a UNIX environment are well documented in commercial texts
and are not an objective of this guide. Please refer to the following books for information about
programming in a UNIX environment.
• Advanced Programming in the UNIX Environment, W. Richard Stevens, Addison-Wesley, 1992.
• Multithreaded Programming with Pthreads, Bill Lewis and Daniel J. Berg, Sun Microsystems
Press, 1998.
• POSIX Programmer’s Guide, Donald Lewine, O’Reilly and Associates, Inc., 1991.
• Practical UNIX & Internet Security, Simon Garfinkel and Gene Spafford, O’Reilly and
Associates, Inc., 1996.
• Pthreads Programming, Bradford Nichols, Dick Buttlar, and Jacqueline Proulx Farrell, O’Reilly
and Associates, Inc., 1996.
• UNIX Network Programming, 2nd Edition, W. Richard Stevens, Prentice-Hall, 1997.

About TNS, TNS/R Native, and TNS/E Native Processes


A TNS process is initiated by executing a TNS interpreted or accelerated object file; TNS object
code executes on TNS, TNS/R, and TNS/E systems. A TNS/R native process is initiated by
executing a TNS/R native object file; TNS/R native object code executes only on TNS/R systems.
A TNS/E native process is initiated by executing a TNS/E native object file; TNS/E native object
code executes only on TNS/E systems.
In this guide, the term “native process” refers generically to TNS/R and TNS/E native processes.
When it is necessary to distinguish between platforms, the terms “TNS/R native process” and
“TNS/E native process” are used. In most cases, the behavior of TNS and native processes is the
same. When it is not, the guide provides considerations or notes about how TNS process behavior
differs from that of native processes.

About the Examples


This guide contains programming examples in C to illustrate how programming in the OSS
environment differs from programming in a standard UNIX environment.
The examples are designed to focus on a particular function or programming construct. They
are intentionally short and to-the-point to avoid distracting from the example’s primary focus.
The effort to keep the examples concise means, however, that the programming examples are
not models of how an experienced programmer would verify user input. Verifying user input
can require a lot of code, and this guide assumes you are an experienced programmer who knows
how to edit user input.

About OSS Utilities


Hewlett-Packard Company is not responsible for the proper functioning of unsupported utilities
or facilities and will not respond to product reports about them. Such utilities and facilities
include those in the OSS /bin/unsupported directory. Use these utilities and facilities at your
own risk.

About TNS, TNS/R Native, and TNS/E Native Processes 15


Supported Release Version Updates (RVUs)
This manual supports J06.03 and all subsequent J-series RVUs, H06.03 and all subsequent H-series
RVUs, and G06.25 and all subsequent G-series RVUs, until otherwise indicated in a replacement
publication.

Intended Audience
This guide is intended for intermediate and advanced C application programmers who write
programs for the OSS environment. Experience with programming in a UNIX environment is
assumed.

New and Changed Information


This manual contains information about some of the following G-series development tools. For
servers running H-series RVUs, these tools are supported only in H06.05 and subsequent H-series
RVUs:
• TNS/R native C compiler
• TNS/R native C++ compiler
• TNS/R native C++ runtime library version 2
• SQL/MP for TNS/R native C
• SQL/MP Compilation Agent for TNS/R programs
• NMCOBOL compiler and nmcobol frontend
• ld
• nld
• noft
• TNS/R native pTAL
If your server is running the H06.03 or H06.04 RVU, continue to use the HP Enterprise
Toolkit—NonStop Edition or servers running G-series RVUs for development tasks that require
these tools. If your server is running J06.03 or later J-series RVUs, these tools are supported.

Changes made to the 520674-014 Edition


• Added information about the NonStop Development Environment for Eclipse (NSDEE) to
“Overview of the OSS Programming Environment” (page 25).
• Added references to the c99 utility to “Overview of the OSS Programming Environment”
(page 25), “Using Subsystems From OSS” (page 235), “Using the Standard POSIX Threads
Library” (page 261), and “Using the POSIX User Thread (PUT) Model Library ” (page 329).
• Changed “Using the Standard POSIX Threads Library” (page 261) to include:
— Information about the _SPT_MODEL_ define, which is required for all programs
compiled on systems running H06.21 and later H-series RVUs and J06.10 and later
J-series RVUs, and other linking considerations
— New and corrected signal types
• Added a new chapter that describes the POSIX User Thread (PUT) Model Library. See “Using
the POSIX User Thread (PUT) Model Library ” (page 329).
• Added new functions to Appendix A (page 389), and Appendix C (page 451).

Changes made to the 520674-013 Edition


Added information about NFS and OSS ACLs to:
• “OSS ACLs” (page 61)
• “Using OSS Access Control Lists (ACLs)” (page 249)
• “OSS Network File System (NFS) and ACLs” (page 257)

16
Changes made to the 520674-012 Edition
These new functions were added to the discussion of jacket routines in Chapter 11 (page 261),
Appendix A (page 389), and Appendix C (page 451):
spt_INITRECEIVEL()
spt_RECEIVEREADL()
spt_REPLYXL()
SPT_SERVERCLASS_SENDL_()
The complete list of jacket routines has been added to Appendix A (page 389).
These new functions were added to Table 3-3 (page 108)Table 3-3, OSS Process-Management
Functions That Can Access Guardian Processes, on page 3-16, Table 10-1 (page 241)Table 10-1,
OSS Security- Related Functions, on page 10-4, Appendix A (page 389), and Appendix C (page 451):
initgroups()
setegid()
seteuid()
setgroups()

Changes Made to the 520674-011 Edition


Added information about AF_UNIX Release 2 software. See “Using AF_UNIX Sockets” (page 176).

Changes Made to the 520674-010 Edition


Added information about the spt_*z thread-blocking functions to Chapter 11 (page 261)
These new functions were added to Appendix A (page 389) and Appendix C (page 451)
spt_closez()
spt_fcntlz()
spt_fstat64z()
spt_fstatz()
spt_fsync()
spt_ftruncate64z()
spt_ftruncatez()
spt_lseek64z()
spt_lseekz()
spt_readvz()
spt_readz()
spt_writevz()
spt_writez()

Changes Made to the 520674-009 Edition


Added information about support for J-series RVUs throughout the manual.
Removed the discussion of the pthread_setconcurrancy() function from Chapter 11
(page 261). This function does not support thread scheduling.

Changes Made to the 520674-008 Edition


New functions were added to:
• Appendix A (page 389)
• Appendix B (page 427)
• Appendix C (page 451)
Changes were made throughout this guide to indicate that OSS access control lists (ACLs) are
supported for H06.08 and later H-series RVUs in addition to G06.29 and later G-series RVUs.

New and Changed Information 17


Changes Made to the 520674-007 Edition
A description of Extensions Based on Standards or Proposed Standards has been added to
Section 1, Overview of the OSS Programming Environment.
In Chapter 2 (page 51):
• A brief introduction to access control lists (ACLs) was added
• A detailed discussion of Accessing OSS Files Larger Than 2 GB from both the OSS
environment and the Guardian environment has been added.
• The Performance Considerations have been revised.
In Chapter 7 (page 195):
• A new topic, Blocking and Nonblocking Terminal I/O, has been added.
• The topic, Running an Interactive OSS Session From a TACL Macro, has been added and
the example within this topic has been updated.
In Chapter 10 (page 239):
• Several new security functions have been added.
• A new topic, Using OSS Access Control Lists (ACLs), has been added.
In Chapter 11 (page 261):
• The new topic, Thread-Aware Signal Handling, has been added.
• A list of nonblocking thread aware functions has been added to Table 11-6 (page 292).
• The new topic, Reentrant OSS Functions, has been added
• The new topic, Thread-Aware Enscribe Functions has been added.
• Several examples and explanations have been added.
• A discussion of concurrancy and the use of the sched_yield() and
pthread_setconcurrancy() functions have been added.
Corrections were made, new functions were added, and obsolete functions were deleted in the
following appendixes:
• Appendix A (page 389)
• Appendix B (page 427)
• Appendix C (page 451)

Document Organization
This guide contains the following sections and appendixes:
• Chapter 1: Overview of the OSS Programming Environment (page 25) introduces the OSS
and Guardian file systems and process types, discusses how to select source and target
environments, describes how to call OSS functions and Guardian procedures and functions
in OSS programs, and indicates the programming tools available.
• Chapter 2: Managing Files (page 51) describes how to use the OSS file system, including
manipulating OSS regular files and Guardian disk files, and nowait I/O.
• Chapter 3: Managing Processes (page 97) describes process management, including managing
OSS and Guardian processes, using the HP extension functions, getting information about
processes, and modifying the process environment.
• Chapter 4: Managing Memory Segments (page 149) describes how the concept of memory
management differs among the UNIX, Guardian, and OSS environments.
• Chapter 5: Managing Time (page 155) describes time management, including querying the
system clock, querying process times, and limiting processor usage.
• Chapter 6: Interprocess Communication (page 163) describes the mechanisms processes can
use to communicate with one another within the same processor, between processors, and
between nodes in a HP NonStop network.

18
• Chapter 7: Managing I/O (page 195) describes how to manage OSS tape, terminal, and printer
I/O.
• Chapter 8: Using Logging Mechanisms (page 225) describes how to log information in the
OSS environment.
• Chapter 9: Using Subsystems From OSS (page 235) mentions any special considerations or
limitations in using HP subsystems from OSS application programs.
• Chapter 10: Managing OSS Security (page 239) lists and provides a short description of the
OSS security features.
• Chapter 11: Using the Standard POSIX Threads Library (page 261) describes the Standard
POSIX Threads product available for C and C++ in the OSS environment.
• Appendix A: Documented OSS Functions (page 389) lists all OSS functions in the current
release and gives information such as where they are documented.
• Appendix B: API Interoperability in TNS Processes (page 427) describes the interoperability
between the OSS and Guardian APIs in TNS processes.
• Appendix C: API Interoperability in Native Processes (page 451) describes the interoperability
between the OSS and Guardian APIs in native processes.
In some cases, you will need to consult the Guardian Programmer’s Guide while writing OSS
application programs. The organization of this guide is very similar to the organization of the
Guardian Programmer’s Guide, so that you can easily make the transition from one programmer’s
guide to the other.

Notation Conventions
General Syntax Notation
This list summarizes the notation conventions for syntax presentation in this manual.
UPPERCASE LETTERS
Uppercase letters indicate keywords and reserved words. Type these items exactly as shown.
Items not enclosed in brackets are required. For example:
MAXATTACH
Italic Letters
Italic letters, regardless of font, indicate variable items that you supply. Items not enclosed
in brackets are required. For example:
file-name
Computer Type
Computer type letters indicate:
• C and Open System Services (OSS) keywords, commands, and reserved words. Type
these items exactly as shown. Items not enclosed in brackets are required. For example:
Use the cextdecs.h header file.
• Text displayed by the computer. For example:
Last Logon: 14 May 2006, 08:02:23
• A listing of computer code. For example
if (listen(sock, 1) < 0)
{
perror("Listen Error");
exit(-1);
}

Bold Text
Bold text in an example indicates user input typed at the terminal. For example:

Notation Conventions 19
ENTER RUN CODE

?123
CODE RECEIVED: 123.00
The user must press the Return key after typing the input.
[ ] Brackets
Brackets enclose optional syntax items. For example:
TERM [\system-name.]$terminal-name

INT[ERRUPTS]
A group of items enclosed in brackets is a list from which you can choose one item or none.
The items in the list can be arranged either vertically, with aligned brackets on each side of
the list, or horizontally, enclosed in a pair of brackets and separated by vertical lines. For
example:
FC [ num ]
[ -num ]
[ text ]

K [ X | D ] address
{ } Braces
A group of items enclosed in braces is a list from which you are required to choose one item.
The items in the list can be arranged either vertically, with aligned braces on each side of the
list, or horizontally, enclosed in a pair of braces and separated by vertical lines. For example:
LISTOPENS PROCESS { $appl-mgr-name }
{ $process-name }

ALLOWSU { ON | OFF }
| Vertical Line
A vertical line separates alternatives in a horizontal list that is enclosed in brackets or braces.
For example:
INSPECT { OFF | ON | SAVEABEND }
… Ellipsis
An ellipsis immediately following a pair of brackets or braces indicates that you can repeat
the enclosed sequence of syntax items any number of times. For example:
M address [ , new-value ]…

- ] {0|1|2|3|4|5|6|7|8|9}…
An ellipsis immediately following a single syntax item indicates that you can repeat that
syntax item any number of times. For example:
"s-char…"
Punctuation
Parentheses, commas, semicolons, and other symbols not previously described must be typed
as shown. For example:
error := NEXTFILENAME ( file-name ) ;

LISTOPENS SU $process-name.#su-name
Quotation marks around a symbol such as a bracket or brace indicate the symbol is a required
character that you must type as shown. For example:
"[" repetition-constant-list "]"
Item Spacing
Spaces shown between items are required unless one of the items is a punctuation symbol
such as a parenthesis or a comma. For example:

20
CALL STEPMOM ( process-id ) ;
If there is no space between two items, spaces are not permitted. In this example, no spaces
are permitted between the period and any other items:
$process-name.#su-name
Line Spacing
If the syntax of a command is too long to fit on a single line, each continuation line is indented
three spaces and is separated from the preceding line by a blank line. This spacing
distinguishes items in a continuation line from items in a vertical list of selections. For example:
ALTER [ / OUT file-spec / ] LINE

[ , attribute-spec ]…

Related Information
Table 1 shows the programming guides, reference manuals, and user guides that contain
information related to the information in this guide.

Related Information 21
Table 1 Related Manuals

The following are related programming guides:


• Availability Guide for Application Design. This manual introduces the various products and
concepts involved in designing and writing applications with increased availability. It
describes alternative approaches to application design and the benefits and compromises
of different approaches, and it includes check lists on how to go about developing more
available applications.
• C/C++ Programmer’s Guide. This guide describes the implementation of the C and C++
programming languages on HP NonStop systems. It discusses the C language syntax, the
C compiler, and the C program execution environment. This guide is intended for system
and application programmers writing programs for the Guardian and OSS environments.

22
• Guardian Programmer’s Guide. This guide describes how to access the Guardian API using
Guardian procedure calls. It is written for application and system programmers.
• Open System Services Porting Guide. This guide describes conversion techniques for moving
existing C-language applications into the OSS environment. It discusses both C-language
and operating system considerations. This guide is intended for application programmers,
with some information for selected operating system users.
• Software Internationalization Guide. This guide describes how to use the OSS
internationalization features. It is written for application and system programmers.
The following are related reference manuals:
• Guardian Procedure Calls Reference Manual. This manual describes the syntax for most Guardian
procedure calls. It is intended for system and application programmers.
• Guardian Native C Library Calls Reference Manual. This manual describes syntax and semantics
of the native C run-time library calls and header files for the Guardian environment. This
manual is intended for system and application programmers.
• Guardian TNS C Library Calls Reference Manual. This manual describes syntax and semantics
of the TNS C run-time library calls and header files for the Guardian environment. This
manual is intended for system and application programmers.
• Open System Services Library Calls Reference Manual. This manual describes syntax and
semantics of the C run-time library calls and header files for the OSS environment. This
manual is intended for system and application programmers.
• Open System Services Shell and Utilities Reference Manual. This manual presents rules and
syntax for each command that the user enters interactively to access the OSS command
interpreter (called the shell), and utilities and other functions that perform general-purpose
and program-development operations. It is written for all audiences: system administrators,
managers, and operators; end users; and application and system programmers.
• Open System Services System Calls Reference Manual. This manual describes all OSS system
calls (file system and kernel functions), their syntax, required external data structures,
resulting operations, and source file (header) locations for all literals and symbolic definitions.
It is written for application and system programmers.
The following are related user guides:
• Guardian User’s Guide. This guide provides basic information about the programs and utilities
that are used most often in the Guardian environment by general system and application
users. It also provides more detailed procedures for system operations, management, and
maintenance tasks that are useful to both beginning and experienced users of HP NonStop
systems.
• Open System Services User’s Guide. This guide provides basic orientation, tutorial, and task
information for using the OSS shell and utilities. It is written for all audiences: system
administrators, managers, and operators; end users; and application and system
programmers.

Publishing History
Part Number Product Version Publication Date

520574-010 N.A. May 2008

520574-011 N.A. August 2008

520574-012 N.A. November 2008

520574-013 N.A. February 2010

520574-014 N.A. August 2010

Publishing History 23
HP Encourages Your Comments
HP encourages your comments concerning this document. We are committed to providing
documentation that meets your needs. Send any errors found, suggestions for improvement, or
compliments to [email protected].
Include the document title, part number, and any comment, error found, or suggestion for
improvement you have concerning this document.

24
1 Overview of the OSS Programming Environment
OSS is an alternative to the Guardian interface through which users and programs can interact
with the HP NonStop operating system. OSS interfaces and functions greatly resemble those of
UNIX systems in general, because of their common relationship to the POSIX standards. OSS
adds to the UNIX API by offering access to Guardian fundamentals and interoperability with
the Guardian environment by offering extensions to the standard API, additional OSS function
calls, and access to Guardian procedure calls.
OSS provides:
• A basis for middleware products. OSS supports a variety of middleware software, such as
the HP NonStop Tuxedo, NonStop Distributed Object Manager/MP (DOM), and NonStop
Server for Java products, that might also be used in an application.
• An open interface to the operating system for supporting portable applications.
This guide focuses on the latter function: writing applications in C for the OSS target execution
environment without the use of middleware. For your convenience, Chapter 9: Using Subsystems
From OSS (page 235) contains a brief overview of some of the middleware available for NonStop
systems. For more information on such middleware, refer to the manual set for the specific
software product in which you are interested.
The OSS programming environment allows you to access Guardian objects and subsystems as
well as OSS objects. OSS accomplishes this interoperability between environments using standard
library and system function calls, and HP extensions to these calls and to Guardian procedures.
This section discusses the following topics:

Topic Content

“The OSS API” (page 25) Relationship to the Guardian API and the NonStop
operating system, and conformance to industry standards.

“Two File Systems” (page 27) Basic differences between the OSS and Guardian file
systems, including directory structures, file access, and
file types.

“Two Process Types” (page 31) Basic differences between the OSS and Guardian
processes, including process identifiers, groups, ancestors,
attributes, and pairs.

“Selecting Source and Target Execution Environments” Typical source and target execution environments and
(page 34) exceptions to the typical case.

“Calling Functions and Procedures in OSS Programs” How to call OSS functions and Guardian functions and
(page 35) procedures and when to use them.

“Using the Development Tools” (page 41) Available editors, development utilities, compilers,
linkers, optimizers, debuggers, and performance
analyzers.

“Using the HP Enterprise Toolkit - NonStop Edition” An integrated development environment that enables
(page 49) you to build applications on a PC.

The OSS API


An application program interface (API) is a set of functions or procedure calls that permits user
programs to communicate with the operating system. The OSS API coexists on NonStop systems
with the traditional Guardian interfaces, as shown in Figure 1-1.

The OSS API 25


Figure 1-1 The Operating Environment for NonStop Systems

An application program can be compiled to run in either the OSS or Guardian environment and
can use services from each environment, including the API, tools, and utilities.

Standards Conformance
The OSS API conforms to the POSIX.1 and POSIX.2 standards, and partially conforms to the
XPG4 specifications. These standards and specifications are described in the following documents:
• Information Technology – Portable Operating System Interface (POSIX) – Part 1: System Application
Program Interface (API) [C Language], ISO/IEC 9945-1 (IEEE Std 1003.1, SH13680), First Edition
1990.
• Information Technology – Portable Operating System Interface (POSIX) – Part 2: Shell and Utilities,
ISO/IEC 9945-2 (IEEE Std 1003.2a), First edition 1992.
• X/Open CAE Specifications – System Interfaces and Headers, Issue 4.
• X/Open CAE Specifications – System Interfaces and Headers, Issue 4, Version 2.

Conformance to POSIX.1
You might need to write applications that strictly conform to a certain standard or specification.
A strictly-conforming POSIX.1 application cannot use any of the following:
• Any function unique to a NonStop system, such as tdm_fork(), that is an extension to the
standard.
• The Guardian environment. This is not discussed by the standard.
• A Guardian object. This is not discussed by the standard.
• A remotely mounted fileset. This is not discussed by the standard.
• A symbolic link. This is not discussed by the current version of the standard.
• A POSIX.2 function, such as those provided in the regex.h and glob.h header files.
• An XPG4 function, such as those provided in the fnmatch.h, nl_types.h, and wchar.h
header files.
• An XPG4 function that is an extension to standard header files, such as getw() in stdio.h.
• Any function related to OSS access control lists (ACLs)

26 Overview of the OSS Programming Environment


• Any function designed to interact with OSS files that are larger than approximately
2 gigabytes. These functions, often called 64-bit APIs or 64-bit functions, typically have the
number 64 in the name (for example the open64() function).
• Functions specified only in the ISO/IEC 9899:1999 standard, which is also referred to as the
C99 standard.

Extensions Based on Standards or Proposed Standards


The OSS API also includes functions that are HP extensions to the XPG4 specifications, but that
are also based on other approved or proposed standards:
• Functions designed to interact with OSS files larger than approximately 2 gigabytes in
addition to smaller OSS files. These functions, often called 64-bit APIs or 64-bit functions,
typically have the number 64 in the name (for example the open64() function). These 64-bit
APIs are based on the Adding Support for Arbitrary File Sizes to the Single Unix Specification,
X/Open Large File Summit (LFS) submission, version 1.5 (March 20, 1996), and are supported
on systems running J-series RVUs, H06.06 or later H-series RVUs, and G06.29 or later G-series
RVUs.
• Functions that support OSS access control lists (ACLs). These functions are based on the
HP-UX implementation and Information Technology – Portable Operating System Interface (
POSIX) – Part 1: System Application Program Interface (API) Amendment #: Protection, Audit,
and Control Interfaces [C Language] (IEEE Draft P1003.1e), October 1997.
• Several functions that support wide-character formats. These functions conform to the
ISO/IEC 9899:1999 standard.

Two File Systems


The OSS environment enables you to access two file systems: the OSS file system and the Guardian
file system. The files in these file systems can exist as local files or remote files. A local file resides
on the local node. A remote file resides on a remote node.

The OSS File System


The OSS file system is a multilevel file system consisting of directories and subdirectories
stemming from a “root” directory denoted by /. A directory can contain files and more directories.
A directory that is in another directory is called a subdirectory. There are no theoretical limits
to the number of subdirectories and files in a directory. Figure 1-2 shows the structure of an OSS
file system and that there is no direct relationship between OSS filenames and disks.

Two File Systems 27


Figure 1-2 OSS Filenames and Disks

Open System Services manages the directory tree using filesets. A fileset is a directory tree that
can be mounted or unmounted. Most literature about UNIX refers to filesets as file systems. In
the OSS and Guardian environments, the term file system also refers to the software that manages
the file system.
OSS files and directories are designated by pathnames. A pathname is the string of characters
that uniquely identifies a file within its file system. A pathname can be either relative or absolute.
An absolute pathname starts with a slash (/) and begins at the root directory. A relative pathname
does not start with a slash and begins with the current working directory. The PATH_MAX symbolic
constant in the limits.h header file defines how long OSS pathnames can be.
A directory or fileset can occupy many disk volumes. Pathnames are logical names. They have
no relationship to disk volumes, as shown in Figure 1-2. A file cannot occupy more than one disk
volume. Refer to the pathname(5) reference page either online or in the Open System Services
System Calls Reference Manual.

File Types
Open System Services supports these file types:
• Regular files (disk files)
• Directories
• FIFOs/pipes
• Sockets
• Symbolic links
• Character special files (Only /dev/tty terminal character files and /dev/null)
All OSS regular (data) files are odd-unstructured files. OSS regular files can be accessed using
Guardian functions and procedures as well as OSS functions.

28 Overview of the OSS Programming Environment


File Access
Access to an OSS file or directory is determined by a set of permission bits associated with it.
The file owner, groups the owner belongs to, and others each have read, write, or execute
permission for a file.
For filesets that support OSS ACLs, access to an OSS file or directory is determined by the ACL.
For more information about OSS ACLs, see “Using OSS Access Control Lists (ACLs)” (page 249).

Access to Files on Remote NonStop Nodes


Any file visible to the OSS filesystem on a different node in an Expand network can be accessed
by preceding the file name of the name of a special directory. This special directory, which exists
just under the root directory, is called /E. The OSS pathname begins with /E, followed by the
node name and the absolute pathname of the file on the remote node. The directory is treated
as any another directory, and it includes all other nodes in the Expand network that support
Open System Services. (Guardian files are also accessible on those other nodes). Here is an
example, of a pathname for an OSS file named thatfile on a remote node named \COMM:
/E/comm/thatdir/thatfile
The pathnames of files on the local node also exist in /E as a special case. The directory
/E/localnode/ is a symbolic link to the local root directory /.

The Guardian File System


The Guardian file system consists of a limited number of levels. A complete (fully qualified)
Guardian file name has four components: a node name, volume name, subvolume name, and
file identifier. A node name begins with a backslash (\), and a volume name begins with a dollar
sign ($). Components are separated by a period (.). Figure 1-3 shows the components of the fully
qualified file name \mynode.$myvol.Mysubvol.myfile.

Figure 1-3 Components of Guardian File Names

Guardian file names visible to an OSS program are physical names: they refer to physical objects.
A node name refers to a physical node, and a volume name refers to a physical disk volume. A
node cannot contain nodes, a volume cannot contain volumes, and a subvolume cannot contain
subvolumes. The relationship between Guardian file names and physical devices is shown in
Figure 1-4.

Two File Systems 29


Figure 1-4 Guardian File Names and Disks

Guardian files on the local node appear as OSS files in the /G directory of the OSS file system.
The local node name is omitted.
Guardian files on remote NonStop nodes also appear as OSS files in the /E directory of the OSS
file system. The pathnames for such files begin with /E/nodename and continue with the /G
directory on the indicated node. For example:
/E/node2/G/volume/subvol/fileid
Figure 1-5 shows the Guardian file /G/volume1/subvol1/myfile in the OSS file system.

30 Overview of the OSS Programming Environment


Figure 1-5 Guardian Files in the OSS File System

File Types
Using OSS functions, you can read and write only odd-unstructured Guardian files. EDIT files
are unstructured files, and you can access them only for reading. OSS functions cannot access
structured Guardian files (SQL, entry-sequenced, key-sequenced, and relative). You can access
structured Guardian files using Guardian procedure calls in an OSS program.

File Access
Guardian file access is determined by the RWEP character string. This is a four-character string;
the positions determine who can Read, Write, Execute, or Purge a file (hence RWEP). For further
information about Guardian file security, refer to the Guardian User’s Guide.

Two Process Types


You can create and manage both OSS and Guardian processes in the OSS environment. OSS and
Guardian processes share some process identifiers and attributes. OSS processes can belong to
process groups, while Guardian processes cannot. Guardian processes can belong to process
pairs, but OSS processes cannot. Creator processes and the process run-time environment are
defined differently for the two types of processes. In the OSS environment, a method for creating

Two Process Types 31


a new process is by using either the fork() or tdm_fork() function and either the exec set
or tdm_execve set of functions in the appropriate sequence.

Process Identification
Table 1-1 shows the ways in which OSS processes and Guardian processes can be identified.
Processes always have “required” identifiers, never have identifiers that are “not available,” and
might have those classified as “optional.” You can specify optional identifiers when you call
process-creation procedures or functions.
Table 1-1 OSS and Guardian Process Identifiers
Process Identifier OSS Process Guardian Process

OSS Process ID Required Not available

Process Handle Required Required

Process Name Optional Optional

The following list defines the OSS and Guardian process identifiers:
OSS process ID
Uniquely identifies an OSS process within a node.
Process handle
Uniquely identifies an OSS or Guardian process within a NonStop network.
Process name
Name containing 1 to 5 alphanumeric characters preceded by a dollar sign ($).

Process Groups
An OSS process can belong to a process group, which is identified by a group ID. Processes in
the same group can be treated collectively; for example, all processes in a group that are active
at the same time can receive the same job control signals. Therefore, when you enter a command
from the OSS shell to suspend a job, all processes in the group associated with that job can receive
the signal to stop. (Signals can be sent to an individual process or to an entire process group.)
A Guardian process cannot belong to a process group or session, which is a collection of one or
more process groups.
Example 1-1 provides code to demonstrate the use of some of the OSS group information functions
including getgrent(), endgrent(), setgrent(), getgrgid(), and getgrnam().

32 Overview of the OSS Programming Environment


Example 1-1 Using Some OSS Group Information Functions
#include <limits.h>
#include <ctype.h>
#include <sys/types.h>
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

struct group *gnam = NULL;


gid_t grouplist[NGROUPS_MAX];
int gcnt;
char groupname[32];

int main(int argc, char *argv[])


{
int i;
char **ptr;
/*
Get the group number or name from the command line.
If no argument is provided, use the group number for the user.
*/
if(argc > 1) {
if(isdigit(argv[1][0])) /* check if numeric value */
gnam = getgrgid(atoi(argv[1]));
else /* else assume group name */
gnam = getgrnam(argv[1]);
} else
gnam = getgrgid(getgid());
if(gnam == NULL) {
fprintf(stderr,"Can't get group entry for %s\n", argv[1]);
exit(1);
}

/* Print group name entry information. */


printf("Group name entry -> = %s\n", gnam->gr_name);
printf("Group number entry -> = %d\n", gnam->gr_gid);

/* Print names of other members of this group using getgrent(). */


strcpy(groupname, gnam->gr_name); /* save name of group name */
setgrent(); /* reset to beginning */
while((gnam = getgrent()) != NULL) {
if(strcmp(gnam->gr_name, groupname) == 0)
break;
}
endgrent(); /* close the file */
ptr = gnam->gr_mem;
printf("All members of group (by name) are:\n");
i = 0;
while(*ptr)
printf("%d: %s\n", i++, *ptr++);

/* Print supplementary group IDs for user. */


if((gcnt = getgroups(NGROUPS_MAX, grouplist)) < 0) {
fprintf(stderr, "Can't get list of group membership\n");
exit(1);
}
printf("\nNumber of supplementary group IDs for user = %d\n", gcnt);
for(i = 0; i < gcnt; i++)
printf("\tGroup ID #%d:\t%d\n", i, grouplist[i]);
return(0);
}

Two Process Types 33


Process Ancestors
The creator process of an OSS process is the “parent” process of the newly created “child” process.
The child process inherits many OSS and Guardian attributes of the parent process.
The creator process of a Guardian process is the “MOM” process of the newly created process
if the new process is unnamed. If the new process is named, the creator process is its “ancestor.”
A Guardian process inherits some attributes from its ancestor or MOM if the attributes are not
specified in the call to the PROCESS_LAUNCH_ procedure. For more information about
relationships between Guardian processes, see the Guardian Programmer’s Guide.

Process Attributes
All processes, OSS and Guardian, have Guardian attributes and some OSS attributes. OSS
processes have additional OSS-specific attributes, such as an OSS process ID. Open System
Services includes standard UNIX functions such as the fork() function and the exec set of
functions as well as HP extension functions, which are tdm_fork(), tdm_execve(),
tdm_execvep(), tdm_spawn(), and tdm_spawnp(). The HP extension functions allow you
to set attributes when a process is created that you cannot set with standard UNIX functions.
For example, when you create a new OSS process image with the execve() function, the new
process retains many attributes of the calling process, and you cannot overwrite them in the call
to execve(). The tdm_execve() function allows you to either retain the caller’s attributes or
specify other values. For example, you can change the attribute specifying the processor in which
a process executes.

Process Environment
The run-time environment of an OSS process is defined using environment variables. A Guardian
process uses PARAMs, ASSIGNs, and DEFINEs to define its environment, but a Guardian process
also has environment variables if it is created using Guardian C functions.

Process Pairs
A Guardian process can belong to a process pair, which consists of a primary process that performs
the application and a secondary (backup) process in another processor that is ready to take over
if the primary process fails. Process pairs provide one way in which you can create fault-tolerant
applications. You implement process pairs using Guardian checkpointing procedures.
An OSS process cannot belong to a process pair, and you cannot call Guardian checkpointing
procedures from OSS programs.

Native and TNS Processes


A TNS/R native process is initiated by executing a TNS/R native object file; TNS/R native object
code executes only on TNS/R systems. A TNS/E native process is initiated by executing a TNS/E
native object file; TNS/E native object code executes only on TNS/E systems. A TNS process is
initiated by executing a TNS interpreted or accelerated object file; TNS object code executes on
TNS, TNS/R, and TNS/E systems.
On TNS/R systems, OSS and Guardian processes can be either TNS/R native or TNS processes.
On TNS/E systems, Guardian processes can be either TNS/E native or TNS processes, but OSS
processes can only be TNS/E native processes; the TNS/E OSS environment does not support
TNS processes.

Selecting Source and Target Execution Environments


Application program development takes place in the source environment and includes writing,
compiling, and debugging code. Once developed, the application program runs in the target

34 Overview of the OSS Programming Environment


execution environment. The source and target execution environments are usually the same (OSS
or Guardian environment), but there are some special cases in which they are different.

The Typical Case


In most cases, you will use a combination of OSS and UNIX workstation tools to develop source
code and produce applications that run in the OSS target execution environment from the OSS
shell.

Special Cases of Cross Compilation


There are two special cases of cross compilation in which you might want to use different source
and target environments.
• OSS source environment, Guardian target execution environment. You might want to produce
applications to run in the Guardian environment from a Tandem Advanced Command
Language (TACL) prompt but take advantage of the OSS development tools to do some
initial development (editing, some compiling and debugging). In the OSS environment, you
can use filenames containing more than eight characters and a deep, tree-structured directory
system, as compared with an eight-character limit for Guardian file identifiers and a shallow
file system.
• Guardian source environment, OSS target execution environment. This is the situation of
porting existing Guardian applications to run in the OSS environment from the OSS shell.
For more information about cross compilation, see the Open System Services Porting Guide.

Calling Functions and Procedures in OSS Programs


In general, you should use OSS function calls because doing so makes applications more portable.
However, there are cases in which you will want or need to call Guardian system procedures
and Guardian C functions.
The following subsections describe when to use which category of functions or procedures and
provide examples of calling Guardian procedures directly from an OSS program.

OSS Functions
Use OSS functions wherever possible, even to manipulate Guardian objects. For example, if you
want to open a Guardian file that is odd-unstructured, use the OSS open() function. Call OSS
functions as you would any standard C function.
OSS functions are defined in library header files in the /usr/include directory. For detailed
information about OSS functions, see the following manuals:
• Library functions (those in logical section 3 of the reference pages) are described in the Open
System Services Library Calls Reference Manual.
• System functions (those in logical section 2 of the reference pages) are described in the Open
System Services System Calls Reference Manual.
• The HP C language for NonStop systems, run-time library, and compiler information are
described in the C/C++ Programmer’s Guide.

Guardian Procedures
You can (and in some cases must) use Guardian procedures when you cannot accomplish a task
with OSS functions. For example, to get the file code of a Guardian file, you must use a Guardian
file system procedure, such as FILE_GETINFO_ or FILE_GETINFOBYNAME_. You also might
want to use Guardian procedures in cases where the Guardian procedure provides more
information. For example, FILE_GETINFOLIST_ provides much more information than the
stat() function about Guardian or OSS files.

Calling Functions and Procedures in OSS Programs 35


Many of the Guardian procedures can be called directly from an OSS C program by including
the cextdecs.h header file in the program. The cextdecs.h file contains function prototype
declarations for the Guardian procedures you can call directly from your C program. You must
use the EXTENSIONS pragma with this file and should compile using the -Wextensions flag.
For information about Guardian procedures, see the Guardian Procedure Calls Reference Manual,
the Guardian Programmer’s Guide, and the Open System Services Porting Guide. Some procedures
in the Guardian Procedure Calls Reference Manual are described as “superseded” by other procedures.
For example, the OPEN procedure is superseded by the FILE_OPEN_ procedure. Superseded
procedures do not take full advantage of more current features and you should not use them.
They are provided only for backward compatibility.
A call to a Guardian procedure usually either returns a return value or sets a condition code.
Most of the Guardian procedures you need to use fall into one of these two categories, and you
can call these procedures directly from an OSS program. Those procedures that return both a
return value and a condition code cannot be called directly from an OSS (or Guardian C) program.

Procedures That Return a Return Value


Example 1-2 (page 37) shows an OSS program that calls the Guardian procedure
FILE_GETINFOBYNAME_ to get information about a Guardian file, whose filename is provided
as an input parameter to the procedure. The procedure return value is assigned to retcode.

36 Overview of the OSS Programming Environment


Example 1-2 Calling a Guardian Procedure That Returns a Return Value
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cextdecs.h(FILE_GETINFOBYNAME_)> /* Note 1 */

char *filename;
short typeinfo[5];

int main(int argc, char *argv[]) {


short retcode, physreclen; /* Note 2 */

/* Get Guardian filename and pass it to the Guardian procedure. */


if(argc > 1)
filename = argv[1];
else
filename = "$system.system.stdioh";
retcode = FILE_GETINFOBYNAME_(filename, /* Guardian filename */
(short) strlen(filename), /* filename length */
typeinfo, /* return array of file information */
&physreclen, /* returned physical record length */
, /* desired options, if any Note 3 */
, /* tag or timeout value, if any */
);

/* Check for valid filename. */


if (retcode != 0) {
fprintf(stderr, "retcode = %d\n", retcode);
fprintf(stderr, "Non-existent file or filename in bad format\n");
exit(1);
}

/* Print information for a disk file. */


printf("Filename = %s\n", filename);
printf("device type = %d\n", typeinfo[0]);
printf("device subtype = %d\n", typeinfo[1]);
printf("physical record length = %d\n", physreclen);
if(typeinfo[0] == 3) { /* it’s a disk file */
printf("object type = %d\n", typeinfo[2]);
printf("file type = %d\n", typeinfo[3]);
printf("file code = %d\n", typeinfo[4]);
}
return(0);
}

Note 1
The cextdecs.h library header file contains function prototype declarations for Guardian
procedures you can call directly from a C program. It is important to specify which Guardian
procedures the program will call; otherwise, all function prototype declarations in
cextdecs.h are included in your program. In this program, only the function prototype
declaration for the FILE_GETINFOBYNAME_ procedure is included.
To use cextdecs.h with a native program, you must specify the EXTENSIONS pragma,
because the procedure declarations in cextdecs.h use _tal syntax instead of the pragma
function syntax.
Note 2
The integer into which a value is returned, retcode, is declared as a short integer. This is
because the integer data type in Guardian procedures represents a 16-bit word, while the
integer data type in OSS C programs represents a 32-bit word.

Calling Functions and Procedures in OSS Programs 37


Note 3
You must insert a placeholder comma (,) if you omit optional parameters, unless you omit
them from the end of the list. Omitted optional parameters contain default values, if they are
defined.

Procedures That Return a Condition Code


Example 1-3 (page 39) calls the Guardian procedures FILE_OPEN_ and READX to open and
read data from a Guardian file, which is provided as an input parameter to the procedure.
FILE_OPEN_ returns a return value in retcode, and READX returns a condition code in CC.

38 Overview of the OSS Programming Environment


Example 1-3 Calling a Guardian Procedure That Returns a Condition Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tal.h> /* Note 1 */
#include <cextdecs.h(FILE_OPEN_,READX)>

_cc_status CC; /* Note 2 */


short filenum, bytesread, retcode;
char *filename;
char buffer[1024];

int main(int argc, char *argv[]) {


int i;

/* Get Guardian filename and open the file. */


if (argc > 1)
filename = argv[1];
else
filename = "$system.system.stdioh";
retcode = FILE_OPEN_(filename, /* name of Guardian file*/
(short)strlen(filename), /* filename length */
&filenum, /* file number returned */
1, /* open for read */
, /* exclusion */
, /* nowait depth */
, /* sync or receive depth */
);

/* Check if open was successful. */


if (retcode != 0) {
fprintf(stderr, "retcode = %d\n", retcode);
fprintf(stderr, "Can't open %s\n", filename);
exit(1);
}

/* Read from the file and check for valid condition code. */
CC = READX( filenum, /* file number */
buffer, /* buffer address */
1024, /* size of buffer */
&bytesread, /* number of bytes read */
);
if(_status_ne(CC)) { /* if condition code indicates an error */
fprintf(stderr, "Read error, bytes read = %d\n", bytesread);
exit(1);
}

/* Print number of bytes read and contents of first ten bytes.*/


printf("Bytes read = %d\n", bytesread);
printf("First 10 bytes read (in octal): ");
for (i = 0; i < 10; i++)
printf("%o ", buffer[i]);
printf("\n");
return(0);
}

Note 1
The tal.h library header file must be included when you call Guardian procedures that
return condition codes.

Calling Functions and Procedures in OSS Programs 39


Note 2
The _catalysts type-specifier indicates that a procedure does not return a value but does
set a condition code.

Procedures That Return Both a Return Value and a Condition Code


Procedures that return both a return value and a condition code cannot be called directly from
an OSS program, so you must write a “jacket” procedure in pTAL that can be called from a C
program. This jacket procedure can contain only the code required to call the desired Guardian
procedure, and the jacket procedure must be callable from an OSS program. Most Guardian
procedures, but not all, can be called from an OSS program.
You will probably not need to call procedures that return both a return value and a condition
code, but if you do, see the C/C++ Programmer’s Guide for details.

Guardian C Functions
The native C run-time library supports both the OSS and Guardian environments, which means
that there is a single library for functions that are part of both APIs. Most differences that exist
in behavior of the functions in the two APIs for TNS programs no longer exist for native programs.
For information about interoperability between the Guardian and OSS APIs in native processes,
see Table C-1: API Interoperability in Native Processes (Functions a through m) (page 457).
There are a few functions that are specified by HP and can be called only from a Guardian module,
which means you must call them from a separate module compiled for the Guardian environment.
For information on these functions, see the Open System Services Library Calls Reference Manual
or the Guardian Native C Library Calls Reference Manual.

Considerations for TNS Programs


To call Guardian C functions from an OSS TNS program in which the main() module is compiled
to run in the OSS environment, you must write the function calls in a separate module compiled
for the Guardian environment and link (bind) that module with the OSS program. The Guardian
C Run-Time Library contains the functions in the ISO/ANSI C standard with HP extensions. In
many cases, C functions of the same name in the OSS and Guardian APIs behave identically, but
in some cases they do not. Also note that not all functions in each API can be called from each
environment. Before writing mixed-module programs, review Table C-1: API Interoperability
in Native Processes (Functions a through m) (page 457), which describes the interoperability
between the Guardian and OSS APIs in TNS processes.
Using Guardian C functions is an alternative to using Guardian procedures when you cannot
accomplish a task with OSS functions. Because of the mixed-module programming and API
interoperability considerations, it is easier to use Guardian procedures. However, if you are more
familiar with the C language than with Guardian procedures, you might want to use Guardian
C functions. For example, if you want to open a Guardian file and then just read and write to it,
this can be done equally well using Guardian procedures or Guardian C functions.
However, you need to look at the whole set of required operations to determine whether you
can implement them all using Guardian C functions or that there would be a mix of Guardian
procedures and Guardian C functions. If there is a mix, it would be easier to use all Guardian
procedures. For example, if your goal is to open a Guardian file and later use
FILE_GETINFOLISTBYNAME_ to get information about it, you could open the file with the
Guardian C open() function. Then you have to use another Guardian C function to translate
the file descriptor returned by open() to a filename, which is required by
FILE_GETINFOLISTBYNAME_.

Compiling and Linking Separate Guardian Modules


To call a Guardian module from an OSS program, you must compile and link that module with
the OSS program in which the main() module is compiled for the OSS environment. The separate

40 Overview of the OSS Programming Environment


Guardian module must be compiled with the SYSTYPE pragma set to GUARDIAN. This gives you
the Guardian, not the OSS, API. The default SYSTYPE pragma for programs compiled with the
c89 or c99 utility is SYSTYPE OSS.
To compile a module with the SYSTYPE pragma set to GUARDIAN, specify the -Wsystype flag
of the c89 or c99 utility.
The c89 or c99 utility is used to compile and link OSS programs. Example 1-4 compiles but does
not link the source file gprog.c with a SYSTYPE of GUARDIAN.

Example 1-4 Specifying the systype Option to the c89 Utility


$ c89 -c -Wsystype=guardian gprog.c

The result of Example 1-4 is an object file named gprog.o. Example 1-5 compiles the main OSS
program and links it with the Guardian C module object file into an executable program file
named outfile.

Example 1-5 Linking Guardian Modules to OSS Programs


$ c89 -o outfile gprog.o ossprog.c

The operations shown in Example 1-4 and Example 1-5 cannot be combined into one c89
command. You must use two c89 commands, because you cannot compile two modules with
different systype values in the same c89 command.
For some basic examples of how to use the c89 and c99 utilities, see “Using the Development
Tools” (page 41) and for more detail, refer to C/C++ Programmer’s Guide and to the c89(1) or
the c99(1) utility reference page either online or in the Open System Services Shell and Utilities
Reference Manual.

Refer to Bits From Left to Right


When using OSS functions, you set the values of parameters, options, flags, and fields instead
of referring to values by their bit numbers within fields. When using Guardian procedures,
sometimes you must refer to a particular bit in a field by its number. For example, to open an
OSS file using its pathname with a Guardian procedure, you set bit 10 of the options parameter
of the FILE_OPEN_ procedure to 1.
Remember that NonStop software refers to bits from left to right, which means that bit 0 is the
leftmost bit in a field.

Using the Development Tools


This subsection describes the programming development tools available to you from the OSS
and Guardian environments, including editors, development utilities, compilers, linkers,
optimizers, debuggers, and performance analyzers.

Using Tools in Both Environments


You can edit, compile, link, and optimize programs to run in either the OSS or Guardian target
execution environment from either development environment. While it is easier in most cases
to use OSS tools to develop applications to run in the OSS target execution environment, there
are some cases in which you will want to use Guardian tools. Also, there are some tools that can
run only from the Guardian environment, such as the TEDIT editor or the Measure performance
analyzer.

Using the Development Tools 41


Multiple Windows
Maintaining two windows open to the same NonStop system, one with a TACL prompt and one
with an OSS shell prompt, lets you move easily between the Guardian and OSS environments.
For example, you can write, compile, and test programs with OSS tools in the OSS environment
and move to the TACL prompt to debug programs and analyze performance. For information
on running Open System Services, see the Open System Services User’s Guide.

gtacl Utility
Using the gtacl utility is another way to mix development environments. gtacl runs a process
in the Guardian environment from the OSS environment and lets you use Guardian tools from
the OSS shell. You can use gtacl to start an interactive TACL process, execute a single Guardian
environment command, or run a Guardian environment program. Example 1-6 uses gtacl to
run the TACL STATUS command.

Example 1-6 Using gtacl to Run a TACL Command


$ gtacl -c 'status *, user'

You can also pipe (send) the output of a Guardian command or program to an OSS utility.
Example 1-7 pipes the output of the TACL FILES command to the OSS grep utility.

Example 1-7 Using gtacl to Pipe TACL Command Output to an OSS Utility
$ gtacl -c 'files' | grep -c 'tdm'

When using gtacl, keep in mind that block-mode applications, such as TEDIT and Pathway,
require 6530 terminal emulation. 6530 terminal emulation is available only in the Guardian
environment, which means that block mode applications are not accessible through gtacl.
For more information about gtacl, refer to the Open System Services User’s Guide and to the
gtacl(1) utility reference page either online or in the Open System Services Shell and Utilities
Reference Manual.

OSSTTY
OSSTTY provides a way for OSS processes to interact with Guardian processes using the OSS
standard files. Using OSSTTY, an OSS process can redirect its standard files (stdin, stdout,
stderr) to a Guardian process or to a Guardian EDIT file. For example, the following command
uses OSSTTY to redirect the stdin of the OSS child process to $vhs, and the stdout to $zhome:
TACL> osh/ in $vhs, out $zhome/ -osstty
For more information on using OSSTTY, see Chapter 7 (page 195). A complete description of the
osstty command options is given in the Open System Services Management and Operations Guide.

OSS Tools
The following tools are available to you from the OSS environment at the OSS shell prompt. If
you provide your own tools, be aware that OSS environment tools run faster as compiled programs
than as OSS shell scripts.

42 Overview of the OSS Programming Environment


Editing Tools
HP provides three text-editing tools in the OSS environment:
• ed, a line editor. For detailed information, refer to the Open System Services User’s Guide and
to the ed(1) reference page either online or in the Open System Services Shell and Utilities
Reference Manual.
• sed, a stream editor. For detailed information, refer to the sed(1) reference page either
online or in the Open System Services Shell and Utilities Reference Manual.
• vi, a screen-oriented line editor. For detailed information, refer to the Open System Services
User’s Guide and to the vi(1) reference page either online or in the Open System Services
Shell and Utilities Reference Manual.

C Development Utilities
Open System Services provides a variety of tools to assist you in developing C applications. The
following are some of the more useful programming tools:
• ar, which creates and maintains groups of one or more named files as a single library file
written in an archive format. If the archive contains object files, the archive can be used as
an object file library by the Binder. For detailed information, refer to the ar(1) utility
reference page either online or in the Open System Services Shell and Utilities Reference Manual.
• lex, which allows you to create structured input analyzers. You provide regular expressions
that specify what you want to find in the input stream and lex generates a C language
lexical analyzer from these rules that provides tokens for your application. The lex utility
is often used in conjunction with yacc, which parses the stream of tokens that the lexical
analyzer produces. For detailed information, refer to the Open System Services User’s Guide
and to the lex(1) utility reference page either online or in the Open System Services Shell
and Utilities Reference Manual.
• make, which maintains program dependencies. The make utility is useful in combining your
program modules into a coherent application and enabling you to maintain individual
modules. For detailed information, refer to the Open System Services User’s Guide and to the
make(1) utility reference page either online or in the Open System Services Shell and Utilities
Reference Manual.
• nm, which lists symbolic information appearing in an object file, executable file, or object-file
library. For detailed information, refer to the nm(1) utility reference page either online or
in the Open System Services Shell and Utilities Reference Manual.
• strip, which removes any information not required for executing files. Do not use strip
before using the symbolic debuggers, because strip removes the symbol region required
for symbolic debugging. For detailed information, refer to the strip(1) utility reference
page either online or in the Open System Services Shell and Utilities Reference Manual.
• yacc, which enables you to generate parsing programs. This utility is useful if, for example,
your application has an input language. You supply a grammar for the language, and yacc
produces a C program that parses the input stream. The yacc utility is often used in
conjunction with lex, from which it receives tokens. For detailed information, refer to the
Open System Services User’s Guide and to the yacc(1) utility reference page either online or
in the Open System Services Shell and Utilities Reference Manual.

Compilation Tools
The c89 and c99 utilities control the C compilation system in the OSS environment. There are
native versions of c89 and c99 for TNS/E systems, a native version of c89 for TNS/R systems,
and a TNS version of c89 for TNS/R systems. (A TNS version of c89 is not supported on TNS/E
systems). The native versions are the default versions. The c99 utility is supported for TNS/E
targets on TNS/E systems only.

Using the Development Tools 43


Native c89 and native c99 provide an interface to the components of the C compilation system,
including the C and C++ language preprocessors, C and C++ compilers, linkers (nld, ld, and
eld utilities), optimizer (built into the compilers), and the SQL compilers. The noft (on TNS/R
systems) and enoft (on TNS/E systems) utilities allow you to examine various attributes of
native object files.
TNS c89 provides an interface to the components of the C compilation system, including the C
and C++ language preprocessors, C and C++ compilers, linkers (Binder), Accelerator (on TNS/R
systems), and the SQL/MP compiler.
Table 1-2 shows some sample c89 commands. For each sample command, the table shows the
name of the output file produced and what operations are performed.
Table 1-2 Sample c89 Commands
Command Output File Operations Performed

c89 test1.c a.out • TNS/R target: Compiles, links (using the default
linker nld), produces non-PIC executable program
file.
• TNS/E target: Compiles, links (using the eld linker),
produces PIC (position-independent code)
executable program file.

c89 test1.c -Wcall_shared a.out Compiles, links (using the ld linker for TNS/R target,
or the eld linker for TNS/E target), produces
position-independent code (PIC) executable file.

c89 -g test1.c a.out Compiles, links, generates symbolic information for


debugging (used by the Inspect debugger for a TNS/R
target, or the Native Inspect debugger for a TNS/E
target), produces executable program file.

c89 -c test1.c test1.o Compiles, does not link, produces object file.

c89 -o testout test1.c testout Compiles, links, produces executable program file.

c89 -o testout test1.o test2.c testout Compiles test2.c, links it with test1.o, produces
executable program file.

c89 -O testout testout Optimizes an executable program file.

For more information, see:

Topic Manual

c89 The C/C++ Programmer’s Guide and the c89(1) utility reference page either online or in the
Open System Services Shell and Utilities Reference Manual

c99 The C/C++ Programmer’s Guide and the c99(1) utility reference page either online or in the
Open System Services Shell and Utilities Reference Manual

nld The nld Manual and the nld(1) reference page either online or in the Open System Services
Shell and Utilities Reference Manual

ld The ld Manual and the ld(1) reference page either online or in the Open System Services
Shell and Utilities Reference Manual

noft The noft Manual and the noft(1) reference page either online or in the Open System Services
Shell and Utilities Reference Manual

eld The eld Manual and the eld(1) reference page either online or in the Open System Services
Shell and Utilities Reference Manual

enoft The enoft Manual and the enoft(1) reference page either online or in the Open System
Services Shell and Utilities Reference Manual

Binder Binder Manual

44 Overview of the OSS Programming Environment


Topic Manual

Accelerator Accelerator Manual

Object Code Object Code Accelerator (OCA) Manual


Accelerator

Compiler Output - Two Object File Types


The TNS/R native environment supports two object file types: position-independent code (PIC)
object files and non-PIC object files. The TNS/E native environment supports only PIC object
files. PIC enables you to create dynamic-link libraries (DLLs) and to create programs that use
DLLs. A DLL is a type of library that can be loaded dynamically by an executing process.
To create a PIC linkfile, an option flag is required on the TNS/R c89 command. On TNS/E systems,
PIC is the only object file type supported, and no option flag is required on the TNS/E c89
command. You then use the ld utility (for a TNS/R target) or the eld utility (for a TNS/E target)
to link the PIC object file into a DLL or PIC program file. Refer to the ld Manual or the eld Manual
for more information about PIC files and the ld or eld utility.
PIC files are not supported in the TNS environment.

Compilation Considerations for TNS Programs


The ld, nld, eld, noft, and enoft utilities are not available to TNS programs.
The Accelerator program optimizes TNS programs for TNS/R systems. (Open System Services
does not support the TNS compilation tools on TNS/E systems.) You can include the -O flag on
the c89 command line with your first compilation, but this is not a good idea because the
optimization step is time-consuming, increases your compilation time, and loses some debugging
information. A better method is to compile and debug your program completely and then optimize
the executable program file.

Command Line Debuggers


Two command-line symbolic debuggers are provided in the OSS and Guardian environments:
Inspect and Native Inspect. The G-series Inspect debugger supports debugging of TNS and
non-position-independent code (non-PIC) TNS/R object files in the OSS and Guardian
environments on TNS/R systems. (To debug a PIC object file on a TNS/R system, you must use
either Visual Inspect or the low-level Debug facility.) The H-series Inspect debugger supports
debugging of TNS processes in the Guardian environment on TNS/E systems; it does not support
debugging of TNS/E native processes. The Native Inspect debugger is supported only on TNS/E
systems, and supports debugging of native processes in the OSS and Guardian environments.
The Native Inspect debugger is conceptually similar to the Inspect debuggers and has similar
functionality, but has different syntax and commands. The Native Inspect syntax is based on
gdb, a debugger that is widely used throughout the industry and is familiar to many application
developers.
Both Inspect and Native Inspect are interactive symbolic debuggers. Both provide source-level,
or symbolic, access to a program by allowing you, for example, to refer to a location by the logical
name you have given it in the source code or by the source code line number. The Inspect and
Native Inspect debuggers also provide machine-level access to a program by allowing you to
refer to an item by its absolute or relative address, display and modify machine registers, and
display machine code. However, if you optimize a program, you might need to use low-level
debugging capabilities. On TNS/E systems, Native Inspect provides commands for low-level
debugging; on TNS/R systems, you can use the Debug facility to look at optimized code.
You can start the Inspect or Native Inspect debugger by itself and then run programs within it,
or you can start both the Inspect or Native Inspect debugger and your program at the same time.
Example 1-8 (page 46) starts the Inspect debugger (on a TNS/R system) or Native Inspect debugger
(on a TNS/E system) by itself, from both the TACL prompt (two examples) and the OSS shell.
Using the Development Tools 45
Example 1-8 Starting the Inspect or Native Inspect Debugger by Itself
>RUN INSPECT
or
$ gtacl -p inspect

Example 1-9 starts the Inspect (on a TNS/R system) or Native Inspect debugger (on a TNS/E
system) and a program to be debugged at the same time, both from the TACL prompt and the
OSS shell.

Example 1-9 Starting the Inspect or Native Inspect Debugger and a Program at the Same Time
> RUND gprog
$ run -debug -inspect=on ossprog

For more information on the G-series Inspect debugger, see the Inspect Manual. If you are familiar
with dbx, a debugger commonly found on UNIX systems, see the Inspect Manual for a table
contrasting dbx and Inspect commands. For more information on the Native Inspect debugger,
see the Native Inspect Manual.

PC-Based Debuggers
NonStop Development Environment for Eclipse debugging
NSDEE Core with Debugging also includes a separately installed integrated debugger that you
can use to debug TNS/E processes. See “Using the NonStop Development Environment for
Eclipse” (page 49).

Visual Inspect
Visual Inspect is a PC-based interactive debugging tool that provides a graphical user interface
(GUI) in which you control the debug session and execute debugging commands through
pull-down menus and dialog boxes. Using Visual Inspect, you control the execution and
debugging of your program from a PC while the program runs on a NonStop server.
Visual Inspect supports high-level symbolic debugging of native and TNS processes (interpreted
and accelerated) in the Guardian and OSS environments through a PC-based graphical user
interface. Visual Inspect can also be used for debugging snapshot files.
Visual Inspect is supported on both G-series and H-series systems. G-series and H-series Visual
Inspect are identical, except that the H-series version has been enhanced with machine-level
debugging capabilities; you can use H-series Visual Inspect for low-level debugging tasks on
the PC that must be done on the NonStop server using Debug or Inspect on G-series systems.
Visual Inspect is the preferred debugger in the native environments. It offers a simpler and more
intuitive user interface and more capabilities compared to the command-line debuggers, and is
designed to work in complex distributed environments. For example, working from a PC, you
can use Visual Inspect to debug multiple processes residing on the same or on different nodes
in a network. The processes can be TNS, native TNS/R, or native TNS/E, in the Guardian or OSS
environment.
You can start Visual Inspect by entering the RUNV command, either at the TACL prompt or
from the OSS shell. The following example starts execution of a program under control of Visual
Inspect on the client PC mypc:

46 Overview of the OSS Programming Environment


Example 1-10 Starting the Visual Inspect Debugger
> RUNV WSADDR=MYPC gprog
$ runv -wsaddr=mypc ossprog

You can also start Visual Inspect by first establishing a client connection to Visual Inspect on a
PC, then entering a run command with -inspect=on. For example, assuming a Visual Inspect
client connection exists, the following command starts a program under control of Visual Inspect:
$ run -debug -inspect=on ossprog
Visual Inspect can also be started from within the Enterprise Toolkit - NonStop Edition (ETK)
PC-based program development environment (see “Using the HP Enterprise Toolkit - NonStop
Edition” (page 49) for more information).
See the Visual Inspect online help for more information on Visual Inspect.

Guardian Tools
The following tools are available to you from the Guardian environment at the TACL prompt.

Editor
TEDIT is a full-screen text editor. For information about TEDIT features and commands, see the
PS Text Edit and PS Text Format User’s Guide.

File-Type Conversion Tools


TEDIT creates type 101 files. Files in the /G directory created with an OSS editor such as vi have
a type of 180. If you have a type 180 file you want to edit with TEDIT, use the conversion tool
CTOEDIT to convert the type 180 file to a type 101 file, as shown in Example 1-11.

Example 1-11 Convert Type 180 File to Type 101 File


> CTOEDIT ossfile, editfile

To convert a type 101 file to a type 180 file, use the EDITTOC conversion tool, as shown in
Example 1-12.

Example 1-12 Convert Type 101 File to Type 180 File


> EDITTOC editfile, ossfile

Note that files of type 180 do not have a concept of line numbers. Converting from file type 101
to 180 and back to 101 results in the loss of line number information.

Compilation Tools
There are two sets of native compilation tools and one set of TNS compilation tools:
• The TNS/R native compilation tools are the the TNS/R native C and C++ compilers, the ld
and nld utilities (linkers), and the noft utility for examining attributes of TNS/R native
object files. Control over code optimization is built into the compilers
• The TNS/E native compilation tools are the TNS/E native C and C++ compilers, the eld
utility (linker), and the enoft utility for examining attributes of TNS/E native object files.
Control over code optimization is built into the compilers.
• The TNS compilation tools are the TNS C compiler, Binder (linker), and Accelerator (optimizer
on systems running G-series RVUs) or Object Code Accelerator (optimizer on systems
running H-series RVUs). On systems running G-series RVUs, the TNS compilation tools are
supported in the OSS and Guardian environments. On systems running H-series RVUs, the
TNS compilation tools are supported only in the Guardian environment.

Using the Development Tools 47


For more information about the Guardian compilation tools, see the following manuals:
• C/C++ Programmer’s Guide
• ld Manual
• nld Manual
• eld Manual
• noft Manual
• enoft Manual
• Binder Manual
• Accelerator Manual
• Object Code Accelerator (OCA) Manual

Debuggers
See the discussion about the Inspect, Native Inspect, NonStop Development Environment for
Eclipse (NSDEE), and Visual Inspect products in “OSS Tools” (page 42).

Measure Performance Analyzer


The Measure product is a data collection and measurement tool that provides a wide range of
performance statistics on system resources; Measure interfaces can be used from the Guardian
environment to gather information on OSS objects. Using the Measure product, you can gather
information from applications, systems, and network components, then use this data to perform
sizing evaluations for applications, balance and tune your system, detect bottlenecks, and balance
workloads. For example, you can use the Measure product to see how processor-bound a program
is so you can evaluate whether it is worthwhile to optimize the program.
Measure provides both a command interface and a programmatic interface. The command
interface is a set of commands you can enter at the terminal or input from a file. The programmatic
interface is a set of procedures you can call from an application program. Using the command
or programmatic interface, you can configure a measurement, start the measurement, stop the
measurement, and create a formatted report.
Measure provides flexibility in the reporting of performance data, allowing you to manipulate
the content and format of output displays. You can use a standard format that can be modified.
You can also display data in plot and bar-chart formats, and you can create custom reports using
Enform or the HP NonStop SQL/MP command interpreter and report writer.
The Measure product has been enhanced to include features specifically designed to support the
OSS environment. These features are summarized in the following subsections. For more
information about the Measure product, see the Measure User’s Guide.

OSS Pathnames in Measure Commands


You can specify OSS pathnames in Measure commands and procedure calls. Measure also
supports the display of OSS pathnames in output reports.

OSS Opens in Measure


The FILE entity now encompasses the OSS file open types, including OSS Regular Files, OSS
Pipes, OSS FIFO, and OSS Sockets. This enhances the ability of Measure to analyze and improve
interprocess data flow for OSS applications.

OSS Entities in Measure


Measure provides instrumentation of a number of OSS components whose capacity or operation
influence overall system performance. These include the OSS CPU counters and OSS Name
Server entities. The OSS CPU counters entity provides information about the OSS elements that
operate in each processor of a system. These elements include the POSIX Extended Segment, the
OSS File System Cache, the OSS File Manager, the OSS Pipe Pool, and the OSS Pipe Server. The

48 Overview of the OSS Programming Environment


OSS Name Server entity provides information about the operation and performance of OSS
Name Server processes.

Other Measure Enhancements for OSS


Other Measure features have been enhanced for OSS support, including:
• PROCESS entity. This entity provides information about one or more processes on a local
system. For OSS instrumentation, the PROCESS entity record is extended to include aggregate
counters for three OSS file types: TTY, /dev/null, and interactions with the OSS Name
Server for directory information.
• DISKFILE Entity. This entity measures all I/O operations performed by all opener processes
on a specified disk file. For OSS instrumentation, the DISKFILE entity record is extended
by four counters. They report on cache callback management in the OSS File System.

Using the NonStop Development Environment for Eclipse


The HP NonStop Development Environment for Eclipse (NSDEE) is a Windows-hosted integrated
development environment for NonStop applications. NSDEE supports building NonStop
applications locally using Windows-hosted cross-compilers and tools, or remotely using compilers
and tools on a NonStop server. NSDEE also provides facilities for transferring source files and
binaries to and from NonStop systems as well as facilities for editing remote source files locally.
NSDEE Core with Debugging also includes a separately installed integrated debugger that you
can use to debug TNS/E processes.
The documentation for NSDEE is integrated with the software. After you install the software,
you can access the documentation from the Eclipse Workbench help menu:
1. To access the Workbench help menu, select Help→Help Contents.
2. From the list of manuals, select the NonStop Development Environment for Eclipse User Guide.
3. If you have installed NSDEE Core with Debugging, you can also select the NonStop
Development Environment for Eclipse Debugging Supplement from the list of manuals.

Using the HP Enterprise Toolkit - NonStop Edition


The HP Enterprise Toolkit - NonStop Edition (ETK) is an integrated development environment
that enables you to build NonStop applications on a PC. HP has integrated its native C and C++
PC cross compiler and related tools into a development environment that can produce code for
both Guardian and OSS environments.
ETK is an extension package to Microsoft Visual Studio .NET that provides a full range of
application development functions . ETK has commands and options that enable you to compile
and link your applications on a PC and then run them on a NonStop system. After compiling
and linking, you can send your object file directly to the NonStop system either automatically
with project deployment or manually with the Transfer Tool. You perform all functions using a
familiar graphical user interface.
ETK provides a choice of compilers, editors, and debuggers, including the Visual Inspect debugger.
Using ETK, you can create and maintain archive files, perform source control, and create projects
that contain embedded SQL/MP or SQL/MX source code.
On G-series systems, many of these development functions can also be performed using the HP
Tandem Development Suite (TDS), but ETK provides certain advantages and is the recommended
development environment. TDS is not supported on system running H-series RVUs.
ETK is delivered on a separate compact disc and is not available on the HP site update tape
(SUT).
For more information on using the ETK and native C and C++ cross compilers on a PC, refer to
the online help for the ETK. For more information on using TDS, refer to the TDS online help
and to the C/C++ Programmer’s Guide.

Using the NonStop Development Environment for Eclipse 49


50
2 Managing Files
You access OSS files in the OSS environment as you would access UNIX files. The OSS
environment also enables you to access files in the Guardian environment, which means that
you can create applications for NonStop systems that use data in Guardian files and that take
advantage of OSS portability and other OSS features.
In the OSS environment, sockets, pipes, FIFOs, and terminals are also files. These files are discussed
elsewhere in this guide. With respect to the OSS environment, this section discusses only
directories and regular files.
This section discusses the following topics:

Topic Content

“The OSS and Guardian File Systems” (page 51) Differences between the two file systems, including
filename formats and mapping, and Guardian security
and OSS file-access permissions.

“Common and Unique Characteristics” (page 62) Summary of the differences between the OSS and UNIX
file systems.

“Accessing Files From the OSS API” (page 63) Discussion and examples of how to access files from the
OSS API.

“Accessing Files From the Guardian API” (page 65) Discussion and examples of how to access files from the
Guardian API.

“Accessing OSS Files Larger Than 2 GB” (page 74) Discussion of support for OSS files larger than
approximately 2 GB, including accessing such files from
OSS APIs and Guardian APIs, and interoperability issues.

“Common Completion” (page 79) An enhancement to the Enscribe file system and the Open
System Services file system.

“Performance Considerations” (page 82) Discussion of how to get optimum performance for your
application.

“OSS File-System Functions” (page 84) List of each OSS file-system function with notes about its
OSS implementation and use with Guardian files.

“Guardian File-System Procedures” (page 94) List of each Guardian file-system procedure that affects
or is affected by OSS files with notes about its use with
OSS files.

The OSS and Guardian File Systems


This subsection describes differences between the Guardian and OSS file systems and the
implications of the differences for OSS programming.

Physical and Logical Names


Visible Guardian filenames are physical: they include the names of physical storage devices. A
fully qualified filename includes the name of a physical system (node) and the name of a physical
disk volume.
OSS pathnames are logical names: they do not include the names of storage devices. An OSS
pathname describes a path through the OSS directory tree to a file. Every OSS pathname (the
character string that identifies a file within its file system) for a disk file has a physical name in
the Guardian namespace, but that physical (Guardian) name cannot normally be used to access
files. To access OSS files, you must use OSS pathnames. For further information about OSS files
and pathnames, refer to the Open System Services User’s Guide.

The OSS and Guardian File Systems 51


The OSS file system theoretically allows an unlimited degree of nesting of directories within a
directory. You can have subdirectories in a directory, subsubdirectories in a subdirectory, and
so on. The Guardian environment allows only three levels in a node: volume, subvolume, and
file ID. You cannot have nesting; therefore, you cannot have a volume that is within another
volume.

Filename and Pathname Mappings


The /G directory contains Guardian files, but they are referred to by OSS pathnames. Guardian
filenames are much more restricted than OSS pathnames and cannot always be used
interchangeably. For example, the OSS filenames properties.c and properties.d are both
translated into the Guardian file ID PROPERTI, because Guardian file IDs must be no longer
than eight characters, whereas OSS filenames can be much longer. This subsection describes how
OSS pathnames and Guardian filenames are mapped to each other, so that you can construct
pathnames and filenames whose information does not get lost in the translation process.

Translating OSS Pathnames to Guardian Filenames


OSS functions use /G directory pathnames when they access Guardian files. /G directory
pathnames for Guardian files on the local node begin with the root directory; Guardian files on
another NonStop server node can be found in the /E directory under the node name and that
node’s corresponding /G directory.
The following steps describe how the local node pathname:
/G/Data.Volume/src.l1.v3.4.8/properties.c
is translated into a Guardian filename.
1. The leading /G is replaced by the local node name with a backslash, a slash, and a dollar
sign ($). The intermediate result is:
\NODE/$Data.Volume/src.l1.v3.4.8/properties.c
2. The portable pathname characters period (.), comma (,), hyphen (-), and underscore (_)
are deleted. The intermediate result is:
\NODE/$DataVolume/srcl1v348/propertiesc
3. Name components, which are between the slashes, are truncated to eight characters. The
intermediate result is:
\NODE/$DataVol/srcl1v348/properti
4. Slashes are replaced by periods. The final result is:
\NODE.$DataVol.srcl1v348.properti

The following steps describe how the remote node pathname:


/E/NODE1/G/Data.Volume/src.l1.v3.4.8/properties.c
is translated into a Guardian filename.
1. The leading /E is replaced by a backslash. The intermediate result is:
\NODE1/G/Data.Volume/src.l1.v3.4.8/properties.c
2. The /G/ is replaced by a slash and a dollar sign ($). The intermediate result is:
\NODE1/$Data.Volume/src.l1.v3.4.8/properties.c
3. The portable pathname characters period (.), comma (,), hyphen (-), and underscore (_)
are deleted. The intermediate result is:
\NODE1/$DataVolume/srcl1v348/propertiesc
4. Name components, which are between the slashes, are truncated to eight characters. The
intermediate result is:
\NODE1/$DataVol/srcl1v348/properti

52 Managing Files
5. Slashes are replaced by periods. The final result is:
\NODE1.$DataVol.srcl1v348.properti

The pathname /G/volname/subvol/fileid of a permanent Guardian disk file is translated


to the filename \NODE.$VOLNAME.SUBVOL.FILEID.
The pathname /G/volname/#num of a temporary Guardian disk file is translated to
\NODE.$VOLNAME.#num.
With relative pathnames, the name component . (dot) is deleted. The pathname ./subvol/fileid
is treated as /G/volname/subvol/fileid.
If a relative pathname contains the name component .. (dot-dot), the preceding name component
is deleted. If the deleted component was the first component of the Guardian filename, normal
root resolution continues at the root of the root fileset. For example, the pathname
/G/vol1/../vol2/subvol/fileid is treated as /G/vol2/subvol/fileid, and
/./vol1/../../dir is treated as /dir.
If the name resulting from the translation is not a valid Guardian filename, the translation
operation terminates with the error ENOENT, except when the creation of such a name is attempted,
which fails with the error EINVAL.
The following examples result in invalid filenames:
/G/data/a/b/c (too many levels)
/G/oss/src:v3.4/logger.c (the colon (:) is an illegal character)
Table 2-1 (page 53) shows pathnames that can be translated to valid Guardian filenames and
the corresponding Guardian filename.
Table 2-1 OSS Pathname to Guardian Filename Translation Examples
OSS Pathname on Node Named NODE Guardian Filename

/G/Data.Volume/src.l1.v3.4.8/properties.c \NODE.$DATAVOL.SRCl1V34. PROPERTI

/G/data/mysubvol/file \NODE.$DATA.MYSUBVOL.FILE

/G/disk \NODE.$DISK

/G/ztnt/#pty7 \NODE.$ztnt.#pty7

Only filenames on the local node can appear in the /G directory, so only local names are translated.
OSS files are stored with Guardian filenames in subvolumes whose names begin with ZYQ. The
OSS absolute pathname that corresponds to a Guardian filename has the following form:
/G[/volume[/subvolume[/fileid]]]
The number of components of the translated pathname depends on the number of components
in the filename. The components of a pathname are derived from a filename as follows:
1. The filename is converted to lower case.
2. volume is derived by replacing the dollar sign ($) in the filename with /G/.
3. A period (.) in the filename is replaced with a slash (/) .
Table 2-2 shows pathnames that can be translated to valid OSS filenames and the corresponding
OSS filename.
Table 2-2 Guardian Filename to OSS Pathname Translation Examples
Guardian Filename OSS Pathname

$VOL /G/vol

$vol /G/vol

$VOL.SUBVOL /G/vol/subvol

$p.#1234 /G/p/#1234

The OSS and Guardian File Systems 53


Table 2-2 Guardian Filename to OSS Pathname Translation Examples (continued)
Guardian Filename OSS Pathname

$p.#PTY12 /G/p/#pty12

$pubs.henry.panaceas /G/pubs/henry/panaceas

Obtaining Corresponding Guardian and OSS Filenames


You can obtain the Guardian filename that corresponds to an OSS pathname and vice-versa with
OSS shell utilities, the Guardian File Utility Program (FUP), or through programmatic interfaces.

Using OSS Shell Utilities


You can obtain the Guardian equivalent of an OSS pathname with the OSS shell utility gname,
and you can obtain the OSS equivalent of a Guardian filename with the OSS shell utility pname.
To display the fully qualified Guardian filename that corresponds to an OSS pathname, enter
the following from the OSS shell:
gname [-s] pathname
where the -s flag displays only the Guardian filename and pathname is an OSS pathname.
Example 2-1 shows examples of using gname.

Example 2-1 Using gname to Obtain a Guardian Filename


$ gname test2
gname: test2 --> \NODE.$VOL.ZYQ00000.Z0000KHP

$ gname -s test
\NODE.$VOL.ZYQ00000.Z0000DV3

$ gname /G/zznt/#pty00bk
gname: /G/zznt/#pty00bk --> \NODE.$ZZNT.#PTY00BK

To display the OSS pathname that corresponds to a Guardian filename, enter the following from
the OSS shell:
pname [-s] filename
where the -s flag displays only the OSS pathname and filename is a Guardian fully qualified
or system-qualified filename. Example 2-2 shows examples of using pname.

54 Managing Files
NOTE: As shown in Example 2-2, you must put a backslash (\) before the slash (/), the backslash
(\), and dollar sign ($) characters, or else the shell will interpret them with their special shell
meanings rather than as plain characters. You can also put the filename inside single quotation
marks.

Example 2-2 Using pname to Obtain an OSS Pathname


$ pname \$VOL.ZYQ00000.Z0000DV3
pname: $VOL.ZYQ00000.Z0000DV3 --> /home/henrysp/test

$ pname \\node.\$VOL.ZYQ00000.Z0000DV3
pname: \node.$VOL.ZYQ00000.Z0000DV3 --> /home/henrysp/test

$ pname -s \$VOL.ZYQ00000.Z0000DV3
/home/henrysp/test

$ pname -s '$VOL.ZYQ00000.Z0000DV3'
/home/henrysp/test

File Utility Program (FUP)


The Guardian FUP INFO command with the DETAIL option displays the OSS pathname for a
file next to the PATH: heading, as illustrated in Example 2-3.

Example 2-3 FUP INFO DETAIL Display With an OSS File


> fup info \NODE.$ROOT.ZYQ00000.Z0000066, detail

$ROOT.ZYQ00000.Z0000066 12 Apr 2000, 13:01


OSS
PATH: /bin/ls
OWNER -1
SECURITY: -r-xr-xr-x
CREATION DATE: 7 Dec 1998, 10:12
ACCESS TIME: 11 Apr 2000, 10:55
EOF: 89232

In the figure, the OWNER field contains -1 because the owner is the super ID. For other owners,
the field contains the structured form (group_number, member_number) of the NonStop
operating system user ID. The structured form can be converted to the scalar form used as the
OSS user ID (UID) using the following formula:
UID = member_number + (256 * group_number).

Using Guardian Procedures


You can obtain the Guardian filename that corresponds to an OSS pathname with the Guardian
procedure PATHNAME_TO_FILENAME_, and you can obtain the OSS pathname that
corresponds to a Guardian filename with the Guardian procedure FILENAME_TO_PATHNAME_.
Example 2-4 shows how to use the PATHNAME_TO_FILENAME_ procedure. The program
takes as its input an OSS pathname and prints the corresponding Guardian filename.

The OSS and Guardian File Systems 55


Example 2-4 Using the Guardian PATHNAME_TO_FILENAME_ Procedure
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cextdecs.h(PATHNAME_TO_FILENAME_)>

char filename[64];
short filelen;
short status;

int main(int argc, char *argv[]) {


short ret;

/* Make sure the correct number of arguments are entered.


If not, print usage message and exit. */
if(argc < 2) {
fprintf(stderr,"Usage: pthtofil pathname\n");
exit (1);
}
/* Invoke the Guardian procedure call.
Note the special format for options. */
ret = PATHNAME_TO_FILENAME_(argv[1], /* OSS pathname */
filename, /* Guardian filename buffer */
64, /* size of filename buffer */
&filelen, /* length of filename */
&status ); /* if = 1, Guardian file (/G)
if = 0, OSS file */

/* If the call fails, print a message and exit. */


if (ret != 0) {
fprintf(stderr,"Bad path name\n");
exit(1);
}
filename[filelen] = '\000'; /* make NULL-terminated string */

/* Determine the file type and print the file. */


if(status&1)
printf("Guardian (/G) file = %s\n", filename);
else
printf("OSS file = %s\n", filename);
return(0);
}

Example 2-5 shows how to use the FILENAME_TO_PATHNAME_ procedure. The program
takes as its input a Guardian filename and prints out the corresponding OSS pathname. This
program example demonstrates the use of /E.

56 Managing Files
Example 2-5 Using the Guardian FILENAME_TO_PATHNAME_ Procedure
Guardian FILENAME_TO_PATHNAME procedure */

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tal.h>
#include <cextdecs.h(FILENAME_TO_PATHNAME_)>

char pathname[PATH_MAX];
short pathlen;
short index = 0;

int main(int argc, char *argv[]) {


short ret;

/* Make sure the correct number of arguments are entered.


If not, print a usage message and exit. */
if(argc < 2) {
fprintf(stderr,"Usage: filtopth filename\n");
exit (1);
}
/* Invoke Guardian procedure call. Note the special format for options */
while(index != -1) { /* print all possible pathnames */
ret = FILENAME_TO_PATHNAME_(argv[1], /* Guardian filename */
(short)strlen(argv[1]), /* length of filename */
pathname, /* buffer for OSS pathname */
PATH_MAX, /* length of buffer */
&pathlen, /* length of pathname */
6, /* absolute pathname wrt. system root */
/* includes system name in the form
/E/system/pathname */
&index /* index of link to file */
);
/* If the call fails, print a message and exit. */
if (ret != 0) {
fprintf(stderr,"Bad file name\n");
exit(1);
}
/* Print pathname */
printf("Pathname = %s\n", pathname);
}
return(0);
}

Example 2-6 shows the use of FILE_COMPLETE_SET, FILE_COMPLETE_, and


FILE_COMPLETE_GETINFO_ to wait for the completion of I/O on Guardian and OSS files. Once
enabled for completion, files from the specified set can be completed multiple times. Guardian
files are opened for NOWAIT I/O, and OSS files can be nonblocking or blocking.

The OSS and Guardian File Systems 57


Example 2-6 Using FILE_COMPLETE_SET, FILE_COMPLETE_, and FILE_COMPLETE_GETINFO_
/* Guardian FILE_COMPLETE_* procedures */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tdmext.h>
#include <unistd.h>
#include <fcntl.h>
#include <zsysc>.h>
#include <tal.h>
#include <cextdecs.hh(FILE_OPEN_,READX,FILE_COMPLETE_,AWAITIOX,\
FILE_COMPLETE_SET_,FILE_COMPLETE_GETINFO_)>

_cc_status CC;
short filenum, fnum, bytesread;
int fd,nb;
short retcode, status;
char *pathname; /* OSS path name */
char *filename; /* Guardian file name */
char bufoss[1025]; /* allow for NULL character at end of OSS buffer */
char bufgdn[1025]; /* allow for NULL character at end of Guardian buffer */
zsys_ddl_complete_element_def comp_elem[2]; /* completion elements */
short err_elem; /* error return for FILE_COMPLETE_SET_ */
short num_elem; /* Total number of Guardian and OSS files */
zsys_ddl_completion_info_def comp_info; /* completion information */
zsys_ddl_complete_element_def info_list[7];
/* array of information elements */

char buffer[1026]; /* allow for NULL termination of string in buffer */


long request_tag;
int i;

int main(int argc, char *argv[]) {


/* Check for the proper number of arguments;
if no path/file names are supplied, use the default names. */
if (argc > 1)
pathname = argv[1];
else
pathname = "/usr/include/stdio.h";
if(argc > 2)
filename = argv[2];
else
filename = "$system.system.stdioh";

/* Open the OSS file in non-blocking and read-only mode */


fd = open(pathname, O_NONBLOCK|O_RDONLY);
/* If the open is unsuccessful, print a message and exit. */
if (fd < 0) {
fprintf(stderr, "Cannot open %s\n", pathname);
exit(1);
}

/* Open the Guardian file in nowait mode */


retcode = FILE_OPEN_(filename, /* name of Guardian file */
(short) strlen(filename), /* filename length */
&filenum, /* file number returned */
1, /* open for read */
, /* shared exclusion */
1, /* number of concurrent nowait I/O
operations permitted */
, /* sync or receive depth */
, /* Guardian filename */
);
/* If the open is unsuccessful, print a message and exit. */
if (retcode != 0) {
fprintf(stderr, "Cannot open %s\n", filename);
fprintf(stderr, "retcode = %d\n", retcode);
exit(1);
}

58 Managing Files
/* Set the completion elements for the OSS file and the Guardian file */
comp_elem[0].z_fnum_fd = fd; /* OSS file */
comp_elem[0].u_z_options.z_options.z_filetype = 1;
comp_elem[0].u_z_options.z_options.z_read_ready = 1;
comp_elem[0].u_z_options.z_options.z_exception = 1;
comp_elem[1].z_fnum_fd = filenum; /* Guardian file */
comp_elem[1].u_z_options.z_options.z_filetype = 0;
status = FILE_COMPLETE_SET_((short *) comp_elem, 2, &err_elem);
if(status) {
if(err_elem)
fprintf(stderr, "Error %d in FILE_COMPLETE_SET for OSS file = \
%s\n", err_elem, pathname);
else
fprintf(stderr, "Error %d in FILE_COMPLETE_SET for Guardian file = \
%s\n", err_elem, filename);
exit(1);
}

/* Start non-blocking I/O on OSS file */


nb = read(fd, bufoss, 1024);
if(nb < 0) {
fprintf(stderr, "OSS file read error %d\n", nb);
exit(1);
}
/* Start nowait read on the Guardian file using READX.
Note that a request tag is not required when only one
outstanding read is issued. It is shown here for
demonstration purposes only. */
request_tag = 123; /* form unique request tag */
CC = READX( filenum, /* file number */
bufgdn, /* buffer address */
1024, /* size of buffer */
, /* number of bytes read, not
used for nowait I/O */
request_tag /* unique request tag */
);
/* If the condition code returned is not the one for success,
print a message and exit. */
if(_status_ne(CC)) { /* check the success condition code */
fprintf(stderr, "Read failed on Guardian file\n");
exit(1);
}

/* Get info. about the set of files enabled for common completion */
status = FILE_COMPLETE_GETINFO_(
(short *) info_list, /* array of information elements */
2, /* only two requested */
&num_elem /* actual number of files */
);
if(status) {
fprintf(stderr, "File Complete Getinfo error %d\n", status);
exit(1);
}
/* The program can execute code while the read operations are being
completed by the system. */
for (i = 0; i < 100000; i++) ;
printf("Now issuing FILE_COMPLETE_ to check for I/O completion.\n");

status = FILE_COMPLETE_(
(short *) &comp_info /* completion information */
, /* time limit (* 0.01 sec.) */
, /* array of complete elements */
, /* number of complete elements */
, /* error index */
);
if(status) {
exit(1);
}

/* AWAITIOX completes the READX operation. */


CC = AWAITIOX(&filenum , /* file number */
,

The OSS and Guardian File Systems 59


&bytesread, /* number of bytes read */
&request_tag /* request tag */
);

/* If the condition code returned is not the one for success,


print a message and exit. */
if(_status_ne(CC)) { /* check the success condition code */
fprintf(stderr, "Awaitiox failed.\n");
exit(1);
}
printf("Bytes read = %d\n", bytesread);

/* Print out the first ten bytes in octal plus "string". */


printf("First 10 bytes read (in octal): ");
for (i = 0; i < 10; i++)
printf("%o ", bufgdn[i]);
printf("\n");
bufgdn[bytesread] = '\0'; /* make sure string is NULL-terminated */
printf("\n%s\n", bufgdn);
return(0);
}

OSS File-Access Permissions


You obtain file-access permissions and other OSS file information with the stat(), lstat(),
and fstat() functions. Mappings of Guardian security to OSS file-access permissions are
summarized in Table 2-3 (page 60). Refer to the stat(2) reference page either online or in the
Open System Services System Calls Reference Manual for details about OSS file access permissions
and how they and Guardian security attributes and settings are mapped to each other.
Table 2-3 Mappings of Guardian Security to OSS File-Access Permissions
Guardian Security Attributes and Settings OSS File-Access Permission

Network (N) Other

Any User (A) Other

Community or Group (C or G) Group

User (U or O) Owner

Super ID (-) None (-)

Read Read

Write Write

Execute Execute

Purge (Ignored)

Mappings of OSS file-access permissions to Guardian security are based on user information
and are not predictable based only on file permission information. OSS file-access permissions
do not reflect:
• Safeguard access control lists (ACLs). To determine whether there is an Safeguard ACL on
a Guardian file, use the Guardian FILE_GETINFOLISTBYNAME_ procedure.
• OSS ACLs. To determine whether there is an OSS ACL on an OSS file you can use these
functions:
— The OSS stat(), fstat(), and lstat() system calls return an ACL-PRESENT flag
that specifies if the file or directory has an optional OSS ACL entry.
— Guardian FILE_GETINFOLIST_ and FILE_GETINFOLISTBYNAME_ procedures return
an ACL-PRESENT flag that specifies if the file or directory has a optional OSS ACL
entry.

60 Managing Files
Safeguard Protection and Disk Volumes
You cannot use Safeguard access control lists (ACLs) to protect individual OSS files. However,
you can protect the disk volume in which OSS files reside by restricting the ability of users to
create files in that volume.
If an Safeguard ACL restricts create access within a disk volume where OSS files reside, you
cannot create files in that volume unless you are one of the users listed in the Safeguard ACL. If
you are not listed in the Safeguard ACL, you can still open, read, and write to any existing file
in that volume.
The Safeguard product is a NonStop subsystem. For information about programmatic access to
this subsystem, see the Safeguard Management Programming Manual and the SPI Programming
Manual.

OSS ACLs
OSS ACLs are supported for directories, regular files, first-in, first-out (FIFO) files, and bound
AF_UNIX sockets in Version 3 catalog filesets on systems running J-series RVUs, H06.08 and
later H-series RVUs, and G06.29 and later G-series RVUs.
ACLs offer a greater degree of selectivity than permission bits. ACLs allow a process whose
effective user ID matches the file owner, super ID, or a member of the Safeguard
SECURITY-OSS-ADMINISTRATOR security group to permit or deny access to a file to a list of
specific users and groups.
ACLs are supported as a superset of the UNIX operating system discretionary access control
(DAC) mechanism for files, but not for other objects such as interprocess communication (IPC)
objects.
All OSS system calls that include pathnames are subject to the ACLs on any directory or file in
the path.
For details about OSS ACLs, see “Using OSS Access Control Lists (ACLs)” (page 249).

OSS ACLs and NFS Clients


OSS ACLs are not supported by the OSS Network File System (NFS) for J06.08 and earlier J-series
RVUs, H06.19 and earlier H-series RVUs, or G-series RVUs. Any attempt by NFS clients to access
OSS objects protected by OSS ACLs that contain optional ACL entries is denied.
OSS ACLs are supported by the OSS NFS for J06.09 and later J-series RVUs and H06.20 and later
H-series RVUs as follows:
• Access by the OSS Network File System (NFS) to OSS objects protected by OSS ACLs that
contain optional ACL entries can be allowed, depending upon the NFSPERMMAP attribute
value for the fileset that contains the object.
• The NFSPERMMAP attribute value selects the algorithm used to map the OSS ACL
permissions for the object to the standard permissions (rwxrwxrwx) expected for the object
by NFS V2 clients.
• The default value for the NFSPERMMAP attribute, DISABLED, specifies that any attempt
by NFS clients to access OSS objects protected by OSS ACLs that contain optional ACL
entries is denied. This behavior matches the behavior for J06.08 and earlier J-series RVUs,
H06.19 and earlier H-series RVUs, and G-series RVUs.
For a detailed description of OSS ACLs, including examples, see the acl(5) reference page
either online or in the Miscellaneous Topics section of the Open System Services System Calls
Reference Manual. For information about the NFSPERMMAP attribute, see the Open System Services
Management and Operations Guide. For more information about OSS NFS file system security, see
the Overview of NFS for Open System Services and the Open System Services NFS Management and
Operations Guide.

The OSS and Guardian File Systems 61


Accessible Files
All OSS source and text files are odd-unstructured files. Files in the /G directory that are used
as OSS source or text files are Guardian file type 180. Files in the OSS environment are Guardian
file type 100 regardless of content. These files permit reading and writing of both even and odd
byte counts and positioning to both even and odd byte addresses. Unstructured files do not have
a built-in record structure.
Only odd-unstructured files can be read and written in the OSS environment. EDIT files (file
type 101) are unstructured but not odd-unstructured, and they can be opened only for reading
in the OSS environment. All other Guardian files are inaccessible from the OSS file system but
can be accessed through Guardian file-system procedures.
On H-series RVUs prior to H06.06 and on G-series RVUs prior to G06.29, OSS files had a size
limit of approximately 2 GB (GB), and an underlying Guardian file of Format 1 (the file format
was normally not visible to customer applications). For J-series RVUs, H06.06 and later RVUs,
and G06.29 and later G-series RVUs, OSS files larger than approximately 2 GB are supported,
and can have an underlying Guardian file of either Format 1 or Format 2 (see “Accessing OSS
Files Larger Than 2 GB” (page 74)).

Using the ANSISTREAMS Pragma (Guardian C Program)


The ANSISTREAMS pragma in a Guardian C program causes your application’s standard input
(stdin), standard output (stdout), and standard error (stderr) files to be opened as
odd-unstructured disk files with no line length limit. Without this pragma these files are opened
as EDIT files with a line length limit of 239 characters. The ANSISTREAMS pragma enables your
programs to comply with the ISO/ANSI C standard, which requires that the C compiler support
lines containing at least 254 characters including the terminating newline character.
If the SYSTYPE OSS pragma is set (the default setting for the c89 and c99 utilities), you do not
need to specify the ANSISTREAMS pragma because it is set automatically.
For further information about the ANSISTREAMS pragma, refer to the C/C++ Programmer’s Guide.

Common and Unique Characteristics


The OSS file system looks like a typical UNIX file system, but there are a few important differences.

Features Common to the UNIX and OSS File Systems


The OSS file system conforms to the POSIX.1 specification. There is no major difference between
the OSS file system and most UNIX file systems. There are some differences in the particulars
of some functions. These differences are summarized for each function in Table 2-5 (page 85)
and explained in detail in the reference pages, which can be found online and in the Open System
Services System Calls Reference Manual and the Open System Services Library Calls Reference Manual.

Features Unique to the OSS File System


The OSS file system has the following unique features:
• Administration through the Guardian environment and nonstandard information displays.
For example, ownership is displayed in the groupname.username format rather than the
standard username format. For additional information, refer to the Open System Services
User’s Guide.
• The /G directory, which is the OSS window into the Guardian file system on your local
NonStop node. All Guardian disk files on a node have a name in the /G directory.
• The /E directory, which is the OSS window into file systems on remote NonStop nodes.
• OSS file caching.
• Common Completion.

62 Managing Files
Accessing Files From the OSS API
In the OSS environment, you access OSS files in the same way that you would in any
POSIX-compliant UNIX programming environment. OSS functions are tailored to the OSS
environment and work more efficiently than Guardian procedures on OSS files.
You can access up to four types of Guardian files on physical disk volumes with OSS function
calls:
• Odd-unstructured Format 1 files (file codes 0, 100, and 180). These files permit reading and
writing of both even and odd byte counts and positioning to both even and odd byte
addresses. Unstructured files do not have a built-in record structure.
• EDIT files (file type 101). These files are unstructured. You can access them only for reading.
• Telnet processes.
• For J-series RVUs, H06.06 and later RVUs, and G06.29 and later G-series RVUs,
odd-unstructured Format 2 files (file codes 0, 100, and 180). These files permit reading and
writing of both even and odd byte counts and positioning to both even and odd byte
addresses. Unstructured files do not have a built-in record structure. For detailed information
about accessing these files, see “Accessing OSS Files Larger Than 2 GB” (page 74).
You cannot access:
• Files on logical disk volumes administered through the Storage Management Foundation
(SMF)
• A volume, a subvolume, or a process other than a TTY simulation process (/G/vol,
/G/vol/subvol, or /G/process, respectively)
• A file within a subvolume with a reserved name beginning with ZYQ (for example:
/G/vol2/zyq00004/z000002x)
Odd-unstructured files and EDIT files are opened as OSS regular files.
If you want your application to modify odd-unstructured Guardian files, or if your application
uses data stored in odd-unstructured Guardian files or EDIT files, you can use the interoperability
capabilities of the OSS environment and access these files with OSS functions. If you need to
modify EDIT files or open structured files, you can use Guardian procedures as described in
“Accessing Files From the Guardian API” (page 65).

NOTE: Optical disks are inaccessible directories in /G. This means that OSS functions cannot
open, create, or read files in directories under /G when the files reside on optical disks.
As an alternative to using Guardian procedures when you cannot accomplish a task with OSS
functions, you might be able to accomplish the task with the Guardian C functions. Write a
separately compiled module using Guardian C functions and link (bind) this module into the
OSS program. Whether you should do this depends on whether you can accomplish the required
set of operations with Guardian C functions. Refer to Chapter 1 (page 25) for more information
about calling Guardian C functions from G-series TNS OSS programs.
Example 2-7 (page 64) shows how to read a Guardian file with OSS function calls; in this case,
open() and read(). The Guardian file is accessed through the /G directory.

Accessing Files From the OSS API 63


Example 2-7 Reading a Guardian File With an OSS Function Call
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

char buffer[1026]; /* allow for NULL termination of string in buffer */


char *filename; /* filename pointer */
int fd; /* file descriptor */
int nbytes; /* number of bytes read */

int main(int argc, char *argv[]) {

/* Check for the proper number of arguments; if no filename


is supplied, open the default file. */
if(argc > 1)
filename = argv[1];
else
filename = "/G/system/system/stdioh"; /* this file is opened if
no name is supplied */
fd = open(filename, O_RDONLY); /* open Guardian file for read */

/* Check for the validity of the file descriptor; if it is not valid,


print a message and exit. */
if(fd < 0) {
fprintf(stderr,"Can't open %s\n", filename);
exit(1);
}

/* If the read is unsuccessful, print an error message and exit. */


nbytes = read(fd, buffer, 1024);
if (nbytes < 0) {
perror("File read error: ");
exit(1);
}

/* Print the number of bytes read and the first part of the file. */
printf("Number of bytes read = %d\n", nbytes);
buffer[nbytes] = 0; /* make string NULL-terminated */
printf("%s\n", buffer);
return(0);
}

Using Functions With Environment-Specific Parameters


There are several file system functions that allow you to operate on a file in one environment
from a process running in the other environment. These functions are freopen(), remove(),
rename(), tmpfile(), and tmpnam(). Each of these functions has environment-specific
variants with suffixes to indicate which type of file you want to operate on. For example,
fopen_guardian() opens a Guardian file from an OSS process and fopen_oss() opens an
OSS file from a Guardian native process.

NOTE: If a TNS module calls any of the environment-specific variants, the feature-test macro
_INTEROPERABLE should be specified when the module is compiled. Specifying
_INTEROPERABLE allows subsequent I/O function calls to know which type of I/O stream they
are operating on.
Example 2-8 opens a Guardian file using fopen_guardian() in an OSS module and opens an
OSS file using fopen().

64 Managing Files
Example 2-8 Using fopen_guardian() in an OSS Module
/* Verify current process is an OSS process */
#ifndef _OSS_TARGET
#error “Wrong systype”
#endif

#include <stdio.h>
int main (int argc, char *argv[]) {
FILE *G_File;
FILE *P_File;
int c;

/* Open the Guardian file, note that since this is an OSS


process, need to explicitly call a version of fopen()that
opens a Guardian file. */
G_File = fopen_guardian ("$system.system.stdioh", "r");

/* Because this is an OSS process, we get the OSS fopen() by


default. */
P_File = fopen("mystdio.h", "w");

/* Note that the rest of the I/O routines do not require


environment-specific parameters. They can operate on OSS or
Guardian files. */
while(!feof(G_File)) {
c = getc(G_File); /* read from Guardian file */
putc(c, P_File); /* write to OSS file */
}
fclose(G_File);
fclose(P_File);
return(0);
}

Accessing Files From the Guardian API


Guardian files can be managed from the Guardian API as described in the Guardian Programmer’s
Guide and the Guardian Procedure Calls Reference Manual.
OSS files can also be managed from the Guardian API. You would use Guardian procedures to
access OSS files when you need to perform operations that use the nowait feature of the Guardian
environment.
Nowait I/O is the ability of an application process to continue executing in parallel with read
and write operations; the application process runs concurrently with the I/O operation. The OSS
environment uses waited I/O, where an application process is suspended during read and write
operations. The process does not resume execution until the I/O operations are complete. Nowait
I/O does not work on files that have been opened with the OSS open() function.
When you use a Guardian I/O procedure in nowait mode, you set the maximum number of
concurrent I/O operations that you want to allow and then complete the I/O operations by calling
the AWAITIO[X] procedure later in your program, as shown in Example 2-9 (page 67). For
details on using nowait I/O with Guardian procedures, refer to the Guardian Programmer’s Guide.

Guardian Procedure Extensions for OSS


HP provides extensions to Guardian procedures so that you can use them with OSS files. The
extensions are summarized in Table 2-6 (page 94).
The following procedures have OSS parameters and OSS attributes:
• FILE_GETINFO_
• FILE_GETINFOBYNAME_

Accessing Files From the Guardian API 65


The following procedures have OSS attributes:
• FILE_GETINFOLIST_
• FILE_GETINFOLISTBYNAME_
• FILE_OPEN_
• FILE_OPEN_CHKPT_
• SETMODE
Some Guardian procedures fail when they reference an OSS file; these are noted in Table 2-6
(page 94).
For information on accessing OSS files larger than approximately 2 GB using Guardian APIs and
for information about compatibility issues for such files, see “Accessing OSS Files Larger Than
2 GB” (page 74). Additional considerations or restrictions on Guardian procedures used on OSS
files are summarized in Table 2-6.
Example 2-9 (page 67) shows the use of the Guardian FILE_OPEN_ and READX procedures to
read data from an OSS file in nowait mode. The AWAITIOX procedure is used to wait for I/O
completion on the read operation.

66 Managing Files
Example 2-9 Reading an OSS File in Nowait Mode With Guardian Procedures
/* Reading an OSS file in Nowait Mode with Guardian Procedures */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <tal.h>
#include <cextdecs.h(FILE_OPEN_,READX,AWAITIOX)>

_cc_status CC;
short filenum, bytesread, retcode;
char *pathname;
char buffer[1025]; /* allow for NULL character at end of buffer */
long request_tag;
int i;

int main(int argc, char *argv[]) {


/* Check for the proper number of arguments;
if no pathname is supplied, use the default name. */
if (argc > 1)
pathname = argv[1];
else
pathname = "/usr/include/stdio.h";

/* Invoke the Guardian procedure. Note the value of "options" field. */


retcode = FILE_OPEN_(pathname, /* name of OSS file */
, /* pathname length not needed */
&filenum, /* file number returned */
1, /* open for read */
, /* shared exclusion */
1, /* number of concurrent nowait I/O
operations permitted */
, /* sync or receive depth */
040, /* <10>=1 indicates OSS pathname */
);

/* If the open is unsuccessful, print a message and exit. */


if (retcode != 0) {
fprintf(stderr, "retcode = %d\n", retcode);
fprintf(stderr, "Cannot open %s\n", pathname);
exit(1);
}

/* Read the file using the Guardian READX procedure.


Note that a request tag is not required when only one
outstanding read is issued. It is shown here for
demonstration purposes only. */
request_tag = 123; /* form unique request tag */
CC = READX( filenum, /* file number */
buffer, /* buffer address */
1024, /* size of buffer */
, /* number of bytes read, not
used for nowait I/O */
request_tag /* unique request tag */
);

/* If the condition code returned is not the one for success,


print a message and exit. */
if(_status_ne(CC)) { /* check the success condition code */
printf(stderr, "Read failed\n");
exit(1);
}

Accessing Files From the Guardian API 67


/* The program can execute code while the read operation is being
completed by the system. */
for (i = 0; i < 100000; i++) ;
printf("Now issuing AWAITIOX to wait for I/O completion.\n");

/* AWAITIOX completes the READX operation. */


CC = AWAITIOX(&filenum, /* file number */
,
&bytesread, /* number of bytes read */
&request_tag, /* request tag */
);

/* If the condition code returned is not the one for success,


print a message and exit. */
if(_status_ne(CC)) { /* check the success condition code */
fprintf(stderr, "Awaitiox failed.\n");
exit(1);
}
printf("Bytes read = %d\n", bytesread);

/* Print out the first ten bytes in octal plus "string". */


printf("First 10 bytes read (in octal): ");
for (i = 0; i < 10; i++)
printf("%o ", buffer[i]);
printf("\n");
buffer[bytesread] = 0; /* make string NULL-terminated */
printf("\n%s\n", buffer);
return(0);
}

Example 2-10 shows the use of the Guardian FILE_OPEN_ and READX procedures to read data
from an OSS file whose name is provided as input to the program. This program waits for I/O
operations to terminate.

68 Managing Files
Example 2-10 Reading an OSS File With Guardian Procedures
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tal.h>
#include <cextdecs.h(FILE_OPEN_,READX)>

_cc_status CC;
short filenum, bytesread, retcode;
char *pathname;
char buffer[1025]; /* allow for NULL-terminated string */

int main(int argc, char *argv[]) {


int i;

/* If no pathname is supplied, use the default name. */


if (argc > 1)
pathname = argv[1];
else
pathname = "/usr/include/stdio.h";

/* Invoke the Guardian procedure. Note the special value of options. */


retcode = FILE_OPEN_(pathname, /* name of OSS file */
, /* length of pathname not needed */
&filenum, /* file number returned */
1, /* open for read */
, /* shared exclusion */
, /* nowait depth */
, /* sync or receive depth */
040, /* <10>=1 indicates OSS pathname */
);

/* If the open fails, print a message and exit. */


if (retcode != 0) {
fprintf(stderr, "retcode = %d\n", retcode);
fprintf(stderr, "Cannot open %s\n", pathname);
exit(1);
}

/* Read the file with the Guardian READX procedure. */


CC = READX( filenum, /* file number */
buffer, /* buffer address */
1024, /* size of buffer */
&bytesread, /* number of bytes read */
);

/* If the condition code returned is not the one for success,


print a message and exit. */
if(_status_ne(CC)) {
fprintf(stderr, "Read error, bytes read = %d\n", bytesread);
exit(1);
}
printf("Bytes read = %d\n", bytesread);

/* Print out the first ten bytes in octal plus "string". */


printf("First 10 bytes read (in octal): ");
for (i = 0; i < 10; i++)
printf("%o ", buffer[i]);
printf("\n");
buffer[bytesread] = '\000'; /* make string NULL-terminated */
printf("\n%s\n", buffer);
return(0);
}

Accessing Files From the Guardian API 69


Using Extended Guardian Procedures
Example 2-11 shows the use of the extended Guardian procedure FILE_GETINFOBYNAME_ to
get information about an OSS file whose pathname is provided as input to the program.

70 Managing Files
Example 2-11 Using a Guardian Procedure to Get OSS File Information by Name
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cextdecs.h(PATHNAME_TO_FILENAME_,FILE_GETINFOBYNAME_)>

char *pathname;
char filename[64];
short filelen;
short status;
short typeinfo[5];
short flags;

int main(int argc, char *argv[]) {


short retcode, physreclen;

/* If no pathname is supplied, get information


about the default file. */
if(argc > 1)
pathname = argv[1];
else
pathname = "/usr/include/stdio.h";

/* Get the Guardian filename equivalent first. */


retcode = PATHNAME_TO_FILENAME_(pathname, /* OSS pathname */
filename, /* Guardian filename buffer */
64, /* Size of filename buffer */
&filelen, /* length of filename */
&status); /* if == 1, Guardian file (/G)
if == 0, OSS file */

/* If the procedure is unsuccessful, print a message and exit.*/


if (retcode != 0) {
fprintf(stderr, "Bad pathname, return code = %d\n", retcode);
exit(1);
}

/* Invoke the Guardian procedure call. */


retcode = FILE_GETINFOBYNAME_(filename, /* Guardian filename */
filelen, /* filename length */
typeinfo, /* return array of file information */
&physreclen, /* returned physical record length */
, /* desired options, if any */
, /* tag or timeout value, if any */
&flags); /* new OSS flags word */
if (retcode != 0) {
fprintf(stderr,"retcode = %d\n", retcode);
fprintf(stderr,"Non-existent file or pathname in bad format\n");
exit(1);
}

/* Print the information about file, indicating whether


it is an OSS file or a Guardian file. */
if(flags&1)
printf("OSS File, ");
else
printf("Guardian File, ");
printf("Pathname = %s\n", pathname);
printf("device type = %d\n", typeinfo[0]);
printf("device subtype = %d\n", typeinfo[1]);
printf("physical record length = %d\n", physreclen);

/* If the device type is a disk file,


print the disk file information. */

Accessing Files From the Guardian API 71


if(typeinfo[0] == 3) {
printf("object type = %d\n", typeinfo[2]);
printf("file type = %d\n", typeinfo[3]);
printf("file code = %d\n", typeinfo[4]);
}
return(0);
}

Example 2-12 shows the use of the Guardian FILE_OPEN_ and FILE_GETINFO_ procedures to
get information about an OSS file. The file is opened, and the file number is passed to the
FILE_GETINFO_ procedure.

72 Managing Files
Example 2-12 Using a Guardian Procedure to Get OSS File Information by Number
/* Using a Guardian Procedure to Get OSS File info by Number*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cextdecs.h(FILE_OPEN_,FILE_GETINFO_)>

short typeinfo[5];
char filename[64];
char *pathname;

int main(int argc, char *argv[]) {


short filenum, filelen, retcode, lasterror;

/* If no pathname is supplied, open the default file. */


if(argc > 1)
pathname = argv[1];
else
pathname = "/usr/include/stdio.h";
retcode = FILE_OPEN_(pathname, /* OSS pathname */
, /* pathname length not required */
&filenum, /* returned file number */
1, /* read-only access */
, /* shared exclusion */
, /* nowait depth */
, /* sync or receive depth */
040, /* <10>=1, set to OSS pathname */
);

/* If the FILE_OPEN_ procedure is unsuccessful,


print a message and exit. */
if (retcode != 0) {
fprintf(stderr, "retcode = %d, filenum = %d\n",
retcode, filenum);
fprintf(stderr, "Cannot open %s\n", pathname);
exit(1);
}

/* Get information about the file by file number. */


retcode = FILE_GETINFO_(filenum, /* file number */
&lasterror, /* error from last operation */
filename, /* Guardian filename returned */
64, /* length of filename buffer */
&filelen, /* number of bytes in filename */
typeinfo ); /* return array of file information */

/* If the procedure is unsuccessful, print a message and exit.*/


if (retcode != 0) {
fprintf(stderr, "retcode = %d, filenum = %d\n",
retcode, filenum);
fprintf(stderr, "Non-existent file or filename in bad format\n");
exit(1);
}

/* Print the file status information. */


printf("Pathname = %s\n", pathname);
filename[filelen] = '\000'; /* make string NULL-terminated */
printf("Filename = %s\n", filename);
printf("device subtype = %d\n", typeinfo[1]);
printf("device type = %d\n", typeinfo[0]);

/* If the device type is a disk file,


print the disk file information. */

Accessing Files From the Guardian API 73


if(typeinfo[0] == 3) {
printf("object type = %d\n", typeinfo[2]);
printf("file type = %d\n", typeinfo[3]);
printf("file code = %d\n", typeinfo[4]);
}
return(0);
}

Accessing OSS Files Larger Than 2 GB


Small Files and Large Files
For RVUs earlier than H06.06 and G06.29, OSS files always had an underlying Guardian file
format of Format 1 and were limited in size to approximately 2 GB (GB). This size limitation was
a direct result of using 32-bit data types for file sizes and offsets. For J-series RVUs, H06.06 and
later RVUs, and G06.29 and later G-series RVUs, 64-bit data types and offsets can be used, and
OSS files are either small files or large files.

Characteristics of Small Files


Small files:
• Have an underlying Guardian file format of either Format 1 or Format 2. This underlying
file format is normally not visible to customer applications.
• Have a size limit of approximately 2 GB when opened or created using a 32-bit API. For
information about the exact size limits, see the Open System Services Management and Operations
Guide.
• Can be accessed using the existing 32-bit application programmatic interfaces (APIs) such
as creat( ) and open() in addition to the 64-bit APIs such as creat64() and open64().
If the file is accessed using a 64-bit API:
— The file is automatically converted to use an underlying Guardian file format of Format 2.
— The file no longer has a size limit of approximately 2 GB. It can grow to the size limit
for large files.
• Can be moved, copied, or restored to systems running RVUs that do not support OSS large
files. In such cases, if the file has an underlying Guardian file format of Format 2 but a size
of less than approximately 2 GB:
— The file is automatically converted to use an underlying Guardian format of Format 1.
— The file becomes subject to the file size limit of approximately 2 GB.

Characteristics of Large Files


Large files:
• Are larger than approximately 2 GB.
• Have a size limit of approximately 1 terabyte, constrained by the space available on the disk
volume. For information about the exact size limits, see the Open System Services Management
and Operations Guide.

NOTE: For J-series RVUs, H06.06 and later H-series RVUs, and G06.29 and later G-series
RVUs, a pax archive file is limited to 8 GB.

• Have an underlying Guardian file format of Format 2. This underlying file format is normally
not visible to customer applications when OSS APIs are used, but might affect program
execution when Guardian APIs are used. For more information, see “Compatibility Issue
For Guardian Files Created by OSS APIs” (page 78)

74 Managing Files
• Can be accessed using 64-bit APIs such as creat64() and open64() only:
— An application can explicitly call the 64-bit version of a function when you use the
#define _LARGEFILE64_SOURCE 1 feature test macro or an equivalent compiler
command option to compile the application.
— An application call to interface() is automatically mapped to the interface64()
function when you use the #define _FILE_OFFSET_BITS 64 feature test macro or
an equivalent compiler command option to compile the application
• Cannot be restored to systems running RVUs that do not support OSS files larger than
approximately 2 GB.
• If OSS APIs are used, large files cannot be accessed from systems running RVUs that do not
support OSS files larger than approximately 2 GB. However, Guardian Enscribe APIs with
64-bit elections can access these files.

Large File Safe (LFS) Applications and Large File Aware (LFA) Appications
An application that is large OSS file safe (LFS) causes no data loss or corruption when it encounters
an OSS file larger than approximately 2 GB. It can not process OSS files larger than approximately
2 GB, but it has the appropriate logic to handle errors or warnings detected during file
manipulation operations and fail gracefully.
An application that is large OSS file aware (LFA) can process OSS files larger than approximately
2 GB with the same functionality as processing OSS files smaller than approximately 2 GB. Such
an application can handle large files as input and generate large files as output. Applications
that are large file aware can also process small files.

Large File Safe APIs


For J-series RVUs, H06.06 and later H-series RVUs, and G06.29 and later G-series RVUS, existing
I/O APIs are modified to fail safely on OSS files larger than approximately 2 GB. These APIs
return an error (EOVERFLOW or EFBIG) when an action cannot be performed on OSS files larger
than approximately 2 GB or an attribute cannot be represented for such a file.
The existing 32-bit I/O APIs modified to be large file safe include:
creat()
open()
ftruncate()
lseek()
fstat()
lstat()
stat()
fstatvfs()
statvfs()
ftw()
nftw()
Other existing I/O APIs modified to be large file safe include:
read()
readv()
write()
writev()
readdir()
fcntl()
The existing Native C runtime library APIs modified to be large file safe are:
fclose()
fflush()
fgetc()

Accessing OSS Files Larger Than 2 GB 75


fgetpos()
fgets()
fgetwc()
fgetws()
fopen_oss()
fprintf()
fputc()
fputs()
fputwc()
fputws()
fread()
freopen_oss()
fwrite()
fscanf()
fseek()
fsetpos()
ftell()
getc()
getchar()
gets()
getw()
getwc()
getws()
getwchar()
printf()
putc()
putchar()
puts()
putw()
putws()
putwchar()
scanf()
vfprintf()
vprintf()
In addition, HP supports two new 32-bit LFS APIs, fseeko() and ftello(), because fseek()
and ftell() use data types that cannot be extended to support large files.
Functions added in J-series RVUs or in RVUs later than H06.06 or G06.29 are either large file
aware or large file safe.

Large File Aware APIs


For J-series RVUs, H06.06 and later H-series RVUs, and G06.29 and later G-series RVUs, new
64-bit APIs are available. These large file aware APIs support both small files and large files.
Typically, the 64-bit APIs include the number 64 in the name of the API.
An application can explicitly call a 64-bit function when you use the
#define _LARGEFILE64_SOURCE 1 feature test macro or an equivalent compiler command
option to compile the application.
An application call to interface() is automatically mapped to the interface64() function
when you use the #define _FILE_OFFSET_BITS 64 feature test macro or an equivalent
compiler command option to compile the application.

76 Managing Files
If a small file is accessed using a 64-bit API:
• The file is automatically converted to use an underlying Guardian file format of Format 2.
• The file no longer has a size limit of approximately 2 GB. It can grow to the size limit for
large files.
The LFA OSS APIs are:
creat64()
open64()
ftruncate64()
lseek64()
fcntl()
fstat64()
lstat64()
stat64()
fstatvfs64()
statvfs64()
readdir64()
ftw64()
nftw64()
glob()
The LFA native C runtime library APIs are:
__ns_backup_fopen64()
__ns_fopen64_special()
fgetpos64()
fopen64()
fopen64_guardian()
fopen64_oss()
fopen64_std_file()
freopen64()
freopen64_guardian()
freopen64_oss()
fseeko64()
fsetpos64()
ftello64()
scandir64()
tmpfile64()
tmpfile64_guardian()
tmpfile64_oss()
The Native C++ runtime libraries do not have new 64-bit specific APIs in the C++ library products.
However, the logic implementing IOStream classes is enhanced to be large OSS file safe for
programs built with the regular compilation environment or large OSS file aware for programs
built with the large file compilation environment (that is, macro _FILE_OFFSET_BITS is defined
to have value 64.).

Interoperability
Opening OSS Files
Applications running on systems that do not include support for OSS large files can use either
OSS or Enscribe APIs to open any OSS file smaller than approximately 2 GB, even if that file is
on a system that includes support for OSS large files.
HP does not support OSS opens of OSS files larger than approximately 2 GB on systems that do
not include support for OSS large files. However, because Enscribe has long understood Guardian
Format 2 files, a program running on a system that does not support large files can use Enscribe

Accessing OSS Files Larger Than 2 GB 77


with 64-bit elections to open an OSS file that resides on a system that supports large files. If the
file is smaller than approximately 2 GB, the file size limit for that open is approximately 2 GB.
If the file is larger than approximately 2 GB, the file size limit for that open is the size of the
volume. The actual size limits depend on the API used and how the file was created. For detailed
information about size limits when opening files, see the Open System Services Management and
Operations Guide.

Opening Guardian C Files


For J-series RVUs, H06.06 and later H-series RVUs, and G06.29 and later G-series RVUs, OSS
can use the creat64() and open64() functions to create Guardian files in the /G name space.
The resulting files, regardless of size, are Guardian Format 2 files with file code 180. If a program
running on any RVU attempts to open this type of file using FILE_OPEN_ without 64-bit elections,
the open succeeds if the file is smaller than approximately 4 GB and fails if the file is larger than
4 GB.
If the open call includes 64-bit elections and is issued on J-series RVUs, H06.06 or later H-series
RVUs, or G06.29 or a later G-series RVUs, the open succeeds regardless of file size.
If an application running on an RVU earlier than G06.29 or H06.06 invokes FILE_OPEN_ with
64-bit elections, the open succeeds. However, if the file size is smaller than 4 GB, the file size
limit for that open is 4 GB. If the file size is larger than 4 GB, the file size limit for that open is
the limit defined at file-creation time.
For detailed information about size limits when opening files, see the Open System Services
Management and Operations Guide.

Compatibility Issue For Guardian Files Created by OSS APIs


For RVUs before G06.29 and H06.06, OSS files always had an underlying Guardian file format
of Format 1. For J-series RVUs, H06.06 and later H-series RVUs, and G06.29 and later G-series
RVUs, OSS files can have an underlying Guardian file format of Format 1 or Format 2. For
applications using OSS APIs to access OSS files, the underlying Guardian file format is not visible
and there are no known compatibility issues. For applications using Enscribe APIs to access
Guardian files created by OSS APIs, there is a known compatibility issue.
Before to the G06.29 and H06.06 RVUs, Guardian files created by OSS APIs were always Format 1
with a maximum size of 175 megabytes. For J-series RVUs, H06.06 and later H-series RVUs, and
G06.29 and later G-series RVUs, Guardian files created by the open() and creat() APIs are
Guardian Format 1 with a maximum size of approximately 2 GB, and Guardian files created by
the open64() and creat64() APIs are Guardian Format 2 with a maximum size of
approximately 26 GB.
The standard OSS utilities, such as cp, pax and pinstall, now use the open64() and
creat64() functions and create a Guardian Format 2 file when given a /G output file name.
For example:
cp myfile /G/disk/subvol/myfile
Guardian applications that use file attributes such as file format and maximum size might fail
when unexpected values are returned (such as Format 2 if only Format 1 is expected).
Guardian applications that use file data and ignore file attributes are unaffected if all of these
conditions are true:
• The application is running on J-series RVUs, H06.06 or later H-series RVUs, or G06.29 or
later G-series RVUs.
• The Format 2 file is unstructured, code 180 with an EOF less than the Format 1 limit of
approximately 4 GB.

78 Managing Files
However, FILE_OPEN_ fails with error 580 if any of these conditions are true:
• The RVU is earlier than G06.29 or H06.06
• The file code is not 180
• The EOF is greater than the Format 1 limit
Recovery choices include:
• Change the application to accept Guardian Format 2 files.
• Protect the application by converting the file to Guardian Format 1 using the following steps:
>FUP CREATE TEMP, FORMAT 1, TYPE U, ODDUNSTR, CODE 180, &
EXT (28,1400), MAXTENTS 749

>FUP COPY myfile,TEMP

>FUP PURGE myfile

>FUP RENAME TEMP,myfile


• Protect the application by creating the file as a Guardian Format 1 file and then appending
data to the file. For example, replace the command:
cp myfile /G/disk/subvol/myfile
With the commands:
gtacl -c 'FUP CREATE $disk.subvol.myfile, FORMAT 1, TYPE U, ODDUNSTR, CODE 180, EXT (28,1400), MAXTENTS
749

cat myfile >> /G/disk/subvol/myfile

Common Completion
Common Completion is an enhancement to the Enscribe file system and the Open System Services
file system that allows completion of a Guardian file or returns ready information for OSS (socket,
OSSTTY, and disk) files for read, write, or exception descriptors. Common Completion is a
combination of an enhanced version of the AWAITIO[X] procedure (for Guardian files) and the
equivalent of the select() function (for OSS files).
For OSS files, select() is used to obtain ready information for OSS socket, OSSTTY, and disk
descriptors. Completion for an OSS file means checking for readiness: that is, either data can be
sent or received, or an exception has occurred.
The select() function checks the status of objects identified by bit masks called file descriptor
sets. Each file descriptor set consists of an array of bits whose relative position and value represent
file descriptors and the status of their corresponding objects. An object is an open file descriptor
for an OSSTTY, a socket, an OSS regular file, a pipe, or a FIFO. There is a file descriptor set for
reading, for writing, and for pending exceptions. OSS and Guardian processes can communicate
within the same processor and between processors and between nodes using FIFOs. However,
they cannot communicate using pipes. Pipes are used to communicate between processes and
their processes

NOTE: Although an OSS socket descriptor is ready, a subsequent I/O operation might not finish
successfully because sockets can be shared by multiple processes. If process A receives notice
that the descriptor is ready for I/O, process B might alter that status before process A can perform
an I/O operation on it.
For Guardian files, AWAITIO[X] is used to complete nowaited Guardian I/O operation.
Completion for Guardian files implies that an I/O operation was initiated in a previous call to a
read or write operation. This I/O operation is completed in AWAITIO[X] and data is returned
to the application.
See the Open System Services System Calls Reference Manual and the Guardian Procedure Calls
Reference Manual for more information.

Common Completion 79
Example 2-13 (page 80) demonstrates the use of select() on FIFOs.

Example 2-13 Using select() on FIFOs


#include <sys/types.h>
#ifndef _XOPEN_SOURCE_EXTENDED
#include <sys/file.h>
#endif
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>

char *fifo[3] = { /* up to 3 named pipes */


"fifo-1",
"fifo-2",
"fifo-3"
};
char *ofile[3] = { /* up to 3 output files */
"ofile-1",
"ofile-2",
"ofile-3"
};

fd_set m_rfds; /* master set of fd_set values */


fd_set s_rfds; /* fd_set values used by select */
int maxfdp1; /* Max. file descriptor number plus 1 */
int rd[3]; /* read/write file descriptors */
int fd[3]; /* fifo file descriptors */
int nrd[3]; /* number of bytes read */
int nread; /* number of bytes read in one read */
int totread; /* running subtotal number of bytes read */
int sumread; /* total number of bytes read */
char buf[3][512]; /* data buffers */

main(int argc, char ** argv)


{
int i; /* counter */
int cnt; /* open fifo counter */
int nfifo; /* number of named pipes created */
int p; /* child process number */
nfifo = argc - 1;
if(nfifo < 1 || nfifo > 3) {
fprintf(stderr, "Specify the names of 1 to 3 files to read.\n");
exit(EXIT_FAILURE);
}
for(i = 0; i < nfifo; i++) { /* create named pipes */
unlink(fifo[i]);
if(mkfifo(fifo[i], 0644) < 0) { /* read/write permissions */
fprintf(stderr, "Can't create fifo %s\n", fifo[i]);
exit(EXIT_FAILURE);
}
}
/* Create child process to read files whose names are passed as arguments
to the program, and write the contents to the named pipes (fifos).*/

if((p = fork()) < 0) {


fprintf(stderr, "Can't create new child process.\n");
exit(EXIT_FAILURE);
} else if(p) { /* Execute code for child process */
printf("Parent process started.\n");
for(i = 0; i < nfifo; i++) /* open fifos for write */
if((fd[i] = open(fifo[i], O_WRONLY)) < 0) {
fprintf(stderr, "Can't open %s\n", fifo[i]);
exit(EXIT_FAILURE);
}
for(i = 0; i < nfifo; i++) /* open files for read */
if((rd[i] = open(argv[i+1], O_RDONLY)) < 0) {

80 Managing Files
fprintf(stderr, "Can't open %s\n", argv[i+1]);
exit(EXIT_FAILURE);
}
sumread = 0;
do {
totread = 0;
for(i = 0; i < nfifo; i++) {
if(nrd[i] < 0) /* don't read if end-of-file */
continue;
if((nrd[i] = read(rd[i], buf[i], 512)) > 0) {
write(fd[i], buf[i], nrd[i]);
totread += nrd[i];
} else
nrd[i] = -1; /* set end-of-file marker */
}
sumread += totread;
} while(totread);
printf("Total bytes read from files = %d\n", sumread);
return(EXIT_SUCCESS); /* write of all fifos done */
}
/* Execute parent program to read the named pipes
using the select() function and non-blocking I/O
*/
printf("Parent process code started.\n");
maxfdp1 = 3; /* Set highest descriptor number */
FD_ZERO(&m_rfds);
for(i = 0; i < nfifo; i++) /* create output files */
if((rd[i] = open(ofile[i], O_WRONLY | O_CREAT, 0644)) < 0) {
fprintf(stderr, "Can't create %s\n", ofile[i]);
exit(EXIT_FAILURE);
}
for(i = 0; i < nfifo; i++) {
if((fd[i] = open(fifo[i], O_RDONLY)) < 0) {
fprintf(stderr, "Can't open fifo %s.\n", fifo[i]);
exit(EXIT_FAILURE);
}
if(fcntl(fd[i], F_SETFL, O_NONBLOCK) < 0) {
fprintf(stderr, "fcntl() error.\n");
exit(EXIT_FAILURE) ;
}
if(fd[i] > maxfdp1)
maxfdp1 = fd[i];
FD_SET(fd[i], &m_frds);
}
maxfdp1++; /* one more than max. file descriptor number */
sumread = 0; /* initialize number of bytes read */
cnt = nfifo; /* number of fifos still open */
while(cnt) {
printf("select starting\n");
s_rfds = m_rfds;
if(select(maxfdp1, &s_rfds, NULL, NULL, NULL) <= 0) {
fprintf(stderr, "select() error %d.\n", errno);
exit(EXIT_FAILURE) ;
}
for(i = 0; i < nfifo; i++) {
nread = 0;
if(FD_ISSET(fd[i], &s_rfds)) {
if((nread = read( fd[i], buf[i], 512)) < 0) {
fprintf(stderr, "read fifo error %d\n", errno);
exit(EXIT_FAILURE);
}
if(nread > 0) { /* some data read */
write(rd[i], buf[i], nread);
sumread += nread;
} else { /* end of file */
FD_CLR(fd[i], &m_rfds ); /* stop reading from this file */
close(fd[i]);
--cnt; /* number of fifos still open */
}
}
} /* end of for loop */
} /* end of while loop */

Common Completion 81
printf("Total bytes read from fifo(s) = %d\n", sumread);
return(EXIT_SUCCESS);
} /* end of main */

Performance Considerations
The following actions improve performance when you use OSS file system functions:

NOTE: Some of these actions affect the configuration of the fileset or of the disk volume and
are not controlled by the application.
• Minimize the number of open operations such as open() and opendir().
• Minimize the use of pipes and FIFOs between processors.
• Minimize the use of AF_UNIX sockets between processes.
• Minimize the use of shared opens (more than one process sharing an open file descriptor)
between processors.
• Minimize the use of operations that alter directory contents, such as creat(), link(),
unlink(), and rename().
• Use file caching, if appropriate (see “File Caching”).
• Use free-space table caching. For more information, see the SCF Reference Manual for the
Storage Subsystem.
• Use O_SYNC when reliability, not performance, is most important.

NOTE: HP recommends that the S_NONSTOP extension not be used in new applications. The
S_NONSTOP extension is ignored on nodes running J-series RVUs or an RVU more recent than
G06.26 or H06.03; the standard O_SYNC feature used with the FTIOMODE attribute provides
better data integrity and improved performance.
• Increase the size of the disk cache, if appropriate. If disk cache is too small, disk processes
might perform unnecessary physical disk I/Os. If disk cache is too large, it can induce
unnecessary memory swap operations and cache faults. (Swaps are also disk I/Os and
therefore time consuming.) Typically, the default values for disk cache is small, so
performance can be slow. There are a number of factors involved in determining the best
disk cache size for your system. For more information, see the SCF Reference Manual for the
Storage Subsystem and the Measure User’s Guide.

File Caching
By default, the OSS environment provides a file cache for regular files in each processor that
does input or output with a disk volume that contains OSS files. HP strongly recommends that
you leave OSS file caching enabled. This cache is necessary for the fault tolerant behavior
controlled by the fileset FTIOMODE or NORMALIOMODE attributes.
If file caching is enabled, the OSS file system determines whether a file should be cached.
If OSS file caching is in effect, the OSS file system reads large blocks of data into its own processor
cache buffer and then resolves user application read requests from that cache buffer. If OSS file
caching is not in effect, the OSS file system does not perform any local caching of data and all
requests are passed to the disk process.
If the OSS file system determines that a file should be cached and all opens of the file are for read
access, then the file is cached on all processors that have opens of the file. The opens must be for
read access only.
The caching state of a file is dynamic and can change as opens, closes, and other events occur on
a file.

82 Managing Files
You should decide whether to use OSS file caching when you first configure a fileset, because
changing the use of OSS file caching requires you to stop the fileset.
Although the storage subsystem can be used to enable or disable file caching for a volume, HP
recommends that you not modify OSS file caching at the disk level. The FTIOMODE and
NORMALIOMODE fileset attributes provide better control over fault-tolerance and performance
for file input or output.

FTIOMODE, NORMALIOMODE, Performance, and Fault Tolerance


The value used for the FTIOMODE and NORMALIOMODE options affect application performance
and fault tolerance. Fault tolerance for files opened without using the O_SYNC bit is controlled
by the NORMALIOMODE option setting; fault tolerance for files opened using the O_SYNC bit
is controlled by the FTIOMODE option setting.

NOTE: HP recommends that the S_NONSTOP extension not be used in new applications. The
S_NONSTOP extension is ignored on nodes running J-series RVUs or an RVU more recent than
G06.26 or H06.03; the standard O_SYNC feature used with the FTIOMODE attribute provides
better data integrity and improved performance.
The attribute settings for NORMALIOMODE are, from highest to lowest fault tolerance and
from lowest to highest performance:
UNBUFFEREDCP
DP2BUFFEREDCP
OSSBUFFEREDCP
DP2BUFFERED (Same as legacy OSS file caching turned off [OSSCACHING OFF])
OSSBUFFERED (Same as legacy OSS file caching turned on [OSSCACHING ON])
If NORMALIOMODE is not specified, the default behavior is OSSBUFFEREDCP.
The FTIOMODE settings are a subset of the NORMALIOMODE settings. The setting used for
the FTIOMODE attribute of a specific fileset must have a fault-tolerance level at least as high as
that of the NORMALIOMODE attribute setting for the fileset. The attribute settings for FTIOMODE
are, from highest to lowest fault tolerance and from lowest to highest performance:
UNBUFFEREDCP
DP2BUFFEREDCP
OSSBUFFEREDCP
If FTIOMODE is not specified, the default behavior is UNBUFFEREDCP.
File caching and buffering affect the data integrity of a file and file transfer speed as described
in Table 2-4.
Table 2-4 I/O Buffering, Fault Tolerance, and Performance
NORMALIOMODE or Behavior Fault Tolerance and Performance
FTIOMODE Attribute Value

UNBUFFEREDCP Uses unbuffered input/output with Provides maximum fault tolerance but
checkpointing. with reduced performance.

DP2BUFFEREDCP Uses disk-process-buffered input/output Provides fault tolerance for single failures,
with checkpointing. with better performance than
DP2 buffers file data and checkpoints the UNBUFFEREDCP.
file state to its backup process to ensure
recovery from single failures.

Performance Considerations 83
Table 2-4 I/O Buffering, Fault Tolerance, and Performance (continued)
NORMALIOMODE or Behavior Fault Tolerance and Performance
FTIOMODE Attribute Value

OSSBUFFEREDCP Uses OSS-buffered input/output with Provides fault tolerance for single failures,
checkpointing. with better performance than
OSS filesystem processes and DP2 share DP2BUFFEREDCP.
responsibility for buffering file data; OSS
provides the buffering whenever possible.
DP2 buffers file data and checkpoints the
file state to its backup process to ensure
recovery from single failures.

DP2BUFFERED Uses disk-process-buffered input/output Provides no fault tolerance, but better


without checkpointing. performance than DPBUFFEREDCP.

OSSBUFFERED Uses OSS-buffered input/output without Provides no fault tolerance, but better
checkpointing. performance than OSSBUFFEREDCP.

Performance and Reliability Tradeoffs


As Table 2-4 shows, you must choose between performance and reliability in OSS file I/O. The
higher the reliability, the slower the performance.
For example, if you cannot afford to lose any file I/O operations, you should set the FTIOMODE
and NORMALIOMODE attribute to UNBUFFEREDCP. If you have set this attribute and the
primary processor fails, the disk process in the backup processor gets the information it needs
to pick up where the disk process in the primary processor left off. This information includes
any file locks and the read/write position in the file. Using UNBUFFEREDCP means that you do
not lose any file I/O operations.
If DP2BUFFERED or OSSBUFFERED is used for NORMALIOMODE, the file is opened without
using the O_SYNC bit, and there is a processor failure:
• A checkpoint does not occur between the disk process in the failed processor and the disk
process in the backup processor.
• The file descriptor becomes invalid, which means you lose the read/write position in the
file. This happens whether file caching is on or off.
You can reset the read/write position in the file by closing the file with the invalid file descriptor,
reopening it, and resuming I/O operations. However, if file caching was off, you lose the file
operation in process when the processor failed. If file caching was on, you lose all file operations
in the cache when the processor failed.
OSS I/O performance is affected by the following:
• Whether free-space table caching is enabled or disabled for the disk process
• Whether OSS file caching is enabled or disabled
• Using the fast-create option when creating a fileset
• Having a volume list for filesets in the superblock
• Setting the trackall flag in the /etc/profile file to create tracked aliases
• Leaving too many unused processes running
See the Open System Services Shell and Utilities Reference Manual, Open System Services Installation
Guide, and Open System Services Management and Operations Guide for more information.

OSS File-System Functions


Table 2-5 (page 85) displays information about each OSS function that you can use to manage
files. The columns of the table contain the following:

84 Managing Files
OSS Function
The name of the function and a brief description.
OSS Notes
Notes about the OSS implementation of the function. The note “Can return extended errors”
means that the function can return errors that are HP extensions to the XPG4 specification.
Refer to the function’s reference page for further information.
Guardian Notes
Notes about using the function when it is called from a Guardian process.
The note “FDM set” (for file, directory, and memory) means that the function is one of a set
of functions that have the following effects when the first of them is called from the Guardian
environment:
• Two Guardian file-system numbers (not necessarily the next two available) are allocated
for the root directory and the current working directory. These file numbers cannot be
closed by calling the Guardian FILE_CLOSE_ procedure.
• The current working directory is assigned from the VOLUME attribute of the Guardian
environment =_DEFAULTS DEFINE.
• The use of static memory by the process increases slightly.
• The functions in the FDM set are access(), chdir(), chmod(), chown(), chroot(),
creat(), creat64()fchmod(), fchown(), fstatvfs(), fstatvfs64(), ftok(),
ftw(), ftw64(), getcwd(), glob(), lchmod(), lchown(), link(), lstat(),
lstat64(), mkdir(), mkfifo(), mknod(), nftw(), nftw64(),open(),
open64(),opendir(), pathconf(), pipe(), readlink(), rename(),
rename_oss(), rmdir(), select(), socket(), socketpair(), stat(),
stat64(), statvfs(),statvfs64(), symlink(), unlink(), and utime().
The information in this table is only a summary of the information in the reference page for a
function. For details, refer to the reference pages either online or in the Open System Services
System Calls Reference Manual and the Open System Services Library Calls Reference Manual.

NOTE: To determine which RVUs support an OSS function, see Appendix A (page 389).
Table 2-5 OSS File-System Functions
OSS Function OSS Notes Guardian Notes

access() Can return extended errors. FDM set.


Determines the accessibility of a file. Not all the Guardian information can
be summarized here; for example,
there are several security restrictions.
For Guardian information, refer to the
reference pages.

chdir() Can return extended errors. FDM set.


Changes the current working Can return Guardian file-system error You can’t use chdir() on Guardian
directory. numbers in errno. process names or subvolumes with a
reserved name.

OSS File-System Functions 85


Table 2-5 OSS File-System Functions (continued)
OSS Function OSS Notes Guardian Notes

chmod() Process must have either the same


fchmod() effective user ID as the owner of the
lchmod() file or the super ID.
Changes file-access permissions. Call to chmod() has no effect on
descriptor of open file, but new
openers of the file are authenticated
with the new permissions specified
in the call.
The fchmod() function is like the
chmod()function except that it
operates on a file descriptor instead
of a pathname.
The lchmod() function is similar to
the chmod() function except when
the final component of the path
parameter refers to a symbolic link,
the lchmod()function changes access
permissions for the symbolic link
instead of the file to which it refers.
The mode parameter uses symbols.
Refer to the reference page.
Can return extended errors.
Can return Guardian file-system error
numbers in errno.

chown() The fchown() function is like the FDM set.Can be used only on files in
fchown() chown()function except that it the /G fileset.
lchown() operates on a file descriptor instead The _POSIX_CHOWN_
Changes the owner and group IDs of of a pathname. RESTRICTEDconstant is ignored for
a file. The lchown() function is similar to files in /G.
the chown() function except when For details on disk file security, refer
the final component of the path to the reference pages.
parameter refers to a symbolic link,
the lchown()function changes access
permissions for the symbolic link
instead of the file to which it refers.
Can return extended errors.
Can return Guardian file-system error
numbers in errno.

chroot() Can return extended errors. FDM set.


Changes the effective root directory. When called with a path parameter
that points to a Guardian subvolume
with a reserved name, it fails.

close() Does not return EINTR.


Closes the file associated with a file Can return extended errors.
descriptor.
Can return Guardian file-system error
numbers in errno.

86 Managing Files
Table 2-5 OSS File-System Functions (continued)
OSS Function OSS Notes Guardian Notes

closedir() Can return extended errors. If the dir_pointer parameter does


Closes a directory stream. Refer to If the dir_pointer parameter does not refer to a currently opened
opendir(). not refer to a currently opened directory stream when it is passed to
directory stream when it is passed to the closedir() function, the
the closedir() function, the following can occur:
following can occur: • The caller might cause a trap
condition.
• The caller might receive a
SIGSEGV or SIGILL signal. • User memory might be corrupted.
• User memory might be corrupted.

confstr()
Determines the current value of a
specified system variable defined by
a string value.

creat() Can return Guardian file-system error FDM set.


creat64() numbers in errno. Refer to open().
Creates a file. Refer to open(). creat64() can access both small
files and large files.

ctermid() If the parameter is a null pointer, the For Guardian processes, it returns a
Generates the pathname for a string is stored in an internal static null pointer and errno is set to
controlling terminal. area and the address is returned. The ENOTOSS.
next call to this function with a null
pointer overwrites the contents of the
internal static area.
Can return extended errors.

dup() Can return extended errors.


Duplicates an open file descriptor. Can return Guardian file-system error
numbers in errno.

dup2() Does not return EINTR.


Duplicates and controls an open file Can return extended errors.Can
descriptor. return Guardian file-system error
numbers in errno.

fclose() Can return extended errors.


Closes a stream. Can return ENXIO, whose value is an
optional extension defined in the
XPG4 specification but is not defined
in the POSIX standards.

fcntl() Does not return EDEADLK. Access to the file through a Guardian
Controls open file descriptors. Advisory record locking is supported procedure call cannot be blocked by
only for regular files; attempts on an OSS lock.
other files give EINVAL. Guardian use of OSS sockets is not
l_len parameter can be negative. supported.

Can return extended errors.


Can return Guardian file-system error
numbers in errno.

fopen() Can return Guardian file-system error


fopen64() numbers in errno.
Opens a file and associates a stream fopen64() can access both small
with it. files and large files

OSS File-System Functions 87


Table 2-5 OSS File-System Functions (continued)
OSS Function OSS Notes Guardian Notes

fopen_guardian() Can return Guardian file-system error Distinguishes between text and binary
fopen64_guardian() numbers in errno. files.
Opens a stream (Guardian fopen() fopen64_guardian() can access Explicit calls are made only when the
function). both small files and large files. unique behavior is desired. Otherwise
use fopen().

fopen_oss() Does not distinguish between text


fopen64_oss() and binary files.
Opens a stream (OSS fopen() Explicit calls are made only when the
function). unique behavior is desired. Otherwise
use fopen().
Can return Guardian file-system error
numbers in errno.
fopen64_oss() can access both
small files and large files.

fpathconf() Can return extended errors. FDM set.


Refer to pathconf(). A call to pathconf() for a regular file
or terminal character file in /G
succeeds for any of the following
constants:
_PC_CHOWN_RESTRICTED
_PC_LINK_MAX
_PC_NAME_MAX
_PC_PATH_MAX
_PC_PIPE_BUF
If the file named by the path
parameter is an empty Guardian
subvolume, errno is not set to
ENOENT.

fread() Can return Guardian file-system error


Performs input operations. numbers in errno.

fstat() Can return extended errors.


fstat64() Can return Guardian file-system error
Refer to stat(). numbers in errno.
fstat64() can access both small
files and large files.

fstatvfs() Can return extended errors. FDM set.


fstatvfs64() Can return Guardian file-system error
Gets fileset information for an open numbers in errno.
file.
fstatvfs64() can access both small
files and large files.

fsync() Can return extended errors. Time values are not saved for file types
Writes modified data and file Can return Guardian file-system error other than regular files in /G.
attributes to permanent storage. numbers in errno.

ftruncate() Can return extended errors.


ftruncate64() Can return Guardian file-system error
Changes file length. numbers in errno.
ftruncate64() can access both
small files and large files.

88 Managing Files
Table 2-5 OSS File-System Functions (continued)
OSS Function OSS Notes Guardian Notes

ftw() Does not return EINVAL. FDM set.All files in /G that are visible
ftw64() Can return extended errors. to opendir() can be traversed.
Traverses a file tree.
Recursive access from / can cause
unexpected results.
ftw64() can access both small files
and large files.

fwrite() Can return Guardian file-system error


Writes to an output stream. numbers in errno.

getcwd() If buffer is a null pointer, FDM set.


Gets the pathname of the current getcwd() uses malloc() to allocate When a Guardian process makes its
directory. a buffer. In that case, the caller first OSS call with a pathname, the
releases the buffer with free(). process’s current working directory
Can return extended errors. becomes the /G version of the default
subvolume as contained in the VOLUME
attribute of the Guardian =_DEFAULTS
DEFINE. Changes to the =_DEFAULTS
DEFINE after this point do not affect
the current working directory, and
changes to the current working
directory of the process do not affect
the =_DEFAULTS DEFINE.

globfree() Can be called only by native


Frees all memory associated with a processes.
previous call to pglob().

ioctl() Can return extended errors. A Guardian process cannot receive the
Controls device files. Can return Guardian file-system error SIGWINCH signal.
numbers in errno. The fildes parameter can specify a
terminal file in /G.

link() Linked pathnames must reside on the FDM set.


Creates an additional directory entry same fileset. Cannot create a link to a Guardian file.
for an existing file on the current file Not supported for directories.
system.
Can return extended errors.

lseek() If called for nonseekable device,


lseek64() errno is set to EINVAL, except for
Sets the file offset for read or write pipes and FIFOs, in which case
operations. errno is set to EISPIPE.
Can return extended errors.
Can return Guardian file-system error
numbers in errno.
lseek64() can access both small
files and large files.

OSS File-System Functions 89


Table 2-5 OSS File-System Functions (continued)
OSS Function OSS Notes Guardian Notes

lstat() For files other than regular disk files, FDM set.
lstat64() st_size is set to 0 (zero), and for There are security and permission
Provides information about a directories, to 4096. mapping considerations. Refer to the
symbolic link or any file. The following bits are ORed into the reference page for detailed information
st_mode field of the stat structure: about using stat() on Guardian files.
S_IRWXU
S_IRWXG
S_IRWXO
S_IFMT
S_ISVTX
S_NONSTOP
S_ISGID
S_ISUID
Can return extended errors.
lstat64() can access both small
files and large files.

mkdir() Can’t create /lost+found or /dev Succeeds only when creating an empty
Creates a directory. in the root directory of a fileset or subvolume exactly three directories
/dev/tty or /dev/null. under root (/G/vol/subvol).
If there are bits in the mode The resulting directory is owned by
parameter other than permission bits the super ID, and all permission bits
S_ISVTX and S_IFDIR, errno is set are set (rwxrwxrwx).
to EINVAL, or the bits are undefined. The group ID is set to 255.
The group ID of the new directory is
set to the group ID of the parent
directory if S_ISGID is set there,
otherwise, the group ID is set to the
effective group ID of the caller.
Can return extended errors.

mknod() The file type S_IFBLK is not a valid FDM set.


Creates a file or assigns a pathname file type.
to a character special file. The file attribute S_NONSTOP is
supported.
Can return extended errors.

mkstemp() Can be called by native processes. Can be called by native processes.


Makes a unique filename.

nftw() Can return extended errors. FDM set.


nftw64() Recursive access from / can cause Guardian files that are visible to the
Traverses a file tree. unexpected results. opendir() function can be traversed.
Can return Guardian file-system error Security controls on Guardian object
numbers in errno. do not affect the outcome of a call to
nftw().
nftw64() can access both small files
and large files.

open() Many flags are implementation FDM set.


open64() defined. There is too much Guardian
Opens a file for reading or writing or Can return extended errors. information to summarize here. For
creates a file in the OSS environment. Guardian information, refer to the
Can return Guardian file-system error
numbers in errno. reference pages and to “Accessing OSS
Files Larger Than 2 GB” (page 74).
open64() can access both small files
and large files.

90 Managing Files
Table 2-5 OSS File-System Functions (continued)
OSS Function OSS Notes Guardian Notes

opendir() Can return extended errors. FDM set.


Performs operations on directories. There is too much OSS information There is too much Guardian
about the HP implementation of this information about using this call on
function to summarize here. For OSS /G and its contents to summarize here.
information, refer to the reference For detailed Guardian information,
pages. refer to the reference pages.

pathconf() Can return extended errors. FDM set.


Retrieves file implementation A call to pathconf() for a regular file
characteristics. or terminal character file in /G
succeeds for any of the following
constants:
_PC_CHOWN_RESTRICTED
_PC_LINK_MAX
_PC_NAME_MAX
_PC_PATH_MAX
_PC_PIPE_BUF
If the file named by the path
parameter is an empty Guardian
subvolume, errno is not set to
ENOENT.

pipe() Can return Guardian file-system error


Creates an numbers in errno.
interprocess-communication channel.

read() The value of the file pointer returned


Reads from a file. for a device that is incapable of
seeking is always 0.
The return of EOF from a device
special file has no effect on
subsequent read() calls.
If nbytes > SSIZE_MAX, -1 is
returned and errno is set to EINVAL.
Can return extended errors.
Can return Guardian file-system error
numbers in errno.

readdir() Can return extended errors.


readdir64() If, after a call to fork() or
Refer to opendir(). tdm_fork(), both the parent and
the child processes make calls to
readdir() to access the same OSS
directory, the results of the calls are
undefined.
readdir64() can access both small
files and large files.

readlink() Can return extended errors. FDM set.


Reads the value of a symbolic link. This function cannot be used on an
object in /G because symbolic links
cannot be created in /G.

readv() Can return extended errors.


Reads from a file into scattered Can return Guardian file-system error
buffers. numbers in errno.

OSS File-System Functions 91


Table 2-5 OSS File-System Functions (continued)
OSS Function OSS Notes Guardian Notes

remove() If remove() is passed the name of


Removes a file. an open file, that file is no longer
accessible by that name. Existing
opens remain in effect. When there
are no more outstanding opens, the
physical file is removed.

rename() or FDM set.


rename_oss() In /G, this function can be used on files
Renames a directory or file within a but cannot be used on directories. The
fileset from the OSS environment. new pathname must correspond to a
Guardian permanent disk filename on
the same volume, and the caller must
have Guardian write access to the file.

rename_guardian() Can return Guardian file-system error Can be used only on Guardian files in
Renames a file in the Guardian file numbers in errno. /G, and the caller must have Guardian
system. write access to the file.

rewinddir() If, after a call to fork() or


Repositions a directory stream to its tdm_fork(), both the parent and
beginning. Refer to opendir(). the child processes make calls to
rewinddir() to access the same
OSS directory, the results of the calls
are undefined.

rmdir() Fails on lost+found in root FDM set.


Removes a directory. directory of a fileset and on /dev.
Fails on disk volumes or processes in
rmdir() can be used to remove the /G and errno is set to EBUSY.
current working directory of a
process.
This call sets errno to EBUSY when
the directory is a mount point.
Can return extended errors.

scandir() scandir64() can access both small


scandir64() files and large files.
Scans a directory and builds an array
of pointers to copies of selected
directory entries.

seekdir() Can return extended errors.


Sets the position in a directory stream. If, after a call to fork() or
Refer to opendir(). tdm_fork(), both the parent and
the child processes make calls to
seekdir() to access the same OSS
directory, the results of the calls are
undefined.

select() Can return extended errors. FDM set.


Selects among file descriptors for Can return Guardian file-system error
synchronous I/O multiplexing. numbers in errno.

socket() Can return extended errors. FDM set.


Creates an endpoint for
communications.

socketpair() Can return extended errors. FDM set.


Creates an endpoint for
communications.

92 Managing Files
Table 2-5 OSS File-System Functions (continued)
OSS Function OSS Notes Guardian Notes

stat() For files other than regular disk files, FDM set.
stat64() st_size is set to 0 (zero), and for There are security and permission
Provides information about a directories, to 4096. mapping considerations. Refer to the
file.stat() function. The following bits are ORed into the reference page for detailed information
st_mode field of the stat structure: about using stat() on Guardian files.
S_IRWXU
S_IRWXG
S_IRWXO
S_IFMT
S_ISVTX
S_NONSTOP
S_ISGID
S_ISUID
Can return extended errors.
Can return Guardian file-system error
numbers in errno.
stat64() can access both small files
and large files.

statvfs() statvfs64() can access both small FDM set.


statvfs64() files and large files.
Gets fileset information using a
pathname.

symlink() Can return extended errors. FDM set.


Makes a symbolic link to a file. This function cannot be used on an
object in /G because symbolic links
cannot be created in /G.

telldir() Can return extended errors.


Returns the current location of a
directory stream.

ulimit() Can return extended errors.


Sets and gets file size limits. The error EINVAL is returned when
the second parameter is too large.

umask()
Sets and gets the value of the file
mode creation mask.

unlink() The calling process requires both FDM set.


Removes a directory entry. execute (search) and write access
permission for the directory of the file
being unlinked.
unlink() is not supported for
directories.
Can return extended errors.

utime() Can return extended errors. FDM set.


Sets the file access and modification The file access time is not updated for
times. I/O operations performed on a file that
is opened in the Guardian
environment.

OSS File-System Functions 93


Table 2-5 OSS File-System Functions (continued)
OSS Function OSS Notes Guardian Notes

write() Calls to write() with nbytes=0 Attempting to write to a Guardian file


Writes to a file. are supported for all files. that is locked with Guardian locks
If nbytes > SSIZE_MAX, write() returns -1 and sets errno to
returns -1 and errno is set to EGUARDIANLOCKED.
EINVAL.
errno can be set to EIO if a physical
I/O error occurs.
Can return extended errors.
Can return Guardian file-system error
numbers in errno.

writev() Can return Guardian file-system error Attempting to write to a Guardian file
Writes to a file from scattered buffers. numbers in errno. that is locked with Guardian locks
returns -1 and sets errno to
EGUARDIANLOCKED.

Guardian File-System Procedures


Table 2-6 displays information about each Guardian procedure that you can use to manage files.
Procedures that have been superseded by other procedures are not shown. The columns of the
table contain the following:
Guardian Procedure
The name of the procedure and a brief description.
OSS Notes
Additional considerations or restrictions when the Guardian procedure is used on OSS files.
For details about a procedure, refer to the Guardian Procedure Calls Reference Manual.
Table 2-6 Guardian File-System Procedures
Guardian Procedure OSS Notes

AWAITIO[X]
Checks for completion of read operations pending on the
$RECEIVE file.

FILE_ALTERLIST_ Fails with file-system error 1163 when the file is an OSS
Changes certain attributes of a Guardian disk file that are file.
normally set when the file is created.

FILE_COMPLETE_ For an OSS file descriptor: The Z^Count^Tranferred


Completes one previously initiated I/O operation for a field is overlaid by Z^Completion^Type and the Z^Tag
Guardian file or returns ready information for one OSS field contains 0D.
file. Completion on an OSS file descriptor means checking for
readiness. The operation of checking for readiness is
equivalent to calling the OSS select() function.
Can be interrupted by an OSS signal, which returns an
error 4004.

FILE_COMPLETE_GETINFO_
Provides information about the set of files that are enabled
for completion by FILE_COMPLETE_.

94 Managing Files
Table 2-6 Guardian File-System Procedures (continued)
Guardian Procedure OSS Notes

FILE_COMPLETE_SET_ For OSS, the type of operation (read, write, or exception)


Enables a set of Guardian and OSS files for completion can be specified.
by subsequent calls to FILE_COMPLETE_. Disabling a file descriptor of -1 means no OSS descriptors
will be completed in consecutive FILE_COMPLETE_ calls;
all OSS descriptors will be removed from the set of
enabled files.

FILE_CREATE_ Fails with file-system error 1163 when the file is an OSS
Creates a Guardian disk file specifying commonly used file.
disk file properties.

FILE_CREATELIST_ Fails with file-system error 1163 when the file is an OSS
Creates a Guardian disk file specifying properties in file.
addition to commonly used disk file properties.

FILE_GETINFO_ Bit 15 of the flags parameter = 0 if the file is a Guardian


Gets information about a file by number. file, 1 if the file is an OSS file.

FILE_GETINFOBYNAME_ Bit 15 of the flags parameter = 0 if the file is a Guardian


Gets information about a file by name. file, 1 if the file is an OSS file.

FILE_GETINFOLIST_ If the item-list parameter specifies item 161 and the


Gets detailed information about a file. result parameter returns 1, the file is an OSS file.
For systems running J-series RVUs, H06.08 and later
H-series RVUs, or G06.29 and later G-series RVUs only,
if the item-list parameter specifies item 169 and the
result parameter returns 11 bit on, OSS ACL file security
is in effect.
Access to record position pointers in 32-bit fields (item
codes 11 and 12) using this API fails with the error
FEBIGKEYS on an OSS file that was opened using 64-bit
elections. An alternative is to access the record position
pointers in 64-bit fields (item codes 201 and 202).
Other item-list parameter items are also specific to OSS
files. Refer to procedure description in the Guardian
Procedure Calls Reference Manual for OSS information.

FILE_GETINFOLISTBYNAME_ If the item-list parameter specifies item 161 and the


Gets detailed information about a file by name. result parameter returns 1, the file is an OSS file.
Access to record position pointers in 32-bit fields (item
codes 11 and 12) using this API fails with the error
FEBIGKEYS on an OSS file that was opened using 64-bit
elections. An alternative is to access the record position
pointers in 64-bit fields (item codes 201 and 202).

FILE_GETLOCKINFO_ This procedure operates only on Guardian files. Error 0


Gets information about locks held or pending on a local is returned if the file is an OSS file.
disk file or local disk volume.

FILE_GETOPENINFO_ When FILE_GETOPENINFO_ is given a Guardian


Gets information about the opens of one disk file on a filename that refers to an OSS file, the primary process
disk device, all the opens on a disk device, or the opens handle returned is for the initial opener. The process
of certain nondisk devices. handle might no longer exist.

FILE_OPEN_ Set options.


Opens a file. <10> to 1 to open an OSS file by its OSS pathname.OSS
files can be opened only with shared exclusion mode.
See also “Accessing OSS Files Larger Than 2 GB”
(page 74).

Guardian File-System Procedures 95


Table 2-6 Guardian File-System Procedures (continued)
Guardian Procedure OSS Notes

FILE_OPEN_CHKPT_ Always fails for OSS processes.


Opens a designated file in the backup Guardian process.

FILE_PURGE_ Fails with file-system error 1163 when the file is an OSS
Deletes a disk file that is not open. file.

FILE_RENAME_ Fails with file-system error 564 when the file is an OSS
Changes the name of an open disk file. file.

FILENAME_TO_PATHNAME_ There is too much OSS information to summarize here.


Converts a Guardian filename into an OSS pathname. Refer to procedure description in the Guardian Procedure
Calls Reference Manual for OSS information.

LOCKFILE Fails with file-system error 2 when the file is an OSS file.
Excludes other users from access to a Guardian file.

LOCKREC Fails with file-system error 2 when the file is an OSS file.
Excludes other users from access to a record.

PATHNAME_TO_FILENAME_ There is too much OSS information to summarize here.


Maps an OSS pathname to the name of the Guardian ZYQ Refer to procedure description in the Guardian Procedure
filename of the corresponding regular file. Calls Reference Manual for OSS information.

READLOCK[X] Fails with file-system error 2 when the file is an OSS file.
Sequentially locks and reads records in a Guardian disk
file, just like combinations of LOCKREC and READ[X].

READUPDATELOCK[X] Fails with file-system error 2 when the file is an OSS file.
Performs random processing of records in a Guardian
disk file.

SETMODE Fails with file-system error 2 when the file is an OSS file.
Sets device-dependent functions.

WRITEUPDATEUNLOCK[X] Fails with file-system error 2 when the file is an OSS file.
Alters, then unlocks the contents of a Guardian record at
the current position.

96 Managing Files
3 Managing Processes
You can create, control, and terminate OSS processes as you would in a standard UNIX
environment. In addition to the standard set of UNIX process-management functions, there are
several HP extension functions that provide flexibility in propagating attributes during process
creation.
OSS processes have a full set of Guardian attributes as well as OSS-specific attributes. Most
Guardian process-management procedures can access OSS processes, and some OSS
process-management functions can access Guardian processes.
This section discusses the following topics:

Topic Content

“Common and Unique Characteristics” (page 97) Summary of the differences between UNIX and OSS
process management.

“Process Attributes” (page 105) Which OSS attributes Guardian processes have, examples
of Guardian attributes that are important to OSS
processes, and a table comparing attributes in OSS and
Guardian processes.

“Process-Management Interoperability” (page 107) Capability of OSS functions to manage Guardian processes
and of Guardian procedures to manage OSS processes.

“Creating and Controlling Processes” (page 111) OSS functions and Guardian procedures to create,
suspend, activate, and terminate processes.

“Querying the Process Environment” (page 121) OSS functions and Guardian procedures to get
information about both OSS and Guardian processes and
their environments.

“Modifying the Process Environment” (page 127) OSS functions and Guardian procedures to modify
characteristics about both OSS and Guardian processes
and their environments.

“Performance Considerations” (page 130) Suggestions regarding the use of processmanagement


functions to improve application performance.

“OSS Process-Management Functions” (page 141) List of each OSS process-management function with notes
about its OSS implementation and use on Guardian
processes.

“Guardian Process-Management Procedures” (page 146) List of each Guardian process-management procedure
with notes about its use on OSS processes.

Common and Unique Characteristics


OSS process management looks like typical UNIX process control, but there are some important
extensions added for interoperability between the OSS and Guardian environments. These
extensions and any differences between OSS process-management functions and typical UNIX
process control are summarized in Table 3-4 (page 141). Table 3-5 (page 147) summarizes the
behavior of Guardian process-management procedures when used to operate on OSS processes.

Features Common to UNIX and OSS Process Management


Common features include those discussed in the following subsections:
• “Process Creation Functions” (page 98)
• “Process Execution Priority-Control Functions” (page 103)

Common and Unique Characteristics 97


Process Creation Functions
You can create OSS processes with the fork() function. The attributes of the parent process are
propagated to the child process, and the child process has an OSS process ID that uniquely
identifies it. An OSS process can send signals to and receive signals from other OSS processes.
You can query and modify the process environment using functions such as getpid() and
putenv(). OSS processes receive notification when a child process terminates with the SIGCHLD
signal and can use the wait() and waitpid() functions.
Example 3-1 (page 99) and Example 3-2 (page 102)Dynamic Echo Server Program illustrate typical
use of the fork(), execv(), and wait() functions in an application. These programs
demonstrate one of the restrictions of using a member of the standard exec set of functions: you
are limited to launching new processes in the same processor; refer to “Performance
Considerations” (page 130) for less restricted examples.
The launcher program in Example 3-1 is compiled as a linked program file named dlaunchl.
The server program in Example 3-2 is compiled as a linked program file named dserver. (A
requester program, shown in Example 6-2 (page 171), is also compiled as a linked program file
named requester2.) All programs are secured for execution in the current working directory.

NOTE: These examples use the AF_INET sockets functions, which provide an interface to HP
NonStop TCP/IP. The programs could also be written using the AF_INET6 sockets functions to
interface to HP NonStop TCP/IPv6. For information and examples of AF_INET6 sockets usage,
refer to the TCP/IP Programming Manual.
In this application, dlaunch1 creates an AF_INET socket and listens for incoming connections
from one or more copies of requester2. Upon receipt of a connection, dlaunch1 uses fork()
to create a duplicate of itself as a child process.
The child process duplicates itself again with another call to fork() to create a grandchild. The
grandchild overwrites itself by starting server, using an execv() call. The child process exits
immediately so that the dlaunch1 call to the wait() function prevents the child process from
becoming a zombie process and wasting processor resources.

98 Managing Processes
Example 3-1 Dynamic Launcher Program
/* dlaunch1.c
*
* Simple OSS example using OSS socket APIs for communication
* between requester and server.
*
* dlaunch1 (dynamic launcher 1) is an inetd-like program which
* accepts socket connections and exec's a dserver process for
* each connection.
*
* dserver reads stdin and echoes to stdout. dlaunch1 and dserver
* write progress messages and error messages to stderr.
*
* dlaunch1 and the multiple dserver processes run on the same cpu.
*/

#define _XOPEN_SOURCE_EXTENDED 1 /* needed for OSS sockets */

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netdb.h>

/* Guardian APIs */
#include <cextdecs.h(PROCESSHANDLE_GETMINE_, PROCESSHANDLE_DECOMPOSE_)>

short cpu, phandle[10]; /* our cpu and process handle */


int newpid, fd, listenfd; /* process id, file descriptor, listening fd */
int readycount, bytesread; /* ready fd count, recv byte count */
struct sockaddr_in addr; /* socket address (family,addr,port) */
struct timeval timeval; /* timeout structure for select() call */
fd_set fdset; /* set of fds for select() call */

#define IDLE_PERIOD 180 /* 180 second timeout value */

int main(int argc, char **argv)


{
/* get process handle and cpu number */
PROCESSHANDLE_GETMINE_(phandle);
PROCESSHANDLE_DECOMPOSE_(phandle, &cpu);

/* print startup message */


fprintf(stderr, "dlaunch1 starting in cpu %d\n", cpu);

/* create AF_INET stream socket */


if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "socket() call failed [errno %d]\n", errno);
exit(1);
}

/* Get server port from the command line or use default 12345 */
if (argc > 1)

Common and Unique Characteristics 99


addr.sin_port = (short)atoi(argv[1]); /* use command line arg */
else
addr.sin_port = 12345; /* use default */

addr.sin_family = AF_INET; /* internet address family */


addr.sin_addr.s_addr = gethostid(); /* assume server on our host */

/* bind socket to address */


if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0)
{
fprintf(stderr, "bind() call failed [errno %d]\n", errno);
exit(1);
}

/* make the socket a listening socket */


if (listen(fd, 5) < 0)
{
fprintf(stderr, "listen() call failed [errno %d]\n", errno);
exit(1);
}

/* fd usage
* 0 stdin - not used by dlaunch1, set up for dserver
* 1 stdout - not used by dlaunch1, set up for dserver
* 2 stderr - used by dlaunch1 for messages, inherited by dserver
* 3 listenfd - used by dlaunch1 for connections,
* not inherited by dserver
*/

close(STDIN_FILENO);
close(STDOUT_FILENO);
listenfd = fd;
fcntl(listenfd, F_SETFD, FD_CLOEXEC); /* don't propagate fd to children */
FD_ZERO(&fdset);

/* loop until error or timeout */


while (1)
{
/* initialize timeout and bitmask for select() call */
timeval.tv_sec = IDLE_PERIOD;
timeval.tv_usec = 0;
FD_SET(listenfd, &fdset);
readycount = select(listenfd+1, &fdset, NULL, NULL, &timeval);

/* if timeout then exit */


if (readycount == 0)
{
fprintf(stderr, "dlaunch1 stopping - timeout\n");
exit(0);
}
/* accept new connection */
if ((fd = accept(listenfd,(struct sockaddr *)NULL,
(size_t *)NULL)) < 0)
{
fprintf(stderr, "accept() call failed [errno %d]\n", errno);
exit(1);
}

/* setup stdin and stdout */


dup2(fd,STDIN_FILENO); /* fd is already STDIN_FILENO */
dup2(fd,STDOUT_FILENO); /* setup stdout */

/* launch a dserver process to handle the connection */


/* note - fork and exec are expensive operations and only */
/* apply to the same cpu as the parent process */
if ((newpid = fork()) < 0)
{
fprintf(stderr, "fork() failed [errno %d]\n", errno);
exit(1);
}
else if (newpid == 0)
{

100 Managing Processes


/* we are child ... create grandchild to avoid zombie processes */
if ((newpid = fork()) < 0)
{
fprintf(stderr, "fork() failed [errno %d]\n", errno);
exit(1);
}
else if (newpid == 0)
{
/* we are grandchild ... exec server process with stdin
* and stdout set to connection and stderr set to
* launcher's stderr
*/
execv("./dserver",argv); /* no return from exec */
}
exit(0); /* child goes away */
}
else
{
/* we are parent */
fprintf(stderr, "dserver exec'ed in cpu %d\n", cpu);
wait(&newpid); /* wait for child to avoid zombie
* child process */
close(STDIN_FILENO);
close(STDOUT_FILENO);
}
} /* end while (1) */
}
The original dlaunch1 process closes the file descriptors associated with the requester2
connection. The grandchild process, dserver, which has inherited file descriptors for the
connection, handles all work associated with the connection. When dserver terminates, it no
longer has a parent process (because its parent, the child process, already terminated) and cannot
become a zombie process.
Note that dserver is a dynamic server, launched only when needed and terminating when its
function is completed. Such servers conserve processor resources if run infrequently. If servers
need to be launched frequently, a static iterative server, such as that shown in Example 3-15
(page 139) or in Example 6-2 (page 171), uses processor resources more efficiently.
Using two terminal sessions, sample dialog for the terminal launching dlaunch1 might be:
/home/software/chrisbl/cabpubs: ./dlaunch1
dlaunch1 starting in cpu 8
dserver exec'ed in cpu 8
dserver [cpu 8] - starting
dserver [cpu 8] - message received on fd 0 = hello from first requester
dserver [cpu 8] - stopping [input closed]
dserver exec'ed in cpu 8
dserver [cpu 8] - starting
dserver [cpu 8] - message received on fd 0 = hello from another requester
dserver [cpu 8] - stopping [input closed]
dlaunch1 stopping - timeout
/home/software/chrisbl/cabpubs:
while the terminal running the copy of requester2 might show:
/home/software/chrisbl/cabpubs: ./requester2
Requester starting
?hello from first requester
Read 27 bytes back from server
?
/home/software/chrisbl/cabpubs: ./requester2
Requester starting
?hello from another requester
Read 29 bytes back from server
?
/home/software/chrisbl/cabpubs:

Common and Unique Characteristics 101


Example 3-2 Dynamic Echo Server Program
/* dserver.c
*
* Simple OSS server example using OSS APIs for communication
* between requester and server.
*
* dserver is a dynamic echo server. A dserver process is launched
* for each requester. dserver reads stdin and echoes on stdout.
* dserver exits when idle for 60 seconds.
*/

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>

/* Guardian APIs */
#include <cextdecs.h(PROCESSHANDLE_GETMINE_, PROCESSHANDLE_DECOMPOSE_)>

short cpu, phandle[10]; /* our cpu and process handle */


int bytesread, readycount; /* ready fd count, recv byte count */
struct timeval timeval; /* timeout structure for select() call */
fd_set fdset; /* set of fds for select() call */

#define IDLE_PERIOD 60 /* 60 seconds */


#define BUFF_LEN 1024 /* buffer size */
char msg_buff[BUFF_LEN+1]; /* single buffer is enough */

int main(int argc, char **argv)


{

/* get process handle and cpu number */


PROCESSHANDLE_GETMINE_(phandle);
PROCESSHANDLE_DECOMPOSE_(phandle, &cpu);

/* print startup message */


fprintf(stderr, "dserver [cpu %d] - starting\n", cpu);

FD_ZERO(&fdset);

/* loop until error or timeout or input closed */


while (1)
{
/* initialize timeout and bitmask for select() call */
timeval.tv_sec = IDLE_PERIOD;
timeval.tv_usec = 0;
FD_SET(STDIN_FILENO, &fdset);
readycount = select(STDIN_FILENO+1, &fdset, NULL, NULL, &timeval);

/* if timeout then exit */


if (readycount == 0)
{
fprintf(stderr, "dserver [cpu %d] - stopping [timeout]\n", cpu);
exit(0);
}
/* fd ready so read data */
if ((bytesread = read(STDIN_FILENO, msg_buff, BUFF_LEN)) < 0)
{
fprintf(stderr, "dserver [cpu %d] - "
"read(fd %d) failed [errno %d]\n",

102 Managing Processes


cpu, STDIN_FILENO, errno);
exit(1);
}
else if (bytesread == 0) /* check for input closed */
{
ffprintf(stderr, "dserver [cpu %d] - "
"stopping [input closed]\n",
cpu);
exit(1);
}
else /* data received */
{
/* give progress message */
msg_buff[bytesread] = '\0'; /* guarantee string NULL-terminated */
fprintf(stderr, "dserver [cpu %d] - "
"message received on fd %d = %s",
cpu, STDIN_FILENO, msg_buff);

/* echo on stdout */
if (write(STDOUT_FILENO, msg_buff, bytesread) < 0)
{
fprintf(stderr, "dserver [cpu %d] - "
"write(fd %d) failed [errno %d]\n",
cpu, STDOUT_FILENO, errno);
exit(1);
}
}
} /* end while (1) */
}

Process Execution Priority-Control Functions


You can change the process scheduling priority, called the nice value, with the nice() function.
The nice value of a parent process is propagated to a child process during a call to the fork(),
tdm_fork(), tdm_spawn(), and tdm_spawnp() functions.
Example 3-3 provides sample code to demonstrate the use of the getpriority() function to
determine the process priority of the processes that are members of the specified group. The
sample code also demonstrates the use of nice() to change the current process priority by the
increment specified in the command line.

Common and Unique Characteristics 103


Example 3-3 Determining and Changing Process Priority using getpriority() and nice()
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>

extern int errno;

int getpri(int which, id_t who)


{
int cval;

errno = 0;
cval = getpriority(which, who);
if(errno) {
fprintf(stderr, "getpriority error, args = %d, %d\n", which, who);
exit(1);
}
return(cval);
}

int main(int argc, char *argv[])


{
int prval, pval, retcode;

/*
Read the value of the process priority increment from the command line.
If the value is not provided, print usage message and exit.
If the value is invalid, print error message and exit.
*/
if(argc > 1) {
prval = atoi(argv[1]);
if(abs(prval) > (2*NZERO-1)) {
fprintf(stderr, "Invalid priority increment %s\n", argv[1]);
exit(1);
}
} else {
fprintf(stderr, "Usage: nicegetp value [0 to 150]\n");
exit(1);
}

/* Print current process priority value. */


pval = getpri(PRIO_PROCESS, 0);
printf("Current process priority value = %d\n", pval);
/* Print current process group priority value. */
pval = getpri(PRIO_PGRP, 0);
printf("Current process group priority value = %d\n", pval);
/* Print process priority value associated with this user. */
pval = getpri(PRIO_USER, 0);
printf("Process priority value associated with user = %d\n", pval);

/* Set current process priority value */


errno =0;
pval = nice(prval);
if(errno) {
fprintf(stderr, "Can't change process priority by %d\n", prval);
exit(1);
}
printf("New nice value = %d\n", pval);
pval = getpri(PRIO_PROCESS, 0);
printf("Process priority set to %d\n", pval);

104 Managing Processes


return(0);

Features Unique to OSS Process Management


• OSS processes have an OSS process ID and a process handle. An OSS process ID is a
nonnegative integer that uniquely identifies a process within a node. A process handle is a
data structure ten words long that uniquely identifies a process within a NonStop network.
• There are HP extension functions. The tdm_fork(), tdm_execve(), tdm_execvep(),
tdm_spawn(), and tdm_spawnp() functions allow you to set attributes when a process
is created that you cannot set with the standard fork() and exec set of functions. For
example, the tdm_fork() function allows you to either retain the attribute values inherited
from the parent or specify other values. The fork() function does not allow you to overwrite
the values of the inherited attributes.
• OSS processes have Guardian attributes. In addition to OSS-specific attributes, OSS processes
have a full set of Guardian attributes, such as process handle and Guardian user ID.
• Most Guardian process-management procedures can access OSS processes. The process
handle of an OSS process allows most Guardian process-management procedures to
manipulate OSS processes, including changing the priority of a process, getting information
about it, and terminating it.
• Some OSS functions can access Guardian processes. For example, OSS functions can provide
the system-dependent system limits, times, and user ID of a Guardian process.
• After a process is created, its execution priority cannot be modified using an OSS function.
In the current release, you must use a Guardian procedure to change process priority.
• Processes running in the OSS environment have their nice() scheduling priorities
determined using UNIX conventions. The scheduling priority for processes running in the
Guardian environment is defined as increasing as the priority number increases. This
convention is the opposite of the convention used on UNIX systems, where a lower priority
number means a higher scheduling priority.

Process Attributes
All processes, OSS and Guardian, have Guardian attributes and some OSS attributes. OSS
processes are basically Guardian processes with some additional OSS-specific attributes, such
as OSS process ID.

OSS Attributes in Guardian Processes


The OSS attributes of Guardian processes include an extended security block that allows Guardian
processes to access OSS and Guardian objects belonging to other related groups and group IDs.
Guardian processes also have some OSS file system attributes that allow Guardian processes to
access OSS objects and do OSS file system work.
A Guardian process has a process handle but not an OSS process ID. This means that an OSS
process cannot send signals to a Guardian process and that a Guardian process cannot belong
to a process group or session.

Guardian Attributes in OSS Processes


There are many Guardian attributes that an OSS child process inherits from its parent. When
you create a process using the OSS HP extension functions such as tdm_fork(), tdm_execve(),
and tdm_spawn(), you can set or overwrite inherited Guardian attributes by specifying values
for the fields in the input structure that contains Guardian attributes. Examples of these attribute
fields are pe_cpu (processor), pe_debug_options (debug options), and pe_hometerm (home
terminal).

Process Attributes 105


Some Guardian attributes are more important for you to manipulate than others. The following
lists the attributes you might want to set when you create a process using the OSS HP extension
functions. For more information about setting these attributes, see the process-creation functions
in the reference pages either online or in the Open System Services System Calls Reference Manual.
• Processor. Specifying the processor on which a process executes allows you to distribute an
application across processors. tdm_fork() does not allow you to specify a value for the
processor attribute, but the tdm_exec and tdm_spawn sets of functions do. You cannot
change the processor in which a process executes after the process is created.
• Debug options. Debug options can instruct a debugging program to create a saveabend file
if the process terminates abnormally. A saveabend file contains data-area and file-status
information at the time of the failure. Debug options also can force the child process to enter
a debugging program after returning from the tdm_fork() function. You cannot change
the debug options of a process after the process is created.
• Home terminal. Making the home terminal different from the controlling terminal allows
you to avoid information collisions. For example, you can make another terminal or terminal
emulator window (other than the controlling terminal) the home terminal, and a debugging
program can display messages there. Use the PROCESS_SETSTRINGINFO_ procedure to
change the home terminal of a process after it is created.
• Priority. Changing the execution priority of a process changes the position of the process in
the ready queue. Use the PROCESS_SETINFO_ procedure to change the priority of a process
after it is created.
• DEFINEs. Specifying a set of DEFINEs to be propagated to a new process lets you pass
information to the process. For example, you can specify an SQL catalog to be used by an
SQL process. Use Guardian procedures, such as DEFINEADD and DEFINEDELETE, or OSS
utilities, such as add_define and del_define, to change the DEFINEs of a process after
it is created.

Comparing OSS and Guardian Process Attributes


Table 3-1 summarizes some important process attributes that OSS and Guardian processes have
in common and those they do not share. Notice that except for a program type of Guardian, OSS
processes almost always have Guardian process attributes while Guardian processes lack several
OSS-specific attributes.
Table 3-1 OSS and Guardian Process Attribute Comparison
Process Attribute Part of an OSS Process? Part of a Guardian Process?

Ancestors

Guardian ancestor Sometimes Sometimes


Guardian MOM/GMOM Sometimes Sometimes
OSS parent Always Never

Groups

OSS group leader Always Never


OSS session leader Always Never

Identification

Guardian creator access ID Always Always


Guardian process access ID Always Always
Guardian process handle Always Always
Guardian process name Sometimes Sometimes
Guardian user ID Always Always
OSS group ID Always Always
OSS parent process ID Always Never
OSS process ID Always Never
OSS user ID Always Always

106 Managing Processes


Table 3-1 OSS and Guardian Process Attribute Comparison (continued)
Process Attribute Part of an OSS Process? Part of a Guardian Process?

Program type

Guardian Never Always


OSS Always Never

Terminals

Guardian home terminal Sometimes Sometimes


OSS controlling terminal Sometimes Never

nice scheduling priority Always Sometimes

Process-Management Interoperability
In general, you should manage OSS processes with OSS functions, because your applications
are more portable. However, there might be cases in which you want to use Guardian procedures
to manage OSS processes or OSS functions to manage Guardian processes. For example, if you
want to use a product or subsystem that runs only in the Guardian environment, you might need
to manage a process from the opposite environment.
The process handle of an OSS process allows most Guardian process-management procedures
to access it. On the other hand, a Guardian process does not have an OSS process ID, which is
required by many OSS process-management functions. This means that some OSS
process-management functions cannot access Guardian processes.
Table 3-2 lists and provides a short description of the Guardian process-management procedures
that can access OSS processes. Note that the only principal Guardian process-management
procedure missing from this list is PROCESS_LAUNCH_, because it can create only Guardian
processes. Table 3-5 (page 147) provides a summary of all Guardian process-management
procedures.
Procedures that are indicated as “superseded” in the Guardian Procedure Calls Reference Manual
are not included in this table, because you should not use them for new program development.
Table 3-2 Guardian Process-Management Procedures That Can Access OSS Processes
Guardian Procedure Description

CHILD_LOST_ Examines a system message to determine whether a process has stopped

FILENAME_TO_PROCESSHANDLE_ Converts a (process) filename to a process handle

OSS_PID_NULL_ Returns a null OSS process ID

PROCESS_ACTIVATE_ Returns a suspended process to a ready state

PROCESS_DEBUG_ Invokes the debugging facility on a process

PROCESS_GETINFO_ Gets a limited set of information about a process

PROCESS_GETINFOLIST_ Gets detailed information about a process or set of processes

PROCESS_GETPAIRINFO_ Obtains information about a named process or process pair

PROCESS_SETINFO_ Modifies a single nonstring attribute of a process

PROCESS_SETSTRINGINFO_ Modifies a single string-form attribute of a process

PROCESS_SPAWN_ Creates an OSS process

PROCESS_STOP_ Terminates a process

PROCESS_SUSPEND_ Places a process into a suspended state

Process-Management Interoperability 107


Table 3-2 Guardian Process-Management Procedures That Can Access OSS Processes (continued)
Guardian Procedure Description

PROCESSHANDLE_COMPARE_ Compares two process handles and reports whether they are identical,
represent different processes of the same process pair, or are different

PROCESSHANDLE_DECOMPOSE_ Returns one or more parts of a process handle

PROCESSHANDLE_GETMINE_ Gets the process handle of the calling process

PROCESSHANDLE_NULLIT_ Initializes a process handle to a null value

PROCESSHANDLE_TO_CRTPID_ Converts a process handle to the corresponding Guardian process ID


(CRTPID)

PROCESSHANDLE_TO_FILENAME_ Converts a process handle to a (process) filename

PROCESSHANDLE_TO_STRING_ Converts a process handle to a process string, which can identify a process
or set of processes

PROCESSNAME_CREATE_ Returns a unique process name that is suitable for passing to the
PROCESS_CREATE_ procedure

PROCESSSTRING_SCAN_ Scans an input string for a process string and returns the corresponding
process handle or a single component of the process string converted to
internal form

SETLOOPTIMER1 Sets the process loop-timer value of the calling process

SIGACTION_INIT_2 Establishes the initial state of signal handling for the calling process
3
SIGACTION_RESTORE_ Restores the signal-handling state stored by a call to
SIGACTION_SUPPLANT_

SIGACTION_SUPPLANT_4 Saves the current signal-handling state and allows a subsystem to take
over signal handling temporarily

SIGJMP_MASKSET_5 Saves the process signal mask in a jump buffer


1 Also available as the C function SETLOOPTIMER().
2 Also available as the C function SIGACTION_INIT_().
3 Also available as the C function SIGACTION_RESTORE_().
4 Also available as the C function SIGACTION_RESTORE_().
5 Also available as the C function SIGACTION_MASKSET_().

Table 3-3 lists and provides a short description of the OSS process-management functions that
can access Guardian processes. Table 3-4 (page 141) provides a summary of all OSS
process-management functions.

NOTE: To determine which RVUs support an OSS function, see Appendix A: Documented
OSS Functions (page 389).
Table 3-3 OSS Process-Management Functions That Can Access Guardian Processes
OSS Function Description

abort() Generates a software signal to terminate the calling process

alarm() Sets or changes a timer that expires at a specified time in the future

_exit() Terminates the calling process


exit()

getegid() Gets the effective group ID of the calling process

getenv() Returns the value of an environment variable

geteuid() Gets the effective user ID of the calling process

108 Managing Processes


Table 3-3 OSS Process-Management Functions That Can Access Guardian Processes (continued)
OSS Function Description

getgid() Gets the real group ID of the calling process

getgroups() Gets the group list of the calling process

getsid() Gets the group ID of the process that is the session leader of the specified process

getuid() Gets the real user ID of the calling process

longjmp() Performs a nonlocal goto

nftw() Traverses a file tree


nftw64()

pause() Suspends the calling process until a signal is received

putenv() Sets an environment variable

raise() Sends a signal to the calling process

setgid() Sets the group ID of the calling process

setjmp() Saves the current execution context

setpgrp() Creates a new session when the calling process is not a process group leader, and sets
the process group ID of the calling process

setregid() Sets the real and effective group IDs of the current process

setreuid() Sets the real and effective user IDs of the current process

setsid() Creates a new session and sets the process group ID

setuid() Sets the user ID of the calling process

sigaction() Specifies the action to be taken upon delivery of a signal

sigaddset() Adds a signal to a signal set

sigdelset() Deletes a signal from a signal set

sigemptyset() Initializes a signal set to exclude all signals

sigfillset() Initializes a signal set to include all signals

sigismember() Tests whether a signal is a member of a signal set

siglongjmp() Performs a nonlocal goto

signal() Specifies the action to be taken upon delivery of a signal

sigpending() Returns the set of signals that are blocked from delivery and pending to the calling
process

sigprocmask() Changes or examines a process signal mask

sigsetjmp() Saves the current execution context and can save the current process signal mask

sigsuspend() Changes a process signal mask and suspends the calling process

sleep() Suspends the calling process for a specified interval of time

times() Gets calling process and child process times

uname() Gets information identifying the system on which the calling process runs

Process-Management Interoperability 109


Signals Interoperability
Signals are software interrupts that provide a way of handling asynchronous events, such as a
user at a terminal typing an interrupt key, timer expiration, detection of a hardware fault, or
abnormal termination of a process.

Using Standard Signals Functions


Both OSS processes and Guardian native processes can send, receive, and handle signals using
the functions in the OSS API, which conform to the POSIX.1 standard. However, there are some
important differences (mostly with respect to how Guardian processes interact with signals),
which are summarized as follows:
• Control of a process over itself and other processes
An OSS process can control, or send a signal to, itself using a function such as raise(),
abort(), or sleep(). An OSS process can also exercise control over another OSS process
by sending a signal to it using the kill() function.
A Guardian native process can use most of the signals functions in the OSS API to send,
receive, and handle signals but only for the purpose of exercising control over itself. A
Guardian native process cannot send a signal to or receive a signal from another Guardian
or OSS process using the kill() function.
• Signals in TNS processes and native processes
Any OSS process (native or G-series TNS) can use OSS signals functions. Only a Guardian
native process can use OSS signals functions.
• Interrupts from a terminal as signals
When a user presses an interrupt key at a terminal, an OSS process receives the interrupt as
a signal. A Guardian process receives the interrupt as a system message and must read its
$RECEIVE file to get the interrupt.
• Process signal mask
The process signal mask of an OSS process is initialized to that of its parent. The process
signal mask of a Guardian process is initialized so that no signals are blocked from delivery
to it.
• Default signal handler
The Common Run-Time Environment (CRE) sets up a default signal handler for a Guardian
program written in C. The CRE does not set up a default signal handler for an OSS program
written in C.

Using HP Signals Extension Functions


Guardian TNS processes receive traps to indicate run-time events requiring immediate attention.
Guardian native processes receive signals to indicate conditions known as traps in Guardian
TNS processes.
The HP signals extensions are provided as migration and convenience tools that allow native
processes to catch signals corresponding to trap conditions in TNS processes. The signals
extensions provide shortcuts to the same basic functions as provided by the standard signal
interfaces.
Both OSS and Guardian native processes can use the signals extensions, but you probably won’t
have much reason to use them because you are concerned with handling the full range of signals,
not just those known as traps in Guardian TNS programs. Traps are a subset of all signals. Also,
the standard signals functions are portable and the HP extensions are not.
The signals extensions are available in C and pTAL. The C versions are SIGACTION_INIT_(),
SIGJMP_MASKSET_(), SIGACTION_SUPPLANT_(), and SIGACTION_RESTORE_().

110 Managing Processes


For information about how to use these functions, see the Guardian Programmer’s Guide.
Examples in the following subsections show how to manage processes with both the OSS and
Guardian APIs. For information about OSS functions, see the Open System Services System Calls
Reference Manual and the Open System Services Library Calls Reference Manual. For information
about Guardian procedures, see the Guardian Procedure Calls Reference Manual.

Creating and Controlling Processes


The OSS API allows you to create OSS processes and to control (through signals functions) both
OSS and Guardian processes. The Guardian API provides procedures to create and control both
OSS and Guardian processes.

Using the OSS API


You can create only OSS processes with OSS functions. Both Guardian and OSS processes can
be controlled through signals functions with one exception: the kill() function. Only OSS
processes can send or receive signals using the kill() function, because kill() needs the OSS
process ID of the intended recipient in order to send a signal to it. (A Guardian process does not
have an OSS process ID.)

NOTE: You can use OSS signals functions with Guardian native processes; you cannot use
them with Guardian TNS processes.

Creating OSS Processes Using HP Extension Functions


The tdm_fork(), tdm_execve(), tdm_execvep(), tdm_spawn(), and tdm_spawnp()
functions allow you to set attributes when a process is created that you cannot set with the
standard fork() and exec set of functions.
You can create OSS processes using the tdm_spawn() or tdm_spawnp() function or by calling
the fork() or tdm_fork() function followed by one of the exec or tdm_exec set of functions.
Application performance is better if you use tdm_spawn() or tdm_spawnp(). These functions
also allow you to specify inheritance information for the child process in the inherit structure,
and the fd_count and fd_map parameters allow you to control the file descriptors the child
process inherits from the parent.
Examples of both methods of creating processes are shown for purposes of comparison.
Example 3-4 creates a named process with a system-generated name using tdm_fork(). The
program then passes a different process name and the processor on which the child process will
execute to tdm_execvep().

Creating and Controlling Processes 111


Example 3-4 Creating an OSS Process Using tdm_fork() and tdm_execvep()
#include <tdmext.h> /* Note 1 */
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

/* Set defaults for input and output structures. Note \2 */


struct process_extension
procext = DEFAULT_PROCESS_EXTENSION;
struct process_extension_results
procresults = DEFAULT_PROCESS_EXTENSION_RESULTS;
extern char **environ;
char *argv[10];

int main(void)
{
char buf[4096];
pid_t pid;
int status, cnt;
char *ptr;

/* Get parameters for the child process from the command line. */
printf("%% "); /* print prompt (printf requires %% to print %) */
while (fgets(buf, 4096, stdin) != NULL) {
ptr = buf;
buf[strlen(buf) - 1] = '\0'; /* replace newline with NULL */

/* Build the parameter list for the child process. */


argv[0] = buf;
cnt = 1;
while(*ptr) {
if(*ptr == ' ') {
*ptr = '\0';
argv[cnt++] = ptr + 1; /* one blank between parameters */
}
ptr++;
}
argv[cnt] = NULL;

/* Request system-generated process name and create child process. */


procext.pe_name_options = _TPC_GENERATE_NAME;
if ( (pid = tdm_fork(&procext, &procresults)) < 0 ) {

/* If tdm_fork() fails, print diagnostic messages. */


fprintf(stderr, "pid = %o\n", pid);
fprintf(stderr, "procresults.pr_len = %o\n",\
procresults.pr_len);
fprintf(stderr, "procresults.pr_pid = %o\n",
procresults.pr_pid);
fprintf(stderr, "procresults.pr_errno = %o\n",
procresults.pr_errno);
fprintf(stderr, "procresults.pr_TPCerror = %o\n",
procresults.pr_TPCerror);
fprintf(stderr, "procresults.pr_TPCdetail = \
%o\n",procresults.pr_TPCdetail);
fprintf(stderr, "errno = %d\n", errno);
perror("tdm_fork error");

/* Pass values for the child process to execvep().*/

112 Managing Processes


} else if (pid == 0) { /* child process executing */
printf("trying execute of %s\n", buf);
printf("argv[0]=%s,argv[1]=%s,argv[2]=%s\n",
argv[0],argv[1],argv[2]);
/* Supply a name and processor number for the child process. */
procext.pe_name_options = _TPC_NAME_SUPPLIED; /* Note 3 */
procext.pe_process_name = "/G/HEINZ"; /* set process name */
procext.pe_cpu = 1; /* set processor number */
/* Pass parameter values to the child process. */
tdm_execvep(buf, argv, environ, &procext, &procresults);
/* If process execution failed, print error message. */
fprintf(stderr, "couldn't execute: %s\n", buf); /* Note 4 */
exit(2);
}

/* The parent process waits for the child process to terminate. */


if ( (pid = waitpid(pid, &status, 0)) < 0)
perror("waitpid error");
printf("%% ");
}
exit(0);
}

Note 1
The tdmext.h library header file defines the input structure containing Guardian process
attributes to be assigned to the new process. It also defines the output structure containing
optional process identification and error information.
Note 2
To set attributes in the new process, you must declare the procext (input) and procresults
(output) structures and initialize them with default values. Then you can set attributes using
literals defined in tdmext.h.
Note 3
To set the process name, request a system-generated process name before calling tdm_fork()
and pass your process name to tdm_evecvep(). If you attempt to pass your name to
tdm_fork() and use the same name in the call to tdm_execvep(), you get an error stating
that the process already has a name.
Note 4
After the call to tdm_fork(), the child process has its own unique OSS process ID, which
does not change. It also has a process handle that does change after the call to
tdm_execvep().
Example 3-5 creates a named process with a system-generated name using tdm_spawnp(). By
setting fields in the inherit structure, the child process becomes a member of a group other than
the parent’s process group, and the child process is the leader of the new process group.

Creating and Controlling Processes 113


Example 3-5 Creating an OSS Process Using tdm_spawnp()
#include <tdmext.h>
#include <spawn.h> /* Note 1 */
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

/* Set defaults for input and output structures */


struct process_extension
procext = DEFAULT_PROCESS_EXTENSION;
struct process_extension_results
procresults = DEFAULT_PROCESS_EXTENSION_RESULTS;
struct inheritance inherit;
extern char **environ;
char *argv[10];

int main(void)
{

char buf[4096];
pid_t pid;
int status, cnt;
int fd_count, fd_map[20];
char *ptr;

/* Get parameters for the child process from the command line. */
printf("%% "); /* print prompt (printf requires %% to print %) */
while (fgets(buf, 4096, stdin) != NULL) {
ptr = buf;
buf[strlen(buf) - 1] = '\0'; /* replace newline with NULL */

/* Build the parameter list for the child process. */


argv[0] = buf;
cnt = 1;
while(*ptr) {
if(*ptr == ' ') {
*ptr = '\0';
argv[cnt++] = ptr + 1; /* one blank between parameters */
}
ptr++;
}
argv[cnt] = NULL;
fd_map[0] = 0; /* Note 2 */
fd_map[1] = 1;
fd_map[2] = 2;
fd_count = 3;

/* Request system-generated process name. */


procext.pe_name_options = _TPC_GENERATE_NAME;
/* Set up child process as new group leader. */
inherit.flags = SPAWN_SETGROUP;
inherit.pgroup = SPAWN_NEWPGROUP;
printf("trying spawn of %s\n", buf);
/* Spawn child process with supplied parameters. */
if((pid=tdm_spawnp(buf,fd_count,fd_map,&inherit,
argv,environ,&procext,&procresults))<0){
/* If unsuccessful, print diagnostic messages. */
fprintf(stderr, "pid = %o\n", pid);
fprintf(stderr, "procresults.pr_len = %o\n",
procresults.pr_len);
fprintf(stderr, "procresults.pr_pid = %o\n",

114 Managing Processes


procresults.pr_pid);
fprintf(stderr, "procresults.pr_errno = %o\n",
procresults.pr_errno);
fprintf(stderr, "procresults.pr_TPCerror = %o\n",
procresults.pr_TPCerror);
fprintf(stderr, "procresults.pr_TPCdetail = %o\n",
procresults.pr_TPCdetail);
fprintf(stderr, "errno = %d\n", errno);
fprintf(stderr, "couldn't spawn: %s\n", buf);
}

/* The parent process waits for the child process to terminate. */


if ( (pid = waitpid(pid, &status, 0)) < 0)
perror("waitpid error");
printf("%% ");
}
exit(0);
}

Note 1
The spawn.h library header file defines the inherit structure, which allows you to specify
the process group ID and signal mask of the new process and a list of signals that the child
process will take default action on.
Note 2
The fd_count and fd_map parameters allow you to control the file descriptors the child
process inherits from the parent. fd_count specifies the number of file descriptors designated
by fd_map. fd_map specifies how the file descriptors in the parent process map to the file
descriptors in the child process. That is, the file descriptor specified in fd_map [0] is copied
to file descriptor 0 (zero) in the child process, and so on.

Using the Guardian API


Using Guardian procedures, you can create and control both OSS and Guardian processes. See
the Guardian Programmer’s Guide for a discussion of the HP signals extension procedures.

Creating and Controlling Guardian Processes


Example 3-6 manages a named Guardian process from the OSS environment by creating it,
suspending it, returning it to a ready state, and terminating it.

Creating and Controlling Processes 115


Example 3-6 Creating and Controlling a Guardian Process Using Guardian Procedures
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dlaunch.h>
#include <zsysc>
#include <cextdecs.h(PROCESS_LAUNCH_, PROCESS_SUSPEND_, \
PROCESS_ACTIVATE_, PROCESS_STOP_)>

/* Initialize input parameter structure to default values. */


process_launch_parms_def proc_param = P_L_DEFAULT_PARMS_;
/* Process results structure. */
zsys_ddl_smsg_proccreate_def proc_results;

char *pname;
short errordetail;
short outlen;
char *proc_name;

int main(int argc, char *argv[]) {


short retcode;
/* If the name of a Guardian program to run is not provided, use a
default program name. */
if(argc > 1)
pname = argv[1];
else
pname = "$system.systools.vols";
proc_name = "$heinz"; /* make the process name unique */

/* Initialize input parameters without default values. */


proc_param.program_name = pname;
proc_param.program_name_len = (short)strlen(pname);
proc_param.process_name = proc_name;
proc_param.process_name_len = (short)strlen(proc_name);
proc_param.name_options = ZSYS_VAL_PCREATOPT_NAMEINCALL;

/* Create a new Guardian process. */


retcode = PROCESS_LAUNCH_ (
&proc_param, /* input parameter list */
&errordetail, /* details of error */
&proc_results, /* output results */
sizeof(proc_results), /* maximum size of output */
&outlen /* actual size of output */
);
/* If unsuccessful, print error message and exit. */
if (retcode != 0) {
fprintf(stderr, "retcode = %d\n", retcode);
fprintf(stderr, "Error detail = %d\n", errordetail);
exit(1);
}
printf("Process %s created successfully\n", proc_name);
sleep(10); /* wait ten seconds */

/* Suspend the child process. */


retcode = PROCESS_SUSPEND_
((short *)&proc_results.z_phandle,
);
if (retcode != 0) {
fprintf(stderr, "Process suspend failure, code = %d\n", retcode);
exit(1);
}
printf("Process %s suspended for 10 seconds\n", proc_name);
sleep(10); /* wait ten seconds */

116 Managing Processes


/* Reactivate the child process. */
retcode = PROCESS_ACTIVATE_
((short *)&proc_results.z_phandle,
);
if (retcode != 0) {
fprintf(stderr, "Process activate failure, code = %d\n",
retcode);
exit(1);
}
printf("Process %s activated for 10 seconds\n", proc_name);
sleep(10); /* wait ten seconds */

/* Terminate the child process. */


retcode = PROCESS_STOP_
((short *)&proc_results.z_phandle,
, /* process specifier */
, /* normal termination option */
, /* completion code */
, /* termination information */
, /* subsystem ID */
, /* text to be sent as part of process
termination system message */
/* message length */
);
if (retcode != 0) {
fprintf(stderr, "Process termination failure, code = %d\n",
retcode);
exit(1);
}
printf("Process %s terminated\n", proc_name);
exit(0);
}

Creating and Controlling OSS Processes


To create and control an OSS process using the Guardian API, you must use the
PROCESS_SPAWN_ procedure. It creates an OSS process and can be called by both Guardian
and OSS processes, although it is most commonly called by Guardian processes, such as monitor
programs, that must manage both Guardian and OSS processes.
When the calling process is a Guardian monitor process pair, the monitor can ensure that an OSS
child process is restarted if it stops. In this way, the OSS child process is considered to be a
persistent process. Writing applications as persistent processes is one way to achieve
application-level fault tolerance.
PROCESS_SPAWN_ also allows you to create an OSS process in a nowait manner, which means
that the PROCESS_SPAWN_ procedure returns as soon as process creation is initiated. The
calling process continues processing while the child process is being created.
The process that calls PROCESS_SPAWN_ is a Guardian parent, regardless of whether it is an
OSS or Guardian process, and it receives process-termination notification through Guardian
system messages instead of the SIGCHLD signal. The parent process reads system messages from
$RECEIVE, which is a special file through which a process receives system messages or messages
from other processes. The created process is not the POSIX child of the created process.

Monitoring OSS Processes Reading Guardian System Messages


A Guardian parent process must monitor an OSS child process by reading Guardian system
messages from $RECEIVE. (An OSS parent process could monitor its child process by reading
Guardian system messages, but it would be very unusual.)

Creating and Controlling Processes 117


When monitoring an OSS child process by reading Guardian system messages, it is important
for the parent process to verify that the child process is still alive after any processor failure
because:
• The parent process does not receive process-termination messages for any unnamed OSS
processes running in a particular processor if that processor fails.
• An OSS process can move to another processor using the tdm_execve() or tdm_execvep()
function. The parent receives a termination message so it can determine that an exec function
took place.
To monitor an OSS process effectively by reading Guardian system messages, a parent process
must do the following:
• Call the MONITORCPUS procedure regularly to be notified of any processor failure.
• If a processor fails, call the PROCESS_GETINFOLIST_ procedure to check on the status of
the OSS child process.
In Example 3-7 (page 119), a Guardian process creates an OSS process using PROCESS_SPAWN_.
The parent process monitors the status of the OSS child process by checking for processor failures
and reading system messages on its $RECEIVE file. If a processor fails, the parent verifies that
the OSS process is still alive by verifying the OSS process ID of the child process is still valid.
This example can run only as a native process because it calls the gfileno() function. A TNS
process must call the fdtogfn() function instead. A native process cannot call fdtogfn().
This example must be compiled in the OSS environment and executed from the Guardian
environment:
1. Compile the program
c89 ossprocess_spawn_.c -Wextensions -Wsystype=guardian
-Wtarget=tns/e -o ossprocess_spawn_
2. Copy the object file to the Guardian environment
3. Run the object file in the Guardian environment
TACL> Run ossprocess_spawn_

118 Managing Processes


Example 3-7 Creating an OSS Process Using PROCESS_SPAWN_
/* Example 3-7 Creating an OSS Process using PROCESS_SPAWN_ */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <spawn.h>
#include <tdmext.h>
#include <zsysc>
#include <cextdecs.h(FILE_OPEN_, FILE_GETINFO_, READX, MONITORCPUS,\
PROCESS_SPAWN_, PROCESS_GETINFOLIST_, FILENAME_TO_PATHNAME_)>

/* Structures for standard I/O file descriptor information */


fdentry_def *fdentry; /* structure pointer for fdentry */
fdinfo_def *fdinfo; /* structure pointer to fdinfo block
with one fdentry */
fdinfo_def fdinit = DEFAULT_FDINFO; /* initialize structure */
/* Structure for inheritance values */
struct inheritance inherit;
/* Set defaults for process spawn input/output structures */
struct process_extension
proc_ext = DEFAULT_PROCESS_EXTENSION;
struct process_extension_results
proc_results = DEFAULT_PROCESS_EXTENSION_RESULTS;

/* Structure used for process termination message */


union {
short msgcode; /* message code */
zsys_ddl_smsg_procdeath_def procdeath;/* termination message format */
} msg;

extern char **environ;


#define FILE_MAX ZSYS_VAL_LEN_FILENAME /* maximum characters in file name */
char *progname; /* Name of program to be executed */
pid_t pid; /* OSS process ID */
char *pargv[4]; /* arguments for program to be run */
short error; /* error code, if any */
char inpath[FILE_MAX]; /* standard input file name */
char outpath[FILE_MAX]; /* standard output file name */
char errpath[FILE_MAX]; /* standard error file name */
char *recvname = "$RECEIVE"; /* $RECEIVE file */
short recvfile; /* file number for $RECEIVE */

/*
* This procedure converts an internal file descriptor to an OSS pathname.
*/

short fd_to_pathname(FILE *fp, char *pathname)


{
short err;
char extfname[FILE_MAX];
short len;
short pathnamelen;
#ifdef D30
err = FILE_GETINFO_((short)fdtogfn((short)fileno(fp)), /*lasterr*/,
#else
err = FILE_GETINFO_((short)gfileno(fp), /*lasterr*/,
#endif
extfname, (short)sizeof(extfname)-1,
&len);
if (err == ENOERR) {
extfname[len] = '\0';
err = FILENAME_TO_PATHNAME_(extfname, len,
pathname, PATH_MAX,
&pathnamelen);
if (err == ENOERR)
pathname[pathnamelen] = '\0';

Creating and Controlling Processes 119


}
return (err);
}

/*
* This procedure returns nonzero if the specified OSS PID identifies
* an existing process. Process handle is retrieved as a test.
*/
int valid_pid(pid_t pid)
{
short err;
short err_detail;
short len;
short phandle[10];
short ret_attr = 48; /* get process handle */
err = PROCESS_GETINFOLIST_(/*cpu*/,/*pin*/,/*node*/,/*nodelen*/,/*phandle*/,
&ret_attr, 1, phandle, (short)sizeof(phandle), &len,
&err_detail, 3 /* get info for PID specified */ ,
/*srchattr*/, /*srchattrcnt*/,
/*srchval*/, /*srchvalcnt*/, pid);
return ( err == 0 );
}

int main(int argc, char *argv[]) {


int i = 1; /* argument counter */
int remote = 0; /* remote = 0 for local command execution */
/* remote = 1 for remote command execution */
char *pathstring; /* search PATH string */
char *progname;

/* If the name of an OSS program is not provided,


use the default program "who" */
if(argc > 1)
progname = argv[1];
else
progname = "who";

/* Get standard file pathnames */


if((error = fd_to_pathname(stdin, inpath)) != ENOERR
|| (error = fd_to_pathname(stdout, outpath)) != ENOERR
|| (error = fd_to_pathname(stderr, errpath)) != ENOERR) {
fprintf(stderr, "Bad file number\n");
exit(1);
}

/* Build the fdinfo structure header */


/* Allocate memory for structure with three fdentry's) */
fdinfo = (fdinfo_def *) malloc(sizeof(fdinit)
+ 2 * sizeof(fdinit.z_fdentry));

/* Copy initialized structure entries into new memory area */


memcpy(fdinfo, &fdinit, sizeof(fdinit));
fdinfo->z_len = sizeof(fdinit); /* size of structure */
fdinfo->z_timeout = -1; /* no timeout to be used */
fdinfo->z_umask = -1; /* use creation mask of caller */
fdinfo->z_cwd = "/tmp"; /* initial working directory */
fdinfo->z_fdcount = 3; /* number of files to be opened */
fdentry = &fdinfo->z_fdentry;
/* Build the fdinfo entry for stdin */
fdentry[0].z_fd = 0; /* file descriptor number */
fdentry[0].z_dupfd = -1; /* no dup of file desc. */
fdentry[0].z_name = inpath; /* standard in file name */
fdentry[0].z_oflag = O_RDONLY; /* open as read only */
fdentry[0].z_mode = 0755; /* file permission mode */
/* Build the fdinfo entry for stdout */
fdentry[1].z_fd = 1;
fdentry[1].z_dupfd = -1;
fdentry[1].z_name = outpath;
fdentry[1].z_oflag = O_WRONLY;
fdentry[1].z_mode = 0755;
/* Build the fdinfo entry for stderr */
fdentry[2].z_fd = 2;

120 Managing Processes


fdentry[2].z_dupfd = -1;
fdentry[2].z_name = errpath;
fdentry[2].z_oflag = O_RDWR;
fdentry[2].z_mode = 0755;
/* Dummy inheritance structure */
inherit.flags = 0;
/* Build program argument list */
pargv[0] = progname;
if(argc <= 2)
pargv[1] = NULL;
else /* copy command arguments */
while(pargv[i] = argv[i+1])
i++;
/* Assign search PATH string based on whether the program/process is
be run on a remote system or a local system */
if(remote)
pathstring = "/E/native/bin:/E/native/usr/bin:/E/native/usr/local/bin";
else
pathstring = "/bin:/usr/bin:/usr/local/bin";

/* Create the new OSS process and run program */


pid = PROCESS_SPAWN_(
progname, /* OSS pathname of program to be run */
fdinfo, /* file descriptor information structure */
pargv, /* pointer to argument strings */
environ, /* pointer to array of addr. of env. values */
&inherit, /* inheritance structure */
sizeof(inherit), /* length of structure */
&proc_ext, /* process extension structure */
&proc_results, /* process results structure */
, /* nowait tag (not used in this example) */
pathstring /* use PATH search string */
);
/* If unsuccessful, print out error message and exit */
if (pid == -1) {
fprintf(stderr, "OSS errno = %d\n", proc_results.pr_errno);
fprintf(stderr, "Guardian error = %d\n", proc_results.pr_TPCerror);
fprintf(stderr, "Error detail = %d\n", proc_results.pr_TPCdetail);
exit(1);
}
/* Wait for death of child process */
MONITORCPUS(-1); /* Request CPU status messages */
if (error = FILE_OPEN_(recvname, (short)strlen(recvname), &recvfile))
exit(1);
/* Read system messages on $RECEIVE */
do {
READX(recvfile, (char *)&msg.msgcode, (short)sizeof(msg));
FILE_GETINFO_(recvfile, &error);
} while (!error
|| error == 6 /* system message */
&& !(msg.msgcode == ZSYS_VAL_SMSG_PROCDEATH /* death message */
&& msg.procdeath.z_osspid == pid /* process ID match */
&& msg.procdeath.z_completion_code
!= ZSYS_VAL_PROCDEATH_CHILDEXEC) /* completion code */
&& !(msg.msgcode == ZSYS_VAL_SMSG_CPUDOWN /* CPU down message check*/
&& !valid_pid(pid))); /* child process ID invalid*/
printf("Child process terminated\n");
exit(0);
}

Querying the Process Environment


The OSS API and the Guardian API both allow you to get information about both OSS and
Guardian processes and their environments.

Using the OSS API


OSS functions provide information about process times (times()), environment variables
(getenv()), user IDs (getuid(), geteuid()), groups and group IDs (getgroups(),
Querying the Process Environment 121
getgid(), getegid()), and system limits (sysconf()) for OSS and Guardian processes.
Because Guardian processes do not have OSS process IDs and cannot belong to process groups,
the getpid(), getppid(), and getpgrp() functions operate only on OSS processes. You can
call sysconf() from a Guardian process, but it is not meaningful to do so.
Example 3-8 gets the system-dependent system limits of a process and sends their values to the
standard output file. The system limits shown in this example are not in the limits.h header
file because they are not available at compile time.

Example 3-8 Getting Information About System Limits Using sysconf()


#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static void pr_sysconf(char *, int);


int main (int argc, char *argv[])
{

/* Retrieve system-dependent system limits. */


pr_sysconf("ARG_MAX =", _SC_ARG_MAX);
pr_sysconf("CHILD_MAX =", _SC_CHILD_MAX);
pr_sysconf("clock ticks/second =", _SC_CLK_TCK);
pr_sysconf("NGROUPS_MAX =", _SC_NGROUPS_MAX);
pr_sysconf("OPEN_MAX =", _SC_OPEN_MAX);
#ifdef _SC_STREAM_MAX
pr_sysconf("STREAM_MAX =", _SC_STREAM_MAX);
#endif
#ifdef _SC_TZNAME_MAX
pr_sysconf("TZNAME_MAX =", _SC_TZNAME_MAX);
#endif
pr_sysconf("_POSIX_JOB_CONTROL =", _SC_JOB_CONTROL);
pr_sysconf("_POSIX_SAVED_IDS =", _SC_SAVED_IDS);
pr_sysconf("_POSIX_VERSION =", _SC_VERSION);
exit(0);
}

/* This function displays system-dependent limits to standard output.*/


static void pr_sysconf(char *mesg, int name)
{
long val;
fputs(mesg, stdout);
errno = 0;
if ( (val = sysconf(name)) < 0) {
if (errno != 0) {
printf("sysconf error\n"); /* not a valid constant name */
exit(1);
}
fputs(" (not defined)\n", stdout); /* value is indeterminate */
} else
printf(" %ld\n", val);
}

Using the Guardian API


The Guardian procedures that provide information about OSS processes as well as Guardian
processes are PROCESS_GETINFO_ and PROCESS_GETINFOLIST_.
The PROCESS_GETINFO_ procedure returns a limited set of information about a specified
process, including the process handle, execution priority, home terminal, type (OSS or Guardian),
swap file and program file statistics, and the OSS process ID if it is an OSS process.

122 Managing Processes


The PROCESS_GETINFOLIST_ procedure returns detailed information about a process or set
of processes that meets specified criteria. These criteria identify processes for which information
is returned.
Example 3-9 (page 124) gets information about an OSS or Guardian process by obtaining the
process handle for the process and then passing the process handle to PROCESS_GETINFO_. If
no process name is provided from the command line, information about the current process is
retrieved and printed.

Querying the Process Environment 123


Example 3-9 Getting Information About a Process Using PROCESS_GETINFO_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <cextdecs.h(FILENAME_TO_PROCESSHANDLE_,\
PROCESS_GETINFO_,PROCESSHANDLE_GETMINE_)>

short processhandle[10];
short mom_processhandle[10];
short gmom_processhandle[10];
short fnlen, priority, htlen, caid, paid, jobid, proglen, swaplen;
short errordetail;
long long proc_time;
char proc_fname[64];
char hometerm[64];
char programfile[64];
char swapfile[64];
short proctype;
long osspid;

int main(int argc, char *argv[]) {


short retcode;

/* Get the process name from the command line. If not supplied, use the
current process. Use the process name to get the process handle. */
if(argc > 1) {
retcode = FILENAME_TO_PROCESSHANDLE_(
argv[1], /* process filename */
(short) strlen(argv[1]), /* length of process filename */
processhandle /* process handle */
);
if(retcode != 0) {
fprintf(stderr, "Invalid process name %s\n", argv[1]);
exit(1);
}
} else {
printf("Using current process\n");
retcode = PROCESSHANDLE_GETMINE_(processhandle);
if (retcode != 0) {
fprintf(stderr, "Can't get current process handle\n");
exit(1);
}
}

/* Get process information and print the values. */


retcode = PROCESS_GETINFO_(
processhandle, /* process handle */
proc_fname, /* process filename */
64, /* maximum length */
&fnlen, /* length of filename */
&priority, /* current execution priority */
mom_processhandle, /* process handle of MOM process */
hometerm, /* home terminal */
64, /* maximum length */
&htlen, /* length of hometerm name */
&proc_time, /* execution time in usec */
&caid, /* creator access ID */
&paid, /* process access ID */
gmom_processhandle, /* process handle of GMOM */
&jobid, /* job ID */
programfile, /* program filename */
64, /* maximum length */
&proglen, /* length of program filename */

124 Managing Processes


swapfile, /* swap filename */
64, /* maximum length */
&swaplen, /* length of swap filename */
&errordetail, /* details of any errors */
&proctype, /* process type (1=OSS,0=Guardian) */
&osspid /* OSS process ID, if type=1 */
);

/* If unsuccessful, print error message and exit. */


if (retcode != 0) {
fprintf(stderr, "retcode = %d\n", retcode);
fprintf(stderr, "Failure details = %d\n",errordetail);
exit(1);
}
printf("Process filename = %s\n", proc_fname);
printf("Process priority = %d\n", priority);
printf("Home terminal = %s\n", hometerm);
printf("Process execution time = %ld microseconds\n", proc_time);
printf("CAID = %d, PAID = %d\n", caid, paid);
printf("Job ID = %d\n", jobid);
printf("Program filename = %s\n", programfile);
printf("Swap filename = %s\n", swapfile);
if(proctype == 1)
printf("OSS process ID = %d\n", osspid);
exit(0);
}
Example 3-10 gets information about an OSS process by passing the OSS process ID to
PROCESS_GETINFOLIST_. If no OSS process ID is provided from the command line, the OSS
process ID of the current process is obtained. Process information is returned in the values_list
buffer and printed.

Querying the Process Environment 125


Example 3-10 Getting Information About a Process Using PROCESS_GETINFOLIST_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <cextdecs.h(PROCESS_GETINFOLIST_)>

short processhandle[10];
short attr_list[] = { /* list of attributes for which values are
to be returned */
21, /* real group ID */
22, /* real user ID */
80, /* effective group ID */
23, /* effective user ID */
90, /* OSS process ID */
94, /* OSS parent process ID */
26, /* OSS session leader ID */
98, /* OSS group leader PID */
27, /* OSS controlling terminal */
111, /* current size of native heap area */
112, /* maximum size of native heap area */
31, /* wait state */
32, /* process state */
48 /* process handle */
};
short attr_count; /* number of attributes */
short values_list[8000]; /* buffer of return values */
short values_len; /* size of return values information*/
short errordetail; /* additional error information */
short srch_option; /* search option */
short srch_attr_list[] = { 28 }; /* attribute code specifying search
criteria. 28 is process type (OSS
or Guardian). */
short srch_attr_count; /* number of search criteria */
short srch_values_list[1024]; /* buffer of return values */
short srch_values_len; /* size of return values */
char ctty[100]; /* controlling terminal */
pid_t osspid; /* OSS process ID */

int main(int argc, char *argv[]) {


int i, nbytes;
short retcode;

/* Get information for the process specified by the OSS process ID. */
if(argc > 1) {
osspid = atoi(argv[1]);
} else
osspid = getpid();
attr_count = (short)(sizeof(attr_list)/sizeof(short));
srch_option = 3; /* return info for process whose
OSS process ID is specified */
retcode = PROCESS_GETINFOLIST_(
, /* processor */
, /* process ident number (PIN) */
, /* node name */
, /* length of node name */
, /* process handle */
attr_list, /* attribute list to be returned */
attr_count, /* number of attributes */
values_list, /* list of output values */
1024, /* maximum number of values */
&values_len, /* length of list returned */
&errordetail, /* details of any errors */

126 Managing Processes


srch_option, /* search for OSS process */
, /* attribute codes used in search */
, /* number of attributes used */
, /* match values found */
, /* length of list returned */
osspid /* OSS process ID */
);

/* If unsuccessful, print error message and exit. */


if (retcode != 0) {
fprintf(stderr, "retcode = %d\n", retcode);
fprintf(stderr, "Failure details = %d\n",errordetail);
exit(1);
}

printf("Printing selected process attributes:\n\n");


i = 0; /* start at beginning of the buffer printing out
the values of process attributes returned */
printf("Real group ID = %d\n", (*(gid_t*)(&values_list[i])));
i += (sizeof(gid_t)/sizeof(short));
printf("Real user ID = %d\n", (*(uid_t*)(&values_list[i])));
i += (sizeof(uid_t)/sizeof(short));
printf("Effective group ID = %d\n", (*(gid_t*)(&values_list[i])));
i += (sizeof(gid_t)/sizeof(short));
printf("Effective user ID = %d\n", (*(uid_t*)(&values_list[i])));
i += (sizeof(uid_t)/sizeof(short));
printf("OSS process ID = %d\n", (*(pid_t*)(&values_list[i])));
i += (sizeof(pid_t)/sizeof(short));
printf("Parent process ID = %d\n", (*(pid_t*)(&values_list[i])));
i += (sizeof(pid_t)/sizeof(short));
printf("Session leader = %d\n", (*(pid_t*)(&values_list[i])));
i += (sizeof(pid_t)/sizeof(short));
printf("Group leader = %d\n", (*(pid_t*)(&values_list[i])));
i += (sizeof(pid_t)/sizeof(short));
nbytes = values_list[i++];
strncpy(ctty, (char *)&values_list[i], nbytes);
printf("Control tty = %s\n", ctty);
i += (nbytes+1)/(sizeof(short));
printf("Current size of native heap area = %d bytes\n", values_list[i]);
i += 2; /* 2 short's */
printf("Maximum size of native heap area = %d bytes\n", values_list[i]);
i += 2; /* 2 short's */
printf("Process wait state = %o\n", values_list[i++]);
printf("Process state = %o\n", values_list[i++]);
printf("Process handle = %o,%o,%o,%o,%o\n",
values_list[i],
values_list[i+1],
values_list[i+2],
values_list[i+3],
values_list[i+4]);
exit(0);
}

Modifying the Process Environment


The OSS API and the Guardian API both allow you to modify characteristics about both OSS
and Guardian processes and their environments.

Using the OSS API


OSS functions can change information about process environment variables (putenv()), user
IDs (setuid()), and group IDs (setgid()) for OSS and Guardian processes. Because Guardian

Modifying the Process Environment 127


processes do not have OSS process IDs and cannot belong to process groups or sessions, the
setsid() and setpgid() functions operate only on OSS processes.
Example 3-11 sets the user ID of the current process to the user ID of the user whose name is
supplied at the command line. This program must be run using the super ID.

Example 3-11 Setting the User ID of the Current Process Using setuid()
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>

int main(int argc, char *argv[])


{

uid_t uid;
struct passwd *pp;
int retcode;

/* Read the name of the user from the command line.


If the user name is not valid, print an error message and exit.
If the user name is not provided, print a usage message and exit. */
if(argc > 1) {
pp = getpwnam(argv[1]);
if (!pp) {
fprintf(stderr, "Unknown user name\n" );
exit (1);
}
} else {
fprintf(stderr, "Usage: procinf2 user name\n" );
exit (1);
}

/* Set user ID to ID of user name entered at the command line. */


uid = pp->pw_uid;

/* Print user ID before and after changing it. */


printf("Current UID = %d\n", getuid());
retcode = setuid(uid);
printf("New UID = %d\n", getuid());
if(retcode != 0) {
fprintf(stderr, "Can't set UID to %d\n", uid);
exit(1);
} else
exit(0);
}

Using the Guardian API


The PROCESS_SETINFO_ and PROCESS_SETSTRINGINFO_ procedures allow you to change
information about OSS as well as Guardian processes. PROCESS_SETINFO_ operates on integer
process attributes, and PROCESS_SETSTRINGINFO_ operates on string attributes.
Example 3-12 (page 129) changes the execution priority of the current process using
PROCESS_SETINFO_ and sets the home terminal to a new window using
PROCESS_SETSTRINGINFO_.

128 Managing Processes


Example 3-12 Modifying Information About the Current Process Using PROCESS_SETINFO_ and
PROCESS_SETSTRINGINFO_
/* Modifying info about the current process using PROCESS_SETINFO_ and */
/* PROCESS_SETSTRINGINFO_ (works on H-series RVUs only) */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cextdecs.h(PROCESS_SETINFO_,PROCESS_SETSTRINGINFO_)>

short priority = 150;


short oldpriority, oldvaluelen;
char *hometerm;

int main(int argc, char *argv[]) {


short retcode;

/* Get name of home terminal from command line.


If none provided, use default setting. */
if (argc > 1)
hometerm = argv[1];
else
#ifdef _TNS_E_TARGET
hometerm = "$ZTNT.#PTY00D4" ; /* Note 1 */
#else
hometerm = "$ZTN0.#PTY00D4" ; /* Note 1 */
#endif
/* Set process execution priority to a specified value. */
retcode = PROCESS_SETINFO_(
, /* process handle of current process */
, /* process specifier */
(short)42, /* current priority attribute code */
&priority, /* priority value */
(short)1, /* length of value (short) */
&oldpriority, /* returned value of priority */
(short)1,
&oldvaluelen /* length of returned value */
);

/* If unsuccessful, print error message and exit. */


if (retcode != 0) {
fprintf(stderr, "retcode = %d\n", retcode);
exit(1);
}
printf("Current process priority set to %d\n", priority);
/* Set process home terminal to new value. */
retcode = PROCESS_SETSTRINGINFO_(
, /* process handle of current process */
, /* process specifier */
5, /* home terminal attribute code */
hometerm, /* new home terminal string value */
(short)strlen(hometerm), /* length of string */
);

/* If unsuccessful, print error message and exit. */


if (retcode != 0) {
fprintf(stderr, "retcode = %d\n", retcode);
exit(1);
}
printf("Home terminal set to %s\n", hometerm);
exit(0);
}

Modifying the Process Environment 129


Note 1
You can get the name of a terminal using the ttyname() function or the tty command.
OSS terminal names are in the format /G/ztnt/#pty00nn. The PROCESS_SETINFO_
procedure requires the Guardian form of a terminal name, which is in the format:
• $ZTN0.#PTY00xx for systems running G-series RVUs.
• $ZTNT.#PTY00xx for systems running H-series RVUs.
To convert from an OSS pathname format to a Guardian filename format, use the
PATHNAME_TO_FILENAME_ procedure.

Performance Considerations
You can improve the performance of your applications with respect to process management by
following these recommendations:
• Minimize the use of the process-creation functions. There is a lot of system overhead involved
in creating processes, so use static server and demon processes whenever possible. Create
a process and do not terminate it until the program no longer needs it.
• Distribute the workload across processors. Specify the processor using the HP extension
functions when creating a process.
• Create processes in one step instead of two. Use the tdm_spawn() or tdm_spawnp()
function instead of calling the fork() or tdm_fork() function followed by one of the
exec or tdm_exec set of functions.
The following subsections illustrate these performance considerations and actions:
• “Using Dynamic Servers Spread Across Available Processors” (page 130)
• “Using Static Servers Spread Across Available Processors” (page 134)

Using Dynamic Servers Spread Across Available Processors


In contrast, Example 3-13 (page 132) offers a more flexible solution to the programs in the sample
application of Example 3-1 (page 99) and Example 3-2 (page 102). This new program uses the
tdm_spawn() function, instead of one of the fork() calls and the execv() call, to allow for
scalability to other processors and for slightly better process-creation performance.
The launcher program in Example 3-13 is compiled as a linked program file named dlaunch2.
The dynamic server program in Example 3-2 is compiled as a linked program file named dserver.
(A requester program, shown in Example 6-2 (page 171), is also compiled as a linked program
file named requester2.) All programs are secured for execution in the current working directory.
In this application, dlaunch2 creates an AF_INET socket and listens for incoming connections
from one or more copies of requester2. Upon receipt of a connection, dlaunch2 starts dserver
in another available processor, using a tdm_spawn() call. dlaunch2 closes the file descriptors
associated with its requester2 connection. dserver, which has inherited file descriptors for
the requester2 connection, handles all work associated with the connection.
Using two terminal sessions, sample dialog for the terminal launching dlaunch2 might be:
/users/chris: ./dlaunch2
dlaunch2 starting in cpu 2
dserver spawn'ed in cpu 0
dserver [cpu 0] - starting
dserver [cpu 0] - message received on fd 0 = hello 1
dserver [cpu 0] - message received on fd 0 = goodbye 1
dserver [cpu 0] - stopping [input closed]
dserver spawn'ed in cpu 1
dserver [cpu 1] - starting
dserver [cpu 1] - message received on fd 0 = hello 2
dserver [cpu 1] - message received on fd 0 = goodbye 2
dserver [cpu 1] - stopping [input closed]
dlaunch2 stopping - timeout

130 Managing Processes


while the terminal running the copy of requester2 might show:
/users/chris: ./requester2
Requester starting
?hello 1
Read 8 bytes back from server
?goodbye 1
Read 10 bytes back from server
?/users/chris: ./requester2
Requester starting
?hello 2
Read 8 bytes back from server
?goodbye 2
Read 10 bytes back from server
?
/users/chris:

Performance Considerations 131


Example 3-13 Dynamic Launcher Program to Spawn Dynamic Server
/* dlaunch2.c
*
* Simple OSS example using OSS socket APIs for communication
* between requester and server.
*
* dlaunch2 (dynamic launcher 2) is an inetd-like program which
* accepts socket connections and spawn's a dserver process for
* each connection.
*
* dserver reads stdin and echoes to stdout. dlaunch2 and dserver
* write progress messages and error messages to stderr.
*
* dlaunch2 starts the dserver processes run on different cpus.
*/

#define _XOPEN_SOURCE_EXTENDED 1 /* needed for OSS sockets */

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <netinet/in.h>

#include <tdmext.h>

/* Guardian APIs */
#include <cextdecs.h(PROCESSHANDLE_GETMINE_, \
PROCESSHANDLE_DECOMPOSE_, \
PROCESSORSTATUS)>

short cpucount; /* cpucount - # cpu in system */


short cpuindex; /* cpuindex - current cpu for dserver */
short cpumask; /* cpumask - bit mask of available cpus /*
short cpu, phandle[10]; /* our cpu and process handle */
int newpid, fd, listenfd; /* process id, file descriptor,
* listening fd */
int readycount, bytesread; /* ready fd count, recv byte count */
struct sockaddr_in addr; /* socket address (family,addr,port) */
struct timeval timeval; /* timeout structure for select() call */
fd_set fdset; /* set of fds for select() call */
#define IDLE_PERIOD 180 /* 180 second timeout value */
extern char *environ[];
static char *childargv[] = {"dserver", NULL};
struct inheritance inherit;
struct process_extension peparm = DEFAULT_PROCESS_EXTENSION;
struct process_extension_results perslt =
DEFAULT_PROCESS_EXTENSION_RESULTS;

int main(int argc, char **argv)


{
/* get system cpu config */
cpumask = (short) PROCESSORSTATUS();
cpucount = (short) (PROCESSORSTATUS() >> 16);
cpuindex = -1;

/* get process handle and cpu number */


PROCESSHANDLE_GETMINE_(phandle);
PROCESSHANDLE_DECOMPOSE_(phandle, &cpu);

/* print startup message */


fprintf(stderr, "dlaunch2 starting in cpu %d\n", cpu);

/* create AF_INET stream socket */


if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{

132 Managing Processes


fprintf(stderr, "socket() call failed [errno %d]\n", errno);
exit(1);
}

/* Get server port from the command line or use default 12345 */
if (argc > 1)
addr.sin_port = (short)atoi(argv[1]); /* use command line arg */
else
addr.sin_port = 12345; /* use default */

addr.sin_family = AF_INET; /* internet address family */


addr.sin_addr.s_addr = gethostid(); /* assume server on our host */

/* bind socket to address */


if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0)
{
fprintf(stderr, "bind() call failed [errno %d]\n", errno);
exit(1);
}

/* make the socket a listening socket */


if (listen(fd, 5) < 0)
{
fprintf(stderr, "listen() call failed [errno %d]\n", errno);
exit(1);
}

/* fd usage
* 0 stdin - not used by dlaunch2, set up for dserver
* 1 stdout - not used by dlaunch2, set up for dserver
* 2 stderr - used by dlaunch2 for messages,
* inherited by dserver
* 3 listenfd - used by dlaunch2 for connections,
* not inherited by dserver
*/

close(STDIN_FILENO);
close(STDOUT_FILENO);
listenfd = fd;
fcntl(listenfd, F_SETFD, FD_CLOEXEC); /* don't propagate fd to children */
FD_ZERO(&fdset);

/* loop until error or timeout */


while (1)
{
/* initialize timeout and bitmask for select() call */
timeval.tv_sec = IDLE_PERIOD;
timeval.tv_usec = 0;
FD_SET(listenfd, &fdset);
readycount = select(listenfd+1, &fdset, NULL, NULL, &timeval);

/* if timeout then exit */


if (readycount == 0)
{
fprintf(stderr, "dlaunch2 stopping - timeout\n");
exit(0);
}

/* accept new connection */


if ((fd = accept(listenfd,(struct sockaddr *)NULL,
(size_t *)NULL)) < 0)
{
fprintf(stderr, "accept() call failed [errno %d]\n", errno);
exit(1);
}

/* setup stdin and stdout */


dup2(fd,STDIN_FILENO); /* fd is already STDIN_FILENO */
dup2(fd,STDOUT_FILENO); /* setup stdout */

/* launch a dserver process to handle the connection */


/* note - spawn is an expensive operation and is more */

Performance Considerations 133


/* flexible than exec */

/* find next available cpu */


do {
cpuindex = (++cpuindex == cpucount) ? 0 : cpuindex;
} while (((cpumask >> (15-cpuindex)) & 1) == 0);

peparm.pe_cpu = cpuindex;
inherit.flags = 0;

if ((newpid = fork()) < 0)


{
fprintf(stderr, "fork() failed [errno %d]\n", errno);
exit(1);
}
else if (newpid == 0)
{
/* we are child ... spawn grandchild to avoid zombie processes */
tdm_spawn(childargv[0], 0, NULL, &inherit,
childargv, environ, &peparm, &perslt);
exit(0); /* child goes away */
}
else
{
/* we are parent */
fprintf(stderr, "dserver spawn'ed in cpu %d\n", peparm.pe_cpu);
wait(&newpid); /* wait for child to avoid zombie child process */
close(STDIN_FILENO);
close(STDOUT_FILENO);
}
} /* end while (1) */
}

Using Static Servers Spread Across Available Processors


Example 3-13 can be further optimized as a launcher for iterative static servers, as shown in
Example 3-14 (page 135). This program uses AF_UNIX sockets and launches a static server in each
processor as soon as it starts; that provides maximum scalability immediately and slightly better
responsiveness by eliminating the process-creation delay when handling each new connection.
The server program in Example 3-14 is compiled as a linked program file named slaunch1.
The server program in Example 3-15 is compiled as a linked program file named sserver. (A
requester program, shown in Example 6-2 (page 171), is also compiled as a linked program file
named requester2.) All programs are secured for execution in the current working directory.
In this application, slaunch1 creates an AF_INET socket and listens for incoming connections
from one or more copies of requester2. It then starts a copy of sserver in each available
processor.

134 Managing Processes


Example 3-14 Launcher Program to Spawn Static Servers
/*slaunch1.c

* Simple OSS example using OSS sockets APIs for communication


* between requester and server.
*
* slaunch1 (static launcher 1) is an inetd-like program which
* starts an sserver (static server) process on each available cpu
* and then passes each incoming socket connection to a sserver process.
*
* slaunch1 and sserver write progress messages and error messages
* to stderr.
*/

#define _XOPEN_SOURCE_EXTENDED 1 /* needed for OSS sockets */

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netdb.h>

#include <tdmext.h>

/* Guardian APIs */
#include <cextdecs.h(PROCESSHANDLE_GETMINE_, \
PROCESSHANDLE_DECOMPOSE_, \
PROCESSORSTATUS)>

short cpucount; /* cpucount - # cpu in system */


short cpuindex; /* cpuindex - current cpu for sserver */
short cpumask; /* cpumask - bit mask of available cpus */
short cpu, phandle[10]; /* our cpu and process handle */
int pairfd[2]; /* socketpair fd values */
int serverfd[16]; /* server fd indexed by cpu number */
int newpid, fd, listenfd; /* process id, file descriptor, listening fd */
int readycount, bytesread; /* ready fd count, recv byte count */
struct sockaddr_in addr; /* socket address (family,addr,port) */
struct timeval timeval; /* timeout structure for select() call */
fd_set fdset; /* set of fds for select() call */
struct msghdr fdmsghdr; /* msghdr for sendmsg() call */
struct iovec iov[1]; /* io vector for sendmsg() call */
struct { /* ancillary data for sendmsg() call */
struct cmsghdr fdcmsghdr;/* ancillary data header */
int fd; /* ancillary data (one fd) */
} fdadata;

#define IDLE_PERIOD 180 /* 180 second timeout value */

extern char *environ[];


static char *childargv[] = {"sserver", NULL};

struct inheritance inherit;


struct process_extension peparm = DEFAULT_PROCESS_EXTENSION;
struct process_extension_results perslt = DEFAULT_PROCESS_EXTENSION_RESULTS;

int main(int argc, char **argv)


{
/* get system cpu config */
cpumask = (short) PROCESSORSTATUS();
cpucount = (short) (PROCESSORSTATUS() >> 16);
cpuindex = -1;

Performance Considerations 135


/* get process handle and cpu number */
PROCESSHANDLE_GETMINE_(phandle);
PROCESSHANDLE_DECOMPOSE_(phandle, &cpu);

/* print startup message */


fprintf(stderr, "slaunch1 starting in cpu %d\n", cpu);

/* create AF_INET stream socket */


if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "socket() call failed [errno %d]\n", errno);
exit(1);
}

/* Get server port from the command line or use default 12345 */
if (argc > 1)
addr.sin_port = (short)atoi(argv[1]); /* use command line arg */
else
addr.sin_port = 12345; /* use default */

addr.sin_family = AF_INET; /* internet address family */


addr.sin_addr.s_addr = gethostid(); /* assume server on our host */

/* bind socket to address */


if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0)
{
fprintf(stderr, "bind() call failed [errno %d]\n", errno);
exit(1);
}

/* make the socket a listening socket */


if (listen(fd, 5) < 0)
{
fprintf(stderr, "listen() call failed [errno %d]\n", errno);
exit(1);
}

listenfd = fd;
fcntl(listenfd, F_SETFD, FD_CLOEXEC); /* don't propagate fd on spawn */
FD_ZERO(&fdset);

/* fd usage
* 2 stderr - used by slaunch1 for messages,
* inherited by sserver
* 3 listenfd - used by slaunch1 for connections, not inherited by sserver
* y fd - accepted connection, passed to sserver and closed
* x serverfd[cpu] - slaunch1 fd corresponding to sserver stdin
*/

/* spawn a static server on each available cpu */


for (cpuindex = 0; cpuindex < cpucount; cpuindex++)
{
if ((cpumask >> (15-cpuindex)) & 1)
{
/* use AF_UNIX socket pair for slaunch1/sserver fd passing */
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pairfd) < 0)
{
fprintf(stderr, "socketpair() call failed [errno %d]\n",
errno);
exit(1);
}

/* setup stdin and stdout */


dup2(pairfd[1],STDIN_FILENO); /* setup server stdin */
dup2(pairfd[1],STDOUT_FILENO); /* setup server stdout */
close(pairfd[1]);
serverfd[cpuindex] = pairfd[0];
fcntl(pairfd[0], F_SETFD, FD_CLOEXEC); /* don't propagate fd on spawn */

inherit.flags = 0;
peparm.pe_cpu = cpuindex;

136 Managing Processes


fprintf(stderr,
"sserver spawn'ed in cpu %d\n", peparm.pe_cpu);
if ((newpid = fork()) < 0)
{
fprintf(stderr, "fork() failed [errno %d]\n", errno);
exit(1);
}
else if (newpid == 0)
{
/* we are child ... spawn grandchild to avoid zombie processes */
if (tdm_spawn(childargv[0], 0, NULL, &inherit,
childargv, environ, &peparm, &perslt) < 0)
{
fprintf(stderr,
"tdm_spawn() to cpu %d failed [errno %d]\n",
cpuindex, errno);
}
exit(0); /* child goes away */
}
else
{
/* we are parent */
wait(&newpid); /* wait for child to avoid zombie child process */
}
}
}

close(STDIN_FILENO);
close(STDOUT_FILENO);
cpuindex = 0;

/* prepare fd passing message */


fdmsghdr.msg_name = NULL;
fdmsghdr.msg_namelen = 0;

fdmsghdr.msg_iov = iov;
fdmsghdr.msg_iovlen = 1;
iov[0].iov_base = &cpuindex; /* sent but not used */
iov[0].iov_len = sizeof(cpuindex);

fdmsghdr.msg_control = &fdadata;
fdmsghdr.msg_controllen = sizeof(fdadata);
fdadata.fdcmsghdr.cmsg_len = sizeof(fdadata);
fdadata.fdcmsghdr.cmsg_level = SOL_SOCKET;
fdadata.fdcmsghdr.cmsg_type = SCM_RIGHTS;
fdadata.fd = -1; /* set prior to each
* sendmsg() call */

/* loop until error or timeout */


while (1)
{
/* initialize timeout and bitmask for select() call */
timeval.tv_sec = IDLE_PERIOD;
timeval.tv_usec = 0;
FD_SET(listenfd, &fdset);
readycount = select(listenfd+1, &fdset, NULL, NULL, &timeval);

/* if timeout then exit */


if (readycount == 0)
{
fprintf(stderr, "slaunch1 stopping - timeout\n");
exit(0);
}

/* accept new connection */


if ((fd = accept(listenfd,(struct sockaddr *)NULL,
(size_t *)NULL)) < 0)
{
fprintf(stderr, "accept() call failed [errno %d]\n", errno);
exit(1);
}

Performance Considerations 137


/* find next available server */
do {
cpuindex = (++cpuindex == cpucount) ? 0 : cpuindex;
} while ((cpumask >> (15-cpuindex)) & 1 == 0);

/* pass socket fd to next available server */


fdadata.fd = fd;
if (sendmsg(serverfd[cpuindex], &fdmsghdr, 0) < 0)
{
fprintf(stderr, "sendmsg() call failed [errno %d]\n", errno);
exit(1);
}
close(fd);
} /* end while (1) */
}
slaunch1 creates an AF_UNIX socket pair to use for interprocess communication with each of
its servers. (Note that slaunch1 fails if the OSS local sockets server has not been started on your
node.)
slaunch1 uses fork() to create a duplicate of itself for each available processor, and then starts
a copy of sserver in that processor using a tdm_spawn() call. slaunch1 closes unneeded
file descriptors and then passes the file descriptor of a requester2 session that needs service
to the next available copy of sserver, cycling among all of the copies and spreading the workload
across all processors.
Each copy of sserver inherits an AF_UNIX socket to receive the file descriptor of a requester2
process connection and handles all work associated with that connection. Note that sserver is
an iterative static server, like the program in Example 6-1 (page 168), and handles multiple
requestors.
The sserver process runs continuously in the background until it is idle for an arbitrary length
of time. sserver could easily be modified to run until killed by an operator.
Using two terminal sessions, sample dialog for the terminal launching slaunch1 might be:
/users/chris: ./slaunch1
slaunch1 starting in cpu 1
sserver spawn'ed in cpu 0
sserver [cpu 0] - starting
sserver spawn'ed in cpu 1
sserver [cpu 1] - starting
sserver spawn'ed in cpu 2
sserver [cpu 2] - starting
sserver spawn'ed in cpu 3
sserver [cpu 3] - starting
sserver [cpu 1] - new connection on fd 3
sserver [cpu 1] - message received on fd 3 = hello
sserver [cpu 1] - connection on fd 3 closed
sserver [cpu 2] - new connection on fd 3
sserver [cpu 2] - message received on fd 3 = hello from another requester
sserver [cpu 2] - connection on fd 3 closed
while the terminal running the copy of requester2 might show:
/users/chris: ./requester2
Requester starting
?hello
Read 7 bytes back from server
?
/users/chris: ./requester2
Requester starting
?hello from another requester
Read 29 bytes back from server
?
/users/chris:

138 Managing Processes


Example 3-15 Static Echo Server
/* sserver.c
*
* Simple OSS server example using OSS APIs for communication
* between requester and server.
*
* sserver is a static echo server. A sserver process is launched
* for each cpu with stdin being used for fd passing from slaunch
* to sserver. When an fd is passed to sserver, it adds it to an
* fdset and then echoes the input on that connection.
*/

#define _XOPEN_SOURCE_EXTENDED 1 /* needed for OSS sockets */

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netdb.h>

#include <tdmext.h>

/* Guardian APIs */
#include <cextdecs.h(PROCESSHANDLE_GETMINE_, \
PROCESSHANDLE_DECOMPOSE_, PROCESSORSTATUS)>

short cpu, phandle[10]; /* our cpu and process handle */


int fd, fdpassfd, newfd, highfd, fdcount, readycount, bytesread;
struct sockaddr_in addr; /* socket address (family,addr,port) */
struct timeval timeval; /* timeout structure for select() call */
fd_set fdset, rdset; /* set of fds, set of fds ready for reading */
struct msghdr fdmsghdr; /* msghdr for recvmsg() call */
struct iovec iov[1]; /* io vector for recvmsg() call */
struct { /* ancillary data for recvmsg() call */
struct cmsghdr fdcmsghdr;/* ancillary data header */
int fd; /* ancillary data (one fd) */
} fdadata;
#define IDLE_PERIOD 60 /* 60 seconds for timeout */
#define BUFF_LEN 1024 /* buffer size */
char msg_buff[BUFF_LEN+1]; /* single buffer is enough for all connections */

int main(int argc, char **argv)


{
/* get process handle and cpu number */
PROCESSHANDLE_GETMINE_(phandle);
PROCESSHANDLE_DECOMPOSE_(phandle, &cpu);

/* print startup message */


fprintf(stderr, "sserver [cpu %d] - starting\n", cpu);

fdcount = 1;
highfd = STDIN_FILENO;
fdpassfd = STDIN_FILENO;

FD_ZERO(&fdset);
FD_SET(fdpassfd, &fdset); /* initially fdset has only one active fd */

/* prepare fd passing message */


fdmsghdr.msg_name = NULL;
fdmsghdr.msg_namelen = 0;

fdmsghdr.msg_iov = iov;

Performance Considerations 139


fdmsghdr.msg_iovlen = 1;
iov[0].iov_base = msg_buff; /* data ignored when passing fd */
iov[0].iov_len = sizeof(msg_buff);

fdmsghdr.msg_control = &fdadata;
fdmsghdr.msg_controllen = sizeof(fdadata);
fdadata.fdcmsghdr.cmsg_len = sizeof(fdadata);
fdadata.fdcmsghdr.cmsg_level = SOL_SOCKET;
fdadata.fdcmsghdr.cmsg_type = SCM_RIGHTS;
fdadata.fd = -1; /* set by each recvmsg() call */

/* Find a ready socket ... */


while (1)
{
/* initialize timeout and bitmask for select() call */
timeval.tv_sec = IDLE_PERIOD;
timeval.tv_usec = 0;
memcpy(&rdset, &fdset, sizeof(fdset));
readycount = select(highfd+1, &rdset, NULL, NULL, &timeval);

/* if timeout then exit */


if (readycount == 0)
{
fprintf(stderr, "sserver [cpu %d] - "
"stopping [timeout]\n",
cpu);
exit(0);
}

/* find first fd that was marked ready for reading */


for (fd = 0; !FD_ISSET(fd, &rdset); fd++)
{
; /* for loop does all the work */
}

/* if ready fd is the fd passing socket, accept new fd */


if (fd == fdpassfd)
{
if ((bytesread = recvmsg(fd, &fdmsghdr, 0)) < 0)
{
fprintf(stderr, "sserver [cpu %d] - "
"recvmsg(fd %d) failed [errno %d]\n",
cpu, fd, errno);
exit(1);
}
else if (bytesread == 0)
{
fprintf(stderr, "sserver [cpu %d] - "
"stopping [stdin unexpectedly closed]\n",
cpu);
exit(1);
}

/* add fd to set of active fds */


newfd = fdadata.fd;
FD_SET(newfd, &fdset);
fdcount++;
if (newfd > highfd)
highfd = newfd;
fprintf(stderr, "sserver [cpu %d] - "
"new connection on fd %d\n",
cpu, newfd);
}
else /* else ready fd is an existing connected socket */
{
/* read data from connected socket which is ready
* for reading */
if ((bytesread = recv(fd, msg_buff, BUFF_LEN, 0)) < 0)
{
fprintf(stderr, "sserver [cpu %d] - "
"recv(fd %d) failed [errno %d]\n",
cpu, fd, errno);

140 Managing Processes


exit(1);
}
else if (bytesread == 0) /* peer closed connection */
{
/* close socket and remove fd from active fd set */
fprintf(stderr, "sserver [cpu %d] - "
"connection on fd %d closed\n",
cpu, fd);
close(fd);
FD_CLR(fd,&fdset);
fdcount--;
}
else /* data received */
{
msg_buff[bytesread] = '\0'; /* make string NULL-terminated */
fprintf(stderr, "sserver [cpu %d] - "
"message received on fd %d = %s",
cpu, fd, msg_buff);
/* echo back to sender */
if (send(fd, msg_buff, bytesread, 0) < 0)
{
fprintf(stderr, "sserver [cpu %d] - "
"send(fd %d) failed [errno %d]\n",
cpu, fd, errno);
exit(1);
}
}
} /* end handle ready fd */
} /* end while (1) */
}

OSS Process-Management Functions


Table 3-4 (page 141) displays information about each OSS function that you can use to manage
processes. The columns of the table contain the following information:
OSS Function
The name of the function and a brief description.
OSS Notes
Notes about the OSS implementation of the function. The note “Can return extended errors”
means that the function can return errors that are HP extensions to the XPG4 specification.
Refer to the function’s reference page for further information.
Guardian Notes
Notes about using the function on a Guardian process.
The information in this table is only a summary of the information in the reference page for a
function. For details, refer to the reference pages either online or in the Open System Services
System Calls Reference Manual and the Open System Services Library Calls Reference Manual.

NOTE: To determine which RVUs support an OSS function, see Appendix A (page 389).
Table 3-4 OSS Process-Management Functions
OSS Function OSS Notes Guardian Notes

abort() Calls the Guardian ABEND procedure


Generates a software signal to when called from a Guardian TNS
terminate the calling process. process.

alarm() Results in undefined behavior when


Sets or changes a timer that expires called from a Guardian TNS process.
at a specified time in the future.

OSS Process-Management Functions 141


Table 3-4 OSS Process-Management Functions (continued)
OSS Function OSS Notes Guardian Notes

execl() Can return extended errors. Sets errno to the ENOTOSS value
Replaces the current process image Propagates open file descriptors when called from a Guardian process.
with a new process image, using a except those opened using a
pathname, a set of environment Guardian function or procedure.
strings, and **environ.

execle() Can return extended errors. Sets errno to the ENOTOSS value
Replaces the current process image Propagates open file descriptors when called from a Guardian process.
with a new process image, using a except those opened using a
pathname, a set of environment Guardian function or procedure.
strings, and an undeclared envp
array.

execlp() Can return extended errors. Sets errno to the ENOTOSS value
Replaces the current process image Propagates open file descriptors when called from a Guardian process.
with a new process image, using a except those opened using a
filename, a set of environment strings, Guardian function or procedure.
and **environ.

execv() Can return extended errors. Sets errno to the ENOTOSS value
Replaces the current process image Propagates open file descriptors when called from a Guardian process.
with a new process image, using a except those opened using a
pathname, an argv array, and Guardian function or procedure.
**environ.

execve() Can return extended errors. Sets errno to the ENOTOSS value
Replaces the current process image Propagates open file descriptors when called from a Guardian process.
with a new process image, using a except those opened using a
pathname, an argv array, and an Guardian function or procedure.
undeclared envp array.

execvep() Can return extended errors. Sets errno to the ENOTOSS value
Replaces the current process image Propagates open file descriptors when called from a Guardian process.
with a new process image, using a except those opened using a
filename, an argv array, and Guardian function or procedure.
**environ.

_exit() Child processes of a terminated OSS A Guardian process has no OSS


exit() process are assigned a parent process process ID and therefore has no wait
Terminate the calling process. ID of 1. (wait() or waitpid())
considerations.

fork() Can return extended errors. Sets errno to the ENOTOSS value
Creates an OSS process. The child process shares directory when called from a Guardian process.
streams with the parent. They share
the same block of directory entries,
but each stream can be used by only
one of the processes.
Propagates open file descriptors
except those opened using a
Guardian function or procedure.

getegid() A process’s effective group ID can be


Gets the effective group ID of the different from the group number in its
calling process. process access ID (PAID).

getenv()
Returns the value of an environment
variable.

142 Managing Processes


Table 3-4 OSS Process-Management Functions (continued)
OSS Function OSS Notes Guardian Notes

geteuid()
Gets the effective user ID of the
calling process.

getgid() A process’s real group ID can be


Gets the real group ID of the calling different from the group number in its
process. creator access ID (CAID).

getgroups() The effective group ID might not


Gets the group list of the calling occur in the returned group ID list if
process. the effective group ID has been
changed by executing a set-group-ID
program or by calling the setgid()
function.

getpgrp() Sets Guardian trap number 5when


Gets the OSS process group ID of the called from a Guardian process.
calling process.

getpid() Sets Guardian trap number 5when


Gets the OSS process ID of the calling called from a Guardian process.
process.

getppid() If the parent process terminates or the Sets Guardian trap number 5 when
Gets the OSS parent process ID of the calling process was created by a called from a Guardian process.
calling process. Guardian process, it returns a parent
process ID of 1.

getsid() Can return extended errors. Sets errno to the ENOTOSS value and
Gets the group ID of the process that sets Guardian trap number 5 when
is the session leader of the specified called from a Guardian process.
process

getuid() A process’s real user ID is not always


Gets the real user ID of the calling numerically equal to its creator access
process. ID.

kill() Can return extended errors. Cannot send signals to Guardian


Sends a signal to a process or group Applications should not count on all processes.Sets errno to the ENOTOSS
of processes. system processes receiving signals. value when called from a Guardian
process.
There are several constraints in
sending signals if there is Safeguard
protection on OSS processes.

longjmp()
Performs a nonlocal goto.

OSS Process-Management Functions 143


Table 3-4 OSS Process-Management Functions (continued)
OSS Function OSS Notes Guardian Notes

nftw() Can return extended Guardian files that are visible to the
nftw64() errors.nftw64() can access both opendir() function can be traversed.
Traverses a file tree. small files and large files. Security controls on Guardian objects
do not affect the outcome of a call to
nftw().
Two Guardian file system file numbers
(not necessarily the next two available)
are allocated for the root directory and
the current working directory.
The current working directory is
assigned from the VOLUME attribute
of the Guardian environment
=_DEFAULTS DEFINE.
The use of static memory by the
process increases slightly.

pause() Can return extended errors. Sets errno to the ENOTOSS value
Suspends the calling process until a when called from a Guardian TNS
signal is received. process.

putenv()
Sets an environment variable.

raise() Can return extended errors. Sets errno to the ENOTOSS value
Sends a signal to the calling process. when called from a Guardian TNS
process.

setgid()
Sets the group ID of the calling
process.

setjmp()
Saves the current execution context.

setpgid() Can return extended errors. Sets errno to the ENOTOSS value and
Sets the process group ID of the sets Guardian trap number 5 when
calling process. called from a Guardian process.

setpgrp() Can return extended errors. Sets errno to the ENOTOSS value and
Creates a new session when the sets Guardian trap number 5 when
calling process is not a process group called from a Guardian process.
leader, and sets the process group ID
of the calling process.

setregid()
Sets the real and effective group IDs
of the current process

setreuid()
Sets the real and effective user IDs of
the current process

setsid() Can return extended errors. Sets errno to the ENOTOSS value and
Creates a new session and sets the sets Guardian trap number 5 when
process group ID. called from a Guardian process.

setuid() The value of the user ID must be in


Sets the user ID of the calling process. the range 0 through 65535.

144 Managing Processes


Table 3-4 OSS Process-Management Functions (continued)
OSS Function OSS Notes Guardian Notes

sigaction() Can return extended errors. Sets errno to the ENOTOSS value
Specifies the action to be taken upon HP has defined several new signals. when called from a Guardian TNS
delivery of a signal. process.

sigaddset() Can return extended errors. Not meaningful when called from a
Adds a signal to a signal set. Guardian TNS process.

sigdelset() Can return extended errors. Not meaningful when called from a
Deletes a signal from a signal set. Guardian TNS process.

sigemptyset() Can return extended errors. Not meaningful when called from a
Initializes a signal set to exclude all Guardian TNS process.
signals.

sigfillset() Can return extended errors. Not meaningful when called from a
Initializes a signal set to include all Guardian TNS process.
signals.

sigismember() Can return extended errors. Not meaningful when called from a
Tests whether a signal is a member Guardian TNS process.
of a signal set.

siglongjmp() Results in undefined behavior when


Performs a nonlocal goto. called from a Guardian TNS process.

signal() Can return extended errors. Sets errno to the ENOTOSS value
Specifies the action to be taken upon HP has defined several new signals. when called from a Guardian TNS
delivery of a signal. process.

sigpending() Can return extended errors. Sets errno to the ENOTOSS value
Returns the set of signals that are when called from a Guardian TNS
blocked from delivery and pending process.
to the calling process.

sigprocmask() Can return extended errors. Sets errno to the ENOTOSS value
Changes or examines a process signal HP has defined several new signals. when called from a Guardian TNS
mask. process.

sigsetjmp() Results in undefined behavior when


Saves the current execution context called from a Guardian TNS process.
and can save the current process
signal mask.

sigsuspend() Can return extended errors. Sets errno to the ENOTOSS value
Changes a process signal mask and HP has defined several new signals. when called from a Guardian TNS
suspends the calling process. process.

sleep() There are several Results in undefined behavior when


Suspends the calling process for a implementation-defined features with called from a Guardian TNS process.
specified interval of time. respect to the SIGALRM signal.

tdm_execve() Is an extension to the XPG4 Sets errno to the ENOTOSS value


tdm_execvep() specification. when called from a Guardian process.
Replaces the current OSS process Is similar to the exec set of functions;
image with a new process image also allows you to retain the attribute
(with HP extensions). values inherited from the parent
process or to specify other values.

OSS Process-Management Functions 145


Table 3-4 OSS Process-Management Functions (continued)
OSS Function OSS Notes Guardian Notes

tdm_fork() Is an extension to the XPG4 Sets errno to the ENOTOSS value


Creates a new OSS process (with HP specification. when called from a Guardian process.
extensions). Is similar to the fork() function; also
allows you to retain the attribute
values inherited from the parent
process or to specify other values.
Does not propagate file locks.

tdm_spawn() Can return extended errors. Sets errno to the ENOTOSS value
tdm_spawnp() Is an extension to the XPG4 when called from a Guardian process.
Creates a new OSS process with a specification.
specified executable image (with HP
extensions). Produces a new OSS process by
combining the function of
tdm_execve() or tdm_execvep()
with tdm_fork(), but with the
following additions:
• Parameters control the file
descriptors the child process
inherits from the parent process.
• The inherit structure allows the
process group ID and signal mask
of the child process to be specified
in addition to a list of signals that
the child process takes default
action on.
• Does not propagate file locks.

times() Can return extended errors. Does not maintain child times.
Gets calling process and child process There is no overflow limit for the Accumulates all processor time as user
times. fields in the tms structure. time.
Might not maintain elapsed time
correctly if the processor’s internal
clock is reset.

uname() Can return extended errors.


Gets information identifying the
system on which the calling process
runs.

wait() If a parent process terminates without Sets errno to the ENOTOSS value
waitpid() waiting for all of its child processes when called from a Guardian process.
Wait for a child process to terminate. to terminate, the remaining child
processes are assigned a parent
process ID of 1.

Guardian Process-Management Procedures


Table 3-5 displays information about each Guardian procedure that you can use to manage
processes. Procedures that have been superseded by other procedures are not shown. The columns
of the table contain the following:
Guardian Procedure
The name of the procedure and a brief description.
OSS Notes
Additional considerations or restrictions when the Guardian procedure is used on OSS
processes.
For details about a procedure, refer to the Guardian Procedure Calls Reference Manual.

146 Managing Processes


Table 3-5 Guardian Process-Management Procedures
Guardian Procedure OSS Notes

CHILD_LOST_ An OSS parent process must read its $RECEIVE file for
Examines a system message to determine whether a system messages.
process has stopped. If an OSS process is reading Guardian system messages
to monitor an OSS process, it might appear that the
monitored process is alive when it has stopped. See
“Monitoring OSS Processes Reading Guardian System
Messages” (page 117).

FILENAME_TO_PROCESSHANDLE_
Converts a Guardian (process) filename to a process
handle.

OSS_PID_NULL_
Returns a null OSS process ID.

PROCESS_ACTIVATE_ Has the same effect as calling the OSS kill() function
Returns a suspended process to a ready state. with SIGCONT as the value of the signal parameter.

PROCESS_DEBUG_ There are several requirements an OSS process must meet


Invokes the debugging facility on a process. to use the debugging facility.

PROCESS_GETINFO_
Gets a limited set of information about a process.

PROCESS_GETINFOLIST_
Gets detailed information about a process or set of
processes.

PROCESS_GETPAIRINFO_ OSS processes cannot belong to process pairs.


Obtains information about a named process or process
pair.

PROCESS_LAUNCH_ Cannot create an OSS process.


Creates a Guardian process.

PROCESS_SETINFO_ If used to change the priority of an OSS process, the same


Modifies a single nonstring attribute of a process. security rules apply as for the OSS kill() function.

PROCESS_SETSTRINGINFO_
Modifies a single string-form attribute of a process.

PROCESS_SPAWN_ Cannot create a Guardian process.


Creates an OSS process.

PROCESS_STOP_ An OSS parent process receives a SIGCHLD signal and


Terminates a process. the OSS process termination status.
A Guardian parent process receives a process-termination
system message.
When used to stop a process other than the caller, the
process handle must be specified.
The security rules are the same as when using the OSS
kill() function to terminate a process.

PROCESS_SUSPEND_ Has the same effect as calling the OSS kill() function
Places a process into a suspended state. with SIGSTOP as the value of the signal parameter.

PROCESSHANDLE_COMPARE_ OSS does not support process pairs.


Compares two process handles and reports whether they
are identical, represent different processes of the same
process pair, or are different.

Guardian Process-Management Procedures 147


Table 3-5 Guardian Process-Management Procedures (continued)
Guardian Procedure OSS Notes

PROCESSHANDLE_DECOMPOSE_
Returns one or more parts of a process handle.

PROCESSHANDLE_GETMINE_
Gets the process handle of the calling process.

PROCESSHANDLE_NULLIT_
Initializes a process handle to a null value.

PROCESSHANDLE_TO_CRTPID_
Converts a process handle to the corresponding Guardian
process ID (CRTPID).

PROCESSHANDLE_TO_FILENAME_
Converts a process handle to a Guardian (process)
filename.

PROCESSHANDLE_TO_STRING_
Converts a process handle to a process string, which can
identify a process or set of processes.

PROCESSNAME_CREATE_
Returns a unique process name that is suitable for passing
to the PROCESS_CREATE_ or PROCESS_SPAWN_
procedures.

PROCESSSTRING_SCAN_
Scans an input string for a process string and returns the
corresponding process handle or a single component of
the process string converted to internal form.

SETLOOPTIMER When the process loop-timer expires for an OSS process,


Sets the process loop-timer value of the calling process. a SIGTIMEOUT signal is generated.

SIGACTION_INIT_
Establishes the initial state of signal handling for the
calling process.

SIGACTION_RESTORE_
Restores the signal-handling state stored by a call to
SIGACTION_SUPPLANT_.

SIGACTION_SUPPLANT_
Saves the current signal-handling state and allows a
subsystem to take over signal handling temporarily.

SIGJMP_MASKSET_
Saves the process signal mask in a jump buffer.

148 Managing Processes


4 Managing Memory Segments
Managing memory has a different meaning in the UNIX and Guardian environments. In a
standard UNIX environment, memory management means mapping virtual addresses to physical
addresses. The operating system performs this function, and an application programmer does
not have to write any code to map addresses.
In the Guardian environment, the operating system also maps virtual to physical addresses, and
no application programming is required to perform this function. However, a Guardian
application programmer can manipulate memory in a program’s main data segment and in
extended data segments.
In the OSS environment, a programmer usually does not have to be aware of the type of memory
a program is using.

NOTE: You need to read this section if (and only if) your G-series OSS TNS programs use
Guardian procedures to share memory with other TNS processes. This section does not apply
to system running H-series RVUs because the H-series OSS environment does not support TNS
programs.
OSS processes can use OSS functions and Guardian procedures to share memory with other OSS
processes. To share memory with Guardian processes, OSS processes must use Guardian
procedures.
OSS functions allow (OSS) processes to share flat extended data segments. Guardian procedures
allow processes to share both flat and selectable extended data segments.
This section describes the differences between flat and selectable extended data segments and
why OSS TNS processes should not attempt to share selectable segments with other processes.
This section discusses the following topics:

Topic Content

“The Operating Environment for NonStop Systems” Summary of the differences between UNIX and OSS
(page 26) memory management.

“Memory-Management Interoperability” (page 150) Capability of OSS and Guardian processes to manage
memory using OSS and Guardian memorymanagement
mechanisms.

“About Extended Data Segments” (page 150) Overview of flat and selectable extended data (memory)
segments.

“When Processes Share Memory Using Guardian Recommendations and cautions about sharing flat and
Procedures” (page 151) selectable segments between TNS processes.

“Performance Considerations” (page 152) Suggestions regarding the use of Guardian memory
management mechanisms to improve application
performance.

“OSS Memory-Management Functions” (page 152) List of each OSS memory-management functions with
notes about its use when called from a Guardian
procedure.

“Guardian Memory-Management Procedures” (page 152) List of each Guardian memory-management procedure
with notes about its use when called from an OSS process.

What Is Not in This Section


Managing memory in the Guardian environment means manipulating extended data segments
as well as communicating between processes using Guardian shared memory and semaphore
procedures.

What Is Not in This Section 149


In the OSS environment, you do not use OSS functions to manipulate extended data segments,
and communication between processes using OSS shared memory, message queues, semaphores,
and pipe functions is considered to be interprocess communication (not memory management).
The focus of this section is Guardian memory management procedures and what you need to
know about them if you have TNS programs. OSS interprocess communication functions are
discussed in Chapter 6: Interprocess Communication (page 163).

Common and Unique Characteristics


Managing memory is a concern in the UNIX and OSS environments; in particular, there is one
case in the OSS environment in which familiarity with NonStop operating system extended data
(memory) segments is required: when OSS TNS processes want to share selectable memory
segments with Guardian TNS processes or other OSS TNS processes.

Features Common to UNIX and OSS Memory Management


The operating system takes care of mapping virtual addresses to physical addresses, and you
do not have to write code to map addresses. Sharing memory is not usually part of the concept
of managing memory, because you do not have to be aware of the type of memory you are
accessing (if there is more than one type).

Features Unique to OSS Memory Management


If an OSS TNS process shares memory with another TNS process using Guardian procedures,
you must be aware of:
• Which type of extended data (memory) segment the processes are sharing (flat or selectable).
• The fact that the TNS data heap in a C program is also a selectable extended data (memory)
segment. Only one selectable segment can be available to a process at any given time, and
this means you cannot access both the data heap in your program and a shared selectable
segment at the same time. (The data heap in native processes is not a selectable segment.)

Memory-Management Interoperability
OSS processes share and synchronize access to flat segments using OSS shared-memory and
semaphore functions or using Guardian procedures. OSS TNS processes cannot share selectable
segments using Guardian procedures.
Guardian processes share and synchronize access to memory using Guardian shared-memory
and semaphore procedures. Guardian processes cannot use OSS functions to share and
synchronize access to memory.
If Guardian and OSS processes want to share and synchronize access to memory, they must use
Guardian shared-memory and semaphore procedures.

Use One API to Manipulate a Memory Segment


You cannot use both OSS functions and Guardian procedures to manipulate the same memory
segment. For example, an OSS process cannot call a Guardian procedure, such as
SEGMENT_ALLOCATE_, to allocate a memory segment and then call an OSS function, such as
shmctl(), to manipulate the same segment.

About Extended Data Segments


Using Guardian procedures, you can make additional virtual memory available to a process by
allocating one or more extended data (memory) segments. There are two types of extended
segments: flat and selectable. You specify the type of extended segment with a parameter supplied
to the SEGMENT_ALLOCATE_ procedure.
OSS processes should share flat segments with Guardian processes or other OSS processes.

150 Managing Memory Segments


Flat Segments
Flat segments have distinct addresses. Because each flat segment is allocated at a different starting
address, a flat segment does not have to be selected, or made current, with SEGMENT_USE_.
All flat segments allocated by a process are available to that process at any given time.

Selectable Segments
Selectable segments all share the same address space; all selectable segments have the same
starting address. Thus, only one selectable segment is available to a process at any given time.
You select a segment, or make a segment current, with the SEGMENT_USE_ procedure.
For a discussion of using extended segments in application programs, see the Guardian
Programmer’s Guide. For information about memory layout on NonStop systems, see the
appropriate server description manual.

When Processes Share Memory Using Guardian Procedures


In most cases, you will use OSS functions to share memory between OSS processes. However,
if an OSS process must share memory with a Guardian process, you must use Guardian
procedures. OSS processes can also use Guardian procedures to share memory, but this is
uncommon.
Guardian procedures allow processes to share flat and selectable segments, but there are several
reasons why processes should share flat segments and not share selectable segments:
• Flat segments provide a performance advantage because you do not have to use the
SEGMENT_USE_ procedure to select a segment. You can also move data between flat
segments using assignment statements instead of the MOVEX procedure.
• Flat segments allow processes to access more virtual memory at any one time.
• Most important, flat segments do not overlap with the TNS data heap in a C program.

TNS Processes Should Not Share a Selectable Segment


There is really nothing to prevent OSS TNS processes from trying to share a selectable segment
with Guardian TNS processes or other OSS TNS processes, but OSS TNS processes cannot share
selectable segments with other processes successfully.
The TNS data heap and other data allocated by the compiler in a C program are in a selectable
segment. The data heap is used for malloc() operations and for aggregate data types, such as
arrays and structures. Many C functions, such as printf(), also use the data heap for temporary
storage. In reality, almost every C run-time function accesses the data heap.
Because the TNS data heap is itself a selectable segment, you cannot access both the data heap
and a selectable segment you want to share with another process at the same time. If an OSS
TNS process attempts to share a selectable segment with another TNS process, compiler-generated
code will access the shared segment expecting its own data, and access to a different segment
will produce unintended and catastrophic results.
When OSS TNS processes share memory with Guardian TNS processes or other OSS TNS
processes, they should share flat segments.

When Processes Share Memory Using Guardian Procedures 151


Performance Considerations
You can improve the performance of your applications with respect to managing memory by
following these recommendations:
• OSS TNS processes should share flat, not selectable, extended data (memory) segments with
Guardian TNS processes or other OSS TNS processes.

OSS Memory-Management Functions


Table 4-1 (page 152) displays information about each OSS function that you can use to manage
memory. Functions that have been superseded by other functions are not shown. The columns
of the table contain the following:
OSS Function
The name of the function and a brief description.
Guardian Notes
Notes about using the function on a Guardian process.
The information in this table is only a summary of the information in the reference page for a
function. For details, refer to the reference pages either online or in the Open System Services
System Calls Reference Manual.

NOTE: To determine which RVUs support an OSS function, see Appendix A: Documented
OSS Functions (page 389).
Table 4-1 OSS Memory Management Functions
OSS Function Guardian Notes

bcmp() Can be called only by native processes.


Compares two areas of memory.

bcopy()
Copies an area of memory.

bzero()
Zeroes an area of memory.

heap_check()
Checks the consistency of the runtime heap.

heap_check_always()
Controls whether the run-time heap consistency is
checked automatically.

heap_min_block_size()
Specifies the minimum block size to attempt to use when
allocating from the heap.

valloc() Can be called only by native processes.


Provides a memory allocator.

Guardian Memory-Management Procedures


Table 4-2 (page 153) displays information about each Guardian procedure that you can use to
manage memory. Procedures that have been superseded by other procedures are not shown.
The columns of the table contain the following:
Guardian Procedure
The name of the procedure and a brief description.

152 Managing Memory Segments


OSS Notes
Additional considerations or restrictions when the Guardian procedure is called from an
OSS process.
Table 4-2 Guardian Memory Management Functions
Guardian Procedure OSS Notes

ADDRESS_DELIMIT_
Returns information about a particular area of the user's
logical address space, including the addresses of the first
and last bytes in that area.

BINSEM_CLOSE_ Closes only a Guardian semaphore, not an OSS


Closes a binary semaphore. semaphore.

BINSEM_CREATE_ Creates, opens, and locks only a Guardian semaphore,


Creates, opens, and locks a binary semaphore. not an OSS semaphore.

BINSEM_FORCELOCK_ Forces a lock on only a Guardian semaphore, not an OSS


Forces a lock on a binary semaphore. semaphore.

BINSEM_LOCK_ Locks only a Guardian semaphore, not an OSS semaphore.


Locks a binary semaphore.

BINSEM_OPEN_ Opens only a Guardian semaphore, not an OSS


Opens a binary semaphore. semaphore.

BINSEM_UNLOCK_ Relinquishes a lock on only a Guardian semaphore, not


Relinquishes a lock on a binary semaphore. an OSS semaphore.

MOVEX
Transfers data from one extended data (memory) segment
to another.

POOL_CHECK_
Returns memory pool error information.

POOL_DEFINE_
Defines the bounds of a memory pool in an extended data
(memory) segment or in the user data segment.

POOL_GETINFO_
Returns information about a memory pool.

POOL_GETSPACE_
Obtains a block of storage from a memory pool.

POOL_PUTSPACE_
Returns a block of storage to a memory pool.

POOL_RESIZE_
Changes the size of an existing memory pool.

RESIZESEGMENT
Changes the size of an existing extended data (memory)
segment.

SEGMENT_ALLOCATE_ Allocates both flat and selectable segments.


Allocates a virtual memory space to a flat or selectable
extended data (memory) segment.

SEGMENT_DEALLOCATE_ Deallocates both flat and selectable segments.


Deallocates a flat or selectable extended data (memory)
segment.

Guardian Memory-Management Procedures 153


Table 4-2 Guardian Memory Management Functions (continued)
Guardian Procedure OSS Notes

SEGMENT_GETINFO_
Returns information about an extended data segment.

SEGMENT_USE_
Makes a selectable segment current (a flat segment need
not be made current). It also returns the last selectable
segment in use.

SETMODE
Can be used to speed large transfers of data between an
extended data (memory) segment and a file (option 141).

154 Managing Memory Segments


5 Managing Time
This section describes the time-management features that are common to both UNIX and the
OSS API and those that are unique to the OSS API.
You can use OSS functions and Guardian procedures to query the system clock, obtain process
times, and set process timers.
This section discusses the following topics:

Topic Content

“Common and Unique Characteristics” (page 155) Summary of the differences between OSS and UNIX time
management.

“Process Attributes” (page 105) The objects on which you can use time-management
functions and procedures.

“Querying the System Clock” (page 156) How to obtain and format the system date and time.

“Querying Process Times” (page 157) How to obtain process times.

“Limiting Processor Time Use” (page 157) How to use the SETLOOPTIMER procedure in an OSS
program.

“OSS Time-Management Functions” (page 157) List of each OSS time-management function with notes
about the OSS implementation and its use on Guardian
objects.

“Guardian Time-Management Procedures” (page 160) List of each Guardian time-management procedure with
notes about its use on OSS objects.

Common and Unique Characteristics


OSS time management is the same as UNIX time management, except that you cannot set or
alter the system clock with an OSS function.

Features Common to UNIX and OSS Time Management


The OSS API enables you to:
• Obtain the system time with the time() function
• Obtain process times with the clock() and times() functions
• Set alarms with the alarm() and ualarm() functions
The OSS API also enables you to format the time and perform time calculations with the following
functions:

Function Summary

asctime() Converts the date and time to a string.

ctime() Converts time units.

difftime() Computes the difference between two calendar time values.

gmtime() Converts a time value to broken-down Coordinated Universal Time (UTC)


time.

localtime() Converts a time value to broken-down local time.

mktime() Converts a broken-down time into time since the Epoch (00:00:00 UTC January
1, 1970 A.D.).

strftime() Converts a date and time to a string.

Common and Unique Characteristics 155


Function Summary

strptime() Converts a character string to a time value.

tzset() Sets the time-zone conversion information.

utime() Sets file access and modification times.

wcsftime() Converts a date and time to a wide character string.

Features Unique to OSS Time Management


The OSS API does not provide functions that set or alter the system time or obtain information
about processor times. It also does not provide an internal timer.

Time-Management Interoperability
You can use Guardian time-management procedures from the OSS environment.
Guardian system clock procedures and OSS system clock functions can be called from both
Guardian and OSS processes. Because the OSS and Guardian time formats are incompatible,
only Guardian system clock procedures work on Guardian time formats and only OSS system
clock functions work on OSS time formats.
You can use the MYPROCESSTIME, PROCESS_GETINFO_, and PROCESS_GETINFOLIST_
procedures and the Measure product to obtain time information about an OSS process. The
PROCESS_GETINFO_ and PROCESS_GETINFOLIST_ procedures are especially useful in that
they can obtain information not just about the calling process, but about another process that
you specify.
When a Guardian process calls the OSS times() function, only restricted information is returned:
times are available for Guardian processes but not for processes that act on behalf of a Guardian
process.
You can use the utime() function to change Guardian file access and modification times of
unstructured files.
The alarm() and ualarm() functions use OSS signals to notify OSS processes and do not work
with Guardian processes, because OSS signals cannot be sent to Guardian processes.
You can use the Guardian SETLOOPTIMER procedure to limit processor time use in OSS
processes.

Querying the System Clock


You query the system date and time in the OSS environment with the time() function as you
would in the UNIX operating system. The timestamp you get from the time() function is
accurate to the nearest second. If you need greater accuracy in OSS programs, you can call
Guardian system date and time procedures and obtain timestamps accurate to the centisecond
or microsecond.
Guardian timestamps differ from the OSS timestamp as shown in Table 5-1.
Table 5-1 Guardian and OSS Timestamps
Feature OSS Timestamp Guardian 48-Bit Timestamp Guardian 64-Bit Julian
Timestamp

Precision Second Centisecond Microsecond

Beginning of Time 00:00:00 UTC January 1, 00:00 December 31, 1974 12:00 (noon) UTC January
1970 A.D. (the Epoch) A.D. 1, 4713 B.C.

Guardian system clock procedures work only on Guardian timestamp formats, and OSS system
time-management functions work only on OSS timestamp formats. For example, the

156 Managing Time


INTERPRETJULIANDAYNO procedure requires a Julian day number, which does not exist in
the OSS API. Likewise, the strftime() function requires an OSS time object.
To obtain a timestamp time with an accuracy to the microsecond in an OSS program, you must
use the Guardian JULIANTIMESTAMP procedure.

Querying Process Times


You can obtain the execution time of processes from the OSS API with the times() or clock()
function. The times() function provides more information than the clock() function.
An OSS process calls the times() or clock() function in the same way a UNIX process would.
If your program is running as a Guardian process, you can also obtain the execution time of that
Guardian process with the times() or clock() function. When a Guardian process calls the
times() or clock() function, it cannot obtain the execution time of its OSS child processes.
The processor time of a Guardian process is accumulated as user time.

Limiting Processor Time Use


You can use the Guardian SETLOOPTIMER procedure to limit the processor time consumed by
an OSS program (as opposed to the elapsed time that you would limit with the alarm() function).
Example 5-1 demonstrates the use of SETLOOPTIMER to control the processor time used by a
compute-bound program. The time limit can be set to a hundredth of a second.

Example 5-1 Using SETLOOPTIMER in an OSS Program


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <cextdecs.h(SETLOOPTIMER)>

int timelimit = 247; /* time-out for processor processing


set to 2.47 seconds */

/* Catch time-out signal. */


void catchtimeout(arg) {
printf("Program used more than %d hundredths of a seconds\n",\
timelimit);
exit(1);
}

struct sigaction action;

int main(int argc, char *argv[]) {


int i;

/* Set up processor processing time-out signal-catching routine. */


action.sa_handler = catchtimeout;
sigaction(SIGTIMEOUT, &action, NULL);

/* Set processor processing time-out to specified limit. */


SETLOOPTIMER((short)timelimit);
for(i=0;i < 100000000; i++) i=i; /* compute loop */
return(0);
}

OSS Time-Management Functions


Table 5-2 (page 159) displays information about each OSS function that you can use to manage
time. The columns of the table contain the following:

Querying Process Times 157


OSS Function
The name of the function and a brief description.
OSS Notes
Notes about the OSS implementation of the function. The note “Can return extended errors”
means that the function can return errors that are HP extensions to the XPG4 specification.
Refer to the function’s reference page for further information.
Guardian Notes
Notes about using the function when it is called from a Guardian process.
The note “FDM set” (for file, directory, and memory) means that the function is one of a set
of functions that have the following effects when the first of them is called from the Guardian
environment:
• Two Guardian file-system numbers (not necessarily the next two available) are allocated
for the root directory and the current working directory. These file numbers cannot be
closed by calling the Guardian FILE_CLOSE_ procedure.
• The current working directory is assigned from the VOLUME attribute of the Guardian
environment =_DEFAULTS DEFINE.
• The use of static memory by the process increases slightly.
• The functions in the FDM set are access(), chdir(), chmod(), chown(), chroot(),
creat(), creat64()fchmod(), fchown(), fstatvfs(), fstatvfs64(), ftok(),
ftw(), ftw64(), getcwd(), glob(), lchmod(), lchown(), link(), lstat(),
lstat64(), mkdir(), mkfifo(), mknod(), nftw(), nftw64(),open(),
open64(),opendir(), pathconf(), pipe(), readlink(), rename(),
rename_oss(), rmdir(), select(), socket(), socketpair(), stat(),
stat64(), statvfs(),statvfs64(), symlink(), unlink(), and utime().
The information in this table is only a summary of the information in the reference page for a
function. For details, refer to the reference pages either online or in the Open System Services
System Calls Reference Manual and the Open System Services Library Calls Reference Manual.
Example 5-2 (page 159) shows the use of the gettimeofday() function to get date to the nearest
microsecond. The function is provided for compatibility with BSD programs.

158 Managing Time


Example 5-2 Using gettimeofday()
#include <sys/time.h>
#include <time.h>
#include <stdio.h>

int main(int argc, char *argv[])


{
struct timeval tv;
struct timezone tz;
/*
Read the system values for the current time and time zone.
The time is expressed in seconds and microseconds since
midnight January 1, 1970.
*/
gettimeofday(&tv, &tz);
printf("The current time is:\n%s", ctime(&tv.tv_sec));
printf("and %d microseconds after midnight January 1, 1970\n", tv.tv_usec);
printf("Daylight savings time value = %d\n", tz.tz_dsttime);
printf("Local time zone in minutes west of Greenwich = %d\n",
tz.tz_minuteswest);
return(0);
}

Table 5-2 OSS Time-Management Functions


OSS Function OSS Notes Guardian Notes

alarm() A SIGLIMIT signal is delivered to Does not work with Guardian TNS
Sets or changes the time-out value for the process if the function call fails. processes because OSS signals cannot
an interval timer. be sent to a Guardian TNS process.

asctime()
Converts a date and time to a string.
Refer to ctime().

clock()
Reports processor time used.

ctime()
Converts time units.

difftime()
Computes the difference between two
calendar time values. Refer to
ctime().

ftime(3) Can be called only by native


Gets date and time. processes.

getdate() Can be called only by native Can be called only by native processes.
Converts user format date and time. processes.

gettimeofday() Cannot be used from the Guardian


Gets date and time. environment.

gmtime()
Converts a time value to
broken-down Coordinated Universal
Time (UTC) time. Refer to ctime().

localtime()
Converts a time value to
broken-down local time. Refer to
ctime().

OSS Time-Management Functions 159


Table 5-2 OSS Time-Management Functions (continued)
OSS Function OSS Notes Guardian Notes

mktime()
Converts a broken-down time into
time since the Epoch (00:00:00 UTC
January 1, 1970 A.D.). Refer to
ctime().

strftime()
Converts a date and time to a string.

strptime()
Converts a character string to a time
value.

time()
Obtains the time in seconds since the
Epoch (00:00:00 UTC January 1, 1970
A.D.).

times() Time values are approximate. When called from a Guardian process,
Obtains process and child process Times are not calculated for a process the following restrictions apply:
elapsed times. if it costs more to compute the • Child times are not maintained.
running time than to run the process • All processor time is accumulated
itself. as user time.
There is no overflow limit for the • Elapsed time might not be correct
fields in the tms structure. if the processor's internal clock has
been reset.
Can return extended errors.

tzset()
Sets the time-zone conversion
information. Refer to ctime().

utime() Can return extended errors. FDM set.The file access time is not
Sets file access and modification updated by the FILE_OPEN_
times. procedure.

wcsftime()
Converts a date and time to a wide
character string. Refer to
strftime().

Guardian Time-Management Procedures


Table 5-3 displays information about each Guardian procedure that you can use to manage time.
Measure procedures and procedures that have been superseded by other procedures are not
shown. The columns of the table contain the following:
Guardian Procedure
The name of the procedure and a brief description.
OSS Notes
Additional considerations or restrictions when the Guardian procedure is called from an
OSS process.
For details about a procedure, refer to the Guardian Procedure Calls Reference Manual.

160 Managing Time


Table 5-3 Guardian Time-Management Procedures
Guardian Procedure OSS Notes

ADDDSTTRANSITION
Allows the super ID to add an entry to the daylight-saving
time (DST) transition table.

CANCELPROCESSTIMEOUT
Cancels a process-time timer previously initiated by a call
to the SIGNALPROCESSTIMEOUT procedure.

CANCELTIMEOUT
Cancels a process-time timer previously initiated by a call
to the SIGNALTIMEOUT procedure.

COMPUTEJULIANDAYNO
Converts a Gregorian calendar date on or after January
1, 0001, to a Julian day number.

COMPUTETIMESTAMP
Converts a Gregorian calendar date into a 64-bit Julian
timestamp.

CONVERTPROCESSTIME
Converts the process time returned by the PROCESSTIME,
MYPROCESSSTIME, and PROCESSINFO procedures into
hours, minutes, seconds, milliseconds, and microseconds.

CONVERTTIMESTAMP
Converts a Greenwich mean time (GMT) timestamp to
or from a local-time-based timestamp.

CPUTIMES
Returns the amount of time since system load that a given
processor has spent in the following states: process busy,
interrupt busy, and idle.

INTERPRETINTERVAL
Converts a fixed variable containing a number of
microseconds into a combination of days, hours, minutes,
seconds, milliseconds, and microseconds.

INTERPRETJULIANDAYNO
Converts a Julian day number to the year, month, and
day.

INTERPRETTIMESTAMP
Converts a 64-bit Julian timestamp into a Gregorian date
and time of day.

JULIANTIMESTAMP
Returns either a Julian timestamp or the number of
microseconds elapsed since the last system load.

MYPROCESSTIME
Returns the process execution time of the calling process.

PROCESS_GETINFO_
Obtains information, including the execution time, about
a specified process.

PROCESS_GETINFOLIST_ Some attributes obtain OSS time information.


Obtains information, including the execution time, about
a specified process.

Guardian Time-Management Procedures 161


Table 5-3 Guardian Time-Management Procedures (continued)
Guardian Procedure OSS Notes

PROCESSOR_GETINFOLIST_ Some attributes obtain OSS time information.


Obtains information about a specified processor.

SETLOOPTIMER
Enables you to limit the processor time a process is
allowed.

SETSYSTEMCLOCK
Allows you to change the system clock.

SIGNALPROCESSTIMEOUT
Sets a timer based on process execution time.

SIGNALTIMEOUT
Sets a timer to a given number of units of elapsed time.

TIME
Provides the current date and time in integer form.

TIMESTAMP
Provides the internal form of the interval clock of the
processor where the application is running.

162 Managing Time


6 Interprocess Communication
Interprocess-communication mechanisms allow processes to communicate within the same
processor, between processors, and between nodes. This section discusses the following topics:

Topic Content

“Available Methods” (page 163) Summary of the mechanisms available to an OSS


application.

“Common and Unique Characteristics” (page 164) Summary of the differences between UNIX and OSS
interprocess communication.

“Interprocess-Communication Interoperability” (page 165) Summary of OSS and Guardian processes ability to
communicate using OSS and Guardian
interprocess-communication methods

“Performance Considerations” (page 183) Suggestions regarding the use of


interprocess-communication mechanisms to improve
application performance.

“OSS Interprocess-Communication Functions” (page 184) List of each OSS interprocess-communication function
with notes about its OSS implementation and its use when
called from Guardian processes.

“Guardian Interprocess-Communication Procedures” List of each Guardian interprocess-communication


(page 191) procedure with notes about its use when called from OSS
processes.

Available Methods
The OSS application program interface (API) provides access to the sockets, pipes, FIFOs, shared
memory, semaphores, and message queues found on most UNIX systems. An OSS application
also has access to Guardian APIs that provide additional interprocess-communication methods
such as Guardian sockets and the Guardian requester/server interface known as the $RECEIVE
file. Some of the OSS and Guardian interprocess communication methods also allow OSS processes
to communicate with Guardian processes.
Table 6-1 (page 163) lists the interprocess-communication methods available in Open System
Services using only OSS APIs, and the capabilities of each relevant to communication between
processors and nodes. The methods are listed in approximate decreasing order of usage on UNIX
systems.
Table 6-1 Interprocess Communication Using OSS APIs
IPC method Within a processor Between processors Between Expand With other systems
nodes

OSS AF_INET and Yes Yes Yes Yes


AF_INET6 sockets

OSS AF_UNIX Yes Yes No No


sockets1

Pipes Yes Yes No No

FIFOs Yes Yes Yes No

Message queues Yes Yes No No

OSS signals Yes Yes No No

OSS shared memory Yes No No No

OSS semaphores Yes No No No

Available Methods 163


1 Applies to both AF_UNIX Release 2 sockets and earlier AF_UNIX sockets. However, AF_UNIX Release 2 sockets must
be of the same mode to communicate with each other. See “Using AF_UNIX Sockets” (page 176).

Table 6-2 lists the interprocess-communication methods available to an OSS process using mixed
OSS and Guardian APIs, and the capabilities of each relevant to communication between
processors and nodes. The methods are listed in an order consistent with Table 6-1.
Table 6-2 Interprocess Communication Using OSS and Guardian APIs
IPC method Within a processor Between processors Between Expand With other systems
nodes

Guardian AF_INET Yes Yes Yes Yes


and AF_INET6
sockets

OSS AF_INET and Yes Yes Yes Yes


AF_INET6 sockets

OSS AF_UNIX Yes Yes No No


sockets1

Pipes (with OSS Yes Yes No No


processes only)

FIFOs Yes Yes Yes No

Message queues (with Yes Yes No No


OSS processes only)

OSS signals Yes Yes No No

Guardian shared Yes No No No


memory

Guardian binary Yes No No No


semaphores

OSS shared memory Yes No No No


(with OSS processes
only)

OSS semaphores Yes No No No


(with OSS processes
only)

$RECEIVE Yes Yes Yes No


1 Applies to both AF_UNIX Release 2 sockets and earlier AF_UNIX sockets. However, AF_UNIX Release 2 sockets must
be of the same mode to communicate with each other. See “Using AF_UNIX Sockets” (page 176).

Common and Unique Characteristics


OSS interprocess communication includes most UNIX interprocess-communication methods.
The extensions and differences of OSS interprocess-communication functions compared to typical
UNIX interprocess communication are summarized in Table 6-3 (page 185). Table 6-5 (page 191)
summarizes the behavior of Guardian interprocess-communication procedures when called from
OSS processes.

Features Common to UNIX and OSS Interprocess Communication


Sockets are the most widely used API for communication between processes running on different
systems. The semantics used by sockets applications vary from UNIX system to UNIX system.
OSS sockets are based on the versions of UNIX systems developed at the University of California,
Berkeley, by the Berkeley Software Distribution (BSD) group. The OSS implementations (BSD
4.3 for AF_INET and AF_INET6, and BSD 4.3+ for AF_UNIX) have limited extensions based on
the XPG4 standard. OSS sockets obey semantics consistent with the POSIX.1G draft standard.

164 Interprocess Communication


For a good introduction to the use of sockets, refer to a commercial text such as UNIX Network
Programming, Second Edition, by W. Richard Stevens.
Pipes and FIFOs are memory-resident interprocess channels through which OSS processes can
communicate. OSS processes having a common ancestor can communicate through a pipe, but
common ancestry is not required for OSS processes to communicate through a FIFO, which is a
named pipe.
OSS processes can share memory segments using OSS shared-memory functions. OSS semaphores
allow multiple processes to synchronize access to shared memory segments to avoid compromising
the integrity of the data in those segments.
OSS processes can also communicate by sending and receiving messages using OSS
message queues.

Features Unique to OSS Interprocess Communication


The following is a summary of the features that are unique to OSS interprocess communication:
• An OSS process can attach a maximum of 15 memory segments at any one time.
• OSS processes can share and synchronize access to memory segments within the same
processor.
• The OSS API does not yet support read-only access to shared memory.
• The OSS sockets API supports features that allow the use of alternate TCP processes within
a node.
• The ftok() function, which generates an OSS interprocess-communication key, is an
optional function in XPG4, Version 2, and is included in the OSS API.
• The OSS sockets functions do not return the errno value ENOSR.
• The OSS sockets functions can return errno values that are HP extensions to the XPG4
specification.
• sockatmark(), socket_transport_name_get(), and
socket_transport_name_set() are HP extensions to the XPG4 specification
• OSS processes can use Guardian AF_INET and AF_INET6 sockets APIs.

Interprocess-Communication Interoperability
OSS and Guardian processes can communicate as described in the following subsections:
• “Using Guardian AF_INET and AF_NET6 Sockets, and OSS AF_INET and AF_INET6 Sockets”
(page 165)
• “Using AF_UNIX Sockets” (page 176)
• “Using FIFOs” (page 178) (named pipes)
• “Using Guardian Shared Memory and Semaphores” (page 178)
• “Using the $RECEIVE File” (page 179).
Guardian processes can use OSS sockets APIs, with the restrictions described in Table 6-3
(page 185). The table includes a short description of the OSS sockets functions.
OSS and Guardian processes cannot communicate using message queues, because only OSS
processes can call the message queue functions. OSS and Guardian processes cannot use AF_UNIX
sockets through the Guardian sockets API because Guardian sockets do not support the AF_UNIX
address family.

Using Guardian AF_INET and AF_NET6 Sockets, and OSS AF_INET and AF_INET6
Sockets
OSS and Guardian processes can communicate within the same node and between nodes or
systems using either:
• Guardian AF_INET or AF_INET6 sockets functions and semantics

Interprocess-Communication Interoperability 165


or
• OSS AF_INET or AF_INET6 sockets functions and semantics.
The AF_INET sockets functions use the services provided by NonStop TCP/IP; the AF_INET6
sockets functions use the services provided by NonStop TCP/IPv6. The two interfaces are similar,
but NonStop TCP/IPv6 allows a larger IP address, and hence, access to a greater number of
systems and devices.
The Guardian version of sockets was also derived from BSD sockets (Berkeley sockets) and
provide the general function of BSD sockets, but have modified APIs and behavior. Guardian
sockets are not POSIX-conformant and are less portable in code than OSS sockets, so converting
a UNIX or POSIX application to use Guardian sockets might require source or algorithm changes.
The use of Guardian sockets for NonStop TCP/IP, Parallel Library TCP/IP, and NonStop TCP/IPV6
is described in the TCP/IP Programming Manual.
OSS processes can communicate with Guardian processes within the same node and between
nodes or systems through AF_INET or AF_INET6 sockets when either process uses the OSS
sockets functions.
The examples in the following subsections illustrate some of these uses.

Communication Using Only OSS APIs


Example 6-1 (page 168) and Example 6-2 (page 171) should give you an idea of how the OSS
AF_INET communication mechanism works and provide you with a template you can expand
in your applications.
Example 6-1 and Example 6-2 show an OSS server process and an OSS requester process using
OSS AF_INET functions to communicate.

NOTE: These examples use the AF_INET sockets functions, which provide an interface to
NonStop TCP/IP. The programs could also be written using the AF_INET6 sockets functions to
interface to NonStop TCP/IPv6. For information and examples of AF_INET6 sockets usage, refer
to the TCP/IP Programming Manual.
The server program in Example 6-1 is compiled as a linked program file named server2 that
is secured for execution in the current working directory. The requester program in Example 6-2
is compiled as a linked program file named requester2 that is secured for execution in the
current working directory.
The server process can be started in the background from the OSS shell using the command:
run ./server2 &
After you start the server process, the requester process in Example 6-2 can be started in the
foreground from the OSS shell using the command:
./requester2
Alternatively, both processes can be started in the foreground from separate terminal sessions.
The following sample dialog illustrates the processes run from two terminal sessions. The server
terminal session for the program in Example 6-1 appears as:
/home/software/chrisbl/cabpubs: ./server2
Server starting
Message received = hello
Message received = goodbye
Server stopping
/home/software/chrisbl/cabpubs:
while the requester terminal session for the program in Example 6-5 appears as:
/home/software/chrisbl/cabpubs: ./requester2
Requester starting
?hello
Read 6 bytes back from server

166 Interprocess Communication


?goodbye
Read 8 bytes back from server
?
/home/software/chrisbl/cabpubs:
Note that the server2 program is an iterative server, performing its functions for multiple
requestors so that process-creation delays are minimized and processor usage is somewhat
optimized. For examples of more traditional dynamic and static server applications, refer to
“Performance Considerations” (page 183).
For more information about using OSS sockets, refer to the individual function reference pages
either online or in the Open System Services System Calls Reference Manual and the Open System
Services Library Calls Reference Manual.

Interprocess-Communication Interoperability 167


Example 6-1 Using AF_INET in an OSS Server Process
/* server2.c
*
* Simple OSS server example using OSS socket APIs
* for communication between requester and server.
*
* This server accepts AF_INET stream socket connections on
* a listening port. Data requests are handled by printing
* the data and then replying back to the requester with the
* original data. The server exits when idle for 60 seconds.
*/

#define _XOPEN_SOURCE_EXTENDED 1 /* needed for OSS sockets */

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netdb.h>

int fd, listenfd, newfd, highfd, fdcount, readycount, bytesread;


struct sockaddr_in addr; /* socket address (family,addr,port) */
struct timeval timeval; /* timeout structure for select() call */
fd_set fdset, rdset; /* set of fds, set of fds ready for reading */

#define IDLE_PERIOD 60 /* 60 seconds *


#define BUFF_LEN 1024 /* buffer size */
char msg_buff[BUFF_LEN+1]; /* one buffer is enough for all connections */

int main(int argc, char **argv)


{
printf("Server starting\n");

/* create AF_INET stream socket ... if error, then exit(1) */


if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("socket() call failed [errno %d]\n", errno);
exit(1);

}
/* Get server port from the command line or use default 12345 */
if (argc > 1)
addr.sin_port = (short)atoi(argv[1]); /* use command line arg */
else
addr.sin_port = 12345; /* use default */

addr.sin_family = AF_INET; /* internet address family */


addr.sin_addr.s_addr = gethostid(); /* assume server on our host */

/* bind socket to address ... if error, then exit(1) */


if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0)
{
printf("bind() call failed [errno %d]\n", errno);
exit(1);
}

/* make the socket a listening socket... if error then exit(1) */


if (listen(fd, 5) < 0)
{
printf("listen() call failed [errno %d]\n", errno);
exit(1);
}

168 Interprocess Communication


fdcount = 1;
highfd = fd;
listenfd = fd;
FD_ZERO(&fdset);
FD_SET(listenfd, &fdset);

/* Find a ready socket ... */


while (1)
{
/* initialize timeout and bitmask for select() call */
timeval.tv_sec = IDLE_PERIOD;
timeval.tv_usec = 0;
memcpy(&rdset, &fdset, sizeof(fdset));
readycount = select(highfd+1, &rdset, NULL, NULL, &timeval);

/* if timeout then exit(0) */


if (readycount == 0)
{
printf("Server stopping\n");
exit(0);
}

/* find first fd that was marked ready for reading */


for (fd = 0; fd <= highfd; fd++)
{
if (FD_ISSET(fd, &rdset))
break;
}
/* if fd is listening socket, accept incoming connection */
if (fd == listenfd)
{
/* accept new connection ... if error, then exit(1) */
if ((newfd = accept(fd,(struct sockaddr *)NULL, (size_t *)NULL)) < 0)
{
printf("accept() call failed [errno %d]\n", errno);
exit(1);
}

/* add fd to fd set */
fdcount++;
FD_SET(newfd, &fdset);
if (newfd > highfd)
highfd = newfd;
}
else /* else fd is an existing connection */
{
if ((bytesread = recv(fd, msg_buff, BUFF_LEN, 0)) <= 0)
{
/* if recv error then exit(1) */
if (bytesread < 0)
{
printf("recv() call failed [errno %d]\n", errno);
exit(1);
}
else /* bytesread == 0 ... peer closed connection */
{
close(fd);
fdcount--;
FD_CLR(fd,&fdset);
}
}
else /* data received */
{
msg_buff[bytesread] = '\0'; /* make string
NULL-terminated */
printf("Message received = %s", msg_buff);

/* echo back to sender ... if error then exit(1) */


if (send(fd, msg_buff, bytesread, 0) < 0)
{
printf("send() call failed [errno %d]\n", errno);

Interprocess-Communication Interoperability 169


exit(1);
}
}
} /* end else fd is an existing connection */
} /* end while (1) */
}

170 Interprocess Communication


Example 6-2 Using AF_INET in an OSS Requester Process
/* requester2.c
*
* Simple OSS requester example using OSS socket APIs
* for communication between requester and server.
*
* This requester accepts terminal input and sends it to a
* server using a send() call and then waits for a response using
* a recv() call. When the server echoes the data back to the
* requester, the recv() call completes and the requester prompts
* for more terminal input. When terminal input ends with EOF,
* the socket connection is closed and the requester stops.
*/

#define _XOPEN_SOURCE_EXTENDED 1 /* needed for OSS sockets */

#include <unistd.h>
#include <fcntl.h>
#include <tal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netdb.h>

int fd, bytesread;


struct sockaddr_in addr; /* socket address (family,addr,port) */

#define BUFF_LEN 1024 /* data buffer length */


char msg_buff[BUFF_LEN+1]; /* data buffer */

int main(int argc, char **argv) {

printf("Requester starting\n");

/* create AF_INET stream socket ... if error, then exit(1) */


if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("socket() call failed [errno %d]\n", errno);
exit(1);
}
/* Get server port from the command line or use default 12345 */
if (argc > 1)
addr.sin_port = (short)atoi(argv[1]); /* use command line arg */
else
addr.sin_port = 12345; /* use default */

addr.sin_family = AF_INET; /* internet address family */


addr.sin_addr.s_addr = gethostid(); /* assume server on our host */

/* connect to server ... if error, then exit(1) */


if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
printf("connect() failed [errno %d]\n", errno);
exit(1);
}

/* Prompt user, read data, send data to server and wait for reply */
while (1) {

Interprocess-Communication Interoperability 171


printf("?"); /* send prompt */
fgets(msg_buff, BUFF_LEN, stdin); /* read user input */
if (feof(stdin)) /* if EOF then exit(0) */
exit(0);
bytesread = (int)strlen(msg_buff); /* includes newline */

/* send line to server... if error then exit(1) */


if (send(fd, msg_buff, bytesread, 0) < 0)
{
printf("send() call failed [errno %d]\n", errno);
exit(1);
}
/* expect echo from server... if close or error then
exit(1) */
if ((bytesread = recv(fd, msg_buff, bytesread, 0)) <= 0)
{
if (bytesread == 0)
printf("Server closed connection\n");
else
printf("recv() call failed [errno %d]\n", errno);
exit(1);
}
printf("Read %d bytes back from server\n",bytesread);
}
}

Communication Using Mixed APIs


Example 6-3 (page 174) and Example 6-2 (page 171) should give you an idea of how the AF_INET
communication mechanism works when different sets of APIs are used and provide you with a
template you can expand in your applications.
Example 6-3 and Example 6-2 show a Guardian server process and an OSS requester process
using Guardian AF_INET and OSS AF_INET functions, respectively, to communicate.

NOTE: These examples use the AF_INET sockets functions, which provide an interface to
NonStop TCP/IP. The programs could also be written using the AF_INET6 sockets functions to
interface to NonStop TCP/IPv6. For information and examples of AF_INET6 sockets usage, refer
to the TCP/IP Programming Manual.
The server program in Example 6-3 is compiled as a linked program file named server2g that
is secured for execution in the current working directory. The requester program in Example 6-2
is compiled as a linked program file named requester2 that is secured for execution in the
current working directory.
The server process can be started in the background from the OSS shell using the command:
run ./server2g &
After you start the server process, the requester process in Example 6-2 can be started in the
foreground from the OSS shell using the command:
./requester2
Alternatively, both processes can be started in the foreground from separate terminal sessions.
The following sample dialog illustrates the processes run from two terminal sessions. The server
terminal session for the program in Example 6-3 appears as:
/home/software/chrisbl/cabpubs: ./server2g
Server starting
Message received = hello
Message received = goodbye
Server stopping
/home/software/chrisbl/cabpubs:
while the requester terminal session for the program in Example 6-5 appears as:

172 Interprocess Communication


/home/software/chrisbl/cabpubs: ./requester2
Requester starting
?hello
Read 6 bytes back from server
?goodbye
Read 8 bytes back from server
?
/home/software/chrisbl/cabpubs:

Interprocess-Communication Interoperability 173


Example 6-3 Using AF_INET in a Guardian Server Process
/* server2g.c
*
* Simple OSS server example using Guardian socket APIs
* for communication between requester and server.
*
* This server accepts AF_INET stream socket connections on
* a listening port. Data requests are handled by printing
* the data and then replying back to the requester with the
* original data. The server exits when idle for 60 seconds.
*
* Note - Guardian sockets do not have Posix semantics.
* select() is not available and nonblocking calls require
* starting operations with a nowait socket call such as
* recv_nw() and then completing the operation with a call
* to AWAITIOX(). Each operation requires a dedicated buffer.
*/

#define _GUARDIAN_SOCKETS /* needed for Guardian sockets */

#include <unistd.h>
#include <fcntl.h>
#include <tal.h>
#include <cextdecs.h(AWAITIOX,FILE_CLOSE_)>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netdb.h>

short fd, listenfd, newfd; /* note - fd is really Guardian fnum */


short bytesread;
long tag;
int addrlen;
struct sockaddr_in addr; /* socket address (family,addr,port) */

enum tag { bind_tag = 1, accept_tag, recv_tag, send_tag };

#define NOWAIT 1
#define SYNC 1
#define FOREVER -1L
#define IDLE_PERIOD 6000 /* 60 seconds = 6000 x 0.01 second */

#define MAX_FDS 100


#define BUFF_LEN 1024
char *msg_buff_ptr[MAX_FDS+1]; /* need one buffer per socket */
char *bufferptr; /* pointer to current buffer */
int main(int argc, char **argv)
{
printf("Server starting\n");

/* create AF_INET stream socket ... if error then exit(1) */


if ((fd = (short)socket_nw(AF_INET, SOCK_STREAM, 0,
NOWAIT, SYNC )) < 0)
{
printf("socket_nw() call failed [errno %d]\n", errno);
exit(1);
}

/* Get server port from the command line or use default 12345 */
if (argc > 1)
addr.sin_port = (short)atoi(argv[1]); /* use command line arg */
else
addr.sin_port = 12345; /* use default */

174 Interprocess Communication


addr.sin_family = AF_INET; /* internet address family */
addr.sin_addr.s_addr = gethostid(); /* assume server on our host */

/* bind socket to address ... if error then exit(1) */


if (bind_nw(fd, (struct sockaddr *)&addr, sizeof(addr), bind_tag) < 0)
{
printf("bind_nw() call failed [errno %d]\n", errno);
exit(1);
}
AWAITIOX(&fd, , , , FOREVER);

/* start a nowait accept ... if error then exit(1) */


addrlen = sizeof(addr);
if (accept_nw(fd, (struct sockaddr *)&addr, &addrlen, accept_tag) < 0)
{
printf("accept_nw() call failed [errno %d]\n", errno);
exit(1);
}

listenfd = fd;

/* Find a finished nowait operation */


while (1)
{
fd = -1;
AWAITIOX(&fd, (long *) &bufferptr, &bytesread, &tag,
IDLE_PERIOD);

/* if timeout then exit(0) */


if (fd == -1)
{
printf("Server stopping\n");
exit(0);
}

/* if incoming connection, accept connection */


if (fd == listenfd)
{
/* create a new socket ... if error then exit(1) */
if ((newfd = (short) socket_nw(AF_INET, SOCK_STREAM, 0,
NOWAIT, SYNC) ) < 0)
{
printf("socket_nw() call failed [errno %d]\n", errno);
exit(1);
}
AWAITIOX(&newfd, , , , FOREVER); /* should finish quickly */

/* if too many connections then exit(1) */


if (newfd > MAX_FDS)
{
printf("Too many connections\n");
exit(1);
}
msg_buff_ptr[newfd] = malloc(BUFF_LEN+1);

/* accept the connection using the filled in addr


* buffer from the finished accept_nw() call. */

if (accept_nw2(newfd, (struct sockaddr *)&addr, accept_tag) < 0)


{
printf("accept_nw2() call failed [errno %d]\n", errno);
exit(1);
}
AWAITIOX(&newfd, , , , FOREVER); /* should finish quickly */

/* need to post a recv() for AWAITIOX() to complete */


if (recv_nw(newfd, bufferptr, BUFF_LEN, 0, recv_tag) < 0)
{
printf("recv() call failed [errno %d]\n", errno);
exit(1);
}

Interprocess-Communication Interoperability 175


/* need to post an accept for the next connection */
addrlen = sizeof(addr);
if (accept_nw(fd, (struct sockaddr *)&addr, &addrlen, accept_tag) < 0)
{
printf("accept_nw() call failed [errno %d]\n", errno);
exit(1);
}
}
else /* else data or error on an existing connection */
{
if (bytesread == 0) /* no data - error or close */
{
/* close our end */
FILE_CLOSE_(fd); /* not close(fd)
but FILE_CLOSE_(fd) */
free(msg_buff_ptr[fd]);
msg_buff_ptr[fd] = NULL;
}
else /* data was received */
{
/* so print data and echo it back to sender */
bufferptr[bytesread] = '\0'; /* make string NULL-terminated */
printf("Message received = %s", bufferptr);

if (send_nw(fd, bufferptr, bytesread, 0, send_tag) < 0)


{
printf("send_nw() call failed [errno %d]\n", errno);
exit(1);
}
AWAITIOX(&fd, , , , FOREVER); /* should finish quickly */

/* need to post a recv() for AWAITIOX() to complete */


if (recv_nw(fd, bufferptr, BUFF_LEN, 0, recv_tag) < 0)
{
printf("recv_nw() call failed [errno %d]\n", errno);
exit(1);
}
} /* end else data was received */
}
} /* end while (1) */
}

Using AF_UNIX Sockets


An OSS process can communicate with a Guardian process using AF_UNIX sockets only when
both processes use the OSS sockets APIs because only the OSS sockets APIs support the AF_UNIX
address family.
Systems running RVUs earlier than J06.05 or H06.16 are using AF_UNIX Release 1 sockets and
software.
Systems running J06.05 and later J-series RVUs or H06.16 and later H-series RVUs are using
AF_UNIX Release 2 sockets and software. For AF_UNIX Release 2 software:
• The OSS sockets local server, $ZPLS, is replaced by the OSS local server 2 servers. Although
the name $ZPLS is used as a transport-provider name, $ZPLS is not a process that runs on
the system.
• An OSS local server 2 server $ZLSnn (where nn is the processor number) for each processor
is started automatically when the processor loads.
• Sockets can be created in one of two modes: compatibility mode and portability mode:
— Compatibility mode maintains the semantics of AF_UNIX Release 1 sockets to allow
applications to migrate to AF_UNIX Release 2 software without changes.
— Portability mode provides behaviors that are similar to other AF_UNIX implementations,
such as Linux and HP-UX.

176 Interprocess Communication


— Sockets are created in compatibility mode by default. The mode of the socket is
determined by the name of the transport provider process when the socket is created.
After a socket is created, the mode of the socket cannot be changed.
— Sockets created in compatibility mode can communicate with other sockets created in
compatibility mode but cannot communicate with sockets created in portability mode.
— Sockets created in portability mode can communicate with other sockets created in
portability mode but cannot communicate with sockets created in compatibility mode.
— The accept() function creates a socket in the same mode as the listening socket whose
file descriptor is passed.

Compatibility Mode
Sockets created in compatibility mode have these characteristics and behaviors, which are the
same as the characteristics and behaviors for AF_UNIX Release 1 sockets:
• If a relative name is passed to connect() then subsequent getpeername() calls return
that same relative name. That is, whatever pathname is passed to connect() is returned,
byte-for-byte, in subsequent calls to getpeername(), including path names beginning
with /E/local_system/ and names containing /./ or /../.
• If the file to which a socket is bound is removed or renamed, calls to getsockname() fail
with the error FE_ENOENT.
• If the file to which a datagram socket is bound is removed or renamed, and then a send
operation is performed on the socket, a recvfrom() or recvmsg() call on the receiving
socket returns a null address.
• A call to listen() with a backlog parameter less than or equal to 0 (zero) causes
subsequent connect() calls to fail with the ECONNREFUSED error unless the socket has
a pending accept() call.
You can create sockets in compatibility mode using one of these methods:
• Use the default transport-provider name. For systems running AF_UNIX Release 2 software,
the default AF_UNIX transport-provider name is $ZPLS, which results in sockets created in
compatibility mode.
• Use the Guardian DEFINE =_AFUNIX_PROCESS_NAME to specify $ZPLS as the transport
provider name. This Guardian define must be a MAP DEFINE with a FILE attribute string
of the desired AF_UNIX transport-provider name. For example:
TACL> ADD DEFINE =_AFUNIX_PROCESS_NAME,CLASS MAP,FILE $ZPLS
or
OSH> add_define =_AFUNIX_PROCESS_NAME class=MAP file=\$ZPLS

NOTE: Although the name $ZPLS is used as a transport-provider name, $ZPLS is not a
process that runs on the system.

• Use the socket_transport_name_set() function to specify $ZPLS as the transport


provider name. This method overrides the default transport-provider name and allows you
to create sockets in either mode within the same application.

Portability Mode
Sockets created in portability mode have these characteristics and behaviors:
• If a relative name is passed to connect() then subsequent getpeername() calls return
the corresponding absolute name. That is, the absolute path name returned by
getpeername() has the /E/local_system/ prefix (if present) stripped, all symbolic
links resolved, all /./ strings suppressed, and all /../ strings resolved.
• If the file to which a socket is bound is removed or renamed, calls to getsockname()
continue to return the original absolute path name.

Interprocess-Communication Interoperability 177


• If the file to which a datagram socket is bound is removed or renamed, and then a send
operation is performed on the socket, a recvfrom() or recvmsg() call on the receiving
socket returns the original pathname in the address parameter.
• Portability mode sockets are more efficient because getsockname(), recvfrom() and
recvmsg() no longer require an interaction with an OSS name server.
• A call to listen() with a backlog parameter less than or equal to 0 (zero) causes
subsequent blocking connect() calls to block until there is a corresponding accept()
call. This differs from the behavior for compatibility mode, in which calls to connect()
fail with the ECONNREFUSED error unless the socket has a pending accept() call.
You can create sockets in portability mode using one of these methods:
• Use the Guardian DEFINE =_AFUNIX_PROCESS_NAME to specify $ZAFN2 as the default
transport-provider name. This Guardian define must be a MAP DEFINE with a FILE attribute
string of the desired AF_UNIX transport-provider name. For example:
TACL> ADD DEFINE =_AFUNIX_PROCESS_NAME,CLASS MAP,FILE $ZAFN2
or
OSH> add_define =_AFUNIX_PROCESS_NAME class=MAP file=\$ZAFN2

NOTE: Although the name $ZAFN2 is used as a transport-provider name, $ZAFN2 is not
a process that runs on the system.

• Use the socket_transport_name_set() function to specify $ZAFN2 as the


transport-provider name. This method overrides the default transport-provider name and
allows you to create sockets in either mode within the same application.

Using FIFOs
OSS and Guardian processes can communicate using FIFOs:
• Within the same processor
• Between processors
• Between nodes (by way of the /E directory)
However, they cannot communicate using unnamed pipes. Unnamed pipes can only be used to
communicate between OSS processes.

Using Guardian Shared Memory and Semaphores


If Guardian and OSS processes want to share and synchronize access to memory, they must use
Guardian shared-memory and semaphore procedures, such as BINSEM_CREATE_,
BINSEM_LOCK_, SEGMENT_ALLOCATE_, and SEGMENT_DEALLOCATE_. Guardian
procedures allow you to share and synchronize access to memory within the same processor.
Only OSS processes can call OSS shared-memory and semaphore functions to share and
synchronize access to flat extended data (memory) segments within the same processor. Both
OSS and Guardian processes can call Guardian shared-memory and semaphore procedures to
share and synchronize access to flat and selectable segments within the same processor.

Use One API to Manipulate a Memory Segment


You cannot use both OSS functions and Guardian procedures to manipulate the same memory
segment. For example, an OSS process cannot call a Guardian procedure, such as
SEGMENT_ALLOCATE_, to allocate a memory segment and then call an OSS function, such as
shmctl(), to manipulate the same segment.

178 Interprocess Communication


Considerations for TNS Processes
HP strongly recommends that a G-series OSS TNS process share flat segments and not share
selectable segments with another TNS process, OSS or Guardian. This is because the TNS data
heap is itself a selectable segment, and you cannot access both the data heap and a selectable
segment you want to share with another process at the same time. (The data heap in native
processes is not a selectable segment.)
See Chapter 4: Managing Memory Segments (page 149) for more information about NonStop
operating system extended data (memory) segments.

Using the $RECEIVE File


OSS and Guardian processes can use Guardian procedures to communicate between nodes,
between processors, and within the same processor through $RECEIVE. $RECEIVE is a special
file in the Guardian filesystem through which a process can receive system messages or messages
from other processes.
The basic algorithm requires a server process to open its $RECEIVE file and accept messages
from one or more requester processes that open the server process file (in UNIX terms, each
requester opens the server process as a special file in the Guardian file system). The server replies
to received messages as necessary and requester processes see the replies as coming from the
server process file. The use of $RECEIVE is described in the Guardian Programmer’s Guide.
Example 6-4 (page 180) and Example 6-5 (page 182) should give you an idea of how the $RECEIVE
interprocess communication mechanism works and provide you with a template you can expand
in your applications. The Guardian Programmer’s Guide contains detailed instructions and examples
on using $RECEIVE, and you should read it before expanding these examples.
The server program in Example 6-4 is compiled as a linked program file named server1 that
is secured for execution in the current working directory. The requester program in Example 6-5
is compiled as a linked program file named requester1 that is secured for execution in the
current working directory.
The server process can be started in the background from the OSS shell using the command
run -name=/G/echo ./server1 &
which /G/echo gives the running server process the process name $ECHO in the Guardian file
system. That process name is used by requesters to open the server program.
After you start the server process, the requester process in Example 6-5 can be started in the
foreground from the OSS shell using the command:
.\requester1
Alternatively, both processes can be started in the foreground from separate terminal sessions.
The following sample dialog illustrates the processes run from two terminal sessions. The server
terminal session for the program in Example 6-4 appears as:
/home/software/chrisbl/cabpubs: run -name=/G/echo ./server1
Server starting
Message received = hello
Message received = goodbye
Server stopping
/home/software/chrisbl/cabpubs:
while the requester terminal session for the program in Example 6-5 appears as:
/home/software/chrisbl/cabpubs: ./requester1
Requester starting
?hello
Read 6 bytes back from server
?goodbye
Read 8 bytes back from server
?
/home/software/chrisbl/cabpubs:

Interprocess-Communication Interoperability 179


Example 6-4 Using $RECEIVE in an OSS Server Process
/* server1.c
*
* Simple OSS server example using Guardian file input/output
* APIs for communication between requester(s) and server.
*
* This server accepts requests on $RECEIVE. Data requests are
* handled by printing the data and then replying back to the
* requester with the original data. Open and close requests
* are handled by updating an opener count. The server exits
* when idle for 60 seconds.
*/

#include <unistd.h>
#include <fcntl.h>
#include <tal.h>
#include <cextdecs.h(FILE_OPEN_, READUPDATEX, REPLYX, FILE_CLOSE_, \
AWAITIOX, FILE_GETINFO_)>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define NOWAITDEPTH 1 /* enable nowait operations */


#define RECVDEPTH 1 /* enable replies on $RECEIVE */
#define IDLE_PERIOD 6000 /* 60 seconds = 6000 x 0.01 second */

short retcode; /* return code for APIs that return short */


_cc_status CC; /* return code for APIs that return condition code */

short fnum, bytesread, error, openers;


char *filename = "$RECEIVE"; /* file name for incoming requests */

#define BUFF_LEN 1024 /* buffer size */


union msg
{
short sys_msg[50]; /* buffer viewed as system message */
char data[BUFF_LEN+1]; /* buffer viewed as user data */
} msg_buff; /* single buffer is enough for all connections */

int main(int argc, char **argv)


{
printf("Server starting\n");

/* The server process opens its $RECEIVE file for nowait IO. */
retcode = FILE_OPEN_(
filename, /* filename */
(short)strlen(filename), /* filename length */
&fnum, /* file number returned */
0, /* access mode (r/w) */
0, /* exclusion mode (shared) */
NOWAITDEPTH, /* nowait depth (nowait enabled) */
RECVDEPTH, /* receive depth (1 msg) */
0); /* options (sys msgs enabled) */
if (retcode != 0) /* if error, exit(1) */
{
fprintf(stderr, "FILE_OPEN_() to %s failed\n", filename);
fprintf(stderr, "Return code = %d\n", retcode);
exit(1);
}

/* Read data from $RECEIVE ... handle system msgs and user msgs */
openers = 0;
while (1)
{
CC = READUPDATEX(fnum, /* file number */
msg_buff.data, /* msg buffer */
BUFF_LEN, /* length */
&bytesread); /* number of bytes read */
if (_status_ne(CC)) /* if error, exit(1) */
{

180 Interprocess Communication


fprintf(stderr, "READUPDATEX() to %s failed\n", filename);
exit(1);
}

/* Wait for I/O completion on $RECEIVE. */


CC = AWAITIOX(&fnum, /* file number */
, /* buffer address */
&bytesread, /* count transferred */
, /* tag */
IDLE_PERIOD); /* time limit (60 sec) */

/* get last file error ... 6 = sys msg, 40 = timeout */


FILE_GETINFO_(fnum, &error);

if (error != 0 && error != 6 && error != 40)/* if error then exit(1) */


{
fprintf(stderr, "AWAITIOX() to %s failed\n",filename);
exit(0);
}

/* if timeout then exit(0) */


if (error == 40)
{
FILE_CLOSE_(fnum);
printf("Server stopping\n");
exit(0);
}

/* If a system message then handle and reply. */


if (error == 6) /* system message received */
{
switch (msg_buff.sys_msg[0]) /* first short is msg type */
{
case -103: /* open message */
openers++;
break;
case -104: /* close message */
openers--;
break;
default: /* other system message */
break;
}

CC = REPLYX(msg_buff.data, 0); /* reply with 0 data bytes */


if (_status_ne(CC)) /* if error, exit(1) */
{
fprintf(stderr, "REPLYX() to %s failed\n", filename);
exit(1);
}

}
else /* else must be a user request */
{
msg_buff.data[bytesread] = '\0'; /* make string NULL-terminated */
printf("Message received = %s", msg_buff.data);
CC = REPLYX(msg_buff.data, bytesread); /* reply with data */
if (_status_ne(CC)) /* if error, exit(1) */
{
fprintf(stderr, "REPLYX() to %s failed\n", filename);
exit(1);
}
}
} /* end while (!done) */
}

Interprocess-Communication Interoperability 181


Example 6-5 Using $RECEIVE in an OSS Requester Process
/* requester1.c
*
* Simple OSS requester example using Guardian file input/output
* APIs for communication between requester and server.
*
* This requester accepts terminal input and sends it to a
* server using a waited WRITEREADX() call. When the server
* echoes the data back to the requester, the WRITEREADX() call
* completes and the requester prompts for more terminal input.
* When terminal input ends with EOF, the server is closed and
* the requester stops.
*/

#include <unistd.h>
#include <fcntl.h>
#include <tal.h>
#include <cextdecs.h(FILE_OPEN_,FILE_CLOSE_, \
WRITEREADX,FILE_GETINFO_)>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

short retcode; /* return code for APIs that return short */


_cc_status CC; /* return code for APIs that return condition code */

#define BUFF_LEN 1024 /* buffer length */


char msg_buff[BUFF_LEN+1]; /* buffer */
char *procname; /* pointer to server process name */
short fnum, bytesread, error;

int main(int argc, char **argv)


{
/* Get server process name from the command line,
else assign default name $ECHO. */
if (argc > 1)
procname = argv[1];
else
procname = "$ECHO";

printf("Requester starting\n");

/* Requester process opens the server process for waited IO. */


retcode = FILE_OPEN_(
procname, /* server process name */
(short)strlen(procname), /* process name length */
&fnum, /* file number returned */
0, /* access mode (r/w) */
0, /* exclusion mode (shared) */
0); /* nowait depth (waited IO)*/
if (retcode != 0) /* if error, exit(1) */
{
fprintf(stderr, "FILE_OPEN_() to %s failed\n", procname);
fprintf(stderr, "Return code = %d\n", retcode);
exit(1);
}

/* Prompt user, read data, send data to server and wait for reply */
while (1)
{
printf("?"); /* send prompt */
fgets(msg_buff, BUFF_LEN, stdin); /* read user input */
if (feof(stdin)) /* if EOF */
{

182 Interprocess Communication


FILE_CLOSE_(fnum); /* close server */
exit(0); /* and exit(0) */
}
bytesread = (short)strlen(msg_buff);/* includes newline */
CC = WRITEREADX(fnum, /* file number */
msg_buff, /* msg buffer */
bytesread, /* size of string to server */
BUFF_LEN, /* length of buffer */
&bytesread); /* number read back */
if (_status_ne(CC)) /* if error, exit(1) */
{
fprintf(stderr, "WRITEREADX() to %s failed\n", procname);
retcode = FILE_GETINFO_(fnum, &error);
if (retcode == 0)
fprintf(stderr, "File error = %d\n", error);
else
fprintf(stderr, "FILE_GETINFO() failed, retcode = %d\n",
retcode);
exit(1);
}
printf("Read %d bytes back from server\n",bytesread);
} /* end while(1) */
}

Performance Considerations
You can improve the performance of your applications with respect to interprocess communication
by following these recommendations.
For input and output in general:
• There can be delays due to the blocking nature of many input/output calls. It can take an
indeterminate amount of time to complete a blocked call. Use the select() function or
nonblocking input/output when indeterminate waits are not desirable. Refer to Example 6-1
(page 168) for an example of the use of the select() call.
For pipes and FIFOs:
• Whenever possible, keep processes that use pipes and FIFOs on the same processor. When
processes reside on the same processor, there is no message system traffic. When processes
reside on different processors, a message system I/O path is created, which slightly degrades
performance. However, keeping processes on different processors can provide better load
balancing and scalability for your applications.
• Make the size of the data buffer exchanged through pipes and FIFOs equal to or less than
the size of the PIPE_BUF system variable. A buffer the size of PIPE_BUF or smaller can be
written in one I/O operation.
An application can force the OSS file system to attempt to resize the buffer used for a specific
pipe or FIFO file by calling the write() or writev() function for a write of more than
PIPE_BUF bytes. If resizing occurs, subsequent reads of up to 52 kilobytes can occur in a
single operation. Because all pipes and FIFOs in a processor have buffers allocated from a
fixed amount of memory, increasing the buffer size for one pipe or FIFO to improve its
throughput reduces the number of pipes and FIFOs that can exist simultaneously in that
processor.
For semaphores:
• Include deadlock-avoidance techniques in your applications.
For sockets:
• OSS AF_UNIX Release 2 sockets have improved performance over AF_UNIX Release 1 sockets
because AF_UNIX Release 2 sockets have fewer system processes involved in the delivery

Performance Considerations 183


of each message. The following list shows the order of increasing overhead (decreasing
performance) for AF_UNIX Release 2 processes and sockets:
1. Both processes are in the same processor and their sockets were created in that processor.
2. The processes are in different processors and each process is using a socket created in
its processor.
3. One of the processes resides in a processor other than where its socket was created.
4. Both processes reside in processors other than where their socket was created.
• OSS AF_UNIX Release 1 sockets and OSS AF_INET and AF_INET6 sockets involve multiple
system processes in the data path for each message, even if both ends of the connection are
on the same processor; as a result, the socket overhead is much higher than for other
interprocess communication mechanisms. The following tradeoffs exist for the use of OSS
AF_UNIX Release 1 sockets, AF_INET sockets, and AF_INET6 sockets:
— If you must have portability and POSIX standard sockets semantics, use OSS sockets.
— If you require improved performance with sockets-like semantics but portability is not
a primary consideration, consider using Guardian sockets. The use of Guardian sockets
for NonStop TCP/IP, Parallel Library TCP/IP, and NonStop TCP/IPV6 is described in
the TCP/IP Programming Manual.
— If you require even higher performance and can abandon portability and sockets
semantics, consider using $RECEIVE. Refer to the Guardian Programmer’s Guide for more
information about programs that use $RECEIVE.
— If you require maximum performance with portability and can abandon sockets
semantics, use OSS pipes or FIFO files. OSS pipes and FIFOs typically provide a direct
data path without intervening system processes.

OSS Interprocess-Communication Functions


Table 6-3 (page 185) displays information about each OSS function that you can use for interprocess
communication. The columns of the table contain the following:
OSS Function
The name of the function and a brief description.
OSS Notes
Notes about the OSS implementation of the function. The note “Can return extended errors”
means that the function can return errors that are HP extensions to the XPG4 specification.
Refer to the function’s reference page for further information.
Guardian Notes
Notes about using the function when it is called from a Guardian process.The note “FDM
set” (for file, directory, and memory) means that the function is one of a set of functions that
have the following effects when the first of them is called from the Guardian environment:
• Two Guardian file-system numbers (not necessarily the next two available) are allocated
for the root directory and the current working directory. These file numbers cannot be
closed by calling the Guardian FILE_CLOSE_ procedure.
• The current working directory is assigned from the VOLUME attribute of the Guardian
environment =_DEFAULTS DEFINE.
• The use of static memory by the process increases slightly.
• The functions in the FDM set are access(), chdir(), chmod(), chown(), chroot(),
creat(), creat64()fchmod(), fchown(), fstatvfs(), fstatvfs64(), ftok(),
ftw(), ftw64(), getcwd(), glob(), lchmod(), lchown(), link(), lstat(),
lstat64(), mkdir(), mkfifo(), mknod(), nftw(), nftw64(),open(),
open64(),opendir(), pathconf(), pipe(), readlink(), rename(),
rename_oss(), rmdir(), select(), socket(), socketpair(), stat(),
stat64(), statvfs(),statvfs64(), symlink(), unlink(), and utime().

184 Interprocess Communication


This table only summarizes the information in the reference page for a function. For details, refer
to the reference pages either online or in the Open System Services System Calls Reference Manual
and the Open System Services Library Calls Reference Manual.

NOTE: Some functions also have reentrant versions. For a complete list of supported functions,
including information about RVU support for each function, see Appendix A (page 389).
Table 6-4 (page 188) displays information about functions useful when managing interprocess
communication. The columns of the table contain the same kinds of information as in Table 6-3.
Table 6-3 OSS Interprocess-Communication Functions
OSS Function OSS Notes Guardian Notes

accept() Can return extended errors. FDM set.


Accepts a new connection on a socket.

bind() Can return extended errors.


Binds a name to a socket.

connect() Can return extended errors.


Connects a socket.

ftok() Can return extended errors. FDM set.


Generates an OSS interprocess
communications (IPC) key.

getsockname() Can return extended errors.


Gets the locally bound name of a
socket.

getsockopt() Can return extended errors.


Gets socket options. Does not support SO_LINGER or
SO_ACCEPTCONN.

listen() Can return extended errors.


Listens for socket connections and
limits the backlog of incoming
connections.

mkfifo() Can return extended errors. FDM set.


Creates a FIFO file. Fails and sets errno to the EINVAL
value if:
• Bits in the mode parameter other
than file permission bits and
S_IFIFO are set.
• Attempt is made to create a FIFO
in the /G file system.
Sets the group ID of the new FIFO to
the group ID of the parent directory
if the S_ISGID flag is set in that
directory; otherwise, the group ID is
set to the effective group ID of the
calling process. G file system.

msgctl() Can return extended errors. Sets errno to the ENOTOSS value
Performs message queue control when called from a Guardian process.
operations.

msgget() Can return extended errors. Sets errno to the ENOTOSS value
Creates or returns the identifier for a when called from a Guardian process.
message queue.

OSS Interprocess-Communication Functions 185


Table 6-3 OSS Interprocess-Communication Functions (continued)
OSS Function OSS Notes Guardian Notes

msgrcv() Can return extended errors. Sets errno to the ENOTOSS value
Reads a message from a message when called from a Guardian process.
queue.

msgsnd() Can return extended errors. Sets errno to the ENOTOSS value
Sends a message to a message queue. when called from a Guardian process.

pclose() Can return extended errors.


Closes a pipe to a process that was
opened using popen().

pipe() Can return extended errors. FDM set.


Creates an interprocess channel.

popen() Can return extended errors. Sets errno to the ENOTOSS value
Initiates a pipe to a process. when called from a Guardian process.

recv() Can return extended errors.


Receives a message from a connected
socket.

recvfrom() Can return extended errors.


Receives a message from a socket.

recvmsg( Can return extended errors.


) Receives a message from a socket
using a message structure.

semctl() Can return extended errors. Sets errno to the ENOTOSS value
Performs semaphore control when called from a Guardian process.
operations.

semget() Can return extended errors. Sets errno to the ENOTOSS value
Creates a new semaphore set ID or when called from a Guardian process.
returns the ID of an existing
semaphore set.

semop() Can return extended errors. Sets errno to the ENOTOSS value
Performs semaphore operations. when called from a Guardian process.

send() Can return extended errors.


Sends a message to a connected
socket.

sendmsg() Can return extended errors.


Sends a message to a socket using a
message structure.

sendto() Can return extended errors.


Sends a message to an unconnected
socket.

setsockopt() Can return extended errors.


Sets socket options. Nonzero values other than 1 can be
used to set Boolean options.

186 Interprocess Communication


Table 6-3 OSS Interprocess-Communication Functions (continued)
OSS Function OSS Notes Guardian Notes

shmat() Can return extended errors.Attaches Sets errno to the ENOTOSS value
Attaches a shared memory segment only flat, not selectable, memory when called from a Guardian process.
to the address space of the calling segments.
process. A shared memory segment must be
aligned on a region boundary. A
region is 32 MB of virtual memory.A
process can attach no more than 15
segments at one time.
Does not support read-only access to
shared memory.Memory segments
are not propagated to a child process
by any of the exec, tdm_exec, or
tdm_spawn sets of functions or when
the child resides in a different
processor from the parent.

shmctl() Can return extended errors. Sets errno to the ENOTOSS value
Performs shared memory control Operates only on flat, not selectable, when called from a Guardian process.
operations. memory segments.

shmdt() Can return extended errors. Sets errno to the ENOTOSS value
Detaches a shared memory segment. Detaches only flat, not selectable, when called from a Guardian process.
memory segments.

shmget() Can return extended errors. Sets errno to the ENOTOSS value
Creates a new shared memory Operates only on flat, not selectable, when called from a Guardian process.
segment or returns the identifier of memory segments.
an existing shared memory segment.
Reuses no-longer-used shared
memory identifiers after a long time
elapses.
A shared memory segment is shared
through a Guardian swap file .If a
processor fails, the following is lost:
all information in the processor’s
shared memory table, all shared
memory segments for that processor,
and all swap files.
The maximum number of shared
memory identifiers is
SHMT_MAXENTRIES.
A shared memory segment can be 1
byte to 128 MB in size.

shutdown() Can return extended errors.


Shuts down socket send or receive
operations.

sockatmark() HP extension to XPG4 specification.


Determines whether a socket is at the
out-of-band mark.

socket() Can return extended errors. FDM set.


Creates an endpoint for
communications.

socketpair() Can return extended errors. FDM set.


Creates a pair of connected sockets. Has memory segment considerations.

OSS Interprocess-Communication Functions 187


Table 6-3 OSS Interprocess-Communication Functions (continued)
OSS Function OSS Notes Guardian Notes

socket_transport_ name_get() HP extension to XPG4 specification.


Gets the name of the
transport-provider process.

socket_transport _name_set() HP extension to XPG4 specification.


Sets the name of the
transport-provider process.

Table 6-4 OSS Interprocess-Communication-Related Functions


OSS Function OSS Notes Guardian Notes

endhostent() Availability of database might require


Closes the network host database. system manager action.

endnetent() Availability of database might require


Closes the network database. system manager action.

endprotoent() Availability of database might require


Closes the connection to the network system manager action.
protocols database.

endservent() Availability of database might require


Closes the connection to the network system manager action.
services database.

freeaddrinfo()
Frees a specified address information
structure previously allocated by
getaddrinfo().

freehostent()
Frees hostent structure previously
allocated by getipnodebyaddr or
getipnodebyname.

gai_sterr()
Aids applications in printing error
messages returned by
getaddrinfo().

getaddrinfo()
Converts hostnames and service
names into socket address structures.

gethostbyaddr() Availability of database might require


Gets a network host entry by address. system manager action.

gethostbyname() Availability of database might require


Gets a network host entry by name. system manager action.

gethostent() Availability of database might require


Gets the next entry in the network system manager action.
host database.

gethostid() Availability of database might require


Gets the identifier for the current system manager action.
host.

getipnodebyaddr()
Gets a network host entry by address.

188 Interprocess Communication


Table 6-4 OSS Interprocess-Communication-Related Functions (continued)
OSS Function OSS Notes Guardian Notes

getipnodebyname()
Gets host information based on IP
node name.

getnameinfo()
Translates a protocol-independent
host address to a host name and gives
the service name.

getnetbyaddr() Availability of database might require


Gets a network entry by address. system manager action.

getnetbyname() Availability of database might require


Gets a network entry by name. system manager action.

getnetent() Availability of database might require


Gets the next entry in the network system manager action.
database.

getpeername() Can return extended errors.


Gets the name of the peer socket.

getprotobyname() Availability of database might require


Gets a protocol entry by name. system manager action.

getprotobynumber() Availability of database might require


Gets a protocol entry by number. system manager action.

getprotoent() Availability of database might require


Gets the next protocol entry. system manager action.

getservbyname() Availability of database might require


Gets a network services entry by system manager action.
name.

getservbyport() Availability of database might require


Gets a network services entry by port system manager action.
number.

getservent() Availability of database might require


Gets the next entry in the network system manager action.
services database.

if_freenameindex()
Frees dynamic memory allocated by
the if_nameindex function.

if_indextoname()
Maps an interface index to its
corresponding name.

if_nameindex()
Gets all interface names and indexes.

if_nametoindex()
Maps an interface name to its
corresponding index.

OSS Interprocess-Communication Functions 189


Table 6-4 OSS Interprocess-Communication-Related Functions (continued)
OSS Function OSS Notes Guardian Notes

htonl()
Converts a 32-bit integer from host
byte order to Internet network byte
order.

htons()
Converts a 16-bit integer from host
byte order to Internet network byte
order.

inet_addr()
Constructs an integer Internet address
from a character string in Internet dot
notation.

inet_lnaof()
Extracts the local network address
from an Internet host address.

inet_makeaddr()
Constructs an integer Internet address
from an Internet network number and
a local network address.

inet_netof()
Extracts the network number from an
Internet host address.

inet_network()
Translates a character string in
Internet dot notation to an Internet
network address.

inet_ntoa()
Translates an integer Internet address
into a character string in Internet dot
notation.

inet_ntop()
Converts a binary internet address to
a character value.

inet_pton()
Converts a character string to an IPv4
or IPv6 binary address.

ntohl()
Converts a 32-bit integer from
Internet network byte order to host
byte order.

ntohs()
Converts a 16-bit integer from
Internet network byte order to host
byte order.

sethostent() Availability of database might require


Opens the network host database and system manager action.
sets the next entry pointer to the first
entry in the database.

190 Interprocess Communication


Table 6-4 OSS Interprocess-Communication-Related Functions (continued)
OSS Function OSS Notes Guardian Notes

setnetent() Availability of database might require


Opens the network database and sets system manager action.
the next entry pointer to the first
entry in the database.

setprotoent() Availability of database might require


Opens the protocols database and sets system manager action.
the next entry to the first entry in the
database.

setservent() Availability of database might require


Opens the network services database system manager action.
and sets the next entry pointer to the
first entry in the database.

Guardian Interprocess-Communication Procedures


Guardian interprocess-communication procedures include those for use of:
• Guardian sockets, as described in the TCP/IP Programming Manual for NonStop TCP/IP,
Parallel Library TCP/IP, and NonStop TCP/IPv6.
• Guardian shared memory
• Guardian binary semaphores
• The requester/server $RECEIVE file method
Table 6-5 (page 191) displays information about each Guardian procedure that you can use for
interprocess communication using the latter three methods. Procedures that have been superseded
by other procedures are not shown. The columns of the table contain the following:
Guardian Procedure
The name of the procedure and a brief description.
OSS Notes
Additional considerations or restrictions when the Guardian procedure is called from an
OSS process.
Table 6-6 (page 193) displays information about Guardian procedures useful when performing
interprocess communication. The columns of the table contain the same kind of information as
in Table 6-5. For details about a procedure, refer to the Guardian Procedure Calls Reference Manual
and the Guardian Programmer’s Guide.
Table 6-5 Guardian Interprocess-Communication Procedures
Guardian Procedure OSS Notes

AWAITIO[X]
Checks for completion of nowait operations pending on
one or all Guardian file opens (using file numbers),
including operations on a server process file.

BINSEM_CLOSE_ Closes only a Guardian semaphore, not an OSS


Closes a binary semaphore. semaphore.

BINSEM_CREATE_ Creates, opens, and locks only a Guardian semaphore,


Creates, opens, and locks a binary semaphore. not an OSS semaphore.

BINSEM_FORCELOCK_ Forces a lock on only a Guardian semaphore, not an OSS


Forces a lock on a binary semaphore. semaphore.

Guardian Interprocess-Communication Procedures 191


Table 6-5 Guardian Interprocess-Communication Procedures (continued)
Guardian Procedure OSS Notes

BINSEM_LOCK_ Locks only a Guardian semaphore, not an OSS semaphore.


Locks a binary semaphore.

BINSEM_OPEN_ Opens only a Guardian semaphore, not an OSS


Opens a binary semaphore. semaphore.

BINSEM_UNLOCK_ Relinquishes a lock on only a Guardian semaphore, not


Relinquishes a lock on a binary semaphore. an OSS semaphore.

CANCEL
Cancels the oldest outstanding nowait operation on a
specified Guardian open, such as a server process file.

CANCELREQ
Cancels a a specific outstanding nowait operation on a
specified Guardian file open, such as a server process file.

FILE_CLOSE_
Closes a Guardian file open, such as a server process file.

FILE_GETINFO_
Provides error information and characteristics about a
Guardian file open, such as a server process file.

FILE_GETRECEIVEINFO_
Returns information about the last message read from the
$RECEIVE file of the calling process.

FILE_OPEN_
Establishes a Guardian file open with a file number. Can
be used by:
• A requester process to open a server process file
• A server process to open its $RECEIVE file

READUPDATE[X]
Reads a message from the $RECEIVE file of a server
process, expecting to reply to the message sender in a
subsequent call to REPLY[X].

REPLY[X]
Replies through the $RECEIVE file of a server process to
a message that was previously read by READUPDATE[X].

SEGMENT_ALLOCATE_ Allocates both flat and selectable segments.


Allocates a virtual memory space to a flat or selectable
extended data (memory) segment.

SEGMENT_DEALLOCATE_ Deallocates both flat and selectable segments.


Deallocates a flat or selectable extended data (memory)
segment.

SEGMENT_USE_
Makes a selectable segment current (a flat segment need
not be made current). It also returns the last selectable
segment in use.

WRITEREAD[X]
Sends a message to a server process and waits for a reply
(assuming waited I/O).

192 Interprocess Communication


Table 6-6 Guardian Interprocess-Communication-Related Procedures
Guardian Procedure OSS Notes

CONTROL
Issues CONTROL operations to a process that simulates
an input/output device.

CONTROLBUF
Issues CONTROLBUF operations to a process that
simulates an input/output device.

MESSAGESTATUS
Checks the $RECEIVE file of a server process to see
whether a specific message has been canceled.

READ[X]
Reads information from the $RECEIVE file of a server
process.

SETMODE
Issues SETMODE functions to a process that simulates
an input/output device.

SETMODENOWAIT
Performs the same functions as SETMODE but in a nowait
manner.

SETPARAM
Issues SETPARAM operations to a process that simulates
an input/output device.

WRITE[X]
Sends a message to a server process and waits for a reply
(assuming waited input/output).

Guardian Interprocess-Communication Procedures 193


194
7 Managing I/O
This section describes how to manage OSS tape, terminal, and printer I/O. It discusses the
following topics:

Topic Content

“Common and Unique Characteristics” (page 195) Summary of the differences between OSS and UNIX I/O.

“I/O Interoperability” (page 195) The objects on which you can use OSS I/O functions and
Guardian procedures.

“Tape I/O” (page 196) Tape I/O using pax and the Guardian API.

“Terminal I/O” (page 198) Terminal I/O using the OSS API.

“Using OSSTTY to Redirect Input and Output to Guardian Using the OSSTTY facility to redirect the OSS standard
Objects” (page 202) files to Guardian processes and EDIT files.

“Printer I/O” (page 214) Printing OSS files using the OSS and Guardian APIs.

“OSS I/O Management Functions” (page 221) List of each OSS I/O function with notes about its OSS
implementation and its use on Guardian objects.

“Guardian I/O Management Procedures” (page 222) List of each Guardian I/O procedure with notes about its
use on OSS objects.

The major difference between managing I/O with the OSS API and managing I/O with the UNIX
operating system is that the OSS environment offers limited I/O features. For greater control
over most I/O operations, you must use Guardian procedures.

Common and Unique Characteristics


OSS tape I/O and printing are handled by OSS utilities. There are no direct OSS programmatic
tape and printer interfaces. For programmatic control, you must use the Guardian API.

Features Common to UNIX and OSS Terminal I/O Management


OSS terminal I/O is handled as with UNIX network terminals. As in UNIX systems, the name of
the controlling terminal is /dev/tty. Both canonical and noncanonical input are supported.

Features Unique to OSS Terminal I/O Management


Some terminal parameter values have no effect, because all access to the OSS environment is
through the Telserv server and a VT100 terminal emulation or through OSSTTY. The OSS
environment supports two types of windows: static windows, which are opened with the
Subsystem Control Facility (SCF), and dynamic windows, which Telserv or OSSTTY creates
when it receives a connection request.

I/O Interoperability
OSS terminal I/O functions operate only on the terminal device /dev/tty. The functions
cfsetispeed() and cfsetospeed() have no effect on the network terminals (they affect
only local terminals). The function tcsetattr affects both the Telserv and OSSTTY terminals.
There are no OSS I/O functions that apply to printers or tape drives.
Guardian I/O procedures operate only on Guardian devices.

Common and Unique Characteristics 195


Tape I/O
The OSS environment has no programmatic access to tapes. To access tapes in the OSS
environment you must use the pax utility. You can, however, use Guardian procedures to write
OSS files and output directly to tape and read them directly from tape.

Tape I/O With pax


The pax utility reads, writes, and lists files and directories to and from archive files. An archive
file can be a disk or tape file. You can use the pax utility from a C program by invoking it with
the popen() function. For information about the pax utility, refer to the pax(1) reference page
either online or in the Open System Services Shell and Utilities Reference Manual.
Example 7-1 (page 197) shows how to use the pax utility from a program. It reads the names of
files to be backed up from the user's terminal input and passes the list of files to the pax utility
using popen().

196 Managing I/O


NOTE: Normally, you or system operators read from and write to tape archives using commands
and utilities from the command line prompt or shell scripts. This example shows how you can
accomplish the same task programmatically, even though it might be unusual to do so.

Example 7-1 Using the pax Utility From a Program


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

FILE *fpout;
#define MAXLINE 132
char paxbuf[MAXLINE];
char line[MAXLINE];

int main (int argc, char *argv[]) {

/* The program is called with name of a backup (archive) file.


Make sure the correct number of arguments are entered.
If not, print a usage message and exit.
*/
if(argc < 2) {
fprintf(stderr, "Usage: paxopen <backup file>\n");
exit(1);
}
/* Create a string for popen() with the necessary arguments
to the pax command to use it as a filter. */
sprintf(paxbuf, "pax -w -f %s", argv[1]);
/* Open the pax utility. */
if((fpout = popen(paxbuf, "w")) == NULL) {
fprintf(stderr, "popen error on %s\n", paxbuf);
exit(1);
}
/* Copy the names of the files to be backed up to the pax filter. */
for(;;) {
fprintf(stderr, "File to back up (^Y for end of list): ");
if(fgets(line, MAXLINE, stdin) == NULL)
break;
if(fputs(line, fpout) == EOF) {
fprintf(stderr, "fputs error to pipe\n");
exit(1);
}
}
/* Check for errors on input processing. */
if(ferror(stdin)) {
fprintf(stderr, "fgets error\n");
exit(1);
}
/* Check for errors in the execution of the pax command. */
if(pclose(fpout) == -1) {
fprintf(stderr, "pclose error\n");
exit(1);
}
printf("Backup file %s created\n", argv[1]);
exit(0);
}

Tape I/O With the Guardian API


To use a programmatic interface to tape or to use labeled tapes, you must use Guardian
procedures.

Tape I/O 197


Labeled tapes have the following advantages over unlabeled tapes:
• A labeled tape contains information about the contents of the tape that prevent undesired
overwriting of the tape.
• Automatic cartridge systems use only labeled tapes.
• Many systems and vendors use only labeled tapes.
• You can access labeled tapes on different systems than the one your file is on.
To perform read or write operations on an OSS file on a labeled tape, follow these steps:
1. Open the desired OSS file.
2. Open the proper tape file by passing the name of a DEFINE that has the appropriate attributes
as the filename parameter to the FILE_OPEN_ procedure.
3. Position the tape to available space on the tape.
4. Perform read or write operations on the tape with the READX or WRITEX procedure.
5. Close access to the tape with the FILE_CLOSE_ procedure.
DEFINEs are file-system elements that provide a means for passing information, such as attributes,
to a process. DEFINEs allow attributes to be grouped and named. Attributes can then be passed
to a process or retrieved by specifying the name of the DEFINE. For information about DEFINEs
and programming with tapes, refer to the Guardian Programmer’s Guide.

Terminal I/O
The only terminals supported by Open System Services are Telserv windows and OSSTTY
windows, so terminal I/O is the same as that for a UNIX network terminal. OSS also supports
local terminals through OSSTTY, although OSSTTY has the look and feel of a remote terminal.
The OSS terminal interface is described in detail in the termios(4) and tty(7) reference pages
either online or in the Open System Services System Calls Reference Manual.

Accessing Terminals From the OSS Environment


The only way to access the OSS environment interactively is through an OSSTTY window or
through a Telserv virtual terminal, or window, with VT100 emulation.

Static and Dynamic Windows


Telserv provides two kinds of windows: static and dynamic.
• A static window is opened with Telserv SCF commands and with OSSTTY, and can exist
independently of a connection to the OSS environment. (The OSSTTY windows #stdin,
#stdout, and #stderr are considered to be static because they are preconfigured and cannot
be changed while OSSTTY is running.)
• A dynamic window is opened by Telserv in response to a connection request. OSSTTY does
not support dynamic windows.
For additional information about Telserv windows, refer to the Telserv Guide and the TCP/IP
Configuration and Management Manual. For additional information about OSSTTY windows, refer
to “Using OSSTTY to Redirect Input and Output to Guardian Objects” (page 202) and to the Open
System Services Management and Operations Guide.

198 Managing I/O


Blocking and Nonblocking Opens
Both blocking and nonblocking opens are supported for static windows:
• Blocking open: For a Telserv window, the function returns successfully when the connection
to the window is requested and established. For OSSTTY windows, the function returns
successfully when the availability of the redirection target is established.
• Nonblocking open: For a Telserv window, the function returns successfully if a Telserv
connection to the window is already established when the request is made. For an OSSTTY
window, the function does not depend on the availability of the redirection target.
For dynamic windows, only blocking opens are supported. You cannot open a dynamic window
unless a connection has already been established.

Blocking and Nonblocking Terminal I/O


For J-series RVUs, H06.06 and later H-series RVUs, and G06.27 and later G-series RVUs,
nonblocking behavior is supported for Telserv and OSSTTY terminal objects for these functions:
• select()
• FILE_COMPLETE_()
• FILE_COMPLETE_SET_()
• FILE_COMPLETE_GETINFO_()
If you attempt to use these funcions on a terminal process running on a system that is running
RVUs earlier than G06.27 or H06.06:
• select() returns the error ENOTSUP.
• FILE_COMPLETE_() and FILE_COMPLETE_SET_() return the error FEINVALIDOP.
Nonblocking behavior for the open() and fcntl() functions continues to be supported.
Each processor in the system has a terminal helper process that provides support for nonblocking
I/O for terminal devices. Terminal helpers are named processes with names of the form $ZTTnn,
where nn is the processor number. Terminal helper processes are started automatically when
the processor is started. If the terminal helper process stops or terminates abnormally, the
processor halts.

Terminal Parameters
Most of the control characters in the c_cflag field of the termios structure in the termios.h
header file are ignored. The HUPL flag of the c_flag field affects both local and remote terminals.
For more information, refer to the termios(4) and tty(7) reference pages either online or
in the Open System Services System Calls Reference Manual.
Also, the following functions have no effect:
• cfsetispeed()
• cfsetospeed()
• csendbreak()

Control Characters
The default values of control characters are defined in the termios.h header file. The definitions
are in the array specified by the c_cc field of the termios structure. According to the standards
that the OSS environment conforms to, these values can vary from implementation to
implementation.
The OSS API has two terminal I/O modes: canonical mode, in which input data is assembled
into lines, and noncanonical mode, in which input data is not assembled into lines.
Canonical mode control characters, their default values, associated flags, and indexes into the
array specified by the c_cc field of the termios structure are shown in Table 7-1.

Terminal I/O 199


Table 7-1 Canonical Mode Control Characters and Associated Flags in termios.h
Control Character Default Value Associated Flag Index in c_cc

EOF %X04 ^D ICANON VEOF

EOL %X0A ^M ICANON VEOL

ERASE %X08 ^H ICANON VERASE

INTR %X03 ^C ISIG, NOFLSH VINTR

KILL %X15 ^U ICANON VKILL

QUIT %X1C ^\ ISIG, NOFLSH VQUIT

START %X11 ^Q IXON/IXOFF VSTART

STOP %X13 ^S IXON/IXOFF VSTOP

SUSP %X1A ^Z ISIG, NOFLSH VSUSP

Noncanonical mode control characters, their default values, associated flags, and indexes into
the array specified by the c_cc field of the termios structure are shown in Table 7-2.
Table 7-2 Noncanonical Mode Control Characters and Associated Flags in termios.h
Control Character Default Value Associated Flag Index in c_cc

INTR %X03 ^C ISIG, NOFLSH VINTR

MIN %X00 ICANON VMIN

QUIT %X1C ^\ ISIG, NOFLSH VQUIT

START %X11 ^Q IXON VSTART

STOP %X13 ^S IXON VSTOP

SUSP %X1A ^Z ISIG, NOFLSH VSUSP

TIME %X00 ICANON VTIME

Because OSSTTY has no control over the interface from which it reads data, the STOP and START
characters in the stream are discarded. OSSTTY supports flow control for applications when
directed to do so programmatically through tcflow() (TCION and TCIOFF flags).

Accessing Terminals From the Guardian Environment


You might need to access a terminal in an OSS program using Guardian procedures. Example 7-2
(page 201) shows the use of Guardian procedures to read from and write to a Telserv window in
an OSS program. The program uses FILE_OPEN_ to open the Telserv window and then uses
WRITEREADX to write to the Telserv window and read data back. This OSS program uses
Guardian I/O and therefore cannot use OSS job-control features. For example, signals are handled
during OSS file I/O calls, such as EINTR during a read() call, but are deferred during Guardian
file I/O calls, such as a WRITEREADX call.

200 Managing I/O


Example 7-2 Accessing an OSS Terminal With Guardian Procedures in the OSS API
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tal.h>
#include <cextdecs.h(FILE_OPEN_,READX,WRITEX,WRITEREADX,\
PROCESS_GETINFO_,FILE_CLOSE_)>

short filenum; /* file code number */


short retcode; /* procedure call return code */
_cc_status CC; /* condition code */
char *terminal; /* name of terminal */
char hometerm[64]; /* name of home terminal */
short htlen; /* length of home terminal name */
char buffer[134]; /* buffer for input/output line */
char *buf; /* pointer to buffer string */
short bytesread; /* bytes read */

int main(int argc, char *argv[]) {


/* Get the Guardian terminal filename from the command argument. */
if (argc > 1)
terminal = argv[1];
else {
retcode = PROCESS_GETINFO_( /* get Home terminal name */
, /* process handle */
, /* process filename */
, /* maximum length of filename */
, /* actual length of filename */
, /* execution priority */
, /* process handle of MOM */
hometerm, /* home terminal name */
64, /* maximum length of hometerm name */
&htlen /* actual length of hometerm name */
);
/* Check if PROCESS_GETINFO_ was successful. */
if (retcode != 0) {
fprintf(stderr, "PROCESS_GETINFO_ failed: retcode = %d\n", \
retcode);
exit(1);
}
terminal = hometerm;
}
retcode = FILE_OPEN_(terminal, /* name of Guardian terminal */
(short)strlen(terminal), /* terminal name length */
&filenum, /* file number returned */
0, /* open for read/write access */
);
/* Check if the open was successful. */
if (retcode != 0) {
fprintf(stderr, "Can't open %s\n", terminal);
fprintf(stderr, "retcode = %d\n", retcode);
exit(1);
}
/* Write to the terminal using WRITEX. */
CC = WRITEX(filenum, /* terminal file number */
buf = "Type in a line followed by ENTER:", /* output string */
(short)strlen(buf) /* size of string */
);
/* Check for successful terminal write operation. */
if (_status_ne(CC)) {
fprintf(stderr, "WRITEX to terminal failed: %s\n", terminal);
exit(1);
}

Terminal I/O 201


/* Read input from the terminal using READX. */
CC = READX(filenum, /* terminal file number */
buffer, /* input buffer */
sizeof(buffer), /* size of buffer */
&bytesread, /* bytes read */
);
/* Check for successful terminal read operation. */
if (_status_ne(CC)) {
fprintf(stderr, "READX from terminal failed: %s\n", terminal);
exit(1);
}
/* Write and read from the terminal in one operation. */
buffer[0] = ':'; buffer[1] = '\0';/* set up colon (:) prompt */
CC = WRITEREADX(filenum, /* terminal file number */
buffer, /* output string */
1, /* size of output string */
132, /* maximum buffer size */
&bytesread, /* actual bytes read */
);
if (_status_ne(CC)) {
fprintf(stderr, "WRITEREADX from terminal failed: %s\n", \
terminal);
exit(1);
}
buffer[bytesread] = 0;
printf("%s\n",buffer); /* print out data just read */
FILE_CLOSE_(filenum); /* close terminal file */
exit(0);
}

Using OSSTTY to Redirect Input and Output to Guardian Objects


The OSSTTY facility provides a way for OSS processes to interact with the Guardian environment.
OSSTTY enables OSS processes to redirect their standard input, standard output, and standard
error files to Guardian processes and, for standard output only, to Guardian EDIT files. Before
the implementation of OSSTTY, the OSS environment could be accessed only through a Telserv
TELNET session. Applications running in the OSS environment could interact with only one
Guardian process, namely Telserv. The OSSTTY process emulates a terminal, and eliminates the
dependency OSS applications have on TELNET sessions.
Figure 7-1 gives a high-level view of OSSTTY and its role as an intermediary between the OSS
and Guardian environments.

202 Managing I/O


Figure 7-1 OSSTTY Interaction With OSS and Guardian Environments

OSSTTY supports three standard qualifiers: #stdin, #stdout, and #stderr. OSS applications
can redirect their standard input, standard output, and standard error to OSSTTY by using these
qualifiers:

Qualifier Description

/G/name/#stdin Redirects standard input data to the OSSTTY process identified by name.

/G/name/#stdout Redirects standard output data to the OSSTTY process identified by name.

/G/name/#stderr Redirects standard error data to the OSSTTY process identified by name.

OSSTTY, in turn, redirects data from these qualifiers to Guardian objects that you specify when
starting OSSTTY.

Starting OSSTTY
You can start OSSTTY either from the TACL prompt or through the OSH command line. The
following subsections present simple forms of the commands for starting OSSTTY. For detailed
descriptions of all OSSTTY run-time options, see the Open System Services Management and
Operations Guide.

Starting OSSTTY From the TACL Prompt


You can start OSSTTY by entering a run command at the TACL prompt. A general form of a
run command that starts an OSSTTY process is as follows:
TACL> run osstty/ name process-name in input out output term hometerm
This command starts a named OSSTTY process. The in, out, and term parameters specify the
Guardian targets of the OSSTTY process.

Using OSSTTY to Redirect Input and Output to Guardian Objects 203


The value specified for input can be either of the following:
• A Guardian process; for example, $vhs (Guardian virtual hometerm subsystem) or $zhome
(Guardian reliable home terminal).
• Any Telserv terminal.
The OSSTTY process will redirect all data received from the specified input to any process that
uses $process-name.#stdin (Guardian process) or /G/process-name/#stdin (OSS
process) as its standard input.
The value specified for output can be any of the following:
• A Guardian process; for example, $vhs (Guardian virtual hometerm subsystem) or $zhome
(Guardian reliable home terminal).
• Any Telserv terminal.
• A Guardian EDIT file.
OSSTTY will redirect to the specified output all data received from any process that uses
$process-name.#stdout (Guardian process) or /G/process-name/#stdout (OSS process)
as its standard output.
The value specified for hometerm can be either of the following:
• A Guardian process; for example, $vhs (Guardian virtual hometerm subsystem) or $zhome
(Guardian reliable home terminal).
• Any Telserv terminal.
OSSTTY will redirect to the specified hometerm all error messages received from any process
that uses $process-name.#stderr (Guardian process) or /G/process-name/#stderr
(OSS process) as its standard error.

Starting OSSTTY on the OSH Command Line


You can start OSSTTY by specifying the -osstty flag on the osh command line. The osh
command initially routes the input, output, and error file information of the OSS process it
launches to its own standard input, output, and error files. You can specify standard input,
output, and error files for the child process on the osh command as run options or by using the
redirection operators (<, >, 2>); for example:
TACL> osh/ in input, out output, term hometerm/ -osstty
TACL> osh -osstty > output
The values for input, output, and hometerm are as described under “Starting OSSTTY From
the TACL Prompt”.
When -osstty is specified on the osh command line, OSSTTY is launched only if the OSS
shell determines that it is necessary. The OSS shell makes this determination based on the standard
files specified in the run options or through redirection operators: if any one of the files specified
is not accessible to the child process, then OSSTTY is launched. For example, in the following
command, OSSTTY is launched because OSS cannot access the Guardian EDIT file myfile as
an output file:
TACL> osh/out $data.mysubvol.myfile/ -osstty
If the files specified as run options or through redirection operators are accessible to OSS, then
OSSTTY is not launched. For example, the following command does not launch OSSTTY because
Guardian EDIT files are accessible to OSS processes as input:
TACL> osh/ in $data.mysubvol.myfile/ -osstty
Once started, OSSTTY becomes the standard input, standard output, and standard error of the
OSS process, and redirects input, output, and error data to the Guardian targets specified as run
options or through redirection operators.

204 Managing I/O


Examples of OSSTTY Usage
Following are some typical examples of OSSTTY usage.

Redirecting Input From a Guardian Process to an OSS Process


In this example, OSSTTY is used to direct input from $vhs (Guardian virtual hometerm
subsystem) to an ftp client running in OSS.
TACL> run osstty /name $tty, in $vhs, nowait/
TACL> osh
$/usr/ucb/ftp </G/tty/#stdin
OSSTTY is started with its standard input set to $vhs. In the OSS environment, an ftp client is
started, with redirection used to receive input from /G/tty/#stdin. Input received through
$vhs is received by OSSTTY and redirected to /G/tty/#stdin. The nowait parameter is used
to return control to the user immediately after OSSTTY is initiated
The technique illustrated in this example could be used to create an OSS application that receives
input interactively from the Guardian environment (through $vhs).

Redirecting Output From OSS to a Guardian EDIT file


The following example illustrates redirecting output from an OSS command to a Guardian EDIT
file.
TACL> run osstty /name $tty, out editfil, nowait/
TACL> osh -c "ls > /G/tty/#stdout"
The run command starts an OSSTTY process named $tty, with its standard output set to
editfil (assume editfil is a Guardian EDIT file). The osh command starts an OSS shell and
runs an ls command that redirects its output to /G/tty/#stdout/. OSSTTY receives the
output and redirects it to its standard output, which is set to EDITFIL.

Redirecting Output From OSS to a Telserv Terminal


In the following example, output from an ls command is redirected, through OSSTTY, to a
Telserv terminal named $ztn0.#ptycasu1.
TACL> run osstty /name $tty, out $ztn0.#ptycasu1, nowait/
-noserver -idletime 0
TACL> osh
$ ls -l > /G/tty/#stdout
The -noserver and -idletime parameters cause OSSTTY to terminate after the ls command
completes.

Executing a Shell Script and Redirecting Output to a Guardian Process


The following example executes an OSS shell script and uses OSSTTY to direct the output to a
Guardian process. The Guardian process is a logger process that sends all input data from its
$RECEIVE file to an EDIT file.
The following command starts the shell script /home/stu01/user_report with output
redirected to the standard output file.
TACL> osh -c "/home/stu01/user_report" > /G/tty/#stdout
The following command starts the Guardian logger process, named logger, with logfile as its
output file.
TACL> run logger /name $log/ logfile
The following command starts OSSTTY, with the logger process specified for the out and term
parameters. OSSTTY will redirect its standard output (/G/tty/#stdout) and standard error
(/G/tty/#stderr) to the logger process.
TACL> run osstty /name $tty, out $log, term $log, nowait/

Using OSSTTY to Redirect Input and Output to Guardian Objects 205


The logger process receives input through $RECEIVE and sends the data to the log file logfile.
Example 7-3 shows the source code for the logger program.

206 Managing I/O


Example 7-3 Example Logger Program Used With OSSTTY
/* Logger Program used with OSSTTY */

#pragma runnable, symbol, nolist, inspect


/* This is a simple logger program. It does the following:

- Opens its $RECEIVE for interprocess communication.

- Creates an EDIT file that is provided as run-time argument


during instantiation. It is used as a log file.

- Accepts an OPEN from an application and logs the data that


is being written to it.

On the reception of the system CLOSE message, the process


closes the log file and terminates.

Note: The program must be started with the log file name as an
argument.

Do not post a READ on the started process.

The log file will be purged and recreated by the process.

Messages other than OPEN and CLOSE are not handled.

Operations are Waited. */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <tal.h>
#include <cextdecs(FILE_OPEN_, OPENEDIT_, READUPDATEX, REPLY, \
CLOSEALLEDIT, FILE_PURGE_, FILE_GETINFO_, WRITEEDIT)>

/* local macros and defines */

#define MAX_USRMSG 8*1024


#define RECV_QMAX 4047
#define FNAME32_LEN 64
#define O_WAITED_OPEN 0x00

/* public data */

short rcv_fd;
short U_data[4*1024];
short edit_fd ;
short rcv_cnt;

/* public functions */

void file_create(char* file_name);


short tty_info_fnum( short fd);
void dol_RECEIVE_opener(void);
short tty_open_file(char *name, short name_len, short nwio,
short nwopen, short excl, short access, long sync,
short *error);

/* private functions */

void user_message(void);
void system_message(void);

main(int argc, char** argv) {

Using OSSTTY to Redirect Input and Output to Guardian Objects 207


short ret_fd;
_cc_status read_status ;
short error = 0;

/* Create the EDIT file */


file_create(argv[1]);

/* Open $RECEIVE for interprocess communication */


dol_RECEIVE_opener();

/* Exit only when close received from OSSTTY */


for (;;)
{
/* Read from $RECEIVE in waited manner */
read_status = READUPDATEX(rcv_fd,
(char *)U_data,
MAX_USRMSG,
&rcv_cnt);
/* A CCG on $RECEIVE means that a system message has
been received */
if( _status_gt(read_status)) {
error = tty_info_fnum (rcv_fd);
if(error == 6)
system_message ();
}
else
user_message( );
}
}
/* Log the message from OSSTTY to the EDIT file */
void user_message(void) {
short error = 0 ;
error = WRITEEDIT(edit_fd, ,
(char *)U_data,
rcv_cnt);
if (error) {
printf("Unable to write to EDIT file\n");
exit(0);
}
REPLY();
}
/* Service the Open and Close system message */
void system_message(void) {
switch(U_data[0]) {
case -103: /* Open message */
{
REPLY();
break;
}
case -104: /* Close Message */
{
CLOSEALLEDIT();
REPLY();
exit(0);
break;
}
default:
REPLY();
break;
}
}

/* Create the log file */


void file_create(char* file_name ) {
short error = 0;

208 Managing I/O


FILE_PURGE_((char *)file_name,
(short)strlen(file_name));
error = OPENEDIT_((char *)file_name,
(short)strlen(file_name),
&edit_fd,
2/*Write Only*/,
0/* shared*/,
0,/*nowait depth*/
15);
if (error) {
printf("Unable to Created EDIT File\n");
exit(0);
}
}

short tty_info_fnum(short fd) {


short error;
(void) FILE_GETINFO_(fd, &error );
return error;
}

/* Open $RECEIVE in waited manner for interprocess


communication */
void dol_RECEIVE_opener(void) {
short error = 0;
if (( rcv_fd = tty_open_file ("$RECEIVE", 8, 0,
O_WAITED_OPEN,
0/*Shared*/,
0/*Read Write*/,
RECV_QMAX, &error)) < 0 ) {
printf("Can't open $RECEIVE\n");
}
}
short tty_open_file (char *name, short name_len, short nwio, short nwopen,
short excl, short access, long sync, short *error)
{
char fname [FNAME32_LEN + 1];
short fd;
short options = 0;

strncpy (fname, name, name_len);


fname[name_len]='\0';
*error = FILE_OPEN_ (fname, name_len,
&fd, access, excl, nwio, (short) sync,
options);
return fd; /* fd = -1 if FILE_OPEN failed */
}

Running an Interactive OSS Session From a TACL Macro


This example shows a method for using OSSTTY to run multiple interactive OSS sessions from
the Guardian environment. The example behaves similarly to the the Guardian Define Process
facility and the TACL #INLINE facility. The example consists of a TACL program that starts an
OSS shell, starts an OSSTTY process, submits OSS commands to the shell, and uses OSSTTY to
redirect output, prompts, and error messages to the Guardian environment.
The program takes into account the fact that OSS shell commands issue input prompts through
the standard error file. The program redirects the shell’s standard error file to the standard output,
then tests each line of output to determine whether it is a prompt or some other message.

Using OSSTTY to Redirect Input and Output to Guardian Objects 209


Note the following about using this program:
• If you give the program a process name qualified with the system name, such as
\mysys.$sh, the program fails with a TACL error.
• If #INFORMAT is set to TACL, you must escape TACL special characters like the vertical
bar with a tilde: ~|
• If you run a utility, such as cat, SCF, or VPROC, the "be" and "print" routines will hang.
The TACL program consists of the following procedures.

Procedure Description

SH $name Starts a named OSSTTY process and an OSS shell process, setting up the necessary
redirection.

UNSH $name Removes the specified previously defined OSSTTY/OSS shell environment.

TELL $name command-string Sends a single command to the specified previously defined OSSTTY/OSS shell
environment. Also displays any output from a prior command.

PRINT $name Displays any output from the specified previously defined OSSTTY/OSS shell
environment.

BE $name Enters interactive mode with the specified previously defined OSSTTY/OSS shell
environment. The user can enter commands and receive responses repeatedly,
until <Ctrl-y> is entered. Entering <Ctrl-y> causes the procedure to exit interactive
mode, but leaves the OSSTTY/OSS shell environment intact.

RESET $name Informs a previously defined OSSTTY environment that there is an interactive
prompt outstanding. (Used in the event that there is a prompt outstanding, but
the procedures do not recognize the prompt.)

The following steps illustrate the use of these procedures:


1. load the TACL macro (required once per TACL session).
TACL> load /keep 1/ sh
2. Start an OSSTTY process named $n1 and an OSS shell that uses $n1.
TACL> sh $n1
3. Send a pwd command to the shell and OSSTTY. There is no response because none is queued.
TACL> tell $n1 pwd
4. Send a cd command to the shell and OSSTTY. The queued response from the prior command
is displayed.
TACL> tell $n1 cd/usr/bdir/webserver

/G/SYSTEM/ADIR

The TACL procedures are shown in Example 7-4.

210 Managing I/O


Example 7-4 Running an Interactive OSS Session From the Guardian Environment
== TACL macro for an interactive OSS session from the Guardian environment
== file: sh
== Start an OSSTTY process and OSS shell
?section sh routine
#push pname
[#case [#argument /value pname/ processname /syntax/
otherwise]
|1|
#set pname [#shiftstring /up/ [pname]]
[#case [#argument end
otherwise]
|1|
[#if [#processexists [pname]] |then|
#output Process [pname] already exists -- terminating.
#output
#pop pname
#return
] == end if

|otherwise|
#output Extraneous input -- terminating.
#output
#pop pname
#return
] == end case

|2|
#output Expecting a nonexistent process name -- terminating.
#output
#pop pname
#return
] == end case
#set pname [#shiftstring /down/ [pname]]
#chardel pname 1 for 1
[#push [pname]^in^buf [pname]^out^buf [pname]^prompt^buf [pname]^need^prompt
[pname]^status stdin stdout
] == end push
#set stdin /G/[pname]/#stdin
#set stdout /G/[pname]/#stdout
sink [#newprocess $system.system.osstty /name $[pname], nowait,
inv [pname]^in^buf dynamic, outv [pname]^out^buf/
-server]
sink [#newprocess $system.system.osh /status [pname]^status, nowait/
-p /bin/sh < [stdin] > [stdout] 2> [stdout]]

sink [#wait [pname]^out^buf]


#set [pname]^prompt^buf [#lineget [pname]^out^buf 1]

#set [pname]^need^prompt -1
#pop pname stdin stdout

== Remove previously defined OSSTTY/OSS shell environment


?section unsh routine
#frame
#push pname prog name
[#case [#argument /value pname/ processname /syntax/
otherwise]
|1|
#set pname [#shiftstring /up/ [pname]]
[#case [#argument end
otherwise]
|1|
|otherwise|

Using OSSTTY to Redirect Input and Output to Guardian Objects 211


#output Extraneous input -- terminating.
#output
#unframe
#return
] == end case

|2|
#output Expecting a process name -- terminating.
#output
#unframe
#return
] == end case
#set name [pname]
#chardel name 1 for 1
[#if not [#variableinfo /existence/ [name]^in^buf] |then|
#output Nothing to get rid of.
#output
#unframe
#return
] == end if
[#if [#processexists [pname]] |then|
#set prog [#fileinfo /file/ [#processinfo /programfile/
[pname]]]
[#if not [#match osstty [prog]] |then|
#output [pname] is not an OSSTTY process.
#output
#unframe
#return
] == end if

[#if [#emptyv [name]^status] |then|


sink [#stop [#variableinfo /process/ [name]^status]]
] == end if

sink [#stop [pname]]


] == end if
#pop [name]^in^buf [name]^out^buf [name]^prompt^buf [name]^need^prompt
#pop [name]^status
#unframe

?section tell routine


#frame
#push pname out^line

#if [#argument /value pname/ processname]


#chardel pname 1 for 1
[#if not [#variableinfo /existence/ [pname]^in^buf] |then|
#output Process not known.
#output
#unframe
#return
] == end if

#set [pname]^out^buf
#append [pname]^in^buf [#rest]
sink [#wait [pname]^out^buf [pname]^status]
#set [pname]^need^prompt -1
print $[pname]

[#if not [#variableinfo /existence/ [pname]^status] |then|


== print complained. Bail-out now
#unframe
#return
] == end if not variableinfo existence pname^status then

212 Managing I/O


#unframe

== Display output from previously defined OSSTTY/OSS shell environment


?section print routine
#frame
#push pname out^line

#if [#argument /value pname/ processname]


#if [#argument end]
#chardel pname 1 for 1
[#if not [#variableinfo /existence/ [pname]^in^buf] |then|
#output Process not known.
#output
#unframe
#return
] == end if

[#loop |while| [[pname]^need^prompt] |do|


#delay 1 == Get out of the way of the shell
#set out^line [#extract [pname]^out^buf]
[#if not [#emptyv [pname]^status] |then|
#set [pname]^need^prompt 0
#output Process $[pname] died ([[pname]^status]). Cleaning up.
#output
#outputv [pname]^out^buf
unsh $[pname]
#unframe
#return
] == end if not emptyv pname^status then

[#if [#match [[pname]^prompt^buf] [out^line]] |then|


#set [pname]^need^prompt 0
|else|
#outputv out^line
] == end if
] == end loop
#unframe

== Enter interactive mode with previously defined OSSTTY/OSS


== shell environment
?section be routine
#frame
#push pname done in^line out^line

#if [#argument /value pname/ processname]


#chardel pname 1 for 1
[#if not [#variableinfo /existence/ [pname]^in^buf] |then|
#output Process not known.
#output
#unframe
#return
] == end if

#set done 0
[#loop |while| not [done] |do|
#inputv in^line [pname]^prompt^buf
[#if [#inputeof] |then|
#set done -1
|else|
#set [pname]^out^buf
#appendv [pname]^in^buf in^line
#set [pname]^need^prompt -1
sink [#wait [pname]^out^buf [pname]^status]

Using OSSTTY to Redirect Input and Output to Guardian Objects 213


print $[pname]

[#if not [#variableinfo /existence/ [pname]^status] |then|


== print complained that the process died. Bail-out now
#unframe
#return
] == end if not variableinfo /existence/ pname^status then

] == end if
] == end loop
#unframe

== Inform previously defined OSSTTY/OSS shell environment of


== prompt outstanding
?section reset routine
#frame
#push pname

#if [#argument /value pname/ processname]


#chardel pname 1 for 1
[#if not [#variableinfo /existence/ [pname]^in^buf] |then|
#output Process not known.
#output
#unframe
#return
] == end if
#set [pname]^need^prompt 0
#unframe

Printer I/O
The OSS API has no function that accesses printers or spoolers directly. You cannot write directly
to printers with the OSS API. To print from an OSS program or get information about a print
job, you access the Guardian spooler with the lp or lpstat utility.
You can, however, write OSS files and output directly to a printer or to the Guardian spooler
using the Guardian API, as described later in this subsection.

Printing With the OSS API


There are no OSS functions that have direct access to a printer or printer spooler. To print an
OSS file from a program, you can use the popen() function to call the lp or lpstat utility. For
information about these utilities, refer to the lp(1) and lpstat(1) reference pages either
online or in the Open System Services Shell and Utilities Reference Manual, or refer to the Open System
Services User’s Guide.
Example 7-5 shows how to print to the default printer with a program. It generates text that is
output to the default printer using the popen() function. The contents of the specified input
pathname is printed on the default line printer with its name on the banner page.

214 Managing I/O


Example 7-5 Printing an OSS File With the lp Utility
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

FILE *fpin, *fpout;


#define MAXLINE 132
char lpbuf[MAXLINE];
char line[MAXLINE];

int main (int argc, char *argv[]) {

if(argc < 2) {
fprintf(stderr, "Usage: lpopen <pathname>\n");
exit(1);
}
/* Open the input file. */
if((fpin = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "Can't open %s\n", argv[1]);
exit(1);
}
/* Create a string for popen() with the name of the file to be
printed in the title. */
sprintf(lpbuf, "lp -t %s", argv[1]);

/* Open the line printer program. */


if((fpout = popen(lpbuf, "w")) == NULL) {
fprintf(stderr, "popen error on %s\n", lpbuf);
exit(1);
}
/* Copy the contents of the file to the line printer filter. */
while(fgets(line, MAXLINE, fpin) != NULL) {
if(fputs(line, fpout) == EOF) {
fprintf(stderr, "fputs error to pipe\n");
exit(1);
}
}
/* Check for errors on input file processing. */
if(ferror(fpin)) {
fprintf(stderr, "fgets error\n");
exit(1);
}
/* Check for errors in execution of lp command. */
if(pclose(fpout) == -1) {
fprintf(stderr, "pclose error\n");
exit(1);
}
printf("File %s output to line printer\n", argv[1]);
exit(0);
}

Printing OSS Files With the Guardian API


You can send OSS files and output to the Guardian spooler or send them directly to a printer
using Guardian procedures.

Sending an OSS File to the Spooler


You can send OSS files and output to the Guardian print spooler and take advantage of the
spooler features. For example, your program can examine the queues of available printers and
move a job to a printer whose queue becomes unexpectedly shorter because of a job cancellation,

Printer I/O 215


or away from a printer that is experiencing delays. You can also access spoolers that are on other
systems than the file you want to print.
Example 7-6 (page 217) shows how to send an OSS file to the spooler and how to control the
spooler from an OSS program using Guardian spooler procedures. The printer is opened using
FILE_OPEN_, then SPOOLSTART is called to establish a level-3 spooling session using a level-3
buffer to compress and block data. The SPOOLCONTROL procedure is used to send control
codes to the level-3 buffer, and the SPOOLWRITE procedure is used to compress and block data
in the level-3 buffer. When the level-3 buffer is full, the buffer is written to the collector. The
SPOOLEND procedure is used to write any remaining data from the level-3 buffer and complete
the job being spooled at level 3. The printer name is specified in Guardian filename format (for
example, $s.#default), because printer names are inaccessible using the OSS pathname format.
For information about the SPOOLCONTROL, SPOOLEND, SPOOLSTART, and SPOOLWRITE
procedures, as well as other spooler procedures, refer to the Spooler Programmer’s Guide.

216 Managing I/O


Example 7-6 Sending an OSS File to the Guardian Spooler
/* Example: Sending an OSS file to the Guardian Spooler */

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

#include <cextdecs.h(FILE_OPEN_,FILE_CLOSE_,\
SPOOLSTART, SPOOLCONTROL,\
SPOOLWRITE,SPOOLEND)>

#define MAXLINE 132


short filenum; /* file code number */
short retcode; /* procedure call return code */
char *printer; /* name of printer */
char *pathname; /* name of file to print */
short size; /* number of bytes used in buffer */
FILE *infile; /* input file to be printed */

#ifdef _TNS_E_TARGET || _TNS_R_TARGET


char buffer[MAXLINE]; /* buffer for print line */
#else
char _lowmem buffer[MAXLINE];
#endif

short l3buffer[512]; /* level-3 buffer for spooler,


note that it is not lowmem, even in CISC */

int main(int argc, char *argv[]) {


/* Get the Guardian printer filename and the name of the file to print.*/
if (argc > 1)
printer = argv[1];
else
printer = "$s.#default";

if (argc > 2)
pathname = argv[2];
else
pathname = __FILE__;

if((infile = fopen(pathname, "r")) == 0) {


perror("Can't open file");
printf("File name is %s\n", pathname);
exit(1);
}
retcode = FILE_OPEN_(printer, /* name of Guardian printer */
(short)strlen(printer), /* printer name length */
&filenum, /* file number returned */
2, /* open for write access */
1, /* open for exclusive use */
);

/* Check if open was successful. */


if (retcode != 0) {
fprintf(stderr, "Can't open %s\n", printer);
fprintf(stderr, "retcode = %d\n", retcode);
exit(1);

} /* Call SPOOLSTART to specify the job's attributes. */


/* in NMC, the "16-bit" and "32-bit" level-3 buffers are equivalent
Using the "32-bit" version makes the code work better with CISC C */
retcode = SPOOLSTART(
filenum, /* file number of spooler job file */
, /* old 16-bit level-3 spooler buffer */

Printer I/O 217


, /*
stick with default location */
, /*
form name for the job */
, /*
report name for the job */
, /*
number of copies */
, /*
page size (in lines) */
047,
/* flag - attributes of job */
/* 040 - hold after bit on */
/* 007 - job priority = 7 */
, /* owner of job */
, /* maximum number of lines allowed for job */
, /* maximum number of pages allowed for job */
, /* filename of spooler collector */
, /* alternative parameter to collector filenum */
l3buffer /* 32 bit pointer to l3 buffer */
);
if (retcode != 0) {
fprintf(stderr, "SPOOLSTART failed, retcode = %d\n", retcode);
exit(1);
}
/* Position the paper to top of form. */
retcode = SPOOLCONTROL( /* send control code to spooler */
, /* 16-bit version of level-3 buffer */
1, /* forms control mode */
0, /* top of form control code */
&size, /* number of bytes used in level-3 buffer*/
l3buffer /* 32-bit version of level-3 buffer */
);
if (retcode != 0) {
fprintf(stderr,"SPOOLCONTROL failed on printer: %s\n", printer);
fprintf(stderr,"retcode = %d\n", retcode);
exit(1);
}

/* Read input file, one line at a time, and send to spooler. */


while(fgets(buffer, MAXLINE, infile)) { /* get line from input file */
retcode =
SPOOLWRITE(, /* 16-bit version of level-3 buffer */
#ifdef _TNS_E_TARGET || _TNS_R_TARGET
(short *)buffer,
#else
(short _near *)buffer, /* print line */
#endif
(short)strlen(buffer), /* size of print line */
&size, /* number of bytes used in level-3 buffer */
l3buffer /* data is compressed and blocked
into the level-3 buffer */
);

/* Check for successful spooler write operation. */


if (retcode != 0) {
fprintf(stderr, "SPOOLWRITE failed: %s\n", printer);
fprintf(stderr, "retcode = %d\n", retcode);
exit(1);
}
}

/* Position the paper to top of form again. */


retcode = SPOOLCONTROL( /* send control code to spooler */
, /* 16-bit level-3 buffer */
1, /* forms control mode */
0, /* top of form control code */
&size, /* number of bytes used in level-3 buffer*/
l3buffer /* 32-bit level-3 buffer */
);
if (retcode != 0) {

218 Managing I/O


fprintf(stderr, "SPOOLCONTROL failed: %s\n", printer);
fprintf(stderr, "retcode = %d\n", retcode);
exit(1);
}

retcode = SPOOLEND( /* complete the spool job */


, /* 16-bit level-3 buffer */
0104, /* flag - attributes of job */
/* 0100 - hold bit on */
/* 0004 - job priority = 4 */
l3buffer
);
if (retcode != 0) {
fprintf(stderr, "SPOOLEND error %d\n", retcode);
exit(1);
}

fclose(infile); /* close input file */


FILE_CLOSE_(filenum); /* close printer file */
printf("File %s spooled to %s printer\n", pathname,printer);
exit(0);

return 0; /* keep compiler happy */


}

Sending an OSS File Directly to a Printer


Your application can send an OSS file or output directly to a printer.
Example 7-7 (page 220) shows how to send an OSS file directly to a printer. You must specify the
printer using the Guardian filename format; you cannot access a printer by using its name in the
/G directory. For further information on working with printers directly, refer to the Guardian
Programmer’s Guide. In this example, the printer is opened using the Guardian FILE_OPEN_
procedure, control messages are sent using the CONTROL procedure, and data is written using
the WRITEX procedure. This example uses the escape sequences for a 5515/5516/5518 printer.
Control codes are dependent on the printer. They are listed in the Guardian Programmer’s Guide
and in manuals for the printer you are using.

Printer I/O 219


Example 7-7 Sending an OSS File Directly to a Printer Using the Guardian API
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tal.h>
#include <cextdecs.h(FILE_OPEN_,CONTROL,WRITEX,FILE_CLOSE_)>

short filenum; /* file code number */


short retcode; /* procedure call return code */
_cc_status CC; /* condition code */
char *printer; /* name of printer */
char *pathname; /* name of file to print */
char buffer[134]; /* buffer for print line */
FILE *infile; /* input file to be printed */

int main(int argc, char *argv[]) {

/* Get the Guardian printer filename and the name of the file to print.*/
if (argc > 1)
printer = argv[1];
else
printer = "$s.#default";
if (argc > 2)
pathname = argv[2];
else
pathname = "/usr/include/stdio.h";
if((infile = fopen(pathname, "r")) == 0) {
perror("Can't open file");
exit(1);
}
retcode = FILE_OPEN_(printer, /* name of Guardian printer */
(short)strlen(printer), /* printer name length */
&filenum, /* file number returned */
2, /* open for write access */
1, /* open for exclusive use */
);
/* Check if open was successful. */
if (retcode != 0) {
fprintf(stderr, "Can't open %s\n", printer);
fprintf(stderr, "retcode = %d\n", retcode);
exit(1);
}

/* Position the paper to top of form. */


CC = CONTROL(filenum, /* send control code to printer */
1, /* forms control mode */
0 /* top of form control code */
);
if (_status_ne(CC)) {
fprintf(stderr, "Illegal control code to printer: %s\n",\
printer);
exit(1);
}
/* Read the input file, one line at a time, and send it to printer. */
while(fgets(buffer, 132, infile)) { /* get line from input file */
CC = WRITEX(filenum, /* write buffer to printer */
buffer, /* printer buffer */
(short)strlen(buffer) /* size of text string */
);
/* Check for successful printer write operation. */
if (_status_ne(CC)) {
fprintf(stderr, "Write to printer failed: %s\n", printer);
exit(1);
}

220 Managing I/O


}
/* Position the paper to top of form again. */
CC = CONTROL(filenum, /* send control code to printer */
1, /* forms control mode */
0 /* top of form control code */
);
if (_status_ne(CC)) {
fprintf(stderr, "Illegal control code to printer: %s\n",\
printer);
exit(1);
}
fclose(infile); /* close input file */
FILE_CLOSE_(filenum); /* close printer file */
exit(0);
}

OSS I/O Management Functions


Table 7-3 (page 221) displays information about each OSS function that you can use to manage
I/O. The columns of the table contain the following:
OSS Function
The name of the function and a brief description.
OSS Notes
Notes about the OSS implementation of the function. The note “Can return extended errors”
means that the function can return errors that are HP extensions to the XPG4 specification.
Refer to the function’s reference page for further information.
Guardian Notes
Notes about using the function from a Guardian process.
The information in this table is only a summary of the information in the reference page for a
function. For details, refer to the reference pages either online or in the Open System Services
Library Calls Reference Manual.

NOTE: To determine which RVUs support an OSS function, see Appendix A (page 389).
Table 7-3 OSS I/O Functions
OSS Function OSS Notes Guardian Notes

cfgetispeed()
Gets the input baud rate for a
terminal.

cfgetospeed()
Gets the output baud rate for a
terminal.

cfsetispeed() Does not affect baud rate.


Sets the input baud rate for a
terminal.

cfsetospeed() Does not affect baud rate.


Sets the output baud rate for a
terminal.

OSS I/O Management Functions 221


Table 7-3 OSS I/O Functions (continued)
OSS Function OSS Notes Guardian Notes

ctermid() If the parameter is a null pointer, the For Guardian TNS processes, it returns
Generates the pathname for a string is stored in an internal static an empty string and errno is set to
controlling terminal. area and the address is returned. The ENOTOSS.
next call to this function overwrites
the contents of the internal static area.
Can return extended errors.

fpathconf() Can return extended errors.


Retrieves file implementation
characteristics.

isatty() Can return extended errors.


Tests for a terminal.

pathconf() Can return extended errors.


Retrieves file implementation
characteristics.

tcdrain() Can return extended errors.


Waits for output to complete.

tcflow() Can return extended errors.


Performs flow control functions.

tcflush() Can return extended errors.


Flushes nontransmitted output data
and nonread input data.

tcgetattr() Can return extended errors.


Gets the attributes associated with a
terminal.

tcsendbreak() Can return extended errors.


Sends a “break” to an asynchronous
serial data line.

tcsetattr() Can return extended errors.


Sets the attributes associated with a
terminal.

ttyname() Can return extended errors.


Gets the name of a terminal.

Guardian I/O Management Procedures


Table 7-4 displays information about each Guardian procedure that you can use to manage I/O.
Procedures that have been superseded by other procedures are not shown. Spooler procedures
are not shown; for information about these, see the Spooler Programmer’s Guide. The columns of
the table contain the following:
Guardian Procedure
The name of the procedure and a brief description.
OSS Notes
Additional considerations or restrictions when the Guardian procedure is used on OSS
processes.
For details about a procedure, refer to the Guardian Procedure Calls Reference Manual.

222 Managing I/O


Table 7-4 Guardian I/O Procedures
Guardian Procedure OSS Notes

CHECKSETMODE
Allows the primary process of a process pair to propagate
SETMODE operations to the backup process of the pair.

CONTROL
Performs device-dependent I/O operations.

CONTROLBUF
Performs device-dependent I/O operations that require
a data buffer.

DEVICE_GETINFOBYLDEV_
Obtains the logical and physical attributes of a device.

LABELEDTAPESUPPORT
Provides a way for nonprivileged programs to determine
whether labeled-tape processing is enabled on the system.

SETMODE
Sets device-dependent procedures.

SETMODENOWAIT
Sets device-dependent procedures in a nowait manner
on nowait files.

Guardian I/O Management Procedures 223


224
8 Using Logging Mechanisms
This section describes how to log information in the OSS environment.
You can log information in two ways in the OSS environment:
• With the OSS logging functions
• With Event Management Service (EMS) procedures
Use the OSS logging functions in portable applications. These functions enable you to use the
function calls of the Berkeley Software Distribution (BSD) UNIX logging mechanism to send log
messages. However, rather than sending log messages to a logging demon, the OSS logging
mechanism sends log messages to EMS.
EMS is a collection of Guardian processes, tools, and interfaces that collects and distributes
messages. EMS relays OSS log messages to destinations such as the system operator’s message
terminal (which is somewhat like a UNIX console). The destinations of the log messages are
determined by the manager of the system that your application is running on and are set up
using EMS.
Use EMS procedures in OSS programs that are written specifically for the OSS environment.
EMS procedures enable you to provide more concise and meaningful events than would be
produced using the OSS logging functions. You use EMS by calling Guardian procedures. EMS
procedures are not discussed in this guide. For information about using EMS, refer to the EMS
Manual.
OSS processes can receive EMS messages by starting a consumer distributor process in the same
way a Guardian process can. An OSS process must use Guardian file-system and process-control
procedures to start and communicate with the consumer distributor.
This section discusses the following topics:

Topic Content

“Common and Unique Characteristics” (page 225) Summary of the differences between OSS and UNIX
logging mechanisms.

“Logging Interoperability” (page 226) The processes in which you can use OSS logging
functions.

“How to Log Information With the OSS API” (page 226) How to use the OSS logging functions.

“OSS Logging-Mechanism Functions” (page 232) List of each OSS logging mechanism function with notes
about its OSS implementation and use on Guardian
processes.

Common and Unique Characteristics


The behavior of the OSS logging functions are the same as those of the BSD UNIX logging
functions, but the ways in which the BSD and OSS functions perform their tasks are different.

Features Common to UNIX and OSS Logging


The OSS logging functions are the same as the BSD logging functions, but they might be somewhat
different from message-logging functions in other varieties of the UNIX operating system.
The OSS API provides the logging functions shown in Table 8-1.

Common and Unique Characteristics 225


Table 8-1 OSS Logging Functions
Function Description

closelog() Closes the connection to the collector

openlog() Initializes logging parameters

setlogmask() Sets the EMS event log mask

syslog() Logs messages

These functions are described in closelog(3), openlog(3), setlogmask(3), and syslog(3)


reference pages, which are available either online or in the Open System Services Library Calls
Reference Manual.

Features Unique to OSS Logging


The OSS logging mechanism sends event messages to an EMS collector process rather than to a
syslogd process as used on some versions of the UNIX operating system. A collector process
gathers EMS events and their associated tokens and sends them to destinations determined by
the system manager. One of the EMS tokens contains message text.
Authorization, demon, kernel, and mail facilities are in the Guardian environment and do not
generate OSS events or messages.
Some priorities, facilities, and options used in logging on BSD versions of the UNIX operating
system have no effect in the OSS environment. For example, the LOG_NOWAIT option of the
logopt parameter of the openlog() function has no effect.
A child process uses the collector that the parent process passes to it in the EMS_COLLECTOR
environment variable.
For detailed information about event messages, the kinds of events to log, and how messages
are routed, refer to the EMS Manual.

Logging Interoperability
You can call OSS logging functions from a Guardian module that is part of an OSS process. You
cannot use the LOG_PID option of the openlog() function on a Guardian process.
OSS processes have the same access to EMS procedures as do Guardian processes. Both OSS
processes and Guardian processes can:
• Call any of the EMS procedures for constructing events
• Open collectors and send them events using the WRITEREAD or WRITEREADX procedures
• Start a consumer distributor and receive EMS event messages
An OSS process must use Guardian file-system and process-control procedures to start and
communicate with the consumer distributor. For further information about using EMS, refer to
the EMS Manual.

How to Log Information With the OSS API


You log information by using the OSS syslog() function. If you want to use the default settings,
simply call the syslog() function.
You can customize logging by performing one or both of the following actions before you call
syslog():
• Call the setlogmask() function to specify the kinds of events to be logged.
• Call the openlog() function to initialize logging parameters.
You can explicitly close the EMS collector process you are using with the closelog() function.

226 Using Logging Mechanisms


The OSS logging functions use the parameters and default parameter values shown in Table 8-2.
The parameters and default values are described in detail later in this section.
Table 8-2 OSS Logging Function Parameters and Default Values
Parameter of Function Default Value Description of Default Value

facility openlog() LOG_USER Logs messages generated by


user processes and displays
the facility string USER.

ident openlog() “syslog” Causes the identity string


“syslog” to appear in
messages.

level syslog() LOG_INFO Assigns the level LOG_INFO


to the event and displays
the level string INFO.

logopt openlog() LOG_ODELAY Opens a collector process


only when the first message
is logged.

maskpri setlogmask() LOG_UPTO (LOG_DEBUG) Logs events of all priorities.

message syslog() Points to the display format


and text that you supply.

The values of these parameters appear in an OSS logging message in the following order:
facility level[,PID = pid] (identity) : message-text
The content of message-text is pointed to by the message parameter.
The values of the logopt and maskpri parameters do not appear in OSS log messages.
The OSS process ID appears in the message if you specify the LOG_PID option in the logopt
parameter of the openlog() function, as described in “logopt Parameter” (page 229).

Specifying a Collector
A user of your application can specify an EMS collector process from the shell by setting the OSS
environment variable EMS_COLLECTOR to the desired collector. You must export the variable
before using the collector. You use the export command to both set the value of the variable and
export it as follows:
export EMS_COLLECTOR=\$COL
In this example, the backslash (\) is required to prevent the shell from interpreting $COL as a
shell variable, and $COL represents the name of the collector.
You can have event messages sent to $0, the local primary collector, if, for some reason a message
cannot be sent to the collector specified by a user with the EMS_COLLECTOR environment variable.
To send events to $0 as a backup, specify the LOG_CONS option in the logopt parameter of the
openlog() function, as described in “logopt Parameter” (page 229).

Specifying the Severity Level of Logged Events


You can specify the severity level of events you want logged by setting the maskpri parameter
of the setlogmask() function. For example, setting the maskpri parameter to LOG_WARNING
causes only events of severity LOG_WARNING to be logged.
You can use the LOG_UPTO operator in the maskpri parameter to select the level through which
events are logged. For example, setting maskpri to LOG_UPTO(LOG_INFO) causes all events
except those of LOG_DEBUG to be logged. There is no default value for maskpri, so you must
set this value yourself.

How to Log Information With the OSS API 227


Table 8-3 lists the names and event numbers of the level parameter in descending order of
severity. The level parameter is also displayed as a string in the message, and this string is also
listed in Table 8-3.
Table 8-3 Logging Level Event Numbers and Strings
Level EMS Event Number Message String

LOG_EMERG 5 EMERGENCY (most severe)

LOG_ALERT 6 ALERT

LOG_CRIT 7 CRITICAL

LOG_ERR 8 ERROR

LOG_WARNING 9 WARNING

LOG_NOTICE 10 NOTICE

LOG_INFO 11 INFO

LOG_DEBUG 12 DEBUG (least severe)

Initializing Logging Parameters


The openlog() function initializes the Event Management Service (EMS) event log parameters
that are used by the OSS logging mechanism. It enables you to change the values of the parameters
listed in Table 8-4 if you do not want to use the default values.
Table 8-4 openlog() Parameters Used by OSS Logging Mechanism
Parameter Description

facility The part of the system you specify as having generated the event message

ident An event subject string that appears in the message

logopt Logging options

facility Parameter
The facility parameter enables you to specify the part of the system that generates the event
message. The default facility is LOG_USER; this is the only facility that has meaning in the OSS
environment. Although authorization, demon, kernel, and mail facilities are in the Guardian
environment and do not generate OSS events or messages, you can use the openlog() function
to specify any facility.
The openlog() function changes the default facility only if the facility parameter is nonzero.
The value of LOG_KERN is 0, so to change the facility to LOG_KERN, change its value to 1 using
the exclusive-or operator, as shown in the following example:
openlog(LOG_KERN | 1);
The facility parameter is also displayed as a string in the OSS log message. The facilities and
their strings are listed in Table 8-5.
Table 8-5 OSS Logging Facilities
Facility Message String Description

LOG_AUTH AUTH Messages generated by the login, su, and other shell
commands or utilities belonging to a user authorization
system.

LOG_CRON CRON Messages generated by a clock demon.

LOG_DAEMON DAEMON Messages generated by system demons.

228 Using Logging Mechanisms


Table 8-5 OSS Logging Facilities (continued)
Facility Message String Description

LOG_KERN KERNEL Messages generated by the kernel.

LOG_LOCAL[0-7] LOCAL[0-7] Messages generated by local facilities. This option is


reserved for local site use.

LOG_LPR LPR Messages generated by a line printer subsystem.

LOG_MAIL MAIL Messages generated by a mail subsystem.

LOG_NEWS NEWS Messages generated by a network news subsystem.

LOG_SYSLOG SYSLOG Messages generated by a syslogd demon.

LOG_USER USER Messages generated by user processes. This is the default


value.

LOG_UUCP UUCP Messages generated by a UNIX-to-UNIX copy program


(UUCP) subsystem.

identity Parameter
The identity parameter enables you to specify an event subject string to appear in the OSS
log message. The default subject string is “syslog”.

logopt Parameter
The logopt parameter enables you to specify logging options. You can specify any set of options.
To specify more than one option, separate the options with the OR operator (|), as in the following
example:
openlog(LOG_CONS | LOG_PID);
The default value of logopt is LOG_ODELAY, which waits until the first message is logged before
opening a collector. Table 8-6 (page 229) lists the logging options.
Table 8-6 OSS Logging Options
Option Description

LOG_CONS Sends the event message to the local primary collector, $0, if the message cannot be
sent to the collector specified by the EMS_COLLECTOR environment variable

LOG_NDELAY Opens the connection to the collector process immediately

LOG_NOWAIT Has no effect

LOG_ODELAY Waits until the first message is logged before opening the connection to the collector
process

LOG_PERROR Has no effect

LOG_PID Includes the OSS process ID of the calling process in each event message

If you specify both LOG_NDELAY and LOG_ODELAY, LOG_NDELAY takes effect.

NOTE: Do not use the LOG_PID option on a Guardian process. If you do, the syslog()
function will call the openlog() function and fail with Guardian trap 5, because Guardian
processes have no OSS process ID.

Logging a Message
You call the syslog() function whenever you want to log a message from your program. For
suggestions about the kinds of events and messages to log, refer to the EMS Manual.

How to Log Information With the OSS API 229


You can use the formatting codes that printf() recognizes in a syslog() call. Example 8-1
shows a code fragment with a call to syslog() using these codes.

Example 8-1 Calling syslog() With Formatting Codes


fahr = 50;

syslog( LOG_DEBUG
, "%4d Fahrenheit -- %6.1f Centigrade "
, fahr
, (5.0/9.0)*(fahr - 32 ) );

This call produces the following message:


USER DEBUG : 50 Fahrenheit -- 10.0 Centigrade
You can use the %m formatting code to include the current error number. Example 8-2 shows a
code fragment with a call to syslog() using %m.

Example 8-2 Calling syslog() With the %m Formatting Code


len = read( master_fd , buf, MAX_READ_SIZE );
if ( len < 0 )
{
syslog( LOG_DEBUG, "READ Error %m on Master File" );
}

This call produces a message such as the following if there is an error:


USER DEBUG : READ Error 4209 on Master File
where 4209 is an OSS file-system error number. You can obtain the related message string with
the perror() or strerror() functions.
Example 8-3 (page 231) provides a complete program showing the use of the system logging
functions in an OSS program.

230 Using Logging Mechanisms


Example 8-3 Use of System Logging Functions
/* Using System logging functions */

#include <fcntl.h>
#include <syslog.h>
#include <stdio.h>

int main(int argc, char *argv[]) {


char *ident="Test X"; /* Identity string, "syslog" by default */
int logopt=LOG_CONS|LOG_PID|LOG_ODELAY; /* Logging options */
int facility=LOG_USER; /* Part of system generating event message */
int maskpri=LOG_UPTO(LOG_INFO); /* EMS event log mask */
char buf[512];
int fd;

/* Open the system log with the appropriate options


- identity string
- logging option
- generated by user program by default
*/
openlog(ident, logopt, facility);

/* Set the Event Management Service (EMS) event log mask */


setlogmask(maskpri);

/* Write a "Daemon X started" message. */


syslog(LOG_INFO, "Daemon X started.\n");
/* Make sure the correct number of arguments are entered
in starting up the daemon.
If not, print a usage message and exit. */

if(argc < 2) {
syslog(LOG_ERR, "Usage: syslog pathname\n");
exit (1);
}
/* If the file cannot be opened, log an error message and exit. */
if((fd = open(argv[1], O_RDONLY)) < 0) {
syslog(LOG_ERR, "Can't open %s\n", argv[1]);
exit(1);
}
/* If the file is not at least 512 bytes long, log a read error. */
if(read(fd, buf, 512) != 512) {
syslog(LOG_ERR, "Read error %m on key daemon file.\n");
exit(1);
}
close(fd);
/* Write a "Daemon X stopped" message. */
syslog(LOG_INFO,"Daemon X stopped.\n");
/* Close connection to EMS collector process */
closelog();
exit(0);
}

Closing a Collector
To close the connection to the EMS collector process opened by openlog() or syslog(), call
the closelog() function.

Logging Parameters and EMS Tokens


OSS logging function parameters correspond to the EMS tokens listed on the syslog(3) reference
page, which is available either online or in the Open System Services Library Calls Reference Manual.

How to Log Information With the OSS API 231


The values of the tokens can be changed by the functions described in this section, but the tokens
themselves cannot be changed with the OSS API.
Table 8-7 lists logging function parameters with their corresponding EMS tokens.
Table 8-7 OSS Logging Function Parameters and Corresponding EMS Tokens
Parameter Token

facility ZOSS-TKN-FACILITY

identity ZOSS-TKN-IDENT

level ZOSS-TKN-LEVEL

message ZEMS-TKN-TEXT

The OSS process ID value displayed in log messages corresponds to the value of the
ZOSS-TKN-PID token. This parameter is included in the event message only if LOG_PID is
specified to openlog().

OSS Logging-Mechanism Functions


Table 8-8 (page 232) displays information about each OSS function that you can use to manage
logging. The columns of the table contain the following:
OSS Function
The name of the function and a brief description.
OSS Notes
Notes about the OSS implementation of the function.
Guardian Notes
Notes about using the function on a Guardian process.
The information in this table is only a summary of the information in the reference page for a
function. For details, refer to the reference pages either online or in the Open System Services
System Calls Reference Manual and the Open System Services Library Calls Reference Manual.
Table 8-8 OSS Logging-Mechanism Functions
OSS Function OSS Notes Guardian Notes

closelog()
Closes the collector process that was
opened by openlog() or syslog().

openlog() If you specify the LOG_PID option on


Initializes logging parameters. a Guardian process, the syslog()
function fails with Guardian trap 5.

perror()
Writes a message explaining the last
error encountered by a library
function.

setlogmask()
Sets the EMS event log mask.

232 Using Logging Mechanisms


Table 8-8 OSS Logging-Mechanism Functions (continued)
OSS Function OSS Notes Guardian Notes

strerror() Upon successful completion, this


Accesses a message explaining the function returns a pointer to the
function error. generated message string. If the error
number is not valid, errno is set to
the EINVAL value.

syslog() If you specify the LOG_PID option


Logs messages. with the openlog() function on a
Guardian process, the syslog()
function fails with Guardian trap 5.

OSS Logging-Mechanism Functions 233


234
9 Using Subsystems From OSS
There are HP subsystems that you can access from OSS programs. This section summarizes
considerations or limitations in using HP subsystems from your OSS application programs. The
section also provides references to manuals that discuss these subsystems in detail.
The following subsections discuss programmatic access from an OSS application to the
corresponding subsystems:
• “Communications Subsystems” (page 235)
• “Subsystems Supporting the Subsystem Programmatic Interface (SPI)” (page 235)
• “HP NonStop SQL/MP” (page 236)
• “HP NonStop SQL/MX” (page 236)
• “HP NonStop TS/MP” (page 236)
• “HP NonStop TMF” (page 237)
• “HP NonStop Tuxedo System” (page 237)
• “HP NonStop Distributed Computing Environment (DCE)” (page 237)
• “Simple Network Management Protocol (SNMP)” (page 238)

Communications Subsystems
A communications subsystem provides users with access to a set of communications services.
It consists of one or more processes running on a system and possibly a protocol module running
on a communications controller.
Examples of HP communications subsystems include Transmission Control Protocol/Internet
Protocol (TCP/IP), HP Tandem LAN Access Method (TLAM), X.25 Access Method (X25AM),
SNAX Extended Facility (SNAX/XF), Open Systems Interconnection/Application Services (OSI/AS),
and Open Systems Interconnection/Message Handling System (OSI/MHS).
You can access HP communications subsystems from OSS applications, but for some operations
you must use Guardian I/O procedures. You will probably want to use nowait I/O, which allows
a program to continue executing in parallel with read or write operations. Nowait I/O is not
available using OSS I/O functions. You also need to read the $RECEIVE file if the subsystem
sends status messages to $RECEIVE. Reading the $RECEIVE file requires using Guardian
procedures.
Because you have to use Guardian procedures for significant portions of your program, it is
easier if you use Guardian I/O procedures exclusively to access communications subsystems
instead of mixing Guardian I/O procedures and OSS I/O functions.
For more information about HP communications subsystems, see the manual sets that describe
the subsystems you need to access. These manual sets can include introductory, configuration,
programming, and reference manuals.

Subsystems Supporting the Subsystem Programmatic Interface (SPI)


The Subsystem Programmatic Interface (SPI) provides a common interface for the management
of HP subsystems by site-written applications. SPI provides the path for management applications
to exchange command-specific messages and event messages with most subsystems and with
many modules of the Subsystem Control Facility (SCF).
SPI is available to C and COBOL programs. The primary requirement is to include the definitions
found in the appropriate Guardian environment header file (in the case of C programs,
$SYSTEM.ZSPIDEF.ZSPIC) when compiling the application. This requirement can be met by
creating a copy of the needed file in the OSS file system and including a reference to the file in
the form appropriate to your programming language; you can even partially automate that action
by including an entry for the action in a make file. For example, the following make file entry:

Communications Subsystems 235


zspi.h: /G/system/zspidef/zspic
cp /G/system/zspidef/zspic ./zspi.h
creates a dependency on the presence of the necessary file in the user’s local directory and makes
sure that any updates made to the Guardian copy of the file also appear in the copy used to
compile the application. Adding an include statement to the C program source code completes
the task of providing access to the SPI features.
Alternatively, you could request that your system administrators create a zspidef directory
within/usr/include and copy the necessary files from the Guardian file system into that
directory each time updates are installed on the system.
For more information about SPI, refer to the SPI Programming Manual and the SPI Common
Extensions Manual.

HP NonStop SQL/MP
The HP NonStop SQL/MP relational database management system uses the standard Structured
Query Language (SQL) to describe and manipulate data. SQL/MP can be used for online
transaction processing, decision support systems, scalable electronic commerce applications, and
other business applications.
You can access SQL databases from an OSS program as you do from a Guardian program, using
embedded SQL statements. You can also get information about SQL objects, catalogs, and
programs using Guardian procedure calls. However, in the Guardian environment, you must
use several products to compile, link, and optimize a program. In the OSS environment, you can
use the c89 (but not the c99) utility to perform all of these functions in a single c89 command.
You do need to invoke the SQL compiler as well as the C compiler in the c89 command, and
the SQL compiler must be version 315 or newer. For information about the c89 utility, see the
c89(1) reference page either online or in the Open System Services Shell and Utilities Reference
Manual.
For more information about writing OSS application programs that access SQL/MP databases,
see the SQL/MP Programming Manual for C.

HP NonStop SQL/MX
The HP NonStop SQL/MX relational database management system uses the standard Structured
Query Language (SQL) to describe and manipulate data. SQL/MX can be used for online
transaction processing, decision support systems, scalable electronic commerce applications, and
other business applications.
You can access SQL databases from an OSS program using embedded SQL statements. You can
also get information about SQL objects, catalogs, and programs. You can use the c89 or the c99
utility to compile, link, and optimize a program in a single c89 or c99 command.
You do need to invoke the SQL/MX compiler as well as the C compiler in the c89 or the c99
command. For information about the c89 utility, see the c89(1) reference page either online
or in the Open System Services Shell and Utilities Reference Manual. For information about the c99
utility, see the c99(1) reference page either online or in the Open System Services Shell and Utilities
Reference Manual.
For more information about writing OSS application programs that access SQL/MX databases,
see the SQL/MX Programming Manual for C and COBOL.

HP NonStop TS/MP
HP NonStop Transaction Services/MP (TS/MP) provides online transaction processing. TS/MP
can create and monitor OSS servers, but it does not support OSS requesters.
An OSS server process must read its $RECEIVE file to get messages from requester processes.
To read the $RECEIVE file, you must use Guardian procedures.

236 Using Subsystems From OSS


OSS and Guardian server classes can be managed by the same PATHMON process. However,
because all server processes in a server class use the same object-code file, OSS and Guardian
server processes cannot reside in the same server class. OSS server processes and server classes
are configured and managed in the same way as Guardian servers and server classes, although
some of the configuration parameters are different. Either the PATHCOM interactive interface
or the Subsystem Programmatic Interface (SPI) can be used.
To allow for management of OSS server processes in the PATHMON environment, OSS server
programs must be coded to follow the standard protocol for Pathway servers: that is, the server
must stop itself when the LINKMON process or the terminal control process closes it on behalf
of the last requester that has a link to it.
TS/MP uses the PROCESS_SPAWN_ procedure to create OSS server processes. If you configure
and use OSS server classes in TS/MP, you might see some PROCESS_SPAWN_ errors, returned
within PATHMON error message 1159.
For more information about how OSS server processes interact with TS/MP, see the TS/MP
Pathsend and Server Programming Manual. For configuration information, see the TS/MP System
Management Manual.

HP NonStop TMF
HP NonStop Transaction Management Facility (TMF) provides transaction protection, database
consistency, and database recovery. It does this by managing database transactions, keeping
track of database activity through the use of audit trails, and providing database recovery methods.
TMF cannot audit, or protect, OSS files. You can access protected Guardian files from the OSS
environment, but you must use Guardian procedures to do so.
For more information about the Guardian procedures you can use to access files protected by
the TMF product, see the TMF Application Programmer’s Guide.

HP NonStop Tuxedo System


The HP NonStop Tuxedo system is the HP implementation of the Novell, Inc., Tuxedo enterprise
transaction processing system. Major features of the NonStop Tuxedo implementation include
the use of the HP core services (NonStop operating system, TS/MP, and TMF) to provide the HP
fundamentals (scalability, availability, and manageability) for Tuxedo applications. The NonStop
Tuxedo system also provides support for transaction management and monitoring, client/server
communications, buffer management, and management and administration of server processes.
Because TS/MP servers open the $RECEIVE file to get messages from requester processes, you
might expect that NonStop Tuxedo servers also open $RECEIVE, but they do not. NonStop
Tuxedo server applications use Tuxedo functions to get input from requester processes.
For more information about programming in the NonStop Tuxedo processing environment, see
the NonStop TUXEDO System Application Development Guide.

NOTE: NonStop Tuxedo applications run as OSS processes.

HP NonStop Distributed Computing Environment (DCE)


HP NonStop Distributed Computing Environment (DCE) is an integrated set of services that
supports the development and execution of distributed applications between heterogeneous
networked computers. Each DCE environment (called a cell) maintains at least the following
core DCE services:
• DCE Threads
• DCE Host Services
• DCE Cell Directory Service

HP NonStop TMF 237


• DCE Time Service
• DCE Security Service
With the exception of DCE Threads, all the core DCE services require administration in one way
or another. Some services, such as CDS and DCE Security Service, usually need more managing
than, for example, DCE Time Service, which needs practically no intervention after you have set
it up. If your DCE cell consists of just a few computers and their users, you could probably
manage the naming, time, and security needs of users, programs, and host systems by logging
on to individual hosts to perform any necessary administration tasks. However, most cells will
consist of many, perhaps hundreds or even thousands, of computers and their users.
Refer to OSF DCE Administration Guide-Core Components, OSF DCE Administration
Guide-–Introduction, OSF DCE Application Development Guide–Core Components, OSF DCE Application
Development Guide–Introduction and Style Guide, and OSF DCE Problem Determination Guide for
more information.

Simple Network Management Protocol (SNMP)


The Simple Network Management Protocol (SNMP) originated in the Internet community in the
late 1980s as a means for managing TCP/IP and Ethernet networks. Because of its relative
simplicity, SNMP has since gained widespread acceptance as a protocol for managing devices
from multiple vendors on a network.
HP uses subagents in its SNMP implementation. SNMP subagents are responsible for handling
a particular collection of resources. Some subagents are implemented as independent processes,
and some are bound into other processes, such as the SNMP agent process.
HP offers a Subagent Toolkit that helps programmers generate subagents that interoperate with
the SNMP agent process. Subagents make customer-written applications manageable by SNMP
managers. Refer to the SNMP Subagent Programmer’s Guide for more information about the
Subagent Toolkit.
HP also offers a Manager Services toolkit that allows C and C++ programmers to create SNMP
managers that run as NonStop operating system processes in either the Guardian or OSS
environment. Refer to the SNMP Subagent Programmer’s Guide for information about the Manager
Services toolkit.
Refer to the SNMP Configuration and Management Manual, the SNMP Manager Programmer’s Guide,
and the SNMP Subagent Programmer’s Guide for more information.

238 Using Subsystems From OSS


10 Managing OSS Security
This section provides a brief overview of the features available for program control of OSS process
and file security. The following topics are discussed:

Topic Content

“Common and Unique Characteristics” (page 239) Summary of the differences between OSS and UNIX
security management

“Functions Available for Security Management” (page 240) Describes the C functions available for managing the
security of OSS objects

“Security Auditing of OSS files” (page 243) Describes the application program interfaces (APIs) that
can be audited when performing OSS file access and
process control activities

“Example of Managing file Ownership” (page 246) Provides a simple example of managing file ownership
in the OSS environment

“Using OSS Access Control Lists (ACLs)” (page 249) Describes OSS access control lists and their use.

Common and Unique Characteristics


Basic file security is the same for the OSS environment as on a UNIX system. files are accessed
according to a file mode and access permissions, as described in the Open System Services User’s
Guide and in Chapter 2: Managing Files (page 51) of this guide.
Certain differences might require you to code the security management portions of a program
or shell script in a manner specific to the OSS environment. For example:
• OSS user and group administration occurs through tools based in the Guardian environment,
such as the Safeguard command interpreter (SAFECOM) program or third-party products.
OSS user and group administration does not use any of the following files or directories,
which can be the target of security intruders:
/etc/groups
/etc/passwd
/etc/security
/etc/shadow
Standard C functions do provide access to information needed from the security database.
However, the database files themselves are not available in the OSS file system.
• OSS administration of device access does not use files in the /dev directory that are available
on some UNIX systems, such as:
console
fd
kmem
ttyda
Again, these files can be the target of security intruders.
• The OSS environment does not provide common UNIX default user names and user IDs
unless they are explicitly created by a site administrator. However, equivalent OSS user
names and user IDs do exist. For example, the privileges normally associated with the UNIX
user name root and the user ID of 0 exist for the OSS user ID of 65535 (the super ID), which
is normally the user SUPER.SUPER.
• OSS file auditing mechanisms and policies are implemented through the Guardian
environment Safeguard product instead of such UNIX commands or utilities as:
/etc/reboot

Common and Unique Characteristics 239


/etc/shutdown
/etc/syslog
passwd
OSS file auditing features are not available through third-party Security Event Exit process
(SEEP) programs.
• Access to OSS auditing logs occurs through the Safeguard audit reduction tool (SAFEART)
program.
• The OSS implementation of object security does not conform to POSIX.6 draft 12, IEEE
Standard 1003-1e, or IEEE Standard 1003-2c. In particular, the OSS environment does not
provide access control list APIs.
Figure 10-1 (page 241) illustrates the major components and interfaces of OSS security management
mentioned in this section.
Refer to the Security Management Guide for an overview of both Guardian and OSS security. Refer
to the Safeguard Audit Service Manual for a description of the SAFEART program and the
information logged for audited OSS files.
The commercial text Practical UNIX & Internet Security listed in Preface (page 15) contains many
suggestions for writing secure programs. Those suggestions include which functions to avoid
in best-practice program designs.

Functions Available for Security Management


The OSS environment provides most of the basic XPG4 functions used by C or C++ programs
for process and file security.
Table 10-1 (page 241) lists and provides a short description of the C functions related to security.
Many of these functions have been described in other sections of this guide in the context of file
management or process management; some of these functions are not normally regarded as
security functions but have security implications when used.

240 Managing OSS Security


NOTE: To determine which RVUs support an OSS function, see Appendix A (page 389).

Figure 10-1 Major Components and Interfaces for OSS Security Management

Table 10-1 OSS Security-Related Functions


OSS Function Security-Related Behavior

acl() Changes file access permissions for a list of users and groups.

chmod() Changes file access permissions.


fchmod()
lchmod()

chown() Changes file ownership.


fchown()
lchown()

crypt() Encrypts a password or other character data.

cuserid() Gets the user name associated with the real user ID of the current process.

encrypt() Encrypts or decrypts an array.

Functions Available for Security Management 241


Table 10-1 OSS Security-Related Functions (continued)
OSS Function Security-Related Behavior

endgrent() Closes the group database.

fstat() Gets the OSS user ID for the owner of an open file.
fstat64()

fstatvfs() Gets fileset access information.


fstatvfs64()

getegid() Gets the effective group ID of the calling process.

geteuid() Gets the effective OSS user ID of the calling process.

getgid() Gets the real group ID of the calling process.

getsid() Gets the group ID of the process that is the session leader of the specified process.

getgrent() Gets group information from the group database.

getgroups() Gets the list of groups to which the current process belongs.

getlogin() Gets the login name (user name) for the current terminal session.

getpass() Reads a string of characters (such as a password) from a terminal without echoing the
characters entered.

getpgrp() Gets the process-group ID of the calling process.

getpid() Gets the OSS process ID of the calling process.

getppid() Gets the OSS process ID of the parent process for the calling process.

getuid() Gets the real OSS user ID of the calling process.

lstat() Gets the OSS user ID for the owner of a file or symbolic link.
lstat64()

mkdir() Creates a directory with specified access permissions and default OSS user ID and group
ID values.

rmdir() Removes a directory subject to access permissions.

setgid() Sets the effective group ID of the calling process.

setgrent() Resets the group name key to get group information from the group database.

setkey() Sets an encryption or decryption key.

setpgid() Changes the process-group ID for job control.

setpgrp() Creates a new session when the calling process is not a process group leader, and sets
the process group ID of the calling process.

setregid() Sets the real and effective group ID.

setreuid() Sets the real and effective user ID.

setsid() Sets the process-group ID for a new terminal session.

setuid() Sets the effective OSS user ID of the calling process.

stat() Gets the OSS user ID for the owner of a file.


stat64()

The Guardian environment provides separate procedures for managing Guardian process and
Guardian file security. Refer to the Security Management Guide for an overview of both Guardian
and OSS security interfaces and activities.

242 Managing OSS Security


Security Auditing of OSS files
Your application program does not need to provide its own file auditing mechanism. Your system
manager can enable file auditing on a specific fileset. When auditing is enabled, certain application
program activities for any file in that fileset can automatically generate entries in the audit file
for the system where the file is located.
The following subsections describe:
• “How to Identify an Audited file in Audit Records” (page 243)
• “What Operations and Objects Are Audited” (page 243)
• “Considerations for File Auditing” (page 245)

How to Identify an Audited file in Audit Records


You can write either an OSS or Guardian application program to process audit records. Audit
files are structured files and are easiest to process with Guardian APIs. The structure and Guardian
file naming conventions for audit files, the field names and object types, and the format of audit
file records are described in the Safeguard Audit Service Manual.
The audit record for an audited file event identifies the file being audited with both its absolute
OSS pathname and the internal name used for it by Guardian access mechanisms. The internal
name includes the creation version serial number (CRVSN) so that a specific instance of a file
can be identified. An audit entry looks like:
pathname=$volume_name.subvolume_name.file_identifier:crvsn
For example:
/bin/ed=$DATA13.ZYQ00001.Z0004G7:1934568735
where 1934568735 is the CRVSN of the file being audited. For more information on the use of
the CRVSN with files, refer to the Open System Services Management and Operations Guide.

What Operations and Objects Are Audited


Table 10-2 (page 243) and Table 10-3 (page 245) provide a brief overview of the information logged
for audited OSS files and available through the SAFEART program. Table 10-4 (page 245) lists
the audited Guardian procedures that can be used from an OSS program.
Manipulating an audited Guardian file through OSS function calls and the /G directory also
causes log entries; the information logged for Guardian files is controlled by Guardian auditing
policies rather than by membership in an audited fileset. Similarly, manipulation of Guardian
files through Guardian procedure calls from an OSS program can be audited through Guardian
policies, which are not discussed in this guide.

NOTE: To determine which RVUs support an OSS function, see Appendix A: Documented
OSS Functions (page 389).
Table 10-2 OSS Function Calls Audited When Used With Audited filesets
OSS Function Attributes or Actions Audited

access() The value of the access_mode parameter.


Use on files in the /G directory is also audited.

acl() The number of ACL entries and the value of each changed ACL entry before and after
the call.

bind() For AF_UNIX sockets, the values of the access_mode parameter, the OSS user ID, group
ID, and rdev.

Security Auditing of OSS files 243


Table 10-2 OSS Function Calls Audited When Used With Audited filesets (continued)
OSS Function Attributes or Actions Audited

chmod() The values of the file mode before and after the call.
fchmod()
lchmod()

chown() The values of the OSS user ID, group ID, and file mode before and after the call.
fchown() Use on files in the /G directory is also audited.
lchown()

creat() For all files, the value of the file mode, the OSS user ID, the group ID, and rdev.
creat64() For regular files, the value of the open flags.

execl() The value of the OSS user ID and group ID.Use on files in the /G directory is also audited.
execle()
execlp()
execv()
execve()
execvp()

fork() The value of the OSS user ID and group ID.

kill() The signal sent, the real OSS user ID and effective OSS user ID of the sender, the OSS
process ID or process group ID, the process handle, and the saved set OSS user ID of the
target process.
If the target process is a member of a process group, the audit information is logged for
all the processes affected by the call when those processes can be determined.

link() The name and the link count of the linked-to file, and the new filename.

mkdir() The value of the file mode, the OSS user ID, the group ID, and rdev.

mkfifo() The value of the file mode, the OSS user ID, the group ID, and rdev.

mknod() The value of the file mode, the OSS user ID, the group ID, and rdev.

open() The value of the open flags and the value of the file mode before and after the call.
open64() Use on files in the /G directory is also audited.

opendir() The value of the open flags and the value of the file mode before and after the call.

rename() The old and new pathname values.

rmdir() For a link count of zero, the value of the file mode, the OSS user ID, the group ID, the
mtime, ctime, size, and rdev.
For a link count that is not zero, the value of the link count after the call.

setgid() The value of the real, effective, and saved-set group ID before and after the call.

setpgid() The value of the process-group ID before and after the call.

setpgrp() The value of the process-group ID before and after the call.

setregid() The value of the real, effective, and saved-set OSS group ID before and after the call

setsid() The value of the process-group ID before and after the call.

setreuid() The value of the real, effective, and saved-set OSS user ID before and after the call.

setuid() The value of the real, effective, and saved-set OSS user ID before and after the call.

symlink() The contents of the symbolic link and the value of the file mode, the OSS user ID, the
group ID, and rdev.

tdm_execve() The process name and the value of the OSS user ID and group ID.
tdm_execvpe() Use on files in the /G directory is also audited.

244 Managing OSS Security


Table 10-2 OSS Function Calls Audited When Used With Audited filesets (continued)
OSS Function Attributes or Actions Audited

tdm_fork() The process name and the value of the OSS user ID and group ID.

tdm_spawn() The process name and the value of the OSS user ID and group ID.
tdm_spawnp() Use on files in the /G directory is also audited.

unlink() For a link count of zero, the value of the file mode, the OSS user ID, the group ID, the
mtime, ctime, size, and rdev.
For a link count that is not zero, the value of the link count after the call .

utime() The values of mtime, atime, and ctime before and after the call.
Use on files in the /G directory is also audited.

Table 10-3 Guardian Procedure Calls Audited When Used With Audited filesets
Procedure Call Attributes or Actions Audited

FILE_OPEN_ Resolution of a supplied pathname to a regular file in an audited fileset; use of an internal
SPT_FILE_OPEN OSS filename; all Guardian file audit attributes.

PROCESS_SPAWN_ Resolution of a supplied pathname to a regular file in an audited fileset; use of an internal
OSS filename; all Guardian file audit attributes.

Table 10-4 Guardian Procedure Calls Audited When Used for Process Control
Procedure Call Attributes or Actions Audited

FILE_OPEN_ The value of the open flags and the value of the file mode before and after the call
SPT_FILE_OPEN

PROCESS_SPAWN_ The process name and the value of the OSS user ID and group ID

Considerations for File Auditing


The /G and/E directories and Network file System (NFS) filesets cannot be audited. Audited
filesets cannot be mounted for NFS client use.
OSS sockets function calls such as connect() are not audited. The pipe() function call is not
audited because its effects are transitory.
The chdir() and chroot() function calls are not audited. The method used to audit pathnames
uses absolute names from the system root directory, so these functions do not require auditing.
When a directory that is a component of one or more fileset mount point pathnames is renamed,
that renaming must be propagated to all of the affected filesets. This propagation is not part of
the renaming operation; propagation occurs after completion of the rename() function call. If
both of the following are true:
• An affected fileset and its mount point are managed by different OSS name server processes
• The renaming is followed immediately by an audited operation on a file in that fileset
Then the audit record produced by the latter operation might include a pathname that does not
reflect the renaming because the renaming propagation has not completed. For example, if an
audited fileset is mounted on /usr/src/projects/mine and the following function calls
occur:
rename("/usr/src/projects", "/usr/src/tasks");
open("/usr/src/tasks/mine/main.c");
Then the pathname recorded for the audited open() call might be
/usr/src/projects/mine/main.c instead of /usr/src/tasks/mine/main.c.

Security Auditing of OSS files 245


The propagation delay depends on processor and system workloads and is normally a second
or less.

Example of Managing file Ownership


Example 10-1 provides an example of code demonstrating the use and effect of the getuid(),
geteuid(), getgid(), getegid(), setgid(), setregid(), and chown() functions in
managing file ownership.

246 Managing OSS Security


Example 10-1 Using OSS Security Functions
/* Using OSS Security functions (without ACLs) */

#include <stdio.h>
#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <grp.h>
#include <pwd.h>
/*
* Print out the group number in decimal followed by (groupname)
*/
void printgroup(gid_t groupid)
{
unsigned long lt; /* temp */
struct group *grpptr; /* pointer to group info */

lt = (unsigned long)groupid; /* make the gid a long */


printf(" %lu(",lt); /* print it */
grpptr = getgrgid(groupid); /* get group structure */
/* print question marks if group name is unknown */
if(grpptr == NULL) {
printf("??????)");
return;
}
printf("%s)",grpptr->gr_name); /* print group name */
return;
}
/*
* Print out the user ID in decimal followed by (username)
*/
void printuser(uid_t userid)
{
unsigned long lt; /* temp */
struct passwd *pwptr; /* pointer to user info */

lt = (unsigned long)userid; /* make the uid a long */


printf(" %lu(",lt); /* print the number */
pwptr = getpwuid(userid); /* get the information */
/* print question marks if user ID is not known */
if(pwptr == NULL) {
printf("??????)");
return;
}
printf("%s)",pwptr->pw_name);
return;
}

void printsupgroups()
{
int ngroups; /* number of supplemental groups */
gid_t grouplist[NGROUPS_MAX]; /* list of group IDs */
int i;
gid_t gid;

/* Get the number of supplementary group IDs in use */


ngroups = getgroups(NGROUPS_MAX, grouplist);
if(ngroups == -1) {
perror("getgroups() failed");
return;
}

Example of Managing file Ownership 247


printf("The following supplementary groups are available:\n");
for(i = 0; i < ngroups; i++) {
gid = grouplist[i];
printf("\t");
printgroup(gid);
printf("\n");
}
return;
}
struct stat statbuf;

int main(int argc, char **argv)


{
uid_t uid;
gid_t gid, egid;
char *login;
char termid[L_ctermid];
int fd;

/* Get new effective group ID from command line.


Default value set to real group ID value.
*/
if(argc > 1)
egid = atoi(argv[1]);
else
egid = getgid();
/* Print out information about the user */
login = getlogin();
if (login == NULL)
printf("Login name is not known\n");
else
printf("Login name is '%s'\n",login);
ctermid(termid);
printf("Terminal pathname is '%s'\n", termid);
uid = getuid();
printf("Real UID is");
printuser(uid);
uid = geteuid();
printf(" and effective UID is");
printuser(uid);
gid = getgid();
printf("\nReal group ID is");
printgroup(gid);
gid = getegid();
printf(" and effective group ID is ");
printgroup(gid);
printf("\n");
printsupgroups();

/* Create a new file with effective group ID of this process.


Then set the effective group ID of this process to one of
the supplemental group values. Use chown to set the group ID
of the file to the new effective group ID. The real group ID
value is left unchanged.
*/
if((fd = open("junkfile", O_RDWR|O_CREAT, 0666)) < 0) {
fprintf(stderr, "Can't create file 'junkfile'\n");
exit(1);
}
close(fd);
if(stat("junkfile", &statbuf) < 0) {
fprintf(stderr, "Can't get status of file 'junkfile'\n");
exit(1);
}
printf("junkfile created with uid = %d, gid = %d\n",

248 Managing OSS Security


statbuf.st_uid, statbuf.st_gid);
if(setregid( ((gid_t)-1), egid) < 0) {
fprintf(stderr, "Can't change effective group ID of process.\n");
exit(1);
}
if(chown("junkfile", (uid_t)-1, egid) < 0) {
fprintf(stderr, "Can't change group ID of file.\n");
exit(1);
}
if(stat("junkfile", &statbuf) < 0) {
fprintf(stderr, "Can't get status of file 'junkfile'\n");
exit(1);
}
printf("junkfile chown'ed with uid = %d, gid = %d\n",
statbuf.st_uid, statbuf.st_gid);
gid = getgid();
printf("Real group ID is");
printgroup(gid);
gid = getegid();
printf("and effective group ID is");
printgroup(gid);
printf("\n");
return(0);
}
This program produces the following output (software.abcde (1,5) is a member of SUPER
group):
/usr/abc: run a.out 255
Login name is SOFTWARE.ABCDE
Terminal pathname is /dev/tty
real UID is 261(SOFTWARE.ABCDE) and effective UID is 261(SOFTWARE.ABCDE)
Real group ID is 1(SOFTWARE) and effective group ID is 1(SOFTWARE)
The following supplementary groups are available:
1(SOFTWARE)
255(SUPER)
junkfile created with uid = 261, gid = 1
junkfile chowned with uid = 261, gid = 255
Real group ID is 1(SOFTWARE) and effective group ID is 255(SUPER)

Using OSS Access Control Lists (ACLs)


OSS access control lists (ACLs) are supported for certain files in Version 3 catalog OSS filesets
on systems running J-series RVUs, H06.08 and later H-series RVUs, or G06.29 and later G-series
RVUs.
OSS already enables nonprivileged users or processes, such as file owners, to allow or deny other
users access to files and other objects as determined by their user identity, group identity, or
both. This level of control is accomplished by setting or manipulating a file’s permission bits to
grant or restrict access by owner, group, and others (see the chmod(2) reference page).
ACLs offer a greater degree of selectivity than permission bits. ACLs allow a process whose
effective user ID matches the file owner, super ID, or a member of the Safeguard SECURITY-OSS-
ADMINISTRATOR security group to permit or deny access to a file to a list of specific users and
groups.
ACLs are supported as a superset of the UNIX operating system discretionary access control
(DAC) mechanism for files, but not for other objects such as interprocess communication (IPC)
objects.
All OSS system calls that include pathnames are subject to the ACLs on any directory or file in
the path.

Using OSS Access Control Lists (ACLs) 249


OSS ACLs:
• Are supported in Version 3 and later catalog versions of OSS filesets.
• Are supported for directories, regular files, first-in, first-out (FIFO) files, and bound AF_UNIX
sockets.
• Support up to 150 ACL entries.
• Support separate permissions for up to 146 additional users and groups.
• Support default ACL inheritance (see “ACL Inheritance” (page 253)).
• Are based on the POSIX 1003.1e draft standard and the HP-UX implementation of ACLs.
• Are not supported by the OSS Network File System (NFS) for J06.08 and earlier J-series
RVUs, H06.19 and earlier H-series RVUs, or G-series RVUs. Any attempt by NFS clients to
access OSS objects protected by OSS ACLs that contain optional ACL entries is denied.
• Are supported by the OSS NFS for J06.09 and later J-series RVUs and H06.20 and later
H-series RVUs, depending upon the NFSPERMMAP attribute value for the fileset that
contains the object. For information about the NFSPERMMAP attribute, see “OSS Network
File System (NFS) and ACLs” (page 257).

Definitions
Control of access to data is a key concern of computer security. These definitions, based on the
Department of Defense Trusted Computer System Evaluation Criteria, explain the concepts of access
control and its relevance to OSS security features:
access
A specific type of interaction between a subject and an object that results in the flow of
information from one to the other. Subjects include persons, processes, or devices that cause
information to flow among objects or change the system state. Objects include files (ordinary
files, directories, special files, FIFOs, and so on) and IPC features (shared memory, message
queues, semaphores, and sockets).
access control list (ACL)
An access control list is a set of user.group, mode entries associated with a file that specifies
permissions for all possible combinations of user IDs and group IDs.
ACL entry
An entry in an ACL that specifies access rights for a file owner, owning group, group class,
additional user, additional group, or all others.
change permissions
The right to alter DAC information (permission bits or ACL entries). Change permission is
granted to object (file) owners and to privileged users.
discretionary access control (DAC)
A means of restricting access to objects based on the identity of subjects, groups to which
they belong, or both. The controls are discretionary because a subject with a certain access
permission is able to pass that permission (perhaps indirectly) to any other subject.
mode
Three bits in each ACL entry that represent read, write, and execute or search permissions.
privilege
The ability to ignore access restrictions and change restrictions imposed by security policy
and implemented in an access control mechanism. In OSS, the super ID is the only user ID
that can ignore access restrictions. However, the super ID and any member of the Safeguard
SECURITY-OSS-ADMINISTRATOR security group can change the ownership and access
permissions (standard UNIX permissions or ACL entries) of a file.

250 Managing OSS Security


Access Control List Entries
An ACL consists of a set of one-line entries that specify permissions for a file. Each entry specifies
for one user-ID or group-ID a set of access permissions, including read, write, and execute/search.
To understand the relationship between access control lists and traditional file permissions,
consider the following file and its permissions:
-rwxr-xr-- james admin datafile
For this file:
• The owner is the user james.
• The group is admin.
• The name of the file is datafile.
• The file owner permissions are rwx.
• The file group permissions are r-x.
• The file other permissions are r--.
In an ACL, user and group IDs are represented by names or numbers, as found in the user
authentication database and group database for the system.

ACL Notation
Supported commands that manage ACLs recognize these symbolic representations:
[d[efault]:]u[ser]:[uid]:perm
[d[efault]:]g[roup]:[gid]:perm
[d[efault]:]c[lass]:perm
[d[efault]:]o[ther]:perm
An ACL entry prefixed with d: or default: can occur only in ACLs for directories. The prefix
indicates that the remainder of the entry is not to be used in determining the access rights to the
directory but instead is to be applied to any files or subdirectories created in the directory (see
“ACL Inheritance” (page 253)).
The uid and gid fields contain either numeric user or group IDs, or their corresponding character
strings from the authentication database and group database for the system.
The perm field indicates access permission either in symbolic form, as a combination of r, w, x,
and - (dash), or in numeric form, as an octal value of 0 through 7 representing the sum of 4 for
read permission, 2 for write permission, and 1 for execute permission.

Types of ACL Entries


An ACL can contain several types of entries:
• “Base ACL Entries” (page 251)
• “Class Entry” (page 252)
• “Actual ACL Entries” (page 253)
• “Default ACL Entries” (page 253)

Base ACL Entries


The base ACL entries grant permissions equivalent to standard UNIX permissions. When an
ACL consists of the four base ACL entries only, it is called a minimal ACL, and the permissions
for the class and other ACL entries are equal. The chmod() and acl() functions can change
base ACL entries.

Using OSS Access Control Lists (ACLs) 251


Table 10-5 Base ACL Entries
Notation Entry Type Description

user::perm USER_OBJ Permissions for the owner of the object

group::perm GROUP_OBJ Permissions for the owning group of the object

class:perm CLASS_OBJ The maximum permissions granted to the file group class

other:perm OTHER_OBJ Permissions for other users

Class Entry
The class ACL entry, which is a base ACL entry, was created to preserve compatibility with
programs that only use chmod(). Because of the class ACL entry, existing programs that use
chmod() can work with file that have ACL entries for optional users and optional groups in
addition to the owning group.
The class entry acts as an upper bound for file permissions. In an ACL that contains optional
group entries or optional user entries, the class entry specifies the maximum permissions that
can be granted to:
• Members of the owning group
• Any additional user entries (optional users)
• Any additional group entries (members of any optional groups)
The class entry is useful because it allows you to restrict the permissions for all of the other ACL
entries by changing only one ACL entry. If optional user or optional group ACL entries are
present, the chmod command changes the permissions of the class ACL entry instead of the
permissions of the owning group. This behavior allows programs that use the chmod command
to support files or directories that have permissions for additional users and groups.

Optional ACL Entries


Optional ACL entries are ACL entries other than the base ACL entries. Optional ACL entries
grant permissions beyond the standard UNIX permissions and can be used to further allow or
deny access to the file. A file or directory is considered to have an ACL only if optional ACLs
are present. In OSS, you can specify up to 146 optional ACL entries in an ACL. You use the
setacl command or the acl() system call to set ACL entries.
Table 10-6 Actual (Nondefault) Optional ACL Entries
Notation Entry Type Description

user:uid:perm USER Permissions for the user specified by uid

group:gid:perm GROUP Permissions for the group specified by gid

Examples of actual optional ACL entries:


u:mary:rwx
Grant read, write, and execute access to the user mary.
user:george:---
Deny access to the user george.
g:writers:rw-
Grant read and write access to all members of the group writers.

252 Managing OSS Security


Actual ACL Entries
The base ACL entries, optional user ACL entries, and optional group ACL entries are considered
actual ACL entries because they actually control access to the associated file or directory. These
ACL entries are also called nondefault ACL entries.

Default ACL Entries


Default ACL entries are allowed for directories only. Default ACL entries do not determine who
can access the directory. Instead, default ACL entries affect the access permissions for files or
directories created in the directory (see “ACL Inheritance” (page 253)). All default ACL entries
are optional ACL entries.
Table 10-7 Default ACL Entries
Notation Entry Type Description

default:user::perm DEF_USER_OBJ Default permissions for the object owner

default user:uid:perm DEF_USER Default permissions for additional users specified


by uid

default:group::perm DEF_GROUP_OBJ Default permissions for members of the owning


group of the object

default:group:gid:perm DEF_GROUP Default permissions for members of the


additional group specified by gid

default:class:perm DEF_CLASS_OBJ Default maximum permissions granted to the file


group class

default:other:perm DEF_OTHER_OBJ Default permissions granted to other users

The permissions for these entries in the parent directory, modified by the file-creation mode, the
umask, or both, become the permissions for the base ACL entries for a new file when the new
file inherits ACL entries from the parent directory:
• default:user::perm (DEF_USER_OBJ)
• default:group::perm (DEF_GROUP_OBJ)
• default:class:perm (DEF_CLASS_OBJ)
• default:other:perm (DEF_OTHER_OBJ)
These entries are sometimes referred to as base default ACL entries.

ACL Uniqueness
Entries are unique in each ACL. An ACL can contain only one of each type of base entry, and
only one entry for any given user or group ID. Likewise, an ACL can contain only one of each
type of default base entry and only one default entry for any given user or group ID.

ACL Inheritance
The permissions, including access control list entries, if any, for a newly created file are determined
by:
• Whether the fileset of the created file supports OSS ACLs
• Whether the system on which the process is running supports OSS ACLs
• Whether the parent directory of the created file contains default ACL entries
• The file-creation mode (mode)
• The process umask (umask)
If the fileset does not support OSS ACLs, the permissions of the created file are the mode
bitwise-ANDed with the complement of the umask.

Using OSS Access Control Lists (ACLs) 253


If the fileset supports OSS ACLs, but the system on which the process is running does not support
OSS ACLs, and the parent directory for the created file does not have default ACL entries, the
permissions of the created file are the mode bitwise-ANDed with the complement of the umask.
If the fileset supports OSS ACLs, but the system on which the process is running does not support
OSS ACLs, and the parent directory for the created file has default ACL entries:
• The permissions for the base ACL entries of the created file or directory are determined by
a combination of the file-creation mode and the default base ACL entries of the parent
directory as follows:

Permissions Type Derived From

USER_OBJ permissions The DEF_USER_OBJ permissions bitwise-ANDed with the modeuser


permissions bitwise-ANDed with the complement of the umaskuser permissions

GROUP_OBJ permissions The DEF_GROUP_OBJ permissions

CLASS_OBJ permissions The DEF_CLASS_OBJ permissions bitwise-ANDed with the modegroup


permissions bitwise-ANDed with the complement of the umaskgroup
permissions

OTHER_OBJ permissions The DEF_OTHER_OBJ permissions bitwise-ANDed with the modeother


permissions bitwise-ANDed with the complement of the umaskother
permissions

• The default optional ACL entries for the parent directory of the created file are added to the
ACL of the created file as actual (nondefault) optional ACL entries.
• If the created file is a directory, all of the default ACL entries of the parent directory are
added to the ACL of the new directory. This behavior allows ACL entries to be inherited by
files and directories created under this new directory.
If both the fileset for the created file and the system in which the process is running support OSS
ACLs, and the parent directory for the created file does not have default ACL entries, the
permissions of the created file are the mode bitwise-ANDed with the complement of the umask.
If both the fileset for the created file and the system in which the process is running support OSS
ACLs, and the parent directory of the created file contains default ACL entries:
• The permissions for the base ACL entries of the created file or directory are determined by
a combination of the file-creation mode and the default base ACL entries of the parent
directory as follows:

Permissions Type Derived From

USER_OBJ permissions The DEF_USER_OBJ permissions bitwise-ANDed with the modeuser


permissions

GROUP_OB permissions The DEF_GROUP_OBJ permissions

GROUP_OB permissions The DEF_CLASS_OBJ permissions bitwise-ANDed with the modegroup


permissions

OTHER_OBJ permissions The DEF_OTHER_OBJ permissions bitwise-ANDed with the modeother


permissions

• The default optional ACL entries for the parent directory of the created file are added to the
ACL of the created file as actual (nondefault) optional ACL entries.
• If the created file is a directory, all of the default ACL entries of the parent directory are
copied to the ACL of the new directory. This behavior allows default ACL entries to be
inherited by files and directories created under this new directory.

254 Managing OSS Security


For security reasons, if an ACL contains default ACL entries, all of the default base ACL entries
should be provided. During ACL inheritance, if any default base ACL entries are missing, the
permissions for the missing default base ACL entries are derived as follows:

Permissions Type Derived From

DEF_USER_OBJ The complement of the umaskuser permissions


permissions

DEF_GROUP_OBJ The complement of the umaskgroup permissions


permissions

DEF_CLASS_OBJ The complement of the umaskgroup permissions


permissions

DEF_OTHER_OBJ The complement of the umaskother permissions


permissions

Examples of ACL Inheritance


Directory /a has the following ACL, as reported by the getacl command:
# file: /a
# owner: alpha
# group: uno
user::rwx
group::rwx
class:rwx
other:rwx
default:user:beta:r--
default:user:gamma:r--
default:group:dos:---
default:group:tres:---
In this example, the ACL for a new file created in the directory /a includes the default ACL
entries for directory /a as actual (nondefault) ACL entries:
# file: /a/newfile
# owner: creator_uid
# group: creator_gid
user::rwuser:
beta:r--
user:gamma:r--
group::r--
group:dos:---
group:tres:---
class:r--
other:r--
In this example, a new directory, dir is created in the /a directory. The default ACL entries of
the parent directory, /a, are added to the ACL of the new subdirectory twice: first as actual
(nondefault) ACL entries and second as the default ACL entries. This behavior ensures that
default ACLs propagate downward as trees of directories are created. This example shows the
ACL of the new directory, dir:
# file: /a/dir
# owner: creator_uid
# group: creator_gid
user::rwx
user:beta:r--
user:gamma:r--
group::r-x
group:dos:---
group:tres:---
class:r-x
other:r-x
default:user:beta:r--

Using OSS Access Control Lists (ACLs) 255


default:user:gamma:r--
default:group:dos:---
default:group:tres:---

Access Check Algorithm


To determine the permissions granted to an accessing process, the operating system checks for
matching IDs in the following order:
1. If the EUID of the process is the same as the owner of the file, grant the permissions specified
in the user:: entry of the ACL. Otherwise, continue to the next check.
2. If the EUID matches the UID specified in one of the additional user:uid: ACL entries,
grant the permissions specified in that entry bitwise-ANDed with the permissions specified
in the class entry. Otherwise, continue to the next check.
3. If the EGID or a supplementary GID of the process matches the owning GID of the file or
one of the GIDs specified in any additional group:gid: ACL entries, grant the permissions
specified in the class entry bitwise-ANDed with the result of bitwise-ORing together all
of the permissions in all matching group entries. Otherwise, continue to the next check.
4. Grant the permissions specified in the other: ACL entry.
Because the checks are performed in this order and the ID match checking stops when a match
is found, you can use optional user or group ACL entries with restrictive permissions to deny
access to certain users or groups.
If the EGID, the supplementary GIDs of the process, or both match the GIDs of multiple group
ACL entries for a file, the process is granted the permissions of all of the matching group entries,
restricted by the permissions in the class entry. For example, assume that the effective user ID
for a process represents the user beta, and the group IDs for that process represent group
membership only in the dos and tres groups. In this example, that process is allowed to open
the file /a/file with read/write access, because the group:dos: entry granted read access,
the group:tres: entry granted write access, and the class: entry allowed read and write
access.
# file: /a/file
# owner: creator_uid
# group: creator_gid
user::rw-
group::rw-
group:dos:r--
group:tres:-w-
class:rw-
other:r--

ACL Operations Supported


• The acl( ) system call sets, retrieves, or counts ACLs.
• The setacl command sets or modifies ACLs.
• The getacl command retrieves ACLs.
• The -acl option of the find command locates files with certain ACL properties.
• The cp, cpio -p, mv, and pax -rw commands copy ACLs with the source files to the
destination files.
• The Backup and Restore 2 utility backs up ACLs with the files on tape and restores ACLs
with the files back to disk.

ACL Interaction with stat()


The st_mode field summarizes the access rights to the file. It differs from file permission bits
only if the file has one or more optional ACL entries. If one or more optional ACL entries are
present in the ACL of the file, the permissions specified in the class entry of the ACL are returned
as the permissions for group in the st_mode field. Because of this behavior, programs that use
256 Managing OSS Security
the stat( ) or chmod( ) functions and are ignorant of ACLs are more likely to produce
expected results. The st_acl field indicates the presence of optional ACL entries in the ACL
for the file. The st_basemode field provides the owning user permissions, owning group
permissions, and other permissions for the file.

ACL Interaction with chmod()


Using the chmod( ) function to set the group permission bits affects the class: entry for the
file, which in turn affects the permissions granted by additional user:uid: and group:gid:
entries. In particular, using chmod( ) to set file permission bits to all zeros removes all access
to the file, regardless of permissions granted by any additional user:uid: or group:gid:
entries. If the chmod( ) function is used on an object that does not have optional ACL entries,
both the class: ACL entry and the owning group (group::) ACL entry permission bits are
changed to the new group permissions value.

ACL Interaction with chown()


If you use the chown( ) function to change the owner or owning group of a file to a user ID or
group ID that has an existing user:uid: or group:gid: entry in the ACL for the file, those
existing entries are not removed from the ACL. However, those existing entries no longer have
any effect, because the user:: or group:: entries take precedence.

OSS Network File System (NFS) and ACLs


For J06.09 and later J-series RVUs and H06.20 and later H-series RVUs, access by the OSS Network
File System (NFS) to OSS objects that have OSS ACLs that contain optional ACL entries can be
allowed, depending upon the NFSPERMMAP attribute value for the OSS fileset that contains
the object.
The system software on NFS Version 2 (NFS V2) client systems makes its own access decisions
based on its interpretation of the permissions bits of the object. Because NFS Version 2 does not
provide support for ACLs, the ACL entries must be mapped to the nine basic permissions bits
used for objects in NFS. An object that is protected by an ACL cannot reflect the correct access
for all users in these nine permission bits. It might be that access that would be granted by the
mapped permission bits is actually denied explicitly by the ACL. It might also be that access that
seems to be denied by the mapped permission bits is, in fact, granted explicitly by the ACL. The
NFSPERMMAP attribute value selects the algorithm used to map the OSS ACL permissions for
the object to the standard permissions (rwxrwxrwx) expected for the object by NFS V2 clients.
For information about the NFSPERMMAP attribute, see the Open System Services Management
and Operations Guide.

Using OSS Access Control Lists (ACLs) 257


NOTE: If an OSS fileset has objects protected by OSS ACLs, that fileset must be mounted from
the NFS client systems using mount options that disable write buffering. Disabling write buffering
on the NFS client system causes NFS write requests from the NFS client systems to contain the
actual effective user id of the writing client process, which enables the NonStop system to properly
enforce the OSS ACL permissions. For example, the mapped NFS permissions can indicate to
an NFS client system that a user has write permission to a file when in fact that specific user is
denied in the OSS ACL on the NonStop system. In this case, an NFS write request that is denied
by an OSS ACL on the NonStop system is likely to be reported to the NFS client application as
an EIO or EPERM error.
Because of the behavior of some NFS V2 clients, if you do not disable write buffering, the server
might not receive the correct user ID information from the NFS client, which can result in write
requests being denied or data being written to a file by a client that should have been denied
write access. See the description of the OSS fileset NFSPERMMAP attribute in the Open System
Services NFS Management and Operations Guide.

For more information about OSS NFS file system security, see the Overview of NFS for Open System
Services and the Open System Services NFS Management and Operations Guide.

Header file
The sys/acl.h header file defines the following constants to govern the number of entries per
ACL:
NACLENTRIES
The maximum number of entries per ACL, including base entries
NACLBASE
The number of base entries
For compatibility with HP-UX, the variable name NACLVENTRIES is provided as an alias for
NACLENTRIES.
The ACL structure struct acl is also defined and includes these fields:
int a_type; /* type of entry */

uid_t a_id; /* group ID */

unsigned short a_perm; /* see <unistd.h> */


The sys/acl.h header defines the set of valid values for the a_type field in addition to the
valid values for the cmd parameter of the acl( ) function.
The sys/aclv.h header file contains the sys/acl.h header file and is provided for compatibility
with HP-UX.

Example Program For ACLs


Example 10-2 (page 259) provides simple examples of using the acl( ) and aclsort() APIs.

258 Managing OSS Security


Example 10-2 Using acl() and aclsort()
/* This program provides simple examples of acl(2) and aclsort(3) usage.
* It adds a GROUP ACL entry (with read permissions) to the ACL of the
* file. The file pathname and group ID number are passed as command
* arguments.
* To run:
* addACLgroup <pathname> <group ID number>
* This program performs the following steps:
* 1. Acquires the count of ACL entries in the ACL on the file
* using acl(ACL_CNT).
* 2. Allocates memory for the ACL buffer using malloc().
* 3. Acquires the existing ACL on the file using acl(ACL_GET).
* 4. Adds a new GROUP ACL entry to the end of the ACL buffer.
* 5. Calls aclsort() to sort the ACL entries in the ACL buffer
* into the proper order.
* 6. Sets the new ACL on the file using acl(ACL_SET).
* If you run this program twice on the same file, it will report
* an error in aclsort() as you are trying to add a second group ACL entry
* for the same group id. aclsort() points to the ACL entry in error.
*/

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <acl.h>
#include <errno.h>

#define READPERM 4
#define CALCCLASS 1

typedef struct acl acl_t;


void printAcl( char *header, acl_t *aclEnt, int count )

{
int i;
printf("%s\n",header);
for (i= 0; i < count; i++) {
printf("acl entry %d ", i);
printf("\ta_type = %d ", aclEnt[i].a_type );
printf("\ta_id = %d ", aclEnt[i].a_id );
printf("\ta_perm = %o\n", aclEnt[i].a_perm );
}

main( int argc, char *argv[])


{
acl_t *aclEnt = 0; /* pointer to ACL buffer */
char *pathname = 0; /* pointer to pathanme */
int prevCount, newCount; /* counts of ACL entries */
int groupId; /* group ID number for new ACL entry */
int error; /* error variable */

pathname = argv[1]; /* get ptr to pathname command argument */


groupId = atoi(argv[2]); /* get groupId command argument value */
printf("Input pathname = %s, input groupId = %d\n", pathname, groupId);

/* find out how many ACL entries in the existing ACL on the object */
if (( prevCount = acl(pathname, ACL_CNT, NACLENTRIES, aclEnt)) == -1 ) {
printf("acl(ACL_CNT) error= %d, text = %s\n", errno, strerror(errno));
return 1;
}

Using OSS Access Control Lists (ACLs) 259


printf("Number of ACL entries = %d\n", prevCount);

/* Allocate space, reserving 1 extra ACL entry for the new GROUP entry */

newCount = prevCount + 1;
if (( aclEnt = (acl_t *) malloc( newCount * sizeof(acl_t))) == 0 ) {
printf("malloc error= %d, text = %s\n", errno, strerror(errno));
return 1;
}

/* Acquire the existing ACL on the object */

if ((prevCount = acl(pathname, ACL_GET, prevCount, aclEnt)) == -1 ) {


printf("acl(ACL_GET) error= %d, text = %s\n", errno, strerror(errno));
free(aclEnt);
return 1;
}
printAcl("Existing ACL entries", aclEnt, prevCount);

/* add new GROUP acl entry at the end of the ACL */

aclEnt[ newCount-1 ].a_type = GROUP;


aclEnt[ newCount-1 ].a_id = groupId;
aclEnt[ newCount-1 ].a_perm = READPERM;
printAcl("New ACL entries before aclsort()",aclEnt, newCount);

/* sort all of the ACL entries into proper order for acl( ACL_SET) */

if ((error = aclsort(newCount, CALCCLASS, aclEnt)) != 0 ) {


printf("aclsort() error = %d\n", error);
free(aclEnt);
return 1;
}
printAcl("New ACL entries after aclsort()", aclEnt, newCount);

/* now set the new ACL on the object */

if ((error = acl(pathname, ACL_SET, newCount, aclEnt)) == -1 ) {


printf("acl(ACL_SET) error= %d, text = %s\n", errno, strerror(errno));
free(aclEnt);
return 1;
}
free( aclEnt );
return 0;
}

260 Managing OSS Security


11 Using the Standard POSIX Threads Library
Standard POSIX Threads is a user-space implementation of IEEE POSIX Standard 1003.1c pthreads
for use by native C and C++ applications in the OSS environment on NonStop servers. The POSIX
threads standard is officially described in International Standard ISO/IEC 9945-1; 1996 (E) IEEE
Std 1003.1,1996 (Incorporating ANSI/IEEE Stds 1003.1-1990, 1003.1b-1993, 1003.1c-1995, and
1003.1i-1995). For simplicity, this chapter refers to the “Standard document.” The Standard
document is available for purchase online at http://standards.ieee.org/.
To use threads, you should be familiar with programming in the OSS environment and with
writing threaded applications. See “About This Document” (page 15) for a list of books on
programming with threads. See the Open System Services Porting Guide for information about
porting existing threaded applications and for differences between the previous standard and
Standard POSIX Threads.
• “Standard POSIX Threads” (page 261)
• “Threading Considerations” (page 276)
• “Single Versus Multiple Application Threads” (page 279)
• “Jacket Routines” (page 281)
— “SERVERCLASS_SEND and SERVERCLASS_SENDL Jacket Routines” (page 281)
— “TMF Transaction Jacket Routines” (page 282)
• “Reference Pages for Thread Functions” (page 283)
• “Threaded Application Examples” (page 283)
• “Thread-Aware and Nonblocking OSS Functions” (page 288)
• “Reentrant OSS Functions” (page 313)
• — “Thread-Aware Toolkit Functions and Types” (page 316)
— “Thread-Aware $RECEIVE I/O Functions” (page 320)
• “Thread-Aware Enscribe Functions” (page 324)
• “OSS File Descriptor and Timer Callbacks” (page 326)

Standard POSIX Threads


Threads are scheduled for execution by the Standard POSIX Threads library, not by the NonStop
operating system. All threads created within a process share the same process address space.
With Standard POSIX Threads, one thread can never be preempted by another thread. You must
ensure that threads relinquish control either by explicitly calling the sched_yield() function
or by waiting on a mutex or condition variable.
All resources of a process—for example, open files or memory—are either global or private, as
shown in Table 11-1. Private resources can be accessed only by a specific thread. Global resources
can be accessed by all threads. Access to global resources by threads should be synchronized
using mutex or condition variables.
Table 11-1 Process Resources
Resource Type Description

Thread stack Private The memory where all thread-local variables are stored

Thread program counter Private The address of the instruction that the thread is about to execute

Thread context Private The data maintained by the threads library on behalf of a thread;
contains the per-thread signal mask, which is used by the
pthread_kill() function

All external data Global Includes process and module global resources

Standard POSIX Threads 261


Table 11-1 Process Resources (continued)
Resource Type Description

All static internal Global


variables

Heap Global

File descriptors and file Global Includes file and record locks
state

SQL cursors Global

Environment variables Global

Signal mask Global The per-process signal mask, used by the kill() function

Compiling and Linking Considerations


To use the Standard POSIX Threads library, you must:
• Include this header file:
/usr/include/spthread.h
The spthread.h file contains prototypes of the Standard POSIX Threads interfaces.
• Specify the _SPT_MODEL_ define. This define is required for systems running H06.21 or
later H-series RVUs or J06.10 or later J-series RVUs.
• For TNS/R programs, when linking with nld or ld, specify ZSPTSRL, the Standard POSIX
Threads shared run-time library.
• For TNS/E programs, when linking with eld, specify ZSPTDLL, the Standard POSIX Threads
DLL, before specifying any public libraries, such as ZSECDLL.
These libraries are located in the current sysnn subvolume.
Beginning with RVU G06.22, T1248 supports both the VERSION2 and VERSION3 C++ libraries.
Additionally, take special steps to ensure that exception handling will continue to function
properly. For compiling a TNS/R C++ program utilizing T1248 and the C++ exception handling
mechanism, link the object /usr/lib/sptcpp.o. This object ensures that exception handling
will continue to work, regardless of the C++ version. However, for programming exclusively in
C, or in C++ on a TNS/E system, linking /usr/lib/sptcpp.o is not necessary.

Error Reporting Changed From Previous Standard


Standard POSIX Threads functions return error indications as return values, instead of setting
errno. The error values returned are in many cases the values that were stored in errno in
Draft 4. Standard POSIX Threads supports only the error values described in the Standard
document.
If an error condition occurs, a pthread routine returns an integer value indicating the type of
error. For example, a call to the Draft 4 implementation of pthread_cond_ destroy() that
returned a -1 and set errno to EBUSY now returns EBUSY as the routine return value.
Reporting errors by returning error values is a global change from the previous standard (Draft
4), in which errors are reported in errno. If you are porting a threaded application that adheres
to Draft 4, you must rewrite the error handling routines. The “Threaded Application Examples”
(page 283) demonstrates error handling with Standard POSIX Threads. See the Open System
Services Porting Guide for a list of the supported return values as well as other porting issues.

Attributes Defined by Threads Macros


The attributes of Standard POSIX Threads are determined by macros in unistd.h. Table 11-2
lists the principal macros that influence the HP implementation for NonStop servers.

262 Using the Standard POSIX Threads Library


Table 11-2 Attributes of Standard POSIX Threads Defined by Macros
Macro or Attribute Description in Standard POSIX Threads

Mutex and condition variable initialization attributes: Not defined. A mutex or condition variable can be
_POSIX_THREAD_PROCESS_SHARED operated on only by threads in the same process that
initialized the mutex or condition variable.

Thread scheduling attribute: Not defined. Threads are created with the
_POSIX_THREAD_PRIORITY_SCHEDULING PTHREAD_SCOPE_PROCESSscheduling contention scope
by default. Threads contend directly with other threads
within their process. This attribute cannot be altered.
The scheduling allocation domain size is 1. Threads are
always bound to the same processor as the parent thread.

Thread scheduling attribute: Has the value PTHREAD_EXPLICIT_SCHED. The


inheritsched scheduling policy and associated attributes, such as
priority, are set to the corresponding values from the
attributes object during thread creation.
This attribute can be altered to
PTHREAD_INHERIT_SCHED (so that the scheduling policy
and attributes are inherited from the creating thread) by
using pthread_attr_setinheritsched().

Thread scheduling attribute: The default value is SCHED_FIFO. This attribute cannot
schedpolicy be altered.

Mutex initialization scheduling attributes: Not defined. The prioceiling and protocol attributes
_POSIX_THREAD_PRIO_INHERIT are not defined.
_POSIX_THREAD_PRIO_PROTECT

Thread creation attribute: Defined. The thread creation stack size attribute can be
_POSIX_THREAD_ATTR_STACKSIZE set in the attribute object.

Thread creation attribute: Not defined. The location of the storage to be used for the
_POSIX_THREAD_ATTR_STACKADDR stack of the created thread cannot be altered.

Thread creation attribute: The default value is PTHREAD_CREATE_JOINABLE (that


detachstate is, storage associated with the thread is reclaimed when
the thread that created it calls a join()).
This attribute can be altered using
pthread_attr_setdetachstate().

Signal Handling
There are two basic types of signals:
• Synchronous signals represent events that occur inside a process.
Synchronous signals occur immediately after the instruction that caused the event—for
example, attempting to divide by zero. A synchronous signal is associated with the thread
that is executing when the event occurs. A thread can install signal handlers (using the
sigaction() function) for the synchronous signals that occur during its execution. For
terminating signals, the default behavior is to terminate the process.
• Asynchronous signals represent events external to a process.
A thread can wait for a set of asynchronous signals using the spt_sigwait() function. If
a thread is waiting for a type of signal that is received, the thread is awakened and if a signal
handler has been installed, it is invoked, and the signal is considered handled; otherwise,
the default signal action is taken. For a terminating signal, the default behavior is to terminate
the process. For J-series RVUs, H06.06 and later H-series RVUs, and G06.29 and later G-series
RVUs, you can define signal-catching functions for asynchronous signals. See “Thread-Aware
Signal Handling” (page 265).

Standard POSIX Threads 263


The supported signal numbers are listed in Table 11-3. For more information about the Standard
POSIX Threads implementation of signals, see “Using Signals” (page 278).
Table 11-3 Signals Processed by Threads
Name Number Type Default Action Description

SIGABEND 311 Process-level Terminate with saveabend Abnormal termination

SIGABRT 6 Synchronous Terminate with saveabend Abort process

SIGALRM 14 Alarm signal Terminate process Alarm clock

SIGCHLD 18 Process-level Discard signal Child has stopped or


terminated

SIGCONT 28 Process-level Continue execution Continue execution

SIGFPE 8 Synchronous Terminate with saveabend Arithmetic overflow

SIGHUP 1 Process-level Terminate process Hangup

SIGILL 4 Synchronous Terminate with saveabend Invalid instruction

SIGINT 2 Asynchronous Terminate process Interrupt

SIGIO 7 Synchronous Discard signal IO possible or completed

SIGKILL 91 Process-level Terminate process Kill

SIGLIMIT 27 Synchronous Terminate with saveabend NonStop operating system


limits trap

SIGMEMERR 22 Synchronous Terminate with saveabend Uncorrectable memory error

SIGMEMMGR 24 Synchronous Terminate with saveabend Memory manager read error

SIGNOMEM 23 Synchronous Terminate with saveabend No memory available


2
SIGPIPE 13 Asynchronous Terminate process Write on a pipe, no one to
read it

SIGQUIT 3 Asynchronous Terminate with saveabend Quit

SIGRECV 19 Synchronous Discard signal Message queued on


$RECEIVE (currently not
used)

SIGSEGV 11 Synchronous Terminate with saveabend Invalid address reference

SIGSTK 25 Synchronous Terminate with saveabend Stack overflow


1
SIGSTOP 20 Process-level Terminate process Stop

SIGTERM 15 Asynchronous Terminate process Software termination signal

SIGTIMEOUT 26 Process-level3 Terminate process Process loop timer time-out

SIGTSTP 21 Process-level Terminate process Interactive stop

SIGTTIN 29 Process-level Stop process Background read attempted


from controlling terminal

SIGTTOU 30 Process-level Stop process Background write attempted


to controlling terminal

SIGUNCP 10 Process-level3 Discard signal Uncooperative process.


Supported for servers
running H-series RVUs only.

SIGURG 5 Asynchronous2 Discard signal Urgent condition on I/O


channel

SIGUSR1 16 Asynchronous Terminate process User-defined signal 1

264 Using the Standard POSIX Threads Library


Table 11-3 Signals Processed by Threads (continued)
Name Number Type Default Action Description

SIGUSR2 17 Asynchronous Terminate process User-defined signal 2

SIGWINCH 12 Synchronous Discard signal Terminal device window size


changed
1 Signal cannot be caught or ignored.
2 For H06.20 and earlier H-series RVUs and J06.09 and earlier J-series RVUs, this is a synchronous signal
3 Not supported on G-series RVUs

Thread-Aware Signal Handling


For J-series RVUs, H06.06 and later H-series RVUs, and G06.29 and later G-series RVUs, the HP
implementation of Standard POSIX Threads catches both externally generated OSS signals and
synchronous signals, which are result of an event that occurs inside a process, and deliver them
to the correct thread.
By default, thread-aware signal behavior is disabled, and signals are handled at the process level.
To enable thread-aware signal handling, export the SPT_THREAD_AWARE_SIGNAL
environmental variable from within the shell to the value 1:
> export SPT_THREAD_AWARE_SIGNAL=1

Standard POSIX Threads 265


Types of Signals
Signals are categorized as synchronous, asynchronous, or process level:
• Synchronous signals result from an event that occurs inside a process and are delivered
synchronously with that event. These signals are delivered to current active thread. If current
active thread has not installed the signal handler, then default actions are performed. Signals
in this category are:1
SIGABRT
SIGFPE
SIGILL
SIGIO
SIGLIMIT
SIGMEMERR
SIGMEMMGR
SIGNOMEM
SIGSEGV
SIGSTK
SIGWINCH
• Asynchronous signals result from an event that is external to the process and are delivered
at any point in the execution of a thread. These signals are delivered to the active threads
in FIFO order. If no active threads have installed a signal handler for the signal, the
process-level actions described in Table 11-3 (page 264) are performed. Signals in this category
are:
SIGINT
SIGPIPE1
SIGQUIT
SIGTERM
SIGURG 1
SIGUSR1
SIGUSR2
• For process level signals only process level actions can be performed. Signal handlers for
these signals are registered directly to the operating system, so an existing handler for a
given signal is overwritten when a new signal handler is defined for that signal. Signals in
this category are:
SIGABEND (can’t be handled by a user-defined signal handler)
SIGCONT
SIGKILL (can’t be handled by a user-defined signal handler)
SIGSTOP (can’t be handled by a user-defined signal handler)
SIGTSTP (process level action is performed)
SIGTIMEOUT (not supported on G-series RVUs)
SIGTTIN
SIGTTOU
SIGUNCP (not supported on G-series RVUs)

266 Using the Standard POSIX Threads Library


Thread-Aware Signal Handling APIs
These APIs are supported for J-series RVUs, H06.06 and later H-series RVUs, and G06.29 and
later G-series RVUs:

API Description

spt_signal() Allows the calling thread to change the action to be taken when a specific signal is
delivered to the thread issuing this function call. To enable thread-aware signal handling,
export the SPT_THREAD_AWARE_SIGNAL environmental variable from within the
shell to the value 1. If thread-aware signal handling is not enabled, signals are handled
at the process level.
For C applications, an application call to signal() is automatically mapped to
spt_signal() when you compile the application using the
#define _SPT_THREAD_SIGNAL feature test macro or an equivalent compiler
command option.
For C++ applications, an application call to signal() is automatically mapped to
spt_signal() when you compile the application using the
#define _SPT_THREAD_SIGNAL_PRAGMA feature test macro or an equivalent
compiler command option.

spt_alarm() Arranges for a SIGALRM signal to be delivered to the process from a thread in the
specified number of seconds. To enable thread-aware signal handling, export the
SPT_THREAD_AWARE_SIGNAL environmental variable from within the shell to the
value 1. If thread-aware signal handling is not enabled, alarms are handled at the
process level.
For C applications, an application call to alarm() is automatically mapped to
spt_alarm() when you compile the application using the
#define _SPT_THREAD_SIGNAL feature test macro or an equivalent compiler
command option.
For C++ applications, an application call to alarm() is automatically mapped to
spt_alarm() when you compile the application using the
#define _SPT_THREAD_SIGNAL_PRAGMA feature test macro or an equivalent
compiler command option.

Limitations
Do not deliver signals like SIGALRM and SIGCHLD using the kill command or the raise()
function because these functions do not provide enough information about the process IDs for
the parent and child processes. Instead, use the spt_alarm() function to raise alarms.

Examples
Example 11-1 (page 268) provides an example of handling the synchronous signal SIGFPE.
The output of Example 11-1 (page 268) depends on whether thread-aware signal handling is
enabled:
• If thread-aware signal handling not enabled, the signal handler defined in the example,
sighand, is not executed, and signal 31 (SIGABEND) is delivered to the process.
• If thread-aware signal handling is enabled, the signal handler defined in the example is
executed, and signal 8 (SIGFPE) is received by the thread. On successful return from a
signal-catching function for a SIGFPE, SIGILL, SIGLIMIT,SIGMEMERR, SIGMEMMGR,
SIGNOMEM, SIGSEGV, or SIGSTK signal that was not generated by a kill() or raise()
function call, a process receives a SIGABEND signal and terminates.

1. The SIGPIPE and SIGURG signals are synchronous for H06.20 and earlier H-series RVUs and J06.09 and earlier J-series
RVUs, and asynchronous for H06.21 and later H-series RVUs and J06.10 and later J-series RVUs.

Standard POSIX Threads 267


Example 11-1 Handling the Synchronous Signal SIGFPE
/* This test program demonstrates handling the */
/* SIGFPE synchronous signal. */
/* You must also export the environment variable **/
/* SPT_THREAD_AWARE_SIGNAL to 1 to **/
/** enable thread-aware signal handling **/

#define SPT_THREAD_AWARE /** enables thread aware behavior **/


#define SPT_THREAD_SIGNAL /** maps signal() to spt_signal()**/
#include <spthread.h>

/*Define a signal handler for this thread */


void sighand(int signo);
int x=10,y=0,z;

void *threadfunc(void *parm)

/* Perform the illegal operation of dividing by zero and */


/* raise the SIGFPE signal. The SIGFPE signal is sent to */
/* the generic handler. */
{
signal(SIGFPE,sighand);
z = x/y;
printf("\nI am in thread1\n");
return NULL;
}

int main(int argc, char **argv)

pthread_t thread1;
int rc;
printf("Enter Testcase - %s\n", argv[0]);

/* create the thread */


pthread_create(&thread1, NULL, threadfunc, NULL);
sleep(1);
printf("Wait for threads to complete\n");
pthread_join(thread1, NULL);
printf("Main completed\n");
return 0;
}
void sighand(int signo)
{
printf("Signal received is %d\n",signo);
}

Example 11-2 (page 270) creates a thread that waits for asynchronous signal SIGINT.
Sample input:
> kill -2 process-name
or
<CRTL-C>
Both of these inputs generate a SIGINT signal.
The output of Example 11-2 (page 270) depends on whether thread-aware signal handling is
enabled:
• If thread-aware signal handling is not enabled, the program terminates, which is the default
behavior when signal 2 (SIGINT) is received. Sample output:

268 Using the Standard POSIX Threads Library


Enter Testcase - ./Test2
spt_sigaction returned 0
Wait for threads to complete
• If thread-aware signal handling is enabled, the signal handler of thread1 is executed and
thread1 no longer waits for a signal. Sample output:
Enter Testcase - ./Test2
spt_sigaction returned 0
Wait for threads to complete
Signal received is 2
spt_sigsuspend returned -1
Main completed.
This behavior differs from the behavior when thread-aware signal handling is not enabled
because the generic handler catches the signal delivered to a process and delivers the signal
to the correct thread(s).

Standard POSIX Threads 269


Example 11-2 Handling the Synchronous Signal SIGINT
/* Program which demonstrates behavior of Asynchronous */
/* signal SIGINT */

/** You must also export the environment variable **/


/** SPT_THREAD_AWARE_SIGNAL to 1 to **/
/** enable thread-aware signal handling **/

#define SPT_THREAD_AWARE /** enables thread aware behavior **/


/** and maps functions to spt_ versions **/
#include <spthread.h>

void sighand(int signo);

struct sigaction sigact_t;

sigset_t waitset;

void *threadfunc(void *parm)

int rc1,rc2;
sigfillset( &waitset );
sigdelset( &waitset,SIGINT);
sigact_t.sa_handler = sighand;
rc1 = sigaction(SIGINT,&sigact_t,NULL);
printf("\nspt_sigaction returned %d\n",rc1);
rc2=sigsuspend(&waitset);
printf("\nspt_sigsuspend returned %d\n",rc2);
return NULL;

int main(int argc, char **argv)

pthread_t thread1;
int rc;
printf("Enter Testcase - %s\n", argv[0]);
pthread_create(&thread1, NULL, threadfunc, NULL);
sleep(1);
printf("Wait for threads to complete\n");
pthread_join(thread1, NULL);
printf("Main completed\n");
return 0;
}

void sighand(int signo)


{
printf("Signal received is %d\n",signo);
}

Example 11-3 (page 272) demonstrates handling the SIGCHLD signal. This example creates two
threads, each of which call fork(). When the child process executes, the process raises the
SIGCHLD signal.

270 Using the Standard POSIX Threads Library


The output of Example 11-3 (page 272) depends on whether thread-aware signal handling is
enabled:
• If thread-aware signal handling is not enabled, the SIGCHLD signal results in the default
action described in Table 11-3 (page 264) (discard the signal). In this example,
spt_sigaction() fails because it is not supported. Sample output:
spt_sigaction for thread1 returned -1
spt_sigaction for thread2 returned -1
Inside Child of Thread1
Inside Child of Thread2
Main Completed
• If thread-aware signal handling is enabled, the SIGCHLD signal is delivered to the correct
thread, and spt_sigaction() function in the example defines the action to be taken.
Sample output:
spt_sigaction for thread1 returned 0
spt_sigaction for thread2 returned 0
Inside Child of Thread2
Signal received for Thread2 is 18
Inside Child of Thread1
Signal received for Thread1 is 18
Main Completed

Standard POSIX Threads 271


Example 11-3 Handling the SIGCHLD Signal
/* This program demonstrates the handling of the */
/* SIGCHLD signal */

/** You must also export the environment variable **/


/** SPT_THREAD_AWARE_SIGNAL to 1 to **/
/** enable thread-aware signal handling **/
#define SPT_THREAD_AWARE /** enables thread aware behavior **/
/** and maps functions to spt_ versions **/
#include <spthread.h>
struct sigaction sigact_t,osigact_t;
sigset_t waitset;
int rc;

void sig_cld1(int);
void sig_cld2(int);
void *do_work1(void *arg)
{
pid_t pid;
sigact_t.sa_handler =sig_cld1;
sigact_t.sa_flags = 0;
rc =spt_sigaction(SIGCHLD,&sigact_t,NULL);
printf("\nspt_sigaction for thread1 returned %d\n",rc);
if ((pid = fork()) < 0)
printf("ERROR IN FORK\n");
else if (pid == 0)
{
sleep(2);
printf("\nInside Child of Thread1\n");
exit(0);
}
spt_waitpid(pid,NULL,NULL);
return NULL;
}

void *do_work2(void *arg)


{
pid_t pid;
osigact_t.sa_handler =sig_cld2;
osigact_t.sa_flags = 0;
rc = spt_sigaction(18,&osigact_t,NULL);
printf("\nspt_sigaction for thread2 returned %d\n",rc);
if ((pid = fork()) < 0)
printf("ERROR IN FORK\n");
else if (pid == 0)
{
sleep(1);
printf("\nInside Child of Thread2\n");
exit(0);
}
spt_waitpid(pid,NULL,NULL);
return NULL;

}
void main()
{
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,do_work1,NULL);
pthread_create(&tid2,NULL,do_work2,NULL);
sched_yield ();
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
printf ("\nMain Completed\n");

272 Using the Standard POSIX Threads Library


}

void sig_cld1(int signo)


{
printf("\nSignal received for Thread1 is %d\n",signo);
}

void sig_cld2(int signo)


{
printf("\nSignal received for Thread2 is %d\n",signo);
}

Example 11-4 (page 274) provides an example of SIGALRM handling. It creates two threads that
wait for a SIGALRM signal.
The output of Example 11-4 (page 274) depends on whether thread-aware signal handling is
enabled:
• If thread-aware signal handling not enabled, the entire process terminates when the SIGALRM
signal is received. Sample output:
spt_sigaction for thread1 returned 0
spt_sigaction for thread2 returned 0
• If thread- aware signal handling is enabled, SIGALRM signal is delivered to the correct
thread, and the sighand1() and sighand2() functions define the actions to be taken . Sample
output:
spt_sigaction for thread1 returned 0
spt_sigaction for thread2 returned 0
Signal received for thread1 is 14
spt_sigsuspend for thread1 returned -1
spt_sigwait returned 0
spt_sigwait for thread2 returned for signal 14
Main Completed

Standard POSIX Threads 273


Example 11-4 Handling SIGALRM Signals
/*Program demonstrating handling the SIGALRM signal */

/** You must also export the environment variable SPT_THREAD_AWARE_SIGNAL **/
/** to 1 to enable thread-aware signal handling **/
#define SPT_THREAD_AWARE /** enables thread aware behavior and maps **/
/** functions other than alarm() and signal() to their spt_ versions**/
#define SPT_THREAD_SIGNAL /** maps alarm() to spt_alarm()**/
#include <spthread.h>
void sighand1(int);
void sighand2(int);
struct sigaction sigact_t;
int rc;
void *do_work(void *arg)
{
sigset_t set;
sigfillset(&set);
sigdelset(&set,SIGALRM);
sigact_t.sa_handler = sighand1;
rc = spt_sigaction(SIGALRM,&sigact_t,NULL);
printf("\n spt_sigaction for thread1 returned %d\n",rc);
alarm(5);
rc = spt_sigsuspend(&set);
printf("\nspt_sigsuspend for thread1 returned %d\n",rc);
return NULL;
}

void *do_work1(void *arg)


{

sigset_t set;
int sig;
sigemptyset(&set);
sigaddset(&set,SIGALRM);
sigact_t.sa_handler = sighand2;
rc=spt_sigaction(SIGALRM,&sigact_t,NULL);
printf("\nspt_sigaction for thread2 returned %d\n",rc);
alarm(6);
rc=spt_sigwait(&set,&sig);
printf("\nspt_sigwait returned %d\n",rc);
printf("\nspt_sigwait for thread2 returned for signal %d\n",sig);
return NULL;

int main()
{
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,do_work,NULL);
pthread_create(&tid2,NULL,do_work1,NULL);
sched_yield();
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
printf("\nMain Completed\n");
}

void sighand1(int signo)

{
printf("Signal received for thread1 is %d\n",signo);
}

void sighand2(int signo)


{
printf("Signal received is %d\n",signo);
}

274 Using the Standard POSIX Threads Library


Threads Portability
Standard POSIX Threads follow the POSIX threads Standard document. Using thread functions
whose names end with _np (non-portable) decreases the portability of a program, because these
functions are extensions to the standard. Using the jacket routines provided by HP also reduces
portability of a threaded application; see “Jacket Routines” (page 281) for more information about
the jacket routines.

Numerical Limits in Standard POSIX Threads


Table 11-4 lists numerical limits imposed by the standard implementation. The symbolic constants
listed in the table are defined in limits.h with the values shown in the table. These symbolic
constants refer to the most restrictive value for each feature.
Table 11-4 Numerical Limits in Standard POSIX Threads
Symbolic Constant Description Value

_POSIX_ARG_MAX Maximum length of the arguments for one of the 4096


exec functions, in bytes, including environment
data

_POSIX_CHILD_MAX Maximum number of simultaneous processes for 6


one real user ID

_POSIX_FD_SETSIZE Maximum number of descriptors that a process _POSIX_OPEN_MAX


can examine

_POSIX_HIWAT Maximum number of bytes that can be buffered _POSIX_PIPE_BUF


on a socket for sending or receiving

_POSIX_LINK_MAX Maximum value of a file’s link count 8

_POSIX_MAX_CANON Maximum number of bytes in a terminal canonical 255


input queue

_POSIX_MAX_INPUT Maximum number of bytes for which space will 255


be available in a terminal input queue

_POSIX_NAME_MAX Maximum number of bytes in a filename 14

_POSIX_NGROUPS_MAX Maximum number of simultaneous supplementary 0


group IDs for one process

_POSIX_OPEN_MAX Maximum number of files that one process can 256


have open at one time

_POSIX_PATH_MAX Maximum number of bytes in a pathname 255

_POSIX_PIPE_BUF Maximum number of bytes that can be written 512


atomically when writing to a pipe

_POSIX_QLIMIT_ Maximum number of connections that can be 1


queued on a socket

_POSIX_SSIZE_MAX Maximum value that can be stored in an object of 32,767


type ssize_t

_POSIX_STREAM_MAX Maximum number of streams that one process can 8


have open at one time

_POSIX_TZNAME_MAX Maximum number of bytes supported for time 3


zone names

Standard POSIX Threads 275


Keeping Application Design Simple
Because of the inherent complexity of multithreaded programming, application designers should
follow these recommendations:
• Write programs with a single application thread when possible.
• Keep multiple application threads independent of each other when possible. If this is not
possible, keep the interdependencies to a minimum.

Threading Considerations
Application designers should be aware of the following general threading considerations when
developing a Standard POSIX Threads application:
• “Sharing Process Resources” (page 276)
• “Using Standard Libraries” (page 276)
• “Addressing the Thread Stack” (page 277)
• “Making Process-Blocking Calls” (page 277)
• “Using Nowait Input or Output” (page 277)
• “Yielding Control” (page 278)
• “Using Signals” (page 278)
• “Spawning a New Process” (page 279)
• “Isolating Faults” (page 279)

Sharing Process Resources


Access by threads to shared process resources such as global data, the heap, and files must be
synchronized using mutexes and condition variables. Table 11-1 (page 261) lists global and private
process resources.

Using Standard Libraries


No Need for Jacket Routines or Special Header Files
Standard POSIX Threads execute until they relinquish control. A thread can never be preempted
while executing code in a standard library. Therefore, an application does not need to protect
standard libraries with global mutexes or use special header files. Standard libraries do not
require jacket routines or other modifications to make them thread-safe or reentrant.
The thread library does provide jacket routines for calls to Pathway servers (SERVERCLASS_SEND
and SERVERCLASS_SEND_INFO) and for TMF transactions, as described in “Jacket Routines”
(page 281).

No Asynchronous Cancels
Standard POSIX Threads does not support the asynchronous receipt of cancels; a thread can
never exit prematurely from a standard library due to cancellation. Therefore, an application
does not need to protect the run-time state of standard libraries by disabling cancelability before
making a call into the libraries.

Beware of Pointers to Static Library Data


Some libraries contain functions that return pointers to static data. In this case, one thread could
invalidate another thread’s pointer. For example, the getpwuid() function returns a pointer to
information about a user, contained in a static variable in the library. This static variable is
overlaid on the next call to this procedure by any thread.
When using functions that return pointers to static library data, immediately copy the data to
thread-private memory.

276 Using the Standard POSIX Threads Library


Beware of Libraries That Maintain Context Across Calls
Some libraries maintain context across calls. For example, the getpwent() function returns
information about the next user in the user database, with the current position kept implicitly
in the library. The setpwent() function ensures that the next call to getpwent() returns the
first user entry. A program can get unexpected results if two different threads use these functions
without synchronizing their calls.
You can use a mutex to protect implicit context maintained by a standard library, for example
by bracketing a series of library calls with the lock and unlock of a mutex. This technique should
be used only for short periods of time.
Standard libraries that use an explicit handle to identify the intended context on each call can be
used without interference between threads. File operations that use file descriptors follow this
model.
Some libraries allow multiple contexts but do not support explicit context identification on all
calls. Instead, the library allows the caller to establish a current context for the process. With
these libraries, the application is responsible for ensuring that the correct context is made current
while a thread is executing. For example, the TMF transaction-demarcation jacket routines use
this method, relying on an implicit current transaction for the process.

Addressing the Thread Stack


Memory for function variables that are not declared static is allocated from the thread-private
stack. This memory is addressable only while the thread is executing. It is not addressable by
other threads; attempting to read or write variables located in another thread’s stack causes
unpredictable results.
All program data that is to be shared by multiple threads must be external data, static internal
data, or data allocated from the heap. This data should be protected by a mutex, as appropriate.
The Standard provides a set of functions to manage thread-specific data. One use of these functions
is to maintain thread global data, such as state. The interface allows you to declare destructor
functions that are invoked at thread run-down. These functions are distinct from cancellation
clean-up handlers.

Making Process-Blocking Calls


When a thread calls a Guardian procedure that blocks the process, all other threads in the process
are also prevented from executing. If a thread is blocked for a significant period of time, it can
delay or even prevent the execution of time-critical run-time functions.
Examples of programs that can block include:
• Pathway servers, which can wait indefinitely while reading $RECEIVE
• The Inspect, Native Inspect, and Visual Inspect symbolic debuggers, whose use can block
a process indefinitely

Using Nowait Input or Output


Programs that use threads cannot call the Guardian AWAITIO or AWAITIOX procedure with
-1 as a file parameter (applying the call to the oldest incomplete operation pending on each file).
AWAITIOX can be used to poll for completion on a specific file, although a thread must complete
all nowait input or output operations before yielding control to another thread. In summary:
• No calls to AWAITIO[X]() with a file number of -1 are made outside of pthreads.
• No calls to AWAITIO[X]() with a file number registered with pthreads are made outside
of pthreads.

Threading Considerations 277


Yielding Control
Because Standard POSIX Threads are never preempted, a call to the sched_yield() function
might be needed to allow time-critical run-time threads to execute. This function releases the
processor to another thread of the same or higher priority. The calling thread may get control
immediately if no threads of the same or higher priority are ready to run.
Be careful using the sched_yield() function. Misuse causes unnecessary context switching,
which increases overhead without allowing the other threads to execute. For example, it is
counterproductive for a thread to yield control while it has a needed resource locked.

Using Signals
• The following signal features are not supported:
— Job Control Signals. The stop a process or continue a process actions implied by these
signals are also not supported.
— The Real-time Signals Extension option.
• Use the sigaction() function, not the signal() function, to specify the action to be
taken when a given signal is received.
• The threads library contains jacket routines for the following OSS system and library
functions:
sigaction()
sigpending()
sigsuspend()
pause()
sleep()
In addition, spt_alarm() and spt_signal() are provided for thread aware signal
handling (see “Thread-Aware Signal Handling” (page 265)).
• The pthread_kill() function provides a mechanism for synchronously directing a signal
to a thread in the calling process.
• A signal is handled in the context of the given thread. However, the signal action (terminating
or stopping) might affect the process as a whole. See “Thread-Aware Signal Handling”
(page 265).
• Signals sent with the pthread_kill() function are queued in FIFO order for the target
thread. More than one instance of the same signal might be pending for a thread. However,
applications should not rely on this ordering.
• You must specify whether a signal listed in Table 11-3 (page 264) as generating a saveabend
actually generates a saveabend by specifying the -Wsaveabend flag in c89 or c99, or
saveabend in nld, ld, or eld.
• If a signal is delivered to a thread waiting on a condition variable, then upon return from
the signal handler, the thread will resume waiting for the condition variable as if it were not
interrupted.

Using Signals With the setjmp() and longjmp() Functions


Using the setjmp() and longjmp() functions can interfere with signal handling. The
longjmp() function causes a thread to jump to the execution context saved by a previous call
to the setjmp() function, but it does not restore the signal mask of the process. If the longjmp()
function is called within a signal handler, the signal mask used in the signal handler is retained
when execution resumes at the setjmp() location. The exception mechanism uses the setjmp()
and longjmp() functions and behaves similarly.
The sigsetjmp() and siglongjmp() functions have an option to save and restore the signal
mask. This option can cause signals that were enabled by another thread to be inadvertently
masked.

278 Using the Standard POSIX Threads Library


When handling signals:
• Do not use the raise() function for an exception, and do not use the longjmp() function
to exit a synchronous signal handler. Simply returning from a signal handler is safe and is
the recommended practice.
• Use exception handlers instead of the setjmp() and longjmp() functions for threaded
OSS applications.
• Do not use the option of the sigsetjmp() and siglongjmp() functions that saves and
restores the signal mask. Doing so can cause signals enabled by another thread to be masked.

Spawning a New Process


Using the fork() or tdm_fork() function in a multithreaded environment can cause problems.
Applications can use either of these functions safely as follows: A parent process that has already
called a function can also use either of the fork functions to create a child process if the child
process calls any of the exec functions, the tdm_execve(), or tdm_execep() function
immediately upon its creation.
A threaded application might alternatively use pthread_atfork() to declare as many as three
fork handlers: a prepare handler called before the fork, a parent handler called after the fork in
the parent process, and a child handler called after the fork in the child process.
When a fork is called, only the calling thread is duplicated in the child process. The expected
usage of pthread_atfork() is for the prepare handler to acquire all mutex locks of interest
to the child, and the other two fork handlers to release them.

Isolating Faults
Because all threads created by a process share the process address space, there is no address
space protection between the application threads in a process. One application thread can corrupt
data, causing other threads or the entire process to fail.

Single Versus Multiple Application Threads


OSS threaded applications can be classified as follows, in order of increasing complexity:
• “Programs With a Single Application Thread” (page 279)
• “Programs With Multiple Independent Application Threads” (page 280)
• “Programs With Multiple Interdependent Application Threads” (page 280)

Programs With a Single Application Thread


Externally, programs with a single application thread behave like standard, sequential
(nonthreaded) programs. The program begins execution in the main() procedure; it then calls
other procedures that, in turn, can call still other procedures. This type of application includes
simple OSS client programs.
In single-threaded applications:
• Process resources can be used freely.
No synchronization is needed. The application can freely use process resources such as
process and module globals, the heap, file descriptors, SQL cursors, and the signal mask.
Mutexes and condition variables are not needed.
• Standard libraries can be used freely.
The application can share access to library data, including implicit context maintained across
multiple library calls. For example, the application thread can use the TMF transaction jacket
routines and no other thread can change the current transaction of the process.

Single Versus Multiple Application Threads 279


• One application thread cannot block another from executing. Process-blocking operations
have minimal effect.
• One application thread cannot corrupt another.
The thread does not share its address space with any other application threads. The
application thread is protected by the address-space protection provided for the process,
offering fault isolation.
The following general threading considerations affect single-threaded applications but have less
effect than for processes with multiple application threads:
• Using process-blocking calls
Although process-blocking calls will not affect other will not affect other application threads,
they can interfere with time-critical threads.
• Isolating faults and yielding control
If the application thread can execute for long periods (more than a second) without
relinquishing control, the application might still need to use the sched_yield() function
to allow time-critical threads to execute.
These general threading considerations apply to single-threaded applications:
• Using nowait input or output as described in “Using Nowait Input or Output” (page 277).
• Spawning a process as discussed in “Spawning a New Process” (page 279).

Programs With Multiple Independent Application Threads


Programs containing multiple threads can improve performance by providing concurrent
execution. An application thread is independent if it does not explicitly share application resources
that exist in the process environment, such as application file opens, SQL cursors, or modifiable
application data structures.
This type of application includes simple OSS servers that maintain the application state in a
database. Such a server simplifies server design because then application state does not need to
be maintained in the server and thus most servers can be context-free. In cases where context
must be maintained across multiple requests, the context is generally private to the client and
should not be shared.
“Threading Considerations” (page 276) describes some considerations for developing an
application with multiple application threads.

Programs With Multiple Interdependent Application Threads


An application thread is interdependent if it shares application resources that exist in the process
environment, such as application file opens, SQL cursors, and modifiable application data
structures. Applications with multiple interdependent application threads must synchronize
access to the shared application resources.
This type of application includes OSS servers that maintain application state in the server to
improve performance or that share resources, such as file opens, to reduce resource consumption.
This type of application also includes client programs that use parallelism.
Programs with multiple interdependent application threads can be synchronized by using
mutexes to reserve access to a shared resource and by using condition variables to wait for a
shared resource to be in a certain state.
Poor performance can result if inappropriate synchronization techniques are used. Synchronizing
at too coarse a level can overly restrict concurrency and cause a server to serialize processing,
dramatically increasing the application’s service time. Synchronizing at too fine a level can result
in an increase in the processor cycles spent on initializing, obtaining, and releasing mutexes and
dispatching threads.

280 Using the Standard POSIX Threads Library


Jacket Routines
A jacket routine invokes a nonblocking (nowait) version of the system call and suspends the
thread until the thread’s operation is complete. Standard POSIX Threads provides jacket routines
for SERVERCLASS_SEND and SEVERCLASS_SENDL_ calls and for TMF transaction demarcation.
Full reference and syntax information for the jacket routines is available online in the OSS
environment using the man command.

SERVERCLASS_SEND and SERVERCLASS_SENDL Jacket Routines


The SPT_SERVERCLASS_SEND_() function in the threads library sends a message to and receives
a reply from a server process in a Pathway server class. This jacket routine invokes a nowait
version of the system SERVERCLASS_SEND_ procedure. The thread that makes the call is
suspended until the send operation is complete.
The SPT_SERVERCLASS_SENDL_() function, which is supported on J06.07 and later J-series
RVUs and H06.18 and later H-series RVUs only, also sends a message to and receives a reply
from a server process in a Pathway server class. This jacket routine invokes a nowait version of
the system SERVERCLASS_SENDL_ procedure. The thread that makes the call is suspended
until the send operation is complete. This function allows for messages up to two megabytes
long when Expand-over-ServerNet is used. This function does not support using Expand-over-IP.
These functions can be used with the SPT_SERVERCLASS_SENDL_() function:
spt_INITRECEIVEL()
spt_RECEIVEREADL()
spt_REPLYXL()
Another jacket routine, the SPT_SERVERCLASS_SEND_INFO_() function returns information
about the last SPT_SERVERCLASS_SEND_() or SPT_SERVERCLASS_SENDL_() call that was
attempted or completed by the current thread. The SPT_SERVERCLASS_SEND_INFO_() function
ensures that the thread gets the information for the last message sent by the thread rather than
by the process.
The SERVERCLASS_SENDL_ jacket routines (SPT_SERVERCLASS_SENDL(),
spt_INITRECEIVEL(), spt_RECEIVEREADL(), and spt_REPLYXL()) are included in the
Standard POSIX Threads library on J06.07 and later J-series RVUs and H06.18 and later H-series
RVUs only:
c89 -o program program.o -lzsptdll
The SERVERCLASS_SEND_ jacket routines are included in the Standard POSIX Threads library
that can be bound to an application requiring them:
c89 -o program program.o -lzsptsrl (TNS/R programs)
c89 -o program program.o -lzsptdll (TNS/E programs)

SERVERCLASS_DIALOG Jacket Routines


The Pathsend SERVERCLASS_DIALOG jacket routines are used to:
• Establish a dialog with a server instance in a Pathway server class
• Send and receive messages within the dialog
• Abort or end the dialog
The Context-Sensitive Pathway requester can be written using the thread-aware
SERVERCLASS_DIALOG jacket routines to communicate with a server instance in the Pathway
server class. The Pathway requester initiates the dialog using
SPT_SERVERCLASS_DIALOG_BEGIN_() routine and sends the first message of the dialog. This
thread-aware jacket routine returns the dialog ID that is used in subsequent operations to
communicate with the Pathway server. The Pathway requester can invoke multiple sends using
SPT_SERVERCLASS_DIALOG_SEND_() within the dialog to send data to the server for

Jacket Routines 281


processing. If the requester encounters an error while sending the data, the requester can abort
the dialog using the SPT_SERVERCLASS_DIALOG_ABORT_() routine.
The Pathway requester can use multiple SPT_SERVERCLASS_DIALOG_SEND_() calls to have
all requests serviced by the same server and all operations performed in a single context.
If the requester encounters Pathsend errors during the server class operation, the requester can
call SPT_SERVERCLASS_SEND_INFO_() to obtain information about the Pathsend error and
file-system error.
Either the requester or the server can abort the dialog, but only the server can end it. The server
ends the dialog by returning file-system error 0 (FEOK). The requester then calls
SPT_SERVERCLASS_DIALOG_END_() to clean up resources after the server has ended the
dialog. To abort the dialog, the requester calls SPT_SERVERCLASS_DIALOG_ABORT_().
The SERVERCLASS_DIALOG_ jacket routines are included in the Standard POSIX Threads
library, which can be bound to an application requiring the routines:
c89 -o program program.o -lzsptsrl (TNS/R programs)
c89 -o program program.o -lzsptdll (TNS/E programs)

TMF Transaction Jacket Routines


The following Transaction Management Facility (TMF) transaction jacket routines invoke the
TMF calls and manage the multiple concurrent transactions rooted in a process:
SPT_ABORTTRANSACTION()
SPT_BEGINTRANSACTION()
SPT_ENDTRANSACTION()
SPT_RESUMETRANSACTION()
The syntax and semantics of these function calls are the same as those of the similarly named
TMF calls.
When using the TMF transaction jacket routines:
• The transaction_tag parameter of the SPT_BEGINTRANSACTION() function is required.
• Each thread can have at most one current transaction. The system RESUMETRANSACTION
procedure is automatically called during thread dispatch to maintain the correct transaction
context.
• Each transaction is initially associated with only the thread that created it by calling the
SPT_BEGINTRANSACTION() function.
• Another thread can be associated with a specific transaction by calling the
SPT_RESUMETRANSACTION() function and specifying the transaction_tag value
returned by the initial SPT_BEGINTRANSACTION() function call.
• If a thread is created, it does not inherit its parent's transaction; the created thread's transaction
context is nil.
• If a thread terminates or is destroyed while it has an active transaction, that transaction is
then inaccessible from the process. If cancellation is a possibility, use exception handlers for
pthread_cancel_e. Alternatively, use the pthread_cleanup_push() and
pthread_cleanup_pop() functions to ensure that the transaction is terminated if the
thread exits or is cancelled.
• If a transaction is aborted by either an operator, network partition, or another process, an
error is reported when the initiating thread attempts to operate on the transaction.
• A process using the TMF transaction jacket routines must not call:
— The TMF procedures BEGINTRANSACTION, ABORTTRANSACTION,
ENDTRANSACTION, or RESUMETRANSACTION
— The SQL/MP BEGIN-WORK and COMMIT-WORK procedures
• A process can perform up to the default of 100 concurrent transactions, with up to 1000
transactions maximum declared using the spt_setTMFConcurrentTransaction()

282 Using the Standard POSIX Threads Library


function. If the maximum is exceeded, a call to the
spt_setTMFConcurrentTransaction() function fails, returning error number 83 (too
many transactions).

Reference Pages for Thread Functions


For full syntax and usage information about the Standard POSIX Threads functions, see the Open
System Services System Calls Reference Manual.
Full reference and syntax information for the SERVERCLASS_SEND and TMF transaction
demarcation jacket routines is available online in the OSS environment using the man command.
Standard POSIX Threads does not support every thread function listed in the reference pages;
for example, the various pthread_rwlock, pthread_nsg, pthread_rad, and pthread_exc
functions are not part of the Standard. Many of the supported functions are changed as well.
Differences between the previous standard and the current standard are described in the Open
System Services Porting Guide.
All the thread functions are listed in Appendix A: Documented OSS Functions (page 389) and
Appendix C (page 451).

Threaded Application Examples


The following example application creates a threaded time-of-day server socket that listens for
connections and upon connection, creates a thread to handle the connection.

Reference Pages for Thread Functions 283


Example 11-5 Threaded Time-of-Day Server Socket
/* Threaded time-of day server socket. */
/* If compiled for TNS/R, specify the ZSPTSRL compilation option. */
/* If compiled for TNS/E, specify the ZSPTDLL, the standard POSIX threads */
/* shared run-time library. */

#include <assert.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>

/*
Defines thread-aware functions calls to the threads package:
*/

#define SPT_THREAD_AWARE
#include <spthread.h>

/*
Defines a short macro to convert file descriptors to non-blocking (T1248’s
thread-aware functions are thread-aware only if the file descriptor is non-
blocking):
*/

#define fd_make_nonblock(fd) \
assert(fcntl(fd,F_SETFL,fcntl(fd,F_GETFL)|O_NONBLOCK) != -1)

/*
Defines the port the server will run on:
*/

#define SERVER_PORT 3000

/*
Shows the worker thread that is created after each accept:
*/

void *worker_thread(void* sock_fd)


{

char buffer[1024];
time_t now;

time(&now);
strcpy(buffer, ctime(&now));
send(*(int *)sock_fd, &buffer, strlen(buffer), 0);
close(*(int *)sock_fd);
return NULL;
}

int main(int argc, char *argv[])

{
int inet_addr_port = SERVER_PORT;
int sock=-1,accept_fd=-1;
size_t size;
struct sockaddr_in servaddr, accept_addr;

/*
Defines one pthread_t per request we intend to handle:
*/

pthread_t my_thread;
pthread_attr_t my_attr;

/*
Turns on concurrency:
*/

284 Using the Standard POSIX Threads Library


if(pthread_setconcurrency(1))
{
perror("pthread_setconcurrency");
exit(-1);
}

/*
Initializes attribute:
*/

if(pthread_attr_init(&my_attr))
{
perror("pthread_attr_init");
exit(-1);
}

/*
Sets detach Attribute:
*/

if(pthread_attr_setdetachstate(&my_attr,PTHREAD_CREATE_DETACHED))
{
perror("pthread_attr_setdetachstate");
exit(-1);
}

/*
Creates socket:
*/

if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)


{
perror("Socket Error");
exit(-1);
}

/*
Sets up Bind:
*/

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(inet_addr_port);

if (bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)

{
perror("Bind Error");
exit(-1);
}

fd_make_nonblock(sock);

/*
Sets socket to listen:
*/

if (listen(sock, 1) < 0)
{
perror("Listen Error");
exit(-1);
}

/*
Starts server:
*/

while(1)

{
bzero(&accept_addr, sizeof(accept_addr));

Threaded Application Examples 285


accept_fd = accept(sock, NULL, NULL);
if (accept_fd < 0)
{
perror("Accept Error");
exit(-1);
}

/*
Dispatches a thread to handle service request:
*/

if(pthread_create(&my_thread,&my_attr,&worker_thread,&accept_fd)
{
perror("pthread_create");
exit(-1);
}
} /* while */
}/* main */

Example 11-6 (page 287) also creates a threaded time-of-day server socket, but using $RECEIVE.

286 Using the Standard POSIX Threads Library


Example 11-6 Threaded Time-of-Day Server Socket Using $RECEIVE
#include <errno.h>
#include <assert.h>
#include <cextdecs.h(FILE_OPEN_,READX,FILE_CLOSE_,WRITEX,FILE_GETINFO_)>
#include <cextdecs.h(FILE_GETRECEIVEINFO_)>
#include <cextdecs.h(REPLYX)>
#include <cextdecs.h(READUPDATEX)>

#define SPT_THREAD_AWARE
/*
Must come after cextdecs.h:
*/
#include <spthread.h>

void * server_thread(void* target)


{
char buffer[1024];
time_t now;
int error;

time(&now);
strcpy(buffer, ctime(&now));

/*
A compiler warning will occur regarding the next line, which is OK:
*/

error = spt_REPLYX(buffer, (short) strlen(buffer), NULL,


(short)target, 0);

fprintf(stderr,"server_thread: spt_REPLYX: error: %d\n",error);


fflush(stderr);
return NULL;
}

int main(void)
{

pthread_t my_thread;
pthread_attr_t my_attr;
char *filename = "$RECEIVE";
char buffer[1024];
long bytesread, error;
short receive_info[17];
short dialog_info;
short target;
short filenum;

/*
Sets concurency level:
*/

if(pthread_setconcurrency(1))
{
perror("pthread_setconcurency");
exit(-1);
}

/*
Initializes attribute:
*/

if(pthread_attr_init(&my_attr))

Threaded Application Examples 287


{
perror("pthread_attr_init");
exit(-1);
}

/*
Sets detach state for thread attribute:
*/

if(pthread_attr_setdetachstate(&my_attr,PTHREAD_CREATE_DETACHED)!=0)

{
perror("pthread_attr_setdetachstate");
exit(-1);
}

error = FILE_OPEN_(filename, (short)strlen(filename), &filenum,


0, , 1, 10, 1);
fprintf(stderr,"main: FILE_OPEN_: error: %d\n",error);
assert(error == 0);
error = spt_INITRECEIVE(filenum, 10);
fprintf(stderr,"main: spt_initReceive: error: %d\n",error);
fflush(stderr);
assert(error == 0);

while (1)

{
error = spt_RECEIVEREAD(filenum, buffer, (short)sizeof(buffer),
&bytesread, -1, receive_info, &dialog_info);
fprintf(stderr,"main_thread: spt_RECEIVEREAD: error: %d\n",error);

target = receive_info[2];

if(pthread_create(&my_thread, &my_attr, &server_thread, 0


(void *)target))

{
perror("pthread_create");
exit(-1);
}

} /* while */
} /* main */

Thread-Aware and Nonblocking OSS Functions


If a function must wait for an I/O operation to complete, the function blocks its caller (either a
thread or a process) from continuing until the I/O operation completes. A function that blocks
all threads while it waits for I/O to complete is a process-blocking function. Process-blocking
functions are not thread aware. If a thread calls a process-blocking function, the calling thread
and all the other threads in the process are prevented from continuing until the I/O operation is
complete and the function returns a status indication. Standard OSS I/O library functions are not
thread-aware.
In contrast to a process-blocking function, a thread-aware function blocks only the thread calling
that function, instead of blocking all threads in the process. The other threads in the process can
continue doing work while the calling thread waits for I/O to complete. A thread-aware function
is sometimes called a thread-blocking function, because it blocks only the calling thread.
Sometimes it is not enough for a function to be thread-aware. There can be times when you do
not want even the calling thread to wait for I/O to complete. Instead, you want the function to

288 Using the Standard POSIX Threads Library


either succeed immediately or to fail immediately. Functions that do not block the calling thread
or the other threads in the process are nonblocking functions. Nonblocking I/O functions are
sometimes called asynchronous I/O functions.
The behavior of an OSS I/O library function can vary according to these factors:
• Whether the file descriptor is for a regular file or a non-regular file.
• Whether the function was designed to be process-blocking, thread-aware (thread-blocking),
or nonblocking for that type of file.
• Whether the file descriptor passed to the function is nonblocking. A file descriptor is
nonblocking when one of these conditions is true:
— The file descriptor has the O_NONBLOCK flag set.
— The file descriptor has been set to non-blocking mode by setting the argument to the
request parameter to F_SETFL when calling the fcntl() function.

NOTE: In this section, thread-aware and nonblocking thread-aware functions are listed
explicitly. However, instead of calling these functions directly, HP recommends that you
use preprocessor directives when compiling your application. See “Preprocessor Directives
Automatically Map Standard System Calls to Thread-Aware or Nonblocking Thread-Aware
System Calls” (page 293).

Regular Files
For regular files, the spt_*z() set of functions are thread-aware. The spt_*z() set of functions
block the calling thread but allow the other threads to run, whether or not the file descriptor is
nonblocking. These functions never return the errors EAGAIN, EINPROGRESS, or
EWOULDBLOCK for regular files, so there are no nonblocking thread-aware functions for regular
files.
In contrast, the spt_*() and spt_*x() sets of functions are not thread-aware for regular files.
For regular files, these functions are always process-blocking.
The spt_*z() set of functions are supported on systems running J06.04 and later J-series RVUs
and H06.15 and later H-series RVUs, and are listed in the rightmost column, labeled Thread-Aware
(Regular Files) and Nonblocking Thread-Aware (Non-Regular Files) Functions, of Table 11-6
(page 292).
In addition to the functions listed in Table 11-6 (page 292), these additional functions, athough
not thread-aware, support the use of spt_*z() set of thread-aware functions by serializing file
operations on an open file:
spt_fstat64z()
spt_fstatz()
spt_lseek64z()
spt_lseekz()

Serialization of File Operations On an Open File


The version of the Standard POSIX Threads library that supports the spt_*z() set of functions
serializes file operations on an open file. If a thread calls one of the spt_*z() set of functions
to access a file that already has a file operation in progress by a different thread, the calling thread
is blocked until the prior file operation is complete. For example:
1. Thread A calls spt_readz() to read the open file MyDataFile. The file does not have an
operation in progress, so thread A starts reading the file.
2. Thread B calls spt_writez() to write to the same open file MyDataFile. Because the
read operation started by thread A is still in progress, thread B is blocked and must wait for
thread A’s read operation to complete.

Thread-Aware and Nonblocking OSS Functions 289


Non-Regular Files
For non-regular files, there are functions that can provide thread-aware behavior or both
nonblocking and thread-aware behavior:
• The spt_*() set of functions are thread aware only if the file descriptor is nonblocking.
The behavior of these functions depend on how the file descriptor O_NONBLOCK flag is
set:
— If O_NONBLOCK (fd flag) is set, then the call will not block the other calling threads.
It might block the calling thread depending on the function call.
— If O_NONBLOCK (fd flag) is not set, then most functions block the entire process. Some
functions, like spt_fd_read_ready() and spt_fd_write_ready(), will block
only the calling thread.
The spt_*() set of functions are listed in the Thread-Aware Functions (Non-Regular Files
Only) column of Table 11-6 (page 292)
• The spt_*x() set of functions are thread-aware whether or not the file descriptor is
nonblocking. If the O_NONBLOCK flag is set, these functions are also nonblocking: they
do not block the calling thread or the other threads, and they return one of these errors to
the application: EAGAIN, EINPROGRESS, or EWOULDBLOCK. Otherwise, these functions
block the calling thread but allow other threads to run. These functions remove the need for
the application to explicitly set the O_NONBLOCK flag of the file descriptor to enable
thread-aware behavior.
The spt_*x() set of functions are are available on systems running J06.03 and later J-series
RVUs, H06.05 and later H-series RVUs, and G06.28 and later G-series RVUs, and are listed
in the Nonblocking Thread-Aware Functions (Non-Regular Files Only) column of Table 11-6
(page 292).
• For non-regular files, the spt_*z() set of functions have the same behavior as spt_*x()
functions. The spt_*z() set of functions are thread-aware whether or not the the
O_NONBLOCK flag of the file descriptor is set. If the O_NONBLOCK flag is set, these
functions are also nonblocking: they do not block the calling thread or the other threads,
and they return one of these errors to the application: EAGAIN, EINPROGRESS, or
EWOULDBLOCK. Otherwise, these functions block the calling thread but allow other threads
to run.
The spt_*z() set of functions are supported on systems running J06.04 and later J-series
RVUs and H06.15 and later H-series RVUs, and are listed in the rightmost column,
Thread-Aware (Regular Files) and Nonblocking Thread-Aware (Non-Regular Files) Functions,
of Table 11-6 (page 292)

290 Using the Standard POSIX Threads Library


Table 11-5 Comparison of spt_*, spt_*x, and spt_*z Functions
Function Set Behavior for Non-Regular Files Behavior for Regular Files

spt_*() File descriptor is nonblocking: Always process-blocking (all threads in the


— Function is thread-aware (other threads process must wait for I/O to complete).
can continue to run)
— Function blocks the calling thread.
File descriptor is not nonblocking: this
function is process-blocking (all threads in
the process must wait for I/O to complete).

spt_*x() Always thead-aware. Can be nonblocking Always process-blocking (all threads in the
for the calling thread. process must wait for I/O to complete)
File descriptor is nonblocking:
— Function is nonblocking thread- aware
(does not block any threads, including
the calling thread): it returns an error
instead of blocking the thread.
File descriptor is not nonblocking:
— Function is thread-aware (other threads
can continue to run)
— Function blocks the calling thread.

spt_*z() Always thead-aware. Can be nonblocking Always thead-aware:1


for the calling thread. — Function is thread-aware (other threads
File descriptor is nonblocking: can continue to run)
— Function is nonblocking thread- aware — Function blocks the calling thread.
(does not block any threads, including I/O operations by multiple threads on the
the calling thread): it returns an error same open file are serialized.
instead of blocking the thread.
File descriptor is not nonblocking:
— Function is thread-aware (other threads
can continue to run)
— Function blocks the calling thread.

1 The functions spt_fstat64z(), spt_fstatz(), spt_lseek64z(), and spt_lseek64z() are not thread
aware but support the spt_*z() thread-aware functions for regular files by serializing file operations on an
open file.

Equivalent System, Thread-Aware, and Nonblocking Thread-Aware Functions


Table 11-6 lists standard functions that have equivalent thread-aware functions. For example:
• read() is a process-blocking function for both regular files and for non-regular files.
• spt_read() is a thread-aware function with this behavior:
— For non-regular files, the file descriptor must be nonblocking for this function to be
thread-aware. This function blocks the calling thread, but allows other threads to run.
— For regular files, this function blocks the entire process.
• spt_readx() is a thread-aware function with this behavior:
— For non-regular files, this function does not require the file descriptor to be nonblocking
for this function to be thread-aware. If the file description is nonblocking, this function
does not block the calling thread, and returns one of these errors to the application:
EAGAIN, EINPROGRESS, or EWOULDBLOCK. Otherwise, this function blocks the
calling thread but allows other threads to run.
— For regular files, this function blocks the entire process.
• spt_readz() is a thread-aware function with this behavior:
— For non-regular files, this function does not require the file descriptor to be nonblocking
for this function to be thread-aware. If the file descriptor is nonblocking, this function

Thread-Aware and Nonblocking OSS Functions 291


does not block the calling thread, and returns one of these errors to the application:
EAGAIN, EINPROGRESS, or EWOULDBLOCK. Otherwise, this function blocks the
calling thread but allows other threads to run. (This is the same behavior as the
spt_readx()function.)
— For regular files, this function blocks the calling thread but allows other threads to run.
This function does not require the file descriptor to be nonblocking for this function to
be thread-aware.

NOTE: To determine which RVUs support an OSS function, see Appendix A (page 389)
Table 11-6 System and Equivalent Thread-Aware Functions
Standard (Process-Blocking) Thread-Aware Functions Nonblocking Thread-Aware Thread-Aware (Regular Files)
OSS Functions (Non-Regular Files Only) Functions (Non-Regular Files and Nonblocking
Only) Thread-Aware (Non-Regular
Files) Functions

accept() spt_accept() spt_acceptx()

— spt_alarm() —

close() spt_close() spt_closex() spt_closez()

connect() spt_connect() spt_connectx()

dup2() — spt_dup2x()

fclose() spt_fclose() spt_fclosex()

fcntl() spt_fcntl() spt_fcntlx() spt_fcntlz()

fflush() spt_fflush() spt_fflushx()

fgetc() spt_fgetc() spt_fgetcx()

fgets() spt_fgets() spt_fgetsx()

fgetwc() spt_getwc() spt_getwcx()

fprintf() spt_fprintf() spt_fprintfx()

fputc() spt_fputc() spt_fputcx()

fputs() spt_fputs() spt_fputsx()

fputwc() spt_fputwc() spt_fputwcx()

fread() spt_fread() spt_freadx()

fsync() — — spt_fsyncz()

ftruncate() — — spt_ftruncatez()

ftruncate64() — — spt_ftruncate64z()

fwrite() spt_fwrite() spt_fwritex()

getc() spt_getc() spt_getcx()

getchar() spt_getchar() spt_getcharx()

gets() spt_gets() spt_getsx()

getw() spt_getw() spt_getwx()

getwc() spt_getwc() spt_getwcx()

getwchar() spt_getwchar() spt_getwcharx()

printf() spt_printf() spt_printfx()

292 Using the Standard POSIX Threads Library


Table 11-6 System and Equivalent Thread-Aware Functions (continued)
Standard (Process-Blocking) Thread-Aware Functions Nonblocking Thread-Aware Thread-Aware (Regular Files)
OSS Functions (Non-Regular Files Only) Functions (Non-Regular Files and Nonblocking
Only) Thread-Aware (Non-Regular
Files) Functions

putc() spt_putc() spt_putcx()

putchar() spt_putchar() spt_putcharx()

puts() spt_puts() spt_putsx()

putw() spt_putw() spt_putwx()

putwc() spt_putwc() spt_putwcx()

putwchar() spt_putwchar() spt_putwcharx()

read() spt_read() spt_readx() spt_readz()

readv() spt_readv() spt_readvx() spt_readvz()

recv() spt_recv() spt_recvx()

recvfrom() spt_recvfrom() spt_recvfromx()

recvmsg() spt_recvmsg() spt_recvmsgx()

select() spt_select() —
spt_select_single_np()

send() spt_send() spt_sendx()

sento() spt_sento() spt_sento()

sendmsg() spt_sendmsg() spt_sendmsgx()

sigaction() spt_sigaction() —

— spt_signal() —

sigpending() spt_sigpending() —

sigsuspend() spt_sigsuspend() —

wait() spt_wait() —

sleep() spt_sleep() —

— spt_usleep() —

system() spt_system() —

vfprintf() spt_vfprintf() spt_vfprintfx()

vprintf() spt_vprintf() spt_vprintfx()

waitpid() spt_waitpid() —

write() spt_write() spt_writex() spt_writez()

writev() spt_writev() spt_writevx() spt_writevz()

Preprocessor Directives Automatically Map Standard System Calls to Thread-Aware


or Nonblocking Thread-Aware System Calls
When you use preprocessor directives when compiling the application, standard system calls
are automatically mapped to the appropriate Standard POSIX Thread system call, eliminating
the need to explicitly call spt_*(), spt_*x(), or spt_*z() functions. Using preprocessor

Thread-Aware and Nonblocking OSS Functions 293


directives is preferred to using explicit calls to thread-aware or nonblocking thread-aware
functions.
HP highly recommends using only one of these preprocessor directive sets in an application:
#define SPT_THREAD_AWARE
#define SPT_THREAD_AWARE_PRAGMA
#define SPT_THREAD_AWARE_NONBLOCKING
#define SPT_THREAD_AWARE_PRAGMA_NONBLOCKING
#define SPT_THREAD_AWARE_XNONBLOCKING
#define SPT_THREAD_AWARE_PRAGMA_XNONBLOCKING
Mixing modules compiled with different preprocessor directive sets or compiled without
preprocessor directives related to thread-aware behavior in an application might cause unexpected
results. For more information, see “The spt_*z() Set of Functions Must Be Used Together”
(page 296).
This table summarizes the behaviors for each of these preprocessor directives for non-regular
and for regular files:

Preprocessor Directive Behavior for Non-Regular File Behavior for Regular File
Descriptors Descriptors

#define SPT_THREAD_AWARE or Thread-aware operations for Process-blocking operations


#define SPT_THREAD_AWARE_PRAGMA nonblocking file descriptors for all file descriptors
Process-blocking operations
for blocking file descriptors

#define SPT_THREAD_AWARE_NONBLOCK or Nonblocking thread-aware Process-blocking operations


#define operations for nonblocking for all file descriptors
SPT_THREAD_AWARE_PRAGMA_NONBLOCK file descriptors
Thread-aware operations for
#define SPT_THREAD_AWARE_XNONBLOCK or blocking file descriptors Thread-aware operations for
#define all file descriptors
SPT_THREAD_AWARE_PRAGMA_XNONBLOCK

Defining Thread-Aware Functions for Non-Regular Files


For C applications, a macro to map interface() to spt_interface() is available when you
use the #define SPT_THREAD_AWARE preprocessor directive before including spthread.h
or when you use an equivalent compiler command option to compile the application.
For C++ applications, an alias to map interface() to spt_interface() is available when
you use the #define SPT_THREAD_AWARE_PRAGMA preprocessor directive before including
spthread.h or when you use an equivalent compiler command option to compile the application.
The following example illustrates using the SPT_THREAD_AWARE_PRAGMA define:
#define SPT_THREAD_AWARE_PRAGMA
#include <iostream.h> nolist
#include <spthread.h> nolist
int main()
...
For information about including a preprocessor directive in an application by specifying the
directive in a compiler command option, see the c89(1) or the c99(1) reference page online
or in the Open System Services Shell and Utilities Reference Manual.
Applications can explicitly call the functions listed in the Thread-Aware Functions (Non-Regular
Files Only) column of Table 11-6 (page 292) without setting any defines before including the
spthread.h header file.

294 Using the Standard POSIX Threads Library


Defining Nonblocking Thread-Aware Functions for Non-Regular Files
The spt_*x() set of nonblocking thread-aware functions for non-regular files are available on
systems running J-series RVUs, H06.05 and later H-series RVUs, and G06.28 and later G-series
RVUs.
For C applications, a macro to map interface() to spt_interfacex() is available when
you use the #define SPT_THREAD_AWARE_NONBLOCK preprocessor directive before including
spthread.h or when you use an equivalent compiler command option to compile the application.
For C++ applications, an alias to map interface() to spt_interfacex() is available when
you use the #define SPT_THREAD_AWARE_PRAGMA_NONBLOCK preprocessor directive before
including spthread.h or when you use an equivalent compiler command option to compile
the application.
This example illustrates using the SPT_THREAD_AWARE_NONBLOCK preprocessor directive in
an application:
#define SPT_THREAD_AWARE_NONBLOCK
#include <spthread.h>
main()
...
For information about including a preprocessor directive in an application by specifying the
directive in a compiler command option, see thec89(1) or the c99(1) reference page online
or in the Open System Services Shell and Utilities Reference Manual.
For non-regular files:
• The spt_*z() set functions have the same behavior as the spt_*x() set of functions.
• For C applications, the behavior of the function is the same whether you use the #define
SPT_THREAD_AWARE_NONBLOCK or the #define SPT_THREAD_AWARE_XNONBLOCK
preprocessor directive.
• For C++ applications, the behavior of the function is the same whether you use the #define
SPT_THREAD_AWARE_PRAGMA_NONBLOCK or the #define
SPT_THREAD_AWARE_PRAGMA_XNONBLOCK preprocessor directive.
The spt_*z() set of nonblocking thread-aware functions for non-regular files are available on
systems running running J06.04 and later J-series RVUs and H06.15 and later H-series RVUs. To
use these functions see “Defining Thread-Aware Functions for Regular Files” (page 295).
Applications can explicitly call the functions listed in the Nonblocking Thread-Aware Functions
(Non-Regular Files Only) column of Table 11-6 (page 292) without setting any defines before
including the spthread.h header file.

Defining Thread-Aware Functions for Regular Files


Thread-aware functions for regular files are available on systems running J06.04 and later J-series
RVUs and H06.15 and later H-series RVUs. These functions are also nonblocking thread-aware
functions for non-regular files.
For C applications, a macro to map interface() to spt_interfacez() is available when
you use the #define SPT_THREAD_AWARE_XNONBLOCK preprocessor directive before including
spthread.h or when you use an equivalent compiler command option to compile the application.
For C++ applications, an alias to map interface() to spt_interfacez() is available when
you use the #define SPT_THREAD_AWARE_PRAGMA_XNONBLOCK preprocessor directive before
including spthread.h or when you use an equivalent compiler command option to compile
the application.

Thread-Aware and Nonblocking OSS Functions 295


NOTE: When you use the #define SPT_THREAD_AWARE_XNONBLOCK or #define
SPT_THREAD_AWARE_PRAGMA_XNONBLOCK, if a function has a corresponding spt_*x()
function but not a corresponding spt_*z() function, the function is mapped to the corresponding
spt_*x() function.
The following example illustrates using the SPT_THREAD_AWARE_XNONBLOCK define:
#define SPT_THREAD_AWARE_XNONBLOCK
#include<spthread.h>
main()
...
For information about including a preprocessor directive in an application by specifying the
directive in a compiler command option, see the c89(1) or the c99(1) reference page online
or in the Open System Services Shell and Utilities Reference Manual.
Applications can explicitly call the functions listed in the rightmost column of Table 11-6 (page 292)
without setting any defines before including the spthread.h header file.

The spt_*z() Set of Functions Must Be Used Together


The Standard POSIX Threads library serializes I/O functions on open files only for the spt_*z()
set of functions. Therefore, if an spt_*z() function exists for a needed standard function, you
should use the spt_*z() function instead of using spt_*x(), spt_*(), or unmapped standard
functions directly.
For example, if you compile one module in a way that maps functions to corresponding functions
in the spt_*z() set of functions and you compile another module in a way that maps functions
to corresponding functions in the spt_*() or spt_*x() set of functions, you can get errors
when the two modules operate on the same open file:
1. Thread A calls spt_readz() to read the open file MyDataFile. The file does not have an
operation in progress, so thread A starts reading the file.
2. Thread B calls read() to read to the same open file MyDataFile, but the module was not
compiled using the SPT_THREAD_AWARE_XNONBLOCK preprocessor directive, so the
call to read() was automatically mapped to spt_read(). Because the spt_read()
function does not support serialization, spt_read() attempts to do the read and fails,
returning the error EALREADY. The EALREADY error indicates that an operation is already
in progress.
In addition, using modules that were not compiled with any of the preprocessor directives with
modules that have been compiled using the SPT_THREAD_AWARE_XNONBLOCK or
SPT_THREAD_AWARE_PRAGMA_XNONBLOCK preprocessor directives can cause unexpected
results. For example, compiling a module so that it calls the unmapped standard function close()
directly, instead of the mapped function spt_closez(), might leave a thread with a pending
thread-aware regular file request suspended with no mechanism available to reschedule it for
execution.

Using Thread-Aware Functions


Example 11-7 (page 297) shows using thread-aware functions with a file stream. If the stream is
to be used with a nonblocking thread-aware function, it is not necessary to set the O_NONBLOCK
flag.

296 Using the Standard POSIX Threads Library


Example 11-7 File Stream Thread-Aware Function Usage
...
fs = fopen(path, mode);
fd = fileno(fs);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
...
// Call thread-aware functions.
...
fclose(fs);
...

Example 11-8 (page 297) shows opening a file descriptor for use with a thread-aware function. If
the file descriptor is to be used with a nonblocking thread-aware function, it is not necessary to
set the O_NONBLOCK flag.

Example 11-8 File Descriptor Thread-Aware Function Usage


...
filedes = open(path, oflag, mode | O_NONBLOCK);
...
// Call thread-aware functions.
...
close(filedes);
...

Example 11-9 (page 297) shows preparing an open file descriptor for use with a thread-aware
function. If the file descriptor is to be used with a nonblocking thread-aware function, it is not
necessary to set the O_NONBLOCK flag.

Example 11-9 Open File Descriptor Thread-Aware Function Usage


...
fcntl(filedes, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
...
// Call thread-aware functions.
...

Example 11-10 (page 299) is a multithreaded program that performs I/O on multiple OSS regular
files using the nonblocking thread-aware functions and guardian nowaited I/O.

Thread-Aware and Nonblocking OSS Functions 297


NOTE: For systems running J06.04 or later J-series RVUs or H06.15 or later H-series RVUs,
using Guardian nowait I/O to perform I/O operations that block only the calling thread is not
necessary if you change the define used in the sample program in Example 11-10 (page 299) from
SPT_THREAD_AWARE_NONBLOCK to SPT_THREAD_AWARE_XNONBLOCK. See
Example 11-11 (page 309).

298 Using the Standard POSIX Threads Library


Example 11-10 Pthreads Nonblocking Disk File I/O (SPT_THREAD_AWARE_NONBLOCK version)
/*
* sptdio.c - SPThreads Diskfile IO Example Program
*
* This Pthreads program demonstrates a multithreaded program that
* can perform I/O on multiple OSS regular files (diskfiles) using
* non-blocking OSS I/O and Guardian nowaited I/O.
*
* Note that OSS I/O on regular files is serialized,
* even though the OSS non-blocking
* interface is used. This is standard Unix behavior.
*
* The following threads can be created by this program:
* - An OSS read thread which uses uses OSS I/O to completely
* read a regular file.
* - An OSS write thread which uses uses OSS I/O to write
* 1Mb of data to the regular file.
* - A Guardian read thread which uses Guardian nowait I/O to
* completely read a regular file.
* - A Guardian write thread which uses Guardian nowait I/O
* to write 1Mb of data to the regular file.
*
* USAGE SYNTAX:
*
* sptdio [-r <OSS-file>] [-w <OSS-file>] [-R <OSS-file>] [-W <OSS-file>]
*
* FLAGS
* -r <OSS-file> Create a thread that uses OSS I/O to
* completely read the given OSS diskfile.
* -w <OSS-file> Create a thread that uses OSS I/O to write the
* given OSS diskfile. 1Mb of data is written to the file.
* -R <OSS-file> Create a thread that uses Guardian nowait I/O to
* completely read the given OSS diskfile.
* -W <OSS-file> Create a thread that uses Guardian nowait I/O to write
* the given OSS diskfile. 1Mb of data is written to
* the file.
*
* EXAMPLE USAGE:
*
* /home/user: run sptdio -r /tmp/r1 -w /tmp/w1 -R /tmp/r2 -W /tmp/w2
*
* ==> All threads created...
* ==> OSS_write_thread() wrote 1048576 bytes to file /tmp/w1
* ==> OSS_read_thread() read 1581888 bytes from file /tmp/r1
* ==> Grd_WRITE_thread() wrote 1048576 bytes to file /tmp/w2
* ==> Grd_READ_thread() read 1581888 bytes from file /tmp/r2
*
* OSS BUILD INSTRUCTIONS:
*
* c89 sptdio.c -o sptdio -Wextensions -Wsystype=oss -g -D_XOPEN_SOURCE=1 \
* -lZSPTDLL
*/

#include <limits.h>
#include <stdlib.h>
/* Use the non-blocking version of the thread aware library */
#define SPT_THREAD_AWARE_NONBLOCK
#include <spthread.h>

#include <tal.h>
#include <cextdecs.h(CANCELREQ, FILE_CLOSE_, FILE_GETINFO_, FILE_OPEN_, \ READX, WRITEX)>

/********************/
/* LITERALS/DEFINES */
/********************/

/* the maximum number of I/O threads created by this program */


#define MAX_THREADS 4

/* concurreny level value passed to pthread_setconcurrency() */


/* the value of 100000 sets the minimum scheduled quantum to 0.000001 seconds. */
#define CONCURRENCY_LEVEL 100000

/* I/O size used by all threads */


#define IOSIZE 8192

/* size of files that are written - 1Mb */


#define WRITE_FILESIZE 1048576

Thread-Aware and Nonblocking OSS Functions 299


/*
*-----------------------------------------------------------------
* OSS_read_thread --
*
* Description:
*
* This thread reads an OSS file using OSS I/O.
*
* Note that OSS I/O on regular files is serialized and only one OSS I/O
* per open can occur at a given time. Even though we use the thread-aware
* library,
* the entire program blocks while the OSS read() function performs the I/O.
*
* Results:
* none.
*
*------------------------------------------------------------------
*/

void *OSS_read_thread(void *OSS_read_file)


{
int fd;
int nbytes;
char *iobuf;
int ret;
long long filesize = 0;

/*****************************************************************/
/* prepare I/O buffer (page aligned, paged into physical memory) */
/*****************************************************************/

if ((iobuf = malloc(IOSIZE)) == NULL)


{
printf("*** ERROR in OSS_read_thread: unable to allocate I/O buffer ***\n");
exit(0);
}
memset(iobuf, 0, IOSIZE);

/*********************/
/* open the OSS file */
/*********************/

if ((fd = open(OSS_read_file, O_RDONLY | O_NONBLOCK)) < 0)


{
printf("*** ERROR in OSS_read_thread: open() of %s failed w/error %d
***\n", OSS_read_file, errno);

exit(0);
}
/**********************************************/
/* read the OSS file in a thread aware manner */
/**********************************************/

while (1)
{
nbytes = read(fd, iobuf, IOSIZE);

if (nbytes < 0)
{
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
{
/**************************************************************************/
/* NOTE that this code does not execute for regular (disk) files, because */
/* read() on a regular file never returns EWOULDBLOCK or EAGAIN */
/**************************************************************************/
ret = spt_fd_read_ready(fd, NULL);
if (ret != 0)
{
printf("*** ERROR in OSS_read_thread: spt_fd_read_ready()
failed w/err %d\n",ret);
exit(0);

300 Using the Standard POSIX Threads Library


}
}
else
{
printf("*** ERROR in OSS_read_thread: read() failed w/error
%d ***\n",errno);
exit(0);
}
}
else if (nbytes == 0) /* EOF */
{
break;
}
else /* read successful */
{
filesize += nbytes;

Thread-Aware and Nonblocking OSS Functions 301


/*********************************************************************/
/* When doing Non-Blocking OSS I/O to diskfiles, it is a good */
/* idea to call sched_yield(), otherwise this thread won't give */
/* up control until the file is completely written. This is because */
/* write() never returns EWOULDBLOCK for a diskfile. */
/*********************************************************************/

sched_yield();
}
} /* while */

close(fd);

printf("==> OSS_read_thread() read %ld bytes from file %s\n", filesize,


OSS_read_file);
return(NULL);
}
/*
*------------------------------------------------------------------------
*
* OSS_write_thread --
*
* Description:
*
* This thread writes an OSS file using OSS I/O.
* Note that OSS I/O on regular files is serialized and only one OSS I/O
* per open can occur at a given time. Even though we use the thread aware
* library,the entire program blocks while the OSS write() function performs
* the I/O.
*
* Results:
* none.
*
*------------------------------------------------------------------------
*/

void *OSS_write_thread(void *OSS_write_file)


{
int fd;
int nbytes;
char *iobuf;
int ret;
long long currsize = 0;

/*****************************************************************/
/* prepare I/O buffer (page aligned, paged into physical memory) */
/*****************************************************************/

if ((iobuf = malloc(IOSIZE)) == NULL)


{
printf("*** ERROR in OSS_write_thread: unable to allocate I/O buffer
***\n");
exit(0);
}
memset(iobuf, 0, IOSIZE);

/*********************/
/* open the OSS file */
/*********************/

if ((fd = open(OSS_write_file, O_WRONLY | O_NONBLOCK | O_CREAT | O_TRUNC, S_IRWXU)) < 0)


{
printf("*** ERROR in OSS_write_thread: open() of %s failed w/error
%d ***\n", OSS_write_file, errno);
exit(0);
}
/***********************************************/
/* write the OSS file in a thread aware manner */
/***********************************************/

while (currsize < WRITE_FILESIZE)


{
nbytes = write(fd, iobuf, IOSIZE);
if (nbytes < 0)
{
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
{

302 Using the Standard POSIX Threads Library


/**************************************************************************/
/* NOTE that this code does not execute for regular (disk) files, because */
/* write() on a regular file never returns EWOULDBLOCK or EAGAIN */
/**************************************************************************/

ret = spt_fd_write_ready(fd, NULL);


if (ret != 0)
{
printf("*** ERROR in OSS_write_thread: spt_fd_write_ready()
failed w/error %d ***\n", ret);
exit(0);
}
}
else
{
printf("*** ERROR in OSS_write_thread: write() failed w/error %d
***\n", errno);
exit(0);
}
}
else /* write successful */
{
currsize += nbytes;
/*********************************************************************/
/* When doing Non-Blocking OSS I/O to diskfiles, it is a good */
/* idea to call sched_yield(), otherwise this thread won't give */
/* up control until the file is completely written. This is because */
/* write() never returns EWOULDBLOCK for a diskfile. */
/*********************************************************************/
sched_yield();
}
} /* while */

close(fd);

printf("==> OSS_write_thread() wrote %d bytes to file %s\n",


WRITE_FILESIZE, OSS_write_file);
return(NULL);
}

/* Grd_READ_thread --
*
* Description:
*
* This thread reads an OSS file using Guardian Nowait I/O.
*
* This function performs Guardian nowait I/O in a thread aware manner,
* such that the entire program never blocks.
* Note however that this thread blocks when it waits for I/O completions.
* Other threads are free to do work while this thread is blocked waiting for
* an I/O completion.
*
* Since Guardian nowait I/O is not serialized, this program can have multiple
* outstanding Guardian I/O requests.
*
* Results:
* none.
*
*------------------------------------------------------------------------
*/

void *Grd_READ_thread(void *Grd_READ_file)


{
short fnum;
long count_read;
char *iobuf;
short err;
spt_error_t spte;
long error;
_cc_status cc;
long tag;
long long filesize = 0;

if ((iobuf = malloc(IOSIZE)) == NULL)


{
printf("*** ERROR in Grd_READ_thread: unable to allocate I/O buffer
***\n");
exit(0);
}
memset(iobuf, 0, IOSIZE);

/*************************************************************************/
/* open the OSS file using FILE_OPEN_() so we can do Guardian nowait I/O */
/*************************************************************************/

err = FILE_OPEN_(Grd_READ_file,
(short) sizeof(Grd_READ_file),
&fnum,
0 /* rd_wr */,
0 /* shared */,
1 /* nowait-depth */ ,

Thread-Aware and Nonblocking OSS Functions 303


0 /* sync depth */,
0x0020 /* options - bit <10> set to allow open of an OSS pathname */);
if (err > 0)
{
printf("*** ERROR in Grd_READ_thread: FILE_OPEN_() of %s failed w/error
%d ***\n", Grd_READ_file, (int) err);
exit(0);
}

/*********************/
/* register the fnum */
/*********************/

spte = spt_regFile(fnum);
if (spte != SPT_SUCCESS)
{
printf("*** ERROR in Grd_READ_thread: spt_regFile() failed w/error %d ***\n",
(int) spte);
exit(0);
}

/***************************************************/
/* Do Guardian nowait I/O in a thread aware manner */
/***************************************************/

while (1)
{
tag = spt_generateTag();

cc = READX(fnum, iobuf, (short) IOSIZE, /* count read */, tag);


if (_status_ne(cc))
{
(void) FILE_GETINFO_(fnum, &err);
printf("*** ERROR in Grd_READ_thread: READX() failed w/error %d
***\n",(int) err);
exit(0);
}
else /* CCE - read successfully initiated */
{
spte = spt_awaitio(fnum, tag, -1, &count_read, &error, NULL);
if (spte != SPT_SUCCESS)
{
(void) CANCELREQ(fnum, tag);
printf("*** ERROR in Grd_READ_thread: spt_awaitio() failed w/error
%d ***\n", (int) error);
exit(0);
}
else if (error == 1) /* EOF */
break;
filesize += count_read;
}
} /* while */

spt_unregFile(fnum);
FILE_CLOSE_(fnum);

printf("==> Grd_READ_thread() read %ld bytes from file %s\n",


filesize, Grd_READ_file);
return(NULL);
}

/*

304 Using the Standard POSIX Threads Library


*------------------------------------------------------------------------
*
* Grd_WRITE_thread --
*
* Description:
*
* This thread writes an OSS file using Guardian Nowait I/O.
*
* This function performs Guardian nowait I/O in a thread aware manner,
* such that the entire program never blocks.
* Note however that this thread blocks when it waits for I/O completions.
* Other threads are free to do work while this thread is blocked waiting
* for an I/O completion.
*
* Since Guardian nowait I/O is not serialized, this program can have
* multiple outstanding Guardian I/O requests.
*
* Results:
* none.
*
*------------------------------------------------------------------------
*/

void *Grd_WRITE_thread(void *Grd_WRITE_file)


{
short fnum;
long count_written;
char *iobuf;
short err;
spt_error_t spte;
long error;
_cc_status cc;
long tag;
off_t currsize = 0;
int fd;

if ((iobuf = malloc(IOSIZE)) == NULL)


{
printf("*** ERROR in Grd_WRITE_thread: unable to allocate I/O buffer
***\n");
exit(0);
}
memset(iobuf, 0, IOSIZE);

/* create the OSS file before opening it with Guardian FILE_OPEN_() */


if ((fd = open(Grd_WRITE_file, O_WRONLY | O_NONBLOCK | O_CREAT | O_TRUNC,
S_IRWXU)) < 0)
{
printf("*** ERROR in Grd_WRITE_thread: open() of %s failed w/error %d
***\n", Grd_WRITE_file, errno);
exit(0);
}
close(fd);

/*****************************************************************************/
/* now open the OSS file using FILE_OPEN_() so we can do Guardian nowait I/O */
/*****************************************************************************/
err = FILE_OPEN_(Grd_WRITE_file,
(short) sizeof(Grd_WRITE_file),
&fnum,
0 /* rd_wr */,
0 /* shared */,
1 /* nowait-depth */ ,
0 /* sync depth - NO CHECKPOINTING */,
0x0020 /* options - bit <10> set to open OSS pathname */);
if (err > 0)
{
printf("*** ERROR in Grd_WRITE_thread: FILE_OPEN_() of % failed w/error
%d ***\n", Grd_WRITE_file, (int) err);
exit(0);
}

Thread-Aware and Nonblocking OSS Functions 305


/* register the fnum */
spte = spt_regFile(fnum);
if (spte != SPT_SUCCESS)
{
printf("*** ERROR in Grd_WRITE_thread: spt_regFile() failed w/error %d
***\n", (int) spte);
exit(0);
}
/***************************************************/
/* Do Guardian nowait I/O in a thread aware manner */
/***************************************************/
while (currsize < WRITE_FILESIZE)
{
tag = spt_generateTag();

cc = WRITEX(fnum, iobuf, (short) IOSIZE, /* count read */, tag);


if (_status_ne(cc))
{
(void) FILE_GETINFO_(fnum, &err);
printf("*** ERROR in Grd_WRITE_thread: WRITEX() failed w/error %d
***\n", (int) err);
exit(0);
}
else /* CCE - write successfully initiated */
{
spte = spt_awaitio(fnum, tag, -1, &count_written, &error, NULL);
if (spte != SPT_SUCCESS)
{
(void) CANCELREQ(fnum, tag);
printf("*** ERROR in Grd_WRITE_thread: spt_awaitio() failed w/error
%d ***\n", (int) error);
exit(0);
}
currsize += count_written;
}
} /* while */

spt_unregFile(fnum);
FILE_CLOSE_(fnum);

printf("==> Grd_WRITE_thread() wrote %d bytes to file %s\n", WRITE_FILESIZE,


Grd_WRITE_file);

return(NULL);
}

306 Using the Standard POSIX Threads Library


int main(int argc, char *argv[])
{
/* the following variables correspond to the OSS filenames specified */
/* as command line parameters to the program */
char OSS_read_filename[PATH_MAX];
char OSS_write_filename[PATH_MAX];
char Grd_READ_filename[PATH_MAX];
char Grd_WRITE_filename[PATH_MAX];
/* total number of threads that have been created */
int nmbr_created_threads = 0;
/* array of handles for each thread created */
pthread_t thread_handle[MAX_THREADS];
int i;

/*************************************/
/* Process command line arguments */
/*************************************/

if (argc > 9)
{
printf("Usage: sptdio [-r <OSS-file>] [-w <OSS-file>] [-R <OSS-file>] [-W
<OSS-file>]\n");
exit(0);
}

/* verify that an even number of command line parameters was specified */


if (((argc - 1) % 2) == 1)
{
printf("Usage: sptdio [-r <OSS-file>] [-w <OSS-file>] [-R <OSS-file>] [-W
<OSS-file>]\n");
exit(0);
}

for (i = 1; i < argc; i = i + 2)


{
if (strcmp(argv[i], "-r") == 0)
{
strcpy(OSS_read_filename, argv[i+1]);
}
else if (strcmp(argv[i], "-w") == 0)
{
strcpy(OSS_write_filename, argv[i+1]);
}
else if (strcmp(argv[i], "-R") == 0)
{
strcpy(Grd_READ_filename, argv[i+1]);
}
else if (strcmp(argv[i], "-W") == 0)
{
strcpy(Grd_WRITE_filename, argv[i+1]);
}
else
{
printf("Usage: sptdio [-r <OSS-file>] [-w <OSS-file>] [-R <OSS-file>]
[-W <OSS-file>]\n");
exit(0);
}
}

/********************************************************/
/* Set the concurrency level for the thread scheduler */
/********************************************************/

pthread_setconcurrency(CONCURRENCY_LEVEL);

/**********************************/
/* Create all of the I/O threads */
/**********************************/

for (i = 1; i < argc; i = i + 2)


{

Thread-Aware and Nonblocking OSS Functions 307


if (strcmp(argv[i], "-r") == 0)
{
pthread_create(&thread_handle[nmbr_created_threads++],
NULL, &OSS_read_thread, OSS_read_filename);
}
else if (strcmp(argv[i], "-w") == 0)
{
pthread_create(&thread_handle[nmbr_created_threads++],
NULL, &OSS_write_thread, OSS_write_filename);
}
else if (strcmp(argv[i], "-R") == 0)
{
pthread_create(&thread_handle[nmbr_created_threads++],
NULL, &Grd_READ_thread, Grd_READ_filename);
}
else if (strcmp(argv[i], "-W") == 0)
{
pthread_create(&thread_handle[nmbr_created_threads++],
NULL, &Grd_WRITE_thread, Grd_WRITE_filename);
}
}

printf("\n==> All threads created...\n");

/************************************************************************/
/* wait for the threads to complete - this is where control is passed */
/* to the threads */
/************************************************************************/

for (i = 0; i < nmbr_created_threads; ++i)


{
pthread_join(thread_handle[i], NULL);
}

} /* main() */
Example 11-11 (page 309) is a multithreaded program similar to Example 11-10 (page 299) except
that performs I/O on multiple OSS regular files using the thread-aware functions that are available
when you use the define SPT_THREAD_AWARE_XNONBLOCK (available on systems running J06.04
and later J-series RVUs and H06.15 and later H-series RVUs). With these functions, you do not
have to use Guardian functions to allow other threads to continue to work while another thread
waits for I/O to complete on an open file.

308 Using the Standard POSIX Threads Library


Example 11-11 Pthreads Thread-Aware Disk File I/O Using SPT_THREAD_AWARE_XNONBLOCK
/*
* sptdio.c - SPThreads Diskfile IO Example Program
*
* This Pthreads program demonstrates a multithreaded program that
* can perform I/O on multiple OSS regular files (diskfiles) using
* thread-aware OSS I/O functions available on systems running
* J06.04 and later J-series RVUs or H06.15 and later H-series RVUs.
*
* Note that OSS I/O on regular files is serialized.
*
* The following threads can be created by this program:
* - An OSS read thread which uses uses OSS I/O to completely
* read a regular file.
* - An OSS write thread which uses uses OSS I/O to write
* 1Mb of data to the regular file.
*
* USAGE SYNTAX:
*
* sptdio [-r <OSS-file>] [-w <OSS-file>]
*
* FLAGS
* -r <OSS-file> Create a thread that uses OSS I/O to
* completely read the given OSS diskfile.
* -w <OSS-file> Create a thread that uses OSS I/O to write the
* given OSS diskfile. 1Mb of data is written to the file.
*
* EXAMPLE USAGE:
*
* /home/user: run sptdio -r /tmp/r1 -w /tmp/w1
*
* ==> All threads created...
* ==> OSS_write_thread() wrote 1048576 bytes to file /tmp/w1
* ==> OSS_read_thread() read 1581888 bytes from file /tmp/r1
*
* OSS BUILD INSTRUCTIONS:
*
* c89 sptdio.c -o sptdio -Wextensions -Wsystype=oss -g -D_XOPEN_SOURCE=1 \
* -lZSPTDLL
*/

#include <limits.h>
#include <stdlib.h>
/* Use the thread-aware library functions that are thread-aware
* (thread-blocking instead of process-blocking) for regular files
*/
#define SPT_THREAD_AWARE_XNONBLOCK
#include <spthread.h>

/********************/
/* LITERALS/DEFINES */
/********************/

/* the maximum number of I/O threads created by this program */


#define MAX_THREADS 4

/* concurreny level value passed to pthread_setconcurrency() */


/* the value of 100000 sets the minimum scheduled quantum to 0.000001 seconds. */
#define CONCURRENCY_LEVEL 100000

/* I/O size used by all threads */


#define IOSIZE 8192

/* size of files that are written - 1Mb */


#define WRITE_FILESIZE 1048576

/*
*-----------------------------------------------------------------
* OSS_read_thread --
*
* Description:
*

Thread-Aware and Nonblocking OSS Functions 309


* This thread reads an OSS file using OSS I/O. Because this program
* uses the define SPT_THREAD_AWARE_XNONBLOCK, the read() function is
* mapped to the spt_readz() function, which is thread-aware and blocks
* the thread instead of the entire process. Other threads are free to do
* work while this thread is blocked waiting for an I/O completion.
*
*
* Results:
* none.
*
*------------------------------------------------------------------
*/

void *OSS_read_thread(void *OSS_read_file)


{
int fd;
int nbytes;
char *iobuf;
int ret;
long long filesize = 0;

/*****************************************************************/
/* prepare I/O buffer (page aligned, paged into physical memory) */
/*****************************************************************/

if ((iobuf = malloc(IOSIZE)) == NULL)


{
printf("*** ERROR in OSS_read_thread: unable to allocate I/O buffer ***\n");
exit(0);
}
memset(iobuf, 0, IOSIZE);

/*********************/
/* open the OSS file */
/*********************/

if ((fd = open(OSS_read_file, O_RDONLY | O_NONBLOCK)) < 0)


{
printf("*** ERROR in OSS_read_thread: open() of %s failed w/error %d
***\n", OSS_read_file, errno);

exit(0);
}
/**********************************************/
/* read the OSS file in a thread aware manner */
/**********************************************/

while (1)
{
nbytes = read(fd, iobuf, IOSIZE);

if (nbytes < 0)
{
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
{
/**************************************************************************/
/* NOTE that this code does not execute for regular (disk) files, because */
/* read() on a regular file never returns EWOULDBLOCK or EAGAIN */
/**************************************************************************/
ret = spt_fd_read_ready(fd, NULL);
if (ret != 0)
{
printf("*** ERROR in OSS_read_thread: spt_fd_read_ready()
failed w/err %d\n",ret);
exit(0);
}
}
else
{
printf("*** ERROR in OSS_read_thread: read() failed w/error
%d ***\n",errno);
exit(0);
}
}
else if (nbytes == 0) /* EOF */
{
break;
}
else /* read successful */
{
filesize += nbytes;

}
} /* while */

close(fd);

printf("==> OSS_read_thread() read %ld bytes from file %s\n", filesize,


OSS_read_file);
return(NULL);
}

310 Using the Standard POSIX Threads Library


/*
*--------------------------------------------------------------------
*
* OSS_write_thread --
*
* Description:
*
* This thread writes an OSS file using OSS I/O. Because this program
* uses the define SPT_THREAD_AWARE_XNONBLOCK, the write() function is
* mapped to the spt_writez() function, which is thread-aware and blocks
* the thread instead of the entire process. Other threads are free to do
* work while this thread is blocked waiting for an I/O completion.
*
* Results:
* none.
*
*---------------------------------------------------------------------
*/

void *OSS_write_thread(void *OSS_write_file)


{
int fd;
int nbytes;
char *iobuf;
int ret;
long long currsize = 0;

/*****************************************************************/
/* prepare I/O buffer (page aligned, paged into physical memory) */
/*****************************************************************/

if ((iobuf = malloc(IOSIZE)) == NULL)


{
printf("*** ERROR in OSS_write_thread: unable to allocate I/O buffer
***\n");
exit(0);
}
memset(iobuf, 0, IOSIZE);

/*********************/
/* open the OSS file */
/*********************/

if ((fd = open(OSS_write_file, O_WRONLY | O_NONBLOCK | O_CREAT | O_TRUNC,


S_IRWXU)) < 0)
{
printf("*** ERROR in OSS_write_thread: open() of %s failed w/error
%d ***\n", OSS_write_file, errno);
exit(0);
}
/***********************************************/
/* write the OSS file in a thread-aware manner */
/***********************************************/

while (currsize < WRITE_FILESIZE)


{
nbytes = write(fd, iobuf, IOSIZE);
if (nbytes < 0)
{
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
{
/**************************************************************************/
/* NOTE that this code does not execute for regular (disk) files, because */
/* write() on a regular file never returns EWOULDBLOCK or EAGAIN */
/**************************************************************************/

ret = spt_fd_write_ready(fd, NULL);


if (ret != 0)
{
printf("*** ERROR in OSS_write_thread: spt_fd_write_ready()
failed w/error %d ***\n", ret);

Thread-Aware and Nonblocking OSS Functions 311


exit(0);
}
}
else
{
printf("*** ERROR in OSS_write_thread: write() failed w/error %d
***\n", errno);
exit(0);
}
}
else /* write successful */
{
currsize += nbytes;
}
} /* while */

close(fd);

printf("==> OSS_write_thread() wrote %d bytes to file %s\n",


WRITE_FILESIZE, OSS_write_file);
return(NULL);
}

int main(int argc, char *argv[])


{
/* the following variables correspond to the OSS filenames specified */
/* as command line parameters to the program */
char OSS_read_filename[PATH_MAX];
char OSS_write_filename[PATH_MAX];
/* total number of threads that have been created */
int nmbr_created_threads = 0;
/* array of handles for each thread created */
pthread_t thread_handle[MAX_THREADS];
int i;

/*************************************/
/* Process command line arguments */
/*************************************/

if (argc > 9)
{
printf("Usage: sptdio [-r <OSS-file>] [-w <OSS-file>]\n");
exit(0);
}

/* verify that an even number of command line parameters was specified */


if (((argc - 1) % 2) == 1)
{
printf("Usage: sptdio [-r <OSS-file>] [-w <OSS-file>]\n");
exit(0);
}

for (i = 1; i < argc; i = i + 2)


{
if (strcmp(argv[i], "-r") == 0)
{
strcpy(OSS_read_filename, argv[i+1]);
}
else if (strcmp(argv[i], "-w") == 0)
{
strcpy(OSS_write_filename, argv[i+1]);
}
else {
printf("Usage: sptdio [-r <OSS-file>] [-w <OSS-file>]\n");
exit(0);
}
}

312 Using the Standard POSIX Threads Library


/********************************************************/
/* Set the concurrency level for the thread scheduler */
/********************************************************/

pthread_setconcurrency(CONCURRENCY_LEVEL);

/**********************************/
/* Create all of the I/O threads */
/**********************************/

for (i = 1; i < argc; i = i + 2)


{
if (strcmp(argv[i], "-r") == 0)
{
pthread_create(&thread_handle[nmbr_created_threads++],
NULL, &OSS_read_thread, OSS_read_filename);
}
else if (strcmp(argv[i], "-w") == 0)
{
pthread_create(&thread_handle[nmbr_created_threads++],
NULL, &OSS_write_thread, OSS_write_filename);
}
}

printf("\n==> All threads created...\n");

/************************************************************************/
/* wait for the threads to complete - this is where control is passed */
/* to the threads */
/************************************************************************/

for (i = 0; i < nmbr_created_threads; ++i)


{
pthread_join(thread_handle[i], NULL);
}

} /* main() */

Reentrant OSS Functions


For systems running J-series RVUs, H06.05 and later H-series RVUs, and G06.28 and later G-series
RVUs, several new reentrant functions are provided (Table 11-10 (page 324)). Many existing
functions are also reentrant. To determine if a function is reentrant, see the reference page for
that function either online or in the Open System Services System Calls Reference Manual.
Many functions are unsafe in multithreaded applications, often because these functions return
a pointer to a string or structure that is in static storage. A second call to the function overwrites
the static storage (the results from the first call). Other issues for multithreaded applications
include the use of global variables and maintaining context across calls.
In programs that use multiple threads, the same functions and the same resources might be
accessed concurrently by several flows of control. To protect resource integrity, code written for
multithreaded programs must be reentrant and thread safe.
A reentrant function does not hold static data over successive calls and does not return a pointer
to static data. All data is provided by the caller of the function. Incoming signals are blocked
until the reentrant function completes.
To determine which RVUs support an OSS function, see Appendix A (page 389).

Reentrant OSS Functions 313


NOTE: On systems running H06.21 or later H-series RVUs or J06.10 or later J-series RVUs,
reentrant functions are also provided in the library that provides the base function. Therefore,
to use the Standard POSIX Threads version of the reentrant function, when you link your
application using eld, you must specify the Standard POSIX Threads library (ZSPTDLL) before
you specify public libraries such as ZSECDLL.
Table 11-7 System and Equivalent Reentrant Functions
System Function Reentrant Function

asctime() asctime_r()

ctermid() ctermid_r()

ctime() ctime_r()

gamma() gamma_r()

getgrent() getgrent_r()

getgrgid() getgrgid_r()

getgrnam() getgrnam_r()

gethostbyaddr() gethostbyaddr_r()

gethostbyname() gethostbyname_r()

gethostent() gethostent_r()

getlogin() getlogin_r()

getnetbyaddr() getnetbyaddr_r()

getnetbyname() getnetbyname_r()

getnetent() getnetent_r()

getprotobyname() getprotobyname_r()

getprotobynumber() getprotobynumber_r()

getprotoent() getprotoent_r()

getpwent() getpwent_r()

getpwnam() getpwnam_r()

getpwuid() getpwuid_r()

getservbyname() getservbyname_r()

getservbyport() getservbyport_r()

getservent() getservent_r()

gmtime() gmtime_r()

lgamma() lgamma_r()

localtime() localtime_r()

rand() rand_r()

readdir() readdir_r()

strtok() strtok_r()

tmpnam() tmpnam_r()

ttyname() ttyname_r()

314 Using the Standard POSIX Threads Library


Example Program Using Reentrant Functions
Example 11-12 (page 316) provides an example program that uses the strtok_r() reentrant
fuction. The program results in this ouput:
thread - 0 token - a
thread - 1 token - a
thread - 0 token - b
thread - 1 token - b
thread - 0 token - c
thread - 1 token - c
thread - 0 token - x
thread - 1 token - x
thread - 0 token - y
thread - 1 token - y
thread - 0 token - z
thread - 1 token - z
For comparison, the same program, using strtok(), instead of the reentrant version,
strtok_r(), results in this output:
thread - 0 token - a
thread - 1 token - a
thread - 0 token - b
thread - 1 token - c
thread - 0 token - x
thread - 1 token - y
thread - 0 token - z
thread - 1 token - x
thread - 0 token - y
thread - 1 token - z

Reentrant OSS Functions 315


Example 11-12 Using the Reentrant Function strtok_r
/* reent.c - Using the reentrant function strtok_r
*
* Compilation steps:
*
* /usr/bin/c89 -Wextensions -Wsystype=oss -c reent.c -o reent.o
* /usr/bin/nld /usr/lib/crtlmain.o reent.o ./libspt.a -obey \
* /usr/lib/libc.obey -lzcplsrl -o reent
*/

#include<spthread.h>
#include<stdio.h>
void *gettok(void *args)
{
char str[25] = "a,b,c,";
char str5[25] = "x,y,z,";
char **lasts;
char *str1 = NULL;
char *ptr;
lasts = &str1;

ptr = strtok_r(str,",",lasts);
while(ptr != NULL)
{
printf("\n thread - %d token - %s",args,ptr);
sleep(2);
ptr = strtok_r(NULL,",",lasts);
}

ptr = strtok_r(str5,",",lasts);
while(ptr != NULL)
{
printf("\n thread - %d token - %s",args,ptr);
sleep(2);
ptr = strtok_r(NULL,",",lasts);
}
printf("\n");

}
void main()
{
pthread_t T[2];
int ret_value,t;
for(t=0;t < 2;t++)
{
ret_value = pthread_create(&T[t],NULL,(void *)gettok,(void *)t);
if (ret_value != 0)
{
printf("Error in creating the thread");
exit(1);
}
}
pthread_join(T[0],NULL);
pthread_join(T[1],NULL);
exit(0);
}

Thread-Aware Toolkit Functions and Types


Functions written using the thread-aware toolkit (Table 11-8) allow one or more threads to
perform work on one or more files without any one thread unnecessarily blocking another thread.
To enable these functions, you must include the spthread.h header file. You can use these
functions with either the spt_*() functions or the spt_*x() functions.

316 Using the Standard POSIX Threads Library


For details on each function, see the appropriate reference page in the Open System Services System
Calls Reference Manual.
Table 11-8 Thread-Aware Toolkit Functions and Types
Function Description

spt_unregFile() Unregister the file number as one you will manage. Any threads
waiting on file number I/O will awaken with SPT_ERROR and system
error 16.

spt_FileIOHandler_p() Callback type required by spt_regFileIOHandler(). A callback


is executed in the context of the last running thread; that is, it executes
on the stack of the last running thread.

spt_regFileIOHandler() Register the file number as one you will manage through a
user-supplied callback. Invoke this callback immediately after each
I/O on filenum completes.

spt_wakeup() Wake up a thread awaiting the tagged I/O on file number. The
awakened thread returns from spt_awaitio() with SPT_SUCCESS.

spt_defaultCallback() Default callback used by spt_regFile(). It calls spt_wakeup()


and passes on the supplied parameters.

spt_regFile() Register the file number as one you will manage through the default
callback.

spt_awaitio() Await a tagged IO on file number to complete, timeout, or be


interrupted. I/O is never canceled by this function, and completes only
if SPT_SUCCESS is returned. Multiple threads should not await the
same tagged I/O on any given file number.

spt_interrupt() Interrupt all threads awaiting I/O on file number. I/O is not cancelled
by this function. Interrupted threads will return from spt_awaitio()
with a return value of SPT_ERROR.

spt_interruptTag() Interrupt the thread awaiting the tagged IO on file number. I/O is not
cancelled by this function. Interrupted threads will return from
spt_awaitio() with a return value of SPT_ERROR.

spt_generateTag() Increment and return a static long appropriate for use as a tag. This
long will eventually wrap and therefore return tags that may still be
in use. For example, if a process calls spt_generateTag() 100 times
every second, the wrap will occur on the 248th day.

spt_fd_read_ready() Wait on a file descriptor to be read ready or have an exception pending.

spt_fd_write_ready() Wait on a file descriptor to be write ready or have an exception


pending.

Using Thread-Aware Toolkit Functions


The following examples show using thread-aware toolkit functions:
• Thread-aware toolkit program flow — Example 11-13 (page 318).
• Simplified program flow for a thread-aware function — Example 11-14 (page 318)
• Thread-aware read() function — Example 11-15 (page 318)
• Nonblocking thread-aware read() function — Example 11-16 (page 319)
• Function using spt_READX() — Example 11-17 (page 320)
Example 11-13 (page 318) uses the default callback mechanism by registering the file number via
spt_regFile(2). In some cases, you may wish to provide your own callback using
spt_regFileIOHandler(2), which registers the file number as one you will manage through
the callback you define.

Reentrant OSS Functions 317


Example 11-13 Thread-Aware Toolkit Program Flow
...
FILE_OPEN(…, &filenum, …);
spt_regFile(filenum);
...
// Do work on filenum.
...
spt_unregFile(filenum);
FILE_CLOSE(filenum);
...

Example 11-14 Simplified Program Flow For a Thread-Aware Function


...
READX(filenum, ...);
spte = spt_awaitio(filenum, tag, -1, count_read, &error, NULL);
if (spte != SPT_SUCCESS) (void) CANCELREQ(filenum, tag);
return error;
...

Example 11-15 illustrates using a thread-aware read() function. This example assumes you are
using the thread-aware library (spt_*() functions) instead of the nonblocking thread-aware
library (spt_*x() functions) or the thread-aware library for regular files (spt_*z() functions).
If you were to rewrite this example using the nonblocking thread-aware library, you could call
read() and handle the the EWOULBLOCK error instead of checking the O_NONBLOCK flag
of the file descriptor (see Example 11-16 (page 319)).

Example 11-15 Thread-Aware read() Function


/* This example assumes you’re using the thread aware library. */
/* It checks to ensure that the O_NONBLOCK flag is set for the */
/* file descriptor. If O_NONBLOCK is set, it is safe to call spt_read() */
/* because spt_read() will return EWOULDBLOCK if the file descriptor is */
/* not ready. */

...
#define SPT_THREAD_AWARE /* maps read() to spt_read() */
#include <spthread.h>
...
ssize_t
my_read(int filedes, void *buffer, size_t nbytes)
{
int before_flags;

/* Get file descriptor's current flags: */


if ((before_flags = fcntl(filedes, F_GETFL)) == -1) return -1;

/* If file descriptor is non-blocking then just issue the call and


return. */
if (before_flags & O_NONBLOCK) return read(filedes, buffer, nbytes);

/* Block this thread and wait until file descriptor is ready. */


if ((errno = spt_fd_read_ready(filedes, NULL)) != 0) return -1;

/* Issue the call and return. */


return read(filedes, buffer, nbytes);
}
...

Example 11-16 illustrates using a nonblocking thread-aware read() function. This example
assumes you are using the nonblocking thread-aware library (spt_*x() functions) instead of

318 Using the Standard POSIX Threads Library


the nonblocking thread-aware library (spt_*x() functions) or the thread-aware library for
regular files (spt_*z() functions). If you were to use this code with the thread-aware library
instead of the nonblocking thread aware library, you risk blocking the whole process if the file
descriptor does not have the O_NONBLOCK flag set.

Example 11-16 Nonblocking Thread-Aware read() Function


/* This program fragment assumes you are using the nonblocking thread- */
/* aware library. If you used the thread-aware library */
/* (define SPT_THREAD_AWARE instead of define SPT_THREAD_AWARE_NONBLOCK),
/* and the file descriptor does not have O_NONBLOCK set,*/
/* the read() call could block the whole program. */

...
#define SPT_TRHEAD_AWARE_NONBLOCK /* maps read() to spt_readx() */
#include <spthread.h>
...
{
int rv;
while (1)
{
rv = read(filedes, buffer, nbytes);

/* If read() returned an error. */


if (rv < 0)
{
/* If not read ready then wait (assumes EWOULBLOCK would be sent.) */
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
{
rv = spt_fd_read_ready(filedes, NULL);

/* If spt_fd_read_ready() returned an error. */


if (rv != 0)
{
errno = rv;
return -1;
}

continue;
}
}

break;
}

return rv;
}

Example 11-17 shows a code fragment that uses the READX() function in a thread-aware manner,
which is appropriate when you are not using the thread-aware library. An alternative to this
approach is to use the SPT_READX() thread-aware function.

Reentrant OSS Functions 319


Example 11-17 Example READX() Function Used In Thread-Aware Manner
{
spt_error_t spte;
long error;
_cc_status cc;
long tag;

tag = spt_generateTag();
cc = READX(filenum, buffer, read_count, , tag);

/* If READX() failed. */
if (_status_lt(cc))
{
short short_error;

(void) FILE_GETINFO_(filenum, &short_error);


return short_error;
}

/* Loop forever. */
while (1)
{
spte = spt_awaitio(filenum, tag, timelimit, count_read,
&error, NULL);

/* If spte is SPT_INTERRUPTED then try again. */


if (spte != SPT_INTERRUPTED) break;
}

/* If spt_awaitio() was unsuccessful.*/


if (spte != SPT_SUCCESS) (void) CANCELREQ(filenum, tag);

return error;

Caveats to Using the Thread-Aware Toolkit


Proper operation of the thread-aware toolkit depends on the following conditions:
• No calls to AWAITIO[X]() with a file number of -1 are made outside of pthreads.
• No calls to AWAITIO[X]() with a file number registered with pthreads are made outside
of pthreads.
• No calls to FILE_COMPLETE_SET() are made outside of pthreads.
• No calls to FILE_COMPLETE_() are made using the permanent set.

Thread-Aware $RECEIVE I/O Functions


$RECEIVE thread-aware functions (Table 11-9) integrate the following basic $RECEIVE I/O
functions with the POSIX thread engine and support.
• Read $RECEIVE (similar to READUPDATEX) so that it is thread-blocking, but not
process-blocking.
• Read $RECEIVE from one or multiple threads and returning all pertinent information
(FILE_GETRECEIVEINFO) in a thread-safe form.
• Inherit transactions on $RECEIVE and properly associating or disassociating the transaction
with the calling thread.
• Block a reading thread if the number of messages read has exceeded receive depth.
For details on each function, see the appropriate reference page in the Open System Services System
Calls Reference Manual.

320 Using the Standard POSIX Threads Library


The functions listed above provide only basic $RECEIVE handling support, not higher-level
capabilities associated with a $RECEIVE package. You can build such higher-level functions
using the primitives present in the thread-aware $RECEIVE functions, but must tailor them for
whatever domain-specific application they occur in. High-level capabilities not supported by
the thread-aware $RECEIVE functions include:
• Maintenance of an opener’s table
• Pathway server semantics (exit upon last close)
• Automatic resend of last replies for NonStop requesters
• Distribution of messages based on type or opener
• Any special handling of system messages (system messages are supported, but are treated
as any other message)
• Encapsulation of the open or close of $RECEIVE, or any SETMODE
Table 11-9 Thread-Aware $RECEIVE Functions and Types
Function Description

spt_INITRECEIVE() Register filenum being managed by the $RECEIVE callback

spt_RECEIVEREAD() Thread-aware function specifically for reading $RECEIVE

spt_REPLYX() Thread-aware REPLYX()

spt_READX() Thread-aware READX()

Using Thread-Aware $RECEIVE Functions


Example 11-18 through Example 11-20 show using thread-aware $RECEIVE functions.
Example 11-18 (page 321) shows the program flow for using a thread-aware $RECEIVE function.

Example 11-18 Thread-Aware $RECEIVE Program Flow


...
FILE_OPEN(…, &filenum, …, receive_depth, …);
spt_INITRECEIVE(filenum, receive_depth);
...
// Do work on filenum.
...
spt_unregFile(filenum);
FILE_CLOSE(filenum);
...

Example 11-19 shows using the thread-aware functions spt_RECEIVEREAD() and


spt_REPLYX() to perform the actual work on $RECEIVE.

Reentrant OSS Functions 321


Example 11-19 Function with spt_RECEIVEREAD() and spt_REPLYX()
...
while (1)
{
if (spt_RECEIVEREAD(…) != 0) break;
...
// Do work.
...
if (spt_REPLYX(…) != 0) break;
}
...

Example 11-20 shows a single thread calling the thread-aware spt_RECEIVEREAD() function.
Using thread-aware $RECEIVE functions allows one or more threads to perform work on
$RECEIVE, without a thread unnecessarily blocking another thread.

322 Using the Standard POSIX Threads Library


Example 11-20 $RECEIVE Server
#include <cextdecs.h(FILE_OPEN_)>
#include <spthread.h>

short filenum;
void *
thread_start(void *parms)
{
long bytesread, error;
char buffer[2];
short receive_info[17];
while (1)
{
error = spt_RECEIVEREAD(filenum, buffer,
(short)sizeof(buffer), &bytesread, -1,
receive_info, NULL);
if (error != 0) break;
// Do real work here!
error = spt_REPLYX("server's reply.", 15, NULL,
receive_info[2], 0);
if (error != 0) break;
}
fprintf(stderr,"thread_start: error: %d\n",error);
return NULL;
}

int
main()
{
pthread_t thread1, thread2;
char *filename = "$RECEIVE";

if (FILE_OPEN_(filename, (short)strlen(filename), &filenum,


0, , 1, 2, 1) != 0)
{
fprintf(stderr,"main: FILE_OPEN_ failed.\n");
exit(1);
}

if (spt_INITRECEIVE(filenum, 2) != 0)
{
fprintf(stderr,"main: spt_INITRECEIVE failed\n");
exit(1);
}

if (pthread_create(&thread1, NULL, &thread_start, NULL) != 0)


{
perror("main: pthread_create");
exit(1);
}
} exit(0)

if (pthread_create(&thread2, NULL, &thread_start, NULL) != 0)


{
perror("main: pthread_create");
exit(1);
}

if (pthread_join(thread1, NULL) != 0)
{
perror("main: pthread_join");
exit(1);
}

Reentrant OSS Functions 323


if (pthread_join(thread2, NULL) != 0)
{
perror("main: pthread_join");
exit(1);
}
}

Caveats to Using Thread-Aware $RECEIVE


Proper operation of thread-aware $RECEIVE depends on the following conditions:
• No calls to AWAITIO[X]() with a file number of -1 are made outside of pthreads.
• No calls to AWAITIO[X]() with file number for $RECEIVE are made outside of pthreads.
• No calls to FILE_COMPLETE_SET() are made outside of pthreads.
• No calls to FILE_COMPLETE_() are made using the permanent set.

Thread-Aware Enscribe Functions


Thread-aware Enscribe functions are supported on J-series RVUs, H06.05 and later H-series
RVUs, and G06.28 and later G-series RVUs. Thread-aware Enscribe functions (Table 11-10
(page 324)) provide thread aware wrappers for Enscribe procedure calls that enable an application
to make use of Enscribe procedure calls without blocking the process.
Thread-aware Enscribe functions are thread-blocking, like functions in the thread-aware library,
instead of process-blocking, like other Enscribe functions.
The parameters and the semantics for the new APIs are the same as those of Enscribe procedures,
which are described in the Guardian Procedure Calls Reference Manual.
The thread-aware APIs for Enscribe procedure calls can:
• Open a file
• Read and write
• Cancel I/O operations issued on the file
• Lock and unlock the file or a record
• Execute device-dependent operations on an open file
• Set device-dependent functions in an open file
These functions must be explicitly called. There are no macros to map to these functions from
the non-thread aware versions.
Table 11-10 Thread-Aware Enscribe Functions
Function Description

SPT_CANCEL Cancels the oldest incomplete operation on a file opened nowaited

SPT_CONTROL Performs device-dependent I/O operations

SPT_FILE_CLOSE_ Closes an open file

SPT_FILE_OPEN_ Establishes a communication path between an application process and a file

SPT_READX Returns data from an open file to the application process data area

SPT_READUPDATEX Reads data from a disk or process file in anticipation of a subsequent write to
the file

SPT_READLOCKX Sequentially locks and reads records in a disk file

SPT_READUPDATELOCKX Locks, then reads the record from the current position in the file in anticipation
of a subsequent call to SPT_WRITEUPDATEX or
SPT_WRITEUPDATEUNLOCKX

SPT_SETMODE Sets device-dependent functions

324 Using the Standard POSIX Threads Library


Table 11-10 Thread-Aware Enscribe Functions (continued)
Function Description

SPT_WRITEREADX Writes data to a file from an array in the application, then waits for data to be
transferred back from the file

SPT_WRITEX Writes data from an array in the application to an open file

SPT_WRITEUPDATEX Transfers data from an array in the application to a file

SPT_WRITEUPDATEUNLOCKX Performs random processing of records in a disk file

SPT_LOCKFILE Excludes other users from accessing a file

SPT_UNLOCKFILE Unlocks a disk file and any records in that file currently locked by the user

SPT_LOCKREC Excludes other users from accessing a record at the current position

SPT_UNLOCKREC Unlocks a record currently locked by the user

Using Thread-Aware Enscribe Functions


Example 11-21 (page 326) shows an example of using the thread-aware SPT_FILE_OPEN_. This
function blocks the calling thread instead of the calling process.
Compilation:
/usr/bin/c89 -Wextensions -Wsystype=oss -c ens_thread.c -o ens_thread.o

nld /usr/lib/crtlmain.o ens_thread.o libspt.a -obey /usr/lib/libc.obey


-lzcplsrl -o ens_thread
Output:
Hello, I am in Thread1
Calling SPT_FILE_OPEN_ - thread-blocking Enscribe call
Hello, I am Thread2
error returned in open : 0 filenum : 6
error in file close 0
In contrast, if you replace the calls to the thread-blocking SPT_FILE_OPEN_ function with calls
to the process-blocking FILE_OPEN_ function, and change the printf() statement accordingly,
the program results in the following output:
Hello, I am in Thread1
Calling FILE_OPEN_ - process-blocking Enscribe call
error returned in open : 0 filenum : 6
error in file close 0
Hello, I am Thread2

Thread-Aware Enscribe Functions 325


Example 11-21 Using the Thread-Aware SPT_FILE_OPEN Function
/* Using the thread-aware SPT_FILE_OPEN function */
#include <cextdecs.h>
#include <spthread.h>
#include <stdio.h>
#include <string.h>
#include <tal.h>

short filenum;

void *Thread2(void *args)


{
printf("Hello, I am Thread2\n");
}

void *Thread1(void *args)


{
short error;
char *name = "$SYSTEM.TEST.EX2";

printf("\nHello, I am in Thread1\n");

printf("Calling SPT_FILE_OPEN_ - thread-blocking Enscribe call \n");


error = SPT_FILE_OPEN_(name,(short)strlen(name),&filenum);
printf("error returned in open : %d filenum : %d\n",error,filenum);

error = FILE_CLOSE_(filenum);
printf("error in file close %d\n",error);
}

void main()
{
pthread_t T[2];
int ret_value;
int t = 1;

ret_value = pthread_create(&T[0],NULL,(void *)Thread1,(void *)t);


if (ret_value != 0)
{
printf("Error in creating the thread");
exit(1);
}

ret_value = pthread_create(&T[1],NULL,(void *)Thread2,(void *)t);


if (ret_value != 0)
{
printf("Error in creating the thread");
exit(1);
}

pthread_join(T[0],NULL);
pthread_join(T[1],NULL);
exit(0);
}

OSS File Descriptor and Timer Callbacks


Thread-aware functions listed in Table 11-11 allow registration and use of callbacks for OSS file
descriptors and timer callbacks. For details on each function, see the appropriate reference page
in the Open System Services System Calls Reference Manual.

326 Using the Standard POSIX Threads Library


Table 11-11 Thread-Aware Callback Functions and Types
Function Description

spt_OSSFileIOHandler_p Callback type required by spt_regOSSFileIOHandler().

spt_regOSSFileIOHandler Register the file descriptor as one that the user will manage through a
user supplied callback.

spt_unregOSSFileIOHandler Unregister file descriptor as one that the user will manage.

spt_setOSSFileIOHandler Set interest in file descriptor.

spt_regTimerHandler Register a user supplied timer callback.

spt_TimerHandler_p Callback type required by spt_regTimerHandler().

Using OSS and Timer Callbacks


Example 11-22 shows an OSS file descriptor callback program flow. Typically, the callback would
conditionally signal a thread that the file descriptor is read-ready.

Example 11-22 OSS File Descriptor Callback


...
spt_regOSSFileIOHandler(fd, callback);
spt_setOSSFileIOHandler(fd, 1, 0, 0); // Only interested in read ready.
...
// Do work on file descriptor via user supplied callback.
...
spt_unregOSSFileIOHandler(fd);
...

Example 11-23 shows an OSS timer callback program flow. As soon as possible, the pthreads
scheduler initially invokes the timer callback, with successive invocations of the callback driven
by the callback’s return value. For more information, see the spt_TimerHandler_p(2) reference
page.

Example 11-23 Timer Callback Program Flow


...
spt_regTimerHandler(callback);
...

Caveat to Using Callbacks


An OSS field descriptor callback takes precedent over all other operations that are waiting on
the file descriptor. For example, if a thread is blocked on spt_fd_read_ready() and there is
a callback registered for that particular file descriptor, the thread will never be awakened by the
file descriptor being read-ready, even if the callback didn’t set interest in read-ready.
Timer callbacks must not block and may be invoked sooner or later than requested.

OSS File Descriptor and Timer Callbacks 327


328
12 Using the POSIX User Thread (PUT) Model Library
The POSIX User Model Thread library is a user-space implementation of IEEE Std 1003.1, 2004,
POSIX System Application Program Interface for use by native C and C++ TNS/E-targeted
applications in the OSS environment on NonStop servers. This library is supported on systems
running H06.21 and later H-series RVUs and J06.10 and later J-series RVUs.
Throughout the rest of this chapter:
• The POSIX User Model Thread library is referred to as the PUT Model library
• The Standard POSIX Threads library is referred to as the SPT library.
To use the PUT Model library, you should be familiar with programming in the OSS environment
and with writing threaded applications. See “About This Document” (page 15) for a list of books
on programming with threads. See the Open System Services Porting Guide for information about
porting existing threaded applications and for differences between the standard and the PUT
Model library.
Threads are scheduled for execution by the PUT Model library, not by the NonStop operating
system. All threads created within a process share the same process address space.
With the PUT Model library, one thread can never be preempted by another thread. You must
ensure that threads relinquish control either by explicitly calling the sched_yield() function,
by waiting on a mutex or condition variable, or by calling a thread-aware library function.

Compiling and Linking Considerations


Header Files
Include the following header file:
/usr/include/pthread.h
The pthread.h file contains prototypes of the PUT Model library interfaces.

Linking to the POSIX User Thread Model Library


Specify ZPUTDLL, the PUT Model library DLL, when linking with eld. These libraries are
located in the current sysnn subvolume.
You cannot use both the PUT Model library and the SPT library in the same application. If the
Common Run-Time Environment (CRE) detects that a combination of incompatible public
libraries is linked into an application, it displays a diagnostic message (run-time error 19) on the
standard log file (stderr) and terminates process execution. For example, the message reporting
that incompatible libraries ZSPTDLL and ZPUTDLL are both present is:
*** Run-time error 019 ***
Incompatible runtime libraries – ZSPTDLL vs. ZPUTDLL
The recovery action is to identify which library is the correct one and rebuild the application
such that the conflicting one is excluded.

Defines
_PUT_MODEL_
(Required) You must use the _PUT_MODEL_ define when building a threaded application
based on the PUT Model library. Because thread-aware signal handling is always enabled
in the PUT Model library, the alarm() and signal() functions are mapped to the PUT
Model library versions of these functions (similar to what the SPT_THREAD_SIGNAL and
SPT_THREAD_PRAGMA_SIGNAL defines do for the SPT library). For more information
about thread-aware signal handling, see “Thread-Aware Signal Handling” (page 377).

Compiling and Linking Considerations 329


_PUT_SELECT_SINGLE_
This define maps select() to a variant of select() that checks the status of a single file
descriptor using a faster algorithm. (This is equivalent to SPT_SELECT_SINGLE in the SPT
library.)

Environment Variables
PUT_THREAD_AWARE_REGULAR_IO_DISABLE
Allows you to disable the thread aware regular file I/O behavior. For more information about
thread-aware regular file I/O behavior, see “Thread-Aware and Nonblocking OSS Functions”
(page 345).
PUT_PROTECTED_STACK_DISABLE
Allows you to disable protected stack support. When you disable protected stack support,
the heap allocation method is used to create the thread stack. For more information about
protected stacks, see “The Protected Thread Stack for Signals” (page 336).

Standards Conformance
The POSIX threads standard is officially described in Institute of Electrical and Electronics
Engineers, Inc., 2004 IEEE Std 1003.1-2001, IEEE Std 1003.1-2001/Cor 1-2002 and IEEE Std
1003.1-2001/Cor 2-2004. For simplicity, this manual refers to the “Standard document.” The
Standard document is available for purchase online at http://standards.ieee.org/.
Portable pthreads functions provided by the PUT Model library (designated with either the
pthread_ or PTHREAD_ prefix and without the _np or _NP suffix) comply with the IEEE Std
1003.1, 2004, POSIX System Application Program Interface.
In contrast to the SPT library, the PUT Model library does not provide these global variables
because these global variables are not specified in the final standard:
pthread_attr_default
pthread_mutexattr_default
pthread_condattr_default

Error Reporting Changed From Draft 4 Standard


The PUT Model library functions return error indications as return values, instead of setting
errno. The error values returned are in many cases the values that were stored in errno in
Draft 4. The PUT Model library supports only the error values described in the Standard
document.
If an error condition occurs, a pthread routine returns an integer value indicating the type of
error. For example, a call to the Draft 4 implementation of pthread_cond_destroy() that
returned a -1 and set errno to EBUSY now returns EBUSY as the routine return value.
Reporting errors by returning error values is a global change from the previous standard (Draft
4), in which errors are reported in errno. If you are porting a threaded application that adheres
to Draft 4, you must rewrite the error handling routines. The “Threaded Application Examples”
(page 382) demonstrates error handling with the PUT Model library. See the Open System Services
Porting Guide for a list of the supported return values as well as other porting issues.

Exceptions and Extensions to the Standard Document


Although the PUT Model library version of sigaction() accepts the SA_ONSTACK flag, the
PUT Model library determines which stack is used to run the thread signal handler. The PUT
Model library does not allow you to establish a signal stack using the sigaltstack() function.
For more information about this behavior, see “The Protected Thread Stack for Signals” (page 336).
These functions are not async-signal safe, so they should not be used in signal handlers:
alarm()

330 Using the POSIX User Thread (PUT) Model Library


fork()
pause()
sigaction()
sigsuspend()
sleep()
wait()
waitpid()

Attributes Defined by Threads Macros


The attributes of the PUT Model library are determined by macros in unistd.h. Table 12-1 lists
the principal macros that influence the HP implementation for NonStop servers.
Table 12-1 Attributes of the POSIX User Thread Model Library Defined by Macros
Macro or Attribute Description in the POSIX User Thread Model Library

_POSIX_THREADS Implementation supports threads options. Defined as 0


(zero)

_POSIX_THREAD_SAFE_FUNCTIONS Implementation supports thread-safe functions. Defined


as 0 (zero).

_POSIX_THREAD_PROCESS_SHARED A mutex or condition variable can be operated on only


by threads in the same process that initialized the mutex
or condition variable. Defined as -1.

_POSIX_THREAD_PRIORITY_SCHEDULING Defined as 0 (zero) and only supports threads created


with the PTHREAD_SCOPE_PROCESS attribute. Threads
contend directly with other threads within their process.
This attribute cannot be altered. The scheduling allocation
domain size is 1. Threads are always bound to the same
processor as the parent thread.

Thread scheduling attribute: inheritsched Has the value PTHREAD_EXPLICIT_SCHED. The


scheduling policy and associated attributes, such as
priority, are set to the corresponding values from the
attributes object during thread creation. This attribute can
be altered to PTHREAD_INHERIT_SCHED (so that the
scheduling policy and attributes are inherited from the
creating thread) by using
pthread_attr_setinheritsched().

Thread scheduling attribute: schedpolicy The default value is SCHED_FIFO. This attribute cannot
be altered.

Mutex initialization scheduling attributes: Defined as -1. The prioceiling and protocol
_POSIX_THREAD_PRIO_INHERIT attributes are not defined.
_POSIX_THREAD_PRIO_PROTECT

Thread creation attribute: Defined as 0 (zero). The thread creation stack size attribute
_POSIX_THREAD_ATTR_STACKSIZE can be set in the attribute object.

Attribute: _POSIX_READER_WRITER_LOCKS Supports read and write locks. Defined as -1.

Thread creation attributes: Defined as -1. These attributes cannot be altered.


_POSIX_THREAD_CPUTIME
_POSIX_THREAD_SPORADIC_SERVER

Attributes Defined by Threads Macros 331


Table 12-1 Attributes of the POSIX User Thread Model Library Defined by Macros (continued)
Macro or Attribute Description in the POSIX User Thread Model Library

Thread creation attribute: The location of the storage to be used for the stack of the
_POSIX_THREAD_ATTR_STACKADDR created thread cannot be altered. Defined as -1.

Thread creation attribute: detachstate The default value is PTHREAD_CREATE_JOINABLE (that


is, storage associated with the thread is reclaimed when
the thread that created it calls a join()). This attribute
can be altered using
pthread_attr_setdetachstate().

Process Resources
All resources of a process—for example, open files or memory—are either global or private, as
shown in Table 12-2. Private resources can be accessed only by a specific thread. Global resources
can be accessed by all threads. Access to global resources by threads should be synchronized
using mutex or condition variables.
Table 12-2 Process Resources
Resource Type Description

Thread stack Private The memory where all thread-local variables are stored

Thread program counter Private The address of the instruction that the thread is about to execute

Thread context Private The data maintained by the threads library on behalf of a thread;
contains the per-thread signal mask, which is used by the
pthread_kill() function

All external data Global Includes process and module global resources

All static internal Global


variables

Heap Global

File descriptors and file Global Includes file and record locks
state

SQL cursors Global

Environment variables Global

Signal mask Private The per-thread signal mask, used by the pthread_kill(),
sigaction(), sigwait(), sigmask(), and sigsuspend()
functions

Signal stack Global The stack that is used to run the signal handler

Numerical Limits in the POSIX User Thread Model Library


Protected Stack Limits
The PUT Model library uses a protected stack for signals (see “The Protected Thread Stack for
Signals” (page 336)) and defines these symbolic constants related to the protected and unprotected
stacks:

Symbolic Constant Description Value

PTHREAD_STACK_MAX_NP Maximum number of bytes available for 33554432


the (unprotected) thread stack.

PTHREAD_STACK_MAX_PROTECTED_STACK Maximum number of bytes available for 16777216


the protected stack.

332 Using the POSIX User Thread (PUT) Model Library


PTHREAD_STACK_MIN_PROTECTED_STACK Minimum number of bytes available for 49152
the protected stack.

Limits Imposed by the Standard


Table 12-3 lists numerical limits imposed by the standard implementation. The symbolic constants
listed in the table are defined in limits.h with the values shown in the table. These symbolic
constants refer to the most restrictive value for each feature.
Table 12-3 Numerical Limits in the POSIX User Thread Model Library
Symbolic Constant Description Value

_POSIX_ARG_MAX Maximum length of the arguments for one of 4096


the exec functions, in bytes, including
environment data

_POSIX_CHILD_MAX Maximum number of simultaneous processes 6


for one real user ID

_POSIX_DESTRUCTOR_ITERATIONS Maximum number of attempts to destroy the 4


thread-specific data of a thread on termination

_POSIX_FD_SETSIZE Maximum number of descriptors that a process _POSIX_OPEN_MAX


can examine

_POSIX_HIWAT Maximum number of bytes that can be buffered _POSIX_PIPE_BUF


on a socket for sending or receiving

_POSIX_KEYS_MAX Maximum number of keys a process can use 1024

_POSIX_LINK_MAX Maximum value of a file’s link count 8

_POSIX_MAX_CANON Maximum number of bytes in a terminal 255


canonical input queue

_POSIX_MAX_INPUT Maximum number of bytes for which space will 255


be available in a terminal input queue

_POSIX_NAME_MAX Maximum number of bytes in a filename 14

_POSIX_NGROUPS_MAX Maximum number of simultaneous 0


supplementary group IDs for one process

_POSIX_OPEN_MAX Maximum number of files that one process can 16


have open at one time

_POSIX_PATH_MAX Maximum number of bytes in a pathname 255

_POSIX_PIPE_BUF Maximum number of bytes that can be written 512


atomically when writing to a pipe

_POSIX_QLIMIT_ Maximum number of connections that can be 1


queued on a socket

_POSIX_SSIZE_MAX Maximum value that can be stored in an object 32,767


of type ssize_t

_POSIX_STACK_MIN Minimum number of bytes available for the 4096


thread stack.

_POSIX_STREAM_MAX Maximum number of streams that one process 8


can have open at one time

_POSIX_THREAD_DESTRUCTOR_ITERATIONS Maximum number of attempts to destroy the 4


thread-specific data of a thread on termination

_POSIX_THREAD_KEYS_MAX Maximum number of thread-specific data keys 128


available per process

Numerical Limits in the POSIX User Thread Model Library 333


Table 12-3 Numerical Limits in the POSIX User Thread Model Library (continued)
Symbolic Constant Description Value

_POSIX_THREAD_THREADS_MAX Maximum number of threads supported per 64


process

_POSIX_TZNAME_MAX Maximum number of bytes supported for time 3


zone names

PTHREAD_DESTRUCTOR_ITERATIONS Maximum number of attempts to destroy 4


thread's thread-specific data on termination)

PTHREAD_KEYS_MAX Maximum number of thread-specific data keys 1024


available per process

PTHREAD_STACK_MIN Minimum number of bytes available for the 4096


thread stack.

PTHREAD_THREADS_MAX Maximum number of threads supported per 2048


process

Signals and Signal Handling


Types of Signals
There are two basic types of signals:
• Synchronous signals represent events that occur inside a process.
Synchronous signals occur immediately after the instruction that caused the event—for
example, attempting to divide by zero. A synchronous signal is associated with the thread
that is executing when the event occurs. A thread can install signal handlers (using the
sigaction() function) for the synchronous signals that occur during its execution. For
terminating signals, the default behavior is to terminate the process.
• Asynchronous signals represent events external to a process.
A thread can wait for a set of asynchronous signals using the PUT Model library version of
the sigwait() function. If a thread is waiting for a type of signal that is received, the thread
is awakened and if a signal handler has been installed, it is invoked, and the signal is
considered handled; otherwise, the default signal action is taken. For a terminating signal,
the default behavior is to terminate the process. You can define signal-catching functions
for asynchronous signals. See “Thread-Aware Signal Handling” (page 337).
The supported signal numbers are listed in Table 12-4. For more information about the PUT
Model library implementation of signals, see “Using Signals” (page 335).
Table 12-4 Signals Processed by Threads
Name Number Type Default Action Description

SIGABEND 311 Process-level Terminate with saveabend Abnormal termination

SIGABRT 6 Synchronous Terminate with saveabend Abort process

SIGALRM 14 Alarm signal Terminate process Alarm clock

SIGCHLD 18 Process-level Discard signal Child has stopped or


terminated

SIGCONT 28 Process-level Continue execution Continue execution

SIGFPE 8 Synchronous Terminate with saveabend Arithmetic overflow

SIGHUP 1 Process-level Terminate process Hangup

SIGILL 4 Synchronous Terminate with saveabend Invalid instruction

334 Using the POSIX User Thread (PUT) Model Library


Table 12-4 Signals Processed by Threads (continued)
Name Number Type Default Action Description

SIGINT 2 Asynchronous Terminate process Interrupt

SIGIO 7 Synchronous Discard signal IO possible or completed

SIGKILL 91 Process-level Terminate process Kill

SIGLIMIT 27 Synchronous Terminate with saveabend NonStop operating system


limits trap

SIGMEMERR 22 Synchronous Terminate with saveabend Uncorrectable memory error

SIGMEMMGR 24 Synchronous Terminate with saveabend Memory manager read error

SIGNOMEM 23 Synchronous Terminate with saveabend No memory available

SIGPIPE 13 Asynchronus Terminate process Write on a pipe, no one to


read it

SIGQUIT 3 Asynchronous Terminate with saveabend Quit

SIGRECV 19 Synchronous Discard signal Message queued on


$RECEIVE (currently not
used)

SIGSEGV 11 Synchronous Terminate with saveabend Invalid address reference

SIGSTK 25 Synchronous Terminate with saveabend Stack overflow

SIGSTOP 201 Process-level Terminate process Stop

SIGTERM 15 Asynchronous Terminate process Software termination signal

SIGTIMEOUT 26 Process-level Terminate process Process loop timer time-out

SIGTSTP 21 Process-level Terminate process Interactive stop

SIGTTIN 29 Process-level Stop process Background read attempted


from controlling terminal

SIGTTOU 30 Process-level Stop process Background write attempted


to controlling terminal

SIGUNCP 10 Process-level Discard signal Uncooperative process.


Supported for servers
running H and J-series RVUs
only.

SIGURG 5 Asynchronous Discard signal Urgent condition on I/O


channel

SIGUSR1 16 Asynchronous Terminate process User-defined signal 1

SIGUSR2 17 Asynchronous Terminate process User-defined signal 2

SIGWINCH 12 Synchronous Discard signal Terminal device window size


changed
1 Signal cannot be caught or ignored.

Using Signals
• The following signal features are not supported:
— Job Control Signals. The stop a process or continue a process actions implied by these
signals are also not supported.
— The Real-time Signals Extension option.
• Use the sigaction() function, not the signal() function, to specify the action to be
taken when a given signal is received.

Signals and Signal Handling 335


• These OSS system and library functions support thread-aware signal handling:
alarm()
sigaction()
signal
sigpending()
sigsuspend()
sigwait()
pause()
sleep()
usleep()
wait()
waitpid()
• The pthread_kill() function provides a mechanism for synchronously directing a signal
to a thread in the calling process.
Signals sent with the pthread_kill() function are queued in FIFO order for the target
thread. More than one instance of the same signal might be pending for a thread. However,
applications should not rely on this ordering.
• A signal is handled in the context of the given thread. However, the signal action (terminating
or stopping) might affect the process as a whole. See “Thread-Aware Signal Handling”
(page 337).
• You must specify whether a signal listed in Table 12-4 (page 334) as generating a saveabend
actually generates a saveabend by specifying the -Wsaveabend flag in c89 or c99, or
saveabend in nld, ld, or eld.
• If a signal is delivered to a thread waiting on a condition variable, then upon return from
the signal handler, the thread will resume waiting for the condition variable as if it were not
interrupted.

The Protected Thread Stack for Signals


The PUT Model library does not allow you to establish a signal stack using the sigaltstack()
function. Instead, the library allocates a protected signal stack for use by signal handlers and
applications that use the PUT Model library can use the sigaltstack() function to get the
status of the signal stack.
Thread-aware signal handling is enabled by default in the PUT Model library. The library allocates
and installs a protected stack to allow external signals and synchronous signals to be delivered
to a signal stack that is different from the thread stack.
• When an external asynchronous signal is delivered to the PUT library signal handler on the
signal stack, the thread library signal handlers check to see if the current thread can handle
the signal. If it can, then the thread library signal handler invokes the thread signal handler
immediately on the same signal stack. If the current thread cannot handle the signal, the
thread library signal handler finds the thread that can and queues the signal for that thread
and return. The thread signal handlers for these queued signals are run either at the thread
dispatch time or at the cancellation point on the main stack for the thread.
• When a synchronous signal is delivered to the thread library signal handler on the signal
stack, the signal gets processed immediately. If the current thread can handle the signal, the
thread signal handler gets invoked immediately on the same signal stack; otherwise, the
thread library signal handler performs the default action associated with the signal and
terminates the process.
• If nested signals are delivered to the thread library signal handler, they are delivered on the
same signal stack as the signal handler being interrupted. If a nested thread signal handler
is run by the thread library signal handler, it is run on the same signal stack as the thread
signal handler that is being interrupted.

336 Using the POSIX User Thread (PUT) Model Library


Using Signals With the setjmp() and longjmp() Functions
Using the setjmp() and longjmp() functions can interfere with signal handling. The
longjmp() function causes a thread to jump to the execution context saved by a previous call
to the setjmp() function, but it does not restore the signal mask of the process. If the longjmp()
function is called within a signal handler, the signal mask used in the signal handler is retained
when execution resumes at the setjmp() location. The exception mechanism uses the setjmp()
and longjmp() functions and behaves similarly.
The sigsetjmp() and siglongjmp() functions have an option to save and restore the signal
mask. This option can cause signals that were enabled by another thread to be inadvertently
masked.
When handling signals:
• Do not use the raise() function for an exception, and do not use the longjmp() function
to exit a synchronous signal handler. Simply returning from a signal handler is safe and is
the recommended practice.
• Use exception handlers instead of the setjmp() and longjmp() functions for threaded
OSS applications.
• Do not use the option of the sigsetjmp() and siglongjmp() functions that saves and
restores the signal mask. Doing so can cause signals enabled by another thread to be masked.

Thread-Aware Signal Handling


The PUT Model library catches both externally generated OSS signals and synchronous signals,
which are result of an event that occurs inside a process, and deliver them to the correct thread.
By default, thread-aware signal behavior is enabled.

Signals and Signal Handling 337


Types of Signals
Signals are categorized as synchronous, asynchronous, or process level:
• Synchronous signals result from an event that occurs inside a process and are delivered
synchronously with that event. These signals are delivered to current active thread. If current
active thread has not installed the signal handler, then default actions are performed. Signals
in this category are:
SIGABRT
SIGFPE
SIGILL
SIGIO
SIGLIMIT
SIGMEMERR
SIGMEMMGR
SIGNOMEM
SIGSEGV
SIGSTK
SIGWINCH
• Asynchronous signals result from an event that is external to the process and are delivered
at any point in the execution of a thread. These signals are delivered to the active threads
in FIFO order. If no active threads have installed a signal handler for the signal, the
process-level actions described in Table 12-4 (page 334) are performed. Signals in this category
are:
SIGINT
SIGPIPE
SIGQUIT
SIGTERM
SIGURG
SIGUSR1
SIGUSR2
• For process level signals only process level actions can be performed. Signal handlers for
these signals are registered directly to the operating system, so an existing handler for a
given signal is overwritten when a new signal handler is defined for that signal. Signals in
this category are:
SIGABEND (cannot be handled by a user-defined signal handler)
SIGCONT
SIGKILL (cannot be handled by a user-defined signal handler)
SIGSTOP (cannot be handled by a user-defined signal handler)
SIGTSTP (process level action is performed)
SIGTIMEOUT
SIGTTIN
SIGTTOU
SIGUNCP

Limitations
Do not deliver signals like SIGALRM and SIGCHLD using the kill command or the raise()
function because these functions do not provide enough information about the process IDs for
the parent and child processes. Instead, use the PUT Model library version of the alarm()
function to raise alarms.

338 Using the POSIX User Thread (PUT) Model Library


Examples
Example 12-1 (page 339) provides an example of handling the synchronous signal SIGFPE. Because
thread-aware signal handling is always enabled, the signal handler defined in the example is
executed, and signal 8 (SIGFPE) is received by the thread. On successful return from a
signal-catching function for a SIGFPE, SIGILL, SIGLIMIT,SIGMEMERR, SIGMEMMGR,
SIGNOMEM, SIGSEGV, SIGABRT, or SIGSTK signal that was not generated by a kill() or
raise() function call, a process receives a SIGABEND signal and terminates.

Example 12-1 Handling the Synchronous Signal SIGFPE


/* This test program demonstrates handling the */
/* SIGFPE synchronous signal. */

#define _PUT_MODEL_ /** enables thread aware behavior **/

#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include “myio.h” /* contains my_printf which is process blocking */

/*Define a signal handler for this thread */


void sighand(int signo);
int x=10,y=0,z;

void *threadfunc(void *parm)

/* Perform the illegal operation of dividing by zero and */


/* raise the SIGFPE signal. The SIGFPE signal is sent to */
/* the generic handler. */
{
signal(SIGFPE,sighand);
z = x/y;
my_printf("\nI am in thread1\n");
return NULL;
}

int main(int argc, char **argv)

pthread_t thread1;
my_printf("Enter Testcase - %s\n", argv[0]);

/* create the thread */


pthread_create(&thread1, NULL, threadfunc, NULL);
sleep(1);
my_printf("Wait for threads to complete\n");
pthread_join(thread1, NULL);
my_printf("Main completed\n");
return 0;
}
void sighand(int signo)
{
my_printf("Signal received is %d\n",signo);
}

Example 12-2 (page 341) creates a thread that waits for asynchronous signal SIGINT.
Sample input:
> kill -2 process-name
or

Signals and Signal Handling 339


<CRTL-C>
Both of these inputs generate a SIGINT signal.
In Example 12-2 (page 341), the signal handler of thread1 is executed and thread1 no longer
waits for a signal. Sample output:
Enter Testcase - ./Test2
sigaction returned 0
Wait for threads to complete
Signal received is 2
sigsuspend returned -1
Main completed.

340 Using the POSIX User Thread (PUT) Model Library


Example 12-2 Handling the Synchronous Signal SIGINT
/* Program that demonstrates behavior of Asynchronous */
/* signal SIGINT */

#define _PUT_MODEL_ /** enables thread aware behavior **/


#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include “myio.h” /** contains my_printf which is process-blocking**/

void sighand(int signo);

struct sigaction sigact_t;

sigset_t waitset;

void *threadfunc(void *parm)

int rc1,rc2;
sigfillset( &waitset );
sigdelset( &waitset,SIGINT);
sigact_t.sa_handler = sighand;
rc1 = sigaction(SIGINT,&sigact_t,NULL);
my_printf("\nsigaction returned %d\n",rc1);
rc2=sigsuspend(&waitset);
my_printf("\nsigsuspend returned %d\n",rc2);
return NULL;

int main(int argc, char **argv)

pthread_t thread1;
my_printf("Enter Testcase - %s\n", argv[0]);
pthread_create(&thread1, NULL, threadfunc, NULL);
sleep(1);
my_printf("Wait for threads to complete\n");
pthread_join(thread1, NULL);
my_printf("Main completed\n");
return 0;
}

void sighand(int signo)


{
my_printf("Signal received is %d\n",signo);
}

Example 12-3 (page 342) demonstrates handling the SIGCHLD signal. This example creates two
threads, each of which call fork(). When the child process executes, the process raises the
SIGCHLD signal. The SIGCHLD signal is delivered to the correct thread, and sigaction()
function in the example defines the action to be taken. Sample output:
sigaction for thread1 returned 0
sigaction for thread2 returned 0
Inside Child of Thread2
Signal received for Thread2 is 18
Inside Child of Thread1
Signal received for Thread1 is 18
Main Completed

Signals and Signal Handling 341


Example 12-3 Handling the SIGCHLD Signal
/* This program demonstrates the handling of the */
/* SIGCHLD signal */

#define _PUT_MODEL_ /** enables thread aware behavior **/


#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include “myio.h” /** contains my_printf which is process-blocking**/

struct sigaction sigact_t,osigact_t;


sigset_t waitset;
int rc;

void sig_cld1(int);
void sig_cld2(int);
void *do_work1(void *arg)
{
pid_t pid;
sigact_t.sa_handler =sig_cld1;
sigact_t.sa_flags = 0;
rc =sigaction(SIGCHLD,&sigact_t,NULL);
my_printf("\nsigaction for thread1 returned %d\n",rc);
if ((pid = fork()) < 0)
my_printf("ERROR IN FORK\n");
else if (pid == 0)
{
sleep(2);
my_printf("\nInside Child of Thread1\n");
exit(0);
}
waitpid(pid,NULL,NULL);
return NULL;
}

void *do_work2(void *arg)


{
pid_t pid;
osigact_t.sa_handler =sig_cld2;
osigact_t.sa_flags = 0;
rc = sigaction(SIGCHLD,&osigact_t,NULL);
my_printf("\nsigaction for thread2 returned %d\n",rc);
if ((pid = fork()) < 0)
my_printf("ERROR IN FORK\n");
else if (pid == 0)
{
sleep(1);
my_printf("\nInside Child of Thread2\n");
exit(0);
}
waitpid(pid,NULL,NULL);
return NULL;

}
int main()
{
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,do_work1,NULL);
pthread_create(&tid2,NULL,do_work2,NULL);
sched_yield ();

342 Using the POSIX User Thread (PUT) Model Library


pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
my_printf ("\nMain Completed\n");
}

void sig_cld1(int signo)


{
my_printf("\nSignal received for Thread1 is %d\n",signo);
}

void sig_cld2(int signo)


{
my_printf("\nSignal received for Thread2 is %d\n",signo);
}

Example 12-4 (page 344) provides an example of SIGALRM handling. It creates two threads that
wait for a SIGALRM signal. The SIGALRM signal is delivered to the correct thread, and the
sighand1() and sighand2() functions define the actions to be taken. Sample output:
sigaction for thread1 returned 0
sigaction for thread2 returned 0
Signal received for thread1 is 14
sigsuspend for thread1 returned -1
sigwait returned 0
sigwait for thread2 returned for signal 14
Main Completed

Signals and Signal Handling 343


Example 12-4 Handling SIGALRM Signals
/*Program demonstrating handling the SIGALRM signal */

#define _PUT_MODEL_ /** enables thread aware behavior **/


#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include “myio.h” /** contains my_printf which is process-blocking**/

void sighand1(int);
void sighand2(int);
struct sigaction sigact_t;
int rc;
void *do_work(void *arg)
{
sigset_t set;
sigfillset(&set);
sigdelset(&set,SIGALRM);
sigact_t.sa_handler = sighand1;
rc = sigaction(SIGALRM,&sigact_t,NULL);
my_printf("\n sigaction for thread1 returned %d\n",rc);
alarm(5);
rc = sigsuspend(&set);
my_printf("\nsigsuspend for thread1 returned %d\n",rc);
return NULL;
}

void *do_work1(void *arg)


{

sigset_t set;
int sig;
sigemptyset(&set);
sigaddset(&set,SIGALRM);
sigact_t.sa_handler = sighand2;
rc=sigaction(SIGALRM,&sigact_t,NULL);
my_printf("\nsigaction for thread2 returned %d\n",rc);
alarm(6);
rc=sigwait(&set,&sig);
my_printf("\nsigwait returned %d\n",rc);
my_printf("\nsigwait for thread2 returned for signal %d\n",sig);
return NULL;

int main()
{
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,do_work,NULL);
pthread_create(&tid2,NULL,do_work1,NULL);
sched_yield();
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
my_printf("\nMain Completed\n");
}

void sighand1(int signo)

{
my_printf("Signal received for thread1 is %d\n",signo);
}

void sighand2(int signo)


{

344 Using the POSIX User Thread (PUT) Model Library


my_printf("Signal received is %d\n",signo);
}

Thread-Aware and Nonblocking OSS Functions


If a function must wait for an I/O operation to complete, the function blocks its caller (either a
thread or a process) from continuing until the I/O operation completes. A function that blocks
all threads while it waits for I/O to complete is a process-blocking function. Process-blocking
functions are not thread aware. If a thread calls a process-blocking function, the calling thread
and all the other threads in the process are prevented from continuing until the I/O operation is
complete and the function returns a status indication. Standard OSS I/O library functions are not
thread-aware.
In contrast to a process-blocking function, a thread-aware function blocks only the thread calling
that function, instead of blocking all threads in the process. The other threads in the process can
continue doing work while the calling thread waits for I/O to complete. A thread-aware function
is sometimes called a thread-blocking function, because it blocks only the calling thread.
Sometimes it is not enough for a function to be thread-aware. There can be times when you do
not want even the calling thread to wait for I/O to complete. Instead, you want the function to
either succeed immediately or to fail immediately. Functions that do not block the calling thread
or the other threads in the process are nonblocking functions. Nonblocking I/O functions are
sometimes called asynchronous I/O functions.
The behavior of an OSS I/O library function can vary according to these factors:
• Whether the file descriptor is for a regular file or a non-regular file.
• Whether the function was designed to be process-blocking, thread-aware (thread-blocking),
or nonblocking for that type of file.
• Whether the file descriptor passed to the function is nonblocking. A file descriptor is
nonblocking when one of these conditions is true:
— The file descriptor has the O_NONBLOCK flag set.
— The file descriptor has been set to non-blocking mode by setting the argument to the
request parameter to F_SETFL when calling the fcntl() function.

Regular Files
For regular files, thread-aware functions block the calling thread but allow the other threads to
run, whether or not the file descriptor is nonblocking. These functions never return the errors
EAGAIN, EINPROGRESS, or EWOULDBLOCK for regular files, so there are no nonblocking
thread-aware functions for regular files. Table 12-5 (page 346) lists the functions for which PUT
Model library provides a version that is thread-aware for regular files. You can disable
thread-aware I/O for regular files by setting the
PUT_THREAD_AWARE_REGULAR_IO_DISABLE environment variable before you start the
process.
In addition to the functions listed in Table 12-5 (page 346), these additional functions, although
not thread-aware, support the use of thread-aware functions by serializing file operations on an
open file:
dup2()
fstat64()
fstat()
lseek64()
lseek()

Serialization of File Operations On an Open File


The PUT Model library supports a thread-aware set of functions that serialize file operations on
an open regular file. If a thread calls one of the thread-aware functions to access a file that already

Thread-Aware and Nonblocking OSS Functions 345


has a file operation in progress by a different thread, the calling thread is blocked until the prior
file operation is complete. For example:
1. Thread A calls the thread-aware version of the read() function to read the open file
MyDataFile. The file does not have an operation in progress, so thread A starts reading
the file.
2. Thread B calls the thread-aware version write() function to write to the same open file
MyDataFile. Because the read operation started by thread A is still in progress, thread B
is blocked and must wait for thread A’s read operation to complete.

Non-Regular Files
For non-regular files, there are functions that can provide thread-aware behavior or both
nonblocking and thread-aware behavior:
• The set of functions that are thread-aware are thread-aware whether or not the file descriptor
is nonblocking. If the O_NONBLOCK flag is set, these functions are also nonblocking: they
do not block the calling thread or the other threads, and they return one of these errors to
the application: EAGAIN, EINPROGRESS, or EWOULDBLOCK. Otherwise, these functions
block the calling thread but allow other threads to run. These functions remove the need for
the application to explicitly set the O_NONBLOCK flag of the file descriptor to enable
thread-aware behavior. The thread-aware functions are listed in the Nonblocking
Thread-Aware Functions (Non-Regular Files Only) column of Table 12-5 (page 346).

Equivalent System, Thread-Aware, and Nonblocking Thread-Aware Functions


The PUT model library does not provide analogs to spt_*x() or spt_*z()functions, such as
spt_readx() or spt_readz(), whose purpose is to be non-blocking alternatives to standard
system library functions. Instead, you refer to the standard function name and compile and link
the application as described in “Compiling and Linking Considerations” (page 329). Additionally,
the PUT model library does not provide analogs to spt_*() functions, such as spt_fprintf(),
whose purpose is to be non-blocking alternatives to the standard C run-time library functions.
Instead, you refer to the standard function names, which are thread aware for H06.21 and later
H-series RVUs and J06.10 and later J-series RVUs.
Table 12-5 lists standard functions that have equivalent thread-aware functions. For example:
• read() is a process-blocking function for both regular files and for non-regular files if you
are not using the PUT Model library.
• The PUT Model library version of read() is a thread-aware function with this behavior:
For non-regular files, this function does not require the file descriptor to be nonblocking for
this function to be thread-aware. If the file descriptor is nonblocking, this function does not
block the calling thread, and returns one of these errors to the application: EAGAIN,
EINPROGRESS, or EWOULDBLOCK. Otherwise, this function blocks the calling thread but
allows other threads to run. For regular files, this function blocks the calling thread but
allows other threads to run. This function does not require the file descriptor to be
nonblocking for this function to be thread-aware.

NOTE: To determine which RVUs support an OSS function, see Appendix A (page 389)
Table 12-5 System and Equivalent Thread-Aware Functions
Standard Nonblocking and thread Nonblocking and thread aware Thread aware in PUT Model
(Process-Blocking) OSS aware in PUT Model in PUT Model library for library (functions not related to
Functions library for regular files non-regular files file I/O)

accept() — yes —

alarm() — — yes

close() yes yes —

346 Using the POSIX User Thread (PUT) Model Library


Table 12-5 System and Equivalent Thread-Aware Functions (continued)
Standard Nonblocking and thread Nonblocking and thread aware Thread aware in PUT Model
(Process-Blocking) OSS aware in PUT Model in PUT Model library for library (functions not related to
Functions library for regular files non-regular files file I/O)

connect() — yes —

dup2() — yes —

fcntl() yes yes —

fork() — — yes

fstat() yes — —

fstat64() yes — —

fsync() yes — —

ftruncate() yes — —

ftruncate64() yes — —

lseek() yes — —

lseek64() yes — —

pause() — — yes

read() yes yes —

readv() yes — —

recv() — yes —

recvfrom() — yes —

recvmsg() — yes —

select() — yes —

send() — yes —

sendmsg() — yes —

sendto() — yes —

sigaction() — — yes

sigaltstack() — — yes

signal() — — yes

sigpending() — — yes

sigsuspend() — — yes

sigwait() — — yes

sleep() — — yes

usleep() — — yes

wait() — — yes

waitpid() — — yes

write() yes yes —

writev() — — yes

Thread-Aware and Nonblocking OSS Functions 347


The Set of Thread-Aware I/O Functions Must Be Used Together
The PUT Model library serializes I/O functions on open files only for the thread-aware regular
I/O set of functions the PUT Model library provides. Using modules that were not compiled to
use the PUT Model library can cause unexpected results. For example, compiling a module so
that it calls the unmapped standard function close() directly, instead of the PUT Model library
version of close(), might leave a thread with a pending thread-aware regular file request
suspended with no mechanism available to reschedule it for execution. For example, if you
compile one module to use the PUT Model library and another module to not use the PUT Model
library, you can get errors when the two modules operate on the same open file:
1. Thread A calls the PUT Model library version (a thread-aware version of read() to read
the open file MyDataFile. The file does not have an operation in progress, so thread A
starts reading the file.
2. Thread B calls standard read() system function (you did not use the PUT Model library),
which is not thread-aware, to read to the same open file MyDataFile. Because the standard
read() function does not support serialization, the standard version of read() attempts
to do the read and fails, returning the error EALREADY. The EALREADY error indicates
that an operation is already in progress.

Using Thread-Aware Functions


Example 12-5 (page 348) shows using thread-aware functions with a file stream. It is not necessary
to set the O_NONBLOCK flag.

Example 12-5 File Stream Thread-Aware Function Usage


...
fs = fopen(path, mode);
fd = fileno(fs);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
...
// Call thread-aware functions.
...
fclose(fs);
...

Example 12-6 (page 348) shows opening a file descriptor for use with a thread-aware function. It
is not necessary to set the O_NONBLOCK flag.

Example 12-6 File Descriptor Thread-Aware Function Usage


...
filedes = open(path, oflag, mode | O_NONBLOCK);
...
// Call thread-aware functions.
...
close(filedes);
...

Example 12-7 (page 349) shows preparing an open file descriptor for use with a thread-aware
function. It is not necessary to set the O_NONBLOCK flag.

348 Using the POSIX User Thread (PUT) Model Library


Example 12-7 Open File Descriptor Thread-Aware Function Usage
...
fcntl(filedes, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
...
// Call thread-aware functions.
...

Example 12-8 (page 350) is a multithreaded program that performs I/O on multiple OSS regular
files using the thread-aware functions that are available when you use the define _PUT_MODEL_.
With these functions, you do not have to use Guardian functions to allow other threads to continue
to work while another thread waits for I/O to complete on an open file.

Thread-Aware and Nonblocking OSS Functions 349


Example 12-8 Pthreads Thread-Aware Disk File I/O Using PUT Model Library
/*
* sptdio.c - Pthreads thread-aware Diskfile IO Example Program
*
* This Pthreads program demonstrates a multithreaded program that
* can perform I/O on multiple OSS regular files (diskfiles) using
* thread-aware OSS I/O functions
* Note that OSS I/O on regular files is serialized.
* Note: If you want process—blocking I/O behavior, export the
* PUT_THREAD_AWARE_REGULAR_IO_DISABLE = 1.
*
* The following threads can be created by this program:
* - An OSS read thread which uses OSS I/O to completely
* read a regular file.
* - An OSS write thread which uses OSS I/O to write
* 1Mb of data to the regular file.
*
* USAGE SYNTAX:
*
* sptdio [-r <OSS-file>] [-w <OSS-file>]
*
* FLAGS
* -r <OSS-file> Create a thread that uses OSS I/O to
* completely read the given OSS diskfile.
* -w <OSS-file> Create a thread that uses OSS I/O to write the
* given OSS diskfile.
* 1Mb of data is written to the file.
*
* EXAMPLE USAGE:
*
* /home/user: run sptdio -r /tmp/r1 -w /tmp/w1
*
* ==> All threads created...
* ==> OSS_write_thread() wrote 1048576 bytes to file /tmp/w1
* ==> OSS_read_thread() read 1581888 bytes from file /tmp/r1
*
* OSS BUILD INSTRUCTIONS:
*
* c89 sptdio.c -o sptdio -Wextensions -Wsystype=oss -g -D_XOPEN_SOURCE=1 \
* -lZPUTDLL
*/

#define _PUT_MODEL_
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include “myio.h” /* contains my_printf which is process blocking */
/* Use the thread-aware library functions that are thread-aware */
/* (thread-blocking instead of process-blocking) for regular files */

#include <pthread.h>

/********************/
/* LITERALS/DEFINES */
/********************/

/* the maximum number of I/O threads created by this program */


#define MAX_THREADS 4

/* concurreny level value passed to pthread_setconcurrency() */


/* the value of 100000 sets the minimum scheduled quantum */

350 Using the POSIX User Thread (PUT) Model Library


/* to 0.000001 seconds. */
#define CONCURRENCY_LEVEL 100000

/* I/O size used by all threads */


#define IOSIZE 8192

/* size of files that are written - 1Mb */


#define WRITE_FILESIZE 1048576

Thread-Aware and Nonblocking OSS Functions 351


/* -----------------------------------------------------------------
* OSS_read_thread --
*
* Description:
*
* This thread reads an OSS file using OSS I/O. Because this program
* uses the define _PUT_MODEL>, the read() function is
* mapped to the thread—aware read() function, which blocks
* the thread instead of the entire process.
* Other threads are free to do
* work while this thread is blocked waiting for an I/O completion.
*
* Results:
* none.
*------------------------------------------------------------------
*/

void *OSS_read_thread(void *OSS_read_file)


{
int fd;
int nbytes;
char *iobuf;
int ret;
long long filesize = 0;

/*****************************************************************/
/* prepare I/O buffer (page aligned, paged into physical memory) */
/*****************************************************************/

if ((iobuf = malloc(IOSIZE)) == NULL)


{
my_printf("*** ERROR in OSS_read_thread: unable to allocate I/O buffer ***\n");
exit(0);
}
memset(iobuf, 0, IOSIZE);

/*********************/
/* open the OSS file */
/*********************/

if ((fd = open(OSS_read_file, O_RDONLY | O_NONBLOCK)) < 0)


{
my_printf("*** ERROR in OSS_read_thread: open() of %s failed w/error %d \
***\n", OSS_read_file, errno);

exit(0);
}
/**********************************************/
/* read the OSS file in a thread aware manner */
/**********************************************/

while (1)
{
nbytes = read(fd, iobuf, IOSIZE);

if (nbytes < 0)
{
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
{
/**************************************************************************/
/* NOTE that this code does not execute for regular (disk) files, because */
/* read() on a regular file never returns EWOULDBLOCK or EAGAIN */
/**************************************************************************/
ret = put_fd_read_ready(fd, NULL);
if (ret != 0)
{
my_printf("*** ERROR in OSS_read_thread: put_fd_read_ready() \
failed w/err %d\n",ret);
exit(0);
}
}
else
{
my_printf("*** ERROR in OSS_read_thread: read() failed w/error \
%d ***\n",errno);
exit(0);
}
}
else if (nbytes == 0) /* EOF */
{
break;
}
else /* read successful */
{
filesize += nbytes;

}
} /* while */

close(fd);

my_printf("==> OSS_read_thread() read %ld bytes from file %s\n", filesize,

352 Using the POSIX User Thread (PUT) Model Library


OSS_read_file);
return(NULL);
}

Thread-Aware and Nonblocking OSS Functions 353


/* -------------------------------------------------------------------
*
* OSS_write_thread --
*
* Description:
*
* This thread writes an OSS file using OSS I/O. Because this program
* uses the define _PUT_MODEL_, the write() function is
* mapped to the thread—aware version of the write() function, which
* blocks the thread instead of the entire process.
* Other threads are free to do
* work while this thread is blocked waiting for an I/O completion.
*
* Results:
* none.
*
*--------------------------------------------------------------------
*/

void *OSS_write_thread(void *OSS_write_file)


{
int fd;
int nbytes;
char *iobuf;
int ret;
long long currsize = 0;

/*****************************************************************/
/* prepare I/O buffer (page aligned, paged into physical memory) */
/*****************************************************************/

if ((iobuf = malloc(IOSIZE)) == NULL)


{
my_printf("*** ERROR in OSS_write_thread: unable to allocate I/O buffer \
***\n");
exit(0);
}
memset(iobuf, 0, IOSIZE);

/*********************/
/* open the OSS file */
/*********************/

if ((fd = open(OSS_write_file, O_WRONLY | O_NONBLOCK | O_CREAT | O_TRUNC,


S_IRWXU)) < 0)
{
my_printf("*** ERROR in OSS_write_thread: open() of %s failed w/error \
%d ***\n", OSS_write_file, errno);
exit(0);
}
/***********************************************/
/* write the OSS file in a thread-aware manner */
/***********************************************/

while (currsize < WRITE_FILESIZE)


{
nbytes = write(fd, iobuf, IOSIZE);
if (nbytes < 0)
{
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
{
/***********************************************************/
/* NOTE that this code does not execute for regular (disk) */
/* files, because write() on a regular file never returns */
/* EWOULDBLOCK or EAGAIN */
/***********************************************************/

ret = put_fd_write_ready(fd, NULL);


if (ret != 0)
{
my_printf("*** ERROR in OSS_write_thread: put_fd_write_ready() \

354 Using the POSIX User Thread (PUT) Model Library


failed w/error %d ***\n", ret);
exit(0);
}
}
else
{
my_printf("*** ERROR in OSS_write_thread: write() failed w/error %d \
***\n", errno);
exit(0);
}
}
else /* write successful */
{
currsize += nbytes;
}
} /* while */

close(fd);

my_printf("==> OSS_write_thread() wrote %d bytes to file %s\n",


WRITE_FILESIZE, OSS_write_file);
return(NULL);
}

int main(int argc, char *argv[])


{
/* the following variables correspond to the OSS filenames specified */
/* as command line parameters to the program */
char OSS_read_filename[PATH_MAX];
char OSS_write_filename[PATH_MAX];
/* total number of threads that have been created */
int nmbr_created_threads = 0;
/* array of handles for each thread created */
pthread_t thread_handle[MAX_THREADS];
int i;

/*************************************/
/* Process command line arguments */
/*************************************/

if (argc > 9)
{
my_printf("Usage: sptdio [-r <OSS-file>] [-w <OSS-file>]\n");
exit(0);
}

/* verify that an even number of command line parameters was specified */


if (((argc - 1) % 2) == 1)
{
my_printf("Usage: sptdio [-r <OSS-file>] [-w <OSS-file>]\n");
exit(0);
}

for (i = 1; i < argc; i = i + 2)


{
if (strcmp(argv[i], "-r") == 0)
{
strcpy(OSS_read_filename, argv[i+1]);
}
else if (strcmp(argv[i], "-w") == 0)
{
strcpy(OSS_write_filename, argv[i+1]);
}
else {
my_printf("Usage: sptdio [-r <OSS-file>] [-w <OSS-file>]\n");
exit(0);
}
}

Thread-Aware and Nonblocking OSS Functions 355


/**********************************/
/* Create all of the I/O threads */
/**********************************/

for (i = 1; i < argc; i = i + 2)


{
if (strcmp(argv[i], "-r") == 0)
{
pthread_create(&thread_handle[nmbr_created_threads++],
NULL, &OSS_read_thread, OSS_read_filename);
}
else if (strcmp(argv[i], "-w") == 0)
{
pthread_create(&thread_handle[nmbr_created_threads++],
NULL, &OSS_write_thread, OSS_write_filename);
}
}

my_printf("\n==> All threads created...\n");

/***************************************************/
/* wait for the threads to complete - */
/* this is where control is passed to the threads */
/* to the threads */
/***************************************************/

for (i = 0; i < nmbr_created_threads; ++i)


{
pthread_join(thread_handle[i], NULL);
}

} /* main() */

Threads Portability
The PUT Model library follows the POSIX Threads Standard document. Using thread functions
whose names end with _np (non-portable) decreases the portability of a program, because these
functions are extensions to the Standard document. Using the jacket routines provided by HP
also reduces portability of a threaded application; see “Jacket Routines (Nonblocking Versions
of SEVERCLASS_ and TMF System Calls)” (page 368) for more information about the jacket
routines.

Thread Safety
The lists in this section apply to systems running J06.10 or later J-series RVUs or H06.21 or later
H-series RVUs only:
• Functions listed in the Open System Services System Calls Reference Manual or in the Open
System Services Library Calls Reference Manual are safe for use in threaded programs unless
they are listed in “Functions That Are Not Thread Safe” (page 357).
• Functions that contain a cancellation point are listed in “Cancellation Points” (page 357).
• Functions that allow a cancellation point to occur are listed in “Potential Cancellation Points”
(page 358).

356 Using the POSIX User Thread (PUT) Model Library


Functions That Are Not Thread Safe
These functions are not safe for use in threaded applications:
asctime() ftw() mrand48()
catgets() ftw64() nl_langinfo()
chvol() gamma() nlist()
crypt() gcvt() nftw()
ctime() get_assign_msg() nftw64()
dbm_clearerr() get_assign_msg_by_name()putc_unlocked()
dbm_close() get_param_by_name() putchar_unlocked()
dbm_delete() get_param_msg() re_comp()
dbm_error() get_startup_msg() re_exec()
dbm_fetch() getc_unlocked() readdir()
dbm_firstkey() getchar_unlocked() readdir64()
dbm_nextkey() getdate() regcmp()
dbm_open() getenv() regex()
dbm_store() getopt() setkey()
dlerror() gfileno() strerror()
drand48() gmtime() strtok()
ecvt() hcreate() system_guardian()
encrypt() hdestroy() tmpfile_guardian()
fcvt() hsearch() tmpfile64_guardian()
fopen_guardian() inet_ntoa() tmpnam_guardian()
fopen_std_file() l64a() ttyname()
fopen64_guardian() lgamma() wcstombs()
fopen64_std_file() localeconv() wctomb()
freopen_guardian() localtime()
freopen64_guardian() lrand48()

Cancellation Points
These functions contain a cancellation point:
close()
fcntl() (with F_SETLK as cmd)
fsync()
read()
readv()
sigwait()
write()
writev()

Thread Safety 357


Potential Cancellation Points
A cancellation point might occur when a thread is executing one of these functions:
catgets() fwprintf() lseek()
dbm_close() fwrite() lseek64()
dbm_delete() fwscanf() lwres_getaddrinfo()
dbm_fetch() getaddrinfo() lwres_gethostbyaddr()
dbm_firstkey() getc() lwres_gethostbyaddr_r()
dbm_nextkey() getc_unlocked() lwres_gethostbyname()
dbm_open() getchar() lwres_gethostbyname_r()
dbm_store() getchar_unlocked() lwres_gethostbyname2()
dlclose() getdate() lwres_getipnodebyaddr()
dlopen() gethostbyaddr() lwres_getipnodebyname()
endhostent() gethostbyaddr_r() lwres_getnameinfo()
endnetent() gethostbyname() mkstemp()
endprotoent() gethostbyname_r() nftw()
endservent() gethostbyname2() nftw64()
fclose() gethostent() pclose()
fflush() gethostent_r() perror()
fgetc() getipnodebyaddr() popen()
fgetpos() getipnodebyname() printf()
fgetpos64() getnameinfo() putc()
fgets() getnetbyaddr() putc_unlocked()
fgetwc() getnetbyaddr_r() putchar()
fgetws() getnetbyname() putchar_unlocked()
fmtmsg() getnetbyname_r() puts()
fprintf() getnetent() putw()
fputc() getnetent_r() putwc()
fputs() getprotobyname() putwchar()
fputwc() getprotobyname_r() rewind()
fputws() getprotobynumber() scanf()
fread() getprotobynumber_r() sethostent()
freehostent() getprotoent() setnetent()
freopen() getprotoent_r() setprotoent()
freopen_oss() gets() setservent()
freopen64() getservbyname() strerror()
freopen64_oss() getservbyname_r() strerror_r()
fscanf() getservbyport() ungetc()
fseek() getservbyport_r() ungetwc()
fseeko() getservent() vfprintf()
fseeko64() getservent_r() vfwprintf()
fsetpos() getw() vprintf()
fsetpos64() getwc() vwprintf()
ftell() getwchar() wordexp()
ftello() getwd() wprintf()
ftello64() glob() wscanf()
ftw() iconv_close()
ftw64() iconv_open()

Reentrant OSS Functions


For J06.10 and later J-series RVUs and H06.21 and later H-series RVUs, reentrant functions are
provided by the public libraries where the base non-reentrant functions are defined. This is in
contrast to earlier RVUs in which the reentrant functions were only defined in the SPT library
(The functions in the SPT library are still available). Applications that use the PUT Model library

358 Using the POSIX User Thread (PUT) Model Library


use the reentrant functions that are defined in the public libraries (do not attempt to use the
reentrant function in the SPT library: you cannot include both modules that use the PUT Model
library and the SPT library in the same application).
Reentrant functions include the _r suffix in their names. To determine if a function is reentrant,
see the reference page for that function either online or in the Open System Services System Calls
Reference Manual.
Many functions are unsafe in multithreaded applications, often because these functions return
a pointer to a string or structure that is in static storage. A second call to the function overwrites
the static storage (the results from the first call). Other issues for multithreaded applications
include the use of global variables and maintaining context across calls.
In programs that use multiple threads, the same functions and the same resources might be
accessed concurrently by several flows of control. To protect resource integrity, code written for
multithreaded programs must be reentrant and thread safe.
A reentrant function does not hold static data over successive calls and does not return a pointer
to static data. All data is provided by the caller of the function.

Example Program Using Reentrant Functions


Example 12-9 (page 360) provides an example program that uses the strtok_r() reentrant
fuction. The program results in this ouput:
thread - 0 token - a
thread - 1 token - a
thread - 0 token - b
thread - 1 token - b
thread - 0 token - c
thread - 1 token - c
thread - 0 token - x
thread - 1 token - x
thread - 0 token - y
thread - 1 token - y
thread - 0 token - z
thread - 1 token - z
For comparison, the same program, using strtok(), instead of the reentrant version,
strtok_r(), results in this output:
thread - 0 token - a
thread - 1 token - a
thread - 0 token - b
thread - 1 token - c
thread - 0 token - x
thread - 1 token - y
thread - 0 token - z
thread - 1 token - x
thread - 0 token - y
thread - 1 token - z

Reentrant OSS Functions 359


Example 12-9 Using the Reentrant Function strtok_r
/* reent.c - Using the reentrant function strtok_r
*
* Compilation steps:
*

* /usr/bin/c89 -Wextensions -Wsystype=oss -c reent.c -o reent.o


* /usr/bin/nld /usr/lib/crtlmain.o reent.o ./libspt.a -obey \
* /usr/lib/libc.obey -lzcredll -o reent
*/

#define _PUT_MODEL_
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include “myio.h” /* contains my_printf which is process blocking */

void *gettok(void *args)


{
char str[25] = "a,b,c,";
char str5[25] = "x,y,z,";
char **lasts;
char *str1 = NULL;
char *ptr;
lasts = &str1;

ptr = strtok_r(str,",",lasts);
while(ptr != NULL)
{
my_printf("\n thread - %d token - %s",args,ptr);
sleep(2);
ptr = strtok_r(NULL,",",lasts);
}

ptr = strtok_r(str5,",",lasts);
while(ptr != NULL)
{
my_printf("\n thread - %d token - %s",args,ptr);
sleep(2);
ptr = strtok_r(NULL,",",lasts);
}
my_printf("\n");

}
int main()
{
pthread_t T[2];
int ret_value,t;
for(t=0;t < 2;t++)
{
ret_value = pthread_create(&T[t],NULL,gettok,(void *)t);
if (ret_value != 0)
{
my_printf("Error in creating the thread");
exit(1);
}
}
pthread_join(T[0],NULL);
pthread_join(T[1],NULL);
exit(0);
}

360 Using the POSIX User Thread (PUT) Model Library


Thread-Aware Toolkit Functions and Types
Functions written using the thread-aware toolkit (Table 12-6) allow one or more threads to
perform work on one or more files without any one thread unnecessarily blocking another thread.
To enable these functions, you must include the pthread.h header file. You can use these
functions with the thread-aware functions in the PUT Model library.
For details on each function, see the appropriate reference page in the Open System Services System
Calls Reference Manual.
Table 12-6 Thread-Aware Toolkit Functions and Types
Function Description

put_unregFile() Unregister the file number as one you will manage. Any threads
waiting on file number I/O will awaken with put_ERROR and system
error 16.

put_FileIOHandler_p() Callback type required by put_regFileIOHandler(). A callback


is executed in the context of the last running thread; that is, it executes
on the stack of the last running thread.

put_regFileIOHandler() Register the file number as one you will manage through a
user-supplied callback. Invoke this callback immediately after each
I/O on filenum completes.

put_wakeup() Wake up a thread awaiting the tagged I/O on file number. The
awakened thread returns from put_awaitio() with put_SUCCESS.

put_defaultCallback() Default callback used by put_regFile(). It calls put_wakeup()


and passes on the supplied parameters.

put_regFile() Register the file number as one you will manage through the default
callback.

put_awaitio() Await a tagged IO on file number to complete, timeout, or be


interrupted. I/O is never canceled by this function. and completes only
if put_SUCCESS is returned. Multiple threads should not await the
same tagged I/O on any given file number.

put_interrupt() Interrupt all threads awaiting I/O on file number. I/O is not cancelled
by this function. Interrupted threads will return from put_awaitio()
with a return value of put_ERROR.

put_interruptTag() Interrupt the thread awaiting the tagged IO on file number. I/O is not
cancelled by this function. Interrupted threads will return from
put_awaitio() with a return value of put_ERROR.

put_generateTag() Increment and return a static long appropriate for use as a tag. This
long will eventually wrap and therefore return tags that may still be
in use. For example, if a process calls put_generateTag() 100 times
every second, the wrap will occur on the 248th day.

put_fd_read_ready() Wait on a file descriptor to be read ready or have an exception pending.

put_fd_write_ready() Wait on a file descriptor to be write ready or have an exception


pending.

Using Thread-Aware Toolkit Functions


The following examples show using thread-aware toolkit functions:
• Thread-aware toolkit program flow — Example 12-10 (page 362).
• Simplified program flow for a thread-aware function — Example 12-11 (page 362)
• Nonblocking thread-aware read() function — Example 12-12 (page 363)
• Function using put_READX() — Example 12-13 (page 364)

Reentrant OSS Functions 361


Example 12-10 (page 362) uses the default callback mechanism by registering the file number via
put_regFile(2). In some cases, you may wish to provide your own callback using
put_regFileIOHandler(2), which registers the file number as one you will manage through
the callback you define.

Example 12-10 Thread-Aware Toolkit Program Flow


...
FILE_OPEN(…, &filenum, …);
put_regFile(filenum);
...
// Do work on filenum.
...
put_unregFile(filenum);
FILE_CLOSE(filenum);
...

Example 12-11 Simplified Program Flow For a Thread-Aware Function


...
READX(filenum, ...);
pute = put_awaitio(filenum, tag, -1, count_read, &error, NULL);
if (pute != put_SUCCESS) (void) CANCELREQ(filenum, tag);
return error;
...

Example 12-12 illustrates using a nonblocking thread-aware read() function. If you were to
disable thread-aware behavior by using the PUT_THREAD_AWARE_REGULAR_IO_DISABLE
environment variable, you risk blocking the whole process if the file descriptor points to a regular
file.

362 Using the POSIX User Thread (PUT) Model Library


Example 12-12 Nonblocking Thread-Aware read() Function

/* This program fragment assumes that you are using the */


/* PUT Model library. For regular files, the read() function */
/* is thread-aware unless you have set the */
/* PUT_THREAD_AWARE_REGULAR_IO_DISABLE environment */
/* variable. For non-regular files, the read() */
/* function can be thread aware or thread aware nonblocking. */
/* If the file descriptor has O_NONBLOCK set, the read() */
/* function is thread-aware nonblocking, and might return */
/* EWOULDBLOCK and EAGAIN

...
#define _PUT_MODEL_ /* maps read() to thread-aware read() */
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
...
{
int rv;
while (1)
{
rv = read(filedes, buffer, nbytes);

/* If read() returned an error. */


if (rv < 0)
{
/* If not read ready then wait (assumes EWOULBLOCK would be sent.) */
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
{
rv = put_fd_read_ready(filedes, NULL);

/* If put_fd_read_ready() returned an error. */


if (rv != 0)
{
errno = rv;
return -1;
}

continue;
}
}

break;
}

return rv;
}

Example 12-13 shows a code fragment that uses the READX() function in a thread-aware manner,
which is appropriate when you are not using the thread-aware library. An alternative to this
approach is to use the put_READX() thread-aware function.

Reentrant OSS Functions 363


Example 12-13 Example READX() Function Used In Thread-Aware Manner
{
put_error_t spte;
long error;
_cc_status cc;
long tag;

tag = put_generateTag();
cc = READX(filenum, buffer, read_count, , tag);

/* If READX() failed. */
if (_status_lt(cc))
{
short short_error;

(void) FILE_GETINFO_(filenum, &short_error);


return short_error;
}

/* Loop forever. */
while (1)
{
spte = put_awaitio(filenum, tag, timelimit, count_read,
&error, NULL);

/* If spte is put_INTERRUPTED then try again. */


if (spte != put_INTERRUPTED) break;
}

/* If put_awaitio() was unsuccessful.*/


if (spte != put_SUCCESS) (void) CANCELREQ(filenum, tag);

return error;

Caveats to Using the Thread-Aware Toolkit


Proper operation of the thread-aware toolkit depends on the following conditions:
• No calls to AWAITIO[X]() with a file number of -1 are made outside of pthreads.
• No calls to AWAITIO[X]() with a file number registered with pthreads are made outside
of pthreads.
• No calls to FILE_COMPLETE_SET() are made outside of pthreads.
• No calls to FILE_COMPLETE_() are made using the permanent set.

Thread-Aware $RECEIVE I/O Functions


$RECEIVE thread-aware functions (Table 12-7) integrate the following basic $RECEIVE I/O
functions with the POSIX thread engine and support.
• Read $RECEIVE (similar to READUPDATEX) so that it is thread-blocking, but not
process-blocking.
• Read $RECEIVE from one or multiple threads and returning all pertinent information
(FILE_GETRECEIVEINFO) in a thread-safe form.
• Inherit transactions on $RECEIVE and properly associating or disassociating the transaction
with the calling thread.
• Block a reading thread if the number of messages read has exceeded receive depth.
For details on each function, see the appropriate reference page in the Open System Services System
Calls Reference Manual.

364 Using the POSIX User Thread (PUT) Model Library


The functions listed above provide only basic $RECEIVE handling support, not higher-level
capabilities associated with a $RECEIVE package. You can build such higher-level functions
using the primitives present in the thread-aware $RECEIVE functions, but must tailor them for
whatever domain-specific application they occur in. High-level capabilities not supported by
the thread-aware $RECEIVE functions include:
• Maintenance of an opener’s table
• Pathway server semantics (exit upon last close)
• Automatic resend of last replies for NonStop requesters
• Distribution of messages based on type or opener
• Any special handling of system messages (system messages are supported, but are treated
as any other message)
• Encapsulation of the open or close of $RECEIVE, or any SETMODE
Table 12-7 Thread-Aware $RECEIVE Functions and Types
Function Description

put_INITRECEIVE() Register filenum being managed by the $RECEIVE callback

put_RECEIVEREAD() Thread-aware function specifically for reading $RECEIVE

put_REPLYX() Thread-aware REPLYX()

put_READX() Thread-aware READX()

Using Thread-Aware $RECEIVE Functions


Example 12-14 through Example 12-16 show using thread-aware $RECEIVE functions.
Example 12-14 (page 365) shows the program flow for using a thread-aware $RECEIVE function.

Example 12-14 Thread-Aware $RECEIVE Program Flow


...
FILE_OPEN(…, &filenum, …, receive_depth, …);
put_INITRECEIVE(filenum, receive_depth);
...
// Do work on filenum.
...
put_unregFile(filenum);
FILE_CLOSE(filenum);
...

Example 12-15 shows using the thread-aware functions put_RECEIVEREAD() and


put_REPLYX() to perform the actual work on $RECEIVE.

Reentrant OSS Functions 365


Example 12-15 Function with put_RECEIVEREAD() and put_REPLYX()
...
while (1)
{
if (put_RECEIVEREAD(…) != 0) break;
...
// Do work.
...
if (put_REPLYX(…) != 0) break;
}
...

Example 12-16 shows a single thread calling the thread-aware put_RECEIVEREAD() function.
Using thread-aware $RECEIVE functions allows one or more threads to perform work on
$RECEIVE, without a thread unnecessarily blocking another thread.

366 Using the POSIX User Thread (PUT) Model Library


Example 12-16 $RECEIVE Server

#define _PUT_MODEL_
#include <cextdecs.h(FILE_OPEN_)>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include “myio.h” /* contains my_fprintf which is process blocking */

short filenum;
void *
thread_start(void *parms)
{
long bytesread, error;
char buffer[2];
short receive_info[17];
while (1)
{
error = put_RECEIVEREAD(filenum, buffer,
(short)sizeof(buffer), &bytesread, -1,
receive_info, NULL);
if (error != 0) break;
/* Do real work here! */
error = put_REPLYX("server's reply.", 15, NULL,
receive_info[2], 0);
if (error != 0) break;
}
my_fprintf(stderr,"thread_start: error: %d\n",error);
return NULL;
}

int
main()
{
pthread_t thread1, thread2;
char *filename = "$RECEIVE";

if (FILE_OPEN_(filename, (short)strlen(filename), &filenum,


0, , 1, 2, 1) != 0)
{
my_fprintf(stderr,"main: FILE_OPEN_ failed.\n");
exit(1);
}

if (put_INITRECEIVE(filenum, 2) != 0)
{
my_fprintf(stderr,"main: put_INITRECEIVE failed\n");
exit(1);
}

if (pthread_create(&thread1, NULL, &thread_start, NULL) != 0)


{
perror("main: pthread_create");
exit(1);
}

if (pthread_create(&thread2, NULL, &thread_start, NULL) != 0)


{
perror("main: pthread_create");
exit(1);
}

Reentrant OSS Functions 367


if (pthread_join(thread1, NULL) != 0)
{
perror("main: pthread_join");
exit(1);
}

if (pthread_join(thread2, NULL) != 0)
{
perror("main: pthread_join");
exit(1);
}
}

Caveats to Using Thread-Aware $RECEIVE


Proper operation of thread-aware $RECEIVE depends on the following conditions:
• No calls to AWAITIO[X]() with a file number of -1 are made outside of pthreads.
• No calls to AWAITIO[X]() with file number for $RECEIVE are made outside of pthreads.
• No calls to FILE_COMPLETE_SET() are made outside of pthreads.
• No calls to FILE_COMPLETE_() are made using the permanent set.

Jacket Routines (Nonblocking Versions of SEVERCLASS_ and TMF System


Calls)
A jacket routine invokes a nonblocking (nowait) version of the system call and suspends the
thread until the thread’s operation is complete. the PUT Model library provides jacket routines
for SERVERCLASS_SEND and SEVERCLASS_SENDL_ calls and for TMF transaction demarcation.

SERVERCLASS_SEND and SERVERCLASS_SENDL Jacket Routines


The PUT_SERVERCLASS_SEND_() function in the POSIX User Threads Model library sends a
message to and receives a reply from a server process in a Pathway server class. This jacket
routine invokes a nowait version of the system SERVERCLASS_SEND_ procedure. The thread
that makes the call is suspended until the send operation is complete.
The PUT_SERVERCLASS_SENDL_() functionalso sends a message to and receives a reply from
a server process in a Pathway server class. This jacket routine invokes a nowait version of the
system SERVERCLASS_SENDL_ procedure. The thread that makes the call is suspended until
the send operation is complete. This function allows for messages up to two megabytes long
when Expand-over-ServerNet is used. This function does not support using Expand-over-IP.
These functions can be used with the PUT_SERVERCLASS_SENDL_() function:
put_INITRECEIVEL()
put_RECEIVEREADL()
put_REPLYXL()
Another jacket routine, the PUT_SERVERCLASS_SEND_INFO_() function returns information
about the last PUT_SERVERCLASS_SEND_() or PUT_SERVERCLASS_SENDL_() call that was
attempted or completed by the current thread. The PUT_SERVERCLASS_SEND_INFO_() function
ensures that the thread gets the information for the last message sent by the thread rather than
by the process.

SERVERCLASS_DIALOG Jacket Routines


The Pathsend SERVERCLASS_DIALOG jacket routines are used to:
• Establish a dialog with a server instance in a Pathway server class
• Send and receive messages within the dialog
• Abort or end the dialog

368 Using the POSIX User Thread (PUT) Model Library


The Context-Sensitive Pathway requester can be written using the thread-aware
SERVERCLASS_DIALOG jacket routines to communicate with a server instance in the Pathway
server class. The Pathway requester initiates the dialog using
PUT_SERVERCLASS_DIALOG_BEGIN_() routine and sends the first message of the dialog. This
thread-aware jacket routine returns the dialog ID that is used in subsequent operations to
communicate with the Pathway server. The Pathway requester can invoke multiple sends using
PUT_SERVERCLASS_DIALOG_SEND_() within the dialog to send data to the server for
processing. If the requester encounters an error while sending the data, the requester can abort
the dialog using the PUT_SERVERCLASS_DIALOG_ABORT_() routine.
The Pathway requester can use multiple PUT_SERVERCLASS_DIALOG_SEND_() calls to have
all requests serviced by the same server and all operations performed in a single context.
If the requester encounters Pathsend errors during the server class operation, the requester can
call PUT_SERVERCLASS_SEND_INFO_() to obtain information about the Pathsend error and
file-system error.
Either the requester or the server can abort the dialog, but only the server can end it. The server
ends the dialog by returning file-system error 0 (FEOK). The requester then calls
PUT_SERVERCLASS_DIALOG_END_() to clean up resources after the server has ended the
dialog. To abort the dialog, the requester calls PUT_SERVERCLASS_DIALOG_ABORT_().
The SERVERCLASS_DIALOG_ jacket routines are included in the PUT Model library, which
can be bound to an application requiring the routines:
c89 -o program program.o -lzputdll

TMF Transaction Jacket Routines


The following Transaction Management Facility (TMF) transaction jacket routines invoke the
TMF calls and manage the multiple concurrent transactions rooted in a process:
PUT_ABORTTRANSACTION()
PUT_BEGINTRANSACTION()
PUT_ENDTRANSACTION()
PUT_RESUMETRANSACTION()
The syntax and semantics of these function calls are the same as those of the similarly named
TMF calls.
When using the TMF transaction jacket routines:
• The transaction_tag parameter of the PUT_BEGINTRANSACTION() function is required.
• Each thread can have at most one current transaction. The system RESUMETRANSACTION
procedure is automatically called during thread dispatch to maintain the correct transaction
context.
• Each transaction is initially associated with only the thread that created it by calling the
PUT_BEGINTRANSACTION() function.
• Another thread can be associated with a specific transaction by calling the
PUT_RESUMETRANSACTION() function and specifying the transaction_tag value
returned by the initial PUT_BEGINTRANSACTION() function call.
• If a thread is created, it does not inherit its parent's transaction; the created thread's transaction
context is nil.
• If a thread terminates or is destroyed while it has an active transaction, that transaction is
then inaccessible from the process. If cancellation is a possibility, use exception handlers for
pthread_cancel_e. Alternatively, use the pthread_cleanup_push() and
pthread_cleanup_pop() functions to ensure that the transaction is terminated if the
thread exits or is cancelled.
• If a transaction is aborted by either an operator, network partition, or another process, an
error is reported when the initiating thread attempts to operate on the transaction.

Jacket Routines (Nonblocking Versions of SEVERCLASS_ and TMF System Calls) 369
• A process using the TMF transaction jacket routines must not call:
— The TMF procedures BEGINTRANSACTION, ABORTTRANSACTION,
ENDTRANSACTION, or RESUMETRANSACTION
— The SQL/MP BEGIN-WORK and COMMIT-WORK procedures
• A process can perform up to the default of 100 concurrent transactions, with up to 1000
transactions maximum declared using the put_setTMFConcurrentTransaction()
function. If the maximum is exceeded, a call to the
put_setTMFConcurrentTransaction() function fails, returning error number 83 (too
many transactions).

Thread-Aware Enscribe Functions


Thread-aware Enscribe functions (Table 12-8 (page 370)) provide thread aware wrappers for
Enscribe procedure calls that enable an application to make use of Enscribe procedure calls
without blocking the process.
Thread-aware Enscribe functions are thread-blocking, like functions in the thread-aware library,
instead of process-blocking, like other Enscribe functions.
The parameters and the semantics for the new APIs are the same as those of Enscribe procedures,
which are described in the Guardian Procedure Calls Reference Manual.
The thread-aware APIs for Enscribe procedure calls can:
• Open a file
• Read and write
• Cancel I/O operations issued on the file
• Lock and unlock the file or a record
• Execute device-dependent operations on an open file
• Set device-dependent functions in an open file
These functions must be explicitly called. There are no macros to map to these functions from
the non-thread aware versions.
Table 12-8 Thread-Aware Enscribe Functions
Function Description

PUT_CANCEL Cancels the oldest incomplete operation on a file opened nowaited

PUT_CONTROL Performs device-dependent I/O operations

PUT_FILE_CLOSE_ Closes an open file

PUT_FILE_OPEN_ Establishes a communication path between an application process and a file

PUT_READX Returns data from an open file to the application process data area

PUT_READUPDATEX Reads data from a disk or process file in anticipation of a subsequent write to
the file

PUT_READLOCKX Sequentially locks and reads records in a disk file

PUT_READUPDATELOCKX Locks, then reads the record from the current position in the file in anticipation
of a subsequent call to PUT_WRITEUPDATEX or
PUT_WRITEUPDATEUNLOCKX

PUT_SETMODE Sets device-dependent functions

PUT_WRITEREADX Writes data to a file from an array in the application, then waits for data to be
transferred back from the file

PUT_WRITEX Writes data from an array in the application to an open file

PUT_WRITEUPDATEX Transfers data from an array in the application to a file

370 Using the POSIX User Thread (PUT) Model Library


Table 12-8 Thread-Aware Enscribe Functions (continued)
Function Description

PUT_WRITEUPDATEUNLOCKX Performs random processing of records in a disk file

PUT_LOCKFILE Excludes other users from accessing a file

PUT_UNLOCKFILE Unlocks a disk file and any records in that file currently locked by the user

PUT_LOCKREC Excludes other users from accessing a record at the current position

PUT_UNLOCKREC Unlocks a record currently locked by the user

Using Thread-Aware Enscribe Functions


Example 12-17 (page 372) shows an example of using the thread-aware PUT_FILE_OPEN_. This
function blocks the calling thread instead of the calling process.
Compilation:
/usr/bin/c89 -Wextensions -Wsystype=oss -c ens_thread.c -o ens_thread.o

nld /usr/lib/crtlmain.o ens_thread.o libspt.a -obey /usr/lib/libc.obey


-lzcplsrl -o ens_thread
Output:
Hello, I am in Thread1
Calling PUT_FILE_OPEN_ - thread-blocking Enscribe call
Hello, I am Thread2
error returned in open : 0 filenum : 6
error in file close 0
In contrast, if you replace the calls to the thread-blocking PUT_FILE_OPEN_ function with calls
to the process-blocking FILE_OPEN_ function, and change the my_printf() statement
accordingly, the program results in the following output:
Hello, I am in Thread1
Calling FILE_OPEN_ - process-blocking Enscribe call
error returned in open : 0 filenum : 6
error in file close 0
Hello, I am Thread2

Thread-Aware Enscribe Functions 371


Example 12-17 Using the Thread-Aware PUT_FILE_OPEN Function
/* Using the thread-aware PUT_FILE_OPEN function */
#define _PUT_MODEL_
#include <cextdecs.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tal.h>
#include “myio.h” /* contains my_printf which is process blocking */

short filenum;

void *Thread2(void *args)


{
my_printf("Hello, I am Thread2\n");
}

void *Thread1(void *args)


{
short error;
char *name = "$SYSTEM.TEST.EX2";

my_printf("\nHello, I am in Thread1\n");

my_printf("Calling PUT_FILE_OPEN_ - thread-blocking Enscribe call \n");


error = PUT_FILE_OPEN_(name,(short)strlen(name),&filenum);
my_printf("error returned in open : %d filenum : %d\n",error,filenum);

error = FILE_CLOSE_(filenum);
my_printf("error in file close %d\n",error);
}

int main()
{
pthread_t T[2];
int ret_value;
int t = 1;

ret_value = pthread_create(&T[0],NULL,Thread1,(void *)t);


if (ret_value != 0)
{
my_printf("Error in creating the thread");
exit(1);
}

ret_value = pthread_create(&T[1],NULL,Thread2,(void *)t);


if (ret_value != 0)
{
my_printf("Error in creating the thread");
exit(1);
}

pthread_join(T[0],NULL);
pthread_join(T[1],NULL);
exit(0);
}

OSS File Descriptor and Timer Callbacks


Thread-aware functions listed in Table 12-9 allow registration and use of callbacks for OSS file
descriptors and timer callbacks. For details on each function, see the appropriate reference page
in the Open System Services System Calls Reference Manual.

372 Using the POSIX User Thread (PUT) Model Library


Table 12-9 Thread-Aware Callback Functions and Types
Function Description

put_OSSFileIOHandler_p Callback type required by put_regOSSFileIOHandler().

put_regOSSFileIOHandler Register the file descriptor as one that the user will manage through a
user supplied callback.

put_unregOSSFileIOHandler Unregister file descriptor as one that the user will manage.

put_setOSSFileIOHandler Set interest in file descriptor.

put_regTimerHandler Register a user supplied timer callback.

put_TimerHandler_p Callback type required by put_regTimerHandler().

Using OSS and Timer Callbacks


Example 12-18 shows an OSS file descriptor callback program flow. Typically, the callback would
conditionally signal a thread that the file descriptor is read-ready.

Example 12-18 OSS File Descriptor Callback


...
put_regOSSFileIOHandler(fd, callback);
put_setOSSFileIOHandler(fd, 1, 0, 0); // Only interested in read ready.
...
// Do work on file descriptor via user supplied callback.
...
put_unregOSSFileIOHandler(fd);
...

Example 12-19 shows an OSS timer callback program flow. As soon as possible, the pthreads
scheduler initially invokes the timer callback, with successive invocations of the callback driven
by the callback’s return value. For more information, see the put_TimerHandler_p(2) reference
page.

Example 12-19 Timer Callback Program Flow


...
put_regTimerHandler(callback);
...

Caveat to Using Callbacks


An OSS field descriptor callback takes precedent over all other operations that are waiting on
the file descriptor. For example, if a thread is blocked on put_fd_read_ready() and there is
a callback registered for that particular file descriptor, the thread will never be awakened by the
file descriptor being read-ready, even if the callback didn’t set interest in read-ready.
Timer callbacks must not block and may be invoked sooner or later than requested.

Converting Applications that use the SPT Library


The Standard POSIX Thread (SPT) library continues to be supported. You can run existing SPT
applications without changes. However, for H06.21 and later H-series RVUs and J06.10 and later
J-series RVUs, you must specify the _SPT_MODEL_ macro when you compile applications that
use the SPT library. For more information about the SPT library, see Chapter 11 (page 261).
This section describes instructions and considerations for converting an application from using
the SPT library to using the PUT Model library.

Converting Applications that use the SPT Library 373


Build Scripts
Build scripts used to compile application modules must define macro _PUT_MODEL_. This
macro determines which definitions are obtained from various header files such as sys/types.h
and stdio.h. The build scripts must not define macro _SPT_MODEL_. The build scripts must
also specify linking the PUT Model library (for example, the c89 –lput option) and must not
specify linking the SPT library (for example, dot use the –lspt option).
Although dynamic linking is possible for the SPT library (a call to dlopen() can cause the SPT
library to be linked during the execution of the application). Static linking is required for the
PUT Model library. The run-time environment terminates execution of an application if a call to
the dlopen() function requires the dynamic linking of the PUT Model library.

Header Files
You must change the header file in #include statements from spthread.h to pthread.h.

Standard Header Files


Because the pthread.h header file includes different standard header files than the spthread.h
header file, you might need to change your application to explicitly include header files that
were formerly provided by the spthread.h header file.
Table 12-10 Standard header files included in spthread.h and pthread.h header files
Header file Included Standard Header Files

spthread.h errno.h unistd.h


fcntl.h wchar.h
sched.h sys/socket.h
stdio.h sys/stat.h
stdlib.h sys/time.h
signal.h

pthread.h sched.h sys/types.h


setjmp.h

It is important to investigate any warning diagnostics generated when a source text is compiled
after changing an inclusion of spthread.h into an inclusion of pthread.h. For example, a
warning such as function "fcntl" declared implicitly reports that no explicit definition
of fcntl() was declared, therefore the compiler assumed defaults for all function attributes.
Consequently, calls to fcntl() are not mapped to the non-blocking variant of fcntl(). For a
PUT Model application this situation causes an unneeded and unwanted suspension of the entire
process. The remedy in such cases is to include whichever standard header file defines the
function and to ensure that you have also defined the _PUT_MODEL_ macro.

Nonstandard Header Files


The SPT library provides nonstandard headers in these header files:
spt_extensions.h
spt_types.h
spt_ucontext.h
The PUT Model library provides nonstandard headers in the header file:
put/put_extensions.h, which includes the header file put/put_types.h
The put/put_extensions.h header file contains definitions supporting the enhanced function
behavior that SPT library applications obtain from the spt_extensions.h header file.

374 Using the POSIX User Thread (PUT) Model Library


The put/put_types.h header file includes PUT Model library versions of the nonstandard
definitions that applications that use the SPT library obtained from spt_types.h, with this
difference:
• The spt_types.h header file defines type timespec_t that refers to a nonstandard
struct timespec data item whose first field has type unsigned long. The
put/put_types.h header file does not define this type. Instead, the standard header file
time.h defines type timespec_t, and specifies it as referring to a standard struct
timespec data item whose first field has type time_t (which is equivalent to type signed
long).
The PUT Model library does not implement a nonstandard header file that corresponds to
spt_ucontext.h because the PUT Model library provides standard function behavior that
supersedes the nonstandard function behavior provided by the SPT library.

Standard and Nonstandard Pthread Types


Some definitions in the spthread.h header files refer to nonstandard pthread types. To comply
to the IEEE Standard (1003.1, 2004 edition) the definitions in pthread.h refer to standard POSIX
pthread types (as defined in sys/types.h) only.
If an application module calls a pthread function whose return value or parameters had a
nonstandard type and you want to conform to the standard, logic and data item definitions must
be revised to use the corresponding standard types. If you want to continue to use the nonstandard
types, they are defined in the PUT Model library header put/put_types.h.
Table 12-11 SPT Library Nonstandard Types and Corresponding PUT Model Library Standard Types
SPT Library Nonstandard Type Corresponding PUT Model Library Standard Type

pthread_address_t void *

pthread_addr_t void *

pthread_integer_t int

pthread_startroutine_t void * (*) (void *)

pthread_initroutine_t void (*) (void)

pthread_destructor_t void (*) (void *)

pthread_void_fn_ptr_t void (*) (void)

Global Variables
In contrast to the SPT library, the PUT Model library does not provide these global variables
because these global variables are not specified in the IEEE Standard (1003.1, 2004 edition):
pthread_attr_default
pthread_mutexattr_default
pthread_condattr_default

Concurrency Level Defaults


The PUT Model library has a default concurrency level of 20. The SPT library has a default
concurrency level of 0 (zero).

Differences in Functions and Function Behavior


Nonblocking Function Equivalents to spt_*x and spt_*z Use Standard Names
The PUT model library does not provide analogs to spt_*() functions, such as spt_readz()
or spt_readx(), whose purpose is to be non-blocking alternatives to standard system functions.

Converting Applications that use the SPT Library 375


If an application module contains calls to such a function, you must modify it to refer to the
standard function name, such as read() and you must include the appropriate standard header
file. For more information about these functions, see “Thread-Aware and Nonblocking OSS
Functions” (page 345).

Nonstandard spt_* Functions Have put_* Equivalents


The SPT library provides some non-standard spt_*() and SPT_functions, such as
spt_select_single_np() and SPT_INITRECEIVE(). The PUT Model library provide
analogs to these functions that you can call directly. If an application module contains calls to
such functions, they must be replaced with calls to the equivalent put_*() or PUT_*() function
(for example, put_select_single_np() and PUT_INITRECEIVE()). Such changes are
straightforward because only the function name is different; there is no change to parameter
types or the function semantics. Reference pages for all the put_*() and PUT_*() functions
are included in either the Open System Services System Calls Reference Manual or the Open System
Services Library Calls Reference Manual.
The put/put_extensions.h header file provides the prototypes for nonstandard functions.
If the macro _TANDEM_SOURCE is defined, directly or indirectly, then when the compiler reads
pthread.h it reads put/put_extensions.h as well. Otherwise you must explicitly include
the put/put_extensions.h header file in your application.

Standard pthread_* functions replace some nonstandard pthread_* functions


The PUT Model library provides a few standard pthread_*() functions that replace the nonstandard
versions provided by the SPT library:
Table 12-12 Nonstandard pthread_ functions replaced by standard versions
Nonstandard SPT library function Standard PUT Model library function

pthread_mutexattr_getkind_np() pthread_mutexattr_gettype()

pthread_mutexattr_setkind_np() pthread_mutexattr_settype()

pthread_attr_getguardsize_np() pthread_attr_getguardsize()

pthread_attr_setguardsize_np() pthread_attr_setguardsize()

Header File Locations for Reentrant Functions


The SPT library provides reentrant functions that are thread-safe alternatives to standard functions
whose semantics make their use by a threaded program unsafe. The SPT header file
spt_extensions.h provides the prototypes for all of these functions.
The PUT Model library does not provide any of the reentrant functions. Instead, each such
function is provided by the same public library and header file that provides the non-reentrant
version of the function. For example, the time.h header file defines both the asctime() and
asctime_r() functions. Consequently, each PUT Library module that refers to a reentrant
function must include the appropriate header.

Implementations of getgrent_r() and getpwent_r() Functions


The implementations of functions getgrent_r() and getpwent_r() in the OSS subject API
library (ZSECDLL) conform to the standard and each of these functions have four parameters.
The corresponding SPT functions have only the first three parameters. Consequently the logic
of an application module that calls the getgrent_r() or getpwent_r() function requires
revision. For more information about these functions, see the reference page for the function
either online or in the Open System Services Library Calls Reference Manual.

376 Using the POSIX User Thread (PUT) Model Library


Different Behavior for C Language I/O Functions
The SPT library intercepts calls to C language I/O functions (such as fgetc(), fprintf(), and
so forth) made by SPT application modules and, because it processes certain outcomes internally,
never reports that an operation failed because of a situation in which errno would be set to
EWOULDBLOCK (or to values describing a few other similar situations).
Because the logic of the PUT Model library is different, calls to C language I/O functions can
complete with errno set to values that report that an operation failed but that the operation
might succeed if retried. Consequently, the logic of an application module that calls a C language
I/O function might need to be revised if the input-ouput resource accessed by the applicable
FILE * can terminate with errno set to one of these values. For information about the behaviors
and possible errno values for a function, see the reference page for that function either online
or in the Open System Services Library Calls Reference Manual.
The SPT library functions implement C language I/O behavior by calling the corresponding C
run-time library (RTL) I/O functions. Those C RTL functions perform the actual I/O operations
by calling process-blocking file system functions (for example, fread() calls read() to obtain
data from the file). In contrast, when applications use the PUT Model library, the C RTL I/O
function services calls non-blocking thread-library functions provided by the PUT Model library.
This difference can invalidate application logic that depends upon the behavior of library logic.
For example, assume a client provides a logging facility that, to guarantee the log data written
to the file is contiguous (that is, no other thread can intersperse any data), depends upon output
operations being executed without the possibility of a thread switch:
• Calling fprintf() to output trace data to the log file is safe for an application that uses
the SPT library but not for an application that uses the PUT Model library. An application
that uses the PUT Model library fprintf() logic could call a PUT Model library version
of a write function that initiates a non-blocking output operation and then allows a different
thread to become active.
• To maintain the SPT library behavior, the application logic must change. For example, you
could replace the fprintf() call with a call to sprintf() followed by a call to write().
Note that even this example works only if the logging logic is in an application module
compiled with macro _PUT_MODEL_ undefined. (Compiling the module with macro
_PUT_MODEL_ defined would translate the textual reference to system function write()
into code that calls the PUT non-blocking write function. The behavior would then be
equivalent to that of fprintf().)
An application module could call the SPT variant of a C language I/O function directly; for
example, spt_fread(). Such calls must be replaced with calls to the base function; for example,
fread(). The functions of this kind are:
fclose() fread() putc()
fflush() fwrite() putchar()
fgetc() getc() puts()
fgets() getchar() putw()
fgetwc() gets() putwc()
fprintf() getw() putwchar()
fputc() getwc() vfprintf()
fputs() getwchar() vprintf()
fputwc() printf()

Thread-Aware Signal Handling


An application that uses the SPT library can either enable thread-aware signal handling or leave
this behavior disabled. For an application that uses the PUT Model library, thread-aware signal
handling is always enabled. Consequently, if an application that uses the SPT library is not
prepared to handle signals, converting it to an application that uses the PUT Model library might
require additional logic to handle thread-specific signals.

Converting Applications that use the SPT Library 377


Use of Process Resources
There are many differences in the internal logic of the public libraries that provide run-time
services. The resultant different (potentially dramatically different) patterns of usage of process
resources can have an impact ranging from minor to severe. In particular, implementations of
various functions in public libraries can consume larger amounts of memory when called from
an application that uses the PUT Model library. For example, the function getservent() returns
the address of a struct servent whose content is managed by the INET public library. For
an application that uses the SPT library, every call modifies and returns the address of the same
data space. For application that uses the PUT Model library, the library allocates and manipulates
a separate struct servent data space for each thread. The cumulative impact of all increases
in memory allocated could affect the performance of, or in a severe case lead to the failure of, a
successful application that was converted from using the SPT library to using the PUT Model
library.

Threaded Application Programming


Keeping Application Design Simple
Because of the inherent complexity of multithreaded programming, application designers should
follow these recommendations:
• Write programs with a single application thread when possible.
• Keep multiple application threads independent of each other when possible. If this is not
possible, keep the interdependencies to a minimum.

Threading Considerations
Application designers should be aware of the following general threading considerations when
developing a the PUT Model library application:
• “Sharing Process Resources” (page 378)
• “Using Standard Libraries” (page 378)
• “Addressing the Thread Stack” (page 379)
• “Making Process-Blocking Calls” (page 380)
• “Using Nowait Input or Output” (page 380)
• “Yielding Control” (page 380)
• “Using Signals” (page 335)
• “Spawning a New Process” (page 380)
• “Isolating Faults” (page 380)

Sharing Process Resources


Access by threads to shared process resources such as global data, the heap, and files must be
synchronized using mutexes and condition variables. Table 12-2 (page 332) lists global and private
process resources.

Using Standard Libraries


No Need for Jacket Routines or Special Header Files
On systems running H06.21 or later H-series RVUs or J06.10 or later J-series RVUS, standard
library functions do not require jacket routines, special header files, or other modifications to
make them thread-safe or reentrant.

378 Using the POSIX User Thread (PUT) Model Library


Jacket Routines for Functions Related to Pathway or TMF
The PUT Model library does provide jacket routines for calls to Pathway servers
(SERVERCLASS_SEND and SERVERCLASS_SEND_INFO) and for TMF transactions, as described
in “Jacket Routines (Nonblocking Versions of SEVERCLASS_ and TMF System Calls)” (page 368).

Asynchronous Cancels are Possible


The PUT Model library supports the asynchronous receipt of cancel requests; a thread can exit
from a standard library due to cancellation (see “Thread Safety” (page 356)). Therefore, if you
want to prevent cancellation, you must disable cancellation before making calls to library functions
that contain cancellation points or potential cancellation points.

Beware of Pointers to Static Library Data


Functions that are not thread-aware might return pointers to static data. In this case, one thread
could invalidate another thread’s pointer. For example, in an application that uses the PUT Model
library, the getenv() function returns a pointer to environmental information contained in a
static variable in the library. The content of this variable can be changed by any thread.
When using functions that return pointers to static library data, immediately copy the data to
thread-private memory.
Most of the standard library functions follow the POSIX standard to protect thread safety when
PUT library is used. For more information about thread safety, see “Thread Safety” (page 356).

Beware of Libraries That Maintain Context Across Calls


Most of the standard library functions maintain thread-specific data and context when you use
the PUT Model library. For more information about thread safety, see “Thread Safety” (page 356).
For non-thread-safe standard library functions, you can use a mutex to protect implicit context
maintained by a standard library, for example by bracketing a series of library calls with the lock
and unlock of a mutex. This technique should be used only for short periods of time.
Standard libraries that use an explicit handle to identify the intended context on each call can be
used without interference between threads. File operations that use file descriptors follow this
model.
Some libraries allow multiple contexts but do not support explicit context identification on all
calls. Instead, the library allows the caller to establish a current context for the process. With
these libraries, the application is responsible for ensuring that the correct context is made current
while a thread is executing. For example, the TMF transaction-demarcation jacket routines use
this method, relying on an implicit current transaction for the process.

Addressing the Thread Stack


Memory for function variables that are not declared static is allocated from the thread-private
stack. This memory is addressable only while the thread is executing. It is not addressable by
other threads; attempting to read or write variables located in another thread’s stack causes
unpredictable results.
All program data that is to be shared by multiple threads must be external data, static internal
data, or data allocated from the heap. This data should be protected by a mutex, as appropriate.
The Standard provides a set of functions to manage thread-specific data. One use of these functions
is to maintain thread global data, such as state. The interface allows you to declare destructor
functions that are invoked at thread run-down. These functions are distinct from cancellation
clean-up handlers.
The PUT Model library uses a protected stack for signals (see “Signals and Signal Handling”
(page 334)).

Threaded Application Programming 379


Making Process-Blocking Calls
When a thread calls a Guardian procedure that blocks the process, all other threads in the process
are also prevented from executing. If a thread is blocked for a significant period of time, it can
delay or even prevent the execution of time-critical run-time functions.
Examples of programs that can block include:
• Pathway servers, which can wait indefinitely while reading $RECEIVE
• The Inspect, Native Inspect, and Visual Inspect symbolic debuggers, whose use can block
a process indefinitely

Using Nowait Input or Output


Programs that use threads cannot call the Guardian AWAITIO or AWAITIOX procedure with
-1 as a file parameter (applying the call to the oldest incomplete operation pending on each file).
AWAITIOX can be used to poll for completion on a specific file, although a thread must complete
all nowait input or output operations before yielding control to another thread. In summary:
• No calls to AWAITIO[X]() with a file number of -1 are made outside of pthreads.
• No calls to AWAITIO[X]() with a file number registered with pthreads are made outside
of pthreads.

Yielding Control
Because the PUT Model library are never preempted, a call to the sched_yield() function
might be needed to allow time-critical run-time threads to execute. This function releases the
processor to another thread of the same or higher priority. The calling thread may get control
immediately if no threads of the same or higher priority are ready to run.
Be careful using the sched_yield() function. Misuse causes unnecessary context switching,
which increases overhead without allowing the other threads to execute. For example, it is
counterproductive for a thread to yield control while it has a needed resource locked.

Spawning a New Process


Using the fork() or tdm_fork() function in a multithreaded environment can cause problems.
Applications can use either of these functions safely as follows: A parent process that has already
called a function can also use either of the fork functions to create a child process if the child
process calls any of the exec functions, the tdm_execve(), or tdm_execep() function
immediately upon its creation.
A threaded application might alternatively use pthread_atfork() to declare as many as three
fork handlers: a prepare handler called before the fork, a parent handler called after the fork in
the parent process, and a child handler called after the fork in the child process.
When a fork is called, only the calling thread is duplicated in the child process. The expected
usage of pthread_atfork() is for the prepare handler to acquire all mutex locks of interest
to the child, and the other two fork handlers to release them.

Isolating Faults
Because all threads created by a process share the process address space, there is no address
space protection between the application threads in a process. One application thread can corrupt
data, causing other threads or the entire process to fail.

380 Using the POSIX User Thread (PUT) Model Library


Single Versus Multiple Application Threads
OSS threaded applications can be classified as follows, in order of increasing complexity:
• “Programs With a Single Application Thread” (page 381)
• “Programs With Multiple Independent Application Threads” (page 381)
• “Programs With Multiple Interdependent Application Threads” (page 382)

Programs With a Single Application Thread


Externally, programs with a single application thread behave like standard, sequential
(nonthreaded) programs. The program begins execution in the main() procedure; it then calls
other procedures that, in turn, can call still other procedures. This type of application includes
simple OSS client programs.
In single-threaded applications:
• Process resources can be used freely.
No synchronization is needed. The application can freely use process resources such as
process and module globals, the heap, file descriptors, SQL cursors, and the signal mask.
Mutexes and condition variables are not needed.
• Standard libraries can be used freely.
The application can share access to library data, including implicit context maintained across
multiple library calls. For example, the application thread can use the TMF transaction jacket
routines and no other thread can change the current transaction of the process.
• One application thread cannot block another from executing. Process-blocking operations
have minimal effect.
• One application thread cannot corrupt another.
The thread does not share its address space with any other application threads. The
application thread is protected by the address-space protection provided for the process,
offering fault isolation.
The following general threading considerations affect single-threaded applications but have less
effect than for processes with multiple application threads:
• Using process-blocking calls
Although process-blocking calls will not affect other will not affect other application threads,
they can interfere with time-critical threads.
• Isolating faults and yielding control
If the application thread can execute for long periods (more than a second) without
relinquishing control, the application might still need to use the sched_yield() function
to allow time-critical threads to execute.
These general threading considerations apply to single-threaded applications:
• Using nowait input or output as described in “Using Nowait Input or Output” (page 380).
• Spawning a process as discussed in “Spawning a New Process” (page 380).

Programs With Multiple Independent Application Threads


Programs containing multiple threads can improve performance by providing concurrent
execution. An application thread is independent if it does not explicitly share application resources
that exist in the process environment, such as application file opens, SQL cursors, or modifiable
application data structures.
This type of application includes simple OSS servers that maintain the application state in a
database. Such a server simplifies server design because then application state does not need to
be maintained in the server and thus most servers can be context-free. In cases where context

Threaded Application Programming 381


must be maintained across multiple requests, the context is generally private to the client and
should not be shared.
“Threading Considerations” (page 378) describes some considerations for developing an
application with multiple application threads.

Programs With Multiple Interdependent Application Threads


An application thread is interdependent if it shares application resources that exist in the process
environment, such as application file opens, SQL cursors, and modifiable application data
structures. Applications with multiple interdependent application threads must synchronize
access to the shared application resources.
This type of application includes OSS servers that maintain application state in the server to
improve performance or that share resources, such as file opens, to reduce resource consumption.
This type of application also includes client programs that use parallelism.
Programs with multiple interdependent application threads can be synchronized by using
mutexes to reserve access to a shared resource and by using condition variables to wait for a
shared resource to be in a certain state.
Poor performance can result if inappropriate synchronization techniques are used. Synchronizing
at too coarse a level can overly restrict concurrency and cause a server to serialize processing,
dramatically increasing the application’s service time. Synchronizing at too fine a level can result
in an increase in the processor cycles spent on initializing, obtaining, and releasing mutexes and
dispatching threads.

Threaded Application Examples


The following example application creates a threaded time-of-day server socket that listens for
connections and upon connection, creates a thread to handle the connection.

382 Using the POSIX User Thread (PUT) Model Library


Example 12-20 Threaded Time-of-Day Server Socket

/* Threaded time-of day server socket. */


/* If compiled for TNS/E, specify the ZPUTDLL, */
/* the standard POSIX threads shared run-time library. */

#define _PUT_MODEL_
#define _XOPEN_SOURCE_EXTENDED 1
#include <assert.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <strings.h>
#include <stdlib.h>
#include <string.h>

/*
Defines thread-aware functions calls to the threads package:
*/

#include <pthread.h>

/*
Defines a short macro to convert file descriptors to non-blocking
(thread-aware functions are thread-aware only if the file descriptor
is non-blocking):
*/

#define fd_make_nonblock(fd) \
assert(fcntl(fd,F_SETFL,fcntl(fd,F_GETFL)|O_NONBLOCK) != -1)

/*
Defines the port the server will run on:
*/

#define SERVER_PORT 3000

/*
Shows the worker thread that is created after each accept:
*/

void *worker_thread(void* sock_fd)


{

char buffer[1024];
time_t now;

time(&now);
strcpy(buffer, ctime(&now));
send(*(int *)sock_fd, &buffer, strlen(buffer), 0);
close(*(int *)sock_fd);
return NULL;
}

int main(int argc, char *argv[])

{
int inet_addr_port = SERVER_PORT;
int sock=-1,accept_fd=-1;
size_t size;
struct sockaddr_in servaddr, accept_addr;

Threaded Application Programming 383


/*
Defines one pthread_t per request we intend to handle:
*/

pthread_t my_thread;
pthread_attr_t my_attr;

/*
Turns on concurrency:
*/

if(pthread_setconcurrency(1))
{
perror("pthread_setconcurrency");
exit(-1);
}

/*
Initializes attribute:
*/

if(pthread_attr_init(&my_attr))
{
perror("pthread_attr_init");
exit(-1);
}

/*
Sets detach Attribute:
*/

if(pthread_attr_setdetachstate(&my_attr,PTHREAD_CREATE_DETACHED))
{
perror("pthread_attr_setdetachstate");
exit(-1);
}

/*
Creates socket:
*/

if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)


{
perror("Socket Error");
exit(-1);
}

/*
Sets up Bind:
*/

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(inet_addr_port);

if (bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)

{
perror("Bind Error");
exit(-1);
}

fd_make_nonblock(sock);

384 Using the POSIX User Thread (PUT) Model Library


/*
Sets socket to listen:
*/

if (listen(sock, 1) < 0)
{
perror("Listen Error");
exit(-1);
}

/*
Starts server:
*/

while(1)

{
bzero(&accept_addr, sizeof(accept_addr));
accept_fd = accept(sock, NULL, NULL);
if (accept_fd < 0)
{
perror("Accept Error");
exit(-1);
}

/*
Dispatches a thread to handle service request:
*/

if(pthread_create(&my_thread,&my_attr,&worker_thread,&accept_fd))
{
perror("pthread_create");
exit(-1);
}
} /* while */
}/* main */

Example 12-21 (page 386) also creates a threaded time-of-day server socket, but using $RECEIVE.

Threaded Application Programming 385


Example 12-21 Threaded Time-of-Day Server Socket Using $RECEIVE

#define _PUT_MODEL_
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
#include <cextdecs.h(FILE_OPEN_,READX,FILE_CLOSE_,WRITEX,FILE_GETINFO_)>
#include <cextdecs.h(FILE_GETRECEIVEINFO_)>
#include <cextdecs.h(REPLYX)>
#include <cextdecs.h(READUPDATEX)>
#include “myio.h” /** contains my_printf which is process-blocking**/

/*
Must come after cextdecs.h:
*/
#include <pthread.h>

void * server_thread(void* target)


{
char buffer[1024];
time_t now;
int error;

time(&now);
strcpy(buffer, ctime(&now));

/*
A compiler warning will occur regarding the next line, which is OK:
*/

error = put_REPLYX(buffer, (short) strlen(buffer), NULL,


(short)target, 0);

my_fprintf(stderr,"server_thread: put_REPLYX: error: %d\n",error);


fflush(stderr);
return NULL;
}

int main(void)
{

pthread_t my_thread;
pthread_attr_t my_attr;
char *filename = "$RECEIVE";
char buffer[1024];
long bytesread, error;
short receive_info[17];
short dialog_info;
short target;
short filenum;

/*
Sets concurency level:
*/

if(pthread_setconcurrency(1))
{
perror("pthread_setconcurency");
exit(-1);
}

/*
Initializes attribute:
*/

if(pthread_attr_init(&my_attr))

{
perror("pthread_attr_init");
exit(-1);
}

386 Using the POSIX User Thread (PUT) Model Library


/*
Sets detach state for thread attribute:
*/

if(pthread_attr_setdetachstate(&my_attr,PTHREAD_CREATE_DETACHED)!=0)

{
perror("pthread_attr_setdetachstate");
exit(-1);
}

error = FILE_OPEN_(filename, (short)strlen(filename), &filenum,


0, , 1, 10, 1);
my_fprintf(stderr,"main: FILE_OPEN_: error: %d\n",error);
assert(error == 0);
error = put_INITRECEIVE(filenum, 10);
my_fprintf(stderr,"main: put_INITRECEIVE: error: %d\n",error);
fflush(stderr);
assert(error == 0);

while (1)

{
error = put_RECEIVEREAD(filenum, buffer, (short)sizeof(buffer),
&bytesread, -1, receive_info, &dialog_info);
my_fprintf(stderr,"main_thread: put_RECEIVEREAD: error: %d\n",error);

target = receive_info[2];

if(pthread_create(&my_thread, &my_attr, &server_thread,


(void *)target))

{
perror("pthread_create");
exit(-1);
}

} /* while */
} /* main */

Threaded Application Programming 387


388
A Documented OSS Functions
This appendix lists the following information for each OSS function.

Function The name of the OSS function.

Reference Where the function is documented:

Library The hard-copy reference page for the function is in the Open System Services
Library Calls Reference Manual.

System The hard-copy reference page for the function is in the Open System Services
System Calls Reference Manual.

HP Information about the HP implementation of the function:

Yes The function is either an HP extension or the HP implementation varies from


the POSIX standard or XPG4 specification.

Extended The function can also return extended errors.

Native Only TNS/R, TNS/E The function is restricted to only the TNS/R and TNS/E native environments.

TNS/E The function is restricted to the TNS/E native environment. It is not supported
in the TNS/R native environment.

RVU Notes H06.nn Support for this function was added after the H06.03 RVU, beginning with the
RVU listed. If there is no G-series RVU listed, this function is not supported
on G-series RVUs. If there is no J-series RVU listed, this function is not
supported on J-series RVUs.

G06.nn Support for this function was added after the G06.25 RVU, beginning with the
RVU listed. If there is no H-series RVU listed, this function is not supported
on H-series RVUs. If there is no J-series RVU listed, this function is not
supported on J-series RVUs.

J06.nn Support for this function was added after the J06.03 RVU, beginning with the
RVU listed. If there is no H-series RVU listed, this function is not supported
on H-series RVUs. If there is no G-series RVU listed, this function is not
supported on G-series RVUs.

[blank] Support for this function for H-series RVUs began with the H06.03 RVU.
Support for this function for G-series RVUs began with or before the G06.25
RVU. Support for this function on J-series RVUs began with the J06.03 RVU.

Function Reference HP Native Only RVU Notes

a64l() Library TNS/R, TNS/E

abort() Library

_abs() Library

abs() Library

accept() System Extended

access() System Yes

acl() System Yes TNS/R, TNS/E G06.28, H06.08,


J06.03

aclsort() Library Yes TNS/R, TNS/E G06.28, H06.08,


J06.03

acos() Library

acosf() Library TNS/E H06.21, J06.10

389
Function Reference HP Native Only RVU Notes

acosh() Library Yes TNS/R, TNS/E

acoshf() Library TNS/E H06.21, J06.10

acoshl() Library TNS/E H06.21, J06.10

acosl() Library TNS/E H06.21, J06.10

advance() Library TNS/R, TNS/E

alarm() Library Yes

asctime() Library

asctime_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

asin() Library

asinf() Library TNS/E H06.21, J06.10

asinh() Library Yes TNS/R, TNS/E

asinhf() Library TNS/E H06.21, J06.10

asinhl() Library TNS/E H06.21, J06.10

asinl() Library TNS/E H06.21, J06.10

assert() Library Yes

atan() Library

atanf() Library TNS/E H06.21, J06.10

atanh() Library Yes TNS/R, TNS/E

atanhf() Library TNS/E H06.21, J06.10

atanhl() Library TNS/E H06.21, J06.10

atanl() Library TNS/E H06.21, J06.10

atan2() Library

atan2f() Library TNS/E H06.21, J06.10

atan2l() Library TNS/E H06.21, J06.10

atexit() Library

atof() Library

atoi() Library

atol() Library

atoll() Library

basename() Library TNS/R, TNS/E

bcmp() Library TNS/R, TNS/E

bcopy() Library TNS/R, TNS/E

bind() System Extended

bsearch() Library

btowc() Library TNS/E H06.08, J06.03

bzero() Library TNS/R, TNS/E

390 Documented OSS Functions


Function Reference HP Native Only RVU Notes

cabs() Library TNS/E H06.21, J06.10

cabsf() Library TNS/E H06.21, J06.10

cabsl() Library TNS/E H06.21, J06.10

cacos() Library TNS/E H06.21, J06.10

cacosf() Library TNS/E H06.21, J06.10

cacosh() Library TNS/E H06.21, J06.10

cacoshf() Library TNS/E H06.21, J06.10

cacoshl() Library TNS/E H06.21, J06.10

cacosl() Library TNS/E H06.21, J06.10

ca11oc() Library Yes

carg() Library TNS/E H06.21, J06.10

cargf() Library TNS/E H06.21, J06.10

cargl() Library TNS/E H06.21, J06.10

casin() Library TNS/E H06.21, J06.10

casinf() Library TNS/E H06.21, J06.10

casinh() Library TNS/E H06.21, J06.10

casinhf() Library TNS/E H06.21, J06.10

casinhl() Library TNS/E H06.21, J06.10

casinl() Library TNS/E H06.21, J06.10

catan() Library TNS/E H06.21, J06.10

catanf() Library TNS/E H06.21, J06.10

catanh() Library TNS/E H06.21, J06.10

catanhf() Library TNS/E H06.21, J06.10

catanhl() Library TNS/E H06.21, J06.10

catanl() Library TNS/E H06.21, J06.10

catclose() Library

catgets() Library

catopen() Library

cbrt() Library TNS/R, TNS/E

cbrtf() Library TNS/E H06.21, J06.10

cbrtl() Library TNS/E H06.21, J06.10

ccos() Library TNS/E H06.21, J06.10

ccosf() Library TNS/E H06.21, J06.10

ccosh() Library TNS/E H06.21, J06.10

ccoshf() Library TNS/E H06.21, J06.10

ccoshl() Library TNS/E H06.21, J06.10

ccosl() Library TNS/E H06.21, J06.10

391
Function Reference HP Native Only RVU Notes

ceil() Library Yes

ceilf() Library TNS/E H06.21, J06.10

ceill() Library TNS/E H06.21, J06.10

cexp() Library TNS/E H06.21, J06.10

cexpf() Library TNS/E H06.21, J06.10

cexpl() Library TNS/E H06.21, J06.10

cfgetispeed() Library

cfgetospeed() Library

cfsetispeed() Library

cfsetospeed() Library

chdir() System Extended

chmod() System Extended

chown() System Extended

chroot() System Yes

chvol() Library

cimag() Library TNS/E H06.21, J06.10

cimagf() Library TNS/E H06.21, J06.10

cimagl() Library TNS/E H06.21, J06.10

clearerr() Library

clock() Library Yes

clog() Library TNS/E H06.21, J06.10

clogf() Library TNS/E H06.21, J06.10

clogl() Library TNS/E H06.21, J06.10

close() System Yes

closedir() Library Extended

closelog() Library

compile() Library TNS/R, TNS/E

confstr() Library

conj() Library TNS/E H06.21, J06.10

conjf() Library TNS/E H06.21, J06.10

conjl() Library TNS/E H06.21, J06.10

connect() System Extended

copysign() Library TNS/R, TNS/E

copysignf() Library TNS/E H06.21, J06.10

copysignl() Library TNS/E H06.21, J06.10

cos() Library

cosf() Library TNS/E H06.21, J06.10

392 Documented OSS Functions


Function Reference HP Native Only RVU Notes

cosh() Library

coshf() Library TNS/E H06.21, J06.10

coshl() Library TNS/E H06.21, J06.10

cosl() Library TNS/E H06.21, J06.10

cpow() Library TNS/E H06.21, J06.10

cpowf() Library TNS/E H06.21, J06.10

cpowl() Library TNS/E H06.21, J06.10

cproj() Library TNS/E H06.21, J06.10

cprojf() Library TNS/E H06.21, J06.10

cprojl() Library TNS/E H06.21, J06.10

creal() Library TNS/E H06.21, J06.10

crealf() Library TNS/E H06.21, J06.10

creall() Library TNS/E H06.21, J06.10

creat() System

creat64() System Yes G06.29, H06.06,


J06.03

crypt() Library Yes TNS/R, TNS/E

csin() Library TNS/E H06.21, J06.10

csinf() Library TNS/E H06.21, J06.10

csinh() Library TNS/E H06.21, J06.10

csinhf() Library TNS/E H06.21, J06.10

csinhl() Library TNS/E H06.21, J06.10

csinl() Library TNS/E H06.21, J06.10

csqrt() Library TNS/E H06.21, J06.10

csqrtf() Library TNS/E H06.21, J06.10

csqrtl() Library TNS/E H06.21, J06.10

ctan() Library TNS/E H06.21, J06.10

ctanf() Library TNS/E H06.21, J06.10

ctanh() Library TNS/E H06.21, J06.10

ctanhf() Library TNS/E H06.21, J06.10

ctanhl() Library TNS/E H06.21, J06.10

ctanl() Library TNS/E H06.21, J06.10

ctermid() Library Extended

ctermid_r() Library Extended TNS/R, TNS/E G06.28, H06.05,


J06.03

ctime() Library

ctime_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

393
Function Reference HP Native Only RVU Notes

cuserid() Library Extended TNS/R, TNS/E

dbm_clearerr() Library Extended TNS/R, TNS/E

dbm_close() Library Extended TNS/R, TNS/E

dbm_delete() Library Extended TNS/R, TNS/E

dbm_error() Library Extended TNS/R, TNS/E

dbm_fetch() Library Extended TNS/R, TNS/E

dbm_firstkey() Library Extended TNS/R, TNS/E

dbm_nextkey() Library Extended TNS/R, TNS/E

dbm_open() Library Extended TNS/R, TNS/E

dbm_store() Library Extended TNS/R, TNS/E

dec_to_longlong() Library Yes

difftime() Library

dirname() Library Yes TNS/R, TNS/E

div() Library

dlclose() Library TNS/R, TNS/E

dlerror() Library TNS/R, TNS/E

dlopen() Library TNS/R, TNS/E

dlresultcode() Library Yes TNS/R, TNS/E

dlsym() Library TNS/R, TNS/E

drand48() Library

dup() System Yes

dup2() System Yes

ecvt() Library

edfseek() Library Yes

edftell() Library Yes

encrypt() Library Yes TNS/R, TNS/E

endgrent() Library Yes TNS/R, TNS/E

endhostent() Library Yes TNS/R, TNS/E

endnetent() Library Yes TNS/R, TNS/E

endprotoent() Library Yes TNS/R, TNS/E

endpwent() Library

endservent() Library Yes TNS/R, TNS/E

erand48() Library

erf() Library TNS/R, TNS/E

erfc() Library TNS/R, TNS/E

erfcf() Library TNS/E H06.21, J06.10

erfcl() Library TNS/E H06.21, J06.10

394 Documented OSS Functions


Function Reference HP Native Only RVU Notes

erff() Library TNS/E H06.21, J06.10

erfl() Library TNS/E H06.21, J06.10

exec() System

execl() System Extended

execle() System Extended

execlp() System Extended

execv() System Extended

execve() System Extended

execvp() System Extended

_exit() System Yes

_Exit() Library TNS/E H06.08, J06.03

exit() Library

exp() Library

expf() Library TNS/E H06.21, J06.10

expl() Library TNS/E H06.21, J06.10

expm1() Library Extended TNS/R, TNS/E

expm1f() Library TNS/E H06.21, J06.10

expm1l() Library TNS/E H06.21, J06.10

exp2() Library TNS/E H06.21, J06.10

exp2f() Library TNS/E H06.21, J06.10

exp2l() Library TNS/E H06.21, J06.10

fabs() Library Yes

fabsf() Library TNS/E H06.21, J06.10

fabsl() Library TNS/E H06.21, J06.10

fchmod() System Extended G06.28, H06.05,


J06.03

fchown() System Extended G06.28, H06.05,


J06.03

fclose() Library Extended

fcntl() System Extended

fcvt() Library TNS/R, TNS/E

fdim() Library TNS/E H06.21, J06.10

fdimf() Library TNS/E H06.21, J06.10

fdiml() Library TNS/E H06.21, J06.10

fdopen() Library

feclearexcept() Library TNS/E H06.21, J06.10

fegetenv() Library TNS/E H06.21, J06.10

fegetexceptflag() Library TNS/E H06.21, J06.10

395
Function Reference HP Native Only RVU Notes

fegetround() Library TNS/E H06.21, J06.10

feholdexcept() Library TNS/E H06.21, J06.10

feof() Library

feraiseexcept() Library TNS/E H06.21, J06.10

ferror() Library

fesetenv() Library TNS/E H06.21, J06.10

fesetexceptflag() Library TNS/E H06.21, J06.10

fesetround() Library TNS/E H06.21, J06.10

fetestexcept() Library TNS/E H06.21, J06.10

feupdateenv() Library TNS/E H06.21, J06.10

fflush() Library Extended

ffs() Library TNS/R, TNS/E

fgetc() Library Extended

fgetpos() Library Extended

fgetpos64() Library Yes G06.29, H06.06,


J06.03

fgets() Library Extended

fgetwc() Library Extended

fgetws() Library Extended

fileno() Library

finite() Library Yes TNS/R, TNS/E

flockfile() Library TNS/E H06.21, J06.10

floor() Library

floorf() Library TNS/E H06.21, J06.10

floorl() Library TNS/E H06.21, J06.10

fma() Library TNS/E H06.21, J06.10

fmaf() Library TNS/E H06.21, J06.10

fmal() Library TNS/E H06.21, J06.10

fmax() Library TNS/E H06.21, J06.10

fmaxf() Library TNS/E H06.21, J06.10

fmaxl() Library TNS/E H06.21, J06.10

fmin() Library TNS/E H06.21, J06.10

fminf() Library TNS/E H06.21, J06.10

fminl() Library TNS/E H06.21, J06.10

fmod() Library Yes

fmodf() Library TNS/E H06.21, J06.10

fmodl() Library TNS/E H06.21, J06.10

396 Documented OSS Functions


Function Reference HP Native Only RVU Notes

fmtmsg() Library TNS/R, TNS/E

fnmatch() Library Extended

fopen() Library

fopen_guardian() Library Yes

fopen_oss() Library Yes

fopen_std_file() Library Yes

fopen64() Library Yes G06.29, H06.06,


J06.03

fopen64_guardian() Library Yes G06.29, H06.06,


J06.03

fopen64_oss() Library Yes G06.29, H06.06,


J06.03

fopen64_std_file() Library Yes G06.29, H06.06,


J06.03

fork() System Extended

fp_class() Library Yes TNS/R, TNS/E

fpathconf() Library Extended

fpclassify() Library TNS/E H06.21, J06.10

fprintf() Library Yes

fputc() Library Extended

fputs() Library Extended

fputwc() Library Extended

fputws() Library Extended

fread() Library Extended

free() Library

freeaddrinfo() Library Yes

freehostent() Library Yes

freopen() Library

freopen_guardian() Library Yes

freopen_oss() Library Yes

freopen64() Library Yes G06.29, H06.06,


J06.03

freopen64_guardian() Library Yes G06.29, H06.06,


J06.03

freopen64_oss() Library Yes G06.29, H06.06,


J06.03

frexp() Library

frexpf() Library TNS/E H06.21, J06.10

frexpl() Library TNS/E H06.21, J06.10

fscanf() Library Yes

397
Function Reference HP Native Only RVU Notes

fseek() Library Yes

fseeko() Library Yes G06.29, H06.06,


J06.03

fseeko64() Library Yes G06.29, H06.06,


J06.03

fsetpos() Library

fsetpos64() Library Yes G06.29, H06.06,


J06.03

fstat() System Extended

fstat64() System Yes G06.29, H06.06,


J06.03

fstatvfs() System Yes

fstatvfs64() System Yes

fsync() System Extended

ftell() Library Extended

ftello64() Library Yes G06.29, H06.06,


J06.03

ftime() Library TNS/R, TNS/E

ftok() Library Extended

ftruncate() System Yes

ftruncate64() System Yes G06.29, H06.06,


J06.03

ftrylockfile() Library TNS/E H06.21, J06.10

ftw() Library Extended

ftw64() Library Yes G06.29, H06.06,


J06.03

funlockfile() Library TNS/E H06.21, J06.10

fwide() Library TNS/E H06.08, J06.03

fwprintf() Library TNS/E H06.08, J06.03

fwrite() Library Extended

fwscanf() Library TNS/E H06.08, J06.03

gai_strerror() Library Yes

gamma() Library

gamma_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

gcvt() Library TNS/R, TNS/E

get_assign_msg() Library Yes

get_assign_msg_by_name() Library Yes

get_max_assign_msg_ordinal() Library Yes

get_param_by_name() Library Yes

get_param_msg() Library Yes

398 Documented OSS Functions


Function Reference HP Native Only RVU Notes

get_startup_msg() Library Yes

getaddrinfo() Library Yes

getc() Library Extended

getc_unlocked() Library Extended TNS/E H06.21, J06.10

getchar() Library Extended

getchar_unlocked() Library Extended TNS/E H06.21, J06.10

getcwd() Library Extended

getdate() Library TNS/R, TNS/E

getdtablesize() Library TNS/R, TNS/E

getegid() System

getenv() Library Yes

getenv_r() Library Yes TNS/E H06.21, J06.10

geteuid() System

getgid() System

getgrent() Library Extended TNS/R, TNS/E

getgrent_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

getgrgid() Library Extended

getgrgid_r() Library Extended TNS/R, TNS/E G06.28, H06.05,


J06.03

getgrnam() Library Extended

getgrnam_r() Library Extended TNS/R, TNS/E G06.28, H06.05,


J06.03

getgroups() System

gethostbyaddr() Library Yes TNS/R, TNS/E

gethostbyaddr_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

gethostbyname() Library Yes TNS/R, TNS/E

gethostbyname_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

gethostbyname2() Library Yes TNS/R, TNS/E H06.05, G06.27

gethostent() Library Yes TNS/R, TNS/E

gethostent_r() Library Yes TNS/R, TNS/E

gethostid() Library Yes TNS/R, TNS/E

gethostname() System TNS/R, TNS/E

getipnodebyaddr() Library Yes

getipnodebyname() Library Yes

getlogin() Library Extended

getlogin_r() Library TNS/R, TNS/E G06.28, H06.05,


J06.03

399
Function Reference HP Native Only RVU Notes

getnameinfo() Library Yes

getnetbyaddr() Library Yes TNS/R, TNS/E

getnetbyaddr_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

getnetbyname() Library Yes TNS/R, TNS/E

getnetbyname_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

getnetent() Library Yes TNS/R, TNS/E

getnetent_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

getopt() Library

getpagesize() Library TNS/R, TNS/E

getpass() Library

getpeername() System Extended TNS/R, TNS/E

getpgid() System Extended TNS/R, TNS/E

getpgrp() System

getpid() System

getppid() System

getpriority() System Extended TNS/R, TNS/E

getprotobyname() Library Yes TNS/R, TNS/E

getprotobyname_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

getprotobynumber() Library Yes TNS/R, TNS/E

getprotobynumber_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

getprotoent() Library Yes TNS/R, TNS/E

getprotoent_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

getpwent() Library Yes

getpwent_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

getpwnam() Library Extended

getpwnam_r() Library Extended TNS/R, TNS/E G06.28, H06.05,


J06.03

getpwuid() Library Extended

getpwuid_r() Library Extended TNS/R, TNS/E G06.28, H06.05,


J06.03

gets() Library Extended

getservbyname() Library Yes TNS/R, TNS/E

getservbyname_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

400 Documented OSS Functions


Function Reference HP Native Only RVU Notes

getservbyport() Library Yes TNS/R, TNS/E

getservbyport_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

getservent() Library Yes TNS/R, TNS/E

getservent_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

getsid() System Extended H06.07, G06.29

getsockname() System Extended TNS/R, TNS/E

getsockopt() System Extended TNS/R, TNS/E

getsubopt() Library TNS/R, TNS/E

gettimeofday() System Yes

getuid() System

getw() Library Extended

getwc() Library Extended

getwchar() Library Extended

getwd() Library TNS/R, TNS/E

getws() Library Extended

gfileno() Library Yes

glob() Library Extended

globfree() Library

gmtime() Library

gmtime_r() Library TNS/R, TNS/E G06.28, H06.05,


J06.03

HBA_CloseAdapter() Library TNS/E

HBA_FreeLibrary() Library TNS/E

HBA_GetAdapterAttributes() Library TNS/E

HBA_GetAdapterName() Library TNS/E

HBA_GetAdapterPortAttributes() Library TNS/E

HBA_GetDiscoveredPortAttributes() Library TNS/E

HBA_GetFcpTargetMapping() Library TNS/E

HBA_GetNumberOfAdapters() Library TNS/E

HBA_GetPortStatistics() Library TNS/E

HBA_GetVersion() Library TNS/E

HBA_LoadLibrary() Library TNS/E

HBA_OpenAdapter() Library TNS/E

HBA_RefreshInformation() Library TNS/E

hcreate() Library

hdestroy() Library

401
Function Reference HP Native Only RVU Notes

heap_check() Library Yes

heap_check_always() Library Yes

heap_min_block_size() Library Yes

hsearch() Library

htonl() Library

htons() Library

hypot() Library

hypotf() Library TNS/E H06.21, J06.10

hypotl() Library TNS/E H06.21, J06.10

iconv() Library

iconv_close() Library

iconv_open() Library

if_freenameindex() Library

if_indextoname() Library

if_nameindex() Library

if_nametoindex() Library

ilogb() Library TNS/R, TNS/E

ilogbf() Library TNS/E H06.21, J06.10

ilogbl() Library TNS/E H06.21, J06.10

imaxabs() Library TNS/E H06.08, J06.03

imaxdiv() Library TNS/E H06.08, J06.03

index() Library TNS/R, TNS/E

inet_addr() Library Yes TNS/R, TNS/E

inet_lnaof() Library TNS/R, TNS/E

inet_makeaddr() Library TNS/R, TNS/E

inet_netof() Library TNS/R, TNS/E

inet_network() Library TNS/R, TNS/E

inet_ntoa() Library TNS/R, TNS/E

inet_ntop() Library Yes

inet_pton() Library Yes

initgroups() Library Yes TNS/R, TNS/E H06.18, J06.07

initstate() Library TNS/R, TNS/E

insque() Library TNS/R, TNS/E

ioctl() System Extended

isalnum() Library

isalpha() Library

isascii() Library

402 Documented OSS Functions


Function Reference HP Native Only RVU Notes

isatty() Library Extended

isblank() Library TNS/E H06.08

iscntrl() Library

isdigit() Library

isfinite() Library TNS/E H06.21, J06.10

isgraph() Library

isgreater() Library TNS/E H06.21, J06.10

isgreaterequal() Library TNS/E H06.21, J06.10

isinf() Library TNS/E H06.21, J06.10

isless() Library TNS/E H06.21, J06.10

islessequal() Library TNS/E H06.21, J06.10

islessgreater() Library TNS/E H06.21, J06.10

islower() Library

isnan() (function) Library

isnan() (macro) Library TNS/E H06.21, J06.10

isnormal() Library TNS/E H06.21, J06.10

isprint() Library

ispunct() Library

isspace() Library

isunordered() Library TNS/E H06.21, J06.10

isupper() Library

iswalnum() Library

iswalpha() Library

iswblank() Library TNS/E H06.08, J06.03

iswcntrl() Library

iswctype() Library

iswdigit() Library

iswgraph() Library

iswlower() Library

iswprint() Library

iswpunct() Library

iswspace() Library

iswupper() Library

iswxdigit() Library

isxdigit() Library

j0() Library

j1() Library

403
Function Reference HP Native Only RVU Notes

jn() Library

jrand48() Library

kill() System Extended

l64a() Library TNS/R, TNS/E

labs() Library

lchmod() System Yes G06.28, H06.05,


J06.03

lchown() System Extended G06.28, H06.05,


J06.03

lcong48() Library

ldexp() Library

ldexpf() Library TNS/E H06.21, J06.10

ldexpl() Library TNS/E H06.21, J06.10

ldiv() Library

lfind() Library

lgamma() Library

lgammaf() Library TNS/E H06.21, J06.10

lgammal() Library TNS/E H06.21, J06.10

lgamma_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

link() System Extended

listen() System Extended TNS/R, TNS/E

llabs() Library TNS/E H06.03, J06.03

lldiv() Library

llrint() Library TNS/E H06.21, J06.10

llrintf() Library TNS/E H06.21, J06.10

llrintl() Library TNS/E H06.21, J06.10

llround() Library TNS/E H06.21, J06.10

llroundf() Library TNS/E H06.21, J06.10

llroundl() Library TNS/E H06.21, J06.10

localeconv() Library

localtime() Library

localtime_r() Library TNS/R, TNS/E G06.28, H06.05,


J06.03

log() Library

logb() Library Extended TNS/R, TNS/E

logbf() Library Extended TNS/E H06.21, J06.10

logbl() Library Extended TNS/E H06.21, J06.10

logf() Library TNS/E H06.21, J06.10

404 Documented OSS Functions


Function Reference HP Native Only RVU Notes

logl() Library TNS/E H06.21, J06.10

log1p() Library Extended TNS/R, TNS/E

log1pf() Library TNS/E H06.21, J06.10

log1pl() Library TNS/E H06.21, J06.10

log2() Library TNS/E H06.21, J06.10

log2f() Library TNS/E H06.21, J06.10

log2l() Library TNS/E H06.21, J06.10

log10() Library

log10f() Library TNS/E H06.21, J06.10

log10l() Library TNS/E H06.21, J06.10

longjump() Library

longlong_to_dec() Library Yes

lrand48() Library

lrint() Library TNS/E H06.21, J06.10

lrintf() Library TNS/E H06.21, J06.10

lrintl() Library TNS/E H06.21, J06.10

lround() Library TNS/E H06.21, J06.10

lroundf() Library TNS/E H06.21, J06.10

lroundl() Library TNS/E H06.21, J06.10

lsearch() Library

lseek() System Extended

lseek64() System Yes G06.29, H06.06,


J06.03

lstat() System Extended

lstat64() System Yes G06.29, H06.06,


J06.03

lwres_freeaddrinfo() Library TNS/R, TNS/E H06.05, G06.27

lwres_freehostent() Library TNS/R, TNS/E H06.05, G06.27

lwres_gai_strerror() Library TNS/R, TNS/E H06.05, G06.27

lwres_getaddrinfo() Library TNS/R, TNS/E H06.05, G06.27

lwres_gethostbyaddr() Library TNS/R, TNS/E H06.05, G06.27

lwres_gethostbyname() Library TNS/R, TNS/E H06.05, G06.27

lwres_gethostbyname2() Library TNS/R, TNS/E H06.05, G06.27

lwres_getipnodebyaddr() Library TNS/R, TNS/E H06.05, G06.27

lwres_getipnodebyname() Library TNS/R, TNS/E H06.05, G06.27

lwres_getnameinfo() Library TNS/R, TNS/E H06.05, G06.27

lwres_hstrerror() Library TNS/R, TNS/E H06.05, G06.27

malloc() Library Yes

405
Function Reference HP Native Only RVU Notes

malloc_pages() Library Yes TNS/E

_max() Library

mblen() Library

mbrlen() Library TNS/E H06.08, J06.03

mbrtowc() Library TNS/E H06.08, J06.03

mbsinit() Library TNS/E H06.08, J06.03

mbsrtowcs() Library TNS/E H06.08, J06.03

mbstowcs() Library

mbtowc() Library

memccpy() Library

memchr() Library

memcmp() Library

memcpy() Library

memmove() Library

memset() Library

_min() Library

mkdir() System Extended

mkfifo() Library Extended

mknod() System Extended

mkstemp() Library TNS/R, TNS/E

mktemp() Library TNS/R, TNS/E

mktime() Library

modf() Library

modff() Library TNS/E H06.21, J06.10

modfl() Library TNS/E H06.21, J06.10

mrand48() Library

msgctl() System Extended

msgget() System Extended

msgrcv() System Extended

msgsnd() System Extended

406 Documented OSS Functions


Function Reference HP Native Only RVU Notes

nan() Library TNS/E H06.21, J06.10

nanf() Library TNS/E H06.21, J06.10

nanl() Library TNS/E H06.21, J06.10

nearbyint() Library TNS/E H06.21, J06.10

nearbyintf() Library TNS/E H06.21, J06.10

nearbyintl() Library TNS/E H06.21, J06.10

nextafter() Library Extended TNS/R, TNS/E

nextafterf() Library TNS/E H06.21, J06.10

nextafterl() Library TNS/E H06.21, J06.10

nexttoward() Library TNS/E H06.21, J06.10

nexttowardf() Library TNS/E H06.21, J06.10

nexttowardl() Library TNS/E H06.21, J06.10

nftw() Library Extended

nftw64() Library Extended G06.29, H06.06,


J06.03

nice() System

nl_langinfo() Library

nlist() Library

nrand48() Library

ntohl() Library

ntohs() Library

open() System Extended

open64() System Yes G06.29, H06.06,


J06.03

opendir() Library Extended

openlog() Library Extended

pathconf() Library Extended

pause() Library Extended

pclose() Library Extended

perror() Library

pipe() System Extended

popen() Library Extended

pow() Library

powf() Library TNS/E H06.21, J06.10

powl() Library TNS/E H06.21, J06.10

printf() Library Yes

pthread_atfork() System Yes TNS/R, TNS/E

pthread_attr_destroy() System Yes TNS/R, TNS/E

407
Function Reference HP Native Only RVU Notes

pthread_attr_getdetachstate() System Yes TNS/R, TNS/E

pthread_attr_getguardsize() System TNS/E H06.21, J06.10

pthread_attr_getguardsize_np() System Yes TNS/R, TNS/E

pthread_attr_getinheritsched() System Yes TNS/R, TNS/E

pthread_attr_getschedparam() System Yes TNS/R, TNS/E

pthread_attr_getschedpolicy() System Yes TNS/R, TNS/E

pthread_attr_getscope() System TNS/E H06.21, J06.10

pthread_attr_getstackaddr() System Yes TNS/R, TNS/E

pthread_attr_getstacksize() System Yes TNS/R, TNS/E

pthread_attr_init() System Yes TNS/R, TNS/E

pthread_attr_setdetachstate() System Yes TNS/R, TNS/E

pthread_attr_setguardsize() System TNS/E H06.21, J06.10

pthread_attr_setguardsize_np() System Yes TNS/R, TNS/E

pthread_attr_setinheritsched() System Yes TNS/R, TNS/E

pthread_attr_setschedparam() System Yes TNS/R, TNS/E

pthread_attr_setschedpolicy() System Yes TNS/R, TNS/E

pthread_attr_setscope() System TNS/E H06.21, J06.10

pthread_attr_setstacksize() System Yes TNS/R, TNS/E

pthread_cancel() System Yes TNS/R, TNS/E

pthread_cleanup_pop() System Yes TNS/R, TNS/E

pthread_cleanup_push() System Yes TNS/R, TNS/E

pthread_cond_broadcast() System Yes TNS/R, TNS/E

pthread_cond_destroy() System Yes TNS/R, TNS/E

pthread_cond_init() System Yes TNS/R, TNS/E

pthread_cond_signal() System Yes TNS/R, TNS/E

pthread_cond_signal_int_np() System Yes TNS/R, TNS/E

pthread_cond_timedwait() System Yes TNS/R, TNS/E

pthread_cond_wait() System Yes TNS/R, TNS/E

pthread_condattr_destroy() System Yes TNS/R, TNS/E

pthread_condattr_init() System Yes TNS/R, TNS/E

pthread_create() System Yes TNS/R, TNS/E

pthread_delay_np() System Yes TNS/R, TNS/E

pthread_detach() System Yes TNS/R, TNS/E

pthread_equal() System Yes TNS/R, TNS/E

pthread_exit() System Yes TNS/R, TNS/E

pthread_get_expiration_np() System Yes TNS/R, TNS/E

pthread_getattr_np() System Yes TNS/R, TNS/E

408 Documented OSS Functions


Function Reference HP Native Only RVU Notes

pthread_getconcurrency() System Yes TNS/R, TNS/E

pthread_getschedparam() System Yes TNS/R, TNS/E

pthread_getspecific() System Yes TNS/R, TNS/E

pthread_getthreadstateinfo_np() System Yes TNS/R, TNS/E

pthread_join() System Yes TNS/R, TNS/E

pthread_key_create() System Yes TNS/R, TNS/E

pthread_key_delete() System Yes TNS/R, TNS/E

pthread_kill() System Yes TNS/R, TNS/E

pthread_kill_np() System Yes TNS/R, TNS/E

pthread_lock_global_np() System Yes TNS/R, TNS/E

pthread_mutex_destroy() System Yes TNS/R, TNS/E

pthread_mutex_init() System Yes TNS/R, TNS/E

pthread_mutex_lock() System Yes TNS/R, TNS/E

pthread_mutex_trylock() System Yes TNS/R, TNS/E

pthread_mutex_unlock() System Yes TNS/R, TNS/E

pthread_mutexattr_destroy() System Yes TNS/R, TNS/E

pthread_mutexattr_getkind _np() System Yes TNS/R, TNS/E

pthread_mutexattr_gettype() System TNS/E H06.21, J06.10

pthread_mutexattr_init() System Yes TNS/R, TNS/E

pthread_mutexattr_setkind _np() System Yes TNS/R, TNS/E

pthread_mutexattr_settype() System TNS/E H06.21, J06.10

pthread_once() System Yes TNS/R, TNS/E

pthread_self() System Yes TNS/R, TNS/E

pthread_setcancelstate() System Yes TNS/R, TNS/E

pthread_setcanceltype() System Yes TNS/R, TNS/E

pthread_setconcurrency() System Yes TNS/R, TNS/E

pthread_setschedparam() System Yes TNS/R, TNS/E

pthread_setspecific() System Yes TNS/R, TNS/E

pthread_sigmask() System Yes TNS/R, TNS/E

pthread_signal_to_cancel_np() System Yes TNS/R, TNS/E

pthread_testcancel() System Yes TNS/R, TNS/E

pthread_unlock_global_np() System Yes TNS/R, TNS/E

PUT_ABORTTRANSACTION() Library Yes TNS/E H06.21, J06.10

put_awaitio() System Yes TNS/E H06.21, J06.10

PUT_BEGINTRANSACTION() Library Yes TNS/E H06.21, J06.10

PUT_CANCEL() System Yes TNS/E H06.21, J06.10

PUT_CONTROL() System Yes TNS/E H06.21, J06.10

409
Function Reference HP Native Only RVU Notes

PUT_ENDTRANSACTION() Library Yes TNS/E H06.21, J06.10

put_fd_read_ready() System Yes TNS/E H06.21, J06.10

put_fd_write_ready() System Yes TNS/E H06.21, J06.10

PUT_FILE_CLOSE_() System Yes TNS/E H06.21, J06.10

PUT_FILE_OPEN_() System Yes TNS/E H06.21, J06.10

put_generateTag() System Yes TNS/E H06.21, J06.10

put_getTMFConcurrentTransactions() System Yes TNS/E H06.21, J06.10

put_INITRECEIVE() System Yes TNS/E H06.21, J06.10

put_INITRECEIVEL() System Yes TNS/E H06.21, J06.10

put_interrupt() System Yes TNS/E H06.21, J06.10

put_interruptTag() System Yes TNS/E H06.21, J06.10

PUT_LOCKFILE() System Yes TNS/E H06.21, J06.10

PUT_LOCKREC() System Yes TNS/E H06.21, J06.10

PUT_READLOCKX() System Yes TNS/E H06.21, J06.10

PUT_READUPDATELOCKX() System Yes TNS/E H06.21, J06.10

PUT_READUPDATEX() System Yes TNS/E H06.21, J06.10

PUT_READX() System Yes TNS/E H06.21, J06.10

put_RECEIVEREAD() System Yes TNS/E H06.21, J06.10

put_RECEIVEREADL() System Yes TNS/E H06.21, J06.10

put_regFile() System Yes TNS/E H06.21, J06.10

put_regFileIOHandler() System Yes TNS/E H06.21, J06.10

put_regOSSFileIOHandler() System Yes TNS/E H06.21, J06.10

put_regPathsendFile() System Yes TNS/E H06.21, J06.10

put_regPathsendTagHandler() System Yes TNS/E H06.21, J06.10

put_regTimerHandler() System Yes TNS/E H06.21, J06.10

put_REPLYX() System Yes TNS/E H06.21, J06.10

put_REPLYXL() System Yes TNS/E H06.21, J06.10

PUT_RESUMETRANSACTION() Library Yes TNS/E H06.21, J06.10

put_select_single_np() System Yes TNS/E H06.21, J06.10

PUT_SERVERCLASS_DIALOG_ABORT_() Library Yes TNS/E H06.21, J06.10

PUT_SERVERCLASS_DIALOG_BEGIN_() Library Yes TNS/E H06.21, J06.10

PUT_SERVERCLASS_DIALOG_END_() Library Yes TNS/E H06.21, J06.10

PUT_SERVERCLASS_DIALOG_SEND_() Library Yes TNS/E H06.21, J06.10

PUT_SERVERCLASS_SEND_() Library Yes TNS/E H06.21, J06.10

PUT_SERVERCLASS_SEND_INFO_() Library Yes TNS/E H06.21, J06.10

PUT_SERVERCLASS_SENDL_() Library Yes TNS/E H06.21, J06.10

PUT_SETMODE() System Yes TNS/E H06.21, J06.10

410 Documented OSS Functions


Function Reference HP Native Only RVU Notes

put_setOSSFileIOHandler() System Yes TNS/E H06.21, J06.10

put_setTMFConcurrentTransactions() System Yes TNS/E H06.21, J06.10

PUT_TMF_GetTxHandle() System Yes TNS/E H06.21, J06.10

PUT_TMF_Init() System Yes TNS/E H06.21, J06.10

PUT_TMF_RESUME() System Yes TNS/E H06.21, J06.10

PUT_TMF_SetAndValidateTxHandle() System Yes TNS/E H06.21, J06.10

PUT_TMF_SetTxHandle() System Yes TNS/E H06.21, J06.10

PUT_TMF_SUSPEND() System Yes TNS/E H06.21, J06.10

PUT_UNLOCKFILE() System Yes TNS/E H06.21, J06.10

PUT_UNLOCKREC() System Yes TNS/E H06.21, J06.10

put_unregFile() System Yes TNS/E H06.21, J06.10

put_unregOSSFileIOHandler() System Yes TNS/E H06.21, J06.10

put_unregPathsendTagHandler() System Yes TNS/E H06.21, J06.10

put_wakeup() System Yes TNS/E H06.21, J06.10

PUT_WRITEREADX() System Yes TNS/E H06.21, J06.10

PUT_WRITEUPDATEUNLOCKX() System Yes TNS/E H06.21, J06.10

PUT_WRITEUPDATEX() System Yes TNS/E H06.21, J06.10

PUT_WRITEX() System Yes TNS/E H06.21, J06.10

putc() Library Extended

putc_unlocked() Library Extended TNS/E H06.21, J06.10

putchar() Library Extended

putchar_unlocked() Library Extended TNS/E H06.21, J06.10

putenv() Library TNS/R, TNS/E

puts() Library Extended

putw() Library Extended

putwc() Library Extended

putwchar() Library Extended

putws() Library Extended

qsort() Library

raise() Library Extended

rand() Library

rand_r() Library TNS/R, TNS/E G06.28, H06.05,


J06.03

random() Library

re_comp() Library TNS/R, TNS/E

re_exec() Library

read() System Extended

411
Function Reference HP Native Only RVU Notes

readdir() Library Yes

readdir_r() Library TNS/R, TNS/E G06.28, H06.05,


J06.03

readdir64() Library Yes G06.29, H06.06,


J06.03

readdir64_r() Library Yes TNS/E H06.21, J06.10

readlink() System Extended

readv() System

realloc() Library Yes

realpath() Library TNS/R, TNS/E

recv() System Extended

recvfrom() System Extended

recvmsg() System Extended

regcmp() Library

regcomp() Library

regerror() Library

regex() Library

regexec() Library

regfree() Library

remainder() Library Extended TNS/R, TNS/E

remainderf() Library TNS/E H06.21, J06.10

remainderl() Library TNS/E H06.21, J06.10

remove() Library

remove_guardian() Library Yes

remove_oss() Library Yes

remque() Library TNS/R, TNS/E

remquo() Library TNS/E H06.21, J06.10

remquof() Library TNS/E H06.21, J06.10

remquol() Library TNS/E H06.21, J06.10

rename() System

rename_guardian() System Yes

rename_oss() System Yes

rewind() Library

rewinddir() Library Extended

rindex() Library

rint() Library TNS/R, TNS/E

rintf() Library TNS/E H06.21, J06.10

rintl() Library TNS/E H06.21, J06.10

412 Documented OSS Functions


Function Reference HP Native Only RVU Notes

rmdir() System Extended

round() Library TNS/E H06.21, J06.10

roundf() Library TNS/E H06.21, J06.10

roundl() Library TNS/E H06.21, J06.10

scalb() Library Extended TNS/R, TNS/E

scalbln() Library TNS/E H06.21, J06.10

scalblnf() Library TNS/E H06.21, J06.10

scalblnl() Library TNS/E H06.21, J06.10

scalbn() Library TNS/E H06.21, J06.10

scalbnf() Library TNS/E H06.21, J06.10

scalbnl() Library TNS/E H06.21, J06.10

scandir() Library Yes G06.29, H06.06,


J06.03

scandir64() Library Yes G06.29, H06.06,


J06.03

scanf() Library Yes

sched_get_priority_max() System Yes

sched_get_priority_min() System Yes

sched_yield() System Yes TNS/R, TNS/E

seed48() Library

seekdir() Library Extended

select() System Extended

semctl() System Extended

semget() System Extended

semop() System Extended

send() System Extended

sendmsg() System Extended

sendto() System Extended

setbuf() Library

setegid() System TNS/R, TNS/E H06.18, J06.07

seteuid() System TNS/R, TNS/E H06.18, J06.07

setgid() System Yes

setgrent() Library Extended TNS/R, TNS/E

setgroups() System Yes TNS/R, TNS/E H06.18, J06.07

sethostent() Library Yes TNS/R, TNS/E

setjmp() Library

setkey() Library Yes TNS/R, TNS/E

setlocale() Library

413
Function Reference HP Native Only RVU Notes

setlocale_from_msg() Library Yes

setlogmask() Library

setnetent() Library Yes TNS/R, TNS/E

setpgid() System Extended

setpgrp() System Extended G06.29, H06.07,


J06.03

setprotoent() Library Yes TNS/R, TNS/E

setpwent() Library Extended

setregid() System Yes G06.27, H06.05,


J06.03

setreuid() System Yes G06.27, H06.05,


J06.03

setservent() Library Yes TNS/R, TNS/E

setsid() System Yes

setsockopt() System Extended

setstate() Library

setuid() System

setvbuf() Library

shmat() System Extended

shmctl() System Extended

shmdt() System Extended

shmget() System Extended

shutdown() System Extended

sigaction() System Extended TNS/R, TNS/E

sigaddset() Library Yes

sigaltstack() System Yes TNS/E H06.21, J06.10

sigdelset() Library Extended

sigemptyset() Library Extended

sigfillset() Library Extended

sigismember() Library Extended

siglongjmp() Library Yes

signal() Library Extended

signbit() Library TNS/E

sigpending() System Extended

sigprocmask() System Extended

sigsetjmp() Library

sigsuspend() System Extended

sigwait() System Yes TNS/E H06.21, J06.10

414 Documented OSS Functions


Function Reference HP Native Only RVU Notes

sin() Library

sinf() Library TNS/E H06.21, J06.10

sinh() Library

sinhf() Library TNS/E H06.21, J06.10

sinhl() Library TNS/E H06.21, J06.10

sinl() Library TNS/E H06.21, J06.10

sleep() H06.21, J06.10

sockatmark() System Yes

socket() System Extended

socket_transport_name_get() System Yes

socket_transport_name_set() System Yes

socketpair() System Extended

snprintf() Library Yes H06.03, J06.03

sprintf() Library Yes

SPT_ABORTTRANSACTION() Library Yes TNS/R, TNS/E

spt_accept() System Yes TNS/R, TNS/E

spt_acceptx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_alarm() System Yes TNS/R, TNS/E G06.29, H06.06,


J06.03

spt_awaitio() System Yes TNS/R, TNS/E

SPT_BEGINTRANSACTION() Library Yes TNS/R, TNS/E

SPT_CANCEL() System Yes TNS/R, TNS/E

spt_close() System Yes TNS/R, TNS/E

spt_closex() System Yes TNS/R, TNS/E

spt_closez() System Yes TNS/R, TNS/E H06.15, J06.04

spt_connect() System Yes TNS/R, TNS/E

spt_connectx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

SPT_CONTROL() System Yes TNS/R, TNS/E G06.28, H06.04,


J06.03

SPT_dup2x() System Yes TNS/R, TNS/E G06.28, H06.04,


J06.03

SPT_ENDTRANSACTION() Library Yes TNS/R, TNS/E

spt_fclose() System Yes TNS/R, TNS/E

spt_fclosex() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_fcntlx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_fcntlz() System Yes TNS/R, TNS/E H06.15, J06.04

415
Function Reference HP Native Only RVU Notes

spt_fd_read_ready() System Yes TNS/R, TNS/E

spt_fd_write_ready() System Yes TNS/R, TNS/E

spt_fflush() System Yes TNS/R, TNS/E

spt_fflushx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_fgetc() System Yes TNS/R, TNS/E

spt_fgetcx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_fgets() System Yes TNS/R, TNS/E

spt_fgetsx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_fgetwc() System Yes TNS/R, TNS/E

spt_fgetwcx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

SPT_FILE_CLOSE_() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

SPT_FILE_OPEN_() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_fork() System Yes TNS/R, TNS/E

spt_fprintf() System Yes TNS/R, TNS/E

spt_fprintfx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_fputc() System Yes TNS/R, TNS/E

spt_fputcx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_fputs() System Yes TNS/R, TNS/E

spt_fputsx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_fputwc() System Yes TNS/R, TNS/E

spt_fputwcx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_fread() System Yes TNS/R, TNS/E

spt_freadx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_fstatz() System Yes TNS/R, TNS/E H06.15, J06.04

spt_fstat64z() System Yes TNS/R, TNS/E H06.15, J06.04

spt_fsyncz() System Yes TNS/R, TNS/E H06.15, J06.04

spt_ftruncatez() System Yes TNS/R, TNS/E H06.15, J06.04

spt_ftruncate64z() System Yes TNS/R, TNS/E H06.15, J06.04

spt_fwrite() System Yes TNS/R, TNS/E

spt_fwritex() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

416 Documented OSS Functions


Function Reference HP Native Only RVU Notes

spt_generateTag() System Yes TNS/R, TNS/E

spt_getc() System Yes TNS/R, TNS/E

spt_getchar() System Yes TNS/R, TNS/E

spt_getcharx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_getcx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_gets() System Yes TNS/R, TNS/E

spt_getsx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_getTMFConcurrentTransactions() System Yes TNS/R, TNS/E

spt_getw() System Yes TNS/R, TNS/E

spt_getwc() System Yes TNS/R, TNS/E

spt_getwchar() System Yes TNS/R, TNS/E

spt_getwcharx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_getwcx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_getwx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_INITRECEIVE() System Yes TNS/R, TNS/E

spt_INITRECEIVEL() System Yes TNS/R, TNS/E H06.18, J06.07

spt_interrupt() System Yes TNS/R, TNS/E

spt_interruptTag() System Yes TNS/R, TNS/E

SPT_LOCKFILE() System Yes TNS/R, TNS/E G06.28, H06.04,


J06.03

SPT_LOCKREC() System Yes TNS/R, TNS/E G06.28, H06.04,


J06.03

spt_lseekz() System Yes TNS/R, TNS/E H06.15, J06.04

spt_lseek64z() System Yes TNS/R, TNS/E H06.15, J06.04

spt_pause() System Yes TNS/R, TNS/E G06.29, H06.06,


J06.03

spt_printf() System Yes TNS/R, TNS/E

spt_printfx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_putc() System Yes TNS/R, TNS/E

spt_putchar() System Yes TNS/R, TNS/E

spt_putcharx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_putcx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_puts() System Yes TNS/R, TNS/E

417
Function Reference HP Native Only RVU Notes

spt_putsx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_putw() System Yes TNS/R, TNS/E

spt_putwx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_putwc() System Yes TNS/R, TNS/E

spt_putwchar() System Yes TNS/R, TNS/E

spt_putwcharx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_putwcx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_putwx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_read() System Yes TNS/R, TNS/E

SPT_READLOCKX() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

SPT_READUPDATELOCKX() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

SPT_READUPDATEX() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_readv() System Yes TNS/R, TNS/E

spt_readvx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_readvz() System Yes TNS/R, TNS/E H06.15, J06.04

SPT_READX() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_readx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_readz() System Yes TNS/R, TNS/E H06.15, J06.04

SPT_RECEIVEREAD() System Yes TNS/R, TNS/E G06.26, H06.03,


J06.03

SPT_RECEIVEREADL() System Yes TNS/R, TNS/E H06.18, J07.07

spt_recv() System Yes TNS/R, TNS/E

spt_recvfrom() System Yes TNS/R, TNS/E

spt_recvfromx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_recvmsg() System Yes TNS/R, TNS/E

spt_recvmsgx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_recvx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_regFile() System Yes TNS/R, TNS/E

spt_regFileIOHandler() System Yes TNS/R, TNS/E

spt_regOSSFileIOHandler() System Yes TNS/R, TNS/E

418 Documented OSS Functions


Function Reference HP Native Only RVU Notes

spt_regPathsendFile() System Yes TNS/R, TNS/E

spt_regPathsendTagHandler() System Yes TNS/R, TNS/E

spt_regTimerHandler() System Yes TNS/R, TNS/E

spt_REPLYX() System Yes TNS/R, TNS/E

spt_REPLYXL() System Yes TNS/R, TNS/E H06.18, J06.07

SPT_RESUMETRANSACTION() Library Yes TNS/R, TNS/E

spt_select() System Yes TNS/R, TNS/E

spt_select_single_np() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_send() System Yes TNS/R, TNS/E

spt_sendmsg() System Yes TNS/R, TNS/E

spt_sendmsgx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_sendto() System Yes TNS/R, TNS/E

spt_sendtox() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_sendx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

SPT_SERVERCLASS_DIALOG_ABORT_() Library Yes TNS/R, TNS/E

SPT_SERVERCLASS_DIALOG_BEGIN_() Library Yes TNS/R, TNS/E

SPT_SERVERCLASS_DIALOG_END_() Library Yes TNS/R, TNS/E

SPT_SERVERCLASS_DIALOG_SEND_() Library Yes TNS/R, TNS/E

SPT_SERVERCLASS_SEND_() Library Yes TNS/R, TNS/E

SPT_SERVERCLASS_SEND_INFO() Library Yes TNS/R, TNS/E

SPT_SERVERCLASS_SENDL_() Library Yes TNS/R, TNS/E H06.18, J06.07

SPT_SETMODE() System Yes TNS/R, TNS/E G06.28, H06.04,


J06.03

spt_setOSSFileIOHandler() System Yes TNS/R, TNS/E G06.26, H06.03,


J06.03

spt_setTMFConcurrentTransactions() System Yes TNS/R, TNS/E

spt_sigaction() System Yes TNS/R, TNS/E G06.29, H06.06,


J06.03

spt_signal() System Yes TNS/R, TNS/E G06.29, H06.06,


J06.03

spt_sigpending() System Yes TNS/R, TNS/E G06.29, H06.06,


J06.03

spt_sigsuspend() System Yes TNS/R, TNS/E G06.29, H06.06,


J06.03

spt_sigwait() System Yes TNS/R, TNS/E G06.29, H06.06,


J06.03

spt_sleep() System Yes TNS/R, TNS/E

spt_system() System Yes TNS/R, TNS/E

419
Function Reference HP Native Only RVU Notes

SPT_TMF_GetTxHandle() System Yes TNS/R, TNS/E

SPT_TMF_Init() System Yes TNS/R, TNS/E

SPT_TMF_RESUME() System Yes TNS/R, TNS/E

SPT_TMF_SetAndValidateTxHandle() System Yes TNS/R, TNS/E

SPT_TMF_SetTxHandle() System Yes TNS/R, TNS/E

SPT_TMF_SUSPEND() System Yes TNS/R, TNS/E

SPT_UNLOCKFILE() System Yes TNS/R, TNS/E G06.28, H06.04,


J06.03

SPT_UNLOCKREC() System Yes TNS/R, TNS/E G06.28, H06.04,


J06.03

spt_unregFile() System Yes TNS/R, TNS/E

spt_unregOSSFileIOHandler() System Yes TNS/R, TNS/E G06.26, H06.03,


J06.03

spt_unregPathsendTagHandler() System Yes TNS/R, TNS/E

spt_usleep() System Yes TNS/R, TNS/E

spt_vfprintf() System Yes TNS/R, TNS/E

spt_vfprintfx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_vprintf() System Yes TNS/R, TNS/E

spt_vprintfx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_waitpid() System Yes TNS/R, TNS/E

spt_wakeup() System Yes TNS/R, TNS/E

spt_write() System Yes TNS/R, TNS/E

SPT_WRITEREADX() System Yes TNS/R, TNS/E G06.28, H06.04,


J06.03

SPT_WRITEUPDATEUNLOCKX() System Yes TNS/R, TNS/E G06.28, H06.04,


J06.03

SPT_WRITEUPDATEX() System Yes TNS/R, TNS/E G06.28, H06.04,


J06.03

spt_writev() System Yes TNS/R, TNS/E

spt_writevx() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_writevz() System Yes TNS/R, TNS/E H06.15, J06.04

SPT_WRITEX() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_writex() System Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

spt_writez() System Yes TNS/R, TNS/E H06.15, J06.04

sqrt() Library

sqrtf() Library TNS/E H06.21, J06.10

sqrtl() Library TNS/E H06.21, J06.10

420 Documented OSS Functions


Function Reference HP Native Only RVU Notes

srand() Library

srand48() Library

srandom() Library TNS/R, TNS/E

sscanf() Library Yes

stat() System Yes

stat64() System Yes G06.29, H06.06,


J06.03

statvfs() System Yes

statvfs64() System Yes G06.29, H06.06,


J06.03

step() Library TNS/R, TNS/E

strcasecmp() Library TNS/R, TNS/E

strcat() Library

strchr() Library

strcmp() Library

strcoll() Library

strcpy() Library

strcspn() Library

strdup() Library

strerror() Library

strerror_r() Library Yes TNS/E H06.21, J06.10

strfmon() Library

strftime() Library

strlen() Library

strncasecmp() Library TNS/R, TNS/E

strncat() Library

strncmp() Library

strncpy() Library

strpbrk() Library

strptime() Library

strrchr() Library

strspn() Library

strstr() Library

strtod() Library

strtof() Library TNS/E H06.08, J06.03

strtoimax() Library TNS/E H06.08, J06.03

strtok() Library

421
Function Reference HP Native Only RVU Notes

strtok_r() Library TNS/R, TNS/E G06.28, H06.05,


J06.03

strtol() Library

strtoll() Library

strtoul() Library

strtoull() Library

strtoumax() Library TNS/E H06.08, J06.03

strxfrm() Library

swab() Library

swprintf() Library TNS/E H06.08, J06.03

swscanf() Library TNS/E H06.08, J06.03

symlink() System Extended

sysconf() Library Yes

syslog() Library Yes

system() Library Yes

tan() Library

tanf() Library TNS/E H06.21, J06.10

tanh() Library

tanhf() Library TNS/E H06.21, J06.10

tanhl() Library TNS/E H06.21, J06.10

tanl() Library TNS/E H06.21, J06.10

tcdrain() Library Extended

tcflow() Library Extended

tcflush() Library Extended

tcgetattr() Library Extended

tcgetpgrp() Library Extended

tcsendbreak() Library Extended

tcsetattr() Library Extended

tcsetpgrp() Library Extended

tdelete() Library

tdm_execve() System Yes

tdm_execvep() System Yes

tdm_fork() System Yes

tdm_spawn() System Extended

tdm_spawnp() System Extended

telldir() Library

tempnam() Library

422 Documented OSS Functions


Function Reference HP Native Only RVU Notes

terminate_program() Library Yes

tfind() Library

tgamma() Library TNS/E H06.21, J06.10

tgammaf() Library TNS/E H06.21, J06.10

tgammal() Library TNS/E H06.21, J06.10

time() Library

times() Library Extended

tmpfile() Library

tmpfile_guardian() Library Yes

tmpfile_oss() Library Yes

tmpfile64() Library Yes G06.29, H06.06,


J06.03

tmpfile64_guardian() Library Yes G06.29, H06.06,


J06.03

tmpfile64_oss() Library Yes G06.29, H06.06,


J06.03

tmpnam() Library

tmpnam_guardian() Library

tmpnam_oss() Library

tmpnam_r() Library Yes TNS/R, TNS/E G06.28, H06.05,


J06.03

toascii() Library

_tolower() Library

tolower() Library

_toupper() Library

toupper() Library

towctrans() Library TNS/E H06.08, J06.03

towlower() Library

towupper() Library

trunc() Library TNS/E H06.21, J06.10

truncf() Library TNS/E H06.21, J06.10

truncl() Library TNS/E H06.21, J06.10

tsearch() Library

ttyname() Library Extended

ttyname_r() Library Extended TNS/R, TNS/E G06.28, H06.05,


J06.03

twalk() Library

tzset() Library

ulimit() System Extended

423
Function Reference HP Native Only RVU Notes

umask() System

uname() System Extended

ungetc() Library

ungetwc() Library

unlink() System Extended

unordered() Library Yes TNS/R, TNS/E

usleep() Library

utime() System Extended

va_arg() Library

va_end() Library

va_start() Library

valloc() Library

vfprintf() Library Extended

vfscanf() Library G06.27, H06.03

vfwprintf() Library TNS/E H06.08, J06.03

vfwscanf() Library TNS/E H06.08, J06.03

vprintf() Library Extended

vscanf() Library G06.27, H06.03

vsnprintf() Library Yes H06.03, J06.03

vsprintf() Library

vsscanf() Library G06.27, H06.03

vswprintf() Library TNS/E H06.08, J06.03

vswscanf() Library TNS/E H06.08, J06.03

vwprintf() Library TNS/E H06.08, J06.03

vwscanf() Library TNS/E H06.08, J06.03

wait() System Yes

waitpid() System Yes

wcrtomb() Library TNS/E H06.08, J06.03

wcscat() Library

wcschr() Library

wcscmp() Library

wcscoll() Library

wcscpy() Library

wcscspn() Library

wcsftime() Library

wcslen() Library

wcsncat() Library

424 Documented OSS Functions


Function Reference HP Native Only RVU Notes

wcsncmp() Library

wcsncpy() Library

wcspbrk() Library

wcsrchr() Library

wcsrtombs() Library TNS/E H06.08, J06.03

wcsspn() Library

wcstod() Library

wcstof() Library TNS/E H06.08, J06.03

wcstoimax() Library TNS/E H06.08, J06.03

wcstok() Library

wcstol() Library

wcstoll() Library

wcstombs() Library

wcstoul() Library

wcstoull() Library

wcstoumax() Library TNS/E H06.08, J06.03

wcswcs() Library

wcswidth() Library

wcsxfrm() Library

wctob() Library TNS/E H06.08, J06.03

wctomb() Library

wctrans() Library TNS/E H06.08, J06.03

wctype() Library

wcwidth() Library

wcmemchr() Library TNS/R, TNS/E

wcmemcmp() Library TNS/R, TNS/E

wcmemcpy() Library TNS/R, TNS/E

wcmemmove() Library TNS/R, TNS/E

wcmemset() Library TNS/R, TNS/E

wordexp() Library

wordfree() Library

wprintf() Library TNS/E H06.08, J06.03

write() System Extended

writev() System Extended

wscanf() Library TNS/E H06.08, J06.03

y0() Library

425
Function Reference HP Native Only RVU Notes

y1() Library

yn() Library

426 Documented OSS Functions


B API Interoperability in TNS Processes
This appendix contains Table B-1 (page 431), which describes the interoperability between the
Guardian API and the Open System Services (OSS) API in TNS processes. This appendix applies
only to G-series systems: the J-series and H-series OSS environments do not support TNS
processes.
Table B-1 lists the functions and macros in the Guardian C Run-Time Library and the OSS API.
Functions in the Guardian sockets library and Guardian system procedures are not included.
The table indicates the following characteristics for each function or macro:
• Modules it can be called from
• Processes it can be called from
• Parameters it requires
• Objects it can operate on

Calling Functions and Macros


The two factors that determine when you can call a function or macro are:
• The environment for which the module containing the call was compiled.
• The environment of the process executing the module.
An OSS module is a module compiled to have OSS semantics and execute in the OSS environment.
Likewise, a Guardian module is a module compiled to have Guardian semantics and execute in
the Guardian environment. Normally, the environments of a module and the process containing
the module are the same.
You can mix modules of different environments in the same process. An OSS process can execute
both OSS and Guardian modules, and a Guardian process can execute both Guardian and OSS
modules. See Chapter 1: Overview of the OSS Programming Environment (page 25) for a
discussion of when to write mixed-module applications.

Environment of the Module


The environment of a module is determined by the value of the SYSTYPE compiler pragma,
which directs the compiler to generate code appropriate for the specified target execution
environment.
In Table B-1, most functions and macros have the same name in both APIs, have identical
parameter lists, and the module will compile without errors regardless the environment you
specify. A few functions and macros, such as the open() function, have different parameter lists
in the two APIs. If you attempt to call the Guardian C open() function in a module compiled
for the OSS environment, you will get a compilation error because the parameter list is incorrect.

Environment of the Process


The environment of a process is determined by the environment of the module defining the
main() function.
Many functions and macros in the Guardian and OSS APIs can be called from a Guardian or
OSS module, which in turn can be part of a Guardian or OSS process. Some functions and macros,
such as the signal() function, can be called only from a Guardian module in a Guardian process
or from an OSS module in an OSS process.
For example, if you attempt to call the signal() function in a module compiled for the Guardian
environment, and then link this module to a main() function compiled for the OSS environment
(an OSS process), you will get a run-time error. This is because the system resources and services
required by the Guardian function cannot be provided by the OSS process environment.

Calling Functions and Macros 427


Function and Macro Behavior
A function or macro that can be called in both the Guardian and OSS environments might or
might not behave in the same way in each environment. Behavior can be classified into three
categories:
• Identical behavior
Many of the functions and macros behave the same way in each environment because they
take environment-independent parameters. For example, string functions such as strcat()
are identical in the Guardian and OSS environments. The malloc() function can allocate
a block of memory in a Guardian module and the free() function can free the same block
of memory in an OSS module.
• Nearly identical behavior
Some functions and macros behave nearly the same in each environment. Functions and
macros with nearly identical behavior also take environment-independent parameters. For
example, mathematical functions such as sinh() generate an exception on arithmetic
overflow in the Guardian environment but not in the OSS environment.
• Different behavior
Some functions and macros behave differently in each environment because they take or
return environment-specific parameters. For example, the Guardian C and OSS tmpnam()
functions are both declared as:
char *tmpnam(char *s)
The Guardian C tmpnam() function returns a valid Guardian filename, and the OSS
tmpnam() function returns a valid OSS pathname.
Although the name of a function or macro can be the same in the Guardian and OSS
environments, each environment can have a function with different syntax and semantics.
For example, the Guardian C open() function is declared as:
int open(char *file_name, int flags [, int security]
[, int depth] [, int pext] [, int sext]);
The OSS open() function is declared as:
int open(char *path, int oflag [, mode_t mode]);
Not only does the Guardian C open() function require a name in Guardian filename syntax
and the OSS open() function require a name in OSS pathname syntax, the functions have
different calling sequences. Also, you cannot pass an OSS file descriptor to the Guardian C
open() function (or to any Guardian C function), and vice versa.
An OSS function or macro that can operate on Guardian objects is limited in what it can do
when compared to the corresponding Guardian C function or macro. For example, the OSS
open() function can open some types of Guardian files (by specifying the file as an OSS
pathname in the /G file system), but the Guardian C open() function can open additional
types of Guardian files.

Using the API Interoperability Table


Some functions and macros in the Guardian and OSS APIs can interoperate completely between
the Guardian and OSS environments: that is, they can be called from either a Guardian or OSS
module, can execute as part of a Guardian or OSS process, and can operate on Guardian or OSS
objects. Some functions and macros are more limited in their interoperability between
environments.
For each function or macro listed in Table B-1 (page 431), the level of interoperability it provides
is indicated by the following information:
• Specification or standard where the function or macro is defined.
• Whether the function or macro can be called from a Guardian module, an OSS module, a
Guardian process, or an OSS process.

428 API Interoperability in TNS Processes


• Types of parameters (OSS or Guardian) the function or macro requires.
• Types of objects (OSS or Guardian) the function or macro operates on.

G and O Notation
In the columns headed “Module Compiled As,” and “Process Called From,” the letter “G”
indicates “Guardian” and “O” indicates “OSS.”

Specified By
The “Specified By” column indicates where a function or macro is defined:
ISO
The function or macro is specified in the ISO/ANSI C standard.
POSIX
The function or macro is specified in the POSIX.1 or POSIX.2 standard. (Functions identified
as “ISO” are also specified in the POSIX.1 standard.)
HP
The function or macro is an extension specified by HP.
X/OPEN
The function or macro is specified in the XPG4 version 2 specification, which is the basis for
the X/OPEN UNIX brand.
XPG4
The function or macro is specified in the XPG4 specification. (Functions and macros identified
as “ISO” or “POSIX” are also specified in the XPG4 specification.)
Functions and macros specified in the ISO standard are declared for both Guardian and OSS
modules.
By default, functions and macros specified in POSIX, XPG4, and X/OPEN UNIX are declared
only for OSS modules. To use such a function or macro in a Guardian module (if that is allowed),
specify the _XOPEN_SOURCE feature-test macro when you compile the module.
By default, functions and macros specified by HP are declared only for Guardian modules. To
use such a function or macro in an OSS module (if that is allowed), specify the _TANDEM_SOURCE
feature-test macro when you compile the module.
Regardless of whether the function or macro is being called from a Guardian or OSS module,
some functions and macros specified by X/OPEN UNIX require that the
_XOPEN_SOURCE_EXTENDED feature-test macro be specified when you compile the module,
and some require that either the _XOPEN_SOURCE_EXTENDED or the _TANDEM_SOURCE
feature-test macro be specified when you compile the module.
For the most complete information about any function, see the reference page for that function
either online or in the Open System Services System Calls Reference Manual.

Defining Parameters and Objects


OSS parameters include OSS pathnames, stream pointers, file descriptors, signals, and process
identifiers. Guardian parameters include Guardian filenames, stream pointers, file descriptors,
signals, and process identifiers. OSS objects include OSS files, streams, and processes. Guardian
objects include Guardian files, streams, and processes.
In some cases, OSS parameters can be used to access Guardian objects. For example, an OSS
pathname parameter can identify a Guardian file using the /G/volume/subvolume/fileid
syntax.

Usage Notes
The “Usage Notes” column provides information about the behavior of the function or macro.
Unless indicated otherwise in the “Usage Notes” column, a function or macro has the same
behavior regardless of the module or process environment from which it is called.

Using the API Interoperability Table 429


The following table describes the “Usage Notes” values that appear frequently.

Usage Note Meaning

Checking variants If the CHECK pragma is specified, functions and macros in both Guardian and OSS
modules perform identical parameter validation. If the NOCHECK pragma is
specified, functions and macros in both Guardian and OSS modules do not perform
extra parameter validation. The Guardian environment compiler defaults to CHECK.
The OSS environment compiler defaults to NOCHECK. Refer to the CHECK pragma
in the C/C++ Programmer’s Guide for details.

Exception variants The function or macro in a Guardian module generates an exception on an arithmetic
fault. The function or macro in an OSS module does not generate an exception on
an arithmetic fault.

Guardian function operates The Guardian function or macro operates only on Guardian objects.
only on Guardian objects

Guardian objects only The function or macro operates only on Guardian objects.

Guardian parameters only The function or macro requires Guardian parameters (Guardian filename, stream
pointer, file descriptor, or process identifier).

Limited OSS objects only The function or macro operates on some types of OSS objects. The extent of support
for OSS objects differs for each function or macro.

Limited when called from The function or macro’s operation is limited when it is called from a Guardian
Guardian process process.

Only Guardian modules or only The function or macro can be called only from a Guardian module within a Guardian
OSS modules process or from an OSS module within an OSS process. The function or macro
cannot be called from both Guardian and OSS modules within the same process.
The module and process environments must be the same. Behavior might be different
in each environment.

OSS function operates on OSS The OSS function or macro operates on OSS objects and some types of Guardian
objects and limited Guardian objects. The extent of support for Guardian objects differs for each function or macro.
objects

OSS function operates only on The OSS function or macro operates only on OSS objects.
OSS objects

OSS objects and limited The function or macro operates on OSS objects and some types of Guardian objects.
Guardian objects The extent of support for Guardian objects differs for each function or macro.

OSS objects only The function or macro operates only on OSS objects.

OSS parameters only The function or macro requires OSS parameters (OSS pathname, stream pointer,
file descriptor, or process identifier).

Parameters must match module When called from a Guardian module, the function or macro requires Guardian
parameters. When called from an OSS module, the function or macro requires OSS
parameters.If the function or macro operates on an open file, the file must have
been opened in a module of the same environment.

_XOPEN_SOURCE_EXTENDED The function or macro requires that the feature-test macro


_XOPEN_SOURCE_EXTENDED be specified when you compile the module.

_XOPEN_SOURCE_EXTENDED The function or macro requires that the feature-test macro


or _XOPEN_SOURCE_EXTENDED or _TANDEM_SOURCE be specified when you
_TANDEM_SOURCE compile the module.

Examples
The following examples illustrate how to use Table B-1 (page 431) to determine how functions
and macros can be used in Guardian and OSS programs.

430 API Interoperability in TNS Processes


1. The following information can be derived about the acos() function:
• Specified in the ISO/ANSI C standard.
• Can be called from Guardian and OSS modules.
• Can be called from Guardian and OSS processes.
• When called from a Guardian module, it causes an exception on arithmetic overflow;
when called from an OSS module, it does not.
2. The following information can be derived about the edlseek() function:
• Is an extension specified by HP.
• Can be called only from Guardian modules.
• Can be called from Guardian and OSS processes.
• Requires Guardian parameters.
• Operates only on Guardian objects.
• Because it is specified by HP, it requires the _TANDEM_SOURCE feature-test macro.
3. The following information can be derived about the edpwent() function:
• Specified in the X/OPEN specification.
• Can be called only from OSS modules.
• Can be called only from OSS processes.
• Requires the the _XOPEN_SOURCE_EXTENDED or _TANDEM_SOURCE feature-test macro.
4. The following information can be derived about the free() function:
• Specified in the ISO/ANSI C standard.
• Can be called from Guardian and OSS modules.
• Can be called from Guardian and OSS processes.
• If the CHECK pragma is specified, the function performs identical parameter validation
in both Guardian and OSS modules. If the NOCHECK pragma is specified, the function
does not perform extra parameter validation in Guardian and OSS modules.
5. The following information can be derived about the rename() function:
• Specified in the ISO/ANSI C standard.
• Can be called from Guardian and OSS modules.
• Can be called from Guardian and OSS processes.
• When called from a Guardian module, it requires Guardian parameters; when called
from an OSS module, it requires OSS parameters.
• Guardian function operates only on Guardian objects; OSS function operates on OSS
objects and limited Guardian objects.
6. The following information can be derived about the signal() function:
• Specified in the ISO/ANSI C standard.
• Can be called only from a Guardian module in a Guardian process or from an OSS
module in an OSS process. The module and process environments must be the same.
The function’s behavior is different in each environment.
• Guardian function operates only on Guardian objects; OSS function operates only on
OSS objects.
Table B-1 API Interoperability in TNS Processes
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

_ _ns_backup_fopen() HP G G

_ HP G G
_ns_fget_file_open_state()

_ _ns_fget_file_state() HP G G

_ _ns_fopen_special() HP G G

Using the API Interoperability Table 431


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

_ _ns_fset_file_state() HP G G

_ _ns_start_backup() HP G G

_abs() HP G, O G, O

_exit() X/OPEN G, O G, O Nowait considerations when called


from the Guardian API

_is_system_trap() HP G G

_max() HP G, O G, O

_min() HP G, O G, O

_tolower() XPG4 G, O G, O

_toupper() XPG4 G, O G, O

abort() ISO G, O G, O

abs() ISO G, O G, O

access() POSIX G, O G, O OSS parameters only


OSS objects and limited Guardian
objects

acos() ISO G, O G, O Exception variants

alarm() POSIX O O OSS objects only

asctime() ISO G, O G, O

asin() ISO G, O G, O Exception variants

assert() ISO G, O G, O

atan() ISO G, O G, O

atan2() ISO G, O G, O Exception variants

atexit() ISO G, O G, O

atof() ISO G, O G, O

atoi() ISO G, O G, O

atol() ISO G, O G, O

bsearch() ISO G, O G, O

calloc() ISO G, O G, O Checking variants

catclose() XPG4 O O OSS parameters only

catgets() XPG4 O O OSS parameters only

catopen() XPG4 O O OSS parameters only

ceil() ISO G, O G, O

cfgetispeed() POSIX O O

cfgetospeed() POSIX O O

cfsetispeed() POSIX O O

cfsetospeed() POSIX O O

432 API Interoperability in TNS Processes


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

chdir() POSIX G, O G, O OSS parameters only


OSS objects and limited Guardian
objects

chmod() POSIX G, O G, O OSS objects only

chown() POSIX G, O G, O OSS objects and limited Guardian


objects

chroot() XPG4 G, O G, O

chvol() HP G G

clearerr() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

clock() ISO G, O G, O

close() XPG4 G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

closedir() POSIX O G, O OSS parameters only


OSS objects and limited Guardian
objects

closelog() X/OPEN G, O G, O

confstr() XPG4 G, O G, O

cos() ISO G, O G, O

cosh() ISO G, O G, O Exception variants

creat() HP G G Guardian parameters only


Guardian objects only

creat() XPG4 O O OSS parameters only


OSS objects and limited Guardian
objects

ctermid() POSIX O O OSS parameters only

ctime() ISO G, O G, O

dec_to_longlong() HP G, O G, O

difftime() ISO G, O G, O

div() ISO G, O G, O

drand48() XPG4 G, O G, O

dup() POSIX O G, O OSS parameters only


OSS objects and limited Guardian
objects

Using the API Interoperability Table 433


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

dup2() POSIX O G, O OSS parameters only


OSS objects and limited Guardian
objects

ecvt() HP G, O G, O

edfseek() HP G G, O Guardian parameters only


Guardian objects only

edftell() HP G G, O Guardian parameters only


Guardian objects only

edlseek() HP G G, O Guardian parameters only


Guardian objects only

endpwent() X/OPEN O O _XOPEN_SOURCE_EXTENDED or


_TANDEM_SOURCE

erand48() XPG4 G, O G, O

erf() XPG4 G, O G, O

erfc() XPG4 G, O G, O

execl() POSIX O O OSS objects only

execle() POSIX O O OSS objects only

execlp() POSIX O O OSS objects only

execv() POSIX O O OSS objects only

execve() POSIX O O OSS objects only

execvp() POSIX O O OSS objects only

exit() ISO G, O G, O

exp() ISO G, O G, O Exception variants

fabs() ISO G, O G, O

fclose() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fcloseall() HP G G

fcntl() HP G G Guardian parameters only


Guardian objects only

fcntl() XPG4 O O OSS parameters only


OSS objects only

fdopen() XPG4 G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

434 API Interoperability in TNS Processes


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

fdtogfn() HP G G, O Guardian parameters only


Guardian objects only

feof() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

ferror() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fflush() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fgetc() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fgetpos() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fgets() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fgetwc() XPG4 O G, O

fgetws() XPG4 O G, O

fileno() XPG4 G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

floor() ISO G, O G, O

fmod() ISO G, O G, O

fnmatch() POSIX G, O G, O

fopen() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

Using the API Interoperability Table 435


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

fopen_guardian() HP G, O G, O Guardian parameters only


Guardian objects only

fopen_oss() HP G, O G, O OSS parameters only


OSS objects and limited Guardian
objects

fopen_std_file() HP G G

fork() POSIX O O OSS objects only

fpathconf() POSIX G, O G, O OSS parameters only

fprintf() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fputc() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fputs() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fputwc() XPG4 O G, O

fputws() XPG4 O G, O

fread() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

free() ISO G, O G, O Checking variants

freopen() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

freopen_guardian() HP G, O G, O Guardian parameters only


Guardian objects only

freopen_oss() HP G, O G, O OSS parameters only


OSS objects and limited Guardian
objects

frexp() ISO G, O G, O

436 API Interoperability in TNS Processes


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

fscanf() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fseek() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fsetpos() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

fstat() POSIX O G, O OSS parameters only


OSS objects and limited Guardian
objects

fsync() XPG4 G, O G, O

ftell() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

ftok() X/OPEN O G, O OSS parameters only


OSS objects only
_XOPEN_SOURCE_EXTENDED or
_TANDEM_SOURCE

ftw() XPG4 O G, O OSS parameters only


OSS objects and limited Guardian
objects

fwrite() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

gamma() XPG4 G, O G, O

get_assign_msg() HP G G

get_assign_msg_by_name() HP G G

get_max_assign_msg HP G G
_ordinal()

get_param_by_name() HP G G

get_param_msg() HP G G

get_startup_msg() HP G G

Using the API Interoperability Table 437


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

getc() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

getchar() ISO G, O G, O Only Guardian modules or only OSS


modules
Guardian function operates only on
Guardian objects
OSS function operates only on OSS
objects

getcwd() POSIX G, O G, O

getegid() POSIX G, O G, O

getenv() ISO G, O G, O

geteuid() POSIX G, O G, O

getgid() POSIX G, O G, O

getgrgid() POSIX O O Data can be overwritten by subsequent


call or call to getgrnam()

getgrnam() POSIX O O Data can be overwritten by subsequent


call or call to getgrgid()

getgroups() POSIX O O

getlogin() POSIX O O

getopt() XPG4 O O

getpgrp() POSIX O O OSS objects only

getpid() POSIX O O OSS objects only

getppid() POSIX O O OSS objects only

getpwent() X/OPEN O O _XOPEN_SOURCE_EXTENDED or


_TANDEM_SOURCE

getpwnam() POSIX O O

getpwuid() POSIX O O

gets() ISO G, O G, O Only Guardian modules or only OSS


modules
Guardian function operates only on
Guardian objects
OSS function operates only on OSS
objects

getsid() XPG4 O O

getuid() POSIX G, O G, O

getw() XPG4 O G, O OSS function operates on OSS objects


and limited Guardian objects

getwc() XPG4 O G, O

getwchar() XPG4 O O

438 API Interoperability in TNS Processes


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

getws() XPG4 O O

glob() POSIX G, O G, O

globfree() POSIX G, O G, O

gmtime() ISO G, O G, O

hcreate() XPG4 G, O G, O

hdestroy() XPG4 G, O G, O

heap_check() HP G, O G, O

heap_check_always() HP G, O G, O

heap_min_block_size() HP G, O G, O

hsearch() XPG4 G, O G, O

hypot() XPG4 G, O G, O

iconv() XPG4 O O

iconv_close() XPG4 O O

iconv_open() XPG4 O O

ioctl() X/OPEN G, O G, O

isalnum() ISO G, O G, O

isalpha() ISO G, O G, O

isascii() XPG4 G, O G, O

isatty() POSIX O G, O OSS parameters only

iscntrl() ISO G, O G, O

iscsym() HP G, O G, O

iscsymf() HP G, O G, O

isdigit() ISO G, O G, O

isgraph() ISO G, O G, O

islower() ISO G, O G, O

isnan() ISO G, O G, O

isprint() ISO G, O G, O

ispunct() ISO G, O G, O

isspace() ISO G, O G, O

isupper() ISO G, O G, O

iswalnum() XPG4 G, O G, O

iswalpha() XPG4 G, O G, O

iswcntrl() XPG4 G, O G, O

iswctype() XPG4 G, O G, O

iswdigit() XPG4 G, O G, O

Using the API Interoperability Table 439


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

iswgraph() XPG4 G, O G, O

iswlower() XPG4 G, O G, O

iswprint() XPG4 G, O G, O

iswpunct() XPG4 G, O G, O

iswspace() XPG4 G, O G, O

iswupper() XPG4 G, O G, O

iswxdigit() XPG4 G, O G, O

isxdigit() XPG4 G, O G, O

j0() XPG4 G, O G, O

j1() XPG4 G, O G, O

jn() XPG4 G, O G, O

jrand48() XPG4 G, O G, O

kill() POSIX O O OSS objects only

labs() ISO G, O G, O

lcong48() XPG4 G, O G, O

ldexp() ISO G, O G, O Exception variants

ldiv() ISO G, O G, O

lfind() XPG4 G, O G, O

lgamma() XPG4 G, O G, O

link() POSIX O G, O OSS parameters only


OSS objects only

localeconv() ISO G, O G, O

localtime() ISO G, O G, O

log() ISO G, O G, O Exception variants

log10() ISO G, O G, O Exception variants

longjmp() ISO G, O G, O Only Guardian modules or only OSS


modules

longlong_to_dec() HP G, O G, O

lrand48() XPG4 G, O G, O

lsearch() XPG4 G, O G, O

lseek() XPG4 G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

lstat() X/OPEN G, O G, O _XOPEN_SOURCE_EXTENDED

malloc() ISO G, O G, O Checking variants

440 API Interoperability in TNS Processes


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

mblen() ISO G, O G, O

mbstowcs() ISO G, O G, O

mbtowc() ISO G, O G, O

memccpy() ISO O G, O

memchr() ISO G, O G, O Checking variants

memcmp() ISO G, O G, O Checking variants

memcpy() ISO G, O G, O Checking variants

memmove() ISO G, O G, O Checking variants

memset() ISO G, O G, O Checking variants

memswap() HP G, O G, O Checking variants

mkdir() POSIX G, O G, O OSS parameters only


OSS objects and limited Guardian
objects

mkfifo() POSIX G, O G, O OSS parameters only

mknod() X/OPEN G, O G, O _XOPEN_SOURCE_EXTENDED

mktime() ISO G, O G, O

modf() ISO G, O G, O

movmem() HP G, O G, O Checking variants

mrand48() XPG4 G, O G, O

msgctl() XPG4 O O OSS objects only

msgget() XPG4 O O OSS objects only

msgrcv() XPG4 O O OSS objects only

msgsnd() XPG4 O O OSS objects only

nl_langinfo() XPG4 G, O G, O

nlist() X/OPEN G, O G, O

nrand48() XPG4 G, O G, O

offsetof() ISO G, O G, O

open() HP G G Guardian parameters only


Guardian objects only

open() XPG4 O O OSS parameters only


OSS objects and limited Guardian
objects

opendir() POSIX G, O G, O OSS parameters only


OSS objects and limited Guardian
objects

openlog() X/OPEN G, O G, O Limited when called from Guardian


process

pathconf() POSIX G, O G, O OSS parameters only

Using the API Interoperability Table 441


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

pause() POSIX O O OSS objects only

pclose() POSIX G, O G, O OSS parameters only

perror() ISO G, O G, O

pipe() POSIX O G, O OSS parameters only

popen() POSIX G, O G, O OSS parameters only

pow() ISO G, O G, O Exception variants

printf() ISO G, O G, O Only Guardian modules or only OSS


modules

putc() ISO G, O G, O Parameters must match module

putchar() ISO G, O G, O Only Guardian modules or only OSS


modules
Guardian function operates only on
Guardian objects
OSS function operates only on OSS
objects

putenv() XPG4 O G, O

puts() ISO G, O G, O Only Guardian modules or only OSS


modules

putw() XPG4 O G, O

putwc() XPG4 O G, O

putwchar() XPG4 O O

putws() XPG4 O O

qsort() ISO G, O G, O

raise() ISO G, O G, O Only Guardian modules or only OSS


modules
Guardian function operates only on
Guardian objects
OSS function operates only on OSS
objects

rand() ISO G, O G, O

read() XPG4 G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

readdir() POSIX G, O G, O OSS parameters only


OSS objects and limited Guardian
objects

readlink() X/OPEN G, O G, O OSS objects only


_XOPEN_SOURCE_EXTENDED

readupdate() HP G G, O Guardian parameters only

realloc() ISO G, O G, O Checking variants

442 API Interoperability in TNS Processes


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

regcomp() XPG4 O O

regerror() XPG4 O O

regexec() XPG4 O O

regfree() XPG4 O O

remove() ISO G, O G, O Parameters must match module

remove_guardian() HP G, O G, O Guardian parameters only

remove_oss() HP G, O G, O OSS parameters only

rename() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

rename_guardian() HP G, O G, O Guardian parameters only


Guardian objects only

rename_oss() HP G, O G, O OSS parameters only


OSS objects and limited Guardian
objects

reply() HP G G, O

repmem() HP G, O G, O Checking variants

rewind() ISO G, O G, O Parameters must match module

rewinddir() POSIX G, O G, O OSS parameters only


OSS objects and limited Guardian
objects

rmdir() POSIX O G, O OSS parameters only


Limited OSS objects only

scanf() ISO G, O G, O Only Guardian modules or only OSS


modules

seed48() XPG4 G, O G, O

seekdir() XPG4 G, O G, O OSS parameters only


OSS objects and limited Guardian
objects

semctl() XPG4 O O

semget() XPG4 O O

semop() XPG4 O O

setbuf() ISO G, O G, O Parameters must match module

setgid() POSIX G, O G, O

setjmp() ISO G, O G, O Only Guardian modules or only OSS


modules

setlocale() ISO G, O G, O

setlocale_from_msg() HP O O OSS parameters only

Using the API Interoperability Table 443


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

setlogmask() X/OPEN G, O G, O

setmem() HP G, O G, O Checking variants

setnbuf() HP G, O G, O Parameters must match module

setpgid() POSIX G, O O OSS objects only

setpgrp() POSIX O O OSS objects only

setpwent() X/OPEN O O _XOPEN_SOURCE_EXTENDED or


_TANDEM_SOURCE

setregid() XPG4 O O OSS objects only

setreuid() XPG4 O O OSS objects only

setsid() POSIX O O OSS objects only

setuid() POSIX G, O G, O

setvbuf() ISO G, O G, O Parameters must match module

shmat() XPG4 O O

shmctl() XPG4 O O

shmdt() XPG4 O O

shmget() XPG4 O O

sigaction() POSIX O O OSS objects only

sigaddset() POSIX O O OSS objects only

sigdelset() POSIX O O OSS objects only

sigemptyset() POSIX O O OSS objects only

sigfillset() POSIX O O OSS objects only

sigismember() POSIX O O OSS objects only

siglongjmp() POSIX O O OSS objects only

signal() ISO G, O G, O Only Guardian modules or only OSS


modules
Guardian function operates only on
Guardian objects
OSS function operates only on OSS
objects

sigpending() POSIX O O OSS objects only

sigprocmask() POSIX O O OSS objects only

sigsetjmp() POSIX O O OSS objects only

sigsuspend() POSIX O O OSS objects only

sin() ISO G, O G, O

sinh() ISO G, O G, O Exception variants

snprintf() (H-series only) ISO G, O G, O

sprintf() ISO G, O G, O

444 API Interoperability in TNS Processes


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

sqrt() ISO G, O G, O Exception variants

srand() ISO G, O G, O

srand48() XPG4 G, O G, O

sscanf() ISO G, O G, O

stat() POSIX O G, O OSS parameters only


OSS objects and limited Guardian
objects

stcarg() HP G, O G, O Checking variants

stccpy() HP G, O G, O Checking variants

stcd_i() HP G, O G, O Checking variants

stcd_l() HP G, O G, O Checking variants

stch_i() HP G, O G, O Checking variants

stci_d() HP G, O G, O Checking variants

stcis() HP G, O G, O Checking variants

stcisn() HP G, O G, O Checking variants

stclen() HP G, O G, O Checking variants

stcpm() HP G, O G, O Checking variants

stcpma() HP G, O G, O Checking variants

stcu_d() HP G, O G, O Checking variants

stpblk() HP G, O G, O Checking variants

stpbrk() HP G, O G, O Checking variants

stpchr() HP G, O G, O Checking variants

stpsym() HP G, O G, O Checking variants

stptok() HP G, O G, O Checking variants

strcat() ISO G, O G, O Checking variants

strchr() ISO G, O G, O Checking variants

strcmp() ISO G, O G, O Checking variants

strcoll() ISO G, O G, O

strcpy() ISO G, O G, O Checking variants

strcspn() ISO G, O G, O Checking variants

strdup() X/OPEN G, O G, O _XOPEN_SOURCE_EXTENDED

strerror() ISO G, O G, O

strfmon() XPG4 G, O G, O

strftime() ISO G, O G, O

strlen() ISO G, O G, O Checking variants

strncat() ISO G, O G, O Checking variants

Using the API Interoperability Table 445


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

strncmp() ISO G, O G, O Checking variants

strncpy() ISO G, O G, O Checking variants

strpbrk() ISO G, O G, O Checking variants

strptime() XPG4 G, O G, O

strrchr() ISO G, O G, O Checking variants

strspn() ISO G, O G, O Checking variants

strstr() ISO G, O G, O Checking variants

strtod() ISO G, O G, O Checking variants

strtok() ISO G, O G, O Checking variants

strtol() ISO G, O G, O Checking variants

strtoll() ISO G, O G, O Checking variants

strtoul() ISO G, O G, O Checking variants

strtoull() ISO G, O G, O Checking variants

strxfrm() ISO G, O G, O

stscmp() HP G, O G, O

swab() XPG4 G, O G, O

symlink() X/OPEN G, O G, O OSS objects only


_XOPEN_SOURCE_EXTENDED

sysconf() POSIX G, O G, O

syslog() X/OPEN G, O G, O

system() ISO G, O G, O Only Guardian modules or only OSS


modules

tan() ISO G, O G, O

tanh() ISO G, O G, O

tcdrain() POSIX O O

tcflow() POSIX O O

tcflush() POSIX O O

tcgetattr() POSIX O O

tcgetpgrp() POSIX O O

tcsendbreak() POSIX O O

tcsetattr() POSIX O O

tcsetpgrp() POSIX O O

tdelete() XPG4 G, O G, O

tdm_execve() HP O O OSS parameters only

tdm_execvep() HP O O OSS parameters only

tdm_fork() HP O O OSS parameters only

446 API Interoperability in TNS Processes


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

tdm_spawn() HP O O OSS parameters only

tdm_spawnp() HP O O OSS objects only

telldir() XPG4 G, O G, O OSS parameters only


OSS objects and limited Guardian
objects

tempnam() XPG4 G, O O

terminate_program() HP G, O G, O

tfind() XPG4 G, O G, O

time() ISO G, O G, O

times() POSIX G, O G, O

tmpfile() ISO G, O G, O Parameters must match module

tmpfile_guardian() HP G, O G, O Guardian parameters only

tmpfile_oss() HP G, O G, O OSS parameters only

tmpnam() ISO G, O G, O Parameters must match module

tmpnam_guardian() HP G, O G, O Guardian parameters only

tmpnam_oss() HP G, O G, O OSS parameters only

toascii() XPG4 G, O G, O

tolower() ISO G, O G, O

toupper() ISO G, O G, O

towlower() XPG4 G, O G, O

towupper() XPG4 G, O G, O

trap_overflows() HP G G

tsearch() XPG4 G, O G, O

ttyname() XPG4 O G, O

twalk() XPG4 G, O G, O

tzset() XPG4 G, O G, O

ulimit() XPG4 G, O G, O

umask() POSIX G, O G, O

uname() POSIX G, O G, O

ungetc() ISO G, O G, O Parameters must match module

ungetwc() XPG4 O G, O

unlink() ISO G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

Using the API Interoperability Table 447


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

utime() POSIX O G, O OSS parameters only


OSS objects and limited Guardian
objects

va_arg() ISO G, O G, O

va_end() ISO G, O G, O

va_start() ISO G, O G, O

vfprintf() ISO G, O G, O Parameters must match module

vfscanf() ISO G, O G, O

vprintf() ISO G, O G, O Only Guardian modules or only OSS


modules

vscanf() ISO G, O G, O

vsnprintf() ISO G,O G,O

vsprintf() ISO G, O G, O

vsscanf() ISO G, O G, O

wait() POSIX O O OSS objects only

waitpid() POSIX O O OSS objects only

wcscat() XPG4 G, O G, O

wcschr() XPG4 G, O G, O

wcscmp() XPG4 G, O G, O

wcscoll() XPG4 G, O G, O

wcscpy() XPG4 G, O G, O

wcscspn() XPG4 G, O G, O

wcsftime() XPG4 G, O G, O

wcslen() XPG4 G, O G, O

wcsncat() XPG4 G, O G, O

wcsncmp() XPG4 G, O G, O

wcsncpy() XPG4 G, O G, O

wcspbrk() XPG4 G, O G, O

wcsrchr() XPG4 G, O G, O

wcsspn() XPG4 G, O G, O

wcstod() XPG4 G, O G, O

wcstok() XPG4 G, O G, O

wcstol() XPG4 G, O G, O

wcstoll() XPG4 G, O G, O

wcstombs() XPG4 G, O G, O

wcstoul() XPG4 G, O G, O

448 API Interoperability in TNS Processes


Table B-1 API Interoperability in TNS Processes (continued)
Function or Macro Specified By Module Process Usage Notes
Compiled Called
As From

wcstoull() XPG4 G, O G, O

wcswcs() XPG4 G, O G, O

wcswidth() XPG4 G, O G, O

wcsxfrm() XPG4 G, O G, O

wctomb() XPG4 G, O G, O

wctype() XPG4 G, O G, O

wcwidth() XPG4 G, O G, O

wmemchr() ISO G, O G, O Checking variants

wmemcmp() ISO G, O G, O Checking variants

wmemcpy() ISO G, O G, O Checking variants

wmemmove() ISO G, O G, O Checking variants

wmemset() ISO G, O G, O Checking variants

wordexp() POSIX G, O G, O

wordfree() POSIX G, O G, O

write() XPG4 G, O G, O Parameters must match module


Guardian function operates only on
Guardian objects
OSS function operates on OSS objects
and limited Guardian objects

writeread() HP G G, O Guardian parameters only

y0() XPG4 G, O G, O

y1() XPG4 G, O G, O

yn() XPG4 G, O G, O

Using the API Interoperability Table 449


450
C API Interoperability in Native Processes
This appendix contains the API Interoperability tables, which describe the interoperability
between the Guardian API and the OSS API in TNS/R and TNS/E native processes.
These tables list the functions and macros in the native C Run-Time Library and the OSS API.
Functions in the Guardian sockets library and Guardian system procedures are not included.
The tables indicate the following characteristics for each function or macro:
• Modules it can be called from
• Processes it can be called from
• Parameters it requires
• Objects it can operate on

Comparing API Interoperability in TNS and Native Processes


The native C run-time library supports both the OSS and Guardian environments. Having a
single library for functions that are part of both APIs means that most differences in behavior
that exist in TNS processes do not exist in native processes.
For example, in TNS processes the signal() function can be called only from a Guardian
module within a Guardian process or from an OSS module within an OSS process. The Guardian
function operates only on Guardian objects, and the OSS function operates only on OSS objects.
None of these differences in behavior of the signal() function exist in native processes.
There are still some functions, however, such as fopen() and rename(), that have
environment-specific behavior and require environment-specific parameters.
In addition, for the native C run-time library:
• Eight functions that require environment-specific parameters have environment-specific
variants. These functions are fopen(), fopen64(), freopen(), freopen64(), remove(),
rename(), tmpnam(), and tmpfile(). The environment-specific variants of these functions
have suffixes, such as fopen_guardian() and fopen_oss(). For example, you can use
fopen_oss() to open an OSS file from within a Guardian process.
• There are no separate Guardian variants of functions that operate on file descriptors instead
of streams. For example, the open() and read() functions can be accessed from both the
Guardian and OSS environments, but always operate on OSS file descriptors.
• Some functions that are specified by HP have been eliminated, such as readupdate() and
edlseek().
• Some functions, such as erf() and strdup(), have been added to the native library for
compliance to the XPG4 specification.
For a detailed description of the differences between the TNS and TNS/R or TNS/E native C
run-time libraries, see the TNS/R Native Application Migration Guide or the TNS/E Native Application
Conversion Guide.

Calling Functions and Macros


The two factors that determine when you can call a function or macro are:
• The environment for which the module containing the call was compiled.
• The environment of the process executing the module.
An OSS module is a module compiled to have OSS semantics and execute in the OSS environment.
Likewise, a Guardian module is a module compiled to have Guardian semantics and execute in
the Guardian environment. Normally, the environments of a module and the process executing
the module are the same.
You can mix modules of different environments in the same process. An OSS process can execute
both OSS and Guardian modules, and a Guardian process can execute both Guardian and OSS
modules. See Chapter 1: Overview of the OSS Programming Environment (page 25) for a
discussion of when to write mixed-module applications.

Comparing API Interoperability in TNS and Native Processes 451


Environment of the Module
The environment of a module is determined by the value of the SYSTYPE compiler pragma,
which directs the compiler to generate code appropriate for the specified target execution
environment.

Environment of the Process


The environment of a process is determined by the environment of the module defining the
main() function.
Most functions and macros in the Guardian and OSS APIs can be called from a Guardian or OSS
module, which in turn can be part of a Guardian or OSS process. For example, the system()
function can be called only from a Guardian module in a Guardian process or from an OSS
module in an OSS process.
If you attempt to call the system() function in a module compiled for the Guardian environment,
and then link this module to a main() module compiled for the OSS environment (an OSS
process), you will get a run-time error. This is because the system resources and services required
by the Guardian variant function cannot be provided by the OSS process environment.
Some functions, such as fopen(), require environment-specific parameters. For example, if you
call the fopen() function with an OSS pathname in a Guardian process, the type of the parameter
does not match the type of the process, and a run-time error is generated.

Function and Macro Behavior


A function or macro can be called in both the Guardian and OSS environments might behave
the same or differently in each environment. In general, behavior is identical when function
parameters are environment independent, and it is different when function parameters are
environment specific.

Functions With Environment-Specific Parameters


The fopen(), fopen64(), freopen(), freopen64(), remove(), rename(), tmpnam(), and
tmpfile() functions require that the type of the parameters match the type of the process. For
example, in an OSS process, the file to be operated on must be indicated by an OSS pathname.
(Remember that files in /G have OSS pathnames.) In a Guardian process, the file to be operated
on must be indicated by a Guardian filename.
Note that the parameter type need not match the process type in the environment-specific variants
of these functions. For example, the fopen_guardian() function opens a Guardian file from
within an OSS or Guardian process.

Functions With Environment-Independent Parameters


Most of the functions and macros available in both the Guardian and OSS environments behave
the same, regardless of the environment, because they take environment-independent parameters.
For example, string functions such as strcat() are identical in the Guardian and OSS
environments. The malloc() function can allocate a block of memory in a Guardian module
and the free() function can free the same block of memory in an OSS module.

Internationalization Functions
In Guardian processes, regardless of whether modules are compiled to run in the Guardian or
OSS environment, only the C/POSIX locale is available. In OSS processes, full internationalization
support is available if the required locales are purchased and installed on the system.

Using the API Interoperability Tables


Some functions and macros in the Guardian and OSS APIs can interoperate completely between
the Guardian and OSS environments: that is, they can be called from either a Guardian or OSS
module, can execute as part of a Guardian or OSS process, and can operate on Guardian or OSS

452 API Interoperability in Native Processes


objects. Some functions and macros are more limited in their interoperability between
environments.
For each function or macro listed in the API Interoperability tables, the level of interoperability
it provides is indicated by the following information:
• Specification or standard where the function or macro is defined.
• Whether the function or macro can be called from a Guardian module, an OSS module, a
Guardian process, or an OSS process.
• Types of parameters (OSS or Guardian) the function or macro requires.
• Types of objects (OSS or Guardian) the function or macro operates on.

G and O Notation
In the columns headed “Module Compiled As,” and “Process Called From,” the letter “G”
indicates “Guardian” and “O” indicates “OSS.”

Specified By
The “Specified By” column indicates where a function or macro is defined:
FC-MI
The function is specified in the Fibre Channel - Methodologies for Interconnects (FC-MI)
Revision 1.6 Annexure A by the Storage Network Industry Association (SNIA).
ISO
The function or macro is specified in the ISO/ANSI C standard.
POSIX
The function or macro is specified in the POSIX.1 or POSIX.2 standard. (Functions identified
as “ISO” are also specified in the POSIX.1 standard.)
HP
The function or macro is an extension specified by HP.
Threads
The function is part of the Standard POSIX Threads and is specified in the International
Standard ISO/IEC 9945-1; 1996 (E) IEEE Std 1003.1,1996 (Incorporating ANSI/IEEE Stds
1003.1-1990, 1003.1b-1993, 1003.1c-1995, and 1003.1i-1995), or
The function is part of the POSIX User Thread Model and is specified in the IEEE Std 1003.1,
2004.
X/OPEN
The function or macro is specified in the XPG4 version 2 specification, which is the basis for
the X/OPEN UNIX brand.
XLFS
The function or macro is an HP extension to the XPG4 specification based on the Adding
Support for Arbitrary File Sizes to the Single Unix Specification, X/Open Large File Summit (LFS)
submission, version 1.5 (March 20, 1996). This function or macro is supported on systems
running G06.29 or later G-series RVUs or H06.06 or later H-series RVUs.
XPG4
The function or macro is specified in the XPG4 specification. (Functions and macros identified
as “ISO” or “POSIX” are also specified in the XPG4 specification.)
Functions and macros specified in the ISO standard are declared for both Guardian and OSS
modules.
By default, functions and macros specified in POSIX, XPG4, and X/OPEN UNIX are declared
only for OSS modules. To use such a function or macro in a Guardian module (if that is allowed),
specify the _XOPEN_SOURCE feature-test macro when you compile the module.
By default, functions and macros specified by HP are declared only for Guardian modules. To
use such a function or macro in an OSS module (if that is allowed), specify the _TANDEM_SOURCE
feature-test macro when you compile the module.

Using the API Interoperability Tables 453


Regardless of whether the function or macro is being called from a Guardian or OSS module,
some functions and macros specified by X/OPEN UNIX require that the
_XOPEN_SOURCE_EXTENDED feature-test macro be specified when you compile the module,
and some require that either the _XOPEN_SOURCE_EXTENDED or the _TANDEM_SOURCE
feature-test macro be specified when you compile the module. _XOPEN_SOURCE_EXTENDED
must be defined as the constant 1.

Defining Parameters and Objects


OSS parameters include OSS pathnames, stream pointers, file descriptors, and process identifiers.
Guardian parameters include Guardian filenames, stream pointers, and process identifiers. OSS
objects include OSS files, streams, and processes. Guardian objects include Guardian files, streams,
and processes.
In some cases, OSS parameters can be used to access Guardian objects. For example, an OSS
pathname parameter can identify a Guardian file using the /G/volume/subvolume/fileid
syntax.

Usage Notes
The “Usage Notes” column provides information about the behavior of the function or macro.
Unless indicated otherwise in the “Usage Notes” column, a function or macro has the same
behavior regardless of the module or process environment from which it is called.
The following table describes the “Usage Notes” values that appear frequently.

Usage Note Meaning

Guardian function operates only on Guardian objects The Guardian function or macro operates only on
Guardian objects.

Guardian objects only The function or macro operates only on Guardian objects.

Guardian parameters only The function or macro requires Guardian parameters


(Guardian filename, stream pointer, or process identifier).

IEEE_float only The function or macro is only implemented for the


IEEE_float floating point option. Application using
this function or macro cannot be compiled if the specified
floating-point option is Tandem_float.

_LARGEFILE64_SOURCE or An application can explicitly call this function when you


_FILE_OFFSET_BITS use the #define _LARGEFILE64_SOURCE 1 feature
test macro or an equivalent compiler command option to
compile the application.
An application call to interface() is automatically
mapped to this interface64() function when you use
the #define _FILE_OFFSET_BITS 64 feature test
macro or an equivalent compiler command option to
compile the application.

Limited OSS objects only The function or macro operates on some types of OSS
objects. The extent of support for OSS objects differs for
each function or macro.

Limited when called from Guardian process The function or macro’s operation is limited when it is
called from a Guardian process.

Only Guardian modules or only OSS modules The function or macro can be called only from a Guardian
module within a Guardian process or from an OSS module
within an OSS process. The function or macro cannot be
called from both Guardian and OSS modules within the
same process. The module and process environments
must be the same. Behavior might be different in each
environment.

454 API Interoperability in Native Processes


Usage Note Meaning

OSS function operates on OSS objects and limited The OSS function or macro operates on OSS objects and
Guardian objects some types of Guardian objects. The extent of support for
Guardian objects differs for each function or macro.

OSS objects and limited Guardian objects The function or macro operates on OSS objects and some
types of Guardian objects. The extent of support for
Guardian objects differs for each function or macro.

OSS objects only The function or macro operates only on OSS objects.

OSS parameters only The function or macro requires OSS parameters (OSS
pathname, stream pointer, file descriptor, or process
identifier).

Parameters must match module When called from a Guardian module, the function or
macro requires Guardian parameters. When called from
an OSS module, the function or macro requires OSS
parameters.
If the function or macro operates on an open file, the file
must have been opened in a module of the same
environment.

Parameters must match process When called from a Guardian process, the function or
macro requires Guardian parameters. When called from
an OSS process, the function or macro requires OSS
parameters.
If the function or macro operates on an open file, the file
must have been opened in a module of the same
environment.

_PUT_MODEL_ To use this function with the PUT library on systems


running J06.10 or later RVUs or H06.21 or later RVUs, the
feature test macro _PUT_MODEL_ must be specified
when you compile the application.

_PUT_MODEL_ or To use this function with the PUT library on systems


_SPT_MODEL_ running J06.10 or later RVUs or H06.21 or later RVUs, the
feature test macro _PUT_MODEL_ must be specified
when you compile the application, or to use this function
with the SPT library on systems running J06.10 or later
RVUs or H06.21 or later RVUs, the feature test macro
_SPT_MODEL_ must be specified when you compile the
application.

_SPT_MODEL_ To use this function with the SPT library on systems


running J06.10 or later RVUs or H06.21 or later RVUs, the
feature test macro _SPT_MODEL_ must be specified when
you compile the application.

SPT_THREAD_AWARE or An application call to interface() is automatically


SPT_THREAD_AWARE_PRAGMA mapped to this spt_interface() function when you
use the #define SPT_THREAD_AWARE feature test macro
(for C applications) or the #define
SPT_THREAD_AWARE_PRAGMA (for C++ applications) or
an equivalent compiler command option to compile the
application.

SPT_THREAD_AWARE_ NONBLOCK or An application call to interface() is automatically


SPT_THREAD_AWARE_ PRAGMA_NONBLOCK mapped to this spt_interfacex() function when you
use the #define SPT_THREAD_AWARE_NONBLOCK
feature test macro (for C applications) or the #define
SPT_THREAD_AWARE_PRAGMA_NONBLOCK (for C++
applications) or an equivalent compiler command option
to compile the application.

Using the API Interoperability Tables 455


Usage Note Meaning

SPT_THREAD_AWARE_ XNONBLOCK or An application call to interface() is automatically


SPT_THREAD_AWARE_ PRAGMA_XNONBLOCK mapped to this spt_interfacez() function when you
use the #define SPT_THREAD_AWARE_XNONBLOCK
feature test macro (for C applications) or the #define
SPT_THREAD_AWARE_PRAGMA_XNONBLOCK (for C++
applications) or an equivalent compiler command option
to compile the application.
If a function has a corresponding spt_*x() function but
not a corresponding spt_*z() function, the function is
mapped to the corresponding spt_*x() function.

SPT_THREAD_AWARE_SIGNAL To enable thread-aware behavior for this function, the


SPT_THREAD_AWARE_SIGNAL environmental variable
must be exported to 1.

SPT_THREAD_SIGNAL or An application call to interface() is automatically


SPT_THREAD_SIGNAL_PRAGMA mapped to this spt_interface() function when you
use the #define SPT_THREAD_SIGNAL feature test
macro (for C applications) or the #define
SPT_THREAD_SIGNAL_PRAGMA (for C++ applications)
or an equivalent compiler command option to compile
the application

_XOPEN_SOURCE_EXTENDED The function or macro requires that the feature-test macro


_XOPEN_SOURCE_EXTENDED be specified when you
compile the module.

_XOPEN_SOURCE_EXTENDED or The function or macro requires that the feature-test macro


_TANDEM_SOURCE _XOPEN_SOURCE_EXTENDED or _TANDEM_SOURCE
be specified when you compile the module.

Examples
The following examples illustrate how to use Table C-1 (page 457) to determine how functions
and macros can be used in Guardian and OSS programs.
1. The following information can be derived about the edfseek() function:
• Is an extension specified by HP.
• Can be called only from a Guardian module.
• Can be called from Guardian and OSS processes.
• Requires Guardian parameters.
• Operates only on Guardian objects.
• Because it is specified by HP, it requires the _TANDEM_SOURCE feature-test macro.
2. The following information can be derived about the free() function:
• Specified in the ISO/ANSI C standard.
• Can be called from Guardian and OSS modules.
• Can be called from Guardian and OSS processes.
3. The following information can be derived about the rename() function:
• Specified in the ISO/ANSI C standard.
• Can be called from Guardian and OSS modules.
• Can be called from Guardian and OSS processes.
• Guardian function operates only on Guardian objects; OSS function operates on OSS
objects and limited Guardian objects.

456 API Interoperability in Native Processes


4. The following information can be derived about the rename_oss() function:
• Is an extension specified by HP.
• Can be called from Guardian or OSS modules.
• Can be called from Guardian or OSS processes.
• Must be called with OSS parameters.
• Operates on OSS objects and limited Guardian objects.
• Because it is specified by HP, it requires the _TANDEM_SOURCE feature-test macro.
Table C-1 API Interoperability in Native Processes (Functions a through m)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

a64l() XPG4 G, O G, O

abort() ISO G, O G, O

_abs() HP G, O G, O

abs() ISO G, O G, O

accept() XPG4 O O _PUT_MODEL_


_XOPEN_SOURCE_EXTENDED

access() POSIX G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

acl() HP G, O G, O Available on Version 3 OSS


filesets only

aclsort() HP G, O G, O Available on Version 3 OSS


filesets only

acos() ISO G, O G, O

acosf() ISO G, O G, O

acosh() ISO G, O G, O

acoshf() ISO G, O G, O

acoshl() ISO G, O G, O

acosl() ISO G, O G, O

advance() The functionality provided by


this macro is defined as
obsolete in POSIX. Functions
such as regcomp() and
regexec() should be used
instead.

alarm() POSIX G, O G, O _PUT_MODEL_

asctime() ISO G, O G, O

asctime_r() Threads G, O G, O _SPT_MODEL_

asin() ISO G, O G, O

asinf() ISO G, O G, O

asinh() ISO G, O G, O

asinhf() ISO G, O G, O

asinhl() ISO G, O G, O

Using the API Interoperability Tables 457


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

asinl() ISO G, O G, O

assert() ISO G, O G, O

atan() ISO G, O G, O

atanf() ISO G, O G, O

atanh() ISO G, O G, O

atanhf() ISO G, O G, O

atanhl() ISO G, O G, O

atanl() ISO G, O G, O

atan2() ISO G, O G, O

atan2f() ISO G, O G, O

atan2l() ISO G, O G, O

atexit() ISO G, O G, O

atof() ISO G, O G, O

atoi() ISO G, O G, O

atol() ISO G, O G, O

atoll() ISO G, O G, O

basename() POSIX O O

bcmp() XPG4 G, O G, O

bcopy() XPG4 G, O G, O

bind() XPG4 O O _XOPEN_SOURCE_EXTENDED

bsearch() ISO G, O G, O

btowc() ISO G, O G, O

bzero() XPG4 G, O G, O

cabs() ISO G, O G, O IEEE_float only

cabsf() ISO G, O G, O IEEE_float only

cabsl() ISO G, O G, O IEEE_float only

cacos() ISO G, O G, O IEEE_float only

cacosf() ISO G, O G, O IEEE_float only

cacosh() ISO G, O G, O IEEE_float only

cacoshf() ISO G, O G, O IEEE_float only

cacoshl() ISO G, O G, O IEEE_float only

cacosl() ISO G, O G, O IEEE_float only

calloc() ISO G, O G, O

carg() ISO G, O G, O IEEE_float only

cargf() ISO G, O G, O IEEE_float only

458 API Interoperability in Native Processes


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

cargl() ISO G, O G, O IEEE_float only

casin() ISO G, O G, O IEEE_float only

casinf() ISO G, O G, O IEEE_float only

casinh() ISO G, O G, O IEEE_float only

casinhf() ISO G, O G, O IEEE_float only

casinhl() ISO G, O G, O IEEE_float only

casinl() ISO G, O G, O IEEE_float only

catan() ISO G, O G, O IEEE_float only

catanf() ISO G, O G, O IEEE_float only

catanh() ISO G, O G, O IEEE_float only

catanhf() ISO G, O G, O IEEE_float only

catanhl() ISO G, O G, O IEEE_float only

catanl() ISO G, O G, O IEEE_float only

catclose() XPG4 O O OSS parameters only

catgets() XPG4 O O OSS parameters only

catopen() XPG4 O O OSS parameters only

cbrt() XPG4 G, O G, O

cbrtf() ISO G, O G, O

cbrtl() ISO G, O G, O

ccos() ISO G, O G, O IEEE_float only

ccosf() ISO G, O G, O IEEE_float only

ccosh() ISO G, O G, O IEEE_float only

ccoshf() ISO G, O G, O IEEE_float only

ccoshl() ISO G, O G, O IEEE_float only

ccosl() ISO G, O G, O IEEE_float only

ceil() ISO G, O G, O

ceilf() ISO G, O G, O

ceill() ISO G, O G, O

cexp() ISO G, O G, O IEEE_float only

cexpf() ISO G, O G, O IEEE_float only

cexpl() ISO G, O G, O IEEE_float only

cfgetispeed() POSIX G, O G, O

cfgetospeed() POSIX G, O G, O

cfsetispeed() POSIX G, O G, O

cfsetospeed() POSIX G, O G, O

Using the API Interoperability Tables 459


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

chdir() POSIX G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

chmod() POSIX G, O G, O OSS objects only

chown() POSIX G, O G, O OSS objects and limited


Guardian objects

chroot() XPG4 G, O G, O

chvol() HP G G, O

cimag() ISO G, O G, O IEEE_float only

cimagf() ISO G, O G, O IEEE_float only

cimagl() ISO G, O G, O IEEE_float only

clearerr() ISO G, O G, O

clock() ISO G, O G, O

clog() ISO G, O G, O IEEE_float only

clogf() ISO G, O G, O IEEE_float only

clogl() ISO G, O G, O IEEE_float only

close() XPG4 O O OSS parameters only


OSS objects and limited
Guardian objects
_PUT_MODEL_

closedir() POSIX O G, O OSS parameters only


OSS objects and limited
Guardian objects

closelog() X/OPEN G, O G, O

compile() The functionality provided by


this macro is defined as
obsolete in POSIX. Functions
such as regcomp() and
regexec() should be used
instead.

confstr() XPG4 G, O G, O

conj() ISO G, O G, O IEEE_float only

conjf() ISO G, O G, O IEEE_float only

conjl() ISO G, O G, O IEEE_float only

connect() XPG4 O O _PUT_MODEL_


_XOPEN_SOURCE_EXTENDED

copysign() ISO G, O G, O

copysignf() ISO G, O G, O

copysignl() ISO G, O G, O

cos() ISO G, O G, O

460 API Interoperability in Native Processes


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

cosf() ISO G, O G, O

cosh() ISO G, O G, O

coshf() ISO G, O G, O

coshl() ISO G, O G, O

cosl() ISO G, O G, O

cpow() ISO G, O G, O IEEE_float only

cpowf() ISO G, O G, O IEEE_float only

cpowl() ISO G, O G, O IEEE_float only

cproj() ISO G, O G, O IEEE_float only

cprojf() ISO G, O G, O IEEE_float only

cprojl() ISO G, O G, O IEEE_float only

creal() ISO G, O G, O IEEE_float only

crealf() ISO G, O G, O IEEE_float only

creall() ISO G, O G, O IEEE_float only

creat() XPG4 G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

creat64() XLFS G, O G, O OSS parameters only


OSS objects and limited
Guardian objects
_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS

crypt() XPG4 G, O G, O

csin() ISO G, O G, O IEEE_float only

csinf() ISO G, O G, O IEEE_float only

csinh() ISO G, O G, O IEEE_float only

csinhf() ISO G, O G, O IEEE_float only

csinhl() ISO G, O G, O IEEE_float only

csinl() ISO G, O G, O IEEE_float only

csqrt() ISO G, O G, O

csqrtf() ISO G, O G, O

csqrtl() ISO G, O G, O

ctan() ISO G, O G, O IEEE_float only

ctanf() ISO G, O G, O IEEE_float only

ctanh() ISO G, O G, O IEEE_float only

ctanhf() ISO G, O G, O IEEE_float only

ctanhl() ISO G, O G, O IEEE_float only

Using the API Interoperability Tables 461


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

ctanl() ISO G, O G, O IEEE_float only

ctermid() POSIX O O OSS parameters only

ctermid_r() Threads O O OSS parameters only


_SPT_MODEL_

ctime() ISO G, O G, O

ctime_r() Threads G, O G, O _SPT_MODEL_

cuserid() XPG4 G, O G, O

dbm_clearerr() XPG4 O O

dbm_close() XPG4 O O

dbm_delete() XPG4 O O

dbm_error() XPG4 O O

dbm_fetch() XPG4 O O

dbm_firstkey() XPG4 O O

dbm_nextkey() XPG4 O O

dbm_open() XPG4 O O

dbm_store XPG4 O O

dec_to_longlong() HP G, O G, O

difftime() ISO G, O G, O

dirname() POSIX O O

div() ISO G, O G, O

dlclose() HP G, O G, O

dlerror() HP G, O G, O

dlopen() HP G, O G, O

dlresultcode() HP G, O G, O

dlsym() HP G, O G, O

drand48() XPG4 G, O G, O

dup() POSIX O O OSS parameters only


OSS objects and limited
Guardian objects

dup2() POSIX O O OSS parameters only


OSS objects and limited
Guardian objects
_PUT_MODEL_

ecvt() HP G, O G, O Data can be overwritten by a


subsequent call

edfseek() HP G G, O Guardian parameters only


Guardian objects only

462 API Interoperability in Native Processes


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

edftell() HP G G, O Guardian parameters only


Guardian objects only

encrypt() XPG4 G, O G, O

endgrent() POSIX G, O G, O

endhostent() XPG4 O O

endnetent() XPG4 O O

endprotoent() XPG4 O O

endpwent() X/OPEN G, O G, O _XOPEN_SOURCE_EXTENDED


or
_TANDEM_SOURCE

endservent() XPG4 O O

erand48() XPG4 G, O G, O

erf() XPG4 G, O G, O

erfc() XPG4 G, O G, O

erfcf() ISO G, O G, O

erfcl() ISO G, O G, O

erff() ISO G, O G, O

erfl() ISO G, O G, O

exec() POSIX O O OSS objects only

execl() POSIX O O OSS objects only

execle() POSIX O O OSS objects only

execlp() POSIX O O OSS objects only

execv() POSIX O O OSS objects only

execve() POSIX O O OSS objects only

execvp() POSIX O O OSS objects only

_exit() POSIX G, O G, O Nowait considerations when


_Exit() called from the Guardian API

exit() ISO G, O G, O

exp() ISO G, O G, O

expf() ISO G, O G, O

expl() ISO G, O G, O

expml() XPG4 G, O G, O

expmlf() ISO G, O G, O

expmll() ISO G, O G, O

exp2() ISO G, O G, O IEEE_float only

exp2f() ISO G, O G, O IEEE_float only

Using the API Interoperability Tables 463


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

exp2l() ISO G, O G, O IEEE_float only

fabs() ISO G, O G, O

fabsf() ISO G, O G, O

fabsl() ISO G, O G, O

fchmod() POSIX G, O G, O OSS objects only

fchown() POSIX G, O G, O OSS objects and limited


Guardian objects

fclose() ISO G, O G, O

fcntl() XPG4 O O OSS parameters only


OSS objects only
_PUT_MODEL_

fcvt() XPG4 G, O G, O

fdim() ISO G, O G, O IEEE_float only

fdimf() ISO G, O G, O IEEE_float only

fdiml() ISO G, O G, O IEEE_float only

fdopen() XPG4 G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

feclearexcept() ISO G, O G, O IEEE_float only

fegetenv() ISO G, O G, O IEEE_float only

fegetexceptflag() ISO G, O G, O IEEE_float only

fegetround() ISO G, O G, O IEEE_float only

feholdexcept() ISO G, O G, O IEEE_float only

feof() ISO G, O G, O

feraiseexcept() ISO G, O G, O IEEE_float only

ferror() ISO G, O G, O

fesetenv() ISO G, O G, O IEEE_float only

fesetexceptflag() ISO G, O G, O IEEE_float only

fesetround() ISO G, O G, O IEEE_float only

fetestexcept() ISO G, O G, O IEEE_float only

feupdateenv() ISO G, O G, O IEEE_float only

fflush() ISO G, O G, O

ffs() XPG4 G, O G, O

fgetc() ISO G, O G, O

fgetpos() ISO G, O G, O

fgetpos64() XLFS G, O G, O _LARGEFILE64_SOURCE or


_FILE_OFFSET_BITS

464 API Interoperability in Native Processes


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

fgets() ISO G, O G, O

fgetwc() XPG4 G, O G, O

fgetws() XPG4 G, O G, O

fileno() XPG4 G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

finite() XPG4 G, O G, O

flockfile() Threads G, O G, O

floor() ISO G, O G, O

floorf() ISO G, O G, O

floorl() ISO G, O G, O

fma() ISO G, O G, O IEEE_float only

fmaf() ISO G, O G, O IEEE_float only

fmal() ISO G, O G, O IEEE_float only

fmax() ISO G, O G, O IEEE_float only

fmaxf() ISO G, O G, O IEEE_float only

fmaxl() ISO G, O G, O IEEE_float only

fmin() ISO G, O G, O IEEE_float only

fminf() ISO G, O G, O IEEE_float only

fminl() ISO G, O G, O IEEE_float only

fmod() ISO G, O G, O

fmodf() ISO G, O G, O

fmodl() ISO G, O G, O

fmtmsg() XPG4 O O

fnmatch() POSIX O O

fopen() ISO G, O G, O Parameters must match


process
Guardian function operates
only on Guardian objects
OSS function operates on OSS
objects and limited Guardian
objects

fopen_guardian() HP G, O G, O Guardian parameters only


Guardian objects only

fopen_oss() HP G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

fopen_std_file() HP G G

Using the API Interoperability Tables 465


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

fopen64() XLFS G, O G, O Parameters must match


process
Guardian function operates
only on Guardian objects
OSS function operates on OSS
objects and limited Guardian
objects_LARGEFILE64_SOURCE
or _FILE_OFFSET_BITS

fopen64_guardian() XLFS G, O G, O Guardian parameters only


Guardian objects
only_LARGEFILE64_SOURCE
or _FILE_OFFSET_BITS

fopen64_oss() XLFS G, O G, O OSS parameters only


OSS objects and limited
Guardian
objects_LARGEFILE64_SOURCE
or _FILE_OFFSET_BITS

fopen64_std_file() XLFS G G _LARGEFILE64_SOURCE or


_FILE_OFFSET_BITS

fork() POSIX O O OSS objects only


_PUT_MODEL_

fp_class() HP G, O G, O HP extension to XPG4

fpathconf() POSIX G, O G, O OSS parameters only

fpclassify() ISO G, O G, O IEEE_float only

fprintf() ISO G, O G, O

fputc() ISO G, O G, O

fputs() ISO G, O G, O

fputwc() XPG4 G, O G, O

fputws() XPG4 G, O G, O

fread() ISO G, O G, O

free() ISO G, O G, O

freeaddrinfo() XPG4 O O

freehostent() XPG4 O O

freopen() ISO G, O G, O Parameters must match


process
Guardian function operates
only on Guardian objects
OSS function operates on OSS
objects and limited Guardian
objects

freopen_guardian() HP G, O G, O Guardian parameters only


Guardian objects only

466 API Interoperability in Native Processes


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

freopen_oss() HP G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

freopen64() XLFS G, O G, O Parameters must match


process
Guardian function operates
only on Guardian objects
OSS function operates on OSS
objects and limited Guardian
objects_LARGEFILE64_SOURCE
or _FILE_OFFSET_BITS

freopen64_guardian() XLFS G, O G, O Guardian parameters only


Guardian objects
only_LARGEFILE64_SOURCE
or _FILE_OFFSET_BITS

freopen64_oss() XLFS G, O G, O OSS parameters only


OSS objects and limited
Guardian
objects_LARGEFILE64_SOURCE
or _FILE_OFFSET_BITS

frexp() ISO G, O G, O

frexpf() ISO G, O G, O

frexpl() ISO G, O G, O

fscanf() ISO G, O G, O

fseek() ISO G, O G, O

fseeko() XLFS G, O G, O _LARGEFILE64_SOURCE

fseeko64() XLFS G, O G, O _LARGEFILE64_SOURCE or


_FILE_OFFSET_BITS

fsetpos() ISO G, O G, O

fsetpos64() XLFS G, O G, O _LARGEFILE64_SOURCE or


_FILE_OFFSET_BITS

fstat() POSIX O O OSS parameters only


OSS objects and limited
Guardian objects
_PUT_MODEL_

fstat64() XLFS O O OSS parameters only


OSS objects and limited
Guardian
objects_LARGEFILE64_SOURCE
or _FILE_OFFSET_BITS
_PUT_MODEL_

fstatvfs() XPG4 O O This function provides


compatibility with the System
V Interface Definition,
Revision 3

Using the API Interoperability Tables 467


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

fstatvfs64() XLFS O O This function provides


compatibility with the System
V Interface Definition,
Revision 3
_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS

fsync() XPG4 O O _PUT_MODEL_

ftell() ISO G, O G, O

ftello() XLFS G, O G, O _LARGEFILE64_SOURCE

ftello64() XLFS G, O G, O _LARGEFILE64_SOURCE or


_FILE_OFFSET_BITS

ftime() XPG4 G, O G, O

ftok() X/OPEN O G, O OSS parameters only


OSS objects only
_XOPEN_SOURCE_EXTENDED
or
_TANDEM_SOURCE

ftruncate() XPG4 O O _PUT_MODEL_

ftruncate64 XLFS O O _LARGEFILE64_SOURCE or


_FILE_OFFSET_BITS
_PUT_MODEL_

ftrylockfile() Threads G, O G, O

ftw() XPG4 O G, O OSS parameters only


OSS objects and limited
Guardian objects

ftw64() XLFS O G, O OSS parameters only


OSS objects and limited
Guardian objects
_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS

funlockfile() Threads G, O G, O

fwide() ISO G, O G, O

fwprintf() ISO G, O G, O

fwrite() ISO G, O G, O

fwscanf() ISO G, O G, O

gai_strerror() XPG4 O O

gamma() XPG4 G, O G, O

gamma_r() Threads G, O G, O _SPT_MODEL_

gcvt() XPG4 G, O G, O

get_assign_msg() HP G G

get_assign_msg_by_name() HP G G

468 API Interoperability in Native Processes


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

get_max_assign_msg _ordinal() HP G G

get_param_by_name() HP G G

get_param_msg() HP G G

get_startup_msg() HP G G

getaddrinfo() XPG4 O O

getc() ISO G, O G, O

getc_unlocked() Threads G, O G, O

getchar() ISO G, O G, O

getchar_unlocked() Threads G, O G, O

getcwd() POSIX G, O G, O

getdate() XPG4 G, O G, O

getdtablesize() XPG4 O O

getegid() POSIX O O

getenv() ISO G, O G, O

getenv_r() HP G, O G, O

geteuid() POSIX O O

getgid() POSIX O O

getgrent() POSIX G, O G, O The functions getgrnam()


and getgrgid() should be
used instead of this function
to ensure portability to future
systems
Data is overwritten by
subsequent call or call to
getgrnam()

getgrent_r() Threads G, O G, O The functions getgrnam()


and getgrgid() should be
used instead of this function
to ensure portability to future
systems
Data is overwritten by
subsequent call or call to
getgrnam()
_SPT_MODEL_

getgrgid() POSIX G, O G, O Data is overwritten by


subsequent call or call to
getgrnam()

getgrgid_r() Threads G, O G, O _SPT_MODEL_

getgrnam() POSIX G, O G, O Data is overwritten by


subsequent call or call to
getgrgid()

getgrnam_r() Threads G, O G, O _SPT_MODEL_

getgroups() POSIX O O

Using the API Interoperability Tables 469


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

gethostbyaddr() XPG4 O O

gethostbyaddr_r() Threads O O _SPT_MODEL_

gethostbyname() XPG4 O O

gethostbyname_r() Threads O O _SPT_MODEL_

gethostbyname2() HP O O

gethostent() XPG4 O O

gethostent_r() Threads O O _SPT_MODEL_

gethostid() XPG4 O O

gethostname() XPG4 O O

getipnodebyaddr() HP O O

getipnodebyname() HP O O

getlogin() POSIX O O

getlogin_r() Threads O O _SPT_MODEL_

getnameinfo() XPG4 O O

getnetbyaddr() XPG4 O O

getnetbyaddr_r() Threads O O _SPT_MODEL_

getnetbyname() XPG4 O O

getnetbyname_r() HP O O _SPT_MODEL_

getnetent() XPG4 O O

getnetent_r() HP O O _SPT_MODEL_

getopt() XPG4 G, O G, O

getpagesize() ISO O O

getpass() XPG4 O O

getpeername() XPG4 O O _XOPEN_SOURCE_EXTENDED

getpgrp() POSIX O O OSS objects only

getpgid() XPG4 O O OSS objects only

getpid() POSIX O O OSS objects only

getppid() POSIX O O OSS objects only

getpriority() XPG4 O O OSS objects only

getprotobyname() XPG4 O O

getprotobyname_r() HP O O _SPT_MODEL_

getprotobynumber() XPG4 O O

getprotobynumber_r() HP O O _SPT_MODEL_

getprotoent() XPG4 O O

getprotoent_r() HP O O _SPT_MODEL_

470 API Interoperability in Native Processes


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

getpwent() X/OPEN G, O G, O _TANDEM_SOURCE


_XOPEN_SOURCE_EXTENDED
or

getpwent_r() HP G, O G, O _SPT_MODEL_

getpwnam() POSIX G, O G, O

getpwnam_r() Threads G, O G, O _SPT_MODEL_

getpwuid() POSIX G, O G, O

getpwuid_r() Threads G, O G, O _SPT_MODEL_

gets() ISO G, O G, O

getservbyname() XPG4 O O

getservbyname_r() HP O O _SPT_MODEL_

getservbyport() XPG4 O O

getservbyport_r() HP O O _SPT_MODEL_

getservent() XPG4 O O

getservent_r() HP O O _SPT_MODEL_

getsid() XPG4 O O

getsockname() XPG4 O O _XOPEN_SOURCE_EXTENDED

getsockopt() XPG4 O O _XOPEN_SOURCE_EXTENDED

getsubopt() XPG4 O O

gettimeofday() XPG4 O O

getuid() POSIX O O

getw() XPG4 O G, O OSS function operates on OSS


objects and limited Guardian
objects

getwc() XPG4 G, O G, O

getwchar() XPG4 G, O G, O

getwd() XPG4 O O For portability to


implementations conforming
to earlier versions of the XPG4
specification, getcwd() is
preferred over this function

getws() XPG4 G, O G, O

gfileno() HP G, O G, O Guardian parameters only

glob() POSIX G, O G, O

globfree() POSIX G, O G, O

gmtime() ISO G, O G, O

gmtime_r() Threads G, O G, O _SPT_MODEL_

HBA_CloseAdapter() FC-MI O O

Using the API Interoperability Tables 471


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

HBA_FreeLibrary() FC-MI O O

HBA_GetAdapterAttributes() FC-MI O O

HBA_GetAdapterName() FC-MI O O

HBA_GetAdapterPortAttributes() FC-MI O O

HBA_GetDiscoveredPortAttributes() FC-MI O O

HBA_GetFcpTargetMapping() FC-MI O O

HBA_GetNumberOfAdapters() FC-MI O O

HBA_GetPortStatistics() FC-MI O O

HBA_GetVersion() FC-MI O O

HBA_LoadLibrary() FC-MI O O

HBA_OpenAdapter() FC-MI O O

HBA_RefreshInformation() FC-MI O O

hcreate() XPG4 G, O G, O

hdestroy() XPG4 G, O G, O

heap_check() HP G, O G, O

heap_check_always() HP G, O G, O

heap_min_block_size() HP G, O G, O

hsearch() XPG4 G, O G, O

htonl() XPG4 O O

htons() XPG4 O O

hypot() XPG4 G, O G, O

hypotf() ISO G, O G, O

hypotl() ISO G, O G, O

iconv() XPG4 O O

iconv_close() XPG4 O O

iconv_open() XPG4 O O

if_freenameindex() XPG4 O O

if_indextoname() XPG4 O O

if_nameindex() XPG4 O O

if_nametoindex() XPG4 O O

ilogb() XPG4 G, O G, O

ilogbf() ISO G, O G, O

ilogbl() ISO G, O G, O

imaxabs() ISO G, O G, O

imaxdiv() ISO G, O G, O

472 API Interoperability in Native Processes


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

index() XPG4 G, O G, O

inet_addr() XPG4 O O

inet_lnaof() XPG4 O O

inet_makeaddr() XPG4 O O

inet_netof() XPG4 O O

inet_network() XPG4 O O

inet_ntoa() XPG4 O O

inet_ntop() XPG4 O O

inet_pton() XPG4 O O

initgroups() XPG4 O O

initstate() XPG4 G, O G, O

insque() XPG4 O O

ioctl() X/OPEN G, O G, O

isalnum() ISO G, O G, O

isalpha() ISO G, O G, O

isascii() XPG4 G, O G, O

isatty() POSIX G, O G, O OSS parameters only

isblank() ISO G, O G, O

iscntrl() ISO G, O G, O

isdigit() ISO G, O G, O

isfinite() ISO G, O G, O IEEE_float only

isgraph() ISO G, O G, O

isgreater() ISO G, O G, O IEEE_float only

isgreaterequal() ISO G, O G, O IEEE_float only

isinf() ISO G, O G, O IEEE_float only

isless() ISO G, O G, O IEEE_float only

islessequal() ISO G, O G, O IEEE_float only

islessgreater() ISO G, O G, O IEEE_float only

islower() ISO G, O G, O

isnan() function ISO G, O G, O Returns a value of 0 (zero) for


Tandem floating-point data.

isnan() macro ISO G, O G, O IEEE_float only

isnormal() ISO G, O G, O IEEE_float only

isprint() ISO G, O G, O

ispunct() ISO G, O G, O

Using the API Interoperability Tables 473


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

isspace() ISO G, O G, O

isunordered() ISO G, O G, O IEEE_float only

isupper() ISO G, O G, O

iswalnum() XPG4 G, O G, O

iswalpha() XPG4 G, O G, O

iswblank() ISO G, O G, O

iswcntrl() XPG4 G, O G, O

iswctype() XPG4 G, O G, O

iswdigit() XPG4 G, O G, O

iswgraph() XPG4 G, O G, O

iswlower() XPG4 G, O G, O

iswprint() XPG4 G, O G, O

iswpunct() XPG4 G, O G, O

iswspace() XPG4 G, O G, O

iswupper() XPG4 G, O G, O

iswxdigit() XPG4 G, O G, O

isxdigit() XPG4 G, O G, O

j0() XPG4 G, O G, O

j1() XPG4 G, O G, O

jn() XPG4 G, O G, O

jrand48() XPG4 G, O G, O

kill() POSIX O O OSS objects only

l64a() XPG4 G, O G, O

labs() ISO G, O G, O

lchmod() HP G, O G, O OSS objects only

lchown() POSIX G, O G, O OSS objects and limited


Guardian objects

lcong48() XPG4 G, O G, O

ldexp() ISO G, O G, O

ldexpf() ISO G, O G, O

ldexpl() ISO G, O G, O

ldiv() ISO G, O G, O

lfind() XPG4 G, O G, O

lgamma() XPG4 G, O G, O

lgammaf() ISO G, O G, O

474 API Interoperability in Native Processes


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

lgammal() ISO G, O G, O

lgamma_r() Threads G, O G, O _SPT_MODEL_

link() POSIX O G, O OSS parameters only


OSS objects only

listen() XPG4 O O _XOPEN_SOURCE_EXTENDED

llabs() ISO G, O G, O

lldiv() XPG4 G, O G, O

llrint() ISO G, O G, O IEEE_float only

llrintf() ISO G, O G, O IEEE_float only

llrintl() ISO G, O G, O IEEE_float only

llround() ISO G, O G, O IEEE_float only

llroundf() ISO G, O G, O IEEE_float only

llroundl() ISO G, O G, O IEEE_float only

localeconv() ISO G, O G, O

localtime() ISO G, O G, O

localtime_r() Threads G, O G, O _SPT_MODEL_

log() ISO G, O G, O

logb() XPG4 G, O G, O

logbf() ISO G, O G, O

logbl() ISO G, O G, O

logf() ISO G, O G, O

logl() ISO G, O G, O

loglp() XPG4 G, O G, O

loglpf() ISO G, O G, O

loglpl() ISO G, O G, O

log2() ISO G, O G, O IEEE_float only

log2f() ISO G, O G, O IEEE_float only

log2l() ISO G, O G, O IEEE_float only

log10() ISO G, O G, O

log10f() ISO G, O G, O

log10l() ISO G, O G, O

longjmp() ISO G, O G, O

longlong_to_dec() HP G, O G, O

lrand48() XPG4 G, O G, O

lrint() ISO G, O G, O IEEE_float only

Using the API Interoperability Tables 475


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

lrintf() ISO G, O G, O IEEE_float only

lrintl() ISO G, O G, O IEEE_float only

lround() ISO G, O G, O IEEE_float only

lroundf() ISO G, O G, O IEEE_float only

lroundl() ISO G, O G, O IEEE_float only

lsearch() XPG4 G, O G, O

lseek() XPG4 O O OSS parameters only


OSS objects and Guardian
objects
_PUT_MODEL_

lseek64() XLFS O O OSS parameters only


OSS objects and Guardian
objects
_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS
_PUT_MODEL_

lstat() X/OPEN G, O G, O _XOPEN_SOURCE_EXTENDED

lstat64() XLFS G, O G, O _XOPEN_SOURCE_EXTENDED


_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS

lwres_freeaddrinfo() HP O O

lwres_freehostent() HP O O

lwres_gai_strerror() HP O O

lwres_getaddrinfo() HP O O

lwres_gethostbyaddr() HP O O

lwres_gethostbyname() HP O O

lwres_gethostbyname2() HP O O

lwres_getipnodebyaddr() HP O O

lwres_getipnodebyname() HP O O

lwres_getnameinfo() HP O O

lwres_hstrerror() HP O O

malloc() ISO G, O G, O

malloc_pages() HP G, O G, O This function can be called by


TNS/E native processes only

_max() HP G, O G, O

mblen() ISO G, O G, O

mbrlen() ISO G, O G, O

mbrtowc() ISO G, O G, O

mbsinit() ISO G, O G, O

476 API Interoperability in Native Processes


Table C-1 API Interoperability in Native Processes (Functions a through m) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

mbsrtowcs() ISO G, O G, O

mbstowcs() ISO G, O G, O

mbtowc() ISO G, O G, O

memccpy() ISO G, O G, O

memchr() ISO G, O G, O

memcmp() ISO G, O G, O

memcpy() ISO G, O G, O

memmove() ISO G, O G, O

memset() ISO G, O G, O

_min() HP G, O G, O

mkdir() POSIX G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

mkfifo() POSIX G, O G, O OSS parameters only

mknod() X/OPEN G, O G, O _XOPEN_SOURCE_EXTENDED

mkstemp() XPG4 O O

mktemp() XPG4 O O

mktime() ISO G, O G, O

modf() ISO G, O G, O

modff() ISO G, O G, O

modfl() ISO G, O G, O

mrand48() XPG4 G, O G, O

msgctl() XPG4 O O OSS objects only

msgget() XPG4 O O OSS objects only

msgrcv() XPG4 O O OSS objects only

msgsnd() XPG4 O O OSS objects only

Using the API Interoperability Tables 477


Table C-2 API Interoperability in Native Processes (Functions n through z)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

nan() ISO G, O G, O IEEE_float only

nanf() ISO G, O G, O IEEE_float only

nanl() ISO G, O G, O IEEE_float only

nearbyint() ISO G, O G, O IEEE_float only

nearbyintf() ISO G, O G, O IEEE_float only

nearbyintl() ISO G, O G, O IEEE_float only

nextafter() XPG4 G, O G, O

nextafterf() ISO G, O G, O

nextafterl() ISO G, O G, O

nexttoward() ISO G, O G, O IEEE_float only

nexttowardf() ISO G, O G, O IEEE_float only

nexttowardl() ISO G, O G, O IEEE_float only

nftw() XPG4 O G, O OSS parameters only


OSS objects and limited
Guardian objects

nftw64() XLFS G, O G, O OSS parameters only


OSS objects and limited
Guardian objects
_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS

nice() XPG4 G, O G, O OSS objects and limited


Guardian objects

nl_langinfo() XPG4 G, O G, O

nlist() HP G, O G, O

nrand48() XPG4 G, O G, O

ntohl() XPG4 O O

ntohs() XPG4 O O

open() XPG4 G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

open64() XLFS G, O G, O OSS parameters only


OSS objects and limited
Guardian objects
_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS

opendir() POSIX G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

openlog() X/OPEN G, O G, O Limited when called from


Guardian process

pathconf() POSIX G, O G, O OSS parameters only

478 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

pause() POSIX G, O G, O _PUT_MODEL_

pclose() POSIX O O OSS parameters only

perror() ISO G, O G, O

pipe() POSIX O G, O OSS parameters only

popen() POSIX O O OSS parameters only

pow() ISO G, O G, O

powf() ISO G, O G, O

powl() ISO G, O G, O

printf() ISO G, O G, O

pthread_atfork() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_destroy() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_getdetachstate() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_getguardsize() Threads O O OSS objects only


_PUT_MODEL_

pthread_attr_getguardsize_ np() Threads O O OSS objects only

pthread_attr_ getinheritsched() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_ getschedparam() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_ getschedpolicy() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_getscope() Threads O O OSS objects only


_PUT_MODEL_

pthread_attr_getstackaddr() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_getstacksize() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_init() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

Using the API Interoperability Tables 479


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

pthread_attr_setdetachstate() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_setguardsize() Threads O O OSS objects only


_PUT_MODEL_

pthread_attr_setguardsize_ np() Threads O O OSS objects only

pthread_attr_setinheritsched() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_setschedparam() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_setschedpolicy() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_attr_setscope() Threads O O OSS objects only


_PUT_MODEL_

pthread_attr_setstacksize() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_cancel() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_cleanup_pop() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_cleanup_push() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_cond_broadcast() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_cond_destroy() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_cond_init() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_cond_signal() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_cond_signal_int_ np() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

480 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

pthread_cond_timedwait() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_cond_wait() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_condattr_destroy() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_condattr_init() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_create() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_delay_np() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_detach() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_equal() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_exit() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_get_expiration_np() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_getattr_np() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_getconcurrency() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_getschedparam() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_getspecific() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_getthreadstateinfo_np() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

Using the API Interoperability Tables 481


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

pthread_join() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_key_create() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_key_delete() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_kill() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_kill_np() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_lock_global_np() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_mutex_destroy() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_mutex_init() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_mutex_lock() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_mutex_trylock() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_mutex_unlock() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_mutexattr_destroy() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_mutexattr_getkind _np() Threads O O OSS objects only

pthread_mutexattr_gettype() Threads O O OSS objects only


_PUT_MODEL_

pthread_mutexattr_init() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_mutexattr_setkind _np() Threads O O OSS objects only

482 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

pthread_mutexattr_settype() Threads O O OSS objects only


_PUT_MODEL_

pthread_once() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_self() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_setcancelstate() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_setcanceltype() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_setconcurrency() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_setschedparam() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_setspecific() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_sigmask() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_signal_to_cancel_np() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_testcancel() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

pthread_unlock_global_np() Threads O O OSS objects only


_PUT_MODEL_ or
_SPT_MODEL_

PUT_ABORTTRANSACTION() HP O O Guardian objects only


_PUT_MODEL_

put_awaitio() Threads O O OSS objects only


_PUT_MODEL_

PUT_BEGINTRANSACTION() HP O O Guardian objects only


_PUT_MODEL_

PUT_CANCEL() HP O O Guardian objects only


_PUT_MODEL_

Using the API Interoperability Tables 483


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

PUT_CONTROL() HP O O Guardian objects only


_PUT_MODEL_

PUT_ENDTRANSACTION() HP O O Guardian objects only


_PUT_MODEL_

put_fd_read_ready() Threads O O OSS objects only


_PUT_MODEL_

put_fd_write_ready() Threads O O OSS objects only


_PUT_MODEL_

PUT_FILE_CLOSE_() HP O O Guardian objects only


_PUT_MODEL_

PUT_FILE_OPEN_() HP O O Guardian objects only


_PUT_MODEL_

put_generateTag() Threads O O OSS objects only


_PUT_MODEL_

put_getTMFConcurrentTransactions() Threads O O OSS objects only


_PUT_MODEL_

put_INITRECEIVE() HP O O Guardian objects only


_PUT_MODEL_

put_INITRECEIVEL() HP O O Guardian objects only


_PUT_MODEL_

put_interrupt() Threads O O OSS objects only


_PUT_MODEL_

put_interruptTag() Threads O O OSS objects only


_PUT_MODEL_

PUT_LOCKFILE() HP O O Guardian objects only


_PUT_MODEL_

PUT_LOCKREC() HP O O Guardian objects only


_PUT_MODEL_

PUT_READLOCKX() HP O O Guardian objects only


_PUT_MODEL_

PUT_READUPDATELOCKX() HP O O Guardian objects only


_PUT_MODEL_

PUT_READUPDATEX() HP O O Guardian objects only


_PUT_MODEL_

PUT_READX() HP O O Guardian objects only


_PUT_MODEL_

put_RECEIVEREAD() HP O O Guardian objects only


_PUT_MODEL_

put_RECEIVEREADL() HP O O Guardian objects only


_PUT_MODEL_

484 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

put_regFile() Threads O O OSS objects only


_PUT_MODEL_

put_regFileIOHandler() Threads O O OSS objects only


_PUT_MODEL_

put_regOSSFileIOHandler() Threads O O OSS objects only


_PUT_MODEL_

put_regPathsendFile() Threads O O OSS objects only


_PUT_MODEL_

put_regPathsendTagHandler() Threads O O OSS objects only


_PUT_MODEL_

put_regTimerHandler() Threads O O OSS objects only


_PUT_MODEL_

put_REPLYX() HP O O Guardian objects only


_PUT_MODEL_

put_REPLYXL() HP O O Guardian objects only


_PUT_MODEL_

PUT_RESUMETRANSACTION() HP O O Guardian objects only


_PUT_MODEL_

put_regTimerHandler() Threads O O OSS objects only


_PUT_MODEL_

put_regTimerHandler() Threads O O OSS objects only


_PUT_MODEL_

put_select_single_np() Threads O O Requires both _PUT_MODEL_


and _PUT_SELECT_SINGLE_
feature test macros be
specified when you compile
the application.

PUT_SERVERCLASS_DIALOG_ABORT_() HP O O Guardian objects only


_PUT_MODEL_

PUT_SERVERCLASS_DIALOG_BEGIN_() HP O O Guardian objects only


_PUT_MODEL_

PUT_SERVERCLASS_DIALOG_END_() HP O O Guardian objects only


_PUT_MODEL_

PUT_SERVERCLASS_DIALOG_SEND_() HP O O Guardian objects only


_PUT_MODEL_

PUT_SERVERCLASS_SEND_() HP O O Guardian objects only


_PUT_MODEL_

PUT_SERVERCLASS_SEND_INFO_() HP O O Guardian objects only


_PUT_MODEL_

PUT_SERVERCLASS_SENDL_() HP O O Guardian objects only


_PUT_MODEL_

Using the API Interoperability Tables 485


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

PUT_SETMODE() HP O O Guardian objects only


_PUT_MODEL_

put_setOSSFileIOHandler() HP O O OSS objects only


_PUT_MODEL_

put_setTMFConcurrentTransactions() Threads O O OSS objects only


_PUT_MODEL_

PUT_TMF_GetTxHandle() Threads O O OSS objects only


_PUT_MODEL_

PUT_TMF_Init() Threads O O OSS objects only


_PUT_MODEL_

PUT_TMF_RESUME() Threads O O OSS objects only


_PUT_MODEL_

PUT_TMF_SetAndValidateTxHandle() Threads O O OSS objects only


_PUT_MODEL_

PUT_TMF_SetTxHandle() Threads O O OSS objects only


_PUT_MODEL_

PUT_TMF_SUSPEND() Threads O O OSS objects only


_PUT_MODEL_

PUT_UNLOCKFILE() HP O O Guardian objects only


_PUT_MODEL_

PUT_UNLOCKREC() HP O O Guardian objects only


_PUT_MODEL_

put_unregFile() Threads O O OSS objects only


_PUT_MODEL_

put_unregOSSFileIOHandler() HP O O OSS objects only


_PUT_MODEL_

put_unregPathsendTagHandler() Threads O O OSS objects only


_PUT_MODEL_

put_wakeup() Threads O O OSS objects only


_PUT_MODEL_

PUT_WRITEREADX() HP O O Guardian objects only


_PUT_MODEL_

PUT_WRITEUPDATEUNLOCKX() HP O O Guardian objects only


_PUT_MODEL_

PUT_WRITEUPDATEX() HP O O Guardian objects only


_PUT_MODEL_

PUT_WRITEX() HP O O Guardian objects only


_PUT_MODEL_

putc() ISO G, O G, O

486 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

putc_unlocked() Threads G, O G, O

putchar() ISO G, O G, O

putchar_unlocked() Threads G, O G, O

putenv() XPG4 G, O G, O

puts() ISO G, O G, O

putw() XPG4 G, O G, O

putwc() XPG4 G, O G, O

putwchar() XPG4 G, O G, O

putws() XPG4 G, O G, O

qsort() ISO G, O G, O

raise() ISO G, O G, O

rand() ISO G, O G, O

rand_r() Threads G, O G, O _SPT_MODEL_

random() XPG4 G, O G, O

re_comp() XPG4 G, O G, O The behavior of this function


in locales other than POSIX is
undefined

re_exec() XPG4 G, O G, O The behavior of this function


in locales other than POSIX is
undefined

read() XPG4 O O OSS parameters only


OSS objects and limited
Guardian objects
_PUT_MODEL_

readdir() POSIX G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

readdir_r() Threads G, O G, O OSS parameters only


OSS objects and limited
Guardian objects
_SPT_MODEL_

readdir64() XLFS G, O G, O OSS parameters only


OSS objects and limited
Guardian objects
_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS

readdir64_r() Threads G, O G, O OSS parameters only


OSS objects and limited
Guardian objects
_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS
_SPT_MODEL_

Using the API Interoperability Tables 487


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

readlink() X/OPEN G, O G, O OSS objects only


_XOPEN_SOURCE_EXTENDED

readv() XPG4 O O OSS parameters only


OSS objects and Guardian
objects
_PUT_MODEL_

realloc() ISO G, O G, O

realpath() O O

recv() XPG4 O O _PUT_MODEL_


_XOPEN_SOURCE_EXTENDED

recvfrom() XPG4 O O _PUT_MODEL_


_XOPEN_SOURCE_EXTENDED

recvmsg() XPG4 O O _PUT_MODEL_


_XOPEN_SOURCE_EXTENDED

regcmp() XPG4 G, O G, O The behavior of this function


in locales other than POSIX is
undefined

regcomp() XPG4 G, O G, O

regerror() XPG4 G, O G, O

regex() XPG4 G, O G, O The behavior of this function


in locales other than POSIX is
undefined

regexec() XPG4 G, O G, O

regfree() XPG4 G, O G, O

remainder() XPG4 G, O G, O

remainderf() ISO G, O G, O

remainderl() ISO G, O G, O

remove() ISO G, O G, O Parameters must match


process

remove_guardian() HP G, O G, O Guardian parameters only

remove_oss() HP G, O G, O OSS parameters only

remque() XPG4 G, O G, O

remquo() ISO G, O G, O IEEE_float only

remquof() ISO G, O G, O IEEE_float only

remquol() ISO G, O G, O IEEE_float only

rename() ISO G, O G, O Parameters must match


process
Guardian function operates
only on Guardian objects
OSS function operates on OSS
objects and limited Guardian
objects

488 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

rename_guardian() HP G, O G, O Guardian parameters only


Guardian objects only

rename_oss() HP G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

rewind() ISO G, O G, O

rewinddir() POSIX G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

rindex() XPG4 G, O G, O

rint() XPG4 G, O G, O

rintf() ISO G, O G, O

rintl() ISO G, O G, O

rmdir() POSIX G, O G, O OSS parameters only


Limited OSS objects only

round() ISO G, O G, O IEEE_float only

roundf() ISO G, O G, O IEEE_float only

roundl() ISO G, O G, O IEEE_float only

scalb() XPG4 G, O G, O

scalbln() ISO G, O G, O IEEE_float only

scalblnf() ISO G, O G, O IEEE_float only

scalblnl() ISO G, O G, O IEEE_float only

scalbn() ISO G, O G, O IEEE_float only

scalbnf() ISO G, O G, O IEEE_float only

scalbnl() ISO G, O G, O IEEE_float only

scandir() HP O O HP extension to XPG4


specification

scandir64() XLFS O O _LARGEFILE64_SOURCE or


_FILE_OFFSET_BITS

scanf() ISO G, O G, O

sched_get_priority_max() Threads O O OSS parameters only


_PUT_MODEL_ or
_SPT_MODEL_

sched_get_priority_min() Threads O O OSS parameters only


_PUT_MODEL_ or
_SPT_MODEL_

sched_yield() Threads O O OSS parameters only


_PUT_MODEL_ or
_SPT_MODEL_

Using the API Interoperability Tables 489


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

seed48() XPG4 G, O G, O

seekdir() XPG4 O O OSS parameters only


OSS objects and limited
Guardian objects

select() XPG4 G, O G, O OSS parameters only


OSS objects and limited
Guardian objects
_PUT_MODEL_

semctl() XPG4 O O

semget() XPG4 O O

semop() XPG4 O O

send() XPG4 O O _PUT_MODEL_


_XOPEN_SOURCE_EXTENDED

sendmsg() XPG4 O O _PUT_MODEL_


_XOPEN_SOURCE_EXTENDED

sendto() XPG4 O O _PUT_MODEL_


_XOPEN_SOURCE_EXTENDED

setbuf() ISO G, O G, O

setegid() XPG4 O O

seteuid() XPG4 O O

setgid() POSIX O O

setgrent() POSIX G, O G, O

setgroups() HP O O

sethostent() XPG4 O O

setjmp() ISO G, O G, O

setkey() XPG4 G, O G, O Programs compiled with this


version of the function cannot
be exported from the United
States of America.

setlocale() ISO G, O G, O

setlocale_from_msg() HP O O OSS parameters only

setlogmask() X/OPEN O O

setnetent() XPG4 O O

setpgid() POSIX O O OSS objects only

setpgrp() POSIX O O OSS objects only

setprotoent() XPG4 O O

setpwent() X/OPEN G, O G, O _XOPEN_SOURCE_EXTENDED


or
_TANDEM_SOURCE

490 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

setregid() XPG4 O O OSS objects only

setreuid() XPG4 O O OSS objects only

setservent() XPG4 O O

setsid() POSIX O O OSS objects only

setsockopt() XPG4 O O _XOPEN_SOURCE_EXTENDED

setstate() XPG4 G, O G, O

setuid() POSIX O O

setvbuf() ISO G, O G, O

shmat() XPG4 O O

shmctl() XPG4 O O

shmdt() XPG4 O O

shmget() XPG4 O O

shutdown() XPG4 O O

sigaction() POSIX G, O G, O _PUT_MODEL_

sigaddset() POSIX O O

sigaltstack() POSIX G, O G, O _PUT_MODEL_

sigdelset() POSIX O O

sigemptyset() POSIX O O

sigfillset() POSIX O O

sigismember() POSIX O O

siglongjmp() POSIX G, O G, O

signal() ISO G, O G, O _PUT_MODEL_

signbit() ISO G, O G, O IEEE_float only

sigpending() POSIX G, O G, O _PUT_MODEL_

sigprocmask() POSIX G, O G, O

sigsetjmp() POSIX G, O G, O

sigsuspend() POSIX G, O G, O _PUT_MODEL_

sigwait() POSIX O O _PUT_MODEL_

sin() ISO G, O G, O

sinf() ISO G, O G, O

sinh() ISO G, O G, O

sinhf() ISO G, O G, O

sinhl() ISO G, O G, O

sinl() ISO G, O G, O

sleep() POSIX O O _PUT_MODEL_

Using the API Interoperability Tables 491


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

sockatmark() HP O O

socket() XPG4 O O _XOPEN_SOURCE_EXTENDED

socket_transport_name_get() XPG4 O O _XOPEN_SOURCE_EXTENDED

socket_transport_name_set() XPG4 O O _XOPEN_SOURCE_EXTENDED

socketpair() XPG4 O O _XOPEN_SOURCE_EXTENDED

snprintf() ISO G, O G, O

sprintf() ISO G, O G, O

SPT_ ABORTTRANSACTION() HP O O Guardian objects only

spt_accept() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA
_XOPEN_SOURCE_EXTENDED

spt_acceptx() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK
_XOPEN_SOURCE_EXTENDED

spt_alarm() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
SIGNAL and
SPT_THREAD_SIGNAL or
SPT_THREAD_SIGNAL_
PRAGMA

spt_awaitio() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

SPT_ BEGINTRANSACTION() HP O O Guardian objects only

SPT_CANCEL() HP O O Guardian objects only

spt_close() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_closex() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK

492 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_closez() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_connect() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA
_XOPEN_SOURCE_EXTENDED

spt_connectx() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK
_XOPEN_SOURCE_EXTENDED

SPT_CONTROL() HP O O Guardian objects only

spt_dup2x() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

SPT_ ENDTRANSACTION() HP O O Guardian objects only

spt_fclose() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_fclosex() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fcntlx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK

Using the API Interoperability Tables 493


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_fcntlz() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fd_read_ready() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_fd_write_ready() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_fflush() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_fflushx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK;
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fgetc() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_fgetcx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK;
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fgets() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

494 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_fgetsx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fgetwc() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_fgetwcx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK;
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

SPT_FILE_CLOSE_() HP O O Guardian objects only

SPT_FILE_OPEN_() HP O O Guardian objects only

spt_fork() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_fprintf() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_fprintfx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK;
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fputc() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

Using the API Interoperability Tables 495


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_fputcx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK;
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fputs() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_fputsx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fputwc() Threads O O OSS objects only

spt_fputwcx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fread() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_freadx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fstatz() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

496 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_fstat64z() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fsyncz() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_ftruncatez() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_ftruncate64z() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_fwrite() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_fwritex() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_generateTag() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_getc() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_getchar() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

Using the API Interoperability Tables 497


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_getcharx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_getcx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_gets() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_getsx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_getTMFConcurrentTransactions() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_getw() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_getwc() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_getwchar() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

498 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_getwcharx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_getwcx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_getwx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_INITRECEIVE() HP O O Guardian objects only

spt_INITRECEIVEL() HP O O Guardian objects only

spt_interrupt() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_interruptTag() Threads O O OSS objects only

SPT_LOCKFILE() HP O O Guardian objects only

SPT_LOCKREC() HP O O Guardian objects only

spt_lseekz() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_lseek64z() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

Using the API Interoperability Tables 499


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_pause() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
SIGNAL and
SPT_THREAD_SIGNAL or
SPT_THREAD_SIGNAL_
PRAGMA

spt_printf() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_printfx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_putc() Threads O O OSS objects only

spt_putchar() Threads O O OSS objects only

spt_putcharx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_putcx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_puts() Threads O O OSS objects only

spt_putsx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

500 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_putw() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_putwc() Threads O O OSS objects only

spt_putwchar() Threads O O OSS objects only

spt_putwcharx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_putwcx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_putwx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_read() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

SPT_READLOCKX() HP O O Guardian objects only

SPT_READUPDATELOCKX() HP O O Guardian objects only

SPT_READUPDATEX() HP O O Guardian objects only

spt_readv() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_readvx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK

Using the API Interoperability Tables 501


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_readvz() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

SPT_READX() HP O O Guardian objects only

spt_readx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK

spt_readz() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_RECEIVEREAD() HP O O Guardian objects only

spt_RECEIVEREADL() HP O O Guardian objects only

spt_recv() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA
_XOPEN_SOURCE_EXTENDED

spt_recvfrom() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA
_XOPEN_SOURCE_EXTENDED

spt_recvfromx() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK
_XOPEN_SOURCE_EXTENDED

spt_recvmsg() Threads O O OSS objects only


_XOPEN_SOURCE_EXTENDED

502 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_recvmsgx() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK
_XOPEN_SOURCE_EXTENDED

spt_recvx() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK
_XOPEN_SOURCE_EXTENDED

spt_regFile() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_regFileIOHandler() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_regOSSFileIOHandler() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_regPathsendFile() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_regPathsendTagHandler() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_regTimerHandler() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_REPLYX() HP O O Guardian objects only

spt_REPLYXL() HP O O Guardian objects only

SPT_RESUMETRANSACTION() HP O O Guardian objects only

Using the API Interoperability Tables 503


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_select() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_select_single_np() Threads O O Mapped to from select()


if SPT_SELECT_SINGLE
is defined and one of the
thread aware defines are used.
_SPT_MODEL_

spt_send() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA
_XOPEN_SOURCE_EXTENDED

spt_sendmsg() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA
_XOPEN_SOURCE_EXTENDED

spt_sendmsgx() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK
_XOPEN_SOURCE_EXTENDED

spt_sendto() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA
_XOPEN_SOURCE_EXTENDED

spt_sendtox() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK
_XOPEN_SOURCE_EXTENDED

504 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_sendx() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK
_XOPEN_SOURCE_EXTENDED

SPT_SERVERCLASS_DIALOG_ABORT_() HP O O Guardian objects only

SPT_SERVERCLASS_DIALOG_BEGIN_() HP O O Guardian objects only

SPT_SERVERCLASS_DIALOG_END_() HP O O Guardian objects only

SPT_SERVERCLASS_DIALOG_SEND_() HP O O Guardian objects only

SPT_SERVERCLASS_SEND_() HP O O Guardian objects only

SPT_SERVERCLASS_SEND_INFO_() HP O O Guardian objects only

SPT_SERVERCLASS_SENDL_() HP O O Guardian objects only

SPT_SETMODE() HP O O Guardian objects only

spt_setOSSFileIOHandler() HP O O OSS objects only

spt_setTMFConcurrentTransactions() Threads O O OSS objects only

spt_sigaction() Threads O O OSS objects only


Set SPT_THREAD_AWARE_
SIGNAL to catch externally
generated signals at the thread
level
_SPT_MODEL_

spt_signal() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
SIGNAL and
SPT_THREAD_SIGNAL or
SPT_THREAD_SIGNAL_
PRAGMA

spt_sigpending() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_sigsuspend() Threads O O OSS objects only


_SPT_MODEL_
Set SPT_THREAD_AWARE_
SIGNAL to catch externally
generated signals at the thread
level

Using the API Interoperability Tables 505


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_sigwait() Threads O O OSS objects only


Set SPT_THREAD_AWARE_
SIGNAL to catch externally
generated signals at the thread
level
_SPT_MODEL_

spt_sleep() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_system() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

SPT_TMF_GetTxHandle() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

SPT_TMF_Init() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

SPT_TMF_RESUME() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

SPT_TMF_SetAndValidateTxHandle() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

SPT_TMF_SetTxHandle() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

SPT_TMF_SUSPEND() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

SPT_UNLOCKFILE() HP O O Guardian objects only

SPT_UNLOCKREC() HP O O Guardian objects only

spt_unregFile() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

506 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_unregOSSFileIOHandler() HP O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_unregPathsendTagHandler() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_usleep() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_vfprintf() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_vfprintfx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_vprintf() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_vprintfx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK; or
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

spt_waitpid() Threads O O OSS objects only


_SPT_MODEL_
To use nonblocking feature set
SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK

spt_wakeup() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

Using the API Interoperability Tables 507


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

spt_write() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

SPT_WRITEREADX() HP O O Guardian objects only

SPT_WRITEUPDATEUNLOCKX() HP O O Guardian objects only

SPT_WRITEUPDATEX() HP O O Guardian objects only

spt_writev() Threads O O OSS objects only


SPT_THREAD_AWARE or
SPT_THREAD_AWARE_
PRAGMA

spt_writevx() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK

spt_writevz() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

SPT_WRITEX() HP O O Guardian objects only

spt_writex() Threads O O OSS objects only


SPT_THREAD_AWARE_
NONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_NONBLOCK

spt_writez() Threads O O OSS objects only


_SPT_MODEL_
SPT_THREAD_AWARE_
XNONBLOCK or
SPT_THREAD_AWARE_
PRAGMA_XNONBLOCK

sqrt() XPG4 G, O G, O

sqrtf() ISO G, O G, O

sqrtl() ISO G, O G, O

srand() ISO G, O G, O

srand48() XPG4 G, O G, O

srandom() XPG4 G, O G, O

sscanf() ISO G, O G, O

stat() POSIX G, O G, O OSS parameters only


OSS objects and limited
Guardian objects

508 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

stat64() XLFS G, O G, O OSS parameters only


OSS objects and limited
Guardian objects
_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS

statvfs() XPG4 O G, O OSS parameters only


OSS objects and limited
Guardian objects

statvfs64() XLFS O G, O OSS parameters only


OSS objects and limited
Guardian objects
_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS

step() XPG4 G, O G, O

strcasecmp() XPG4 G, O G, O

strcat() ISO G, O G, O

strchr() ISO G, O G, O

strcmp() ISO G, O G, O

strcoll() ISO G, O G, O

strcpy() ISO G, O G, O

strcspn() ISO G, O G, O

strdup() X/OPEN G, O G, O _XOPEN_SOURCE_EXTENDED

strerror() ISO G, O G, O

strerror_r() Threads G, O G, O

strfmon() XPG4 G, O G, O

strftime() ISO G, O G, O

strlen() ISO G, O G, O

strncasecmp() XPG4 G, O G, O

strncat() ISO G, O G, O

strncmp() ISO G, O G, O

strncpy() ISO G, O G, O

strpbrk() ISO G, O G, O

strptime() XPG4 G, O G, O

strrchr() ISO G, O G, O

strspn() ISO G, O G, O

strstr() ISO G, O G, O

strtod() ISO G, O G, O

strtof() ISO G, O G, O

strtoimax() ISO G, O G, O

Using the API Interoperability Tables 509


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

strtok() ISO G, O G, O

strtok_r() Threads G, O G, O _SPT_MODEL_

strtol() ISO G, O G, O

strtoll() ISO G, O G, O

strtoul() ISO G, O G, O

strtoull() ISO G, O G, O

strtoumax() ISO G, O G, O

strxfrm() ISO G, O G, O

swab() XPG4 G, O G, O

swprintf() ISO G, O G, O

swscanf() ISO G, O G, O

symlink() X/OPEN G, O G, O OSS objects only


_XOPEN_SOURCE_EXTENDED

sysconf() POSIX G, O G, O

syslog() X/OPEN G, O G, O

system() ISO G, O G, O Only Guardian modules or


only OSS modules

tan() ISO G, O G, O

tanf() ISO G, O G, O

tanh() ISO G, O G, O

tanhf() ISO G, O G, O

tanhl() ISO G, O G, O

tanl() ISO G, O G, O

tcdrain() POSIX O O

tcflow() POSIX O O

tcflush() POSIX O O

tcgetattr() POSIX O O

tcgetpgrp() POSIX O O

tcsendbreak() POSIX O O

tcsetattr() POSIX O O

tcsetpgrp() POSIX O O

tdelete() XPG4 G, O G, O

tdm_execve() HP O O OSS parameters only

tdm_execvep() HP O O OSS parameters only

tdm_fork() HP O O OSS parameters only

tdm_spawn() HP O O OSS parameters only

510 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

tdm_spawnp() HP O O OSS objects only

telldir() XPG4 O O OSS parameters only


OSS objects and limited
Guardian objects

tempnam() XPG4 O O

terminate_program() HP G, O G, O

tfind() XPG4 G, O G, O

tgamma() ISO G, O G, O IEEE_float only

tgammaf() ISO G, O G, O IEEE_float only

tgammal() ISO G, O G, O IEEE_float only

time() ISO G, O G, O

times() POSIX G, O G, O

tmpfile() ISO G, O G, O Result matches process temp


file created in

tmpfile_guardian() HP G, O G, O Guardian parameters only

tmpfile_oss() HP G, O G, O OSS parameters only

tmpfile64() XLFS G, O G, O _LARGEFILE64_SOURCE or


_FILE_OFFSET_BITS

tmpfile64_guardian() XLFS G, O G, O Guardian parameters only


_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS

tmpfile64_oss() XLFS G, O G, O OSS parameters only


_LARGEFILE64_SOURCE or
_FILE_OFFSET_BITS

tmpnam() ISO G, O G, O Parameters must match


process

tmpnam_guardian() HP G, O G, O Guardian parameters only

tmpnam_oss() HP G, O G, O OSS parameters only

tmpnam_r() Threads G, O G, O _SPT_MODEL_

toascii() XPG4 G, O G, O

_tolower() XPG4 G, O G, O

tolower() ISO G, O G, O

_toupper() XPG4 G, O G, O

toupper() ISO G, O G, O

towctrans() ISO G, O G, O

towlower() XPG4 G, O G, O

towupper() XPG4 G, O G, O

trunc() ISO G, O G, O IEEE_float only

Using the API Interoperability Tables 511


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

truncf() ISO G, O G, O IEEE_float only

truncl() ISO G, O G, O IEEE_float only

tsearch() XPG4 G, O G, O

ttyname() XPG4 O G, O

ttyname_r() Threads O G, O _SPT_MODEL_

twalk() XPG4 G, O G, O

tzset() XPG4 G, O G, O

ulimit() XPG4 O O

umask() POSIX O O

uname() POSIX O O

ungetc() ISO G, O G, O

ungetwc() XPG4 G, O G, O

unlink() ISO O G, O OSS parameters only


OSS objects and limited
Guardian objects

unordered() XPG4 G, O G, O

usleep() POSIX O O _PUT_MODEL_

utime() POSIX O G, O OSS parameters only


OSS objects and limited
Guardian objects

va_arg() ISO G, O G, O

va_end() ISO G, O G, O

va_start() ISO G, O G, O

valloc() XPG4 G, O G, O

vfprintf() ISO G, O G, O

vfscanf() ISO G, O G, O

vfwprintf() ISO G, O G, O

vfwscanf() ISO G, O G, O

vprintf() ISO G, O G, O

vscanf() ISO G, O G, O

vsnprintf() ISO G, O G, O

vsprintf() ISO G, O G, O

vsscanf() ISO G, O G, O

vswprintf() ISO G, O G, O

vswscanf() ISO G, O G, O

vwprintf() ISO G, O G, O

512 API Interoperability in Native Processes


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

vwscanf() ISO G, O G, O

wait() POSIX O O OSS objects only

waitpid() POSIX O O OSS objects only


_PUT_MODEL_

wcrtomb() ISO G, O G, O

wcscat() XPG4 G, O G, O

wcschr() XPG4 G, O G, O

wcscmp() XPG4 G, O G, O

wcscoll() XPG4 G, O G, O

wcscpy() XPG4 G, O G, O

wcscspn() XPG4 G, O G, O

wcsftime() XPG4 G, O G, O

wcslen() XPG4 G, O G, O

wcsncat() XPG4 G, O G, O

wcsncmp() XPG4 G, O G, O

wcsncpy() XPG4 G, O G, O

wcspbrk() XPG4 G, O G, O

wcsrchr() XPG4 G, O G, O

wcsrtombs() ISO G, O G, O

wcsspn() XPG4 G, O G, O

wcstod() XPG4 G, O G, O

wcstof() ISO G, O G, O

wcstoimax() ISO G, O G, O

wcstok() XPG4 G, O G, O

wcstol() XPG4 G, O G, O

wcstoll() XPG4 G, O G, O

wcstombs() XPG4 G, O G, O

wcstoul() XPG4 G, O G, O

wcstoull() XPG4 G, O G, O

wcstoumax() ISO G, O G, O

wcswcs() XPG4 G, O G, O

wcswidth() XPG4 G, O G, O

wcsxfrm() XPG4 G, O G, O

wctob() ISO G, O G, O

wctomb() XPG4 G, O G, O

Using the API Interoperability Tables 513


Table C-2 API Interoperability in Native Processes (Functions n through z) (continued)
Function or Macro Specified Module Process Usage Notes
By Compiled Called
As From

wctrans() ISO G, O G, O

wctype() XPG4 G, O G, O

wcwidth() XPG4 G, O G, O

wmemchr() ISO G, O G, O

wmemcmp() ISO G, O G, O

wmemcpy() ISO G, O G, O

wmemmove() ISO G, O G, O

wmemset() ISO G, O G, O

wordexp() POSIX O O

wordfree() POSIX O O

wprintf() ISO G, O G, O

write() XPG4 O O OSS parameters only


OSS objects and limited
Guardian objects
_PUT_MODEL_

writev() XPG4 O O OSS parameters only


OSS objects only
_PUT_MODEL_

wscanf() ISO G, O G, O

y0() XPG4 G, O G, O

y1() XPG4 G, O G, O

yn() XPG4 G, O G, O

514 API Interoperability in Native Processes


Glossary
$RECEIVE A special Guardian file through which a process receives and optionally replies to messages
from other processes.
absolute A pathname that begins with a slash (/) character and is resolved beginning with the root
pathname directory. Contrast with relative pathname.
accelerated object The MIPS RISC instructions (in the MIPS region) that result from processing a TNS object file
code with the Accelerator or the Intel® Itanium® instructions (in the Itanium instruction region)
that result from processing a TNS object file with the Object Code Accelerator (OCA).
accelerated object A TNS object file that, in addition to its TNS instructions (in the TNS region) and symbol
file information (in the symbol region), has been augmented by the Accelerator with equivalent
but faster MIPS RISC instructions (in the MIPS region), the Object Code Accelerator (OCA)
with equivalent but faster Intel® Itanium® instructions (in the Itanium instruction region), or
both.
Accelerator A program optimization tool that processes a TNS object file and produces an accelerated object
file that also contains equivalent MIPS RISC instructions (called the MIPS region). TNS object
code that is accelerated runs faster on TNS/R processors than TNS object code that is not
accelerated. Contrast with Object Code Accelerator (OCA).
access control list A structure attached to a software object that defines access permissions for multiple users and
(ACL) groups. It extends the permissions defined by the file system permission bits by allowing you
specify the access rights of many individuals and groups instead of just one of each.
ACL See access control list (ACL).
API See application program interface (API).
application A set of services (such as programming language functions or procedures) that are called by
program interface an application program to communicate with other software components. For example, an
(API) application program in the form of a client might use an API to communicate with a server
program.
appropriate An implementation-defined means of associating privileges with a process for function calls
privileges or function call options that need special privileges.
BSD Berkeley Software Distribution.
canonical input A terminal input mode in which data is not made available to a process until an entire logical
mode line (delimited by a newline, EOF, or EOL character) is entered. This mode is sometimes called
line mode or nontransparent mode. Contrast with noncanonical input mode.
child process A process created by another process. The creating process becomes the parent process of the
new process. See also parent process.
conformance Meeting the requirement of a specific standard.
conforming An application that is either an ISO/IEC-conforming POSIX.1 application or a
POSIX.1 national-standards-body conforming POSIX.1 application.
application
controlling A terminal that might be associated with a session. A session can have only one controlling
terminal terminal, and a controlling terminal can control only one session at a time. When a session has
a controlling terminal, all the following are true:
• Certain character sequences entered from that terminal cause signals to be sent to all
processes in the process groups of that session.
• Certain characters entered from that terminal might receive special treatment.
Members of background process groups of the session are restricted from certain kinds of access
to the controlling terminal.
See also session.
daemon See demon.
demon On a UNIX system, a process that runs continuously to provide a specific service for other
processes. A demon does not have a controlling terminal and is not explicitly invoked. On an

515
HP NonStop system, a demon runs in the OSS environment and has an OSS process ID. See
also static server.
directory A type of OSS file that contains directory entries, which name links to other files. No two
directory entries in the same directory have the same name.
directory tree A hierarchy of directories. In the OSS environment, directories are connected to each other in
a branching hierarchical fashion such that there is only one path between any two directories
(provided there is no backtracking).
dynamic window A window, or virtual terminal, that Telserv creates when it receives a connection request.
EDIT file An unstructured file with the file code 101 in the Guardian file system. An EDIT file can be
processed by either the EDIT or PS Text Edit (TEDIT) editor. An EDIT file typically contains
source program or script code, documentation, or program output. OSS functions can open an
EDIT file only for reading.
EMS See Event Management Service (EMS).
errno An external variable that contains the most recent error condition set by a C function.
event A significant change in some condition in the system or network. An event can be an operational
error, notification of limits exceeded, request for action, notification of lines and other objects
becoming available, and so on. Note that an event is not always an error.
Event A part of the Distributed Systems Management (DSM) product used to provide event collection,
Management event logging, and event distribution facilities. It provides for different event descriptions for
Service (EMS) interactive and programmatic interfaces, lets an operator or application select specific
event-message data, and allows for flexible distribution of event messages within a system or
network.
extended data An area of virtual memory used to contain data.
segment
feature test macro A symbol that, if defined in a program’s source code, includes specific other symbols from a
header within that program’s source code and makes those symbols visible.
FIFO A type of file that is always read and written in a first-in, first-out manner.
file An object to which data can be written or from which data can be read. A file has attributes
such as access permissions and a file type. In the OSS environment, file types include regular
file, character special file, FIFO, pipe, socket, symbolic link, Guardian file, and directory..
file descriptor The nonnegative integer that uniquely identifies a single open of a file to a running process.
Each file descriptor is associated with an open file description that contains data about the file.
file identifier In the Guardian environment, the portion of a filename following the subvolume name. In the
OSS environment, a portion of the internal information used to identify a file in the OSS file
system. The two identifiers are not comparable.
file permission Information about a file that is used, along with other information, to determine whether a
bits process or user has read, write, or execute/search permission to that file. The bits are divided
into three parts: owner, group, and other. Each part is used with the corresponding file class
of processes.
file system In the OSS environment, a collection of files and file attributes. A file system provides the
namespace for the file serial numbers that uniquely identify its files. Open System Services
provides a file system (see also ISO/IEC IS 9945-1: 1990 [ANSI/IEEE Std. 1003.1-1990], Clause
2.2.2.38); the Guardian application program interface (API) provides a file system; and OSS
Network File System (NFS) provides a file system. (OSS NFS filenames and pathnames are
governed by slightly different rules than OSS filenames and pathnames.) Within the OSS and
OSS NFS file systems, filesets exist as manageable objects.
On an HP NonStop system, the Guardian file system for a node is a subset of the OSS virtual
file system. Traditionally, the API for file access in the Guardian environment is referred to as
the Guardian file system.
In some UNIX and NFS implementations, the term file system is used to mean the same thing
as fileset. That is, a file system is a logical grouping of files that, except for the root of the file
system, can be contained only by directories within the file system.
See also fileset.

516 Glossary
filename In the OSS environment, a component of a pathname containing any valid characters other
than a slash (/) or a null. In the Guardian environment, a filename is the set of node name,
volume name, subvolume name, and file identifier characters that uniquely identifies a file.
fileset In the OSS environment, a set of files with a common mount point within the file hierarchy. A
fileset can be part or all of a single virtual file system.
On an HP NonStop system, the Guardian file system for a node has a mount point and is a
subset of the OSS virtual file system. The entire Guardian file system therefore could be viewed
as a single fileset. However, each volume, and each process of subtype 30, within the Guardian
file system is actually a separate fileset.
The term file system is often used interchangeably with fileset in UNIX documentation.
flat segment A type of logical segment. Each flat segment has its own distinct address range within the
process address space that never overlaps the range of any other allocated segments. Thus all
allocated flat segments for a process are always available for use concurrently. Contrast with
selectable segment.
function An OSS or Guardian C function.
group ID The nonnegative integer used to identify a group of users of an HP NonStop network node.
Each user of that node is a member of at least one group. When the identity of a group is
associated with a process, a group ID value is referred to as one of the following:
• Real group ID
• Effective group ID
• Supplementary group ID
• Saved-set group ID
Guardian An environment available for interactive or programmatic use with the HP NonStop operating
system. Processes that run in the Guardian environment use the Guardian system procedure
calls as their application program interface; interactive users of the Guardian environment use
the HP Tandem Advanced Command Language (TACL) or another HP product’s command
interpreter. Contrast with Open System Services (OSS).
Guardian module A module compiled to execute in the Guardian environment.
header An object that, when specified for inclusion in a program’s source code, causes the program to
behave as if the statement including the header were actually a specific set of other programming
statements. A header contains coded information that provides details (such as data item length)
about the data that the header precedes.
In an OSS program, a header is the name of a file known to the run-time library used by a
process. In a Guardian environment C language program, a header is the file identifier for a
file known to the run-time library used by a process.
HP NonStop The product name for the OSS environment. See Open System Services (OSS).
Open System
Services (OSS)
interoperability 1. Within an Expand node, the ability to use the features or facilities of one environment from
another. For example, the gtacl command in the Open System Services (OSS) environment
allows an interactive user to start and use a Guardian tool in the Guardian environment.
2. Among systems from multiple vendors or with multiple versions of operating systems from
the same vendor, the ability to exchange status, files, and other information. Product externals
and end-user publications for NonStop servers often use the term connectivity in this context.
labeled tape A tape containing information about the contents of the tape that prevent undesired overwriting
of the tape.
large file aware An application or function that can process large OSS files in addition to small OSS files. For
example, it must be able to access large files as input and generate large files as output. Contrast
with large file safe.
large file safe An application or function that causes no loss of data or corruption of data when it encounters
a large OSS file. A large file safe application or function is not required to process large OSS
files with the same ability as when it processes small files, but it must handle errors or warnings
detected during file manipulation operations and fail gracefully. Contrast with large file aware.

517
large OSS file A regular file that has a size greater than or equal to approximately 2 gigabytes. Contrast with
small OSS file.
man page A term sometimes used in UNIX documentation for the online or hard-copy version of a file
that provides reference information. See reference page.
nesting The inclusion of items of one type within items of that type. For example, in the OSS
environment, directories can contain directories.
non-regular file An OSS file that is not a regular (disk) file.
noncanonical A terminal input mode in which data is made available to a process when a timer expires or
input mode when a certain number of characters have been entered. Noncanonical data is not grouped into
logical lines of input. This mode is sometimes called block mode or transparent mode. Contrast
with canonical input mode.
nowait I/O The ability of an application process to continue executing in parallel with read or write
operations that it initiates. Contrast with waited I/O.
Object Code A program optimization tool that processes a TNS object file and produces an accelerated file
Accelerator for a TNS/E system. OCA augments a TNS object file with equivalent Intel Itanium instructions.
(OCA) TNS object code that is accelerated runs faster on TNS/E systems than TNS object code that is
not accelerated. Contrast with Accelerator.
OCA See Object Code Accelerator (OCA).
odd-unstructured Files that have no built-in record structures and permit reading and writing of both even and
files odd byte counts and positioning to both even and odd byte addresses.
Open System An open system environment available for interactive or programmatic use with the HP NonStop
Services (OSS) operating system. Processes that run in the OSS environment usually use the OSS application
program interface; interactive users of the OSS environment usually use the OSS shell for their
command interpreter. Synonymous with Open System Services (OSS) environment. Contrast
with Guardian.
operator message A message, intended for an operator, that describes a significant event on an HP NonStop
server.
OSS See Open System Services (OSS).
OSS module A module compiled to execute in the OSS environment.
OSS process ID The unique identifier that represents a process during the lifetime of the process and during
(PID) the lifetime of the process group of that process. See also PID
parent process The process that created a given process, or (if the creating process has stopped) a process that
has inherited a given process.
See also child process.
pathname In the OSS environment, the string of characters that uniquely identifies a file within its file
system. A pathname can be either relative or absolute. See also ISO/IEC IS 9945-1:1990
(ANSI/IEEE Std. 1003.1-1990 or POSIX.1), Clause 2.2.2.57.
persistent process A process that must always be either waiting, ready, or executing. Persistent processes are
usually controlled by a monitor process that checks on the status of persistent processes and
restarts them, if necessary.
PID In the OSS environment, the OSS process ID, a numeric identifier assigned to an OSS process
and unique within an HP NonStop node. In the Guardian environment, PID is sometimes used
to mean either of the following:
• A Guardian process identifier such as the process ID
• The cpu, pin value that is unique to a process within a NonStop node
See also OSS process ID (PID).
pipe An unnamed FIFO, created programmatically by invoking the pipe() function or interactively
with the shell pipe syntax character (|). A shell pipe redirects the standard output of one process
to become the standard input of another process. A programmatic pipe is an interprocess
communication mechanism.

518 Glossary
portable An application that can execute on a wide range of hardware systems from multiple
application manufacturers. A portable application is a program that can be moved with little or no change
in its source code from another manufacturer’s system to an HP NonStop system.
procedure A Guardian system procedure.
process 1. A program that has been submitted to the operating system for execution, or a program that
is currently running in the computer.
2. An address space, a single thread of control that executes within that address space, and the
system resources required by that thread of control.
process group A set of processes that can signal associated processes. Each process in a node is a member of
a process group; the process group has a process group ID. A new process becomes a member
of the process group of its creator.
process handle An identifier that uniquely identifies an OSS or Guardian process within a network of HP
NonStop systems.
reentrant function A function that does not hold static data over successive calls and does not return a pointer to
static data. All data is provided by the caller of the function.
reference page The OSS or Distributed Computing Environment (DCE) online or hard-copy version of a file
that provides reference information for a software facility. Some UNIX documentation uses the
term man page instead, referring either to the online delivery mechanism used to display the
file (usually the shell man command) or to the nature of the file as part of a manual.
regular file In the OSS file system, a file that is a randomly accessible sequence of bytes. A regular file
contains binary or text data and has no structure imposed by the system. Contrast with special
file.
relative pathname A pathname that does not begin with a slash (/) character. A relative pathname is resolved
beginning with the current working directory. Contrast with absolute pathname.
root See root fileset and root directory. See also super ID.
root directory A directory associated with a process that the system uses for pathname resolution when a
pathname begins with a slash (/) character.
root fileset The fileset with the device number of 0, normally containing the root directory for the OSS file
system in an HP NonStop system. HP recommends that this fileset be named “root”.
selectable A type of logical segment formerly known as an extended data segment. The data area for a
segment selectable segment always begins with relative segment 4, and this area can be dynamically
switched among several selectable segments by calls to the Guardian SEGMENT_USE_
procedure. The effect is similar to a rapid overlaying of one large data area.
See also flat segment.
semaphore A mechanism used to provide multiple processes with access to a shared data object.
session A set of process groups associated for job control purposes. A session can have a controlling
terminal.
shared memory An interprocess communication mechanism that allows two or more processes to share a given
region of memory.
shell 1. A program that interprets sequences of text input as commands. A shell can operate on an
input stream or it can interactively prompt and read commands from a terminal.
2. An envelope of code that provides a convenient way to call a procedure in another execution
environment.
signal The method by which an environment notifies a process of an event. Signals are used to notify
a process when an error that is not related to input or output has occurred.
signal delivery The time when OSS takes the action appropriate for a specific process and a specific signal.
signal generation The time when an event occurs that causes a signal for a process.
signal handler A function or procedure that is executed when a specific signal is delivered to a specific process.
signal mask The set of signals that are currently blocked from delivery to a specific process.
small OSS file A regular file that is smaller than approximately 2 gigabytes. Contrast with large OSS file.
socket An end-point for stream-oriented communication. A socket has a file descriptor.

519
special file A file associated with an I/O device. Often called a device file. Special files are read and written
the same as ordinary files, but requests to read or write result in activation of the associated
device. Due to convention and consistency, these files should always reside in the /dev directory.
See also file.
static server In the Guardian environment, a process that runs continuously and provides a specific service
to other processes. A static server differs from a traditional UNIX demon in that a demon
actively looks for tasks to perform, while a static server performs only tasks brought to its
attention by a client (requestor) process.
See also demon.
static window A window, or virtual terminal, that is opened with the Subsystem Control Facility (SCF). You
do not need to establish a Telserv connection before opening a static window.
super ID On HP NonStop systems, a privileged user who can read, write, execute, and purge all files on
the system. The super ID is usually a member of a system-supervisor group.
The super ID has the set of special permissions called appropriate privileges. In the Guardian
environment, the structured view of the super ID, which is (255, 255), is most commonly used;
in the OSS environment, the scalar view of the super ID, which is 65535, is most commonly
used.
terminal A type of OSS character special file that conforms to the interface description in Clause 7 of
ISO/IEC IS 9945-1: 1990.
TNS Refers to fault-tolerant HP computers that support the HP NonStop operating system and that
are based on microcoded complex instruction-set computing (CISC) technology. TNS processors
run the TNS instruction set. Contrast with TNS/R and TNS/E.
TNS object code The TNS instructions that result from processing program source code with a TNS language
compiler. TNS object code executes on TNS, TNS/R, and TNS/E systems.
TNS object file An object file created by a TNS compiler or the Binder. A TNS object file contains TNS
instructions. TNS object files can be processed by the Accelerator or by the TNS Object Code
Accelerator (OCA) to produce to produce accelerated object files. A TNS object file can be run
on TNS, TNS/R, and TNS/E systems.
TNS process A process whose main program object file is a TNS object file, compiled using a TNS compiler.
A TNS process executes in interpreted or accelerated mode while within itself, when calling a
user library, or when calling into TNS system libraries. A TNS process temporarily executes in
native mode when calling into native-compiled parts of the system library. Object files within
a TNS process might be accelerated or not, with automatic switching between accelerated and
interpreted modes on calls and returns between those parts.
Contrast with TNS/R native process and TNS/E native process.
TNS/E Refers to fault-tolerant HP computers that support the HP NonStop operating system and are
based on the Intel Itanium processor. TNS/E systems run the Itanium instruction set and can
run TNS object files by interpretation or after acceleration. TNS/E systems include all HP
NonStop systems that use NSE-x processors. Contrast with TNS and TNS/R.
TNS/E native The Intel Itanium instructions that result from processing program source code with a TNS/E
object code native compiler. TNS/E native object code executes only on TNS/E systems, not on TNS or
TNS/R systems.
TNS/E native An object file created by a TNS/E native compiler that contains Intel Itanium instructions and
object file other information needed to construct the code spaces and the initial data for a TNS/E native
process.
TNS/E native A process initiated by executing a TNS/E native object file. Contrast withTNS process and
process TNS/E native process.
TNS/R Refers to fault-tolerant HP computers that support the HP NonStop operating system and are
based on 32-bit reduced instruction-set computing (RISC) technology. TNS/R systems run the
MIPS-1 RISC instruction set and can run TNS object files by interpretation or after acceleration.
TNS/R systems include all HP systems that use NSR-x processors. Contrast with TNS and
TNS/E.

520 Glossary
TNS/R native The RISC instructions that result from processing program source code with a TNS/R native
object code compiler. TNS/R native object code executes only on TNS/R systems, not on TNS or TNS/E
systems.
TNS/R native An object file created by a TNS/R native compiler that contains RISC instructions and other
object file information needed to construct the code spaces and the initial data for a TNS/R native process.
TNS/R native A process initiated by executing a TNS/R native object file. Contrast with TNS process and
process TNS/E native process.
UID A nonnegative integer that uniquely identifies a user within a node.
The UID is a scalar number consisting of the group number multiplied by 256 and added to
the member number; for example, the UID of the super ID is (255*256) + 255, or 65535. The UID
is used in the OSS environment for functions normally associated with a UNIX user ID.
See also user ID.
unstructured file A disk file that is essentially a large byte array, most often used as a code file or an EDIT file,
not as a data file.
user ID The unique identification of a user within a node.
In the Guardian environment, the term “user ID” usually means the group number and member
number pair; for example, the user ID of the super ID is usually described as (255, 255). In the
OSS environment, the term “user ID” usually refers to the single number that is the scalar view
of the user ID—a number called the UID. See also UID.
volume A logical disk, which can be one or two magnetic disk drives. In HP NonStop S-series systems,
volumes have names that begin with a dollar sign ($), such as $DATA.
waited I/O I/O operations for which the initiating process does not resume execution until the I/O operations
are completed. Contrast with nowait I/O.

521
522
Index
derived default base entries, 255
Symbols example of, 255
$0 collector process, 227 permissions for new files, 253
$RECEIVE, 110, 117, 164, 165, 176, 179, 235, 237, 277, 380 limits for, 250
example with OSS processes and Guardian procedures, NFS V2 clients and, 257
166, 172, 179 notation, 251
$ZAFN2, 178 on directories, 253
$ZLSnn, 176 OSS permissions and, 60
$ZPLS, 176, 177 present on a file, 60
/dev/tty, 195 Safeguard, 60
32-bit APIs (see Large File Safe (LFS)) setacl command, 256
64-bit APIs (see Large File Aware (LFA)) supported RVUs, 61
_exit() function, 142 types of files supported, 250
_INTEROPERABLE feature-test macro, 64 types of objects supported, 61
_PUT_MODEL_ macro access control lists (ACLs)
, 374 and NFS, 61, 250
_r in function names (see reentrant functions) access() function, 85, 87, 243
_TANDEM_SOURCE feature-test macro, 453 acl() function, 241, 243, 256
_XOPEN_SOURCE feature-test macro, 453 ACL-PRESENT flag, 60
_XOPEN_SOURCE_EXTENDED feature-test macro, 454 ACLs (see Access control lists (ACLs))
aclsort() function, 258
A add_define utility, 106
abort() function, 110, 141 ADDDSTTRANSITION procedure, 161
Absolute pathname, 28 AF_INET sockets, 163, 164, 165
Accelerator, 45, 47 AF_INET6 sockets, 164
accept() function, 177, 185 AF_UNIX sockets
Access control lists (ACLs) AF_UNIX Release 1, 176
access-checking algroithm, 256 AF_UNIX Release 2, 176
acl() function, 256 audited function calls, 243
ACL-PRESENT flag, 60 compatibility mode, 176, 177
aclsort() function, 258 Guardian sockets API, 165
and chmod() function, 257 interprocess communication using OSS and Guardian
and chown() function, 257 APIs, 164
and Network File System (NFS), 61 interprocess communication using OSS APIs, 163
and SECURITY-OSS-ADMINISTRATOR security OSS sockets local server ($ZPLS), 176
group, 61 OSS sockets local server 2 ($ZLSnn), 176
and stat() function, 256 portability mode, 176, 177
and utilities, 256 transport-provider name, 177, 178
and Version 3 filesets, 61 alarm() function, 141, 155, 159
compared to permissions, 249 Guardian processes, 156
copying, 256 ANSISTREAMS pragma , 62
disk volumes and, 61 API, 26
effect on pathnames, 61, 249 Application program interface (API), 25
entries Applications
actual, 253 block mode, 42
base, 251 development of, 35
base default, 253 ar utility, 43
class, 252 asctime() function, 155, 159
default, 253 Attributes, process, 105
nondefault, 253 setting, 113
optional, 252 AWAITIO/[X] procedures
example program, 258 with threads, 277, 380
getacl command, 256 AWAITIO\[X] procedures, 191
header file, 258 example, 66
inheritance AWAITIObk/[X] procedures, 94
and directories, 254

523
B Conforming POSIX.1 application, 27
bind() function, 185, 243 confstr() function, 87
BINSEM_CLOSE_ procedure, 191 connect() function, 177, 185, 245
BINSEM_CREATE_ procedure, 191 CONTROL procedure, 193, 223
BINSEM_FORCELOCK_ procedure, 191 example, 219
BINSEM_LOCK_ procedure, 192 CONTROLBUF procedure, 193
BINSEM_OPEN_ procedure, 192 Controlling processes
BINSEM_UNLOCK_ procedure, 192 example using the PROCESS_SPAWN_ procedure, 118
Bits, referring to, 41 Guardian processes
bk/G directory, 30, 52 example using Guardian procedures, 115
Block-mode applications, 42 using Guardian procedures, 115, 118
OSS processes, using Guardian procedures, 115, 118
C using OSS functions, 111
C development utilities, 43 Controlling terminal, 106
C functions, Guardian, use in OSS programs, 40 CONVERTPROCESSTIME procedure, 161
C modules, Guardian CONVERTTIMESTAMP procedure, 161
invoking, 41 CPUTIMES procedure, 161
systype guardian pragma, 41 creat() function, 87, 244
c89 utility, 41, 44, 236 creat64() function, 244
c99 utility, 41, 44, 236 Creating processes
Caching, file, 82 example using the PROCESS_SPAWN_ procedure, 118
CANCEL procedure, 192 Guardian processes
Cancelability example using Guardian procedures, 115
PUT Model library, 379 using Guardian procedures, 115
SPT library, 276 OSS processes
cancellation points example using the tdm_fork() and tdm_execvep()
, 357 functions, 111
potential, 358 example using the tdm_spawnp() function, 113
CANCELPROCESSTIMEOUT procedure, 161 using Guardian procedures, 115
CANCELREQ procedure, 192 performance considerations, 130
CANCELTIMEOUT procedure, 161 using OSS functions, 111
cextdecs.h library header file , 37 Cross compilation , 35
cfgetispeed() function, 221 Cross compiler, PC, 49
cfgetospeed() function, 221 crypt() function, 241
cfsetispeed() function, 221 ctermid() function, 87, 222
cfsetospeed() function, 221 ctime() function, 155, 159
chdir() function, 85, 245 CTOEDIT file-type conversion tool, 47
CHECKSETMODE procedure, 223 cuserid() function, 241
Child process, 34
CHILD_LOST_ procedure, 147 D
chmod() function, 86, 241, 244 Data buffer size and performance improvements, 183
ACLs and, 257 Data heap , 150
chown() function, 86, 241, 244 Debug options, Guardian process attributes for, 106
ACLs and, 257 Debuggers
chroot() function, 86, 245 Inspect, 45
clock() function, 155, 157, 159 Native Inspect, 45
close() function, 86 NSDEE debugging features, 46, 49
closedir() function, 87 Visual Inspect, 46
closelog() function, 226, 231, 232 Declarations, Guardian procedures, 37
Comma, as placeholder for optional Guardian parameter, DEFINEs, 106, 198
38 Guardian process attributes for, 106
Communications subsystems, accessing from OSS del_define utility, 106
programs, 235 Development, application, 35
Compilation tools DEVICE_GETINFOBYLDEV_ procedure, 223
Guardian, 47 difftime() function, 155
OSS, 43 Directory, 27
COMPUTEJULIANDAYNO procedure, 161 DLLs (see Dynamic-link libraries (DLLs))
COMPUTETIMESTAMP procedure, 161 dup() function, 87
Condition codes, Guardian procedure, OSS example, 38 Dynamic window

524 Index
Telserv, 198, 199 Fault isolation, 279, 380
Dynamic-link libraries (DLLs), 45 fchmod() function, 241, 244
fchown() function, 241, 244
E fclose() function, 87
EAGAIN error, 289, 345 fcntl() function, 87
EALREADY error, 296, 348 fd_count parameter, child process, 115
ECONNREFUSED error, 177, 178 fd_map parameter, child process, 115
ed line editor, 43 FE_ENOENT error, 177
EDIT files , 31 Feature-test macro, 453, 454
OSS access, 62 FIFO, 163, 164, 165
redirecting OSS output to, 202 File caching, 82
EDITTOC file-type conversion tool, 47 File descriptor
EINPROGRESS error, 289, 345 inherited from parent process , 115
eld utility, 44, 47 nonblocking, 289, 345
EMS File system, 28
collector processes , 226 Guardian, 29, 31
specifying from shell , 227 OSS, 27, 29
procedures, 225, 226 File types
access from OSS processes, 226 Guardian, OSS access, 31
tokens, logging parameter, 232 OSS, 28
EMS_COLLECTOR shell variable, 227 File-type conversion tools, 47
encrypt() function, 241 FILE_ALTERLIST_ procedure, 94
endgrent() function, 242 FILE_CLOSE_ procedure, 192
endhostent() function, 188 FILE_COMPLETE_ procedure, 94
endnetent() function, 188 FILE_COMPLETE_GETINFO_ procedure, 94
endprotoent() function, 188 FILE_COMPLETE_SET_ procedure, 95
endservent() function, 188 FILE_CREATE_ procedure, 95
enoft utility, 44, 47 FILE_CREATELIST_ procedure, 95
Enscribe functions, thread-aware, 370 FILE_GETINFO_ procedure, 95, 192
Environment example, 72
execution, 35 FILE_GETINFOBYNAME_ procedure, 95
process example, 36, 70
modifying, 127 FILE_GETINFOLIST_ procedure, 95
obtaining information about, 121 information provided, 35
source, 35 FILE_GETINFOLISTBYNAME_ procedure, 95
target, 35 FILE_GETLOCKINFO_ procedure, 95
Environment variables, 34 FILE_GETOPENINFO_ procedure, 95
Environment-specific parameters in functions, 64, 451 FILE_GETRECEIVEINFO_ procedure, 192
Epoch, 156 FILE_OPEN_ procedure, 95, 192
Error reporting in thread functions, 262, 330 example, 38, 66, 68, 72, 200, 216, 219
ETK, 49 used with audited file, 245
Event Management Service (EMS) (see EMS) FILE_OPEN_CHKPT_ procedure, 96
EWOULDBLOCK error, 289, 345 FILE_PURGE_ procedure, 96
Examples, programming, 15 FILE_RENAME_ procedure, 96
exec set of functions, 34, 105, 244 Filename
and threads, 279, 380 displaying Guardian filename corresponding to OSS
execl() function, 142 pathname, 54
execle() function, 142 displaying OSS pathname corresponding to Guardian
execlp() function, 142 filename, 54
Execution environment, 35 Guardian (see Guardian filenames)
Execution priority OSS, and disks, 27
changing, example, 128 FILENAME_TO_PATHNAME_ procedure, 96
process, changing, 106 example, 56
execv() function, 142 FILENAME_TO_PROCESSHANDLE_ procedure, 147
execve() function, 34, 142 Files
execvep() function, 142 accessing from Guardian API, 65
accessing from OSS API, 62
F EDIT
Facility, logging, 228 See EDIT files, 31

525
Guardian getpid() function, 143, 242
See Guardian files, 31 getppid() function, 143, 242
odd-unstructured, 31 getprotobyname() function, 189
OSS access, 62 getprotobynumber() function, 189
OSS getprotoent() function, 189
See OSS files, 55 getservbyname() function, 189
unstructured, 31 getservbyport() function, 189
Fileset, 28 getservent() function, 189
fopen() function, 87 getsid() function, 143, 242
fopen_guardian() function, 88 getsockname() function, 177, 185
fopen_oss() function, 88 getsockopt() function, 185
fork() function, 34, 98, 142, 244 gettimeofday() function, 159
performance considerations, 130 getuid() function, 143, 242
with threads, 279, 380 Global resources, 261, 332
fpathconf() function, 88, 222 globfree() function, 89
fread() function, 88 gmtime() function, 155
freeaddrinfo() function, 188 gname utility, 54
freehostent function, 188 Group ID, 32
fstat() function, 60, 88, 242 gtacl utility , 42
fstat64() function, 242 Guardian attributes
fstatvfs() function, 88, 242 OSS processes, 105
fstatvfs64() function, 242 setting, 106
fsync() function, 88 Guardian C functions, using in OSS programs, 40
ftime() function, 159 Guardian C modules
FTIOMODE attribute, 82 binding to OSS program, 41
ftok() function, 165, 185 compiling with systype pragma, 41
ftruncate() function, 88 invoking, 41
ftw() function, 89 systype guardian pragma, 41
Function Guardian DEFINE eq_AFUNIX_PROCESS_NAME, 177,
OSS, using, 35 178
with environment-specific parameters, 64, 451 Guardian environment
FUP INFO command, OSS file display, 55 Guardian processes, running with gtacl, 42
nesting, 52
G text-editor, 47
gai_sterr() function, 188 Guardian file system , 29
getacl command, 256 Guardian filenames, 29, 51
getaddrinfo() function, 188 corresponding pathnames, 54, 56
getcwd() function, 89 length, 52
getdate() function, 159 pathname translation rules, 53
getegid() function, 142, 242 Guardian files
getenv() function, 142 access, 31
geteuid() function, 143, 242 accessing from OSS API, 62, 63
getgid() function, 143, 242 RWEP, 31
getgrent() function, 242 security, 31
getgroups() function, 143, 242 Guardian parent process
gethostbyaddr() function, 188 ancestors, 34
gethostbyname() function, 188 OSS process, 117
gethostent() function, 188 Guardian procedures
gethostid() function, 188 bit references, 41
getipnodebyaddr function, 188 integer data type, 37
getipnodebyname() function, 189 prototype declarations, 37
getlogin() function, 242 using in OSS programs, 35
getnameinfo() function, 189 Guardian processes
getnetbyaddr() function, 189 attributes, 34
getnetbyname() function, 189 creating and controlling from OSS, example using
getnetent() function, 189 Guardian procedures, 115
getpass() function, 242 inheritance, 34
getpeername() function, 177, 189 modifying environment, 127
getpgrp() function, 143, 242 obtaining information about, 121

526 Index
OSS access, 105 Inheritance information, OSS, 111
OSS attributes, 105 Initializing logging parameters, 228
OSS child process times, 157 Inspect debugger, 45
processor time, 157 process blocking, 277, 380
redirecting OSS input and output, 202 Integer data type
running from OSS environment, 42 Guardian procedures, 37
Guardian security, 31 OSS C programs, 37
corresponding OSS file-access permission, 60 Interoperability
Guardian sockets, 166, 167 API
Guidelines for threaded application development, 276, in native processes, 451
378 in TNS processes, 427
file system, 63
H I/O management, 195
Header files, library , 35 interprocess communication, 165
Home terminal Guardian process attribute, 106 logging, 226
HP Enterprise Toolkit - NonStop Edition, 49 memory management, 150
HP extension functions , 34 process management, 107
HP NonStop SQL/MP, accessing from OSS programs, 236 redirecting I/O to Guardian objects, 202
HP NonStop SQL/MX, accessing from OSS programs, signals, 110
236 time management, 156
HP NonStop subsystems INTERPRETINTERVAL procedure, 161
accessing from OSS programs, 235 INTERPRETJULIANDAYNO procedure , 156, 161
communications, accessing from OSS programs, 235 INTERPRETTIMESTAMP procedure, 161
HP NonStop TMF, accessing from OSS programs, 237 Interprocess communication
HP NonStop TS/MP, accessing from OSS programs, 236 between nodes, 179
HP NonStop Tuxedo system, accessing from OSS between processors, 163, 164
programs, 237 example with OSS processes and Guardian procedures,
HP Tandem Development Suite (TDS), 49 166
HP Tandem LAN Access Method (TLAM), accessing from performance considerations, 183
OSS programs, 235 UNIX differences, 165
htonl() function, 190 using a $RECEIVE file, 179
htons() function, 190 ioctl() function, 89
isatty() function, 222
I
I/O J
balancing read and write operations, and performance Jacket routines, 276, 378
improvement, 183 JULIANTIMESTAMP procedure, 157, 161
printing, 214, 215, 221
example, lp utility with popen() function, 214 K
redirecting to Guardian objects, 202 kill() function, 110, 143, 244
tape, 196
example, pax utility with popen() function, 197 L
terminal, 198 Labeled tape
control characters, 199 and OSS files, 198
example, 200 LABELEDTAPESUPPORT procedure, 223
if_freenameindex() function, 189 Large File Aware (LFA)
if_indextoname() function, 189 APIs provided by HP, 77
if_nameindex() function, 189 definition, 75
if_nametoindex() function, 189 Large File Safe (LFS)
inet_addr() function, 190 APIs provided by HP, 75
inet_lnaof() function, 190 definition, 75
inet_makeaddr() function, 190 Large files (see also OSS files, large files)
inet_netof() function, 190 access from systems without large file support, 77
inet_network() function, 190 accessing from systems without large file support, 75
inet_ntoa() function, 190 and 64-bit APIs, 75
inet_ntop() function, 190 and FILE_OPEN, 78
inet_pton() function, 190 and FILE_OPEN_ error 580, 79
inherit structure, 115 Guardian files created by OSS APIs, 78
tdm_spawn() and tdm_spawnp() functions, 111 size limit, 74

527
underlying Guardian file format, 74 versus single-threading, 280, 381
lchmod() function, 241, 244 Mutex
lchown() function, 241, 244 to protect context, 277, 379
ld utility, 44, 47 to protect shared data, 277, 379
lex utility, 43 with multiple interdependent threads, 280, 382
Library MYPROCESSTIME procedure, 156, 161
standard and threaded applications, 276
standard, and single-threading, 279, 381 N
threads, 261, 281, 329, 368 Name, process, setting, 113
Library functions, 35 Native Inspect debugger, 45
Library header files, 35 Native process, 34
link() function, 89, 244 Nesting, 52
Linking C modules, OSS, 44 Network File System (NFS), 245
listen() function, 177, 178, 185 NFS, 245
localtime() function, 155, 159 nftw() and nftw64() functions, 90
LOCKFILE procedure, 96 nftw() function, 144
LOCKREC procedure, 96 nftw64() function, 144
LOG_WARNING, severity level, 227 nice() function, 103, 105
Logging, 227 nld utility, 44, 47
facility, 228 nm utility, 43
functions, calling from Guardian module, 226 noft utility, 44, 47
interoperability, 226 Nonblocking I/O functions, 289, 345
parameters, initializing , 228 PUT Model library, 346
longjmp() function, 143, 278, 337 NonStop Development Environment for Eclipse (NSDEE),
lp utility, example with popen() function, 214 49
lseek() and lseek64() functions, 89 NORMALIOMODE attribute, 82
lstat() and lstat64() functions, 90 Nowait I/O, 277, 280, 380, 381
lstat() function, 242 Nowait Ibk/O, 65
lstat64() function, 242 Nowait OSS process creation, 117
NSDEE, 49
M ntohs() function, 190
make utility, 43
Measure product , 48, 156 O
Memory O_NONBLOCK flag, 289, 345
data heap, 150 O_SYNC file open flag, 82, 83
manipulating with both OSS functions and Guardian Object Code Accelerator (OCA), 47
procedures, 178 Odd-unstructured files, 31
sharing, 165 OSS access, 62
and synchronizing, 150, 178 Open System Services (OSS), 25
UNIX differences , 150 Open Systems Interconnection/Application Services
Message queues, 163, 164, 165 (OSI/AS), accessing from OSS programs, 235
MESSAGESTATUS procedure, 193 Open Systems Interconnection/Message Handling System
mkdir() function, 90, 242, 244 (OSI/MHS), accessing from OSS programs, 235
mkfifo() function, 185, 244 open() and open64() functions, 90
mknod() function, 90, 244 open() function, 90, 244
mkstemp() function, 90 Guardian files, 63
mktime() function, 155, 160 open64() function, 244
Modules, Guardianbk/ C opendir() function, 91, 244
binding to OSS program, 41 openlog() function, 226, 227, 228, 232
compiling with systype pragma, 41 Optimizer, 45
MOM process, 34 OSI/AS, accessing from OSS programs, 235
MONITORCPUS procedure , 118 OSI/MHS, accessing from OSS programs, 235
msgctl() function, 185 OSS C programs, integer data type, 37
msgget() function, 185 OSS child processes, monitoring by reading $RECEIVE,
msgrcv() function, 186 117
msgsnd() function, 186 OSS environment
Multithreading Guardian command, piping output, 42
independent application threads, 280, 381 TACL process, starting from, 42
interdependent application threads, 280, 382 text-editing tools, 43

528 Index
OSS file system, 27 OSS requesters, not supported by HP NonStop/TM TS/MP
directories, 52 , 236
nesting, 52 OSS servers, monitoring with HP NonStop/TM TS/MP ,
UNIX differences, 62 236
OSS files OSS_PID_NULL_ procedure, 147
FUP INFO command display, 55 OSSTTY facility;Interoperability
information with Guardian procedure by name, 70, 72 using OSSTTY, 202
information with Guardian procedure by number, 72
labeled-tape operations, 198 P
large files, 74 Parameters, optional Guardian,
printing from program, 214 comma as placeholder for, 38
reading with Guardian procedure, nowait mode, 68 Parent process, 34
reading with Guardian procedure, wait mode, 69 pathconf() function, 91, 222
sending directly to printer, 219 Pathname, 28, 51
sending to Guardian print spooler, 216 corresponding Guardian filenames, 54, 55
size limits, 62 from Guardian filename with FUP INFO DETAIL, 55
small files, 74 Guardian filename translation rules, 52
types, 28, 62 length, 52
OSS functions, use in programs, 35 relative, Guardian translation, 53
OSS HP extension functions, process management, 105 PATHNAME_TO_FILENAME_ procedure, 96, 130
OSS logging example, 55, 70
facility, 228 Pathway server
functions, calling from Guardian module , 226 and SERVERCLASS_DIALOG, 281, 368
parameters and SERVERCLASS_SEND_, 281, 368
default values, 227 and SERVERCLASS_SENDL_, 281, 368
initializing , 228 process blocking, 277, 380
severity level, 227 pause() function, 144
UNIX differences, 226 pax utility, example with popen() function, 197
OSS module PC cross compiler, 49
environment, 451, 452 pclose() function, 186
OSS pathnames, 51 Performance analyzer, 48
OSS process handle, 105 Performance considerations
OSS process ID, 32, 105 file system functions, 82
OSS processes, 202 fork() function , 130
accessing EMS procedures , 226 interprocess communication , 183
attributes, 34 process creation, 111, 130
controlling process management , 130
example using the PROCESS_SPAWN_ procedure, tdm_fork() function , 130
118 tdm_spawn() function , 130
using Guardian procedures, 117 tdm_spawnp() function , 130
creating, 111 workload distribution, 130
example using the PROCESS_SPAWN_ procedure, Permissions, OSS
118 corresponding Guardian security, 60
example using the tdm_fork() and tdm_execvep() FUP INFO display, 55
functions, 111 permission bits, 29
example using the tdm_spawnp() function, 113, 115 perror() function, 232
nowait manner, 117 Persistent process, 117
using Guardian procedures, 117 PIC (see Position-independent code (PIC))
environment , 452 Pipe, 163, 164, 165
Guardian access, 105 pipe() function, 91, 186, 245
Guardian parent, 117 Piping Guardian output, 42
inheritance, 34 pname utility, 54
modifying environment, 127 popen() function, 186
obtaining information about, 121 example with lp utility, 214
example with PROCESS_GETINFOLIST_ procedure, example with pax utility, 197
125, 127 Portability of threads, 275, 356
operator messages, receiving, 225 Position-independent code (PIC), 45
UNIX differences, 97 POSIX standards, 26, 27
POSIX Threads (see Threads)

529
Pragmas example, 118
SYSTYPE GUARDIAN, 41 used with audited file, 245
SYSTYPE OSS, 41 PROCESS_STOP_ procedure, 147
Printers example, 115
/G directory inaccessibility, 219 PROCESS_SUSPEND_ procedure, 147
control codes, 219 example, 115
sending OSS files directly to, 219 Processes, 31
Printing, 215 controlling
example, lp utility with popen() function, 214 See Controlling processes, 111
OSS utilities only, 195 creating
Priority See Creating processes, 111
Guardian process attribute, 106 Guardian
process execution, 106 See Guardian processes, 105
Private resources, 261, 332 identification, 32
Procedure, Guardian modifying environment, 127
condition code obtaining information about
and return value, 36, 40 environment, 121
OSS example, 38 example with PROCESS_GETINFO_ procedure, 123
return value OSS
and condition code, 36, 40 See OSS processes, 105
OSS example, 36 persistent, 117
use in OSS programs, 35 pipes and FIFOs on same processor, and performance
Process attributes, 105 improvements , 183
setting, 113 PROCESSHANDLE_COMPARE_ procedure, 147
Process environment PROCESSHANDLE_DECOMPOSE_ procedure, 148
modifying, 127, 130 PROCESSHANDLE_GETMINE_ procedure, 148
obtaining information about, 121 PROCESSHANDLE_NULLIT_ procedure, 148
OSS, 34 PROCESSHANDLE_TO_CRTPID_ procedure, 148
Process group, 32 PROCESSHANDLE_TO_FILENAME_ procedure , 148
Process handle, 32 PROCESSHANDLE_TO_STRING_ procedure, 148
OSS process, 105, 107 PROCESSNAME_CREATE_ procedure , 148
Process ID, OSS, 105 Processor
Process identifiers, 32 Guardian process attribute, 106
Process management process execution, 106
OSS HP extension functions, 105 Processor time, limiting, example , 157
performance improvement, 130 PROCESSOR_GETINFOLIST_ procedure, 162
Process name, 32 PROCESSSTRING_SCAN_ procedure , 148
setting, 113 Programmatic interfaces, 55
Process pairs, 34 Programming examples, 15
Process priority, modification by OSS process, 105 Programming, UNIX, books, 15
Process resources, 276, 378 Prototype declarations for Guardian procedures, 37
Process-blocking calls, from threads, 277, 380 Pthread functions, 261, 329
Process-blocking I/O function, 288, 345 pthread.h header file, 329
PROCESS_ACTIVATE_ procedure, 147 pthread.h header files, 374
example, 115 pthread_yield function (sched_yield), 261
PROCESS_CREATE_ procedure PUT Model library
example, 115 $RECEIVE I/O, 364
PROCESS_DEBUG_ procedure, 147 _PUT_MODEL_ define, 329
PROCESS_GETINFO_ procedure , 122, 147, 156, 161 _PUT_MODEL_ macro, 374
example, 123 _PUT_SELECT_SINGLE_ define, 330
PROCESS_GETINFOLIST_ procedure , 118, 123, 147, 156, and reentrant functions, 359
161 attributes defined by macros, 331
example, 125 build script, 374
PROCESS_GETPAIRINFO_ procedure, 147 cancel requests, 379
PROCESS_SETINFO_ procedure , 106, 130, 147 cancellation points, 357
example, 128 concurrency level, default, 375
PROCESS_SETSTRINGINFO_ procedure, 147 converting to from SPT, 373
example, 128 Enscribe functions, thread-aware, 370
PROCESS_SPAWN_ procedure, 117, 147, 237 Environment variables, 330

530 Index
file descriptor and timer callbacks, 372 reentrant functions
header file, 329, 374 definition of, 313, 359
header files, 374 H06.21 and later H-series RVUs, 359
incompatibility with SPT library, 329 J06.10 and later J-series RVUs, 359
nonblocking, 345 Relative pathname, 28
nonblocking functions, 346 Guardian translation, 53
numerical limits, 333 remove() function, 92
portability of, 356 rename() function, 92, 244
potential cancellation points, 358 rename_oss() function, 92
process resources, use of, 378 REPLYX procedure, 192
protected signal stack, 336 Resource types, 261, 332
serializing file operations on open regular files, 345 retcode, 37
SERVERCLASS_DIALOG jacket routines, 368 Return value
SERVERCLASS_SEND jacket routines, 368 changes for thread functions, 262, 330
SERVERCLASS_SENDL jacket routines, 368 Guardian procedure, OSS example, 36
signals, 335, 337 rewinddir() function, 92
standard and nonstandard types, 375 rmdir() function, 92, 242, 244
standards conformance, 330 Root directory, 27
supported RVUs, 329
thread safety, 356 S
thread unsafe functions, 357 S_NONSTOP attribute
thread-aware functions, 346 performance and reliability considerations, 83
thread-aware I/O, disabling, 345 S_NONSTOP file open flag, 82, 83
thread-aware toolkit functions, 361 Safeguard
TMF jacket routines, 369 access control lists (ACLs), 60
ZPUTDLL, 329 using for file audit reduction, 239
PUT_ABORTTRANSACTION() function, 369 using to administer users and groups, 239
PUT_BEGINTRANSACTION() function, 369 using to protect disk volumes, 61
PUT_ENDTRANSACTION() function, 369 scandir() and scandir64() functions, 92
put_extensions.h header file, 374 sched_yield function, 261, 278, 280, 329, 380, 381
PUT_PROTECTED_STACK_DISABLE, 330 Scheduling priority, 105
PUT_RESUMETRANSACTION() function, 369 Security, Guardian and OSS permissions, 60
PUT_SERVERCLASS_DIALOG_ABORT_() function, 369 sed stream editor, 43
PUT_SERVERCLASS_DIALOG_BEGIN_() function, 369 seekdir() function, 92
PUT_SERVERCLASS_DIALOG_END_() function, 369 SEGMENT_ALLOCATE_ procedure, 192
PUT_SERVERCLASS_DIALOG_SEND_() function, 369 SEGMENT_DEALLOCATE_ procedure, 192
PUT_SERVERCLASS_SEND_() function, 368 SEGMENT_USE_ procedure, 192
PUT_SERVERCLASS_SEND_INFO_() function, 368 select() function, 92
PUT_SERVERCLASS_SENDL_() function, 368 Semaphore, 163, 164, 165
PUT_THREAD_AWARE_REGULAR_IO_DISABLE, 330 semctl() function, 186
put_types.h header file, 374 semget() function, 186
putenv() function, 144 semop() function, 186
send() function, 186
R sendmsg() function, 186
raise() function, 110, 144, 279, 337 sendto() function, 186
read() function, 91 Server class, 237
readdir() and readdir64() functions, 91 Server process, interprocess communication examples,
readlink() function, 91 166
READLOCKX procedure, 96 SERVERCLASS_DIALOG routines, 281, 368
READUPDATELOCKX procedure, 96 SERVERCLASS_SEND_ function, 281, 368
READUPDATEX procedure, 192 SERVERCLASS_SENDL_ function, 281, 368
readv() function, 91 setacl command, 256
READX procedure, 193 setgid() function, 144, 242, 244
example, 38, 66, 68, 200 setgrent() function, 242
recv() function, 186 sethostent() function, 190
recvfrom() function, 177, 178, 186 setjmp() function, 144, 278, 337
recvmsg() function, 177, 178, 186 setkey() function, 242
Redirecting I/O to Guardian objects, 202 setlogmask() function, 226, 227, 232
redirecting I/O to Guardian objects, 202 SETLOOPTIMER procedure, 148, 162

531
OSS processes, 156 socket_transport_name_set() function, 177, 178, 188
example, 157 socketpair() function, 92, 187
SETMODE procedure, 96, 193, 223 sockets
SETMODENOWAIT procedure, 193, 223 AF_INET
setnetent() function, 191 See AF_INET sockets, 165
SETPARAM procedure, 193 AF_INET6
setpgid() function, 144, 242, 244 See AF_INET6 sockets, 166
setpgrp() function, 144, 244 AF_UNIX
setprotoent() function, 191 See AF_UNIX sockets, 176
setregid() function, 144, 242, 244 Source environment, 35
setreuid() function, 144, 242, 244 spawn.h library header file , 115
setservent() function, 191 Spawning a new process, and threads, 279, 380
setsid() function, 144, 242, 244 Specifications, XPG4, 26
setsockopt() function, 186 Spooler, Guardian print, sending OSS files to, 216
SETSYSTEMCLOCK procedure, 162 SPT_ABORTTRANSACTION() function, 282
setuid() function, 144, 242, 244 spt_alarm() function, 267
example, 128 SPT_BEGINTRANSACTION() function, 282
Severity level, events, 227 SPT_ENDTRANSACTION() function, 282
Shared memory , 163, 164 spt_extensions.h header file, 374
shmat() function, 187 SPT_RESUMETRANSACTION() function, 282
shmctl() function, 178, 187 SPT_SERVERCLASS_DIALOG_ABORT_() function, 282
shmdt() function, 187 SPT_SERVERCLASS_DIALOG_BEGIN_() function, 281
shmget() function, 187 SPT_SERVERCLASS_DIALOG_END_() function, 282
sigaction() function, 145, 263, 334 SPT_SERVERCLASS_DIALOG_SEND_() function, 281
used with threads, 278, 336 SPT_SERVERCLASS_SEND_() function, 281
SIGACTION_INIT_ procedure, 148 SPT_SERVERCLASS_SEND_INFO_() function, 281
SIGACTION_RESTORE_ procedure, 148 SPT_SERVERCLASS_SENDL_() function, 281
SIGACTION_SUPPLANT_ procedure, 148 spt_signal() function, 267
sigaddset() function, 145 spt_sigwait() function, 263
sigdelset() function, 145 spt_star() functions, 290
sigemptyset() function, 145 spt_starx() functions, 290
sigfillset() function, 145 spt_starz() functions, 289, 290
sigismember() function, 145 mixed mode applications, 296
SIGJMP_MASKSET_ procedure, 148 serialization of file operations, 289
siglongjmp() function, 145 spt_types.h header file, 374
Signal, 111 spt_ucontext.h header file, 374
compared to trap, 110 spthread.h header file, 262
handler, default, 110 SQL compiler, 44, 236
threads with, 279, 337 SQL databases, accessing from an OSS program , 236
Signal mask, 278, 337 SQL objects, catalogs, and programs, information from
signal() function, 145 an OSS program , 236
SIGNALPROCESSTIMEOUT procedure, 162 Standard POSIX Threads functions, 261
SIGNALTIMEOUT procedure, 162 Standards, POSIX, 26
sigpending() function, 145 stat() and stat64() functions, 93
sigprocmask() function, 145 stat() function, 60, 242
sigsetjmp() function, 145 ACLs and, 257
sigsuspend() function, 145 information provided, 35
sigwait() function, 334 stat64() function, 242
Single-threading versus multithreading, 279, 381 Static window
sleep() function, 110, 145 Telserv, 198
Small files (see OSS files, small files) statvfs() and statvfs64() functions, 93
and 64-bit APIs, 74 strerror() function, 233
size limit, 74 strftime() function, 155, 157, 160
underlying Guardian file format, 74 strip utility, 43
SNAX Extended Facility (SNAX/XF), accessing from OSS strptime() function, 156, 160
programs, 235 Subdirectories, 52
sockatmark() function, 187 Super ID, 239
socket() function, 92, 187 Symbolic debuggers, 45
socket_transport_name_get() function, 188 symlink() function, 93, 244

532 Index
sysconf() function, example, 122 using OSSTTY, 205
syslog() function, 226, 227, 229, 233 Text-editing tools
System functions, 35 Guardian, 47
System limits, system-dependent, obtaining, example, OSS, 43
122 Thread functions, 261, 329
SYSTYPE pragma, 41 Thread-aware OSS functions
$RECEIVE I/O, 320, 364
T contrasted to process-blocking functions, 288, 345
TACL processes, starting from OSS environment, 42 file descriptor, 326, 372
tal.h library header file, and condition codes, 39 for non-regular files, 290, 346
Tape I/O, 196 for regular files, 289, 345
example, pax with popen() function, 197 timer callbacks, 326, 372
OSS utilities only, 195 toolkit, 316, 361
pax utility, 196 using, 296, 348
Target environment, 35 Thread-blocking I/O function (see Thread-aware OSS
tcdrain() function, 222 functions)
tcflow() function, 222 Threading considerations, 276, 378
tcflush() function, 222 Threads
tcgetattr() function, 222 compiling and binding , 262, 281, 282, 329, 369
TCP/IP error reporting, 262, 330
accessing from OSS programs, 235 NonStop server implementation, 261, 329
tcsendbreak() function, 222 portability, 275, 356
tcsetattr() function, 222 signals, 263, 278, 334, 335
tdm_execep() function, 279, 380 protected stack, 336
tdm_execve() function, 105, 145, 279, 380 PUT Model library signal stack, 336
used with audited file, 244 single versus multiple, 280, 381
tdm_execvep() function, 105, 145 stack addressability, 277, 379
example, 111 Time management, UNIX differences, 156
used with audited file, 244 TIME procedure, 162
tdm_fork() function, 34, 105, 146 time() function, 155, 160
example, 111 times() function, 146, 155, 157, 160
performance considerations, 130 in Guardian process, 156
used with audited file, 245 timespec_t type, 375
used with threads, 279, 380 TIMESTAMP procedure, 162
tdm_spawn() function, 105, 146 Timestamps , 156
performance considerations, 111, 130 TLAM, accessing from OSS programs, 235
used with audited file, 245 TMF jacket routines for threads, 282, 369
tdm_spawnp() function, 105 TNS process, 34
example, 113, 115 TNSE native process, 34
performance considerations, 111, 130 TNSR native process, 34
used with audited file, 245 Tools
tdm_spawnp(2) function, 146 development
tdmext.h library header file , 113 Guardian, 47
TDS, 49 OSS, 42
TEDIT full-screen text editor, 47 multienvironment, 41
telldir() function, 93 text-editing
Telserv windows, 198 Guardian, 47
Terminal OSS, 43
control characters, 199 Transaction jackets for threads, 282, 369
Guardian, accessing with Guardian procedures, Trap, compared to signal, 110
example, 200 tty command, 130
names, 130 ttyname() function , 130, 222
Terminal I/O, 198 tzset() function, 156, 160
/dev/tty, 195
canonical mode, 199 U
interoperability, 195 ulimit() function, 93
network terminals only, 195 umask() function, 93
noncanonical mode, 200 uname() function, 146
UNIX differences, 195 unlink() function, 93, 245

533
Unstructured file, 31
Unsupported utilities, 15
User ID, example of setting with setuid(), 128
Utilities
development, 43
unsupported, 15
utime() function, 93, 156, 160, 245
Guardian files, 156

V
vi screen-oriented line editor, 43
Visual Inspect debugger, 46

W
wait() function, 146
waitpid() function, 146
wcsftime() function, 160
Windows, multiple, 42
Workload distribution, performance considerations, 130
write() function, 94
WRITEREADX procedure, 192
example, 202
WRITEUPDATEUNLOCK\[X] procedure, 96
writev() function, 94
WRITEX procedure, 193
example, 219

X
X.25 Access Method (X25AM), accessing from OSS
programs, 235
XPG4 specifications, 26, 165

Y
yacc utility, 43
Yielding control by threads, 278, 280, 380, 381

Z
ZPUTDLL, 329

534 Index
535

You might also like