Chapter Contents

Previous

Next
SAS/C Software: Changes and Enhancements, Release 6.50


New OpenEdition Library Functions

 This section describes the new library functions available to Release 6.50 SAS/C users under OpenEdition.


chpriority

  Change process priority

SYNOPSIS
 #include <sys/resource.h>
int chpriority(int kind, id_t id, 
               int form, int prio);

DESCRIPTION
The chpriority function changes the OpenEdition priority of a process, or of all processes in a process group or belonging to a user. See the  getpriority function description in section getpriority for further information on OpenEdition priorities.  

The kind argument to  chpriority should be specified as a symbolic constant indicating the scope of the priority change. The permissible values are: 

 

The id argument specifies the process id, process group id, or user id whose priority should be changed. If  id is 0, the calling process id, process group id, or user id is specified. 

The form argument specifies whether the  prio argument is an absolute or relative priority. It should be specified as one of the following symbolic constants: 

 

The prio argument specifies the requested new priority, or the amount by which the priority should be changed, depending of the value of the  form argument. Priorities are restricted to the range of -20 to 19, where lower numbers indicate higher priority.  

Note:   OpenEdition sites must enable the use of the chpriority function. If the use of  chpriority has not been enabled, any use of  chpriority will fail with errno set to  ENOSYS.  [cautend]

 RETURN VALUE
chpriority returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The chpriority function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
This example is compiled using sascc370 -Krent -o. This program demonstrates the use of the Open Edition process priority functions  chpriority(),  getpriority(), and  setpriority().
 /*---------------------------+
| POSIX/UNIX header files    |
+----------------------------*/
#include <unistd.h>

#include <sys/types.h>

#include <errno.h>
 
