************* BACK AND FORTH PAGING SUBROUTINE ************

PAGEFLOP

If they want to quit, do so
 If They want to quit subsession, Do SO!
  Decrement LOCAL and GLOBAL Page Counters

FORWARD

  Increment LOCAL and GLOBAL Page Counters
   *************** END PAGEFLOP *********************
  ****** CHAPTER INTERNAL SELECTOR ALGORITHM ******

SELECTOR

   Reset Local Page Counter

SELAGAIN

 CHECK IF ONLY A <CR>

WRONGSEL

YOUR SELECTION IS NOT IN THE 0 - #SELIMIT  RANGE  Please try again

AANVANG

Copyright CourseWare Technologies Inc., 1985-88


Lesson - 11


 THE UNIX SYSTEM INTERFACE 

P1

UNIX System Interface|Topics to Learn|11-0|10,45
  #                  Topic
 ---                -------
  1   -   The UNIX System interface
  2   -   Using Binary I/O Functions
  3   -   First Review
  4   -   More Binary I/O Functions
  5   -   Performing Random Access
  6   -   Performing Binary (Standard) I/O
  7   -   Second Review
  0   -   Return to the Main Menu

P2

UNIX System Interface|The UNIX System Interface|11-1.1|13,50
     Under UNIX the pathname of the standard C library
is included automatically during linking and is:

 /lib/libc.a 


     The standard I/O library has the pathname:

 /usr/include/stdio.h 

and must be included explicitly in your program with: 

 #include <stdio.h> 

P3

UNIX System Interface|The UNIX System Interface|11-1.2|9,54
     Until now, all of the I/O functions we have 
discussed performed operations on objects of type 
char only (or we used conversion specifiers).


     With buffered or high level I/O, the operating
system accesses or buffers the data from the files 
in single blocks, rather than in the number of bytes
allocated for the specified variable.

P4

UNIX System Interface|The UNIX System Interface|11-1.3|17,54
     Using binary I/O, one refers to the object by
specifying its size rather than its type.  Files 
that contain these objects may be referred to as 
binary files.

     All buffered I/O functions use binary I/O 
functions.

     In binary I/O there is no data buffering.

  *  Data is written directly into a file.
  *  The number of bytes requested = the number of bytes accessed.


     Under a UNIX operating system, the physical 
format of all files is alike.  It is the treatment of 
the data in the files that may be different.

P5

UNIX System Interface|Binary I/O Functions|11-2.1|16,54
     Most binary I/O under UNIX is performed using 
the following calls or functions:

     open()  opens a disk file for binary I/O

    close()  closes a file opened for binary I/O

    creat()  creates a file

   unlink()  deletes a file

     read()  reads a specified number of bytes from a file

    write()  writes a specified number of bytes to a file

    lseek()  random file access function

P6

UNIX System Interface|Binary I/O Functions|11-2.2|5,46
     Prior to using a file, it must be opened. 
The binary analog to fopen() is open().


    open() - Returns a -1 on a failure

P7

UNIX System Interface|Binary I/O Functions|11-2.3|14,54
Syntax:          f_d = open(file_name, rwmode);

where:

f_d is the value (of type int) that open() 
returns.  It is referred to as the file descriptor.

file_name is a character string constant which is the 
name of the file to be opened.

rwmode is the access mode which may have a value of:
                    0 - read access only
                    1 - write access only
                    2 - read and write access

P8

UNIX System Interface|Binary I/O Functions|11-2.4|7,48
     The complement to function open() is the 
function close(f_d), which closes the file with 
file descriptor f_d.


     close() returns 0 on success and -1 if it
failed to close the file.

P9

UNIX System Interface|Binary I/O Functions|11-2.5| 12 , 52
     To create a new file or rewrite an old one, use 
the function creat(), the syntax for which is:

f_d = creat(file_name, p_mode);

where:
          f_d  is the file descriptor of type int
    file_name  is the name of file to be created
       p_mode  is the protection mode for the file made
               up of octal specifier "0" plus nine bits

P10

