Mailing List Archive

Patch: sysopen()
Here's sysopen(), which is fairly like POSIX::open() except that its
interface is much more open()-like. (It takes a filehandle as its
first parameter instead of returning a file descriptor number.)

With this function, in combination with the Fcntl module, we can have
three-parameter open without involving POSIX. Yeah!

Share and enjoy.

(PS: If you get patch rejections on opcode.h or keywords.h, just
regenterate them by running "perl opcode.pl" or "perl keywords.pl",
respectively.)

Index: keywords.h
***************
*** 209,244 ****
#define KEY_symlink 208
#define KEY_syscall 209
! #define KEY_sysread 210
! #define KEY_system 211
! #define KEY_syswrite 212
! #define KEY_tell 213
! #define KEY_telldir 214
! #define KEY_tie 215
! #define KEY_tied 216
! #define KEY_time 217
! #define KEY_times 218
! #define KEY_tr 219
! #define KEY_truncate 220
! #define KEY_uc 221
! #define KEY_ucfirst 222
! #define KEY_umask 223
! #define KEY_undef 224
! #define KEY_unless 225
! #define KEY_unlink 226
! #define KEY_unpack 227
! #define KEY_unshift 228
! #define KEY_untie 229
! #define KEY_until 230
! #define KEY_use 231
! #define KEY_utime 232
! #define KEY_values 233
! #define KEY_vec 234
! #define KEY_wait 235
! #define KEY_waitpid 236
! #define KEY_wantarray 237
! #define KEY_warn 238
! #define KEY_while 239
! #define KEY_write 240
! #define KEY_x 241
! #define KEY_xor 242
! #define KEY_y 243
--- 209,245 ----
#define KEY_symlink 208
#define KEY_syscall 209
! #define KEY_sysopen 210
! #define KEY_sysread 211
! #define KEY_system 212
! #define KEY_syswrite 213
! #define KEY_tell 214
! #define KEY_telldir 215
! #define KEY_tie 216
! #define KEY_tied 217
! #define KEY_time 218
! #define KEY_times 219
! #define KEY_tr 220
! #define KEY_truncate 221
! #define KEY_uc 222
! #define KEY_ucfirst 223
! #define KEY_umask 224
! #define KEY_undef 225
! #define KEY_unless 226
! #define KEY_unlink 227
! #define KEY_unpack 228
! #define KEY_unshift 229
! #define KEY_untie 230
! #define KEY_until 231
! #define KEY_use 232
! #define KEY_utime 233
! #define KEY_values 234
! #define KEY_vec 235
! #define KEY_wait 236
! #define KEY_waitpid 237
! #define KEY_wantarray 238
! #define KEY_warn 239
! #define KEY_while 240
! #define KEY_write 241
! #define KEY_x 242
! #define KEY_xor 243
! #define KEY_y 244

