Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/kshlib/open/open.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2007-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* David Korn <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
static const char id[] = "\n@(#)$Id: open (AT&T Research) 1998-07-07 $\0\n";
23
24
#include <shell.h>
25
#include <option.h>
26
#include <stk.h>
27
#include <tm.h>
28
#ifndef SH_DICT
29
# define SH_DICT "libshell"
30
#endif
31
#ifndef array_elem
32
# define array_elem(ap) ((ap)->nelem&0xffffff)
33
#endif
34
35
36
/*
37
* time formatting related
38
*/
39
struct dctime
40
{
41
Namfun_t fun;
42
Namval_t *format;
43
};
44
45
static char *get_time(Namval_t* np, Namfun_t* nfp)
46
{
47
static char buff[256];
48
struct dctime *dp = (struct dctime*)nfp;
49
time_t t = nv_getn(np,nfp);
50
char *format = nv_getval(dp->format);
51
tmfmt(buff,sizeof(buff),format,(time_t*)0);
52
return(buff);
53
}
54
55
static void put_time(Namval_t* np, const char* val, int flag, Namfun_t* nfp)
56
{
57
struct dctime *dp = (struct dctime*)nfp;
58
char *last;
59
if(val)
60
{
61
int32_t t;
62
if(flag&NV_INTEGER)
63
{
64
if(flag&NV_LONG)
65
t = *(Sfdouble_t*)val;
66
else
67
t = *(double*)val;
68
}
69
else
70
{
71
t = tmdate(val, &last, (time_t*)0);
72
if(*last)
73
errormsg(SH_DICT,ERROR_exit(1),"%s: invalid date/time string",val);
74
}
75
nv_putv(np,(char*)&t,NV_INTEGER,nfp);
76
}
77
else
78
{
79
nv_unset(dp->format);
80
free((void*)dp->format);
81
nv_putv(np,val,flag,nfp);
82
}
83
}
84
85
static Namval_t *create_time(Namval_t *np, const char *name, int flags, Namfun_t *nfp)
86
{
87
struct dctime *dp = (struct dctime*)nfp;
88
if(strcmp(name,"format"))
89
return((Namval_t*)0);
90
return(dp->format);
91
}
92
93
static const Namdisc_t timedisc =
94
{
95
sizeof(struct dctime),
96
put_time,
97
get_time,
98
0,
99
0,
100
create_time,
101
};
102
103
104
static Namval_t *make_time(Namval_t* np)
105
{
106
int offset = stktell(stkstd);
107
char *name = nv_name(np);
108
struct dctime *dp = newof(NULL,struct dctime,1,0);
109
if(!dp)
110
return((Namval_t*)0);
111
sfprintf(stkstd,"%s.format\0",name);
112
sfputc(stkstd,0);
113
dp->format = nv_search(stkptr(stkstd,offset),sh.var_tree,NV_ADD);
114
dp->fun.disc = &timedisc;
115
nv_stack(np,&dp->fun);
116
return(np);
117
}
118
119
/*
120
* mode formatting related
121
*/
122
static char *get_mode(Namval_t* np, Namfun_t* nfp)
123
{
124
mode_t mode = nv_getn(np,nfp);
125
return(fmtperm(mode));
126
}
127
128
static void put_mode(Namval_t* np, const char* val, int flag, Namfun_t* nfp)
129
{
130
if(val)
131
{
132
int32_t mode;
133
char *last;
134
if(flag&NV_INTEGER)
135
{
136
if(flag&NV_LONG)
137
mode = *(Sfdouble_t*)val;
138
else
139
mode = *(double*)val;
140
}
141
else
142
{
143
mode = strperm(val, &last,0);
144
if(*last)
145
errormsg(SH_DICT,ERROR_exit(1),"%s: invalid mode string",val);
146
}
147
nv_putv(np,(char*)&mode,NV_INTEGER,nfp);
148
}
149
else
150
nv_putv(np,val,flag,nfp);
151
}
152
153
static const Namdisc_t modedisc =
154
{
155
0,
156
put_mode,
157
get_mode,
158
};
159
160
static Namval_t *make_mode(Namval_t* np)
161
{
162
char *name = nv_name(np);
163
Namfun_t *nfp = newof(NULL,Namfun_t,1,0);
164
if(!nfp)
165
return((Namval_t*)0);
166
nfp->disc = &modedisc;
167
nv_stack(np,nfp);
168
return(np);
169
}
170
171
/*
172
* field related typese and functions
173
*/
174
typedef struct _field_
175
{
176
char *name; /* field name */
177
int flags; /* flags */
178
short offset; /* offset of field into data */
179
short size; /* size of field */
180
Namval_t *(*make)(Namval_t*); /* discipline constructor */
181
} Shfield_t;
182
183
/*
184
* lookup field in field table
185
*/
186
static Shfield_t *sh_findfield(Shfield_t *ftable, int nelem, const char *name)
187
{
188
Shfield_t *fp = ftable;
189
register int i,n;
190
register const char *cp;
191
for(cp=name; *cp; cp++)
192
{
193
if(*cp=='.')
194
break;
195
}
196
n = cp-name;
197
for(i=0; i < nelem; i++,fp++)
198
{
199
if(memcmp(fp->name,name,n)==0 && fp->name[n]==0)
200
return(fp);
201
}
202
return(0);
203
}
204
205
/*
206
* class types and functions
207
*/
208
209
typedef struct _class_
210
{
211
int nelem; /* number of elements */
212
int dsize; /* size for data structure */
213
Shfield_t *fields; /* field description table */
214
} Shclass_t;
215
216
struct dcclass
217
{
218
Namfun_t fun;
219
Shclass_t sclass;
220
};
221
222
static Namval_t *sh_newnode(register Shfield_t *fp, Namval_t *np)
223
{
224
char *val = np->nvalue + fp->offset;
225
char *name = nv_name(np);
226
register Namval_t *nq;
227
int offset = stktell(stkstd);
228
sfprintf(stkstd,"%s.%s\0",name,fp->name);
229
sfputc(stkstd,0);
230
nq = nv_search(stkptr(stkstd,offset),sh.var_tree,NV_ADD);
231
if(fp->size<0)
232
val = *(char**)val;
233
nv_putval(nq,val,fp->flags|NV_NOFREE);
234
if(fp->make)
235
(*fp->make)(nq);
236
return(nq);
237
}
238
239
static Namval_t *fieldcreate(Namval_t *np, const char *name, int flags, Namfun_t *nfp)
240
{
241
struct dcclass *dcp = (struct dcclass*)nfp;
242
Shclass_t *sp = &dcp->sclass;
243
Shfield_t *fp = sh_findfield(sp->fields,sp->nelem,name);
244
Namval_t *nq,**nodes = (Namval_t**)(dcp+1);
245
int n = fp-sp->fields;
246
int len = strlen(fp->name);
247
if(!(nq=nodes[n]))
248
{
249
nodes[n] = nq = sh_newnode(fp,np);
250
nfp->last = "";
251
}
252
if(name[len]==0)
253
return(nq);
254
return(nq);
255
}
256
257
static void genvalue(Sfio_t *out, Shclass_t *sp, int indent, Namval_t *npar)
258
{
259
Shfield_t *fp = sp->fields;
260
Namval_t *np, **nodes= (Namval_t**)(sp+1);
261
register int i,isarray;
262
if(out)
263
{
264
sfwrite(out,"(\n",2);
265
indent++;
266
}
267
for(i=0; i < sp->nelem; i++,fp++)
268
{
269
#if 0
270
/* handle recursive case */
271
#endif
272
if(!(np=nodes[i]) && out)
273
np = sh_newnode(fp,npar);
274
if(np)
275
{
276
isarray=0;
277
if(nv_isattr(np,NV_ARRAY))
278
{
279
isarray=1;
280
if(array_elem(nv_arrayptr(np))==0)
281
isarray=2;
282
else
283
nv_putsub(np,(char*)0,ARRAY_SCAN);
284
}
285
sfnputc(out,'\t',indent);
286
sfputr(out,fp->name,(isarray==2?'\n':'='));
287
if(isarray)
288
{
289
if(isarray==2)
290
continue;
291
sfwrite(out,"(\n",2);
292
sfnputc(out,'\t',++indent);
293
}
294
while(1)
295
{
296
char *fmtq;
297
if(isarray)
298
{
299
sfprintf(out,"[%s]",sh_fmtq(nv_getsub(np)));
300
sfputc(out,'=');
301
}
302
if(!(fmtq=nv_getval(np)) || !(fmtq=sh_fmtq(fmtq)))
303
fmtq = "";
304
sfputr(out,fmtq,'\n');
305
if(!nv_nextsub(np))
306
break;
307
sfnputc(out,'\t',indent);
308
}
309
if(isarray)
310
{
311
sfnputc(out,'\t',--indent);
312
sfwrite(out,")\n",2);
313
}
314
}
315
}
316
if(out)
317
{
318
if(indent>1)
319
sfnputc(out,'\t',indent-1);
320
sfputc(out,')');
321
}
322
}
323
324
static char *walk_class(register Namval_t *np, int dlete, struct dcclass *dcp)
325
{
326
static Sfio_t *out;
327
Sfio_t *outfile;
328
int savtop = stktell(stkstd);
329
char *savptr = stkfreeze(stkstd,0);
330
if(dlete)
331
outfile = 0;
332
else if(!(outfile=out))
333
outfile = out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
334
else
335
sfseek(outfile,0L,SEEK_SET);
336
genvalue(outfile,&dcp->sclass,0,np);
337
stkset(stkstd,savptr,savtop);
338
if(!outfile)
339
return((char*)0);
340
sfputc(out,0);
341
return((char*)out->_data);
342
}
343
344
static char *get_classval(Namval_t* np, Namfun_t* nfp)
345
{
346
return(walk_class(np,0,(struct dcclass *)nfp));
347
}
348
349
static void put_classval(Namval_t* np, const char* val, int flag, Namfun_t* nfp)
350
{
351
walk_class(np,1,(struct dcclass *)nfp);
352
if(nfp = nv_stack(np,(Namfun_t*)0))
353
{
354
free((void*)nfp);
355
if(np->nvalue && !nv_isattr(np,NV_NOFREE))
356
free((void*)np->nvalue);
357
}
358
if(val)
359
nv_putval(np,val,flag);
360
}
361
362
static const Namdisc_t classdisc =
363
{
364
sizeof(struct dcclass),
365
put_classval,
366
get_classval,
367
0,
368
0,
369
fieldcreate
370
};
371
372
static int mkclass(Namval_t *np, Shclass_t *sp)
373
{
374
struct dcclass *tcp = newof(NULL,struct dcclass,1,sp->nelem*sizeof(Namval_t*));
375
if(!tcp)
376
return(0);
377
memset((void*)(tcp+1),0,sp->nelem*sizeof(Namval_t*));
378
tcp->fun.disc = &classdisc;
379
tcp->sclass = *sp;
380
np->nvalue = (char*)calloc(sp->dsize,1);
381
nv_stack(np,&tcp->fun);
382
return(1);
383
}
384
385
/*
386
* ====================from here down is file class specific
387
*/
388
static struct stat *Sp;
389
390
struct filedata
391
{
392
struct stat statb;
393
int fd;
394
char *name;
395
};
396
397
static Shfield_t filefield[] =
398
{
399
{ "atime", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_atime), sizeof(Sp->st_atime), make_time},
400
{ "ctime", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_ctime), sizeof(Sp->st_ctime), make_time},
401
{ "dev", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_dev),sizeof(Sp->st_dev)},
402
{ "fd", NV_INTEGER|NV_RDONLY, offsetof(struct filedata,fd), sizeof(int)},
403
{ "gid", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_gid), sizeof(Sp->st_gid)},
404
{ "ino", NV_LONG|NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_ino), sizeof(Sp->st_ino)},
405
{ "mode", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_mode), sizeof(Sp->st_mode), make_mode},
406
{ "mtime", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_mtime), sizeof(Sp->st_mtime), make_time},
407
{ "name", NV_RDONLY, offsetof(struct filedata,name), -1 },
408
{ "nlink", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_nlink), sizeof(Sp->st_nlink)},
409
{ "size", NV_LONG|NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_size), sizeof(Sp->st_size)},
410
{ "uid", NV_INTEGER|NV_RDONLY, offsetof(struct stat,st_uid), sizeof(Sp->st_uid)}
411
};
412
413
static Shclass_t Fileclass =
414
{
415
sizeof(filefield)/sizeof(*filefield),
416
sizeof(struct filedata),
417
filefield
418
};
419
420
421
#define letterbit(bit) (1<<((bit)-'a'))
422
423
static const char sh_optopen[] =
424
"[-?\n@(#)$Id: open (AT&T Labs Research) 2007-03-11 $\n]"
425
"[-author?David Korn <[email protected]>]"
426
"[-license?http://www.opensource.org/licenses/cpl1.0.txt]"
427
"[+NAME? open - create a shell variable correspnding to a file]"
428
"[+DESCRIPTION?\bopen\b creates the compound variable \avar\a correspinding "
429
"to the file given by the pathname \afile\a. The elements of \avar\a "
430
"are the names of elements in the \astat\a structure with the \bst_\b "
431
"prefix removed.]"
432
"[+?If the \b-r\b and/or \b-w\b mode is specified, then \afile\a is opened and "
433
"the variable \avar\a\b.fd\b is the file descriptor.]"
434
"[a:append?Open for append.]"
435
"[b:binary?Open in binary mode.]"
436
"[c:create?Open for create.]"
437
"[i:inherit?Open without the close-on-exec bit set.]"
438
"[r:read?Open with read access.]"
439
"[w:write?Open with write access.]"
440
"[m:mode]:[mode:=rwrwrw?Open with access mode \amode\a.]"
441
"[x:exclusive?Open exclusive.]"
442
"\n"
443
"\nvar file\n"
444
"\n"
445
"[+EXIT STATUS?]{"
446
"[+0?Success.]"
447
"[+>0?An error occurred.]"
448
"}"
449
"[+SEE ALSO?\bstat\b(2)]"
450
;
451
452
453
extern int b_open(int argc, char *argv[], Shbltin_t *context)
454
{
455
register Namval_t *np;
456
register int n,oflag=0;
457
Shell_t *shp = context->shp;
458
struct filedata *fdp;
459
struct stat statb;
460
mode_t mode = 0666;
461
long flags = 0;
462
int fd = -1;
463
while (n = optget(argv, sh_optopen)) switch (n)
464
{
465
case 'r':
466
case 'i':
467
case 'w':
468
flags |= letterbit(n);
469
break;
470
case 'b':
471
#ifdef O_BINARY
472
oflag |= O_BINARY;
473
#endif
474
break;
475
case 't':
476
#ifdef O_TEXT
477
oflag |= O_TEXT;
478
#endif
479
break;
480
case 'x':
481
oflag |= O_EXCL;
482
break;
483
case 'c':
484
oflag |= O_CREAT;
485
break;
486
case 'a':
487
oflag |= O_APPEND;
488
break;
489
case 'm':
490
break;
491
case ':':
492
errormsg(SH_DICT,2, "%s", opt_info.arg);
493
break;
494
case '?':
495
errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
496
break;
497
}
498
argc -= opt_info.index;
499
argv += opt_info.index;
500
if(argc!=2)
501
errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
502
if(!(flags&(letterbit('r')|letterbit('w'))))
503
{
504
if(stat(argv[1],&statb)<0)
505
errormsg(SH_DICT,ERROR_system(1),"%s: open failed",argv[1]);
506
}
507
else
508
{
509
if(flags&letterbit('r'))
510
{
511
if(flags&letterbit('w'))
512
oflag |= O_RDWR;
513
else
514
oflag |= O_RDONLY;
515
}
516
else if(flags&letterbit('w'))
517
oflag |= O_WRONLY;
518
fd = open(argv[1],oflag,mode);
519
if(fd<0)
520
errormsg(SH_DICT,ERROR_system(1),"%s: open failed",argv[1]);
521
}
522
if(!(flags&letterbit('i')))
523
fcntl(fd,F_SETFL,0);
524
np = nv_open(argv[0],shp->var_tree,NV_ARRAY|NV_VARNAME|NV_NOASSIGN);
525
if(!nv_isnull(np))
526
nv_unset(np);
527
mkclass(np,&Fileclass);
528
fdp = (struct filedata*)np->nvalue;
529
if(!(flags&(letterbit('r')|letterbit('w'))))
530
fdp->statb = statb;
531
else
532
fstat(fd,&fdp->statb);
533
fdp->fd = fd;
534
fdp->name = strdup(argv[1]);
535
return(0);
536
}
537
538
SHLIB(open)
539
540