UNIX System Interface|More Binary I/O Functions|11-4.1|15,54
  OCTAL      OWNER       GROUP       OTHERS
     0         XXX        XXX         XXX
               RWE        RWE         RWE

     In the table above, X = '0' OR '1'


     On failure, creat() returns -1.


     A successfully created file need not be opened 
explicitly for write.


   A file must be explicitly opened for read().

P11

UNIX System Interface|More Binary I/O Functions|11-4.2|13,54
   The complement of creat() is the function 
unlink(file_name), which removes file_name from
the system.


     Reading and writing is performed with the 
functions read() and write(), which return the 
number of bytes read or written on success and
-1 on failure.


     A 0 returned on read indicates the end of 
the file.

P12

UNIX System Interface|More Binary I/O Functions|11-4.3|7,54
Syntax for the read() and write() functions:

       n_read = read(f_d, rec_buf, size);
      n_write = write(f_d, rec_buf, size);

where:  rec_buf is the address of the buffer.

         size is the number of bytes to be read 
         or written.

P13

UNIX System Interface|More Binary I/O Functions|11-4.4|14,57
The following example shows a typical way to copy files 
using the system calls read() and write() rather than 
the character buffering functions we saw in Lesson 8.
Note that the buffer size is 512 characters or bytes, which
is assumed to be the block size for the system.  This 
number varies and is usually 1024 bytes or more on the 
systems under the Berkeley (BSD) version of UNIX.  The 
type of the buffer in this case is really irrelevant;
however, type char is the most logical since the size of
a character normally corresponds to 1 byte.  In situations 
where you will be reading an explicit structure, you 
should use the address of the structure as the address 
of the buffer.  All structure elements will get loaded 
with their values automatically.

P14

UNIX System Interface|More Binary I/O Functions|11-4.5|7,54
NOTE:  The destination file data_out was created with
protection 0110100100, i.e., -rw-r--r--.  The while
statement controls the copying process.  Notice that
BUFSIZE bytes are always requested.  BUFSIZE bytes may
or may not be read.  Since read() does return the
number of bytes read, i.e., bytes, only that number
of bytes is written into the destination file.

P15

UNIX System Interface|More Binary I/O Functions|11-4.6|13,55
/*  Copying the input file data_in to the output 
    file data_out.   The data will be specified 
    by size (binary) rather than type  */

    #define   BUFSIZE    512      /* 1 block of data */
    main()
    {
        int bytes;                   /* byte counter */
        char buf[BUFSIZE];            /* data buffer */
        int fd_in, fd_out;       /* file descriptors */

        /* OPEN INPUT FILE FOR READ */
        if ((fd_in = open("data_in", 0)) != -1) {

P16

UNIX System Interface|More Binary I/O Functions|11-4.7|15,57
/* Create output file for writing */

    if ((fd_out =    creat("data_out", 0644)) != -1)    {

        /*  Transfer data from the input file
        to the output file in 512 byte blocks */

        while((bytes = read(fd_in, buf, bufsize))    > 0)
        write(fd_out,    buf, bytes);

        close(fd_out);         /* close the output file */
    }
    close (fd_in);              /* close the input file */
    }
}

P17

UNIX System Interface|Performing Random Access|11-5.1|16,60
     Sequential file traversal is not very efficient.  Under
UNIX, the function call used for random access is lseek().

Syntax:     long lseek();
             lseek(f_d, offset, origin);

where:  f_d is the file descriptor
     offset is a signed long integer which specifies whether
            the seek is to be done from the beginning of the 
            file (origin = 0), the end of the file (origin = 2), 
            or the current position in the file (origin = 1)


   Upon successful completion, lseek() will return the 
resulting pointer location as measured in bytes from the 
beginning of the file.

P18

UNIX System Interface|Performing Random Access|11-5.2|14,51
    /* Random access arithmetic */

long int displacement;
int f_d;

lseek(f_d, 0L, 0);          /* move 0 bytes from the
                                begining of the file */
lseek(f_d, 0L, 2);         /* move 0 bytes from the
                                end of the file      */
lseek(f_d, -27L, 1); /* move 27 bytes backward from
                    the current position in the file */

lseek(f_d, displacement, 1); /* move displacement bytes
               from the current position in the file */