Index: opcode.h
*************** typedef enum {
*** 212,354 ****
OP_PRTF, /* 205 */
OP_PRINT, /* 206 */
! OP_SYSREAD, /* 207 */
! OP_SYSWRITE, /* 208 */
! OP_SEND, /* 209 */
! OP_RECV, /* 210 */
! OP_EOF, /* 211 */
! OP_TELL, /* 212 */
! OP_SEEK, /* 213 */
! OP_TRUNCATE, /* 214 */
! OP_FCNTL, /* 215 */
! OP_IOCTL, /* 216 */
! OP_FLOCK, /* 217 */
! OP_SOCKET, /* 218 */
! OP_SOCKPAIR, /* 219 */
! OP_BIND, /* 220 */
! OP_CONNECT, /* 221 */
! OP_LISTEN, /* 222 */
! OP_ACCEPT, /* 223 */
! OP_SHUTDOWN, /* 224 */
! OP_GSOCKOPT, /* 225 */
! OP_SSOCKOPT, /* 226 */
! OP_GETSOCKNAME, /* 227 */
! OP_GETPEERNAME, /* 228 */
! OP_LSTAT, /* 229 */
! OP_STAT, /* 230 */
! OP_FTRREAD, /* 231 */
! OP_FTRWRITE, /* 232 */
! OP_FTREXEC, /* 233 */
! OP_FTEREAD, /* 234 */
! OP_FTEWRITE, /* 235 */
! OP_FTEEXEC, /* 236 */
! OP_FTIS, /* 237 */
! OP_FTEOWNED, /* 238 */
! OP_FTROWNED, /* 239 */
! OP_FTZERO, /* 240 */
! OP_FTSIZE, /* 241 */
! OP_FTMTIME, /* 242 */
! OP_FTATIME, /* 243 */
! OP_FTCTIME, /* 244 */
! OP_FTSOCK, /* 245 */
! OP_FTCHR, /* 246 */
! OP_FTBLK, /* 247 */
! OP_FTFILE, /* 248 */
! OP_FTDIR, /* 249 */
! OP_FTPIPE, /* 250 */
! OP_FTLINK, /* 251 */
! OP_FTSUID, /* 252 */
! OP_FTSGID, /* 253 */
! OP_FTSVTX, /* 254 */
! OP_FTTTY, /* 255 */
! OP_FTTEXT, /* 256 */
! OP_FTBINARY, /* 257 */
! OP_CHDIR, /* 258 */
! OP_CHOWN, /* 259 */
! OP_CHROOT, /* 260 */
! OP_UNLINK, /* 261 */
! OP_CHMOD, /* 262 */
! OP_UTIME, /* 263 */
! OP_RENAME, /* 264 */
! OP_LINK, /* 265 */
! OP_SYMLINK, /* 266 */
! OP_READLINK, /* 267 */
! OP_MKDIR, /* 268 */
! OP_RMDIR, /* 269 */
! OP_OPEN_DIR, /* 270 */
! OP_READDIR, /* 271 */
! OP_TELLDIR, /* 272 */
! OP_SEEKDIR, /* 273 */
! OP_REWINDDIR, /* 274 */
! OP_CLOSEDIR, /* 275 */
! OP_FORK, /* 276 */
! OP_WAIT, /* 277 */
! OP_WAITPID, /* 278 */
! OP_SYSTEM, /* 279 */
! OP_EXEC, /* 280 */
! OP_KILL, /* 281 */
! OP_GETPPID, /* 282 */
! OP_GETPGRP, /* 283 */
! OP_SETPGRP, /* 284 */
! OP_GETPRIORITY, /* 285 */
! OP_SETPRIORITY, /* 286 */
! OP_TIME, /* 287 */
! OP_TMS, /* 288 */
! OP_LOCALTIME, /* 289 */
! OP_GMTIME, /* 290 */
! OP_ALARM, /* 291 */
! OP_SLEEP, /* 292 */
! OP_SHMGET, /* 293 */
! OP_SHMCTL, /* 294 */
! OP_SHMREAD, /* 295 */
! OP_SHMWRITE, /* 296 */
! OP_MSGGET, /* 297 */
! OP_MSGCTL, /* 298 */
! OP_MSGSND, /* 299 */
! OP_MSGRCV, /* 300 */
! OP_SEMGET, /* 301 */
! OP_SEMCTL, /* 302 */
! OP_SEMOP, /* 303 */
! OP_REQUIRE, /* 304 */
! OP_DOFILE, /* 305 */
! OP_ENTEREVAL, /* 306 */
! OP_LEAVEEVAL, /* 307 */
! OP_ENTERTRY, /* 308 */
! OP_LEAVETRY, /* 309 */
! OP_GHBYNAME, /* 310 */
! OP_GHBYADDR, /* 311 */
! OP_GHOSTENT, /* 312 */
! OP_GNBYNAME, /* 313 */
! OP_GNBYADDR, /* 314 */
! OP_GNETENT, /* 315 */
! OP_GPBYNAME, /* 316 */
! OP_GPBYNUMBER, /* 317 */
! OP_GPROTOENT, /* 318 */
! OP_GSBYNAME, /* 319 */
! OP_GSBYPORT, /* 320 */
! OP_GSERVENT, /* 321 */
! OP_SHOSTENT, /* 322 */
! OP_SNETENT, /* 323 */
! OP_SPROTOENT, /* 324 */
! OP_SSERVENT, /* 325 */
! OP_EHOSTENT, /* 326 */
! OP_ENETENT, /* 327 */
! OP_EPROTOENT, /* 328 */
! OP_ESERVENT, /* 329 */
! OP_GPWNAM, /* 330 */
! OP_GPWUID, /* 331 */
! OP_GPWENT, /* 332 */
! OP_SPWENT, /* 333 */
! OP_EPWENT, /* 334 */
! OP_GGRNAM, /* 335 */
! OP_GGRGID, /* 336 */
! OP_GGRENT, /* 337 */
! OP_SGRENT, /* 338 */
! OP_EGRENT, /* 339 */
! OP_GETLOGIN, /* 340 */
! OP_SYSCALL, /* 341 */
OP_max
} opcode;

