iPXE
monojob.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <string.h>
28#include <stdio.h>
29#include <errno.h>
30#include <ipxe/process.h>
31#include <ipxe/console.h>
32#include <ipxe/keys.h>
33#include <ipxe/job.h>
34#include <ipxe/monojob.h>
35#include <ipxe/timer.h>
36
37/** @file
38 *
39 * Single foreground job
40 *
41 */
42
43static int monojob_rc;
44
45static void monojob_close ( struct interface *intf, int rc ) {
46 monojob_rc = rc;
47 intf_restart ( intf, rc );
48}
49
53
56
58
59/**
60 * Clear previously displayed message
61 *
62 * @v len Length of previously displayed message
63 */
64static void monojob_clear ( size_t len ) {
65 unsigned int i;
66
67 for ( i = 0 ; i < len ; i++ )
68 putchar ( '\b' );
69 for ( i = 0 ; i < len ; i++ )
70 putchar ( ' ' );
71 for ( i = 0 ; i < len ; i++ )
72 putchar ( '\b' );
73}
74
75/**
76 * Wait for single foreground job to complete
77 *
78 * @v string Job description to display, or NULL to be silent
79 * @v timeout Timeout period, in ticks (0=indefinite)
80 * @ret rc Job final status code
81 */
82int monojob_wait ( const char *string, unsigned long timeout ) {
83 struct job_progress progress;
84 unsigned long last_check;
85 unsigned long last_progress;
86 unsigned long last_display;
87 unsigned long now;
88 unsigned long elapsed;
89 unsigned long completed = 0;
90 unsigned long scaled_completed;
91 unsigned long scaled_total;
92 unsigned int percentage;
93 size_t clear_len = 0;
94 int ongoing_rc;
95 int key;
96 int rc;
97
98 if ( string )
99 printf ( "%s...", string );
101 last_check = last_progress = last_display = currticks();
102 while ( monojob_rc == -EINPROGRESS ) {
103
104 /* Allow job to progress */
105 step();
106 now = currticks();
107
108 /* Continue until a timer tick occurs (to minimise
109 * time wasted checking for progress and keypresses).
110 */
111 elapsed = ( now - last_check );
112 if ( ! elapsed )
113 continue;
114 last_check = now;
115
116 /* Check for keypresses */
117 if ( iskey() ) {
118 key = getchar();
119 if ( key == CTRL_C ) {
121 break;
122 }
123 }
124
125 /* Monitor progress */
126 ongoing_rc = job_progress ( &monojob, &progress );
127
128 /* Reset timeout if progress has been made */
129 if ( completed != progress.completed )
130 last_progress = now;
131 completed = progress.completed;
132
133 /* Check for timeout, if applicable */
134 elapsed = ( now - last_progress );
135 if ( timeout && ( elapsed >= timeout ) ) {
136 monojob_rc = ( ongoing_rc ? ongoing_rc : -ETIMEDOUT );
137 break;
138 }
139
140 /* Display progress, if applicable */
141 elapsed = ( now - last_display );
142 if ( string && ( elapsed >= TICKS_PER_SEC ) ) {
143 monojob_clear ( clear_len );
144 /* Normalise progress figures to avoid overflow */
145 scaled_completed = ( progress.completed / 128 );
146 scaled_total = ( progress.total / 128 );
147 if ( scaled_total ) {
148 percentage = ( ( 100 * scaled_completed ) /
149 scaled_total );
150 clear_len = printf ( "%3d%%", percentage );
151 } else {
152 printf ( "." );
153 clear_len = 0;
154 }
155 if ( progress.message[0] ) {
156 clear_len += printf ( " [%s]",
157 progress.message );
158 }
159 last_display = now;
160 }
161 }
162 rc = monojob_rc;
164
165 monojob_clear ( clear_len );
166 if ( string ) {
167 if ( rc ) {
168 printf ( " %s\n", strerror ( rc ) );
169 } else {
170 printf ( " ok\n" );
171 }
172 }
173
174 return rc;
175}
union @162305117151260234136356364136041353210355154177 key
Sense key.
Definition scsi.h:3
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
int getchar(void)
Read a single character from any console.
Definition console.c:86
int iskey(void)
Check for available input on any console.
Definition console.c:131
int putchar(int character)
Write a single character to each console device.
Definition console.c:29
void timeout(int)
ring len
Length.
Definition dwmac.h:226
Error codes.
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define EINPROGRESS
Operation in progress.
Definition errno.h:419
#define ECANCELED
Operation canceled.
Definition errno.h:344
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
User interaction.
iPXE timers
#define TICKS_PER_SEC
Number of ticks per second.
Definition timer.h:16
String functions.
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
#define INTF_DESC_PURE(operations)
Define an object interface descriptor for a pure-interface object.
Definition interface.h:116
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition interface.h:218
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
int job_progress(struct interface *intf, struct job_progress *progress)
Get job progress.
Definition job.c:44
Job control interfaces.
Key definitions.
#define CTRL_C
Definition keys.h:21
struct interface monojob
Definition monojob.c:57
static struct interface_descriptor monojob_intf_desc
Definition monojob.c:54
static struct interface_operation monojob_intf_op[]
Definition monojob.c:50
static void monojob_close(struct interface *intf, int rc)
Definition monojob.c:45
int monojob_wait(const char *string, unsigned long timeout)
Wait for single foreground job to complete.
Definition monojob.c:82
static void monojob_clear(size_t len)
Clear previously displayed message.
Definition monojob.c:64
static int monojob_rc
Definition monojob.c:43
Single foreground job.
void step(void)
Single-step a single process.
Definition process.c:99
Processes.
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
An object interface.
Definition interface.h:125
Job progress.
Definition job.h:16
unsigned long total
Total operation size.
Definition job.h:31
char message[32]
Message (optional)
Definition job.h:33
unsigned long completed
Amount of operation completed so far.
Definition job.h:24
unsigned long currticks(void)
Get current system time in ticks.
Definition timer.c:43
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition vsprintf.c:465