P19

UNIX System Interface|Performing Random Access|11-5.3|6,56
    The following operations produce incorrect results:

lseek(f_d, -10L,0);    /* trying to go backward from
                           the beginning of the file */
lseek(f_d, 7L, 2);      /* trying to go forward from
                                 the end of the file */

P20

UNIX System Interface|Performing Random Access|11-5.4|16,57
The following is a file version of an example we saw in 
Lesson 10.  Please note the following points.   The call 
lseek(f_d, 0L,2) will return the size of the file in 
bytes, (the number of bytes from the beginning to the 
end of the file).  When this number is divided by the 
structure size, ACCT_SIZE, that will give us the number 
of structures in the file.  The index limit is n-1, 
which is the upper limit for the binary search.  All 
displacements are scaled by ACCT_SIZE.  The read()
statement uses a pointer to a structure as a pointer
to a buffer - which makes all structure elements pop
into the right place, eliminating any conversions or
temporary buffering. The binary search algorithm is
otherwise identical to the simplest case with an array 
of integers.  Also note the advantage of binary I/O 
when one is dealing with large data objects.

P21

UNIX System Interface|Performing Random Access|11-5.5|13,54
/* Random access example */

/* Assume that one must supply a user id and a password 
   in order to log on to a system.  This system has a 
   file called userpass which contains the data on valid
   accounts.  This file is made up of records of the 
   following form:  */

typedef    struct {
    char user_id[21];                   /* user id */
    char password[16];       /* encrypted password */
    long date;          /* encoded expiration date */
} account;

P22

UNIX System Interface|Performing Random Access|11-5.6|7,57
/* Random Access Example (continued) */

/* The records are sorted using "user_id" as the keyword 
   and are stored in the file in ascending order.  The 
   following function will search the file for a matching 
   account and return TRUE if account exists, FALSE if it 
   doesn't.  NOTE:  The binary search algorithm is used.*/

P23

UNIX System Interface|Performing Random Access|11-5.7|17,54
/* Random Access Example (continued) */

#define  TRUE      1
#define  FALSE     0
#define  ACCT_SIZE sizeof (account)

validate(acct_rec, f_d)
  account *acct_rec;    /* pointer to user's acct */
  int f_d;             /* account file descriptor */
{
  account buffer;          /* account rec. buffer */
  long displ;                /* file displacement */
  int low, high, mid, cond;

  long lseek();        /* random seeking function */

  low = 0;

P24

UNIX System Interface|Performing Random Access|11-5.8|13,45
/* Random Access Example (continued) */

/* determine the number of accounts */
high = ((lseek(f_d, 0L, 2))/(ACCT_SIZE)) - 1;

while (low <= high) {
mid =    (low + high) / 2;
displ    = mid *    ACCT_SIZE;

/* Move file descriptor to next rec. */

if ((lseek(f_d, displ, 0)) ==    -1)
    break;

P25

UNIX System Interface|Performing Random Access|11-5.9|13,49
/* Random Access Example (continued) */

/*  Read the current acct. record  */

if ( read(f_d, &buffer, acct_size)
      == acct_size) {
    /* check validity */
    if ((cond    = strcmp(buffer.user_id,
      acct_rec->user_id))    < 0)
    high = mid - 1;
    else if (cond > 0)
    low =    mid + 1;
    else{  /* Check if password and date match */

P26

UNIX System Interface|Performing Random Access|11-5.10|16,49
/* Random Access Example (continued) */

      if ((strcmp(buffer.password,
            acct_rec->password) == 0) &&
            buffer.date >= acct_rec->date)
          return(TRUE);
      else
          return(FALSE);
    }
   }  /* read a record of wrong size, => error */
   else
      return(false);
   }
   /*  no match found return error code  */
   return(false);
}

P27

UNIX System Interface|Performing Binary Standard I/O|11-6.1|16,54
     Standard I/O files may be treated as binary files.


     The UNIX shell opens three files for every program it 
runs:

                                    file descriptor
   *  The standard input file              0

   *  The standard output file             1

   *  The standard error file              2


     Therefore, terminal I/O may as well be performed 