! #define MAXO 342

#ifndef DOINIT
--- 212,355 ----
OP_PRTF, /* 205 */
OP_PRINT, /* 206 */
! OP_SYSOPEN, /* 207 */
! OP_SYSREAD, /* 208 */
! OP_SYSWRITE, /* 209 */
! OP_SEND, /* 210 */
! OP_RECV, /* 211 */
! OP_EOF, /* 212 */
! OP_TELL, /* 213 */
! OP_SEEK, /* 214 */
! OP_TRUNCATE, /* 215 */
! OP_FCNTL, /* 216 */
! OP_IOCTL, /* 217 */
! OP_FLOCK, /* 218 */
! OP_SOCKET, /* 219 */
! OP_SOCKPAIR, /* 220 */
! OP_BIND, /* 221 */
! OP_CONNECT, /* 222 */
! OP_LISTEN, /* 223 */
! OP_ACCEPT, /* 224 */
! OP_SHUTDOWN, /* 225 */
! OP_GSOCKOPT, /* 226 */
! OP_SSOCKOPT, /* 227 */
! OP_GETSOCKNAME, /* 228 */
! OP_GETPEERNAME, /* 229 */
! OP_LSTAT, /* 230 */
! OP_STAT, /* 231 */
! OP_FTRREAD, /* 232 */
! OP_FTRWRITE, /* 233 */
! OP_FTREXEC, /* 234 */
! OP_FTEREAD, /* 235 */
! OP_FTEWRITE, /* 236 */
! OP_FTEEXEC, /* 237 */
! OP_FTIS, /* 238 */
! OP_FTEOWNED, /* 239 */
! OP_FTROWNED, /* 240 */
! OP_FTZERO, /* 241 */
! OP_FTSIZE, /* 242 */
! OP_FTMTIME, /* 243 */
! OP_FTATIME, /* 244 */
! OP_FTCTIME, /* 245 */
! OP_FTSOCK, /* 246 */
! OP_FTCHR, /* 247 */
! OP_FTBLK, /* 248 */
! OP_FTFILE, /* 249 */
! OP_FTDIR, /* 250 */
! OP_FTPIPE, /* 251 */
! OP_FTLINK, /* 252 */
! OP_FTSUID, /* 253 */
! OP_FTSGID, /* 254 */
! OP_FTSVTX, /* 255 */
! OP_FTTTY, /* 256 */
! OP_FTTEXT, /* 257 */
! OP_FTBINARY, /* 258 */
! OP_CHDIR, /* 259 */
! OP_CHOWN, /* 260 */
! OP_CHROOT, /* 261 */
! OP_UNLINK, /* 262 */
! OP_CHMOD, /* 263 */
! OP_UTIME, /* 264 */
! OP_RENAME, /* 265 */
! OP_LINK, /* 266 */
! OP_SYMLINK, /* 267 */
! OP_READLINK, /* 268 */
! OP_MKDIR, /* 269 */
! OP_RMDIR, /* 270 */
! OP_OPEN_DIR, /* 271 */
! OP_READDIR, /* 272 */
! OP_TELLDIR, /* 273 */
! OP_SEEKDIR, /* 274 */
! OP_REWINDDIR, /* 275 */
! OP_CLOSEDIR, /* 276 */
! OP_FORK, /* 277 */
! OP_WAIT, /* 278 */
! OP_WAITPID, /* 279 */
! OP_SYSTEM, /* 280 */
! OP_EXEC, /* 281 */
! OP_KILL, /* 282 */
! OP_GETPPID, /* 283 */
! OP_GETPGRP, /* 284 */
! OP_SETPGRP, /* 285 */
! OP_GETPRIORITY, /* 286 */
! OP_SETPRIORITY, /* 287 */
! OP_TIME, /* 288 */
! OP_TMS, /* 289 */
! OP_LOCALTIME, /* 290 */
! OP_GMTIME, /* 291 */
! OP_ALARM, /* 292 */
! OP_SLEEP, /* 293 */
! OP_SHMGET, /* 294 */
! OP_SHMCTL, /* 295 */
! OP_SHMREAD, /* 296 */
! OP_SHMWRITE, /* 297 */
! OP_MSGGET, /* 298 */
! OP_MSGCTL, /* 299 */
! OP_MSGSND, /* 300 */
! OP_MSGRCV, /* 301 */
! OP_SEMGET, /* 302 */
! OP_SEMCTL, /* 303 */
! OP_SEMOP, /* 304 */
! OP_REQUIRE, /* 305 */
! OP_DOFILE, /* 306 */
! OP_ENTEREVAL, /* 307 */
! OP_LEAVEEVAL, /* 308 */
! OP_ENTERTRY, /* 309 */
! OP_LEAVETRY, /* 310 */
! OP_GHBYNAME, /* 311 */
! OP_GHBYADDR, /* 312 */
! OP_GHOSTENT, /* 313 */
! OP_GNBYNAME, /* 314 */
! OP_GNBYADDR, /* 315 */
! OP_GNETENT, /* 316 */
! OP_GPBYNAME, /* 317 */
! OP_GPBYNUMBER, /* 318 */
! OP_GPROTOENT, /* 319 */
! OP_GSBYNAME, /* 320 */
! OP_GSBYPORT, /* 321 */
! OP_GSERVENT, /* 322 */
! OP_SHOSTENT, /* 323 */
! OP_SNETENT, /* 324 */
! OP_SPROTOENT, /* 325 */
! OP_SSERVENT, /* 326 */
! OP_EHOSTENT, /* 327 */
! OP_ENETENT, /* 328 */
! OP_EPROTOENT, /* 329 */
! OP_ESERVENT, /* 330 */
! OP_GPWNAM, /* 331 */
! OP_GPWUID, /* 332 */
! OP_GPWENT, /* 333 */
! OP_SPWENT, /* 334 */
! OP_EPWENT, /* 335 */
! OP_GGRNAM, /* 336 */
! OP_GGRGID, /* 337 */
! OP_GGRENT, /* 338 */
! OP_SGRENT, /* 339 */
! OP_EGRENT, /* 340 */
! OP_GETLOGIN, /* 341 */
! OP_SYSCALL, /* 342 */
OP_max
} opcode;

