forked from gdamore/less-fork
-
Notifications
You must be signed in to change notification settings - Fork 0
/
os.c
executable file
·140 lines (124 loc) · 2.57 KB
/
os.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
* Copyright (C) 1984-2012 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
*
* For more information, see the README file.
*/
/*
* Modified for use with illumos.
* Copyright 2014 Garrett D'Amore <garrett@damore.org>
*/
/*
* Operating system dependent routines.
*
* Most of the stuff in here is based on Unix, but an attempt
* has been made to make things work on other operating systems.
* This will sometimes result in a loss of functionality, unless
* someone rewrites code specifically for the new operating system.
*
* The makefile provides defines to decide whether various
* Unix features are present.
*/
#include "less.h"
#include <signal.h>
#include <setjmp.h>
#include <time.h>
#include <errno.h>
int reading;
static jmp_buf read_label;
extern int sigs;
/*
* Like read() system call, but is deliberately interruptible.
* A call to intread() from a signal handler will interrupt
* any pending iread().
*/
int
iread(int fd, unsigned char *buf, unsigned int len)
{
int n;
sigset_t mask;
start:
if (_setjmp(read_label)) {
/*
* We jumped here from intread.
*/
reading = 0;
sigemptyset(&mask);
sigprocmask(SIG_SETMASK, &mask, NULL);
return (READ_INTR);
}
flush();
reading = 1;
n = read(fd, buf, len);
reading = 0;
if (n < 0) {
/*
* Certain values of errno indicate we should just retry the
* read.
*/
if (errno == EINTR)
goto start;
if (errno == EAGAIN)
goto start;
return (-1);
}
return (n);
}
/*
* Interrupt a pending iread().
*/
void
intread(void)
{
_longjmp(read_label, 1);
}
/*
* Return the current time.
*/
long
get_time(void)
{
time_t t;
(void) time(&t);
return (t);
}
/*
* errno_message: Return an error message based on the value of "errno".
*/
char *
errno_message(char *filename)
{
return (easprintf("%s: %s", filename, strerror(errno)));
}
static off_t
muldiv(off_t val, off_t num, off_t den)
{
double v = (((double)val) * num) / den;
return ((off_t)(v + 0.5));
}
/*
* Return the ratio of two off_t, as a percentage.
* {{ Assumes a off_t is a long int. }}
*/
int
percentage(off_t num, off_t den)
{
return ((int)muldiv(num, (off_t)100, den));
}
/*
* Return the specified percentage of a off_t.
*/
off_t
percent_pos(off_t pos, int percent, long fraction)
{
/*
* Change percent (parts per 100) to perden
* (parts per NUM_FRAC_DENOM).
*/
off_t perden = (percent * (NUM_FRAC_DENOM / 100)) + (fraction / 100);
if (perden == 0)
return (0);
return (muldiv(pos, perden, (off_t)NUM_FRAC_DENOM));
}