/*---------------------------+
| ISO/ANSI header files      |
+----------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <errno.h>
/*---------------------------+
| Name:     main             |
| Returns: exit(EXIT_SUCCESS)|
| or exit(EXIT_FAILURE)      |
+----------------------------|
+---------------------------*/
int main()
{
/* generic return code      */
   int rc;

/* which kind of process    */
/* id to use                */
   int kind;                  

 /* process id              */
   id_t id;                  

/* is oeprty relative or    */
/* absolute                 */
   int form;                 
 
/* process priority         */
/* (version 1)              */
   int prty1;                
 
/* process priority         */
/* (version 2)              */
   int prty2;                
 
/* process id from getpid() */
   pid_t pid;                
 
/* process group id from     */
/* getpgid()                 */
   pid_t pgid;               
  
/* process user id from      */
*/ getuid()                  */
   uid_t uid;                  

/* get the user id for this   */
/* process                    */
   uid = getuid();              

/* get the process id for     */
/* this process               */
   pid = getpid();              
/* get the group process id   */
/* for this process  */
   pgid = getpgid(pid); 

   if (pgid == -1)
   {
    perror("Call to getpgid failed");
    exit(EXIT_FAILURE);
   }

   printf("      The process id: %d\n", 
     (int)pid);
   printf("The process group id: %d\n", 
     (int)pgid);
   printf(" The process user id: %d\n", 
     (int)uid);

   /*------------------------------*/
   /* Get the process priority     */
   /* using the process id         */
   /*------------------------------*/
   print 
     ("\nGet the Process Priority 
         using the Process ID\n");

/* the id arg is the pid of a process */

   kind = PRIO_PROCESS;

   /* version 1 */
   id = (id_t)pid;

/* Set errno to zero for    */
/* error handling           */
   errno = 0;            
   prty1 = getpriority(kind, id);   

/* ---------------------------------*/
/* Test for Error                   */
/* Note:                            */
/* getpriority() may return a '-1'  */
/* return code for either a         */
/* failure rc, or when the priority */
/* is in-fact '-1'.  To distinguish */
/* between the two conditions,      */
/* check the errno                  */
/* value for a non-zero value.      */
/*----------------------------------*/
 if (prty1 == -1 && errno != 0)
 {
   perror("Call to getpriority failed");
   exit(EXIT_FAILURE);
   }
   else
   {
      printf("The process priority 
       (pid:version 1): %d\n", prty1);
   }
 
/* version 2 */
/* 0 implies current processs id  */
   id = (id_t)0;         

/* Reset errno to zero for        */
/* error handling                 */
   errno = 0;            
   prty2 = getpriority(kind, id);   

/* Test for Error */
   if (prty2 == -1 && errno != 0)
   {
      perror("Call to getpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
     printf("The process priority 
     (pid:version 2): %d\n", prty2);
   }

/*-----------------------------*/
/* Get the process priority    */
/* using the group process id  */
/*-----------------------------*/
   printf("\nGet the Process Priority 
    using the Group Process ID\n");

/* the id arg is the group process id */
   kind = PRIO_PGRP;     

/* version 1 */
   id = (id_t)pgid;

/* Set errno to zero for error handling      */
   errno = 0;            
   prty1 = getpriority(kind, id);   

/* Test for Error */
   if (prty1 == -1 && errno != 0)
   {
      perror("Call to getpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      printf("The process priority 
       (gpid:version 1): %d\n", prty1);
   }
 
/* version 2 */
/* 0 implies current group processs id       */
   id = (id_t)0;         

/* Reset errno to zero for error handling    */
   errno = 0;            
   prty2 = getpriority(kind, id);   

/* Test for Error */
   if (prty2 == -1 && errno != 0)
   {
      perror("Call to getpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      printf("The process priority 
       (gpid:version 2): %d\n", prty2);
   }

 /*-------------------------------------------*/
 /* Get the process priority using the        */
 /* process User id                           */
 /*-------------------------------------------*/
 print 
  ("\nGet the Process Priority of the User ID\n");

/* the id arg is the user id of the process  */
   kind = PRIO_USER;     

/* version 1 */
   id = (id_t)uid;
/* Set errno to zero for error handling      */
   errno = 0;            
   prty1 = getpriority(kind, id);   

   /* Test for Error */
   if (prty1 == -1 && errno != 0)
   {
      perror("Call to getpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      printf("The process priority (uid:version 2):
        %d\n", prty1);
   }
 
/* version 2 */
/* Reset errno to zero for error handling    */
   errno = 0;   
        
 /* 0 implies current process user id        */
   id = (id_t)0;         
   prty2 = getpriority(kind, id);   

   /* Test for Error */
   if (prty2 == -1 && errno != 0)
   {
      perror("Call to getpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      printf("The process priority (uid:version 2): 
       %d\n", prty2);
   }

/*-----------------------------------------------*/
/* Set the process priority using the            */
/* process id                                    */ 
 /*----------------------------------------------*/
 printf
("\nSet the Process Priority using 
   the Process ID\n");

/* the id arg is the pid of a process        */
   kind = PRIO_PROCESS;  

/* an id of 0 implies current processs id    */
   id = (id_t)0;         

/* Reset errno to zero for error handling    */
   errno = 0;            

/* Set process priority to 5                 */
   prty1 = 5;            

   rc = setpriority(kind, id, prty1);

   /*---------------------------------------------*/
   /* Test for Error                              */
   /* Note: OpenEdition sites must enable the use */
   /*       of the setpriority() function. If the */
   /*       use of setpriority() has not been     */
   /*       enabled, any use of setpriority()     */
   /*       will fail with errno set to ENOSYS.   */
   /*                                             */
   /*---------------------------------------------*/
   if (rc == -1)
   {
      perror("Call to setpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      prty2 = getpriority(kind, id);   

      /* Test for Error */
      if (errno != 0)
      {
         perror("Call to getpriority failed");
         exit(EXIT_FAILURE);
      }
      printf("The process priority is now (pid):
        %d\n", prty2);
   }

   /*--------------------------------------------*/
   /* Set the process priority using the group   */
   /* process id                                 */
   /*--------------------------------------------*/
 printf
("\nSet the Process Priority using 
   the Group Process ID\n");

/* the id arg is the group id of the process */
   kind = PRIO_PGRP;     

/* 0 implies current group processs id       */
   id = (id_t)0;         

/* Reset errno to zero for error handling    */
   errno = 0;            

/* Set process priority to 10                */
   prty1 = 10;           


   rc = setpriority(kind, id, prty1);

   /* Test for Error */
   if (rc == -1)
   {
      perror("Call to setpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      prty2 = getpriority(kind, id);   

      /* Test for Error */
      if (errno != 0)
      {
         perror("Call to getpriority failed");
         exit(EXIT_FAILURE);
      }
      printf("The process priority is now (gpid): 
       %d\n", prty2);
   }

 /*-------------------------------------------*/
 /* Set the process priority using the        */
 /*process User id                            */
 /*-------------------------------------------*/
  printf
  ("\nSet the Process Priority of 
     the User ID\n");

/* the id arg is the user id of the process  */
   kind = PRIO_USER;     

/* an id of 0 implies current user id        */
   id = (id_t)0;         

/* Reset errno to zero for error handling    */
   errno = 0;            

/* Set process priority to 15                */
   prty1 = 15;           


   rc = setpriority(kind, id, prty1);

/* Test for Error */
   if (rc == -1)
   {
      perror("Call to setpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      prty2 = getpriority(kind, id);   

      /* Test for Error */
      if (errno != 0)
      {
         perror("Call to getpriority failed");
         exit(EXIT_FAILURE);
      }
printf
("The process priority is now 
   (uid): %d\n", prty2);
   }

/*-------------------------------------------*/
/* Change the process priority using the     */
/* process id                                */
/*-------------------------------------------*/
printf
 ("\nChange the Process Priority 
    using the Process ID\n");

/* the id arg is the pid of a process        */
   kind = PRIO_PROCESS;  

/* an id of 0 implies current processs id    */
   id = (id_t)0;        
 
/* Reset errno to zero for error handling    */
   errno = 0;            

/* change using "absolute"                   */
/* priority - equivalent to setpriority()    */
   form = CPRIO_ABSOLUTE;
   printf("\tChange using CPRIO_ABSOLUTE\n");

/* Change process priority to 3              */
   prty1 = 3;            

   rc = chpriority(kind, id, form, prty1);

/*------------------------------------------------*/ 
/* Test for Error                                 */
/* Note: OpenEdition sites must enable the use    */
/*       of the chpriority() function.            */
/*       If the use of chpriority() has not been  */
/*       enabled, any use of chpriority() will    */
/*       fail with errno set to ENOSYS.           */
/*                                                */
/*------------------------------------------------*/
   if (rc == -1)
   {
      perror("Call to chpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      prty2 = getpriority(kind, id);   

      /* Test for Error */
      if (errno != 0)
      {
         perror("Call to getpriority failed");
         exit(EXIT_FAILURE);
      }
  printf
  ("The process priority is now 
     (pid): %d\n", prty2);
   }

/* change using "relative" priority */
   form = CPRIO_RELATIVE;
   printf("\tChange using CPRIO_RELATIVE\n");

/* Bump process priority up by 2            */
   prty1 = 2;            

   rc = chpriority(kind, id, form, prty1);

   /* Test for Error */
   if (rc == -1)
   {
      perror("Call to chpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      prty2 = getpriority(kind, id);   

      /* Test for Error */
      if (errno != 0)
      {
       perror("Call to getpriority failed");
       exit(EXIT_FAILURE);
      }
   printf("The process priority is now (pid): 
     %d\n", prty2);
   }

/*---------------------------------------------*/
/* Change the process priority using the       */
/* group process id                           */ 
/*---------------------------------------------*/
 printf
  ("\nChange the Process Priority using 
     the Group Process ID\n");

/* the id arg is the group id of the process */
   kind = PRIO_PGRP;     

/* 0 implies current group processs id       */
    id = (id_t)0;         

/* Reset errno to zero for error handling    */
   errno = 0;            

   /* change using "absolute"                 */
   /* priority - equivalent to setpriority()  */
   form = CPRIO_ABSOLUTE;
   printf("\tChange using CPRIO_ABSOLUTE\n");

 /* Change process priority to 7              */
   prty1 = 7;           

   rc = chpriority(kind, id, form, prty1);

   /* Test for Error */
   if (rc == -1)
   {
      perror("Call to chpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      prty2 = getpriority(kind, id);   

      /* Test for Error */
      if (errno != 0)
      {
         perror("Call to getpriority failed");
         exit(EXIT_FAILURE);
      }
  printf
("The process priority is now 
    (gpid): %d\n", prty2);
   }

/* change using "relative" priority */
   form = CPRIO_RELATIVE;
   printf("\tChange using CPRIO_RELATIVE\n");

/* Bump process priority up by 3            */
   prty1 = 3;            

   rc = chpriority(kind, id, form, prty1);

   /* Test for Error */
   if (rc == -1)
   {
      perror("Call to chpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      prty2 = getpriority(kind, id);   

      /* Test for Error */
      if (errno != 0)
      {
         perror("Call to getpriority failed");
         exit(EXIT_FAILURE);
      }
 printf("The process priority is now (gpid): 
   %d\n", prty2);
   }

/*--------------------------------------*/
/* Change the process priority using    */
/* the process User id                  */
/*--------------------------------------*/
printf
("\nChange the Process Priority 
   of the User ID\n");

/* the id arg is the user id of the process  */
   kind = PRIO_USER;     

/* 0 implies current group processs id       */
   id = (id_t)0;         

/* Reset errno to zero for error handling    */
   errno = 0;            

/* change using "absolute"                  */
/*  priority - equivalent to setpriority()  */
   form = CPRIO_ABSOLUTE;
   printf("\tChange using CPRIO_ABSOLUTE\n");

/* Change process priority to 11           */
   prty1 = 11;           

   rc = chpriority(kind, id, form, prty1);

   /* Test for Error */
   if (rc == -1)
   {
      perror("Call to chpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      prty2 = getpriority(kind, id);   

      /* Test for Error */
      if (errno != 0)
      {
       perror("Call to getpriority failed");
         exit(EXIT_FAILURE);
      }

printf("The process priority is now (uid):
   %d\n", prty2);
   }

/* change using "relative" priority */
   form = CPRIO_RELATIVE;
   printf("\tChange using CPRIO_RELATIVE\n");

/* Bump process priority up by 4            */
   prty1 = 4;            

   rc = chpriority(kind, id, form, prty1);

   /* Test for Error */
   if (rc == -1)
   {
      perror("Call to chpriority failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      prty2 = getpriority(kind, id);   

      /* Test for Error */
      if (errno != 0)
      {
      perror("Call to getpriority failed");
       exit(EXIT_FAILURE);
      }
      printf("The process priority is now (uid):
         %d\n", prty2);
   }

   exit(EXIT_SUCCESS);

}  /* end of main() */

RELATED FUNCTIONS
getpriority,  setpriority


 

endgrent

   Close the group database

SYNOPSIS
 #include <sys/types.h>
#include <grp.h>
void endgrent(void);

DESCRIPTION
The endgrent function closes the OpenEdition group database once the  getgrent function is complete. If  getgrent is called after a call to  endgrent, the database will be opened once again, and information about the first group returned.

 RETURN VALUE
endgrent has no return value.

 USAGE NOTES
The endgrent function can only be used with MVS 5.2.2 or a later release. 

If the endgrent function cannot be executed (for instance, because OpenEdition is not installed or running), it issues an MVS user  ABEND 1230 to indicate the error.

 RELATED FUNCTIONS
getgrent,  setgrent


 

endpwent

   Close the user database

SYNOPSIS
 #include <sys/types.h>
#include <pwd.h>
void endpwent(void);

DESCRIPTION
The endpwent function closes the OpenEdition user database once the  getpwent function is complete. If  getpwent is called after a call to  endpwent, the database will be opened once again, and information about the first user returned.

 RETURN VALUE
endpwent has no return value.

 USAGE NOTES
The endpwent function can only be used with MVS 5.2.2 or a later release. 

If the endpwent function cannot be executed (for instance, because OpenEdition is not installed or running), it issues an MVS user  ABEND 1230 to indicate the error.

 RELATED FUNCTIONS
getpwent,  setpwent


 

extlink

   Define an external link

SYNOPSIS
 #include <unistd.h>
int extlink(const char *ename,
            const char *lname);

DESCRIPTION
The extlink functions creates a link from the OpenEdition hierachical file system to an external (non-HFS) file. The argument  ename is the name of the external file, and  lname specifies the name of the link.  lname must specify the name of an HFS file. For programs not compiled with the
 posix
option, style prefixes may be required. The external name, ename, must not specify a style prefix. See "File Naming Conventions" in the SAS/C Library Reference, Volume 1, for further information. 

Note:   External links are not transparent, similar to other OpenEdition symbolic links. That is, opening or unlinking an external link will not open or delete the referenced external file. External links are used by IBM's NFS implementation and can be used by other applications, but are not handled automatically by either OpenEdition or the SAS/C library. The contents of an external link can be accessed using the readextlink function.  [cautend] 

Note:   An external link resembles a symbolic link, and that S_ISLNK(s->st_mode) will be true when  s is the value stored by the  lstat function for an external link. You can distinguish external links from other links using  S_ISEXTL(s->st_mode, s->st_genvalue), which will be non-zero only for an external link.  [cautend]

 RETURN VALUE
extlink returns  0 if successful, or  -1 if unsuccessful.

 RELATED FUNCTIONS
lstat,  readextlink


 

getgrent

   Access group database sequentially

SYNOPSIS
 #include <sys/types.h>
#include <grp.h>
struct group *getgrent(void);

DESCRIPTION
The getgrent function is used to read the system database that defines all OpenEdition groups. The first call to  getgrent returns the first defined group, and each successive call returns information about the next group in the database. After information about the last group is obtained,  getgrent returns  0 to indicate the end of file. When  0 is returned, the file position is reset, so that the next call to  getgrent will retrieve the first database entry. 

Note:   It is more efficient to use the getgrgid or  getgrnam function to obtain information about a specific group, rather than a loop calling  getgrent.  getgrent is provided mainly as an aid to porting existing UNIX programs that use it.   [cautend]

 RETURN VALUE
getgrent returns a pointer to a  struct group if successful, and the end of the group database has not been reached.  getgrent returns  0 if the end of the database has been reached, or if an error condition occurred. See the function description for  getgrgid in the "  posix Function Reference" section of the SAS/C Library Reference, Volume 2 for more information about the definition of  struct group. 

Note:   The pointer returned by getgrent may be a static data area that can be rewritten by the next call to  getgrent,  getgrgid or  getgrnam.  [cautend]

 USAGE NOTES
The getgrent function can only be used with MVS 5.2.2 or a later release.

 RELATED FUNCTIONS
endgrent,  getgrgid,  getgrnam,  setgrent


 

getitimer

   Obtain interval timer values

SYNOPSIS
 #include <sys/time.h>
int getitimer(int kind, 
              struct itimerval *val);

DESCRIPTION
The getitimer function returns information about an active interval timer. (See the  setitimer function in section setitimer for more information about interval timers.) 

The kind argument is a symbolic constant that specifies the type of time interval for which information is wanted. The permitted values are: 

 

The val argument is a pointer to an  itimerval structure in which information about the current interval timer should be stored. See the  setitimer function description for more information on the contents of a  struct itimerval.

 RETURN VALUE
getitimer returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The getitimer function can only be used with MVS 5.2.2 or a later release.

 RELATED FUNCTIONS
setitimer


 

getpgid

   Get Process Group Id for a Process

SYNOPSIS
 #include <sys/types.h>
#include <unistd.h>
pid_t getpgid(pid_t pid);

DESCRIPTION
The getpgid function returns the process group id for a specific process id. The argument  pid should be the id of the process, or  0 to request the process group id for the current process.

 RETURN VALUE
getpgid returns the process group id, or  -1 if it fails.

 USAGE NOTES
The getpgid function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
This example is compiled using sascc370 -Krent -o.
 /*------------------------------------+
| POSIX/UNIX header files             |
+-------------------------------------*/
#include <unistd.h>

#include <sys/types.h>

/*------------------------------------+
| ISO/ANSI header files               |
+-------------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <errno.h>
/*------------------------------------+
| Name:      main                     |
| Returns:   exit(EXIT_SUCCESS) or 
| exit(EXIT_FAILURE)                  |
+-------------------------------------*
int main()
{
/* current process id from getpid()     */
   pid_t pid;  
               
/* process group id from getpgid()      */
   pid_t pgid;                

/*------------------------------------------*/
/* Get the group process id of the current  */
/* process                                  */
/* Note: Both version 1 and version 2 are   */
/*       equivalent to calling the          */
/*.      getpgrp() function                 */
/*------------------------------------------*/
printf
  ("\nGet the Group Process ID of the 
    Current Process\n");

/* version 1                                 */
/* Set errno to zero for error handling      */
   errno = 0;            

/* get the process id for this process       */
   pid = getpid();       

/* get the group process id for this process  */
   pgid = getpgid(pid); 

/* Test for Error */
   if (pgid == -1)
   {
      perror("Call to getpgid failed");
      exit(EXIT_FAILURE);
   }
   else
   {
      printf
("      The process id: %d\n", (int)pid);
      printf("The process group id:%d\n", 
        (int)pgid);
   }
 
/* version 2                                 */
/* Reset errno to zero for error handling    */
   errno = 0;            

/* 0 implies current processs id             */
   pid = 0;              

/* get the group process id for this process  */
   pgid = getpgid(pid); 

/* Test for Error */
   if (pgid == -1)
   {
      perror("Call to getpgid failed");
      exit(EXIT_FAILURE);
   }
   else
   {
 printf
  ("The process group id: %d\n", (int)pgid);
   }

   exit(EXIT_SUCCESS);

}  /* end of main() */

RELATED FUNCTIONS
getpgrp,  setpgid


 

getpriority

   Determine process priority

SYNOPSIS
 #include <sys/resource.h>
int getpriority(int kind, int id);

DESCRIPTION
The getpriority function obtains the OpenEdition priority of a process, a process group or a user. The priority is an integer between -20 and 19 which is used in scheduling process execution. Lower priority numbers are considered more urgent. These priority numbers are translated by OpenEdition in a site-specific manner into MVS SRM (system resources manager) specifications that control the priority of both OpenEdition and non-OpenEdition MVS processing. See the IBM Publication OpenEdition MVS Planning (SC23-3015) for more information on OpenEdition priorities and their interpretation.  

The kind argument to  getpriority should be specified as a symbolic constant indicating what kind of priority information is needed. The permissible values are: 

 

The id argument specifies the process id, process group id, or user id whose priority is needed. If  id is  0, the calling process id, process group id, or user is indicated. 

If there is more than one process running that matches the arguments, for instance, multiple processes for a specified user, the smallest priority value for any process is returned.

RETURN VALUE
getpriority returns the requested priority if successful, or  -1 if unsuccessful. Since  -1 can also be returned as a priority value, you should set  errno to  0 before calling  getpriority, and test it for a non-zero value after the call to determine whether an error occurred.

 USAGE NOTES
The getpriority function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
Refer to chpriority for an example that demonstrates the use of the OpenEdition process priority functions chpriority,  getpriority, and  setpriority.

 RELATED FUNCTIONS
chpriority,  setpriority


 

getpwent

   Access user database sequentially

SYNOPSIS
 #include <sys/types.h>
#include <pwd.h>
struct passwd *getpwent(void);

DESCRIPTION
The getpwent function is used to read the system database defining all OpenEdition users. The first call to  getpwent returns the first defined user, and each successive call returns information about the next user in the database. After information about the last user is obtained,  getpwent returns  0 to indicate the end of file. When  0 is returned, the file position is reset, so that the next call to  getpwent will retrieve the first database entry. 

Note:   It is more efficient to use the getpwuid or  getpwnam function to obtain information about a specific user, rather than a loop calling  getpwent.  getpwent is provided mainly as an aid to porting existing UNIX programs that use it.   [cautend]

 RETURN VALUE
getpwent returns a pointer to a  struct passwd if successful, and the end of the user database has not been reached.  getpwent returns  0 if the end of the database has been reached, or if an error condition occurred. See the function description for  getpwuid in the "  posix Function Reference" section of the SAS/C Library Reference, Volume 2 for more information about the definition of  struct passwd. 

Note:   The pointer returned by getpwent may be a static data area that can be rewritten by the next call to  getpwent,  getpwuid or  getpwnam.  [cautend]

 USAGE NOTES
The getpwent function can only be used with MVS 5.2.2 or a later release.

 RELATED FUNCTIONS
endpwent,  getpwnam,  getpwuid,  setpwent


 

getrlimit

   Obtain OpenEdition resource limits

SYNOPSIS
 #include <sys/resource.h>
int getrlimit(int resource, 
              struct rlimit *info);

DESCRIPTION
The getrlimit function determines the resource limits for the calling process. The limits are expressed as a pair of integers, a soft limit and a hard limit. The soft limit controls the amount of the resource the program is actually allowed to consume, while the hard limit specifies an upper bound on the soft limit. The soft limit can be raised up to the hard limit value, but the hard limit can only be raised by a privileged (superuser) caller. 

The info argument is a pointer to a structure of type  struct rlimit, into which will be stored the defined limits. The structure contains the following fields: 

 

The resource argument defines the resource to which the limit applies. It should be specified as one of the symbolic values defined below. 

 RETURN VALUE
getrlimit returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The getrlimit function can only be used with MVS 5.2.2 or a later release. 

Note:   Resource limits are inherited from the parent process when fork or  exec is used.  [cautend]

 RELATED FUNCTIONS
setrlimit


 

getrusage

   Obtain OpenEdition usage statistics

SYNOPSIS
 #include <sys/resource.h>
int getrusage(int type, 
              struct rusage *info);

DESCRIPTION
The getrusage function returns resource usage information for the calling process, or for terminated child processes of the calling process. 

The type argument is a symbolic constant which specifies the processes for which resource information is wanted. The permissible values are: 

 

Note:   If RUSAGE_CHILDREN is specified, information is returned only for child processes for which the parent has waited.  [cautend] 

The info argument specifies a pointer to an  rusage structure in which resource usage information is to be stored. The  rusage structure contains two fields: 

  1. ru_utime - the user time consumed by the process(es)
  2.  ru_stime - the system time consumed by the process(es)
 

The ru_utime and  ru_stime fields both have type  struct timeval, which allows a time value to be specified to an accuracy of a microsecond. The structure has two fields: 

  1. tv_sec - the number of seconds used
  2.  tv_usec - the number of microseconds used

 RETURN VALUE
getrusage returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The getrusage function can only be used with MVS 5.2.2 or a later release


 

getsid

   Get session leader id for a process

SYNOPSIS
 #include <sys/types.h>
#include <unistd.h>
pid_t getsid(pid_t pid);

DESCRIPTION
The getsid function returns the process id for the session leader for a specific process. The argument  pid should be either the id of a specific process or  0 to request the id of the session leader for the current process.

 RETURN VALUE
getsid returns the session leader's process id, or  -1 if it fails.

 USAGE NOTES
The getsid function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
This example is compiled using sascc370 -Krent -o.
 /*--------------------------------------+
| POSIX/UNIX header files               |
+--------------------------------------*/
#include <sys/types.h>

#include <unistd.h>

/*--------------------------------------+
| ISO/ANSI header files                 |
+--------------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

/*--------------------------------------+
| Name:      main                       |
| Returns:   exit(EXIT_SUCCESS)         |
|            or exit(EXIT_FAILURE)      |
+ -------------------------------------*/
int main()
{
/* current process id from getpid()     */
   pid_t pid;                 
/* process group id from getsid()       */
   pid_t sid;                 

/*---------------------------------------*/
/* Get the Session Leader id for the     */
/* Current Process                       */
/*---------------------------------------*/
printf("\nGet the Session Leader ID 
    of the Current Process\n");

/* version 1 */
/* Set errno to zero for error handling    */
   errno = 0;           

/* get the process id for this process     */
   pid = getpid();      

/* get the session leader id for           */
/* this process                            */
   sid = getsid(pid);   

/* Test for Error */
   if (sid == -1)
   {
      perror("Call to getsid failed");
      exit(EXIT_FAILURE);
   }
   else
   {
printf
 ("       The process id: %d\n", (int)pid);
printf
 ("The Session Leader id: %d\n", (int)sid);
   }
 
/* version 2                               */
/* Reset errno to zero for error handling  */
   errno = 0;            

 /* 0 implies current processs id          */
   pid = 0;             

/* get the session leader id for           */
/* this process                            */
   sid = getsid(pid);   

/* Test for Error */
   if (sid == -1)
   {
      perror("Call to getsid failed");
      exit(EXIT_FAILURE);
   }
   else
   {
 printf("       The process id: %d\n", 
  (int)pid);
 printf("The Session Leader id: %d\n", 
  (int)sid);
   }
 
   exit(EXIT_SUCCESS);

}  /* end of main() */

RELATED FUNCTIONS
setsid


 

getwd

    Get working directory path name

SYNOPSIS
 #include <unistd.h>
char *getwd(char *buffer);

DESCRIPTION
getwd determines and stores the name of the working OpenEdition directory. The  buffer argument is an array where the path name is to be stored. It should address an area of at least  PATH_MAX+1 bytes. 

Note:   The PATH_MAX symbol is defined in the header file.  [cautend] 

When you call getwd in an application which was not compiled with the  posix option, the returned directory name will begin with an  hfs: style prefix.

 RETURN VALUE
If successful, getwd returns a pointer to the  buffer in which the directory path name was stored. If it fails, it returns  NULL.

 USAGE NOTES
The getwd function can only be used with MVS 5.2.2 or a later release.  

Note:   Use of the more portable and standard getcwd function is recommended in place of  getwd.  [cautend]

 RELATED FUNCTIONS
getcwd


 

lchown

    Change file or link ownership

SYNOPSIS
 #include <unistd.h>
int lchown(const char *pathname,
           uid_t owner, gid_t group);

DESCRIPTION
lchown changes the owner or owning group of an HFS file or symbolic link. It can be used with either regular files or special files such as directories, FIFO files or links.  pathname is the name of the file or link,  owner is the new owning user id, and  group is the new group id. If either  owner or  group is specified as -1, the owner or group of the file or link is unchanged. 

For programs not compiled with the posix option, a style prefix may be required as part of the  pathname specification. See "File Naming Conventions" in the SAS/C Library Reference, Volume 1, for further information. 

Note:   For information when OpenEdition permits file ownership to be changed, see the chown function in the SAS/C Library Reference, Volume 2.  [cautend]

 RETURN VALUE
lchown returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The lchown function can only be used with MVS 5.2.2 or a later release.

 RELATED FUNCTIONS
chown,  fchown


 

mmap

   Map an HFS file into memory

SYNOPSIS
 #include <mman.h>
void *mmap(void *addr, size_t len, 
           int prot, int flags, 
           int fd, off_t offset);

DESCRIPTION
The mmap function is used to request memory mapping of all or part of an HFS file. Memory mapping allocates a block of memory so that fetching from the memory block will obtain the corresponding bytes of the file. Depending on the  mmap flags, memory mapping is capable of changing the corresponding bytes of the file when data is stored in the memory block.  

The addr argument may be either  0 or a memory address. If  addr is  0, the system will map the file anywhere in memory it chooses. If  addr is not  0, the system will attempt to allocate the memory for the file mapping near the address specified.  

The len argument specifies the number of bytes of the file that are to be mapped. The length must not cause the map to extend beyond the end of the file. If the length does not specify an integral number of pages, the map is extended to the next highest page boundary, and the additional space is set to binary zeroes.  

The prot argument specifies the protection status of the mapped memory. It should be specified as one of the symbolic constants: 

 

You cannot specify PROT_WRITE if the file descriptor for the file does not permit writing.  

Note:   The protection status of the mapped memory can be changed later by a call to the mprotect function.  [cautend] 

The flags argument specifies one or more option flags, combined using the or operator (|). Each flag should be specified as one of the following symbolic constants:  

 

The fd argument specifies an open file descriptor for the file to be mapped, which must be a regular HFS file.  

The offset argument specifies the first byte of the file to be mapped. The offset must be an exact multiple of the system page size (4096 bytes). 

Note:   See the IBM OpenEdition Assembler Callable Services manual for additional information about the behavior of mmap and the conditions under which it can be used.  [cautend]

 RETURN VALUE
mmap returns the address of the start of the mapped memory if successful, or  0 if unsuccessful.

 USAGE NOTES
The mmap function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
This example is compiled using sascc370 -Krent -o . The program uses the memory map functions,  mmap(),  mprotect(),  msync(), and  munmap(), to copy a file similar to the unix  cp command. 

 /*--------------------------------------+
| POSIX/UNIX header files               |
+---------------------------------------*/
#include <unistd.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/mman.h>

/*--------------------------------------+
| ISO/ANSI header files                 |
+--------------------------------------*/
#include <stdlib.h>

#include <stdio.h>

/*--------------------------------------+
| Types                                 |
+--------------------------------------*/

/*--------------------------------------+
| Constants                             |
+--------------------------------------*/
#define F_MODE 
 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

/*--------------------------------------+
| Name:      main                       |
| Returns:   exit(EXIT_SUCCESS) or      *
|            exit(EXIT_FAILURE)         |
+--------------------------------------*/
int main( int argc, char **argv )
{
/* file descripter for the src file    */
    int fdSrc;                 

/* file descripter for the dest file   */
    int fdDest;  
              
/* memory addr of the mapped src file  */
    char *src;                 

/* memory addr of the mapped dest file */
    char *dest;                

/* Buffer for fstat() info             */
    struct stat statBuffer;    

/*--------------------------------------*/
/* test args to main                    */
/*--------------------------------------*/
   if ( argc != 3 )
   {
      fprintf(stderr, "Usage: mmcp  \n");
      exit(EXIT_FAILURE);
   }

/*-----------------------------------*/
/* open the source file for read     */
/*-----------------------------------*/
   if ( (fdSrc = open(argv[1], O_RDONLY)) < 0 )
   {
    fprintf(stderr,
     "ERROR: Cannot open source file <%s>\n", 
        argv[1]);
       exit(EXIT_FAILURE);
   }

/*------------------------------------*/
/* open/create new file for output    */
/*------------------------------------*/
if ( (fdDest = 
open(argv[2], O_RDWR | O_CREAT 
 | O_TRUNC, F_MODE)) < 0)
   {
 fprintf(stderr,
  "ERROR: 
   Cannot create dest file <%s>\n", argv[1]);
    exit(EXIT_FAILURE);
   }
 
/*--------------------------------------*/
/* retrieve size of source file from    */
/* fstat() function                     */
/*--------------------------------------*/
   if ( fstat(fdSrc, &statBuffer) < 0 )
   {
   fprintf(stderr,
   "ERROR: 
   Cannot fstat source file <%s>\n", argv[1]);
   exit(EXIT_FAILURE);
   }

/*---------------------------------------------*/
/* set the size of the dest file.             */ 
/* If we don't we'll get an                    */
/* SIGSEGV when we try to copy to its mmap.    */
/*---------------------------------------------*/
 if ( ftruncate( fdDest, 
  (off_t)statBuffer.st_size ) < 0 )
   {
   fprintf(stderr,
   "ERROR: 
   Cannot set size of the dest file <%s>\n", 
   argv[2]);
   exit(EXIT_FAILURE);
   }

/*----------------------------------------------*/
/* map the source file to memory                */
/* (for read only)                              */
/*----------------------------------------------*/
if ( (src = mmap(0, 
     statBuffer.st_size, PROT_READ, MAP_SHARED,
        fdSrc, 0)) == (char *)-1)
   {
   fprintf(stderr,
   "ERROR: Cannot memory map source file <%s>\n", 
   argv[1]);
   exit(EXIT_FAILURE);
   }
   else
   {
   printf
   ("NOTE: source file <%s> mapped 
   at address <%p>\n", argv[1], src);
   }

/*----------------------------------------------*/
/* map the dest file to memory                  */
/* (for read only)                              */
/*----------------------------------------------*/
 if ( (dest = mmap
  (0, statBuffer.st_size, PROT_READ,
          MAP_SHARED, fdDest, 0)) == (char *)-1)
   {
   fprintf(stderr,
   "ERROR: 
   Cannot memory map dest file <%s>\n", argv[2]);
   exit(EXIT_FAILURE);
   }
   else
   {
   printf("NOTE: 
   dest file <%s> mapped at address <%p>\n",
   argv[2], dest);
   }

/*-----------------------------------------------*/
/* chg the protection of memory map of           */
/* the dest file to write                        */
/*-----------------------------------------------*/
if ( (mprotect(dest, 
  statBuffer.st_size, PROT_WRITE)) == -1)
   {
   fprintf(stderr,
   "ERROR: 
   Cannot change memory map protect of 
   dest file <%s>\n", argv[2]);
   exit(EXIT_FAILURE);
   }

/*------------------------------------------*/
/* copy src to dest in memory               */
/*------------------------------------------*/
   memcpy(dest, src, statBuffer.st_size);

/*-------------------------------------------*/
/* synchronize the memory mapped dest file.  */
/*-------------------------------------------*/
 if ( (msync
  (dest, statBuffer.st_size, MS_SYNC)) == -1)
   {
   fprintf(stderr,
   "ERROR: 
   Cannot synchronize memory map of 
   dest file <%s>\n", argv[2]);
   exit(EXIT_FAILURE);
   }

/*--------------------------------------------*/
/* cancel mapping of memory to the src file.  */
/*--------------------------------------------*/
   if ( (munmap(src, statBuffer.st_size)) == -1)
   {
   fprintf(stderr,
   "ERROR: 
   Cannot terminate memory map of 
   src file <%s>\n", argv[2]);
   exit(EXIT_FAILURE);
   }

/*--------------------------------------------*/
/* cancel mapping of memory to the dest file. */
/*--------------------------------------------*/
   if ( (munmap(dest, statBuffer.st_size)) == -1)
   {
   fprintf(stderr,
   "ERROR: 
   Cannot terminate memory map of 
   dest file <%s>\n", argv[2]);
   exit(EXIT_FAILURE);
   }

   exit(EXIT_SUCCESS);

}  /* end of main() */

/* end of mmcp.c */

RELATED FUNCTIONS
mprotect,  msync,  munmap


 

mprotect

   Change protection of memory mapped to a file

SYNOPSIS
 #include <mman.h>
int mprotect(void *addr, 
             unsigned int len, 
             int prot);

DESCRIPTION
The mprotect function is used to change the protection status of one or more pages of memory mapped to an HFS file by a previous call to the  mmap function.  

The addr argument is the address of the first page of mapped memory for which the protection attributes are to be changed. The address must be on a page boundary, but need not be the first byte of the entire area mapped to a file.  

The len argument specifies the number of bytes of memory whose protection attributes are to be changed. If the length does not specify an integral number of pages, it is rounded up to do so. The length need not specify the entire area of mapped memory.  

The prot argument specifies the new protection status of the mapped memory. It should be specified as one of the symbolic constants described in the  mmap function write-up.  

You cannot specify PROT_WRITE if the file descriptor for the file does not permit writing.  

Note:   See the IBM OpenEdition Assembler Callable Services manual for additional information about the behavior of mprotect and the conditions under which it can be used.  [cautend]

 RETURN VALUE
mprotect returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The mprotect function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
Refer to mmap for an example.

RELATED FUNCTIONS
mmap,  msync,  munmap


 

msgctl

   Control a message queue

SYNOPSIS
 #include <sys/msg.h>
int msgctl(int id, int cmd,
           struct msgid_ds *buf);

DESCRIPTION
The msgctl function is used to perform one of several control operations on an OpenEdition message queue.  

Note:   See the msgget function description in section msgget for general information about message queues.   [cautend] 

The id argument to  msgctl specifies a message queue id. This argument is an id, such as the id returned by  msgget, not a message queue key, which might be passed as an argument to  msgget. 

The cmd argument should be specified as a symbolic constant specifying the particular operation to be performed by  msgctl. The constant values are described below.  

Several of the msgctl operations allow you to obtain or access the message queue id data structure, which is mapped by the  struct msqid_ds type defined in  sys/msg.h. This data structure is defined as follows: 

 struct msqid_ds {
   /* permission information */
   struct ipc_perm msg_perm;

   /* messages presently on the queue */
   unsigned msg_qnum;

   /* max bytes of queued info */
   unsigned msg_qbytes;

   /* process id of last sender */
   pid_t msg_lspid;

   /* process id of last receiver */
   pid_t msg_lrpid;

   /* time of last msgsnd call */
   time_t msg_stime;

   /* time of last msg(x)rcv call */
   time_t msg_rtime;

   /* time of last change by msgget/msgctl */
   time_t msg_ctime;
};

The ipc_perm structure, which contains security information about the owner and the creator of the message queue, is defined as follows:  

 struct ipc_perm {
   /* owner's effective user ID */
   uid_t uid;

   /* owner's effective group ID */
   gid_t gid;

   /* creator's effective user ID */
   uid_t cuid;

   /* creator's effective group ID */
   gid_t cgid;

   /* read/write permission bits */
   mode_t mode;
};

For msgctl operations which access or modify the message queue data structure, the  buf argument addresses a  struct msqid_ds, used as described below. For other operations, the  buf argument is ignored. 

The cmd values accepted by  msgctl and their meanings are as follows: 

 RETURN VALUE
msgctl returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The msgctl function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE 1
This example is compiled using sascc370 -Krent -o. This program uses the functions  msgget(),  msgsnd(),  msgrcv(), and  msgctl() to establish an IPC Server using Message Queues.
 /*-------------------------+
| POSIX/UNIX header files  |
+-------------------------*/
#include <sys/types.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/ipc.h>

#include <sys/msg.h>

/*-------------------------+
| ISO/ANSI header files    |
+-------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <errno.h>

/*---------------------------+
| Constants                  |
+---------------------------*/
/* maximum message size           */
#define MAX_MSGSIZE          256    

/* message key, set by server     */
#define MSG_KEY      (key_t)1097    

/* Server's message type          */
#define SERVER_MSG_TYPE (long)10    

/* Client's message type          */
#define CLIENT_MSG_TYPE (long)20    

/* give everyone read/write        */
/* permission to messages          */
#define MSG_PERM  (S_IRUSR|S_IWUSR
|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

/*----------------------------------+
| Types                             |
+-----------------------------------*/
/* Declare the message structure.   */
typedef struct Message              
{
    /* positive message type        */
    long    type;                   
    /* message data                 */
    char    text[MAX_MSGSIZE];      
}Message;

/*----------------------------------+
| Name:      main                   |
| Returns:   exit(EXIT_SUCCESS) or  |
|            exit(EXIT_FAILURE)     |
+----------------------------------*/
int main()
{
/* message queue id                 */
    int msgQID;          

/* message flags                     */
    int msgFlags;         

/* message type                      */
    long msgType;         

/* message key                       */
    key_t msgKey;         

/* message to send                   */
    Message sendMsg;      

/* message received                  */
    Message recvMsg;      

/*------------------------------------*/
/* Create message queue.              */
/* Give everyone read/write           */
/* permissions.                       */
/*------------------------------------*/
   msgKey = MSG_KEY;
   msgFlags = IPC_CREAT | MSG_PERM;

   if ( (msgQID = msgget(msgKey, msgFlags)) < 0 )
   {
       perror("SERVER: msgget");
       exit(EXIT_FAILURE);
   }

/*---------------------------------------*/
/* Receive a message from client.        */
/*---------------------------------------*/
   msgType = CLIENT_MSG_TYPE;
   msgFlags = 0;

   if (msgrcv(msgQID, &recMsg, MAX_MSGSIZE, 
       msgType, msgFlags) < 0)
   {
       perror("SERVER: msgrcv");
       msgctl(msgQID, IPC_RMID, NULL);
       exit(EXIT_FAILURE);
   }

/*-----------------------------------------*/
/* Print message received from client.     */
/*-----------------------------------------*/
   printf("%s\n", recvMsg.text);

/*------------------------------------------*/
/* Send ACK Message to client.              */
/*------------------------------------------*/
sendMsg.type = SERVER_MSG_TYPE;
sprintf(sendMsg.text, 
        "From SERVER: Message received!");
msgFlags = 0;

   if (msgsnd(msgQID, &sendMsg, 
   strlen(sendMsg.text)+1, msgFlags) < 0)
   {
       perror("SERVER: msgsnd");
       msgctl(msgQID, IPC_RMID, NULL);
       exit(EXIT_FAILURE);
   }

/*--------------------------------------------*/
/* Go to sleep to allow time for the client   */
/* to recieve the message                     */
/* before removing the message queue.         */
/*--------------------------------------------*/
   sleep(60);

/*--------------------------------------------*/
/* Call msgctl to remove message queue.       */
/*--------------------------------------------*/
   if (msgctl(msgQID, IPC_RMID, NULL) < 0)
   {
       perror("SERVER: msgctl");
       exit(EXIT_FAILURE);
   }
 
   exit(EXIT_SUCCESS);

}  
/* end of main() */

EXAMPLE 2
This example is compiled using sascc370 -Krent -o.  

This program usese the functions msgctl(),  msgget(),  msgsnd(), and  msgxrcv to establish IPC Client using XMessage Queues. Also, it uses Open Edition's extended Message structure.  

Note:   You cannot use the Extended Message structure to send a message, i.e., call msgsnd() with this structure. Attempting to do so will cause the program to "hang".  [cautend]

 /*--------------------------------------------+
| POSIX/UNIX header files                     |
+--------------------------------------------*/
#include <sys/types.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/ipc.h>

#include <sys/msg.h>

/*--------------------------------------------+
| ISO/ANSI header files                       |
+--------------------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <time.h>

#include <errno.h>

/*--------------------------------------------+
| Constants                                   |
+--------------------------------------------*/
 /* maximum message size                      */
#define MAX_MSGSIZE          256   

/* message key, set by server                 */
#define MSG_KEY      (key_t)1097    

/* Server's message type                      */
#define SERVER_MSG_TYPE (long)10    

/* Client's message type                      */
#define CLIENT_MSG_TYPE (long)20    


/* give everyone read/write                   */
/* permission to messages                     */
#define MSG_PERM  
(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

/*---------------------------------------------+
| Types                                        |
+---------------------------------------------*/
/* Declare the message structure. */
typedef struct Message              
{
/* positive message type          */
    long    type;                   
/* message data                   */
    char    text[MAX_MSGSIZE];      
}Message;

/* Declare the message structure. */
typedef struct XMessage              
{
/* time msg sent                  */
    time_t  time;                   

/* effective uid of sender        */
    uid_t   uid;                    

/* effective gid of sender        */
    gid_t   gid;                    

/* process id of sender           */
    pid_t   pid;                    

/* positive message type          */
    long    type;                   

/* message data                   */
    char    text[MAX_MSGSIZE];      
}XMessage;

/*-------------------------------------------+
| Name:      main                            |
| Returns:   exit(EXIT_SUCCESS) or           |
|            exit(EXIT_FAILURE)              |
+-------------------------------------------*/
int main()
{
/* message queue id                         */
    int msgQID;           

/* message flags                            */
    int msgFlags;         

/* command to message queue, used w/ msgctl *
    int msgQcmd;          /

/* message type                             */
    long msgType;         

/* message key                              */
    key_t msgKey;         

/* message to send                          */
    Message sendMsg;      

/* message received - eXtended              */
    XMessage recvMsg;     

/*------------------------------------------*/
/* Create message queue.                    */
/* Give everyone read/write permissions.    */
/*------------------------------------------*/
   msgKey = MSG_KEY;
   msgFlags = IPC_CREAT | MSG_PERM;

 if ( (msgQID = msgget(msgKey, msgFlags)) < 0 )
   {
       perror("SERVER: msgget");
       exit(EXIT_FAILURE);
   }

/*---------------------------------------------*/
/* Receive a message from client.              */
/*---------------------------------------------*/
   msgType = CLIENT_MSG_TYPE;
   msgFlags = 0;

   if (msgxrcv(msgQID, &recMsg, MAX_MSGSIZE, 
         msgType, msgFlags) < 0)
   {
       perror("SERVER: msgrcv");
       msgctl(msgQID, IPC_RMID, NULL);
       exit(EXIT_FAILURE);
   }

/*---------------------------------------------*/
/* Print message received from client.         */
/*---------------------------------------------*/
   printf("Message: %s\n", recvMsg.text);
   printf("   Time message was sent: %s\n", 
     ctime(&recvMsg.time));
   printf("   The user id of sender: %d\n", 
     (int)recvMsg.uid);
   printf("  The group id of sender: %d\n", 
     (int)recvMsg.gid);
   printf("The process id of sender: %d\n", 
     (int)recvMsg.pid);

   /*-------------------------------------------*/
   /* Send ACK XMessage to client.              */
   /*-------------------------------------------*/
   sendMsg.type = SERVER_MSG_TYPE;
   sprintf(
    sendMsg.text, 
     "From SERVER: XMessage received!");
   msgFlags = 0;

   if (msgsnd(msgQID, &sendMsg, 
      strlen(sendMsg.text)+1, msgFlags) < 0)
   {
       perror("SERVER: msgsnd");
       msgctl(msgQID, IPC_RMID, NULL);
       exit(EXIT_FAILURE);
   }

/*----------------------------------------------*/
/* Go to sleep to allow time for the client to  */
/* recieve the message                          */
/* before removing the message queue.           */
   /*-------------------------------------------*/
   sleep(60);

/*----------------------------------------------*/
/* Call msgctl to remove message queue.         */
/*----------------------------------------------*/
   if (msgctl(msgQID, IPC_RMID, NULL) < 0)
   {
   perror("SERVER: msgctl");
   exit(EXIT_FAILURE);
   }
 
   exit(EXIT_SUCCESS);

}  /* end of main() */

RELATED FUNCTIONS
msgget,  msgrcv,  msgsnd,  msgxrcv


 

msgget

    Create or find a message queue

SYNOPSIS
 #include <sys/msg.h>

int msgget(key_t key, int flags);

DESCRIPTION
The msgget function is used either to create a new message queue or to locate an existing queue based on a key. Message queues are implemented by OpenEdition, and allow messages of multiple types to be queued. OpenEdition message queues support multiple senders and multiple receivers and do not require the senders and receivers to be running simultaneously. Message queues, once created using  msgget, remain in existence until they are explicitly destroyed with a call to  msgctl.  

The key argument is an integral value which identifies the message queue desired. A  key value of  IPC_PRIVATE requests a new message queue without an associated  key, and which can be accessed only by the queue id returned by  msgget.  

The flags argument specifies zero or more option flags specifying whether or not the queue already exists, and how access to the queue should be regulated. The argument should be specified as  0 for no flags, or as one or more of the following symbolic constants, combined using the or operator (|):  

 

Additionally, any of the permission bits S_IRUSR,  S_IWUSR,  S_IRGRP,  S_IWGRP,  S_IROTH and  S_IWOTH may be specified as part of the  flags argument, to regulate what users are permitted to access or modify the message queue. See the  umask function description in the SAS/C Library Reference, Volume 2, for more information about the meaning of these flags.

 RETURN VALUE
msgget returns the identifier of the message queue if successful, or  -1 if unsuccessful.

 USAGE NOTES
The msgget function can only be used with MVS 5.2.2 or a later release. 

Note:   A site can impose limits on the number and size of queued messages.  [cautend]

EXAMPLE 1
This example is compiled using sascc370 -Krent -o. This program uses the functions  msgget(),  msgsnd(), and  msgrcv() to establish IPC Client using Message Queues.
 /*------------------------------------------+
| POSIX/UNIX header files                   |
+-------------------------------------------*/
#include <fcntl.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

/*------------------------------------------+
| ISO/ANSI header files                     |
+------------------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <errno.h>

/*------------------------------------------+
| Constants                                 |
+------------------------------------------*/
/* maximum message size           */
#define MAX_MSGSIZE          256    

/* message key, set by server     */
#define MSG_KEY      (key_t)1097    

/* Server's message type          */
#define SERVER_MSG_TYPE (long)10    

/* Client's message type          */
#define CLIENT_MSG_TYPE (long)20    

/* give everyone read/write       */
/* permission to messages         */
#define MSG_PERM  (S_IRUSR|S_IWUSR|S_IRGRP
  |S_IWGRP|S_IROTH|S_IWOTH)

/*---------------------------------+
| Types                            |
+---------------------------------*/
/* Declare the message structure. */
typedef struct Message              
{
/* positive message type          */
    long    type;                   
/* message data                   */
    char    text[MAX_MSGSIZE];      
}Message;

/*---------------------------------+
| Name:      main                  |
| Returns:   exit(EXIT_SUCCESS) or |
|            exit(EXIT_FAILURE)    |
+---------------------------------*/
int main()
{
/* message queue id                         */
    int msgQID;           

/* message flags                            */
    int msgFlags;         

/* message type                             */
    long msgType;         

/* message key                              */
    key_t msgKey;         

/* message to send                          */
    Message sendMsg;      

/* message received                         */
    Message recvMsg;      

/*------------------------------------------*/
/* Get the message queue id for MSG_KEY,    */
/* which was set by the                     */
/* message server.                          */
/*------------------------------------------*/
   msgKey = MSG_KEY;
   msgFlags = MSG_PERM;

   if ( (msgQID = msgget(msgKey, msgFlags)) < 0 )
   {
       perror("CLIENT: msgget");
       exit(EXIT_FAILURE);
   }

/*-------------------------------------------*/
/* Send the message.                         */
/*-------------------------------------------*/
   sendMsg.type = CLIENT_MSG_TYPE;
   sprintf
    (sendMsg.text, "From CLIENT: Are you there?");
   msgFlags = 0;

   if (msgsnd(msgQID, &sendMsg, 
     strlen(sendMsg.text)+1, msgFlags) < 0)
   {
   perror("CLIENT: msgsnd");
   exit(EXIT_FAILURE);
   }

/*-----------------------------------------*/
/* Receive a message from server.          */
/*-----------------------------------------*/
   msgType = SERVER_MSG_TYPE;
   msgFlags = 0;

   if (msgrcv(msgQID, &recMsg, MAX_MSGSIZE, 
     msgType, msgFlags) < 0)
   {
   perror("CLIENT: msgrcv");
   exit(EXIT_FAILURE);
   }

/*-------------------------------------------*/
/* Print message received from server.       */
/*-------------------------------------------*/
   printf("%s\n", recvMsg.text);
 
   exit(EXIT_SUCCESS);

}  /* end of main() */

EXAMPLE 2
Refer to msgctl for an example program that establishes an IPC Server using Message Queues.

EXAMPLE 3
This example is compiled using sascc370 -Krent -o. This program uses the  msgget() function to create IPC message queue and then uses the  msgctl() function to retrieve statistics on the newly created message queue.
 /*-------------------------------------------+
| POSIX/UNIX header files                    |
+-------------------------------------------*/
#include <sys/types.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/ipc.h>

#include <sys/msg.h>
 
/*-------------------------------------------+
| ISO/ANSI header files                      |
+-------------------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <time.h>

#include <errno.h>

/*-------------------------------------------+
| Types                                      |
+-------------------------------------------*/
/* message queue id structure     */
typedef struct msqid_ds MsgQueueID; 

/*--------------------------------------------+
| Constants                                   |
+--------------------------------------------*/
/* message key                    */
#define MSG_KEY      (key_t)1097    

/* give everyone read/write permission to     */
/*messages                                    */
#define MSG_PERM (S_IRUSR|S_IWUSR|S_IRGRP
  |S_IWGRP|S_IROTH|S_IWOTH)

/*---------------------------------------------+
| Name:      main                              |
| Returns:   exit(EXIT_SUCCESS) or             |
|            exit(EXIT_FAILURE)                |
+---------------------------------------------*/
int main()
{
/* message queue id                   */
    int msgQID;                 

/* message flags                      */
    int msgFlags;               

/* command to message queue.          */
    int msgQcmd;                

/* message key                        */
    key_t msgKey;               

/* message queue id data structure    */
    MsgQueueID * msgQueue;      

/*---------------------------------------------*/
/* Create message queue.                       */
/* Give everyone read/write permissions.       */
/*---------------------------------------------*/
   msgKey = MSG_KEY;
   msgFlags = IPC_CREAT | MSG_PERM;

   if ( (msgQID = msgget(msgKey, msgFlags)) < 0 )
   {
       perror("MSGSTAT: msgget");
       exit(EXIT_FAILURE);
   }

/*-----------------------------------------------*/
/* Allocate memory to store information from     */
/* message queue                                 */
/*-----------------------------------------------*/
   msgQueue = malloc(sizeof(MsgQueueID));

   if (msgQueue == NULL)
   {
   fprintf(stderr,
   "ERROR: 
   Cannot allocate memory for message queue
   stats\n");
   exit(EXIT_FAILURE);
   }

/*-----------------------------------------------*/
/* Call msgctl to retrieve information from      */
/* message queue                                 */
   /*--------------------------------------------*/
   msgQcmd = IPC_STAT;

   if (msgctl(msgQID, msgQcmd, msgQueue) < 0)
   {
   perror
   ("MSGSTAT: msgctl failed to retrieve 
   message queue stats");
   free(msgQueue);
   exit(EXIT_FAILURE);
   }
 
/*-----------------------------------------------*/
/* Print infomation retrieved from message queue */
/*-----------------------------------------------*/
   printf("Message Queue ID statistics:\n\n");
   printf("\tQueue owner's effective user ID: 
     %d\n",(int)msgQueue->msg_perm.uid);
   printf("\tQueue owner's effective group ID: 
     %d\n",(int)msgQueue->msg_perm.gid);
   printf("\tQueue creator's effective user ID: 
     %d\n",(int)msgQueue->msg_perm.cuid);
   printf("\tQueue creator's effective group ID: 
     %d\n",(int)msgQueue->msg_perm.cgid);
   printf("\tQueue permission mode bits: 
     %#.3o\n\n",(int)msgQueue->msg_perm.mode);
   printf("\tNumber of messages currently on Queue: 
     %d\n",msgQueue->msg_qnum);
   printf("\tMaximum bytes of queued info: 
     %d\n", msgQueue->msg_qbytes);
   printf("\tProcess id of last sender: 
     %d\n", (int)msgQueue->msg_lspid);
   printf("\tProcess id of last receiver: 
     %d\n", (int)msgQueue->msg_lrpid);
   printf("\tTime of last msgsnd call: 
     %s",ctime(&msgQueue->msg_stime));
   printf("\tTime of last msg(x)rcv call: 
     %s",ctime(&msgQueue->msg_rtime));
   printf("\tTime of last chg by msgget/msgctl: 
     %s",ctime(&msgQueue->msg_ctime));

/*-------------------------------------------------*/
/* Free memory used to store information from      */
/* message queue                                   */
/*-------------------------------------------------*/
   free(msgQueue);

/*--------------------------------------------------*/
/* Call msgctl to remove message queue.             */
/*--------------------------------------------------*/
   msgQcmd = IPC_RMID;

  if (msgctl(msgQID, msgQcmd, NULL) < 0)
  {
  perror
  ("MSGSTAT: msgctl failed to remove message queue");
  exit(EXIT_FAILURE);
   }
 
   exit(EXIT_SUCCESS);

}  /* end of main() */

EXAMPLE 4
This example is compiled using sascc370 -Krent -o. 

This program uses the functions msgget(),  msgsnd(), and  msgxrcv() to establish IPC Client using XMessage Queues. Also, it uses Open Edition's extended Message structure. 

Note:   You cannot use the Extended Message structure to send a message, i.e., call msgsnd() with this structure. Attempting to do so will cause the program to "hang".   [cautend]

 /*---------------------------------+
| POSIX/UNIX header files          |
+---------------------------------*/
#include <fcntl.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

/*---------------------------------+
| ISO/ANSI header files            |
+----------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <time.h>

#include <errno.h>

/*---------------------------------+
| Constants                        |
+---------------------------------*/
/* maximum message size           */
#define MAX_MSGSIZE          256    

/* message key, set by server     */
#define MSG_KEY      (key_t)1097    

/* Server's message type          */
#define SERVER_MSG_TYPE (long)10    

/* Client's message type          */
#define CLIENT_MSG_TYPE (long)20    

/* give everyone read/write       */
/* permission to messages         */
#define MSG_PERM  
 (S_IRUSR|S_IWUSR|S_IRGRP
  |S_IWGRP|S_IROTH|S_IWOTH)

/*-----------------------------------+
| Types                              |
+-----------------------------------*/
/* Declare the message structure. */
typedef struct Message              
{
/* positive message type          */
    long    type;                   
/* message data                   */
    char    text[MAX_MSGSIZE];      
}Message;

/* Declare the OE Extended message structure. */
typedef struct XMessage 
{
/* time msg sent                  */
    time_t  time;                   

/* effective uid of sender        */
    uid_t   uid;                    

/* effective gid of sender        */
    gid_t   gid;                    

/* process id of sender           */
    pid_t   pid;                    

/* positive message type          */
    long    type;                   

/* message data                   */
    char    text[MAX_MSGSIZE];      
}XMessage;

/*----------------------------------+
| Name:      main                   |
| Returns:   exit(EXIT_SUCCESS) or  |
|            exit(EXIT_FAILURE)     |
+----------------------------------*/
int main()
{
/* message queue id                         */
    int msgQID;           

/* message flags                            */
    int msgFlags;         

/* message type                             */
    long msgType;         

/* message key                              */
    key_t msgKey;         

/* message to send                          */
    Message sendMsg;      

/* message received - eXtended              */
    XMessage recvMsg;     

/*-------------------------------------------*/
/* Get the message queue id for MSG_KEY,     */
/* which was set by the                      */
/* message server.                           */
/*-------------------------------------------*/
   msgKey = MSG_KEY;
   msgFlags = MSG_PERM;

   if ( (msgQID = msgget(msgKey, msgFlags)) < 0 )
   {
       perror("CLIENT: msgget");
       exit(EXIT_FAILURE);
   }

/*----------------------------------------------*/
/* Send the message.                            */
/*----------------------------------------------*/
sendMsg.type = CLIENT_MSG_TYPE;
sprintf
  (sendMsg.text, "From CLIENT: Are you there?");
  msgFlags = 0;

if (msgsnd(msgQID, &sendMsg, 
   strlen(sendMsg.text)+1, msgFlags) < 0)
   {
       perror("CLIENT: msgsnd");
       exit(EXIT_FAILURE);
   }

/*------------------------------------------*/
/* Receive a message from server.           */
/*------------------------------------------*/
   msgType = SERVER_MSG_TYPE;
   msgFlags = 0;

  if (msgxrcv(msgQID, 
   &recMsg, MAX_MSGSIZE, msgType, msgFlags) < 0)
   {
       perror("CLIENT: msgrcv");
       exit(EXIT_FAILURE);
   }

/*------------------------------------------*/
/* Print message received from server.      */
/*------------------------------------------*/
   printf("Message: %s\n", recvMsg.text);
   printf("   Time message was sent: %s\n", 
     ctime(&recMsg.time));
   printf("   The user id of sender: %d\n", 
    (int)recvMsg.uid);
   printf("  The group id of sender: %d\n", 
    (int)recvMsg.gid);
   printf("The process id of sender: %d\n", 
    (int)recvMsg.pid);
 
   exit(EXIT_SUCCESS);

}  /* end of main() */

EXAMPLE 5
Refer to msgctl for an example that establishes an IPC Server using Message Queues. Also, it uses Open Edition's extended Message structure.

RELATED FUNCTIONS
msgctl,  msgrcv,  msgsnd,  msgxrcv


 

msgrcv

   Receive a message from a message queue

SYNOPSIS
 #include <sys/msg.h>
int msgrcv(int id, void *msg, size_t size, 
           long msgtype,int flags);

DESCRIPTION
The msgrcv function is used to receive a message from an OpenEdition message queue. The  msgtype argument allows the caller to select the type of message to be received.  

Note:   See the msgget function description in section msgget for general information about OpenEdition message queues.  [cautend] 

The id argument to  msgrcv specifies the id of the message queue from which messages will be received. This argument is an id, such as the id returned by  msgget, not a message queue key, which might be passed as an argument to  msgget. 

The msg argument should be a pointer to a message buffer into which the received message should be stored. The message buffer should have the following layout: 

 struct {
   long mtype;     /* message type */
   char mtext[n];  /* message text */
};

where n is an integer constant large enough for the message text.  

Note:   You must declare an appropriate type for the messages you receive yourself, as no such type is defined by sys/msg.h. Also the meaning of  mtype is not fixed by the message queue protocol, but can be used by the application to establish message types or priorities in any natural way.  [cautend] 

The size argument to  msgrcv should be the maximum number of bytes of message text to be received.  size should not include the size of the  mtype field. If the size of the message text to be received is larger than the  size argument, the result depends upon the options specified by the  flags argument.  

The msgtype argument specifies which message, if any, is received. The argument is interpreted as follows: 

 

The flags argument specifies zero or more option flags specifying processing options. The argument should be specified as  0 for no flags, or as one or more of the following symbolic constants, combined using the or operator (|):  

 RETURN VALUE
If successful, msgrcv returns the number of bytes of message text stored (not including the  mtype field). If it fails,  msgrcv returns  -1.

 USAGE NOTES
The msgrcv function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE 1
Refer to msgget for an example.

EXAMPLE 2
Refer to msgctl for an example that establishes and IPC Server using Message Queues.

RELATED FUNCTIONS
msgctl,  msgget,  msgsnd,  msgxrcv


 

msgsnd

   Send a message to a message queue

SYNOPSIS
 #include <sys/msg.h>
int msgsnd(int id, const void *msg,
           size_t size, int flags);

DESCRIPTION
The msgsnd function is used to send a message to an OpenEdition message queue, for later receipt by another process calling  msgrcv or  msgxrcv.  

Note:   See the msgget function description in section msgget for general information about message queues.  [cautend] 

The id argument to  msgsnd specifies the id of the message queue to which messages will be sent. This argument is an id, such as the id returned by  msgget, not a message queue key, which might be passed as an argument to  msgget. 

The msg argument should be a pointer to a message buffer that contains the message to be sent. The message buffer should have the following layout: 

 struct {
   long mtype;     /* message type */
   char mtext[n];  /* message text */
};
where n is an integer constant large enough for the message text.  

Note:   You must declare an appropriate type for the messages you send yourself, as no such type is defined by sys/msg.h. Also the meaning of  mtype is not fixed by the message queue protocol (other than that its value must be greater than zero), but it can be used by the application to establish message types or priorities in any natural way.  [cautend] 

The size argument to  msgsnd should be the number of bytes of message text to be sent.  size should not include the size of the  mtype field. It is possible to send a message which contains only a type, but no text, in which case a size of  0 should be passed.  

The flags argument specifies either  0 or the  IPC_NOWAIT option. If  IPC_NOWAIT is set, and the system limits on the amount of queued up data have been reached, the call to  msgsnd will immediately fail, with  errno set to  EAGAIN. If  IPC_NOWAIT is not set, and the limits have been reached, the calling process will wait until enough messages are removed from the queue to allow this message to be sent.

 RETURN VALUE
msgsnd returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The msgsnd function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE 1
Refer to msgget for an example.

EXAMPLE 2
Refer to msgctl for an example that establishes an IPC Server using Message Queues.

EXAMPLE 3
Refer to msgget for an example that establishes IPC Client using XMessage Queues.

EXAMPLE 4
Refer to msgctl for an example that establishes an IPC Server using Message Queues. Also, it uses Open Edition's extended Message structure.

RELATED FUNCTIONS
msgctl,  msgget,  msgrcv,  msgxrcv


 

msgxrcv

   Receive a message from a message queue with sender information

SYNOPSIS
 #include <sys/msg.h>
int msgxrcv(int id, void *msg, 
            size_t size, long msgtype,
            int flags);

DESCRIPTION
The msgxrcv function is used to receive a message from an OpenEdition message queue. The  msgtype argument allows the caller to select the type of message to be received. Unlike  msgrcv,  msgxrcv stores information about the time the message was sent and the process which sent the message. 

Note:   See the msgget function description in section msgget for general information about OpenEdition message queues.  [cautend] 

The id argument to  msgxrcv specifies the id of the message queue from which messages will be received. This argument is an id, such as the id returned by  msgget, not a message queue key, which might be passed as an argument to  msgget. 

The msg argument should be a pointer to a message buffer into which the received message should be stored. The message buffer should have the following layout: 

 struct {
   /* the time the message was sent */
   time_t mtime;

   /* the effective uid of the sender */
   uid_t muid;

   /* the effective gid of the sender */
   gid_t mgid;

   /* the process id of the sender */
   pid_t mpid;

   /* message type */
   long mtype;

   /* message text */
   char mtext[n];
};

where n is an integer constant large enough for the message text.

Note:   You must declare an appropriate type for the messages you receive yourself, as no such type is defined by sys/msg.h. Also, the meaning of  mtype is not fixed by the message queue protocol, but can be used by the application to establish message types or priorities in any natural way.  [cautend] 

The size argument to  msgxrcv should be the maximum number of bytes of message text to be received.  size should not include the size of any of the fields preceding  mtext in the structure. If the size of the message text to be received is larger than the  size argument, the result depends upon the options specified by the  flags argument.  

The msgtype argument specifies which message, if any, is received. The argument is interpreted as follows: 

 

The flags argument specifies zero or more option flags specifying processing options. The argument should be specified as  0 for no flags, or as one or more of the following symbolic constants, combined using the or operator (|):  

 RETURN VALUE
If successful, msgxrcv returns the number of bytes of message text stored (not including the header fields). If it fails,  msgxrcv returns  -1.

 USAGE NOTES
The msgxrcv function can only be used with MVS 5.2.2 or a later release.

 PORTABILITY
msgxrcv is an OpenEdition extension to UNIX message queue processing, and is not portable.

 EXAMPLE 1
Refer to msgget for an example that establishes an IPC Client using XMessage Queues.

EXAMPLE 2
Refer to msgctl for an example that establishes an IPC Server using Message Queues. Also, it uses Open Edition's extended Message structure.

RELATED FUNCTIONS
msgctl,  msgget,  msgrcv,  msgsnd


 

msync

   Synchronize a memory mapped HFS file

SYNOPSIS
 #include <mman.h>
int msync(void *addr, unsigned int len,
          int flags);

DESCRIPTION
The msync function is used to synchronize an HFS file with one or more pages of memory mapped to the file. The call may either cause the file to be updated with data in memory or cause the data in memory to be updated from the file.  

The addr argument is the address of the first page of mapped memory to be synchronized. The address must be on a page boundary, but need not be the first byte of the entire area mapped to a file.  

The len argument specifies the number of bytes of memory to be synchronized. If the length does not specify an integral number of pages, it is rounded up to do so. The length need not specify the entire area of mapped memory.  

The flags argument specifies options describing how synchronization should be performed. One or more of the following symbolic constants should be specified, combined using the or operator (|).  

 

One of the three flags must be specified, and only one of MS_ASYNC and  MS_SYNC may be specified. If  MS_INVALIDATE is specified together with another flag, the memory contents specified are discarded only after all write operations have completed. 

See the IBM OpenEdition Assembler Callable Services manual for additional information about the behavior of msync and the conditions under which it can be used.

 RETURN VALUE
msync returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The msync function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
Refer to mmap for an example.

RELATED FUNCTIONS
mmap,  mprotect,  munmap


 

munmap

   Cancel mapping of a memory area to a file

SYNOPSIS
 #include <mman.h>
int munmap(void *addr, unsigned int len);

DESCRIPTION
The munmap function is used to terminate mapping of part or all of a memory area previously mapped to a file by the  mmap function.  

The addr argument is the address of the first page of mapped memory to be unmapped. The address must be on a page boundary, but need not be the first byte of the entire area mapped to a file.  

The len argument specifies the number of bytes of memory to be unmapped. If the length does not specify an integral number of pages, it is rounded up to do so. The length need not specify the entire area of mapped memory.  

If an area of memory is mapped and then partially unmapped, any reference to an unmapped portion will cause a segmentation violation.

If the memory area was created by a call to mmap specifying the  MAP_SHARED symbolic flag, all changed areas of memory are written back to the file before  munmap completes. If the  mmap call specified  MAP_PRIVATE, all changes are discarded.  

See the IBM OpenEdition Assembler Callable Services manual for additional information about the behavior of munmap and the conditions under which it can be used.

 RETURN VALUE
munmap returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The munmap function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
Refer to mmap for an example.

RELATED FUNCTIONS
mmap,  mprotect,  msync


 

oetaskctl

   Control subtasks with OpenEdition

SYNOPSIS
 #include <lclib.h>
int oetaskctl(int setting);

DESCRIPTION
The oetaskctl function is used to control the interpretation of MVS subtasks of the current program, such as subtasks created by the system or  oslink functions, or by the assembler  ATTACH macro. By default, subtasks of a program which has used OpenEdition facilities are treated as threads. This means that OpenEdition resources, such as file descriptors, current directory, and signal handlers, are shared between the subtasks. Because the SAS/C library assumes that these resources are not shared, this mode of operation can lead to errors.  

Alternately, oetaskctl can be used to indicate that subtasks of the calling program are to be treated as a separate process from the calling program. This implies each subtask will have its own set of file descriptors, its own current directory, and its own signal handling. This is generally recommended when both tasks are SAS/C programs.  

The setting argument to  oetaskctl specifies whether a new subtask should be treated as a thread or a process. An argument of  0 specifies a thread, and  1 specifies a process. 

Note:   The thread or process decision is made when the subtask calls the first OpenEdition function, not when the subtask is ATTACHed.  [cautend]

 RETURN VALUE
oetaskctl returns the previous  oetaskctl setting if successful. It returns  -1 if it was unable to complete successfully.

 USAGE NOTES
oetaskctl is useful only if both the calling task and the subtask use OpenEdition facilities.

 SEE ALSO
ATTACH,  system


 

readextlink

   Read an external link

SYNOPSIS
 #include <unistd.h>
int readextlink(const char *name,
                char *buf,
                size_t size);

DESCRIPTION
readextlink reads the contents of an external link. (See the  extlink function description in section extlink for further information on external links.) The  name argument specifies the name of the external link. The  buf argument specifies the address of a buffer into which the contents of the link should be read, and  size specifies the size of the buffer in bytes. If  size is  0, no data is stored, and the length required is returned as the function value. 

When you call readextlink in an application which was not compiled with the

 posix
option, the link name is interpreted according to the normal rules for file name interpretation. For this reason, when not compiled with
 posix
the file name should include a style prefix unless the default style is hfs. 

Note:   The name stored in buf will not contain any prefix.  [cautend]

 RETURN VALUE
readextlink returns the number of bytes stored in the buffer, or the number of bytes required if  size was zero, or  -1 if unsuccessful.

 USAGE NOTES
The getrusage function can only be used with MVS 5.2.2 or a later release.

 RELATED FUNCTIONS
extlink,  lstat


 

realpath

   Return absolute pathname

SYNOPSIS
 #include <lclib.h>
char *realpath(const char *pathname, 
               char absname[PATH_MAX+1]);

If the feature test macro _SASC_POSIX_SOURCE is defined and  _POSIX_SOURCE is not defined, the prototype is also visible in  <stdlib.h>.

 DESCRIPTION
The realpath function can be used to return a standard form of an OpenEdition path name. The path name returned will be an absolute path name, which does not involve the "." or ".." notations or symbolic links. 

The pathname argument to  realpath is the OpenEdition path name to be resolved. If the program was not compiled with the

 posix 
compiler option, pathname should begin with an  hfs: style prefix. 

The absname argument should be an array of  PATH_MAX+1 characters, in which  realpath will store the canonical form of the path name.  PATH_MAX is defined in the header file  <limits.h>. If the program was not compiled with the

 posix 
compiler option, the value stored will begin with an hfs: style prefix.

 RETURN VALUE
realpath returns the address of the standardized path name if successful, and otherwise returns  0.

 USAGE NOTES
The realpath function can only be used with MVS 5.2.2 or a later release.


 

semctl

   Control a semaphore set

SYNOPSIS
 #include <sys/sem.h>
int semctl(int id, 
           int num, 
           int cmd, argument);

DESCRIPTION
The semctl function is used to perform one of several control operations on an OpenEdition semaphore set.  

Note:   See the semget function description in section semget for general information about semaphore sets.  [cautend] 

The id argument to  semctl specifies a semaphore set id. This argument is an id, such as the id returned by  semget, not a semaphore set key, which might be passed as an argument to  semget. 

The num argument to  semctl specifies the index of the specific semaphore to which the control operation applies. Some operations apply to the entire set. For these operations, this argument is ignored. 

The cmd argument specifies the operation which is to be performed. The value and type of the fourth argument (  argument) to  semctl, if any, is dependent on the  cmd specification.  cmd should be specified as one of the following symbolic values: 

 

Several of the semctl operations allow you to obtain or access the semaphore set id data structure, which is mapped by the  struct semid_ds type defined in  

sys/sem.h.  

This data structure is defined as follows:

 struct semid_ds {
   /* permission information */
   struct ipc_perm sem_perm;

   /* number of semaphores in set */
   unsigned short sem_nsems;

   /* time of last semop call */
   time_t sem_otime;

   /* time of last change by semctl */
   time_t sem_ctime;
};

The ipc_perm structure, which contains security information about the owner and the creator of the semaphore set, is defined as follows:  

 struct ipc_perm {
   /* owner's effective user ID */
   uid_t uid;

   /* owner's effective group ID */
   gid_t gid;

   /* creator's effective user ID */
   uid_t cuid;

   /* creator's effective group ID */
   gid_t cgid;

   /* read/write permission bits */
   mode_t mode;
};

RETURN VALUE
For operations of GETVAL,  GETNCNT,  GETZCNT and  GETPID,  semctl returns the information requested. For all others, it returns  0 if successful. In all cases, it returns  -1 if unsuccessful.

 USAGE NOTES
The semctl function can only be used with MVS 5.2.2 or a later release.

 RELATED FUNCTIONS
semget,  semop


 

semget

    Create or find a set of semaphores

SYNOPSIS
 #include <sys/sem.h>
int semget(key_t key, int num, int flags);

DESCRIPTION
The semget function is used to create a new set of semaphores or to locate an existing set based on a key. Semaphore sets are implemented by OpenEdition, and allow synchronization of multiple processes which do not share memory. Each semaphore in the set has an integer value, which can be raised, lowered and tested safely by multiple processes. OpenEdition semaphores allow multiple semaphores to be processed with a single call, and support both blocking and non-blocking processing. Semaphore sets, once created using  semget, remain in existence until explicitly destroyed with a call to  semctl. 

The key argument is an integral value which identifies the semaphore set desired. A  key value of  IPC_PRIVATE requests a new semaphore set without an associated  key, and which can be accessed only by the queue id returned by  semget. 

The num argument specifies the number of semaphores in the set, if the set is created. If the semaphore set already exists,  num must not be larger than the number of semaphores in the set.  

Note:   The num argument may be specified as zero if the set already exists, but not for a new set.  [cautend] 

The flags argument specifies zero or more option flags specifying whether or not the semaphore set already exists, and how access to the set should be regulated. The argument should be specified as  0 for no flags, or as one or more of the following symbolic constants, combined using the or operator (|):  

 

Additionally, any of the permission bits S_IRUSR,  S_IWUSR,  S_IRGRP,  S_IWGRP,  S_IROTH and  S_IWOTH may be specified, to define what users are permitted to access or modify the semaphore set. See the  umask function description in the SAS/C Library Reference, Volume 2, for more information about the meaning of these flags.

 RETURN VALUE
semget returns the identifier of the semaphore set if successful, or  -1 if unsuccessful.

 USAGE NOTES
The semget function can only be used with MVS 5.2.2 or a later release. 

When semget creates a set of semaphores, the semaphores are uninitialized. You should use the  SETALL command of  semctl to give the semaphores their initial values.

 EXAMPLE
This example is compiled using sascc370 -Krent -o. This program demonstrates the use of the Open Edition IPC functions  semget() and  semstat().
 /*--------------------------------+
| POSIX/UNIX header files         |
+--------------------------------*/
#include <sys/types.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/ipc.h>

#include <sys/sem.h>

/*--------------------------------+
| ISO/ANSI header files           |
+--------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <time.h>

#include errno.h>

/*--------------------------------+
| Types                           |
+--------------------------------*/
/* argument for semctl()            */
typedef union semun               
{
/* for SETVAL                       */
   int  val;                      

/* for IPC_STAT and IPC_SET         */
   struct semid_ds * ID;          

/* for GETALL and SETALL            */
   unsigned short * array;        

} SemaphoreSet;

/*----------------------------------+
| Constants                         |
+----------------------------------*/
/* semaphore key                    */
#define SEM_KEY      (key_t)1097    

/* give everyone read/write         */
/* permission to semaphore          */
#define SEM_PERM  (S_IRUSR|S_IWUSR
  |S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

/*------------------------------------+
| Name:      main                     |
| Returns:   exit(EXIT_SUCCESS) or    |
|            exit(EXIT_FAILURE)       |
+-------------------------------------*/
int main()
{
/* semaphore set id                   */
    int semID;                  

/* semaphore flags                    */
    int semFlags;               

/* number of semaphore in a set      */
    int numSems;                

/* index into semaphore set (array)   */
    int semNumber;              

/* command to semaphore.              */
    int semCmd;                 

/* union of info on semaphore set     */
    SemaphoreSet semSet;        

/*-----------------------------------------*/
/* Create semaphore set with 5 semaphores. */
/* Give everyone read/write permissions.   */
/*-----------------------------------------*/
/* create set with 5 semaphores    */
   numSems = 5;                    
   semFlags = IPC_CREAT | SEM_PERM;

if ( (semID = semget
  (SEM_KEY, numSems, semFlags)) < 0 )
   {
       perror("SEMSTAT: semget");
       exit(EXIT_FAILURE);
   }

/*-------------------------------------*/
/* Allocate memory to store            */
/* information from semaphore set      */
/*-------------------------------------*/
 semSet.ID = malloc(sizeof(struct semid_ds));

   if (semSet.ID == NULL)
   {
   fprintf(stderr,
   "ERROR: 
   Cannot allocate memory for 
   semaphore set stats\n");
   semctl(semID, NULL, IPC_RMID, NULL);
   exit(EXIT_FAILURE);
   }

/*------------------------------------*/
/* Call semctl to retrieve            */
/* information from semaphore set     */
/*------------------------------------*/
/* command to retrieve stats         */
   semCmd = IPC_STAT;            
/* ignored for IPC_STAT command      */
   semNumber = 0;                

if (semctl(semID, semNumber, 
   semCmd, semSet) < 0)
   {
   perror("SEMSTAT: semctl failed to 
   retrieve semaphore set stats");
   semctl(semID, NULL, IPC_RMID, NULL);
   free(semSet.ID);
   exit(EXIT_FAILURE);
   }
 
/*-----------------------------------*/
/* Print infomation retrieved from   */
/*  semaphore set                    */
/*-----------------------------------*/
 printf("Semaphore Set Statistics:\n\n");

printf("\tOwner's effective user ID: %d\n",
      (int)semSet.ID->sem_perm.uid);
printf("\tOwner's effective group ID: %d\n",
      (int)semSet.ID->sem_perm.gid);
printf("\tCreator's effective user ID: %d\n",
      (int)semSet.ID->sem_perm.cuid);
printf("\tCreator's effective group ID: %d\n",
      (int)semSet.ID->sem_perm.cgid);
printf("\tPermission mode bits: %#.3o\n\n",
      (int)semSet.ID->sem_perm.mode);

printf("\tNumber of semaphores currently in 
   the set: %d\n",
      semSet.ID->sem_nsems);
printf("\tTime of last semop call: %s",
      ctime(&semSet,ID->sem_otime));
printf("\tTime of last change: %s",
      ctime(&semSet.ID->sem_ctime));

/*--------------------------------------*/
/* Free memory used to store            */
/* information from semaphore set       */
 *--------------------------------------*/
   free(semSet.ID);

/*---------------------------------------*/
/* Call semctl to remove semaphore set.  */
/*---------------------------------------*/
if (semctl(semID, NULL, IPC_RMID, NULL) < 0)
   {
   perror("SEMSTAT: semctl failed to 
   remove semNumber set");
   exit(EXIT_FAILURE);
   }
 
   exit(EXIT_SUCCESS);

}  /* end of main() */

RELATED FUNCTIONS
semctl,  semop


 

semop

   Update semaphores atomically

SYNOPSIS
 #include <sys/sem.h>
int semop(int id, struct sembuf *ops, 
          size_t num);

DESCRIPTION
The semop function is used to update one or more semaphores from a set atomically. For each update, the caller can request either blocking until the operation can be performed, or immediate failure of  semop.  

Note:   See the semget function description in section semget for general information about OpenEdition semaphores.  [cautend] 

The id argument to  semop specifies the id of the semaphore set to be updated. This argument is an id, such as the id returned by  semget, not a semaphore set key, which might be passed as an argument to  semget. 

The ops argument should be a pointer to an array of one or more  sembuf structures, each of which defines a single semaphore operation to be performed. All the operations are performed simultaneously and atomically; that is, no changes are made to any semaphore until they can be made to all specified semaphores. The  struct sembuf mapping is defined by  sys/sem.h as follows: 

 struct sembuf {
   /* semaphore number */
   unsigned short sem_num;

   /* semaphore operation code */
   short sem_op;

   /* option flags */
   short sem_flg;
};

The sem_num field of a  struct sembuf specifies the specific semaphore to be updated. The  sem_op field is interpreted in the following manner: 

 

The sem_flg field of the  sembuf structure is used to specify option flags. It may contain  0 if no options are required, or one or more of the following symbolic constants, combined by the or operator (|). 

 

The num argument to  semop indicates the number of operations specified by the  ops argument.

 RETURN VALUE
semop returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The semop function can only be used with MVS 5.2.2 or a later release.

 PORTABILITY
Complex semop calls may be handled differently by different systems, especially if some operations specify  IPC_NOWAIT and some do not. For best results, it is recommended that  IPC_NOWAIT should be either specified by all elements of the  ops array, or by none of them.

 EXAMPLE
This example uses a single semaphore to synchronize access to a resource. The semaphore is created the first time the application runs, and is deleted only if the first argument to the program is the string -d.
 #include <sys/sem.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

int main(int argc, char *argv[])
{
  /* semaphore set id */
  int id;

  /* inital value for semaphore set */
  unsigned short available[1] = { 1 };

  /* return code var */
  int rc;

  /* to reserve the semaphore */
  struct sembuf reserve[1];

  /* to release the semaphore */
  struct sembuf release[1];

   /* If this application's semaphore 
      does not exist, create it */

  /* arg1-arbitrary unique semaphore key */
  /* arg2-only 1 semaphore in set */
  /* arg3-don't create it */
  id = semget(0x5A5C, 1, 0);

  if (id < 0)

    /* if failed, but not because
       semaphore doesn't exist */
    if (errno != ENOENT) 
    {

      badget:
      perror("semget");
      abort();
    } 

    /* no semaphore, create it */
    else 
    {
      /* unless its to be deleted */
      if (argc>1 && 
          strcmp(argv[1],"-d")==0)
          exit(0);
      id=semget(0x5A5C, 1,
           IPC_CREAT | S_IRUSR | S_IWUSR);
      /* if that fails, give up */
      if (id < 0) goto badget;

      /* Init semaphore to 1 (available) */
      rc=semctl(id, 0, SETALL, available);
      if (rc < 0) 
      {
        perror("semctl SETALL");
        abort();
      }
    }

  /* set up to reserve semaphore */
  reserve[0].sem_num = 0;

  /* try to decrement semaphore by 1 */
  reserve[0].sem_op = -1;

  /* if process dies, unreserve it */
  reserve[0].sem_flg = SEM_UNDO;
                          
  /* wait for semaphore to become
     non-zero, then zero it */
  rc = semop(id, reserve, 1);

  if (rc < 0) 
  {
    perror("semop reserve");
    abort();
  }

  /* We now have exclusive control of the 
     guarded resource. Place code here to 
     update the resource. */

  if (argc>1 && strcmp(argv[1],"-d") == 0)
  {
    /* Check for a request to delete 
       the semaphore */
    rc = semctl(id, 0, IPC_RMID);
    if (rc < 0) 
    {
      perror("semctl IPC_RMID");
      abort();
    }
    exit(0);
  }

  /* Release semaphore for next request */

  /* set up to release semaphore */
  release[0].sem_num = 0;

  /* try to increment semaphore by 1 */
  release[0].sem_op = 1;

  /* if process dies, undo it */
  release[0].sem_flg = SEM_UNDO;

  rc = semop(id, release, 1);
  if (rc < 0) 
  {
    perror("semop release");
      abort();
  }
  exit(0);
}

RELATED FUNCTIONS
semctl,  semget


 

setgrent

   Reposition the group database

SYNOPSIS
 #include <sys/types.h>
#include <grp.h>
void setgrent(void);

DESCRIPTION
The setgrent function rewinds the group database so that the next call to the  getgrent function will access the first group in the database.

 RETURN VALUE
setgrent has no return value.

 USAGE NOTES
The setgrent function can only be used with MVS 5.2.2 or a later release. 

If the setgrent function cannot be executed (for instance, because OpenEdition is not installed or running), it issues an MVS user  ABEND 1230 to indicate the error.

 RELATED FUNCTIONS
endgrent,  getgrent


 

setitimer

   Define an interval timer

SYNOPSIS
 #include <sys/time.h>
int setitimer(int kind,
              const struct itimerval *ival,
              struct itimerval *oval);

DESCRIPTION
The setitimer function defines an interval timer, that is, a timer which generates a signal each time a specified time interval expires. Three different forms of time measurement may be specified.  

The kind argument is a symbolic constant specifying the type of time interval required. The permitted values are: 

 

The ival argument specifies the time values controlling the timer. This argument is a pointer to an  itimerval structure, which contains two fields defined as follows: 

 

In other words, the it_value field specifies the amount of time between the  setitimer call and the first expiration, while the  it_interval field specifies the time between successive expirations. If  it_value is specified as zero when  setitimer is called, any existing interval is immediately cancelled. If  it_interval is specified as zero, the timer will expire once, and then be cancelled.  

The it_value and  it_interval fields both have type  struct timeval, which allows a time value to be specified to an accuracy of a microsecond. The structure has two fields: 

 

The oval argument to  setitimer is a pointer to a  struct itimerval in which the current interval timer values are to be stored.  oval may be specified as  NULL, in which case, this information is not stored.

 RETURN VALUE
setitimer returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The setitimer function can only be used with MVS 5.2.2 or a later release.  

Programs which are not invoked from the shell must call the oesigsetup function to enable handling of the timer signals before invoking  setitimer.

 RELATED FUNCTIONS
getitimer


 

setpriority

   Change process priority

SYNOPSIS
 #include <sys/resource.h>
int setpriority(int kind, int id, 
                int prio);

DESCRIPTION
The setpriority function changes the OpenEdition priority of a process, or the priority of all processes in a process group or belonging to a user. See the  getpriority function description in section getpriority for further information on OpenEdition priorities. 

The kind argument to  setpriority should be specified as a symbolic constant indicating the scope of the priority change. The permissible values are: 

 

The id argument specifies the process id, process group id, or user id whose priority should be changed. If  id is  0, it specifies the calling process, process group or user.  

The prio argument specifies the requested new priority. It should be a signed integer between -20 to 19. Lower numbers indicate higher priority. 

Note:   OpenEdition sites must enable the use of the setpriority function. If the use of  setpriority has not been enabled, any use of  setpriority will fail with  errno set to  ENOSYS.  [cautend]

 RETURN VALUE
setpriority returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The setpriority function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
Refer to chpriority for an example that demonstrates the use of the OpenEdition process priority functions chpriority,  getpriority, and  setpriority.

 RELATED FUNCTIONS
chpriority,  getpriority


 

setpwent

   Reposition the user database

SYNOPSIS
 #include <sys/types.h>
#include <pwd.h>
void setpwent(void);

DESCRIPTION
The setpwent function rewinds the user database so that the next call to the  getpwent function will access the first user in the database.

 RETURN VALUE
setpwent has no return value.

 USAGE NOTES
The setpwent function can only be used with MVS 5.2.2 or a later release. 

If the setpwent function cannot be executed (for instance, because OpenEdition is not installed or running), it issues an MVS user  ABEND 1230 to indicate the error.

 RELATED FUNCTIONS
endpwent,  getpwent


 

setregid

   Set real and/or effective group id

SYNOPSIS
 #include <sys/types.h>
#include <unistd.h>
int setregid(gid_t realgid, 
             gid_t effgid);

DESCRIPTION
The setregid function is used to set the real and/or the effective group ids for the calling process. A superuser or daemon process has the ability to set any valid group id. Other processes are limited in their use of  setregid.  

Note:   See the IBM OpenEdition MVS Assembler Callable Services publication, SC28-2899, for more information on the use of setregid by unprivileged processes.  [cautend] 

The realgid argument to  setregid specifies the new real group id. If  realgid is specified as  -1, the real group id is unchanged. The  effgid argument to  setregid specifies the new effective group id. If  effgid is specified as  -1, the effective group id is unchanged.

 RETURN VALUE
setregid returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The setregid function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
This example is compiled using sascc370 -Krent -o. This program demonstrates the use of the OpenEdition functions  setregid() and  setreuid().
 /*---------------------------------------+
| POSIX/UNIX header files                |
+---------------------------------------*/
#include <sys/types.h>

#include <unistd.h>

/*---------------------------------------+
| ISO/ANSI header files                  |
+---------------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

/*---------------------------------------+
| Name:      main                        |
| Returns:   exit(EXIT_SUCCESS) or       |
|            exit(EXIT_FAILURE)          |
+---------------------------------------*/
int main()
{
/* generic return code                          */
   int rc;            

/* real group ID of calling process             */
   gid_t rgid;        

/* effective group ID of calling process        */
   gid_t egid;        

/* real user ID of calling process              */
   uid_t ruid;        

/* effective user ID of calling process         */
   uid_t euid;        

/*----------------------------------------------*/
/* Get the real and effective group and user    */
/* ids for this process.                        */
/*----------------------------------------------*/
   printf("\nGet the Real and Effective 
      Group and User IDs\n");
/* get real group ID                            */
   rgid = getgid();   

/* get effective group ID                       */
   egid = getegid();  

/* get real user ID                             */
   ruid = getuid();   

/* get effective user ID                        */
   euid = geteuid();  

   printf("     The real group id is: %d\n", 
    (int)rgid);
   printf("The effective group id is: %d\n", 
    (int)egid);
   printf("      The real user id is: %d\n", 
    (int)ruid);
   printf(" The effective user id is: %d\n", 
    (int)euid);

/*-----------------------------------------------*/
/* Set the real and effective group id for this  */
/* process.                                      */
/*-----------------------------------------------*/
printf("\nSetting the Real and Effective Group ID\n");

   errno = 0;
   egid = rgid;
/* -1 implies use current real group id (nochg) */
   rgid = (gid_t)-1;  

   rc = setregid(rgid, egid);

   /* Test for Error */
   if (rc == -1)
   {
      perror("Call to setregid failed");
      exit(EXIT_FAILURE);
   }

/*--------------------------------------------*/
/* Set the real and effective user id for     */
/* this process.                              */
/*--------------------------------------------*/
 printf("\nSetting the Real and 
   Effective User ID\n");

   errno = 0;
   euid = ruid;
/* -1 implies use current real user id (nochg) */
   ruid = (gid_t)-1;  

   rc = setreuid(ruid, euid);

   /* Test for Error */
   if (rc == -1)
   {
      perror("Call to setreuid failed");
      exit(EXIT_FAILURE);
   }

/*-----------------------------------------*/
/* Get the real and effective group and    */
/* user ids                                */
/*-----------------------------------------*/
   printf("\nThe Real and Effective 
     Group and User IDs are now!\n");

/* get real group ID                       */
   rgid = getgid();   

/* get effective group ID                  */
   egid = getegid();  

/* get real user ID                        */
   ruid = getuid();   

/* get effective user ID                   */
   euid = geteuid();  

   printf("     The real group id is: %d\n", 
    (int)rgid);
   printf("The effective group id is: %d\n", 
    (int)egid);
   printf("      The real user id is: %d\n", 
    (int)ruid);
   printf(" The effective user id is: %d\n", 
    (int)euid);

   exit(EXIT_SUCCESS);

}  /* end of main() */

RELATED FUNCTIONS
getegid,  getgid,  setegid,  setgid


 

setreuid

   Set real and/or effective user id

SYNOPSIS
 #include <sys/types.h>
#include <unistd.h>
int setreuid(uid_t realuid, uid_t effuid);

DESCRIPTION
The setreuid function is used to set the real and/or the effective user ids for the calling process. A superuser or daemon process has the ability to set any valid user id. Other processes are limited in their use of  setreuid.  

Note:   See the IBM OpenEdition MVS Assembler Callable Services publication, SC28-2899, for more information on the use of setreuid by unprivileged processes.  [cautend] 

The realuid argument to  setreuid specifies the new real user id. If  realuid is specified as  -1, the real user id is unchanged. The  effuid argument to  setreuid specifies the new effective user id. If  effuid is specified as  -1, the effective user id is unchanged.

 RETURN VALUE
setreuid returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The setreuid function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
Refer to setregid for an example that demonstrates the use of the OpenEdition functions setregid() and  setreuid().

 RELATED FUNCTIONS
geteuid,  getuid,  seteuid,  setuid


 

setrlimit

   Define OpenEdition resource limits

SYNOPSIS
 #include <sys/resource.h>
int setrlimit(int resource,
              const struct rlimit *info);

DESCRIPTION
The setrlimit function defines resource limits for the calling process. Limits are expressed as a pair of integers, a soft limit and a hard limit. The soft limit controls the amount of the resource the program is actually allowed to consume, while the hard limit specifies an upper bound on the soft limit. The soft limit can be raised up to the hard limit value, but the hard limit can only be raised by a privileged (superuser) caller.  

The resource argument defines the resource to which the limit applies. It should be specified as one of the symbolic values defined below. 

 The info argument is a pointer to a structure of type  struct rlimit, which defines the soft and hard limits. The structure contains the following fields:  
  1. rlim_cur - the current (i.e., soft) limit
  2.  rlim_max - the maximum limit
 
RETURN VALUE
setrlimit returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The setrlimit function can only be used with MVS 5.2.2 or a later release. 

Note:   Resource limits defined by setrlimit are propagated to child processes created by  fork or  exec.  [cautend]

 RELATED FUNCTIONS
getrlimit


 

shmat

   Attach a shared memory segment

SYNOPSIS
 #include <sys/shm.h>
void *shmat(int id, const void *addr,
            int flags);

DESCRIPTION
The shmat function is used to attach a shared memory segment to a process, so that the memory contents can be accessed.  

Note:   See the shmget function description in section shmget for general information about shared memory segments.  [cautend] 

The id argument to  shmat specifies a shared memory segment id. This argument is an id, such as the id returned by  shmget, not a memory segment key, which might be passed as an argument to  shmget. 

The addr argument to  shmat specifies a pointer value indicating the address at which the memory segment is to be attached. If  addr is  NULL, the segment will be attached at an address selected by the system. If  addr is specified,  shmat will fail if the segment cannot be attached as specified because memory is already allocated near the address specified.  

Note:   The flag bit SHM_RND influences the interpretation of  addr, as described below.  [cautend] 

The flags argument specifies zero or more option flags. The argument should be specified as  0 for no flags, or as one or more of the following symbolic constants, combined using the or operator (|):  

 RETURN VALUE
shmat returns the address of the attached segment, or (void *)  -1 if unsuccessful.

 USAGE NOTES
The shmat function can only be used with MVS 5.2.2 or a later release. 

Note:   A site can impose limits on the size and number of shared memory segments that can be attached.  [cautend]

EXAMPLE 1
This example is compiled using sascc370 -Krent -o. This program uses the functions  shmat(),  shmctl(),  shmdt(), and  shmget() to establish an IPC Client using a Shared Memory Segment.
 /*-------------------------------------+
| POSIX/UNIX header files              |
+-------------------------------------*/
#include <fcntl.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include sys/shm.h>

/*-------------------------------------+
| ISO/ANSI header files                |
+-------------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <errno.h>

/*-------------------------------------+
| Constants                            |
+-------------------------------------*/
/* memory segment character value     */
#define MEM_CHK_CHAR        '*'     

/* shared memory key                  */
#define SHM_KEY      (key_t)1097    

#define SHM_SIZE     (size_t)256    

/* size of memory segment (bytes)     */
/* give everyone read/write           */
/* permission to shared memory        */
#define SHM_PERM  (S_IRUSR|S_IWUSR
  |S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

/*------------------------------------+
| Name:      main                     |
| Returns:   exit(EXIT_SUCCESS) or    |
|            exit(EXIT_FAILURE)       |
+------------------------------------*/
int main()
{
/* loop counter                       */
    int i;                      

/* shared memory segment id           */
    int shMemSegID;             

/* shared memory flags                */
    int shmFlags;               

/* ptr to shared memory segment       */
    char * shMemSeg;            

/* generic char pointer               */
    char * cptr;                

/*-------------------------------------*/
/* Get the shared memory segment for   */
/* SHM_KEY, which was set by           */
/* the shared memory server.           */
/*-------------------------------------*/
   shmFlags = SHM_PERM;

if ( (shMemSegID = 
shmget(SHM_KEY, SHM_SIZE, shmFlags)) < 0 )
   {
   perror("CLIENT: shmget");
   exit(EXIT_FAILURE);
   }

/*-----------------------------------------*/
/* Attach the segment to the process's     */
/* data space at an address                */
/* selected by the system.                 */
/*-----------------------------------------*/
shmFlags = 0;
if ( (shMemSeg = 
      shmat(shMemSegID, NULL, shmFlags)) == 
      (void *) -1 )
   {
       perror("SERVER: shmat");
       exit(EXIT_FAILURE);
   }

/*-------------------------------------------*/
/* Read the memory segment and verify that   */
/* it contains the values                    */
/* MEM_CHK_CHAR and print them to the screen */
/*-------------------------------------------*/
for (i=0, cptr = shMemSeg; i < SHM_SIZE; 
i++, cptr++)
   {
      if ( *cptr != MEM_CHK_CHAR )
      {
         fprintf(stderr, "CLIENT: 
           Memory Segment corrupted!\n");
         exit(EXIT_FAILURE);
      }

      putchar( *cptr );
/* print 40 columns across            */

      if ( ((i+1) % 40) == 0 )        
     {
         putchar('\n');
      }
   }
   putchar('\n');

/*--------------------------------------------*/
/* Clear shared memory segment.               */
/*--------------------------------------------*/
   memset(shMemSeg, '\0', SHM_SIZE);

/*------------------------------------------*/
/* Call shmdt() to detach shared            */
/* memory segment.                          */
/*------------------------------------------*/
   if ( shmdt(shMemSeg) < 0 )
   {
       perror("SERVER: shmdt");
       exit(EXIT_FAILURE);
   }

   exit(EXIT_SUCCESS);

}  /* end of main() */

EXAMPLE 2
This example is compiled using sascc370 -Krent -o. This program uses the functions  shmat(),  shmctl(),  shmdt(), and  shmget() to establish an IPC Server using a Shared Memory Segment. 

Note:   One cannot use the Extended Message structure to send a message, i.e., call shmsnd() with this structure. Attempting to do so will cause the program to "hang".   [cautend]

 /*--------------------------------------+
| POSIX/UNIX header files               |
+--------------------------------------*/
#include <sys/types.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/ipc.h>

#include >sys/shm.h>

/*--------------------------------------+
| ISO/ANSI header files                 |
+--------------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <time.h>

#include <errno.h>

/*--------------------------------------+
| Constants                             |
+--------------------------------------*/
/* value to fill memory segment        */
#define MEM_CHK_CHAR         '*'    

/* shared memory key                   */
#define SHM_KEY      (key_t)1097    

/* size of memory segment (bytes)      */
#define SHM_SIZE     (size_t)256    

/* give everyone read/write permission   */
/* to shared memory                      */
#define SHM_PERM  (S_IRUSR|S_IWUSR
  |S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

/*----------------------------------------+
| Name:      main                         |
| Returns:   exit(EXIT_SUCCESS) or        |
|            exit(EXIT_FAILURE)           |
+-----------------------------------------*/
int main()
{
/* shared memory segment id           */
    int shMemSegID;             

/* shared memory flags                */
    int shmFlags;               

/* ptr to shared memory segment       */
    char * shMemSeg;            

/*---------------------------------------*/
/* Create shared memory segment          */
/* Give everyone read/write permissions. */
/*---------------------------------------*/
   shmFlags = IPC_CREAT | SHM_PERM;

 if ( (shMemSegID = 
  shmget(SHM_KEY, SHM_SIZE, shmFlags)) < 0 )
   {
       perror("SERVER: shmget");
       exit(EXIT_FAILURE);
   }

/*-------------------------------------------*/
/* Attach the segment to the process's data  */
/* space at an address                       */
/* selected by the system.                   */
/*-------------------------------------------*/
shmFlags = 0;
if ( (shMemSeg = 
      shmat(shMemSegID, NULL, shmFlags)) == 
  (void *) -1 )
   {
       perror("SERVER: shmat");
       exit(EXIT_FAILURE);
   }

/*-------------------------------------------*/
/* Fill the memory segment with MEM_CHK_CHAR */
/* for other processes to read               */
/*-------------------------------------------*/
   memset(shMemSeg, MEM_CHK_CHAR, SHM_SIZE);

/*-----------------------------------------------*/
/* Go to sleep until some other process changes  */
/* first character                               */
/* in the shared memory segment.                 */
/*-----------------------------------------------*/
   while (*shMemSeg == MEM_CHK_CHAR)
   {
      sleep(1);
   }

/*------------------------------------------------*/
/* Call shmdt() to detach shared memory segment.  */
/*------------------------------------------------*/
   if ( shmdt(shMemSeg) < 0 )
   {
       perror("SERVER: shmdt");
       exit(EXIT_FAILURE);
   }


/*--------------------------------------------------*/
/* Call shmctl to remove shared memory segment.     */
/*--------------------------------------------------*/
   if (shmctl(shMemSegID, IPC_RMID, NULL) < 0)
   {
       perror("SERVER: shmctl");
       exit(EXIT_FAILURE);
   }
 
   exit(EXIT_SUCCESS);

}  /* end of main() */

RELATED FUNCTIONS
shmctl,  shmdt,  shmget


 

shmctl

   Control a shared memory segment

SYNOPSIS
 #include <sys/shm.h>
int shmctl(int id, int cmd,
           struct shmid_ds *buf);

DESCRIPTION
The shmctl function is used to perform one of several control operations on a shared memory segment.  

Note:   See the shmget function description in section shmget for general information about shared memory segments.  [cautend] 

The id argument to  shmctl specifies a shared memory segment id. This argument is an id, such as the id returned by  shmget, not a memory segment key, which might be passed as an argument to  shmget. 

The cmd argument should be specified as a symbolic constant specifying the specific operation to be performed by  shmctl. The constant values are described below.  

Several of the shmctl operations allow you to obtain or access the shared memory id data structure, which is mapped by the  struct shmid_ds type defined in  sys/shm.h. 

This data structure is defined as follows:

 struct shmid_ds {
   /* permission information */
   struct ipc_perm shm_perm;

   /* segment size */
   int shm_segsz;

   /* process id for last shm operation */
   pid_t shm_lpid;

   /* process id of creator */
   pid_t shm_cpid;

   /* number of times segment attached */
   unsigned shm_nattch;

   /* time of last shmat call */
   time_t shm_atime;

   /* time of last shmdt call */
   time_t shm_dtime;

   /* time of last change by shmget/shmctl */
   time_t shm_ctime;
};

The ipc_perm structure contains security information about the owner and the creator of the memory segment and is defined as follows:  

 struct ipc_perm {
   /* owner's effective user ID */
   uid_t uid;

   /* owner's effective group ID */
   gid_t gid;

   /* creator's effective user ID */
   uid_t cuid;

   /* creator's effective group ID */
   gid_t cgid;

   /* read/write permission bits */
   mode_t mode;
};

For shmctl operations which access or modify the shared memory id data structure, the  buf argument addresses a  struct shmid_ds, used as described below. For other operations, the  buf argument is ignored.  

The cmd values accepted by  shmctl and their meanings are as follows: 

 RETURN VALUE
shmctl returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The shmctl function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE 1
Refer to shmat for an example that uses the functions shmat(),  shmctl(),  shmdt(), and  shmget() to establish an IPC Client using a Shared Memory Segment.

 EXAMPLE 2
Refer to shmat for an example that uses the functions shmat(),  shmctl(),  shmdt(), and  shmget() to establish an IPC Server using a Shared Memory Segment.

 RELATED FUNCTIONS
shmat,  shmdt,  shmget


 

shmdt

   Detach a shared memory segment

SYNOPSIS
 #include <sys/shm.h>
int shmdt(const void *addr);

DESCRIPTION
The shmdt function is used to detach a shared memory segment from a process. The segment is not destroyed, even if the calling process is the only process which has it attached. (See the  shmget function description in section shmget for general information about shared memory segments.) 

The addr argument specifies a pointer value to the location at which the shared segment is attached.

 RETURN VALUE
shmdt returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The shmdt function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE 1
Refer to shmat for an example that uses the functions shmat(),  shmctl(),  shmdt(), and  shmget() to establish an IPC Client using a Shared Memory Segment.

 EXAMPLE 2
Refer to shmat for an example that uses the functions shmat(),  shmctl(),  shmdt(), and  shmget() to establish an IPC Server using a Shared Memory Segment.

 RELATED FUNCTIONS
shmat,  shmctl,  shmget


 

shmget

    Create or find a shared memory segment

SYNOPSIS
 #include <sys/shm.h>
int shmget(key_t key, size_t size,
           int flags);

DESCRIPTION
The shmget function is used to create a new shared memory segment or to locate an existing one based on a key. Shared memory segments are memory areas which can be shared by several processes and which, once created, continue to exist until explicitly deleted using the  shmctl function.  

The key argument is an integral value which identifies the shared memory segment desired. A  key value of  IPC_PRIVATE requests a new shared memory segment without an associated key, and which can be accessed only by the segment id returned by  shmget.  

The size argument specifies the required size of the segment. If the segment already exists,  size must be no greater than the size specified when the segment was created.  

The flags argument specifies zero or more option flags specifying whether or not the segment already exists, and how access to the segment should be regulated. The argument should be specified as  0 for no flags, or as one or more of the following symbolic constants, combined using the or operator (|):  

 

Additionally, any of the permission bits S_IRUSR,  S_IWUSR,  S_IRGRP,  S_IWGRP,  S_IROTH and  S_IWOTH may be specified, to define what users are permitted to access or modify the memory segment. See the  umask function description in the SAS/C Library Reference, Volume 2, for more information about the meaning of these flags.

 RETURN VALUE
shmget returns the identifier of the shared memory segment if successful, or  -1 if unsuccessful.

 USAGE NOTES
The shmget function can only be used with MVS 5.2.2 or a later release. 

Note:   A site can impose limits on the size and number of shared memory segments created.  [cautend]

EXAMPLE 1
Refer to shmat for an example that uses the functions shmat(),  shmctl(),  shmdt(), and  shmget() to establish an IPC Client using a Shared Memory Segment.

 EXAMPLE 2
Refer to shmat for an example that uses the functions shmat(),  shmctl(),  shmdt(), and  shmget() to establish an IPC Server using a Shared Memory Segment.

 EXAMPLE 3
This example is compiled using sascc370 -Krent -o. This program demonstrates the functions  shmget() and  shmstat(). It uses the  shmget() function to create IPC shared memory segment and then uses the  shmctl() function to retrieve statistics on the newly created memory segment.
 /*-------------------------------------+
| POSIX/UNIX header files              |
+-------------------------------------*/
#include <sys/types.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/ipc.h>

#include <sys/shm.h>

/*-------------------------------------+
| ISO/ANSI header files                |
+-------------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <time.h>

#include <errno.h

/*-------------------------------------+
| Types                                |
+-------------------------------------*/
/* shared memory segment structure */
typedef struct shmid_ds ShMemSeg;  

/*--------------------------------------+
| Constants                             |
+--------------------------------------*/
/* shared memory key                   */
#define SHM_KEY      (key_t)1097    

/* size of memory segment (bytes)      */
#define SHM_SIZE     (size_t)256    

/* give everyone read/write             */
/* permission to shared memory          */
#define SHM_PERM  (S_IRUSR|S_IWUSR
 |S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

/*--------------------------------------+
| Name:      main                       |
| Returns:   exit(EXIT_SUCCESS) or      |
|            exit(EXIT_FAILURE)         |
+--------------------------------------*/
int main()
{
/* shared memory segment id            */
    int shMemSegID;             

/* shared memory flags                 */
    int shmFlags;               

/* command to shared memory            */
    int shmCmd;                 

/* ptr to shared mem id structure      */
    ShMemSeg * shMemSeg;        

/*--------------------------------------*/
/* Create shared memory segment         */
/* Give everyone read/write permissions */
/*--------------------------------------*/
   shmFlags = IPC_CREAT | SHM_PERM;

if ( (shMemSegID = 
shmget(SHM_KEY, SHM_SIZE, shmFlags)) < 0 )
   {
       perror("SHMSTAT: shmget");
       exit(EXIT_FAILURE);
   }

/*-------------------------------------------*/
/* Allocate memory to store information      */
/* from shared memory seg                    */
/*-------------------------------------------*/
   shMemSeg = malloc(sizeof(ShMemSeg));

   if (shMemSeg == NULL)
   {
   fprintf(stderr,
   "ERROR: 
   Cannot allocate memory for 
   shared mem stats\n");
   exit(EXIT_FAILURE);
   }

/*---------------------------------------------*/
/* Call shmctl to retrieve information from    */
/* shared memory seg                           */
/*---------------------------------------------*/
   shmCmd = IPC_STAT;

   if (shmctl(shMemSegID, shmCmd, shMemSeg) < 0)
   {
   perror("SHMSTAT: shmctl failed to 
   retrieve shared mem stats");
   free(shMemSeg);
   exit(EXIT_FAILURE);
   }
 
/*---------------------------------------------*/
/* Print infomation retrieved from shared      */
/* memory segment                              */
/*---------------------------------------------*/
 printf("Shared Memory Segment statistics:\n\n");

 printf("\tSegment owner's effective user ID: 
   %d\n",(int)shMemSeg->shm_perm.uid);
 printf("\tSegment owner's effective group ID: 
   %d\n",(int)shMemSeg->shm_perm.gid);
 printf("\tSegment creator's effective user ID: 
   %d\n",(int)shMemSeg->shm_perm.cuid);
 printf("\tSegment creator's effective group ID: 
   %d\n",(int)shMemSeg->shm_perm.cgid);
 printf("\tSegment permission mode bits: 
   %#.3o\n\n",(int)shMemSeg->shm_perm.mode);

 printf("\tShared Memory Segment size: 
   %d\n",shMemSeg->shm_segsz);
 printf("\tProcess id of last Segment operation: 
   %d\n",(int)shMemSeg->shm_lpid);
 printf("\tProcess id of Segment creator: 
   %d\n",(int)shMemSeg->shm_cpid);
 printf("\tNumber of times Segment attached: 
   %u\n",shMemSeg->shm_nattch);
 printf("\tTime of last shmat call: 
   %s", ctime(&shMemSeg->shm_atime));
 printf("\tTime of last shmdt call: 
   %s", ctime(&shMemSeg->shm_dtime));
   printf("\tTime of last change: 
   %s", ctime(&shMemSeg->shm_ctime));

/*-------------------------------------------*/
/* Free memory used to store information     */
/* from shared memory seg                    */
/*-------------------------------------------*/
   free(shMemSeg);

/*---------------------------------------------*/
/* Call shmctl to remove shared memory segment */
/*---------------------------------------------*/
   shmCmd = IPC_RMID;

 if (shmctl(shMemSegID, shmCmd, NULL) < 0)
 {
    perror("SHMSTAT: 
    shmctl failed to remove shared mem");
    exit(EXIT_FAILURE);
   }
 
   exit(EXIT_SUCCESS);

}  /* end of main() */

RELATED FUNCTIONS
shmat,  shmctl,  shmdt


 

sigblkjmp

   Intercept longjmp without changing signal mask

SYNOPSIS
 #include <lcjmp.h>
int sigblkjmp(sigjmp_buf env);

DESCRIPTION
sigblkjmp requests interception of calls to  longjmp or  siglongjmp that could terminate the calling function. When you call  sigblkjmp, it always returns  0. If a call to  longjmp or  siglongjmp is later intercepted, the call to  sigblkjmp is resumed and upon completion returns the integer argument that was passed to  longjmp. The  env variable is modified to indicate the target of the intercepted call so it can be resumed by a call to  siglongjmp.  

Note:   When a siglongjmp call is intercepted due to the use of  sigblkjmp, the signal mask has not yet been changed.  [cautend]  

After a call to longjmp or  siglongjmp is intercepted,  sigblkjmp must be re-issued if continued interception is wanted.  

Because exit is implemented as a  longjmp to the caller of  main, you can use  sigblkjmp to intercept program exit.

 RETURN VALUE
sigblkjmp normally returns  0; it returns a non-zero value if a call to  longjmp or  siglongjmp has been intercepted (in which case  sigblkjmp returns the value of the second argument passed to  longjmp or  siglongjmp).

 CAUTION
Variables of storage class auto and  register whose values are changed between the  sigblkjmp and  siglongjmp calls have indeterminate values on return to  sigblkjmp.

 EXAMPLE
This example demonstrates how sigblkjmp can be used to enable a function to release resources even if terminated by a call to  longjmp or  siglongjmp in a function that  sigblkjmp calls: 

 #include <stdio.h>
#include <lcjmp.h>
#include <stdlib.h>
#include <lcsignal.h>

sigjmp_buf env;

static void get_resource(void), 
  use_resource(void);

int main()
{
  int code;
  if (code = sigsetjmp(env,1)) 
    goto escape;

  get_resource();
  puts("get_resource returned normally.");
  exit(0);

 escape:
  printf("Executing escape routine for ",
         "error %d\n", code);
  exit(code);
}

static void get_resource(void)
{
  int code;
  sigjmp_buf my_env;
  sigset_t blockall, oldset;

  sigfillset(&blockall);
  /* block all signals while allocating 
     and using resource */
  sigprocmask(SIG_SETMASK, &blockall, 
              &oldset);

  /* Allocate resource here */
  if (code = sigblkjmp(my_env)) 
    goto release;

  puts("Resources allocated.");
  /* Free resource here */
  use_resource();
  puts("use_resource returned normally, "
    "get_resource is freeing resources.");
  setprocmask(SIG_SETMASK, &oldset, NULL);
  return;
 release:

  printf("use_resource indicated ", 
         "error %d\n", code);
  puts("Resources now freed, proceeding ",
       "with longjmp.");
  siglongjmp(my_env, code);
}

static void use_resource(void)
{
  puts("Entering use_resource.");
  /* Attempt to use resource here. */
  puts("Error 3 detected, ",
       "calling siglongjmp.");
  siglongjmp(env, 3);
  puts("This statement will not ",
       "be executed.");
}

RELATED FUNCTIONS
blkjmp,  longjmp,  setjmp,  siglongjmp,  sigsetjmp


 

spawn

   Spawn a new process

SYNOPSIS
 #include <spawn.h>
pid_t spawn(const char *path, 
            int count, 
            const int fd_map[], 
            struct inheritance *inh, 
            const char *argv[], 
            const char *envp[]);

DESCRIPTION
The spawn function creates a new process to run an executable program in the hierarchical file system. If indicated by an environment variable, an attempt is made to execute the process in the same address space as the caller.  spawn permits the calling process to remap file descriptors, alter the signal handling, and change the process group of the new process. 

The path argument specifies the name of the HFS file to be executed. 

The count specifies the number of file descriptors to be remapped, and  fd_map specifies a list of file descriptors that describe the remapping. If  fd_map is  0, no remapping is performed, and the child process receives all file descriptors open in the current process. If  fd_map is not  0, then for n less than  count, file descriptor n in the child process is mapped to be the same file as  fd_map[n] in the parent process. If  fd_map[n] has the value  SPAWN_FDCLOSED, file descriptor n will be closed in the child process. All file descriptors greater than or equal to  count will be closed in the child process. 

The inh argument specifies a pointer to an inheritance structure which defines how signals and process groups should be handled in the child process. The inheritance structure contains the following fields:  

flags bit flags defining required inheritance options
pgroup an alternate process group for the new process
sigmask a new signal mask for the child process
sigdefault a set of signals to restore to default handling
ctlttyfd a controlling terminal file descriptor for the child process

 

The inheritance structure can be used to request the following inheritance options. 

If the SPAWN_SETGROUP flag is set in  inh->flags, the child's process group will be set as specified by  inh->pgroup. If  inh->pgroup is  0, the child will be created in a new process group. Otherwise, the new process will be assigned to the specified process group. If  SPAWN_SETGROUP is not set, the new process is part of the same process group as the parent. 

If the SPAWN_SETSIGDEF flag is set in  inh->flags, each signal specified in  inh->sigdefault (a value of type  sigset_t) is reset to default handling in the child process. All other signals inherit their handling from the parent process, as with the  exec functions. 

If the SPAWN_SETSIGDEF flag is not set, all signals inherit their handling from the parent in the manner of  exec. If the  SPAWN_SETSIGMASK flag is set in  inh->flags, the initial signal mask for the new child process is as specified by  inh->sigmask (a value of type  sigset_t). If the  SPAWN_SETSIGMASK flag is not set, the child process inherits the signal mask of the parent process.  

If the SPAWN_SETTCPGRP flag is set in  inh->flags, the file descriptor specified by  inh->ctlttyfd becomes the controlling terminal for the child process's foreground process group. If the  SPAWN_SETTCPGRP flag is not set, the child process inherits the controlling terminal file descriptor from the parent process. 

The argv argument to  spawn specifies a list of arguments to be passed to the new process.  argv is an array of strings, where  argv[0] contains the name of the executable file, and the final element of  argv is a  NULL pointer value. 

The envp argument to  spawn specifies an array of environment variable values. Each element of the array is a string of the form: 

var=value 

The last element of the array must be a NULL pointer to indicate the end of the array. If the new process should inherit the environment variables of the calling process, pass the external environment variable pointer  environ as  envp. 

Certain environment variables may be defined in the envp array to modify the operation of  spawn. These are as follows: 

If the environment variable _BPX_SHAREAS is defined and has the value  YES,  spawn will attempt to create the new process in the same address space as the parent address space.  

Note:   The spawn may be unable to use the same address space for security or performance reasons, in which case a new address space will be created for the process.  [cautend]  

Note:   When several processes run in a single address space, some requirements of the

 posix
standards are violated. (For instance, it is not possible for the child process to execute after termination of the parent in this case.)  [cautend] If _BPX_SHAREAS is not defined, or has any value other than  YES, the child process will be executed in a new address space. 

If the environment variable _BPX_SPAWN_SCRIPT is defined and set to  YES, the spawn service recognizes an attempt to use  spawn to invoke a shell script, and instead spawns a copy of the shell to run the script. If the environment variable is not defined, or has some value other than  YES, the script is treated as a non-executable file.

 RETURN VALUE
If successful, spawn returns the process id of the new process. If unsuccessful,  spawn returns  -1.

 USAGE NOTES
The spawn function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
 /* This example must be compiled 
   with the posix compiler option */

#include <spawn.h>
#include <unistd.h>
#include <signal.h>

/* posix environment variable ptr */
extern char **environ;

pid_t subprocess(const char *file,
                 int input_fd,
                 int output_fd,
                 int local)
{
  /* 
     This function uses the spawn system 
     call to create a subprocess. The 
     file descriptor specified by 
     input_fd is used as the new process' 
     standard input, and the file 
     descriptor specified by output_fd 
     is used as the new process' standard 
     output. If the flag local is non-zero, 
     the new process is created in the same 
     address space. If local is non-zero, 
     the process is created in a new address 
     space, and the signal SIGHUP is set to 
     be ignored in the new process.
   */

   /* file map for new process */
   int fd_map[3];

   /* inheritance structure */
   struct inheritance inh;

   /* argument vector for new process */
   const char *argv[2];

   /* old handler for SIGHUP */
   void (*hup_hndlr)(int);

   pid_t newpid;

   /* use input_fd as new stdin */
   fd_map[0] = input_fd;

   /* use output_fd as new stdout */
   fd_map[1] = output_fd;

   /* use same file for stderr */
   fd_map[2] = 2;

   inh.flags = SPAWN_SETSIGDEF;

   /* set all signals to default 
      in new process */
   sigfillset(inh.sigdefault);

   /* if spawning non-locally */
   if (local == 0) 
   {
      /* don't default SIGHUP */
      sigdelset(inh.sigdefault, SIGHUP);
      /* temporarily ignore SIGHUP */
      hup_hndlr = signal(SIGHUP, SIG_IGN);
   }

   setenv("_BPX_SHAREAS", 
          local? "YES": "NO");

   /* set up argv for new process, */
   argv[0] = file;

   /* no args */
   argv[1] = 0;

   /* spawn new procdess */
   newpid = spawn(file, 3, fd_map, &inh, 
                  argv, environ);

   /* restore SIGHUP handling 
      if necessary */
   if (local == 0)

      signal(SIGHUP, hup_hndlr);

   /* return id of new process */
   return newpid;
}

RELATED FUNCTIONS
execve,  fork,  oeattache,  spawnp


 

spawnp

   Spawn a new process

SYNOPSIS
 #include <spawn.h>
pid_t spawnp(const char *file, 
             int count, 
             const int fd_map[], 
             struct inheritance *inh, 
             const char *argv[], 
             const char *envp[]);

DESCRIPTION
The spawnp function creates a new process to run an executable program in the hierarchical file system. It performs the same functions as the  spawn function, except the path portion of the filename is optional. 

The file argument to  spawnp is the name of the HFS file to be executed. If the name includes path information, then the file is invoked exactly as specified. If no path information is specified, a search is made of the directories specified by the  PATH environment variable (as specified by the  envp argument) until an executable file of the specified name is located. 

All other arguments to spawnp are interpreted exactly like the corresponding argument to  spawn.

 RETURN VALUE
If successful, spawnp returns the process id of the new process. If unsuccessful,  spawnp returns  -1.

 USAGE NOTES
The spawnp function can only be used with MVS 5.2.2 or a later release.

 RELATED FUNCTIONS
execve,  fork,  oeattache,  spawn


 

tcgetsid

   Get session leader id for a process

SYNOPSIS
 #include <sys/types.h>
#include <termios.h>
pid_t tcgetsid(int fileDescriptor);

DESCRIPTION
The tcgetsid function returns the process group id of the session for which a specific file descriptor is the controlling terminal. The argument  fileDescriptor specifies the terminal file descriptor for which the information is required.

 RETURN VALUE
tcsetgid returns the process group id for the associated session, or  -1 if it fails (for instance, if the file associated with  fileDescriptor is not a controlling terminal).

 USAGE NOTES
The tcgetsid function can only be used with MVS 5.2.2 or a later release.

 EXAMPLE
This example is compiled using sascc370 -Krent -o. This program demonstrates the use of the Open Edition function  tcgetsid().
 /*----------------------------------+
| POSIX/UNIX header files           |
+----------------------------------*/
#include <sys/types.h>

#include <termios.h>

#include <errno.h>

/*----------------------------------+
| ISO/ANSI header files             |
+----------------------------------*/
#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

/*----------------------------------+
| Name:      main                   |
| Returns:   exit(EXIT_SUCCESS) or  |
|            exit(EXIT_FAILURE)     |
+----------------------------------*/
int main()
{
/* session leader id for stdin          */
   pid_t stdin_SID;           

/* session leader id for stdout         */
   pid_t stdout_SID;          

/* session leader id for stderr         */
   pid_t stderr_SID;          

/*----------------------------------------*/
/* Get the Session Leader ID for STDIN    */
/*----------------------------------------*/
printf("\nGet the Session Leader ID 
  for STDIN\n");

   stdin_SID = tcgetsid(STDIN_FILENO);

   /* Test for Error */
   if (stdin_SID == -1)
   {
   fprintf(stderr,"Could not get SID 
   for stdin\n");
   exit(EXIT_FAILURE);
   }
   else
   {
   printf(" The Session Leader ID 
   for stdin: %d\n", (int)stdin_SID);
   }

/*--------------------------------------------*/
/* Get the Session Leader ID for STDOUT       */
*---------------------------------------------*/
printf("\nGet the Session Leader ID for STDOUT\n");

   stdout_SID = tcgetsid(STDOUT_FILENO);

   /* Test for Error */
   if (stdout_SID == -1)
   {
   fprintf(stderr,"Could not get SID 
   for stdout\n");
      exit(EXIT_FAILURE);
   }
   else
   {
   printf("The Session Leader ID 
   for stdout: %d\n", (int)stdout_SID);
   }

/*---------------------------------------------*/
/* Get the Session Leader ID for STDERR        */
/*---------------------------------------------*/
printf
  ("\nGet the Session Leader ID for STDERR\n");

   stderr_SID = tcgetsid(STDERR_FILENO);

   /* Test for Error */
   if (stderr_SID == -1)
   {
   fprintf(stderr,"Could not get SID 
   for stderr\n");
   exit(EXIT_FAILURE);
   }
   else
   {
   printf("The Session Leader ID 
   for stderr: %d\n", (int)stderr_SID);
   }

   exit(EXIT_SUCCESS);

}  /* end of main() */

RELATED FUNCTIONS
getsid,  setsid,  tcgetpgrp


 

truncate

   Truncate an HFS file

SYNOPSIS
 #include <unistd.h>
int truncate(const char *pathname, 
             off_t length);

DESCRIPTION
truncate truncates or extends an OpenEdition file.  pathname specifies the name of the file.  length specifies the size of the file. If the length is greater than the current file size, zero bytes are added to the file at the end. 

For programs not compiled with the posix option, a style prefix may be required as part of the pathname. See "File Naming Conventions" in the SAS/C Library Reference, Volume 1, for further information.

 RETURN VALUE
truncate returns  0 if successful, or  -1 if unsuccessful.

 USAGE NOTES
The truncate function can only be used with MVS 5.2.2 or a later release.

 RELATED FUNCTIONS
ftruncate



Chapter Contents

Previous

Next

Top of Page

Copyright © Mon Mar 9 09:11:22 EST 1998 by SAS Institute Inc., Cary, NC, USA. All rights reserved.