@@ -4,6 +4,10 @@ import type { PHPWorker } from './php-worker';
44import type { Remote } from './comlink-sync' ;
55import { logger } from '@php-wasm/logger' ;
66
7+ function wait ( ms : number ) : Promise < void > {
8+ return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
9+ }
10+
711/**
812 * An isomorphic proc_open() handler that implements typical shell in TypeScript
913 * without relying on a server runtime. It can be used in the browser and Node.js
@@ -142,7 +146,7 @@ export function sandboxedSpawnHandlerFactory(
142146 // Technical limitation of subprocesses – we need to
143147 // wait before exiting to give consumer a chance to read
144148 // the output.
145- await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
149+ await wait ( 10 ) ;
146150 processApi . exit ( 0 ) ;
147151 break ;
148152 }
@@ -151,22 +155,52 @@ export function sandboxedSpawnHandlerFactory(
151155 // Technical limitation of subprocesses – we need to
152156 // wait before exiting to give consumer a chance to read
153157 // the output.
154- await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
158+ await wait ( 10 ) ;
155159 processApi . exit ( 0 ) ;
156160 break ;
157161 }
158162 case 'rm' : {
159163 const target = args [ args . length - 1 ] ;
164+ const flags = args . slice ( 1 , - 1 ) . join ( ' ' ) ;
165+
166+ if ( args . length < 2 || target . startsWith ( '-' ) ) {
167+ processApi . stderr ( 'usage: rm [-rf] file\n' ) ;
168+ // Technical limitation of subprocesses – we need to
169+ // wait before exiting to give consumer a chance to read
170+ // the output.
171+ await wait ( 10 ) ;
172+ processApi . exit ( 1 ) ;
173+ break ;
174+ }
175+
176+ const isRecursive = flags . includes ( 'r' ) ;
177+ const isForce = flags . includes ( 'f' ) ;
178+
179+ let errorMessage = '' ;
180+
160181 if ( await php . isDir ( target ) ) {
161- await php . rmdir ( target , { recursive : true } ) ;
182+ if ( isRecursive ) {
183+ await php . rmdir ( target , { recursive : true } ) ;
184+ } else {
185+ errorMessage = `rm: cannot remove '${ target } ': Is a directory\n` ;
186+ }
162187 } else if ( await php . isFile ( target ) ) {
163188 await php . unlink ( target ) ;
164189 }
165- // Technical limitation of subprocesses – we need to
166- // wait before exiting to give consumer a chance to read
167- // the output.
168- await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
169- processApi . exit ( 0 ) ;
190+ // Target doesn't exist and -f flag is not set
191+ else if ( ! isForce ) {
192+ errorMessage = `rm: cannot remove '${ target } ': No such file or directory\n` ;
193+ }
194+
195+ if ( errorMessage ) {
196+ processApi . stderr ( errorMessage ) ;
197+ // Technical limitation of subprocesses – we need to
198+ // wait before exiting to give consumer a chance to read
199+ // the output.
200+ await wait ( 10 ) ;
201+ }
202+
203+ processApi . exit ( errorMessage ? 1 : 0 ) ;
170204 break ;
171205 }
172206 }
0 commit comments