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 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 FILE_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 
43 static int monojob_rc;
44 
45 static void monojob_close ( struct interface *intf, int rc ) {
46  monojob_rc = rc;
47  intf_restart ( intf, rc );
48 }
49 
52 };
53 
56 
58 
59 /**
60  * Clear previously displayed message
61  *
62  * @v len Length of previously displayed message
63  */
64 static 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  */
82 int 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;
163  monojob_close ( &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 }
An object interface operation.
Definition: interface.h:18
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
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
static struct interface_descriptor monojob_intf_desc
Definition: monojob.c:54
#define TICKS_PER_SEC
Number of ticks per second.
Definition: timer.h:16
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:465
int monojob_wait(const char *string, unsigned long timeout)
Wait for single foreground job to complete.
Definition: monojob.c:82
Error codes.
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition: interface.h:218
iPXE timers
#define INTF_DESC_PURE(operations)
Define an object interface descriptor for a pure-interface object.
Definition: interface.h:116
#define ECANCELED
Operation canceled.
Definition: errno.h:344
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
Single foreground job.
An object interface.
Definition: interface.h:125
unsigned long total
Total operation size.
Definition: job.h:31
ring len
Length.
Definition: dwmac.h:231
#define CTRL_C
Definition: keys.h:21
unsigned long completed
Amount of operation completed so far.
Definition: job.h:24
struct interface monojob
Definition: monojob.c:57
static struct interface_operation monojob_intf_op[]
Definition: monojob.c:50
User interaction.
#define EINPROGRESS
Operation in progress.
Definition: errno.h:419
An object interface descriptor.
Definition: interface.h:56
int getchar(void)
Read a single character from any console.
Definition: console.c:86
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
Job progress.
Definition: job.h:16
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:33
Processes.
static void monojob_close(struct interface *intf, int rc)
Definition: monojob.c:45
Job control interfaces.
char message[32]
Message (optional)
Definition: job.h:33
static int monojob_rc
Definition: monojob.c:43
Key definitions.
void step(void)
Single-step a single process.
Definition: process.c:99
int job_progress(struct interface *intf, struct job_progress *progress)
Get job progress.
Definition: job.c:44
static void monojob_clear(size_t len)
Clear previously displayed message.
Definition: monojob.c:64
void timeout(int)
unsigned long currticks(void)
Get current system time in ticks.
Definition: timer.c:43
int putchar(int character)
Write a single character to each console device.
Definition: console.c:29
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:670
String functions.
int iskey(void)
Check for available input on any console.
Definition: console.c:131
union @391 key
Sense key.
Definition: scsi.h:18
FILE_SECBOOT(PERMITTED)