1 4887 chin /*********************************************************************** 2 4887 chin * * 3 4887 chin * This software is part of the ast package * 4 8462 April * Copyright (c) 1982-2007 AT&T Intellectual Property * 5 4887 chin * and is licensed under the * 6 4887 chin * Common Public License, Version 1.0 * 7 8462 April * by AT&T Intellectual Property * 8 4887 chin * * 9 4887 chin * A copy of the License is available at * 10 4887 chin * http://www.opensource.org/licenses/cpl1.0.txt * 11 4887 chin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 4887 chin * * 13 4887 chin * Information and Software Systems Research * 14 4887 chin * AT&T Research * 15 4887 chin * Florham Park NJ * 16 4887 chin * * 17 4887 chin * David Korn <dgk (at) research.att.com> * 18 4887 chin * * 19 4887 chin ***********************************************************************/ 20 4887 chin #pragma prototyped 21 4887 chin 22 4887 chin #include <shell.h> 23 4887 chin #include <stdio.h> 24 8462 April #include <stdbool.h> 25 4887 chin #include <option.h> 26 4887 chin #include <stk.h> 27 4887 chin #include <tm.h> 28 4887 chin #include "name.h" 29 4887 chin #undef nv_isnull 30 4887 chin #ifndef SH_DICT 31 4887 chin # define SH_DICT "libshell" 32 4887 chin #endif 33 4887 chin #include <poll.h> 34 8462 April 35 8462 April #define sh_contexttoshb(context) ((Shbltin_t*)(context)) 36 8462 April #define sh_contexttoshell(context) ((context)?(sh_contexttoshb(context)->shp):(NULL)) 37 4887 chin 38 4887 chin /* 39 4887 chin * time formatting related 40 4887 chin */ 41 4887 chin struct dctime 42 4887 chin { 43 4887 chin Namfun_t fun; 44 4887 chin Namval_t *format; 45 4887 chin char buff[256]; /* Must be large enougth for |tmfmt()| */ 46 4887 chin }; 47 4887 chin 48 4887 chin static char *get_time(Namval_t* np, Namfun_t* nfp) 49 4887 chin { 50 4887 chin struct dctime *dp = (struct dctime*)nfp; 51 4887 chin time_t t = nv_getn(np,nfp); 52 4887 chin char *format = nv_getval(dp->format); 53 4887 chin tmfmt(dp->buff,sizeof(dp->buff),format,(time_t*)0); 54 4887 chin return(dp->buff); 55 4887 chin } 56 4887 chin 57 4887 chin static void put_time(Namval_t* np, const char* val, int flag, Namfun_t* nfp) 58 4887 chin { 59 4887 chin struct dctime *dp = (struct dctime*)nfp; 60 4887 chin char *last; 61 4887 chin if(val) 62 4887 chin { 63 4887 chin int32_t t; 64 4887 chin if(flag&NV_INTEGER) 65 4887 chin { 66 4887 chin if(flag&NV_LONG) 67 4887 chin t = *(Sfdouble_t*)val; 68 4887 chin else 69 4887 chin t = *(double*)val; 70 4887 chin } 71 4887 chin else 72 4887 chin { 73 4887 chin t = tmdate(val, &last, (time_t*)0); 74 4887 chin if(*last) 75 4887 chin errormsg(SH_DICT, ERROR_exit(1),"%s: invalid date/time string", val); 76 4887 chin } 77 4887 chin nv_putv(np, (char*)&t,NV_INTEGER, nfp); 78 4887 chin } 79 4887 chin else 80 4887 chin { 81 4887 chin nv_unset(dp->format); 82 4887 chin free((void*)dp->format); 83 4887 chin nv_putv(np, val, flag, nfp); 84 4887 chin } 85 4887 chin } 86 4887 chin 87 4887 chin static Namval_t *create_time(Namval_t *np, const char *name, int flags, Namfun_t *nfp) 88 4887 chin { 89 4887 chin struct dctime *dp = (struct dctime*)nfp; 90 4887 chin if(strcmp(name, "format")) 91 4887 chin return((Namval_t*)0); 92 4887 chin return(dp->format); 93 4887 chin } 94 4887 chin 95 4887 chin static const Namdisc_t timedisc = 96 4887 chin { 97 4887 chin sizeof(struct dctime), 98 4887 chin put_time, 99 4887 chin get_time, 100 4887 chin 0, 101 4887 chin 0, 102 4887 chin create_time, 103 4887 chin }; 104 4887 chin 105 4887 chin 106 4887 chin static Namval_t *make_time(Namval_t* np) 107 4887 chin { 108 4887 chin int offset = stktell(stkstd); 109 4887 chin char *name = nv_name(np); 110 4887 chin struct dctime *dp = newof(NULL,struct dctime,1,0); 111 4887 chin if(!dp) 112 4887 chin return((Namval_t*)0); 113 4887 chin sfprintf(stkstd,"%s.format\0",name); 114 4887 chin sfputc(stkstd,0); 115 4887 chin dp->format = nv_search(stkptr(stkstd,offset),sh.var_tree,NV_ADD); 116 4887 chin dp->fun.disc = &timedisc; 117 4887 chin nv_stack(np,&dp->fun); 118 4887 chin return(np); 119 4887 chin } 120 4887 chin 121 4887 chin /* 122 4887 chin * mode formatting related 123 4887 chin */ 124 4887 chin static char *get_mode(Namval_t* np, Namfun_t* nfp) 125 4887 chin { 126 4887 chin mode_t mode = nv_getn(np,nfp); 127 4887 chin return(fmtperm(mode)); 128 4887 chin } 129 4887 chin 130 4887 chin static void put_mode(Namval_t* np, const char* val, int flag, Namfun_t* nfp) 131 4887 chin { 132 4887 chin if(val) 133 4887 chin { 134 4887 chin int32_t mode; 135 4887 chin char *last; 136 4887 chin if(flag&NV_INTEGER) 137 4887 chin { 138 4887 chin if(flag&NV_LONG) 139 4887 chin mode = *(Sfdouble_t*)val; 140 4887 chin else 141 4887 chin mode = *(double*)val; 142 4887 chin } 143 4887 chin else 144 4887 chin { 145 4887 chin mode = strperm(val, &last,0); 146 4887 chin if(*last) 147 4887 chin errormsg(SH_DICT, ERROR_exit(1),"%s: invalid mode string", val); 148 4887 chin } 149 4887 chin nv_putv(np,(char*)&mode,NV_INTEGER,nfp); 150 4887 chin } 151 4887 chin else 152 4887 chin nv_putv(np,val,flag,nfp); 153 4887 chin } 154 4887 chin 155 4887 chin static const Namdisc_t modedisc = 156 4887 chin { 157 4887 chin 0, 158 4887 chin put_mode, 159 4887 chin get_mode, 160 4887 chin }; 161 4887 chin 162 4887 chin static Namval_t *make_mode(Namval_t* np) 163 4887 chin { 164 4887 chin char *name = nv_name(np); 165 4887 chin Namfun_t *nfp = newof(NULL,Namfun_t,1,0); 166 4887 chin if(!nfp) 167 4887 chin return((Namval_t*)0); 168 4887 chin nfp->disc = &modedisc; 169 4887 chin nv_stack(np,nfp); 170 4887 chin return(np); 171 4887 chin } 172 4887 chin 173 4887 chin /* 174 4887 chin * field related typese and functions 175 4887 chin */ 176 4887 chin typedef struct _field_ 177 4887 chin { 178 4887 chin char *name; /* field name */ 179 4887 chin int flags; /* flags */ 180 4887 chin short offset; /* offset of field into data */ 181 4887 chin short size; /* size of field */ 182 4887 chin Namval_t *(*make)(Namval_t*); /* discipline constructor */ 183 4887 chin } Shfield_t; 184 4887 chin 185 4887 chin /* 186 4887 chin * lookup field in field table 187 4887 chin */ 188 4887 chin static Shfield_t *sh_findfield(Shfield_t *ftable, int nelem, const char *name) 189 4887 chin { 190 4887 chin Shfield_t *fp = ftable; 191 4887 chin register int i,n; 192 4887 chin register const char *cp; 193 4887 chin for(cp=name; *cp; cp++) 194 4887 chin { 195 4887 chin if(*cp=='.') 196 4887 chin break; 197 4887 chin } 198 4887 chin n = cp-name; 199 4887 chin for(i=0; i < nelem; i++,fp++) 200 4887 chin { 201 4887 chin if(memcmp(fp->name,name,n)==0 && fp->name[n]==0) 202 4887 chin return(fp); 203 4887 chin } 204 4887 chin return(0); 205 4887 chin } 206 4887 chin 207 4887 chin /* 208 4887 chin * class types and functions 209 4887 chin */ 210 4887 chin 211 4887 chin typedef struct _class_ 212 4887 chin { 213 4887 chin int nelem; /* number of elements */ 214 4887 chin int dsize; /* size for data structure */ 215 4887 chin Shfield_t *fields; /* field description table */ 216 4887 chin } Shclass_t; 217 4887 chin 218 4887 chin struct dcclass 219 4887 chin { 220 4887 chin Namfun_t fun; 221 4887 chin Shclass_t sclass; 222 4887 chin }; 223 4887 chin 224 4887 chin static Namval_t *sh_newnode(register Shfield_t *fp, Namval_t *np) 225 4887 chin { 226 4887 chin char *val = np->nvalue + fp->offset; 227 4887 chin char *name = nv_name(np); 228 4887 chin register Namval_t *nq; 229 4887 chin int offset = stktell(stkstd); 230 4887 chin sfprintf(stkstd,"%s.%s\0",name,fp->name); 231 4887 chin sfputc(stkstd,0); 232 4887 chin nq = nv_search(stkptr(stkstd,offset),sh.var_tree,NV_ADD); 233 4887 chin if(fp->size<0) 234 4887 chin val = *(char**)val; 235 4887 chin nv_putval(nq,val,fp->flags|NV_NOFREE); 236 4887 chin if(fp->make) 237 4887 chin (*fp->make)(nq); 238 4887 chin return(nq); 239 4887 chin } 240 4887 chin 241 4887 chin static Namval_t *fieldcreate(Namval_t *np, const char *name, int flags, Namfun_t *nfp) 242 4887 chin { 243 4887 chin struct dcclass *dcp = (struct dcclass*)nfp; 244 4887 chin Shclass_t *sp = &dcp->sclass; 245 4887 chin Shfield_t *fp = sh_findfield(sp->fields,sp->nelem,name); 246 4887 chin Namval_t *nq,**nodes = (Namval_t**)(dcp+1); 247 4887 chin int n = fp-sp->fields; 248 4887 chin int len = strlen(fp->name); 249 4887 chin void *data = (void*)np->nvalue; 250 4887 chin if(!(nq=nodes[n])) 251 4887 chin { 252 4887 chin nodes[n] = nq = sh_newnode(fp,np); 253 4887 chin nfp->last = ""; 254 4887 chin } 255 4887 chin if(name[len]==0) 256 4887 chin return(nq); 257 4887 chin return(nq); 258 4887 chin } 259 4887 chin 260 4887 chin static void genvalue(Sfio_t *out, Shclass_t *sp, int indent, Namval_t *npar) 261 4887 chin { 262 4887 chin Shfield_t *fp = sp->fields; 263 4887 chin Namval_t *np, **nodes= (Namval_t**)(sp+1); 264 4887 chin register int i,isarray; 265 4887 chin if(out) 266 4887 chin { 267 4887 chin sfwrite(out,"(\n",2); 268 4887 chin indent++; 269 4887 chin } 270 4887 chin for(i=0; i < sp->nelem; i++,fp++) 271 4887 chin { 272 4887 chin #if 0 273 4887 chin /* handle recursive case */ 274 4887 chin #endif 275 4887 chin if(!(np=nodes[i]) && out) 276 4887 chin np = sh_newnode(fp,npar); 277 4887 chin if(np) 278 4887 chin { 279 4887 chin isarray=0; 280 4887 chin if(nv_isattr(np,NV_ARRAY)) 281 4887 chin { 282 4887 chin isarray=1; 283 4887 chin if(array_elem(nv_arrayptr(np))==0) 284 4887 chin isarray=2; 285 4887 chin else 286 4887 chin nv_putsub(np,(char*)0,ARRAY_SCAN); 287 4887 chin } 288 4887 chin sfnputc(out,'\t',indent); 289 4887 chin sfputr(out,fp->name,(isarray==2?'\n':'=')); 290 4887 chin if(isarray) 291 4887 chin { 292 4887 chin if(isarray==2) 293 4887 chin continue; 294 4887 chin sfwrite(out,"(\n",2); 295 4887 chin sfnputc(out,'\t',++indent); 296 4887 chin } 297 4887 chin while(1) 298 4887 chin { 299 4887 chin char *fmtq; 300 4887 chin if(isarray) 301 4887 chin { 302 4887 chin sfprintf(out,"[%s]",sh_fmtq(nv_getsub(np))); 303 4887 chin sfputc(out,'='); 304 4887 chin } 305 4887 chin if(!(fmtq=nv_getval(np)) || !(fmtq=sh_fmtq(fmtq))) 306 4887 chin fmtq = ""; 307 4887 chin sfputr(out,fmtq,'\n'); 308 4887 chin if(!nv_nextsub(np)) 309 4887 chin break; 310 4887 chin sfnputc(out,'\t',indent); 311 4887 chin } 312 4887 chin if(isarray) 313 4887 chin { 314 4887 chin sfnputc(out,'\t',--indent); 315 4887 chin sfwrite(out,")\n",2); 316 4887 chin } 317 4887 chin } 318 4887 chin } 319 4887 chin if(out) 320 4887 chin { 321 4887 chin if(indent>1) 322 4887 chin sfnputc(out,'\t',indent-1); 323 4887 chin sfputc(out,')'); 324 4887 chin } 325 4887 chin } 326 4887 chin 327 4887 chin static char *walk_class(register Namval_t *np, int dlete, struct dcclass *dcp) 328 4887 chin { 329 4887 chin static Sfio_t *out; 330 4887 chin Sfio_t *outfile; 331 4887 chin int savtop = stktell(stkstd); 332 4887 chin char *savptr = stkfreeze(stkstd,0); 333 4887 chin if(dlete) 334 4887 chin outfile = 0; 335 4887 chin else if(!(outfile=out)) 336 4887 chin outfile = out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING); 337 4887 chin else 338 4887 chin sfseek(outfile,0L,SEEK_SET); 339 4887 chin genvalue(outfile,&dcp->sclass,0,np); 340 4887 chin stkset(stkstd,savptr,savtop); 341 4887 chin if(!outfile) 342 4887 chin return((char*)0); 343 4887 chin sfputc(out,0); 344 4887 chin return((char*)out->_data); 345 4887 chin } 346 4887 chin 347 4887 chin static char *get_classval(Namval_t* np, Namfun_t* nfp) 348 4887 chin { 349 4887 chin return(walk_class(np,0,(struct dcclass *)nfp)); 350 4887 chin } 351 4887 chin 352 4887 chin static void put_classval(Namval_t* np, const char* val, int flag, Namfun_t* nfp) 353 4887 chin { 354 4887 chin walk_class(np,1,(struct dcclass *)nfp); 355 4887 chin if(nfp = nv_stack(np,(Namfun_t*)0)) 356 4887 chin { 357 4887 chin free((void*)nfp); 358 4887 chin if(np->nvalue && !nv_isattr(np,NV_NOFREE)) 359 4887 chin free((void*)np->nvalue); 360 4887 chin } 361 4887 chin if(val) 362 4887 chin nv_putval(np,val,flag); 363 4887 chin } 364 4887 chin 365 4887 chin static const Namdisc_t classdisc = 366 4887 chin { 367 4887 chin sizeof(struct dcclass), 368 4887 chin put_classval, 369 4887 chin get_classval, 370 4887 chin 0, 371 4887 chin 0, 372 4887 chin fieldcreate 373 4887 chin }; 374 4887 chin 375 4887 chin static int mkclass(Namval_t *np, Shclass_t *sp) 376 4887 chin { 377 4887 chin struct dcclass *tcp = newof(NULL,struct dcclass,1,sp->nelem*sizeof(Namval_t*)); 378 4887 chin if(!tcp) 379 4887 chin return(0); 380 4887 chin memset((void*)(tcp+1),0,sp->nelem*sizeof(Namval_t*)); 381 4887 chin tcp->fun.disc = &classdisc; 382 4887 chin tcp->sclass = *sp; 383 4887 chin np->nvalue = (char*)calloc(sp->dsize,1); 384 4887 chin nv_stack(np,&tcp->fun); 385 4887 chin return(1); 386 4887 chin } 387 4887 chin 388 4887 chin /* 389 4887 chin * ====================from here down is file class specific 390 4887 chin */ 391 4887 chin static struct stat *Sp; 392 4887 chin 393 4887 chin struct filedata 394 4887 chin { 395 4887 chin struct stat statb; 396 4887 chin int fd; 397 4887 chin char *name; 398 4887 chin }; 399 4887 chin 400 4887 chin static Shfield_t filefield[] = 401 4887 chin { 402 4887 chin { "atime", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_atime), sizeof(Sp->st_atime), make_time}, 403 4887 chin { "ctime", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_ctime), sizeof(Sp->st_ctime), make_time}, 404 4887 chin { "dev", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_dev),sizeof(Sp->st_dev)}, 405 4887 chin { "fd", NV_INTEGER|NV_RDONLY, offsetof(struct filedata,fd), sizeof(int)}, 406 4887 chin { "gid", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_gid), sizeof(Sp->st_gid)}, 407 4887 chin { "ino", NV_LONG|NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_ino), sizeof(Sp->st_ino)}, 408 4887 chin { "mode", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_mode), sizeof(Sp->st_mode), make_mode}, 409 4887 chin { "mtime", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_mtime), sizeof(Sp->st_mtime), make_time}, 410 4887 chin { "name", NV_RDONLY, offsetof(struct filedata,name), -1 }, 411 4887 chin { "nlink", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_nlink), sizeof(Sp->st_nlink)}, 412 4887 chin { "size", NV_LONG|NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_size), sizeof(Sp->st_size)}, 413 4887 chin { "uid", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_uid), sizeof(Sp->st_uid)} 414 4887 chin }; 415 4887 chin 416 4887 chin static Shclass_t Fileclass = 417 4887 chin { 418 4887 chin sizeof(filefield)/sizeof(*filefield), 419 4887 chin sizeof(struct filedata), 420 4887 chin filefield 421 4887 chin }; 422 4887 chin 423 4887 chin 424 4887 chin #define letterbit(bit) (1<<((bit)-'a')) 425 4887 chin 426 4887 chin static const char sh_optopen[] = 427 4887 chin "[-?\n@(#)$Id: open (AT&T Labs Research) 2007-05-07 $\n]" 428 4887 chin "[-author?David Korn <dgk (at) research.att.com>]" 429 4887 chin "[-author?Roland Mainz <roland.mainz (at) nrubsig.org>]" 430 4887 chin "[-license?http://www.opensource.org/licenses/cpl1.0.txt]" 431 4887 chin "[+NAME? open - create a shell variable correspnding to a file]" 432 4887 chin "[+DESCRIPTION?\bopen\b creates the compound variable \avar\a correspinding " 433 4887 chin "to the file given by the pathname \afile\a. The elements of \avar\a " 434 4887 chin "are the names of elements in the \astat\a structure with the \bst_\b " 435 4887 chin "prefix removed.]" 436 4887 chin "[+?\afile\a is opened (based on \b-r\b and/or \b-w\b) and the variable " 437 4887 chin "\avar\a\b.fd\b is the file descriptor.]" 438 4887 chin "[a:append?Open for append.]" 439 4887 chin "[b:binary?Open in binary mode" 440 4887 chin #ifndef O_BINARY 441 4887 chin " (not supported/ignored on this platform)" 442 4887 chin #endif 443 4887 chin ".]" 444 4887 chin "[t:text?Open in text mode" 445 4887 chin #ifndef O_TEXT 446 4887 chin " (not supported/ignored on this platform)" 447 4887 chin #endif 448 4887 chin ".]" 449 4887 chin "[c:create?Open for create.]" 450 4887 chin "[i:inherit?Open without the close-on-exec bit set.]" 451 4887 chin "[I:noinherit?Open with the close-on-exec bit set.]" 452 4887 chin "[r:read?Open with read access.]" 453 4887 chin "[w:write?Open with write access.]" 454 4887 chin "[m:mode]:[mode:=rwrwrw?Open with access mode \amode\a.]" 455 4887 chin "[x:exclusive?Open exclusive.]" 456 4887 chin 457 4887 chin "[N:nofollow?If the path names a symbolic link, open fails with ELOOP " 458 4887 chin #ifndef O_NOFOLLOW 459 4887 chin " (not supported/ignored on this platform)" 460 4887 chin #endif 461 4887 chin ".]" 462 4887 chin "[S:sync?Write I/O operations on the file descriptor complete as " 463 4887 chin "defined by synchronized I/O file integrity completion" 464 4887 chin #ifndef O_SYNC 465 4887 chin " (not supported/ignored on this platform)" 466 4887 chin #endif 467 4887 chin ".]" 468 4887 chin "[T:trunc?If the file exists and is a regular file, and the file " 469 4887 chin "is successfully opened read/write or write-only, its length is " 470 4887 chin "truncated to 0 and the mode and owner are unchanged. It " 471 4887 chin "has no effect on FIFO special files or terminal device " 472 4887 chin "files. Its effect on other file types is " 473 4887 chin "implementation-dependent. The result of using -T " 474 4887 chin "with read-only files is undefined" 475 4887 chin #ifndef O_TRUNC 476 4887 chin " (not supported/ignored on this platform)" 477 4887 chin #endif 478 4887 chin ".]" 479 4887 chin "\n" 480 4887 chin "\nvar file\n" 481 4887 chin "\n" 482 4887 chin "[+EXIT STATUS?]{" 483 4887 chin "[+0?Success.]" 484 4887 chin "[+>0?An error occurred.]" 485 4887 chin "}" 486 4887 chin "[+SEE ALSO?\btmpfile\b(1),\bdup\b(1),\bclose\b(1),\bstat\b(1),\bpoll\b(1),\bstat\b(2)]" 487 4887 chin ; 488 4887 chin 489 4887 chin 490 4887 chin extern int b_open(int argc, char *argv[], void *extra) 491 4887 chin { 492 4887 chin register Namval_t *np; 493 4887 chin register int n,oflag=0; 494 8462 April Shell_t *shp = sh_contexttoshell(extra); 495 4887 chin struct filedata *fdp; 496 4887 chin mode_t mode = 0666; 497 4887 chin long flags = 0; 498 4887 chin int fd = -1; 499 4887 chin char *arg; 500 4887 chin 501 4887 chin while (n = optget(argv, sh_optopen)) switch (n) 502 4887 chin { 503 4887 chin case 'r': 504 4887 chin case 'w': 505 4887 chin case 'i': 506 4887 chin flags |= letterbit(n); 507 4887 chin break; 508 4887 chin case 'I': 509 4887 chin flags &= ~(letterbit('i')); 510 4887 chin break; 511 4887 chin case 'b': 512 4887 chin #ifdef O_BINARY 513 4887 chin oflag |= O_BINARY; 514 4887 chin #endif 515 4887 chin break; 516 4887 chin case 't': 517 4887 chin #ifdef O_TEXT 518 4887 chin oflag |= O_TEXT; 519 4887 chin #endif 520 4887 chin break; 521 4887 chin case 'N': 522 4887 chin #ifdef O_NOFOLLOW 523 4887 chin oflag |= O_NOFOLLOW; 524 4887 chin #endif 525 4887 chin break; 526 4887 chin case 'T': 527 4887 chin #ifdef O_TRUNC 528 4887 chin oflag |= O_TRUNC; 529 4887 chin #endif 530 4887 chin break; 531 4887 chin case 'x': 532 4887 chin oflag |= O_EXCL; 533 4887 chin break; 534 4887 chin case 'c': 535 4887 chin oflag |= O_CREAT; 536 4887 chin break; 537 4887 chin case 'a': 538 4887 chin oflag |= O_APPEND; 539 4887 chin break; 540 4887 chin case 'S': 541 4887 chin #ifdef O_SYNC 542 4887 chin oflag |= O_SYNC; 543 4887 chin #endif 544 4887 chin break; 545 4887 chin case 'm': 546 4887 chin mode = strperm(arg = opt_info.arg, &opt_info.arg, mode); 547 4887 chin if (*opt_info.arg) 548 4887 chin errormsg(SH_DICT, ERROR_system(1), "%s: invalid mode", arg); 549 4887 chin break; 550 4887 chin case ':': 551 4887 chin errormsg(SH_DICT, 2, "%s", opt_info.arg); 552 4887 chin break; 553 4887 chin case '?': 554 4887 chin errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg); 555 4887 chin break; 556 4887 chin } 557 4887 chin argc -= opt_info.index; 558 4887 chin argv += opt_info.index; 559 4887 chin if(argc!=2 || !(flags&(letterbit('r')|letterbit('w')))) 560 4887 chin errormsg(SH_DICT, ERROR_usage(2), optusage((char*)0)); 561 4887 chin 562 4887 chin if(flags&letterbit('r')) 563 4887 chin { 564 4887 chin if(flags&letterbit('w')) 565 4887 chin oflag |= O_RDWR; 566 4887 chin else 567 4887 chin oflag |= O_RDONLY; 568 4887 chin } 569 4887 chin else if(flags&letterbit('w')) 570 4887 chin oflag |= O_WRONLY; 571 4887 chin 572 4887 chin fd = sh_open(argv[1], oflag, mode); 573 4887 chin if(fd<0) 574 4887 chin errormsg(SH_DICT, ERROR_system(1), "%s: open failed", argv[1]); 575 4887 chin 576 4887 chin if(!(flags&letterbit('i'))) 577 4887 chin fcntl(fd, F_SETFL, 0); 578 4887 chin 579 4887 chin np = nv_open(argv[0], shp->var_tree, NV_ARRAY|NV_VARNAME|NV_NOASSIGN); 580 4887 chin if(!nv_isnull(np)) 581 4887 chin nv_unset(np); 582 4887 chin mkclass(np, &Fileclass); 583 4887 chin fdp = (struct filedata*)np->nvalue; 584 4887 chin fstat(fd, &fdp->statb); 585 4887 chin fdp->fd = fd; 586 4887 chin fdp->name = strdup(argv[1]); 587 4887 chin return(0); 588 4887 chin } 589 4887 chin 590 4887 chin static const char sh_optclose[] = 591 4887 chin "[-?\n@(#)$Id: close (AT&T Labs Research) 2007-04-21 $\n]" 592 4887 chin "[-author?Roland Mainz <roland.mainz (at) nrubsig.org>]" 593 4887 chin "[-license?http://www.opensource.org/licenses/cpl1.0.txt]" 594 4887 chin "[+NAME? close - close a file descriptor]" 595 4887 chin "[+DESCRIPTION?\bclose\b closes the file descriptor specified by fd.]" 596 4887 chin "\n" 597 4887 chin "\nfd\n" 598 4887 chin "\n" 599 4887 chin "[+EXIT STATUS?]{" 600 4887 chin "[+0?Success.]" 601 4887 chin "[+>0?An error occurred.]" 602 4887 chin "}" 603 4887 chin "[+SEE ALSO?\bopen\b(1),\bdup\b(1),\btmpfile\b(1),\bpoll\b(1),\bstat\b(1)]" 604 4887 chin ; 605 4887 chin 606 4887 chin extern int b_close(int argc, char *argv[], void *extra) 607 4887 chin { 608 4887 chin register int n=0; 609 4887 chin int fd = -1; 610 4887 chin 611 4887 chin while (n = optget(argv, sh_optclose)) switch (n) 612 4887 chin { 613 4887 chin case ':': 614 4887 chin errormsg(SH_DICT, 2, "%s", opt_info.arg); 615 4887 chin break; 616 4887 chin case '?': 617 4887 chin errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg); 618 4887 chin break; 619 4887 chin } 620 4887 chin argc -= opt_info.index; 621 4887 chin argv += opt_info.index; 622 4887 chin if(argc!=1) 623 4887 chin errormsg(SH_DICT, ERROR_usage(2), optusage((char*)0)); 624 4887 chin 625 4887 chin errno = 0; 626 4887 chin fd = strtol(argv[0], (char **)NULL, 0); 627 4887 chin if (errno != 0 || fd < 0) 628 4887 chin errormsg(SH_DICT, ERROR_system(1), "%s: invalid descriptor", argv[0]); 629 4887 chin 630 4887 chin n = sh_close(fd); 631 4887 chin 632 4887 chin if (n < 0) 633 4887 chin errormsg(SH_DICT, ERROR_system(1), "%s: close error", argv[0]); 634 4887 chin 635 4887 chin return(n==0?0:1); 636 4887 chin } 637 4887 chin 638 4887 chin 639 4887 chin static const char sh_opttmpfile[] = 640 4887 chin "[-?\n@(#)$Id: tmpfile (AT&T Labs Research) 2007-05-07 $\n]" 641 4887 chin "[-author?Roland Mainz <roland.mainz (at) nrubsig.org>]" 642 4887 chin "[-license?http://www.opensource.org/licenses/cpl1.0.txt]" 643 4887 chin "[+NAME? tmpfile - create a shell variable correspnding to a temporary file]" 644 4887 chin "[+DESCRIPTION?\btmpfile\b creates the compound variable \avar\a correspinding " 645 4887 chin "to a temporary file. The elements of \avar\a " 646 4887 chin "are the names of elements in the \astat\a structure with the \bst_\b " 647 4887 chin "prefix removed.]" 648 4887 chin "[i:inherit?Open without the close-on-exec bit set.]" 649 4887 chin "[I:noinherit?Open with the close-on-exec bit set.]" 650 4887 chin "\n" 651 4887 chin "\nvar\n" 652 4887 chin "\n" 653 4887 chin "[+EXIT STATUS?]{" 654 4887 chin "[+0?Success.]" 655 4887 chin "[+>0?An error occurred.]" 656 4887 chin "}" 657 4887 chin "[+SEE ALSO?\bopen\b(1),\bdup\b(1),\bclose\b(1),\bstat\b(1),\bstat\b(2)]" 658 4887 chin ; 659 4887 chin 660 4887 chin 661 4887 chin extern int b_tmpfile(int argc, char *argv[], void *extra) 662 4887 chin { 663 4887 chin register Namval_t *np; 664 4887 chin register int n; 665 8462 April Shell_t *shp = sh_contexttoshell(extra); 666 4887 chin struct filedata *fdp; 667 8462 April bool inherit = false; 668 4887 chin FILE *file = NULL; 669 4887 chin int ffd, fd = -1; 670 4887 chin while (n = optget(argv, sh_opttmpfile)) switch (n) 671 4887 chin { 672 4887 chin case 'i': 673 8462 April inherit = true; 674 4887 chin break; 675 4887 chin case 'I': 676 8462 April inherit = false; 677 4887 chin break; 678 4887 chin case ':': 679 4887 chin errormsg(SH_DICT, 2, "%s", opt_info.arg); 680 4887 chin break; 681 4887 chin case '?': 682 4887 chin errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg); 683 4887 chin break; 684 4887 chin } 685 4887 chin argc -= opt_info.index; 686 4887 chin argv += opt_info.index; 687 4887 chin if(argc!=1) 688 4887 chin errormsg(SH_DICT, ERROR_usage(2), optusage((char*)0)); 689 4887 chin 690 4887 chin file = tmpfile(); 691 4887 chin if(!file) 692 4887 chin errormsg(SH_DICT, ERROR_system(1), "%s: tmpfile failed", argv[1]); 693 4887 chin ffd = fileno(file); 694 4887 chin fd = sh_dup(ffd); 695 4887 chin if(fd<0) 696 4887 chin errormsg(SH_DICT, ERROR_system(1), "%s: tmpfile failed", argv[1]); 697 4887 chin fclose(file); 698 4887 chin 699 4887 chin if(!inherit) 700 4887 chin fcntl(fd, F_SETFL, 0); 701 4887 chin 702 4887 chin np = nv_open(argv[0], shp->var_tree, NV_ARRAY|NV_VARNAME|NV_NOASSIGN); 703 4887 chin if(!nv_isnull(np)) 704 4887 chin nv_unset(np); 705 4887 chin mkclass(np,&Fileclass); 706 4887 chin fdp = (struct filedata*)np->nvalue; 707 4887 chin 708 4887 chin fstat(fd, &fdp->statb); 709 4887 chin fdp->fd = fd; 710 4887 chin fdp->name = NULL; 711 4887 chin return(0); 712 4887 chin } 713 4887 chin 714 4887 chin static const char sh_optdup[] = 715 4887 chin "[-?\n@(#)$Id: dup (AT&T Labs Research) 2007-05-07 $\n]" 716 4887 chin "[-author?Roland Mainz <roland.mainz (at) nrubsig.org>]" 717 4887 chin "[-license?http://www.opensource.org/licenses/cpl1.0.txt]" 718 4887 chin "[+NAME? dup - duplicate an open file descriptor]" 719 4887 chin "[+DESCRIPTION?The \bdup\b commands returns a new file descriptor having the " 720 4887 chin "following in common with the original open file descriptor " 721 4887 chin "fd: same open file (or pipe), same file pointer (that is, both file descriptors " 722 4887 chin "share one file pointer) same access mode (read, write or read/write). " 723 4887 chin "The file descriptor returned is the lowest one available.]" 724 4887 chin "[i:inherit?Open without the close-on-exec bit set.]" 725 4887 chin "[I:noinherit?Open with the close-on-exec bit set.]" 726 4887 chin "\n" 727 4887 chin "\nvar fd\n" 728 4887 chin "\n" 729 4887 chin "[+EXIT STATUS?]{" 730 4887 chin "[+0?Success.]" 731 4887 chin "[+>0?An error occurred.]" 732 4887 chin "}" 733 4887 chin "[+SEE ALSO?\bopen\b(1),\btmpfile\b(1),\bclose\b(1),\bpoll\b(1),\bstat\b(1)]" 734 4887 chin ; 735 4887 chin 736 4887 chin 737 4887 chin extern int b_dup(int argc, char *argv[], void *extra) 738 4887 chin { 739 4887 chin register Namval_t *np; 740 4887 chin register int n; 741 8462 April Shell_t *shp = sh_contexttoshell(extra); 742 4887 chin struct filedata *fdp; 743 8462 April bool inherit = false; 744 4887 chin int ffd, fd = -1; 745 4887 chin while (n = optget(argv, sh_optdup)) switch (n) 746 4887 chin { 747 4887 chin case 'i': 748 8462 April inherit = true; 749 4887 chin break; 750 4887 chin case 'I': 751 8462 April inherit = false; 752 4887 chin break; 753 4887 chin case ':': 754 4887 chin errormsg(SH_DICT, 2, "%s", opt_info.arg); 755 4887 chin break; 756 4887 chin case '?': 757 4887 chin errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg); 758 4887 chin break; 759 4887 chin } 760 4887 chin argc -= opt_info.index; 761 4887 chin argv += opt_info.index; 762 4887 chin if(argc!=2) 763 4887 chin errormsg(SH_DICT, ERROR_usage(2), optusage((char*)0)); 764 4887 chin 765 4887 chin errno = 0; 766 4887 chin ffd = strtol(argv[1], (char **)NULL, 0); 767 4887 chin if (errno != 0 || ffd < 0) 768 4887 chin errormsg(SH_DICT, ERROR_system(1), "%s: invalid fd", argv[1]); 769 4887 chin 770 4887 chin fd = sh_dup(ffd); 771 4887 chin if(fd<0) 772 4887 chin errormsg(SH_DICT, ERROR_system(1), "%s: dup failed", argv[1]); 773 4887 chin 774 4887 chin if(!inherit) 775 4887 chin fcntl(fd,F_SETFL,0); 776 4887 chin 777 4887 chin np = nv_open(argv[0],shp->var_tree,NV_ARRAY|NV_VARNAME|NV_NOASSIGN); 778 4887 chin if(!nv_isnull(np)) 779 4887 chin nv_unset(np); 780 4887 chin mkclass(np, &Fileclass); 781 4887 chin fdp = (struct filedata*)np->nvalue; 782 4887 chin 783 4887 chin fstat(fd, &fdp->statb); 784 4887 chin fdp->fd = fd; 785 4887 chin fdp->name = NULL; 786 4887 chin return(0); 787 4887 chin } 788 4887 chin 789 4887 chin static const char sh_optstat[] = 790 4887 chin "[-?\n@(#)$Id: stat (AT&T Labs Research) 2007-05-07 $\n]" 791 4887 chin "[-author?David Korn <dgk (at) research.att.com>]" 792 4887 chin "[-author?Roland Mainz <roland.mainz (at) nrubsig.org>]" 793 4887 chin "[-license?http://www.opensource.org/licenses/cpl1.0.txt]" 794 4887 chin "[+NAME? stat - get file status]" 795 4887 chin "[+DESCRIPTION?\bstat\b creates the compound variable \avar\a correspinding " 796 4887 chin "to the file given by the pathname \afile\a. The elements of \avar\a " 797 4887 chin "are the names of elements in the \astat\a structure with the \bst_\b " 798 4887 chin "prefix removed.]" 799 4887 chin "[l:lstat?If the the named file is a symbolic link returns information about " 800 4887 chin "the link itself.]" 801 4887 chin "\n" 802 4887 chin "\nvar file\n" 803 4887 chin "\n" 804 4887 chin "[+EXIT STATUS?]{" 805 4887 chin "[+0?Success.]" 806 4887 chin "[+>0?An error occurred.]" 807 4887 chin "}" 808 4887 chin "[+SEE ALSO?\bopen\b(1),\btmpfile\b(1),\bdup\b(1),\bclose\b(1),\bpoll\b(1),\bstat\b(2),\blstat\b(2)]" 809 4887 chin ; 810 4887 chin 811 4887 chin 812 4887 chin extern int b_stat(int argc, char *argv[], void *extra) 813 4887 chin { 814 4887 chin register Namval_t *np; 815 4887 chin register int n; 816 8462 April Shell_t *shp = sh_contexttoshell(extra); 817 4887 chin struct filedata *fdp; 818 4887 chin long flags = 0; 819 4887 chin struct stat statb; 820 4887 chin while (n = optget(argv, sh_optstat)) switch (n) 821 4887 chin { 822 4887 chin case 'l': 823 4887 chin flags |= letterbit(n); 824 4887 chin break; 825 4887 chin case ':': 826 4887 chin errormsg(SH_DICT, 2, "%s", opt_info.arg); 827 4887 chin break; 828 4887 chin case '?': 829 4887 chin errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg); 830 4887 chin break; 831 4887 chin } 832 4887 chin argc -= opt_info.index; 833 4887 chin argv += opt_info.index; 834 4887 chin if(argc!=2) 835 4887 chin errormsg(SH_DICT, ERROR_usage(2), optusage((char*)0)); 836 4887 chin 837 4887 chin if(flags&letterbit('l')) 838 4887 chin { 839 4887 chin if(lstat(argv[1], &statb) < 0) 840 4887 chin errormsg(SH_DICT, ERROR_system(1), "%s: stat failed", argv[1]); 841 4887 chin } 842 4887 chin else 843 4887 chin { 844 4887 chin if(stat(argv[1], &statb) < 0) 845 4887 chin errormsg(SH_DICT, ERROR_system(1), "%s: stat failed", argv[1]); 846 4887 chin 847 4887 chin } 848 4887 chin 849 4887 chin np = nv_open(argv[0],shp->var_tree,NV_ARRAY|NV_VARNAME|NV_NOASSIGN); 850 4887 chin if(!nv_isnull(np)) 851 4887 chin nv_unset(np); 852 4887 chin mkclass(np,&Fileclass); 853 4887 chin fdp = (struct filedata*)np->nvalue; 854 4887 chin fdp->statb = statb; 855 4887 chin fdp->fd = -1; 856 4887 chin fdp->name = strdup(argv[1]); 857 4887 chin return(0); 858 4887 chin } 859 4887 chin 860 4887 chin 861 4887 chin static const char sh_optrewind[] = 862 4887 chin "[-?\n@(#)$Id: rewind (AT&T Labs Research) 2007-05-07 $\n]" 863 4887 chin "[-author?Roland Mainz <roland.mainz (at) nrubsig.org>]" 864 4887 chin "[-license?http://www.opensource.org/licenses/cpl1.0.txt]" 865 4887 chin "[+NAME? rewind - reset file position indicator in a stream]" 866 4887 chin "[+DESCRIPTION?The \brewind\b command will move the file pointer of fd to position 0.]" 867 4887 chin "\n" 868 4887 chin "\nfd\n" 869 4887 chin "\n" 870 4887 chin "[+EXIT STATUS?]{" 871 4887 chin "[+0?Success.]" 872 4887 chin "[+>0?An error occurred.]" 873 4887 chin "}" 874 4887 chin "[+SEE ALSO?\bopen\b(1),\btmpfile\b(1),\bdup\b(1),\bclose\b(1),\bstat\b(1),\bstat\b(2)]" 875 4887 chin ; 876 4887 chin 877 4887 chin 878 4887 chin extern int b_rewind(int argc, char *argv[], void *extra) 879 4887 chin { 880 8462 April Shell_t *shp = sh_contexttoshell(extra); 881 4887 chin int fd = -1; 882 4887 chin register int n; 883 4887 chin while (n = optget(argv, sh_optrewind)) switch (n) 884 4887 chin { 885 4887 chin case ':': 886 4887 chin errormsg(SH_DICT, 2, "%s", opt_info.arg); 887 4887 chin break; 888 4887 chin case '?': 889 4887 chin errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg); 890 4887 chin break; 891 4887 chin } 892 4887 chin argc -= opt_info.index; 893 4887 chin argv += opt_info.index; 894 4887 chin if(argc!=1) 895 4887 chin errormsg(SH_DICT, ERROR_usage(2), optusage((char*)0)); 896 4887 chin 897 4887 chin errno = 0; 898 4887 chin fd = strtol(argv[0], (char **)NULL, 0); 899 4887 chin if (errno != 0 || fd < 0) 900 4887 chin errormsg(SH_DICT, ERROR_system(1), "%s: invalid fd", argv[0]); 901 4887 chin 902 4887 chin if (sh_seek(fd, 0, SEEK_SET) == (off_t)-1) 903 4887 chin errormsg(SH_DICT, ERROR_system(1), "seek error"); 904 4887 chin 905 4887 chin return(0); 906 4887 chin } 907