! #define MAXO 343

#ifndef DOINIT
*************** EXT char *op_name[] = {
*** 563,566 ****
--- 564,568 ----
"printf",
"print",
+ "sysopen",
"sysread",
"syswrite",
*************** OP * pp_leavewrite _((void));
*** 937,940 ****
--- 939,943 ----
OP * pp_prtf _((void));
OP * pp_print _((void));
+ OP * pp_sysopen _((void));
OP * pp_sysread _((void));
OP * pp_syswrite _((void));
*************** EXT OP * (*ppaddr[])() = {
*** 1284,1287 ****
--- 1287,1291 ----
pp_prtf,
pp_print,
+ pp_sysopen,
pp_sysread,
pp_syswrite,
*************** EXT OP * (*check[])() = {
*** 1633,1636 ****
--- 1637,1641 ----
ck_listiob, /* prtf */
ck_listiob, /* print */
+ ck_fun, /* sysopen */
ck_fun, /* sysread */
ck_fun, /* syswrite */
*************** EXT U32 opargs[] = {
*** 1982,1985 ****
--- 1987,1991 ----
0x00002e15, /* prtf */
0x00002e15, /* print */
+ 0x0091160c, /* sysopen */
0x0091761d, /* sysread */
0x0091161d, /* syswrite */

Index: proto.h
*************** I32 do_msgrcv _((SV** mark, SV** sp));
*** 81,85 ****
I32 do_msgsnd _((SV** mark, SV** sp));
#endif
! bool do_open _((GV* gv, char* name, I32 len, FILE* supplied_fp));
void do_pipe _((SV* sv, GV* rgv, GV* wgv));
bool do_print _((SV* sv, FILE* fp));
--- 81,86 ----
I32 do_msgsnd _((SV** mark, SV** sp));
#endif
! bool do_open _((GV* gv, char* name, I32 len,
! bool raw, int rawmode, int rawperm, FILE* supplied_fp));
void do_pipe _((SV* sv, GV* rgv, GV* wgv));
bool do_print _((SV* sv, FILE* fp));

Index: doio.c
***************
*** 63,90 ****

bool
! do_open(gv,name,len,supplied_fp)
GV *gv;
register char *name;
I32 len;
FILE *supplied_fp;
{
- FILE *fp;
register IO *io = GvIOn(gv);
- char *myname = savepv(name);
- int result;
- int fd;
- int writing = 0;
- int dodup;
- char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
FILE *saveifp = Nullfp;
FILE *saveofp = Nullfp;
char savetype = ' ';

- SAVEFREEPV(myname);
- mode[0] = mode[1] = mode[2] = '\0';
- name = myname;
forkprocess = 1; /* assume true if no fork */
! while (len && isSPACE(name[len-1]))
! name[--len] = '\0';
if (IoIFP(io)) {
fd = fileno(IoIFP(io));
--- 63,85 ----

bool
! do_open(gv,name,len,raw,rawmode,rawperm,supplied_fp)
GV *gv;
register char *name;
I32 len;
+ bool raw;
+ int rawmode, rawperm;
FILE *supplied_fp;
{
register IO *io = GvIOn(gv);
FILE *saveifp = Nullfp;
FILE *saveofp = Nullfp;
char savetype = ' ';
+ int writing = 0;
+ FILE *fp;
+ int fd;
+ int result;

forkprocess = 1; /* assume true if no fork */
!
if (IoIFP(io)) {
fd = fileno(IoIFP(io));
*************** FILE *supplied_fp;
*** 114,206 ****
IoOFP(io) = IoIFP(io) = Nullfp;
}
! if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
! mode[1] = *name++;
! mode[2] = '\0';
! --len;
! writing = 1;
! }
! else {
! mode[1] = '\0';
! }
! IoTYPE(io) = *name;
! if (*name == '|') {
! /*SUPPRESS 530*/
! for (name++; isSPACE(*name); name++) ;
! if (strNE(name,"-"))
! TAINT_ENV();
! TAINT_PROPER("piped open");
! if (dowarn && name[strlen(name)-1] == '|')
! warn("Can't do bidirectional pipe");
! fp = my_popen(name,"w");
! writing = 1;
}
! else if (*name == '>') {
! TAINT_PROPER("open");
! name++;
! if (*name == '>') {
! mode[0] = IoTYPE(io) = 'a';
! name++;
}
! else
! mode[0] = 'w';
! writing = 1;
! if (*name == '&') {
! duplicity:
! dodup = 1;
name++;
! if (*name == '=') {
! dodup = 0;
name++;
}
! if (!*name && supplied_fp)
! fp = supplied_fp;
! else {
! while (isSPACE(*name))
name++;
! if (isDIGIT(*name))
! fd = atoi(name);
else {
! IO* thatio;
! gv = gv_fetchpv(name,FALSE,SVt_PVIO);
! thatio = GvIO(gv);
! if (!thatio) {
#ifdef EINVAL
! SETERRNO(EINVAL,SS$_IVCHAN);
#endif
! goto say_false;
}
- if (IoIFP(thatio)) {
- fd = fileno(IoIFP(thatio));
- if (IoTYPE(thatio) == 's')
- IoTYPE(io) = 's';
- }
- else
- fd = -1;
- }
- if (dodup)
- fd = dup(fd);
- if (!(fp = fdopen(fd,mode)))
if (dodup)
! close(fd);
! }
! }
! else {
! while (isSPACE(*name))
! name++;
! if (strEQ(name,"-")) {
! fp = stdout;
! IoTYPE(io) = '-';
}
! else {
! fp = fopen(name,mode);
}
}
! }
! else {
! if (*name == '<') {
mode[0] = 'r';
- name++;
- while (isSPACE(*name))
- name++;
if (*name == '&')
goto duplicity;
--- 109,225 ----
IoOFP(io) = IoIFP(io) = Nullfp;
}
!
! if (raw) {
! result = rawmode & 3;
! IoTYPE(io) = "<>++"[result];
! writing = (result > 0);
! fd = open(name, rawmode, rawperm);
! if (fd == -1)
! fp = NULL;
! else {
! fp = fdopen(fd, ((result == 0) ? "r"
! : (result == 1) ? "w"
! : "r+"));
! if (!fp)
! close(fd);
! }
}
! else {
! char *myname;
! char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
! int dodup;
!
! myname = savepvn(name, len);
! SAVEFREEPV(myname);
! name = myname;
! while (len && isSPACE(name[len-1]))
! name[--len] = '\0';
!
! mode[0] = mode[1] = mode[2] = '\0';
! IoTYPE(io) = *name;
! if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
! mode[1] = *name++;
! --len;
! writing = 1;
}
!
! if (*name == '|') {
! /*SUPPRESS 530*/
! for (name++; isSPACE(*name); name++) ;
! if (strNE(name,"-"))
! TAINT_ENV();
! TAINT_PROPER("piped open");
! if (dowarn && name[strlen(name)-1] == '|')
! warn("Can't do bidirectional pipe");
! fp = my_popen(name,"w");
! writing = 1;
! }
! else if (*name == '>') {
! TAINT_PROPER("open");
name++;
! if (*name == '>') {
! mode[0] = IoTYPE(io) = 'a';
name++;
}
! else
! mode[0] = 'w';
! writing = 1;
!
! if (*name == '&') {
! duplicity:
! dodup = 1;
! name++;
! if (*name == '=') {
! dodup = 0;
name++;
! }
! if (!*name && supplied_fp)
! fp = supplied_fp;
else {
! /*SUPPRESS 530*/
! for (; isSPACE(*name); name++) ;
! if (isDIGIT(*name))
! fd = atoi(name);
! else {
! IO* thatio;
! gv = gv_fetchpv(name,FALSE,SVt_PVIO);
! thatio = GvIO(gv);
! if (!thatio) {
#ifdef EINVAL
! SETERRNO(EINVAL,SS$_IVCHAN);
#endif
! goto say_false;
! }
! if (IoIFP(thatio)) {
! fd = fileno(IoIFP(thatio));
! if (IoTYPE(thatio) == 's')
! IoTYPE(io) = 's';
! }
! else
! fd = -1;
}
if (dodup)
! fd = dup(fd);
! if (!(fp = fdopen(fd,mode)))
! if (dodup)
! close(fd);
! }
}
! else {
! /*SUPPRESS 530*/
! for (; isSPACE(*name); name++) ;
! if (strEQ(name,"-")) {
! fp = stdout;
! IoTYPE(io) = '-';
! }
! else {
! fp = fopen(name,mode);
! }
}
}
! else if (*name == '<') {
! /*SUPPRESS 530*/
! for (name++; isSPACE(*name); name++) ;
mode[0] = 'r';
if (*name == '&')
goto duplicity;
*************** register GV *gv;
*** 349,353 ****
SvSETMAGIC(GvSV(gv));
oldname = SvPVx(GvSV(gv), len);
! if (do_open(gv,oldname,len,Nullfp)) {
if (inplace) {
TAINT_PROPER("inplace open");
--- 368,372 ----
SvSETMAGIC(GvSV(gv));
oldname = SvPVx(GvSV(gv), len);
! if (do_open(gv,oldname,len,FALSE,0,0,Nullfp)) {
if (inplace) {
TAINT_PROPER("inplace open");
*************** register GV *gv;
*** 397,401 ****
(void)unlink(SvPVX(sv));
(void)rename(oldname,SvPVX(sv));
! do_open(gv,SvPVX(sv),SvCUR(GvSV(gv)),Nullfp);
#endif /* MSDOS */
#else
--- 416,420 ----
(void)unlink(SvPVX(sv));
(void)rename(oldname,SvPVX(sv));
! do_open(gv,SvPVX(sv),SvCUR(GvSV(gv)),FALSE,0,0,Nullfp);
#endif /* MSDOS */
#else
*************** register GV *gv;
*** 426,430 ****
sv_catpv(sv,oldname);
SETERRNO(0,0); /* in case sprintf set errno */
! if (!do_open(argvoutgv,SvPVX(sv),SvCUR(sv),Nullfp)) {
warn("Can't do inplace edit on %s: %s",
oldname, Strerror(errno) );
--- 445,449 ----
sv_catpv(sv,oldname);
SETERRNO(0,0); /* in case sprintf set errno */
! if (!do_open(argvoutgv,SvPVX(sv),SvCUR(sv),FALSE,0,0,Nullfp)) {
warn("Can't do inplace edit on %s: %s",
oldname, Strerror(errno) );

Index: ext/POSIX/POSIX.c
*************** XS(XS_FileHandle_new_tmpfile)
*** 3012,3016 ****
{
GV *gv = newGVgen("FileHandle");
! if ( do_open(gv, "+>&", 3, RETVAL) )
sv_setsv(ST(0), sv_bless(newRV((SV*)gv), gv_stashpv("FileHandle",1)));
else
--- 3012,3016 ----
{
GV *gv = newGVgen("FileHandle");
! if ( do_open(gv, "+>&", 3, FALSE, 0, 0, RETVAL) )
sv_setsv(ST(0), sv_bless(newRV((SV*)gv), gv_stashpv("FileHandle",1)));
else

Index: keywords.pl
***************
*** 234,237 ****
--- 234,238 ----
symlink
syscall
+ sysopen
sysread
system

Index: opcode.pl
***************
*** 445,448 ****
--- 445,449 ----
print print ck_listiob ims F? L

+ sysopen sysopen ck_fun st F S S S?
sysread sysread ck_fun imst F R S S?
syswrite syswrite ck_fun imst F S S S?

Index: pod/perlfunc.pod
***************
*** 2607,2610 ****
--- 2607,2631 ----
which in practice should usually suffice.

+ =item sysopen FILEHANDLE,FILENAME,MODE
+
+ =item sysopen FILEHANDLE,FILENAME,MODE,PERMS
+
+ Opens the file whose filename is given by FILENAME, and associates it
+ with FILEHANDLE. If FILEHANDLE is an expression, its value is used as
+ the name of the real filehandle wanted. This function calls the
+ underlying operating system's C<open> function with the parameters
+ FILENAME, MODE, PERMS.
+
+ The possible values and flag bits of the MODE parameter are
+ system-dependent; they are available via the standard module C<Fcntl>.
+ However, for historical reasons, some values are universal: zero means
+ read-only, one means write-only, and two means read/write.
+
+ If the file named by FILENAME does not exist and the C<open> call
+ creates it (typically because MODE includes the O_CREAT flag), then
+ the value of PERMS specifies the permissions of the newly created
+ file. If PERMS is omitted, the default value is 0666, which allows
+ read and write for all. This default is reasonable: see C<umask>.
+
=item sysread FILEHANDLE,SCALAR,LENGTH,OFFSET


Index: pp_hot.c
*************** do_readline()
*** 1018,1022 ****
#endif /* !CSH */
#endif /* !MSDOS */
! (void)do_open(last_in_gv, SvPVX(tmpcmd), SvCUR(tmpcmd),Nullfp);
fp = IoIFP(io);
#endif /* !VMS */
--- 1018,1023 ----
#endif /* !CSH */
#endif /* !MSDOS */
! (void)do_open(last_in_gv, SvPVX(tmpcmd), SvCUR(tmpcmd),
! FALSE, 0, 0, Nullfp);
fp = IoIFP(io);
#endif /* !VMS */

Index: pp_sys.c
*************** PP(pp_open)
*** 246,250 ****
gv = (GV*)POPs;
tmps = SvPV(sv, len);
! if (do_open(gv, tmps, len,Nullfp)) {
IoLINES(GvIOp(gv)) = 0;
PUSHi( (I32)forkprocess );
--- 246,250 ----
gv = (GV*)POPs;
tmps = SvPV(sv, len);
! if (do_open(gv, tmps, len, FALSE, 0, 0, Nullfp)) {
IoLINES(GvIOp(gv)) = 0;
PUSHi( (I32)forkprocess );
*************** PP(pp_prtf)
*** 969,972 ****
--- 969,1001 ----
SP = ORIGMARK;
PUSHs(&sv_undef);
+ RETURN;
+ }
+
+ PP(pp_sysopen)
+ {
+ dSP; dTARGET;
+ GV *gv;
+ IO *io;
+ SV *sv;
+ char *tmps;
+ STRLEN len;
+ int mode, perm;
+
+ if (MAXARG > 3)
+ perm = POPi;
+ else
+ perm = 0666;
+ mode = POPi;
+ sv = POPs;
+ gv = (GV *)POPs;
+
+ tmps = SvPV(sv, len);
+ if (do_open(gv, tmps, len, TRUE, mode, perm, Nullfp)) {
+ IoLINES(GvIOp(gv)) = 0;
+ PUSHs(&sv_yes);
+ }
+ else {
+ PUSHs(&sv_undef);
+ }
RETURN;
}

Index: toke.c
*************** yylex()
*** 3195,3198 ****
--- 3195,3201 ----
LOP(OP_SYSCALL,XTERM);

+ case KEY_sysopen:
+ LOP(OP_SYSOPEN,XTERM);
+
case KEY_sysread:
LOP(OP_SYSREAD,XTERM);
*************** I32 len;
*** 3833,3836 ****
--- 3836,3840 ----
break;
case 7:
+ if (strEQ(d,"sysopen")) return -KEY_sysopen;
if (strEQ(d,"sysread")) return -KEY_sysread;
if (strEQ(d,"symlink")) return -KEY_symlink;

Index: vms/ext/VMS/stdio/stdio.xs
***************
*** 91,95 ****
}
*(name++) = '&';
! if (do_open(gv,mode,name - mode,fp))
sv_setsv(ST(0),newRV((SV*)gv));
}
--- 91,95 ----
}
*(name++) = '&';
! if (do_open(gv,mode,name - mode,FALSE,0,0,fp))
sv_setsv(ST(0),newRV((SV*)gv));
}