home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
c
/
clock345.zip
/
IOCTL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-07
|
17KB
|
559 lines
/*****************************************************************************/
/* THE FOLLOWING PROGRAM IS THE SOLE PROPERTY OF */
/* RONALD Q. SMITH */
/* CONTAINING HIS PROPRIETARY CONFIDENTIAL INFORMATION */
/* COPYRIGHT RONALD Q. SMITH 1992 */
/*****************************************************************************/
/* Global data definitions */
#include <dos.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include <stdlib.h>
#include <string.h>
#include <ioctl.h>
/* Function prototypes */
static int ioctl_write(void * data, int length);
static int ioctl_read(void * data, int length);
static int open_clock(void);
/* Global static variables */
static unsigned int handle = 0;
static unsigned char password[8] = "";
/*
PROCEDURE: connec
connec changes the value of the CONNECTED flag in CLOCK.SYS. Values supported
are:
0 = disconnected
1 = connected for writes only (default)
2 = connected for writes and periodic reads
3 = connected for all operations
INTERFACE:
status = connec(&connected);
"connected" is the new value of the connected flag.
"status" is zero if the operation succeeds. It is the DOS
error code if the operation fails. Likely values are:
1 = Not CLOCK.SYS
5 = Incorrect password
6 = Unable to obtain handle for CLOCK$
0xD = Illegal value for connected
-1 = Internal error
*/
extern int pascal far connec(int *connect)
{
auto struct {
int function;
int connect;
} connect_data;
auto int status;
/* Copy data to be sent to local storage. */
connect_data.function = 1; /* Set CONNECT */
connect_data.connect = *connect;
/* Check for legal values. */
if (connect_data.connect > 3)
return(0xD);
/* Write new value. */
status = ioctl_write(&connect_data, sizeof connect_data);
return ((status == sizeof connect_data) ? 0 : ((status < 0) ?
-status : -1));
}
/*
PROCEDURE: stzone
stzone sets the time zone offsets and the time zone name.
INTERFACE:
status = stzone(&hour, &minute, &second, zone);
"hour:minute:second" is the difference in time between UTC and
local time. The values are positive West of Greenwich and
negative East.
"zone" is a character string containing the local time zone name.
It must be LJSF (Left Justified, Space Filled) or LJNT (Left
Justified, NULL Terminated). It must be no more than 32
characters in length.
"status" is zero if the operation succeeds. It is the DOS
error code if the operation fails. Likely values are:
1 = Not CLOCK.SYS
5 = Incorrect password
6 = Unable to obtain handle for CLOCK$
0xD = Illegal value for offset
-1 = Internal error
*/
extern int pascal far stzone(int *std_hour, int *std_minute, int *std_second,
unsigned char std_name[32], int *day_hour, int *day_minute,
int *day_second, unsigned char day_name[32])
{
auto struct {
int function;
struct time_zone standard;
struct time_zone daylight;
} zone_data;
auto int status;
auto char *zone_loc;
/* Copy values to local storage. LJSF zones. */
zone_data.function = 2;
zone_data.standard.offs.hour = *std_hour;
zone_data.standard.offs.minute = *std_minute;
zone_data.standard.offs.second = *std_second;
memcpy(zone_data.standard.zone, std_name, sizeof zone_data.standard.zone);
zone_data.daylight.offs.hour = *day_hour;
zone_data.daylight.offs.minute = *day_minute;
zone_data.daylight.offs.second = *day_second;
memcpy(zone_data.daylight.zone, day_name, sizeof zone_data.daylight.zone);
/* Check for legal offset values. */
if ((abs(zone_data.standard.offs.hour) > 23) ||
(abs(zone_data.standard.offs.minute) > 59) ||
(abs(zone_data.standard.offs.second) > 59) ||
(abs(zone_data.daylight.offs.hour) > 23) ||
(abs(zone_data.daylight.offs.minute) > 59) ||
(abs(zone_data.daylight.offs.second) > 59))
{
return(0xD);
}
/* Write new values to CLOCK.SYS */
status = ioctl_write(&zone_data, sizeof zone_data);
return ((status == sizeof zone_data) ? 0 : ((status < 0) ?
-status : -1));
}
/*
PROCEDURE: stmode
stmode sets a new value for the mode flag.
INTERFACE:
status = stmode(&mode);
"mode" is the new value for the mode flag. The "mode" flag
contains a set of bits which may be set in any combination.
"status" is zero if the operation succeeds. It is the DOS
error code if the operation fails. Likely values are:
1 = Not CLOCK.SYS
5 = Incorrect password
6 = Unable to obtain handle for CLOCK$
0xD = Illegal value for mode
-1 = Internal error
*/
extern int pascal far stmode(struct modes *mode)
{
auto struct {
int function;
struct modes mode;
} mode_data;
auto int status;
/* Copy values to local storage. */
mode_data.function = 3;
mode_data.mode = *mode;
/* Write new value to CLOCK.SYS */
status = ioctl_write(&mode_data, sizeof mode_data);
return ((status == sizeof mode_data) ? 0 : ((status < 0) ?
-status : -1));
}
/*
PROCEDURE: rstrct
rstrct sets the time restriction limit values.
INTERFACE:
status = rstrct(&back_hour, &back_minute, &back_second, &forward_hour,
&forward_minute, &forward_second);
"back_hour:back_minute:back_second" is the new limit on backward
time changes. All values must be positive and less than or
equal to 23:59:59.
"forward_hour:forward_minute:forward_second" is the new limit on
forward time changes. All values must be positive and less than
or equal to 23:59:59.
"status" is zero if the operation succeeds. It is the DOS
error code if the operation fails. Likely values are:
1 = Not CLOCK.SYS
5 = Incorrect password
6 = Unable to obtain handle for CLOCK$
0xD = Illegal value for limits
-1 = Internal error
*/
extern int pascal far rstrct(int *back_hour, int *back_minute,
int *back_second, int *forward_hour, int *forward_minute,
int *forward_second)
{
auto struct {
int function;
int back_hour;
int back_minute;
int back_second;
int forward_hour;
int forward_minute;
int forward_second;
} rstrct_data;
auto int status;
/* Copy values to local storage. */
rstrct_data.function = 4;
rstrct_data.back_hour = *back_hour;
rstrct_data.back_minute = *back_minute;
rstrct_data.back_second = *back_second;
rstrct_data.forward_hour = *forward_hour;
rstrct_data.forward_minute = *forward_minute;
rstrct_data.forward_second = *forward_second;
/* Check values for legal limits. */
if ((rstrct_data.back_hour < 0) || (rstrct_data.back_hour > 23) ||
(rstrct_data.back_minute < 0) || (rstrct_data.back_minute > 59) ||
(rstrct_data.back_second < 0) || (rstrct_data.back_second > 59) ||
(rstrct_data.forward_hour < 0) || (rstrct_data.forward_hour > 23) ||
(rstrct_data.forward_minute < 0) || (rstrct_data.forward_minute > 59)
|| (rstrct_data.forward_second < 0) ||
(rstrct_data.forward_second > 59))
{
return(0xD);
}
/* Write new values to CLOCK.SYS */
status = ioctl_write(&rstrct_data, sizeof rstrct_data);
return ((status == sizeof rstrct_data) ? 0 : ((status < 0) ?
-status : -1));
}
/*
PROCEDURE: tdisp
tdisp sets the time display cursor location. The mode to enable the display
must be set separately with stmode.
INTERFACE:
status = tdisp(&disp_x, &disp_y, &attribute);
"disp_x" is the screen x coordinate in character positions of
the left-most character of the time display. The value must be
positive and less than 256.
"disp_y" is the screen y coordinate in lines of the time display.
The value must be positive and less than 256.
"attribute" is the screen attribute to be used for the display.
The value must be less than 256 and the low-order three bits of
each nybble must not be equal.
"status" is zero if the operation succeeds. It is the DOS
error code if the operation fails. Likely values are:
1 = Not CLOCK.SYS
5 = Incorrect password
6 = Unable to obtain handle for CLOCK$
0xD = Illegal value for tdisp
-1 = Internal error
*/
extern int pascal far tdisp(int *disp_x, int *disp_y, int *attribute)
{
auto struct {
int function;
int disp_x;
int disp_y;
int attribute;
} tdisp_data;
auto int status;
/* Copy values to local storage. */
tdisp_data.function = 5;
tdisp_data.disp_x = *disp_x;
tdisp_data.disp_y = *disp_y;
tdisp_data.attribute = *attribute;
/* Check values for ranges. */
if ((tdisp_data.disp_x < 0) || (tdisp_data.disp_x > 255) ||
(tdisp_data.disp_y < 0) || (tdisp_data.disp_y > 255) ||
(tdisp_data.attribute < 0) || (tdisp_data.attribute > 255) ||
((tdisp_data.attribute & 7) == ((tdisp_data.attribute >> 4) & 7)))
{
return(0xD);
}
/* Write new values to CLOCK.SYS */
status = ioctl_write(&tdisp_data, sizeof tdisp_data);
return ((status == sizeof tdisp_data) ? 0 : ((status < 0) ?
-status : -1));
}
/*
PROCEDURE: setpw
setpw sets the password to be used on all future operations to change the
CLOCK.SYS values. setpw must be called with the correct password prior to
any operation after password checking is enabled. If password checking is
not enabled, setpw is not required.
INTERFACE:
setpw(pword);
"pword" is an 8-character array containing the password to
be used. It must be LJSF or LJNF (Left Justified, NULL Filled).
*/
extern void pascal far setpw(unsigned char *pword)
{
/* Copy the password to local storage for use on later calls. */
memcpy(password, pword, sizeof password);
}
/*
PROCEDURE: newpw
newpw sets a new password into CLOCK.SYS. This new password is immediately
effective. newpw also copies the new password to local storage as the current
password if the operation of setting it in CLOCK.SYS is successful.
INTERFACE:
status = newpw(pword);
"pword" is the new password. It must be exactly 8 characters in
length. It may be LJSF or LJNF.
"status" is zero if the operation succeeds. It is the DOS
error code if the operation fails. Likely values are:
1 = Not CLOCK.SYS
5 = Incorrect password
6 = Unable to obtain handle for CLOCK$
-1 = Internal error
*/
extern int pascal far newpw(unsigned char *pword)
{
auto struct {
int function;
unsigned char pword[sizeof password];
} newpw_data;
auto int status;
/* Copy the values to local storage. */
newpw_data.function = 6;
memcpy(newpw_data.pword, pword, sizeof password);
/* Set the new password in CLOCK.SYS */
status = ioctl_write(&newpw_data, sizeof newpw_data);
/* If everything OK, copy the new password to the current password. */
if (status == sizeof newpw_data)
{
memcpy(password, pword, sizeof password);
return(0);
}
return ((status < 0) ? -status : -1);
}
/*
PROCEDURE: clksta
clksta gets the current state of CLOCK.SYS.
INTERFACE:
status = clksta(&data);
"data" is a structure that will contain the returned information.
"status" is the number of bytes read or the negative of the DOS
error status if an error occurs.
*/
extern int pascal far clksta(struct CLOCK_DATA *data)
{
return(ioctl_read(data, sizeof (struct CLOCK_DATA)));
}
/****************************************************************************/
/* INTERNAL FUNCTIONS */
/****************************************************************************/
/*
PROCEDURE: ioctl_write
ioctl_write performs a "Send Control Data to Character Device" function.
INTERFACE:
status = ioctl_write(data, length);
"data" is an array of "length" bytes.
"length" is the number of bytes to be sent.
"status" is the number of bytes accepted by the device or the negative
of _doserrno if an error occurs.
*/
static int ioctl_write(void * data, int length)
{
auto union REGS regs;
auto unsigned char send_data[200]; /* Leave room for growth */
/* If file for CLOCK$ not open, open it. */
if (!handle)
{
if (open_clock() <= 0)
return(-_doserrno);
}
/* Copy password and caller's data to same area to send. */
memcpy(send_data, password, sizeof password);
memcpy(&send_data[sizeof password], data, length);
regs.x.ax = 0x4403; /* IOCTL Send Control Data */
regs.x.bx = handle;
regs.x.cx = length + sizeof password;
regs.x.dx = (int) send_data; /* Send data bytes */
intdos(®s, ®s);
return(regs.x.cflag ? -_doserrno : regs.x.ax - sizeof password);
}
/*
PROCEDURE: ioctl_read
ioctl_read performs a "Read Control Data from Character Device" function.
INTERFACE:
status = ioctl_read(data, length);
"data" is an array of "length" bytes to receive the information.
"length" is the number of bytes to be read.
"status" is the number of bytes returned by the device or
is the negative of the DOS error status if an error occurs.
*/
static int ioctl_read(void * data, int length)
{
auto union REGS regs;
/* If file for CLOCK$ not open, open it. */
if (!handle)
{
if (open_clock() <= 0)
return(-_doserrno);
}
regs.x.ax = 0x4402; /* IOCTL Read Control Data */
regs.x.bx = handle;
regs.x.cx = length;
regs.x.dx = (int) data; /* Read data bytes */
intdos(®s, ®s);
return(regs.x.cflag ? -_doserrno : regs.x.ax);
}
/*
PROCEDURE: open_clock
"open_clock" opens a file handle for the CLOCK$ device.
INTERFACE:
open_clock();
open_clock returns the file handle or the value -1 if
unable to establish a handle.
*/
static int open_clock(void)
{
return(handle = open("CLOCK$",O_RDWR));
}
/*****************************************************************************/
/* THE PRECEDING PROGRAM IS THE SOLE PROPERTY OF */
/* RONALD Q. SMITH */
/* CONTAINING HIS PROPRIETARY CONFIDENTIAL INFORMATION */
/* COPYRIGHT RONALD Q. SMITH 1992 */
/*****************************************************************************/