in binary format.

P28

UNIX System Interface|Performing Binary Standard I/O|11-6.2|17,58
The following is a binary version of the previous example.
The primary difference is the way the data is read.  All 
data is referred to by size.  The variables of type other 
than char must be converted prior to being stored 
in the corresponding variable.  The C library function 
atoi() does ascii-to-integer conversion; therefore, its 
argument must be properly terminated with a '\0'.  A 
subtle point which may cause some headaches is the reading
of a the newline character, read(0,buffer,1), in the function 
read_client().  Since the program assumes that there will be 
6 specialties, then 6 specialties columns must have data in 
them (blanks or X's).  A newline after the 3rd specialty 
or blanks after the 6th specialty will confuse the program 
and produce incorrect results.  It is a project for the 
student to improve the program and make it robust so it 
does not matter after which column the '\n' character 
is placed.

P29

UNIX System Interface|Performing Binary Standard I/O|11-6.3|11,54
/*         Professional Search Agency Problem
             Binary Standard I/O Version          */

#include <stdio.h>
               /* External declarations */
struct candidate {
  char id[51];                 /* name and tel. no */
  short salary;                   /* salary in $Ks */
  short experience;         /* years of experience */
  char specialties[6];  /* areas of specialization */
};

P30

UNIX System Interface|Performing Binary Standard I/O|11-6.4|15,57
/* Search Agency Problem--Binary Version (continued) */

main()
{
    struct candidate request, person;

    printf("\n\nThe following candidates meet");
    printf("The Requirements\n");
    if ((read_client(&request) != EOF))
       while ((read_client(&person) != eof))
          if  (compatible(&request, &person)) {
              write(1,person.id, 50);
              write(1,"\n",1);
          }
}

P31

UNIX System Interface|Performing Binary Standard I/O|11-6.5|18,54
/* Search Agency Problem--Binary Version (continued) */
read_client(client)               /* read client info. */
   struct candidate *client;
{  char buffer[3];
  /*    READ IDENTITY   */
  if    (read(0, client->id,50)    == 50) {
    /* THEN THERE IS A FULL RECORD */
    client->id[50] = '\0';
    /* READ CLIENT'S SALARY */
    read(0,    buffer,2); buffer[2] = '\0';
    client->salary = atoi(buffer);
    /* READ YEARS OF EXPERIENCE */
    read(0,    buffer,2); buffer[2] = '\0';
    client->experience = atoi(buffer);
    /* READ IN CLIENT'S SPECIALTIES */
    read(0,client->specialties,6);
    read(0,buffer,1);               /* read new line  */
    return(1); return(EOF);  }               }

P32

UNIX System Interface|Performing Binary Standard I/O|11-6.6|18,58
/* Search Agency Problem--Binary Version (continued) */
#define  TRUE       1
#define  FALSE   0
compatible(request, client)
    struct candidate *request, *client;
{
    int compat=false,    i;

    if (((client->salary - request->salary) <= 3) &&
       ((request->experience - client->experience) <= 2)){
       for (i=0; i < 6; i++)
          client->specialties[i]    == 'X')    {
          compat    = TRUE;
          break;
       }
    }
    return compat;
}

P33

UNIX System Interface|Performing Binary Standard I/O|11-6.7|14,57
/* Search Agency Problem--Binary Version (continued) */

/*  Note that the input must contain an entry for each 
    specialty, a blank or an "x", followed immediately
    by a newline.

                  /*** THE INPUT ****/
REQUEST                                        4810  X
Alex Anderson            (818) 279-1436        4408X X  X
Alice Jordan             (202) 347-9245        3604 XX
Michele Hopkins          (213) 319-3400        5214X X X
John Holdridge           (617) 236-1746        4711 X X X
Judy Boston              (619) 362-9867        4509X X
Richard Wilson           (408) 988-5249        4810XX

P34

UNIX System Interface|Performing Binary Standard I/O|11-6.8|8,54
/* Search Agency Problem--Binary Version (continued) */

/***          The OUTPUT          ***/

The following candidates meet the requirements:

Alex Anderson          (818) 279-1436
Judy Boston            (619) 362-9867