summaryrefslogtreecommitdiff
path: root/support/ctan_chk/ctan_chk.w
blob: b00475c73d6ac51d543dfc3b28903159dc79473e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
% file: ctan_chk.w
%
\def\Tex{\TeX}
\def\cweb{\Cweb}
\def\Cweb{{\prgstyle Cweb}}
\def\prgstyle{\tt \sl }
\def\NOsign{
 {\tt{\char`\#}}
}
\def\Verticalbar{{\tt \char`|}}
\def\GTsign{
\ifmmode
 >
\else
$>$
\fi
}
\def\Arrow{$\Rightarrow$}
\def\prtobrace{$\{$}
\def\prtcbrace{$\}$}
\def\Backslash{
{\tt\char`\\}
}

\def\printlistinglineno{\hskip .7 in \llap{\the\lineno:\quad}}
\def\ptindent#1{\line{\hskip.5in{#1}\hfill}}
\def\Yacco2{Ya$c_2o_2$}
\def\yacco2{\Yacco2}
\def\O2{$O_2$}
\def\o2{\O2}
\def\Cpp{C\kern-.25em \raise.25ex\hbox{\tt $+\kern-0.2ex+$}}
\def\Olinker{$O_{2}^{linker}$}
\def\olinker{$O_{2}^{linker}$}
\def\TILDE{\catcode`\~=11{}~}
\def\INDENT#1#2{\line{\hskip#1{#2}\hfill}}
\def\fbreak{\hfill\break}


@* Gawk program |ctan_chk.gawk|.\fbreak
Basic Gawk program that uses Ctan's published guidelines for authors to help eliminate slopiness in uploaded files/project.
It is completely open for users to program additional guidelines and Ctan's future  adjustments. 
The program came about when I first attempted to upload ``Yacco2'' for Ctan consideration.
As Yacco2 was quite large, it took me 3 attempts to clean up my project.
Depending on how u develop your project, in my case the Yacco2 project for Ctan upload is a subset of the complete system
and so each uplift required the guideline assessment/purging process.

This is my attempt to help both the author in getting the new system in shape for Ctan uplift 
and to lower the Ctan volanteers interaction to aid for publishing on their servers.
It is my thank you to these volanteers / Ctan.
\fbreak
\fbreak
This |gawk| program verifies whether an upload project for CTAN 
follows its published guidelines on their website:\fbreak
\ptindent{http://ctan.org/upload/}
\fbreak
Here is the link to the awk/gawk reference manual for people needing a refresher to its programming statements:\fbreak
\ptindent{https://www.gnu.org/software/gawk/manual/gawk.html\#Reading-Files}

@*1 License.\fbreak
ctan\_chk's distributed source code is subject to the terms of the GNU General Public License (version 3).
If a copy of the MPL was not distributed with this file, you can obtain one at https://gnu.org/licenses/gpl.html.
\fbreak
\fbreak
\ptindent{Project:                   ctan guidelines verifier and corrector program for uploading projects}
\ptindent{Distributed under license: GNU General Public License (version 3).}
\ptindent{Distribution Date:         \today}
\ptindent{Distribution version:      1.0}
\ptindent{Comments:                  Currently for the Unix flavoured Platforms running Gawk}
\ptindent{Author:                    Dave Bone}
\fbreak
\ptindent{Contributors list:}
\ptindent{  Dave Bone}

@*2 |Ctan_chk| reference.\fbreak
Unzip the |ctan_chk.zip| file.
Please read |ctan_chk.pdf| document. It instructs one in ``how to'' use the gawk |ctan_chk.gawk| program.

@*2  Literate Programming genre.\fbreak
|ctan_chk.pdf| user manual and |ctan_chk.gawk| program are generated by the Cweb system's 
{\it{cweave}} and {\it{ctangle}} programs along with the {\it{pdftex}}.
The |ctan_chk_bash| script does it all for u; have a read it doesn't bite.
Please consider using Cweb and joining
``www.tug.org'' where u'll find the Cweb system.

@*1 Comments on program's functions.\fbreak
Normally u edit the |ctan_chk.gawk| file (using gawk comments) as to what "verification function" is called to check out your project's files.
Here is a list of the verification functions to call:\fbreak
Helper functions:\fbreak
\ptindent{|is_file_a_directory| --- is file a directory type rather than a data type?}
\ptindent{|is_file_an_executable| --- Maybe too platform dependent: is it an executable}
\fbreak
Verification functions:\fbreak
\ptindent{|chk_auxiliary_files| --- files that should be removed / deleted}
\ptindent{|chk_file_permissions| --- file execute permissions check}
\ptindent{|chk_extended_file_attributes| --- does file have  extended attribute like @@}
\ptindent{|chk_empty_files| --- zero byte size file?}
\ptindent{|chk_empty_directory| --- empty folder}
\ptindent{|chk_file_to_bypass_in_zip| --- file to bypass by zip using its -x option}
\fbreak
Correction functions:\fbreak
\ptindent{|remove_file_s_execute_attribute| --- Read ``Remove file's execute attribute'' section for details}
\ptindent{|delete_file| --- interacts with user. Used by itself or from other functions like |chk_auxiliary_files|}
\ptindent{|remove_file_s_extended_attributes| --- Remove extended attribute from file (platform dependent)}

@*2 Running Gawk program has 2 run/pass attitude.\fbreak
U run this program twice with appropriate editing sessions inbetween the run passes:\fbreak
\ptindent{run Pass 1 function where your edited functions to call and capturing output with {\it{tee}} utility}
\ptindent{\Arrow{} pass 1's input file is an absolute pathed files list. See |How to use this gawk program| section}
\ptindent{\Arrow{} assess the messages outputted as to what guidelines need to be corrected}
\ptindent{\Arrow{} outputted messages have 2 parts: part 1 the filename and part 2 the quoted message}
\fbreak
\ptindent{run Pass 2 function where u comment out pass 1 call and uncomment pass 2 function call}
\ptindent{\Arrow{} inside the |pass2_correct| function, uncomment the appropriate correction function to call}
\ptindent{\Arrow{} the captured messages from {\it{tee}} of pass 1 is its inputted file}
\ptindent{\Arrow{} in awk/gawk terms this |gawk|'s record is composed of fields where the field separator is space}
\ptindent{\Arrow{} so the 2nd pass receives the 2 fields filename, and message}
\fbreak
\fbreak
Output example of guideline violations from Pass 1:\fbreak
\ptindent{\Arrow{} "/yacco2/.DS\_Store" 'Extended attributes -rwxr-xr-x@@'}
\ptindent{\Arrow{} "/yacco2/.DS\_Store" 'Write permissions -rwxr-xr-x@@ to possibly delete file type: data'}
\ptindent{\Arrow{} "/yacco2/.DS\_Store" 'Bypass file in zip'}
\ptindent{\Arrow{} "/yacco2/.gitignore" 'Auxilary file to be deleted'}
\ptindent{\Arrow{} "/yacco2/.nbattrs" 'Extended attributes -rwxr-xr-x+'}
\ptindent{\Arrow{} "/yacco2/.nbattrs" 'Write permissions -rwxr-xr-x+ to possibly delete file type: XML'}
\ptindent{\Arrow{} "/yacco2/.nbattrs" 'Bypass file in zip'}
\ptindent{\Arrow{} "/yacco2/bin/.DS\_Store" 'Extended attributes -rwxr-xr-x@@'}
\ptindent{\Arrow{} "/yacco2/bin/.DS\_Store" 'Write permissions -rwxr-xr-x@@ to possibly delete file type: data'}
\ptindent{\Arrow{} "/yacco2/bin/.DS\_Store" 'Bypass file in zip'}
\ptindent{\Arrow{} "/yacco2/bin/man/man1/1lrerrors.log" 'Auxilary file to be deleted'}
\ptindent{\Arrow{} "/yacco2/bin/man/man1/1lrerrors.log" 'Empty file to be deleted'}
\ptindent{\Arrow{} "/yacco2/bin/man/man1/1lrtracings.log" 'Auxilary file to be deleted'}
\ptindent{\Arrow{} "/yacco2/bin/man/man1/1lrtracings.log" 'Empty file to be deleted'}
\ptindent{\Arrow{} "/yacco2/bin/man/man1/o2.man" 'Extended attributes -rw-r--r--@@'}
\ptindent{\Arrow{} "/yacco2/bin/man/man1/o2linker.man" 'Extended attributes -rw-r--r--@@'}
\ptindent{\Arrow{} "/yacco2/bin/man/man1/yacco2.man" 'Extended attributes -rw-r--r--@@'}
\ptindent{\Arrow{} "/yacco2/bin/man/man1/yacco2cmd.tmp" 'Auxilary file to be deleted'}
\ptindent{\Arrow{} "/yacco2/bin/man/man1/yacco2cmd.tmp" 'Empty file to be deleted'}
\ptindent{\Arrow{} "/yacco2/bld\_bash\_APPLE" 'Extended attributes -rwxr-xr-x@@'}
\ptindent{\Arrow{} "/yacco2/bld\_bash\_APPLE" 'Write permissions -rwxr-xr-x@@ to possibly delete file type: ASCII'}
\ptindent{\Arrow{} "/yacco2/book/appendix\_a.aux" 'Auxilary file to be deleted'}
\ptindent{\Arrow{} "/yacco2/book/ch\_fsm.tex" 'Write permissions -rwxr-xr-x@@ to possibly delete file type: LaTeX'}
\fbreak
Running the initial program could potentially output the above sampling.
If there are just 1 message type outputted then u would just focus on ``pass 2'' to correct it.
Having a mix of messages means ``pass 1'' should be edited to just deal with the 1 message type
 at a time. This allows the homogenous output to be captured and edit the removal of  files to bypass.
Now the program can be edited to support the message type action correcting the violation
and rerun.
Each listed guideline type would go thru this edit behaviour:  ``pass 1'' to see the violations, analyse its outcome,
re-edit program, and then run the correction.  

@*2 Anatomy of this |gawk| program.\fbreak
It contains 3 |gawk| actions: BEGIN, Body, and END.
This program's BEGIN and END actions are just read record stats.
U can add your own code as this program is open to your creativity.
The action Body contains the 2 passes: |pass1_guidelines_verify| and |pass2_correct|.
To comment out a function call, add a \NOsign{} at the beginning of its line.
To activate a commented out function call, just remove its |gawk|'s comment character: \NOsign.

@*2 How to generate the  pdf document and this gawk program.\fbreak
The \Cweb{} ``literate programming'' framework is used to generate
its pdf document and its gawk program from |ctan_chk.w|.
Though Cweb emits a ``c'' type code, gawk code is very similar to ``c''.\fbreak
0) Run from a terminal using bash.\fbreak
\ptindent{{\bf{. ctan\_chk\_bash}}}
\ptindent{\Arrow{} The various utilities used are outputed on the terminal}

U are open to add your own code to the |ctan_chk.w| program and rerun the above script.
If u do not have the \Cweb{} framework installed, u can
add the code to the |ctan_chk.gawk| file. 

@*2 How to use this gawk program.\fbreak
0) Run from a terminal using bash.\fbreak
1) Generate a file containing your project's files whose path is absolute\fbreak
\ptindent{{\bf{find /absolute path of your project \GTsign{} xxx}}}
\ptindent{\Arrow{} xxx is a holding file containing your project's files} 
\ptindent{\Arrow{} example of an absolute path: {\bf {/usr/local/yacco2}}} 
2) Edit |ctan_chk.gawk| to what function calls u want to use inside |pass1_guidelines_verify|\fbreak
3) Run gawk ctan\_chk program verifying your project\fbreak
\ptindent{{\bf{gawk -f ctan\_chk.gawk xxx}} \NOsign xxx is the file read containing the files to assess}\fbreak
\ptindent{\Arrow{} it outputs files to correct on the terminal with appropriate guideline message}
\ptindent{\Arrow{} no outputted messages means your project passed with flying colours :\prtcbrace}
\fbreak
\ptindent{\Arrow{} To capture the verification output:}
\ptindent{{\bf{gawk -f ctan\_chk.gawk xxx\Verticalbar{}tee yyy}}}\fbreak
\ptindent{\Arrow{} Use of {\it{tee}} utility to capture the output into yyy file}

@*3 Example: Checking auxilary files to delete.\fbreak
Here are the steps to see whether there are files to remove/delete.
File xxx contains the files to verify as exampled earlier in this document.\fbreak
1) {\bf{gawk -f ctan\_chk.gawk xxx}}\fbreak
\fbreak
2) Its output should have messages similar to this:\fbreak
\ptindent{\Arrow{} "/yacco2/bin/man/man1/1lrerrors.log" 'Auxilary file to be deleted'}
\fbreak
3) Rerun {\bf{gawk -f ctan\_chk.gawk xxx\Verticalbar{}tee yyy}} where the output messages are put in {\bf{yyy}} file.\fbreak
\break
4) Edit: comment out  pass1\_guidelines\_verify and uncomment \#pass2\_correct in Body action code:\fbreak
The gened |ctan_chk.gawk| program could have different commented ``section no:'' used in the below
edit session. What is important are function names referenced: for example, |pass1_guidelines_verify|  which
you'll find in your |ctan_chk.gawk| program. Same comments apply against the other pieces of code being edited.\fbreak
\ptindent{\# section no:22*/}
\ptindent{\# section no28:*/}
\ptindent{\prtobrace}
\ptindent{ pass1\_guidelines\_verify(\$1);}
\ptindent{ \#pass2\_correct(\$1,\$2);}
\ptindent{\prtcbrace}
to\fbreak
\ptindent{\# section no:22*/}
\ptindent{\# section no28:*/}
\ptindent{\prtobrace}
\ptindent{ \#pass1\_guidelines\_verify(\$1);}
\ptindent{ pass2\_correct(\$1,\$2);}
\ptindent{\prtcbrace}
\fbreak
5) Edit: uncomment out \#delete\_file in pass2\_correct:\fbreak
\ptindent{\# section no:28*/}
\ptindent{\# section no29:*/}
\ptindent{function pass2\_correct(filename,message)}
\ptindent{\prtobrace}
\ptindent{ \#remove\_file\_s\_execute\_attribute(filename,message);}
\ptindent{ \#remove\_file\_s\_extended\_attributes(filename,message);}
\ptindent{ \#delete\_file(filename);}
\ptindent{\prtcbrace}
to\break
\ptindent{\# section no:28*/}
\ptindent{\# section no29:*/}
\ptindent{function pass2\_correct(filename,message)}
\ptindent{\prtobrace}
\ptindent{ \#remove\_file\_s\_execute\_attribute(filename,message);}
\ptindent{ \#remove\_file\_s\_extended\_attributes(filename,message);}
\ptindent{ delete\_file(filename);}
\ptindent{\prtcbrace}
\fbreak
\fbreak
\fbreak
\fbreak
\fbreak
\fbreak
6) Save edited |ctan_chk.gawk| program and rerun with {\bf{yyy}}:\fbreak
\ptindent{\Arrow{} {\bf {gawk -f ctan\_chk.gawk yyy}}}
Each file being deleted is questioned and allows u to bypass it.\fbreak
This is due to the {\bf{-i}} option used in {\it{rm -i file-to-delete}}\fbreak
\fbreak
Other guideline contraints would follow the same run / edit / rerun template above adjusting
the program accordingly.\fbreak
\ptindent{\Arrow{} {\bf{Just remember to reset the program back to its initial setting.}}}
As an aside comment, u could have uncommented the |delete_file| call inside the   
|chk_auxiliary_files| function and do the correction while in the ``assess guideline'' pass.
So why did u not express this before :\prtobrace?
Well the normal correction pattern is see what guidelines are violated by ``pass 1', edit the program, 
and then rerun against ``pass 2'' correction.
Once u are familiar with the program throw out my patterns and jig your own :\prtcbrace.
@* Function code sections.
@*2 ctan gawk's comments --- author, license etc.
@<Emit gawk comments@>=
#
# Program: ctan_chk.gawk
#
# Author:  Dave Bone
#
# License:  
# This Source Code Form is subject to the terms of the GNU General Public License (version 3). 
# If a copy of the MPL was not distributed with this file, 
# You can obtain one at:  "https://gnu.org/licenses/gpl.html".
#
# Purpose: Implementation of some suggested CTAN guidelines that an upload project should respect.
#          Correction functions help u cleanup the droppings.
# See www.ctan.org website for  "upload guideline" document
# Read ctan_chk.pdf document describing the program with various run scenarios.
#
#

@*1 Helper functions.
@*2 Is file a directory.\fbreak
Directory found returns 1.
@<|is_file_a_directory|@>=
function is_file_a_directory(filename, filetype)@\
{
 x="file \"%s\"";
 y=sprintf(x,filename);
 y|getline a;
 close(y);
 split(a,parts);
 filetype[1] = parts[2];
 xx = parts[2];
 str= "^directory$";
 if (xx ~ str) {
  return 1;
 }
 return 0; 
}

@*2 Is file an executable.\fbreak
This function {\bf{might be too platform dependent}}.\fbreak
If so then don't call it or find an alternative.\fbreak
A return 1 means it's an executable.
@<|is_file_an_executable|@>=
function is_file_an_executable(filename, filetype)@\
{
 x="file %s";
 y=sprintf(x,filename);
 y|getline a;
 close(y);
 split(a,parts);
 filetype[1] = parts[2];
 xx = parts[2];
 str= "(executable|POSIX|Mach-O|ELF)$";
 if (xx ~ str) {
  return 1; 
  }
  return 0;
}

@*1 Guideline assessment functions.
@*2 Check for auxiliary type files.\fbreak
``str'' contains a regular expression of file extensions to search for starting with a ``.'' followed by
the round bracket expression of extensions to search on ending by the end-of-string regular expression indicator: \$.
Inside the rounded bracket expression is the choice of extensions separated by  \Verticalbar{} 
which is the ``or'' operator of a regular expression.\fbreak
\fbreak
The double \Backslash{} in str is due to how gawk parses the program code:
it does a double pass:\fbreak
\ptindent{1) on the string: str}
\ptindent{2) on the regular expression called}
Just having a ``.'' at the start of  regular expression means it is a single ``wild character'' to accept. 
To accept a period ``.'' that starts the file extension, u have to escape it.
Pass 1 for the literal string is the first escape sequence on \Backslash{} the 2nd backslash.
In pass 2 for the regular expession called, the \Backslash{} escapes the ``.'' to not interpret
as the regular expression  wild character.\fbreak
\fbreak
str can be added to. Make sure u include the added extension started with the \Verticalbar{} when appended to before
the closing off rounded bracked ``)''. \fbreak
\fbreak
|chk_auxiliary_files| outputs a 2 part message: file name and message it considers as an auxiliary file to be deleted.
Calling |delete_file| interacts with the user whether to delete it or not.
It is commented out so that the messages can saved and reviewed before the correction pass takes place:
See |Pass 2 --- correct violated guidelines| section providing more information.
U can uncomment the |delete_file| statement below if u prefer to delete the file in the assessment pass 
rather than the correction pass. Your call and temperment. 
@<|chk_auxiliary_files|@>=
function chk_auxiliary_files(filename)@\
{
 if (is_file_a_directory(filename) == 1) 
  return 0;

 str= "\\.(ps|gitignore|git|aux|log|bbl|bcf|blg|brf|ilg|ind|idx|glo|loa|lof|lot|nav|out|snm|vrb|toc|dvi|glg|gls|tmp|o|bak|mpx|scn|toc)$";
 if (filename ~ str) {
  a= "\"%s\" 'Auxilary file to be deleted'";
  b= sprintf(a,filename);
  print b;
  #delete_file(filename);
  return 1;
 }
 return 0;
}

@*2 Check for extended attributes.\fbreak
Basicly looks at the output from the ``ls -al'' of a file.
If there are extended attributes it will be displayed at the end of the first field as ``@@'' or ``+''.
It outputs the filename and message to the terminal.
Return 1 if found.
@<|chk_extended_file_attributes|@>=
function chk_extended_file_attributes(filename)@\
{
 x="ls -al \"%s\"";
 y=sprintf(x,filename);
 y|getline a;
 close(y);
 number_of_fields = split(a,parts);
 if (number_of_fields < 9)
  return 0;
  
 xx=parts[1];
 str= "(@@|+)$";
 if (xx !~ str) {
  return 0;
 }
  
 a="\"%s\" 'Extended attributes %s'";   
 b=sprintf(a,filename,parts[1]);
 print b;
 #remove_file_s_extended_attributes(filename,b);
 return 1;
}
@*2 Check for empty files.\fbreak
Uncomment out the |delete_file| statement below if u want to remove it in the assessment phase.
Asks whether to delete the zero sized file and  returns 1.
@<|chk_empty_files|@>=
function chk_empty_files(filename)@\
{
 if (is_file_a_directory(filename) == 1)
  return 0;
 
 x="ls -al \"%s\"";
 y=sprintf(x,filename);
 y|getline a;
 close(y);
 number_of_fields = split(a,parts);
 if (number_of_fields < 9)@\
 {
  print "ERROR ===> ls -al should be 9 fields and it isn't: " a " no fields: " number_of_fields;
  return 0;
 }
 i=strtonum(parts[5]);
 if (i > 0){
  return 0;
 }
 a="\"%s\" 'Empty file to be deleted'";
   
 b=sprintf(a,filename);
 print b;
 #delete_file(filename);
 return 1;
}

@*2 Check for empty directory.\fbreak
Empty directory found returns a 1.\fbreak
This check requires u to assess what u want to do: delete it, or add an ``info.txt'' file inside it.
For example in the ``Yacco2'' project, it is a full
development framework of a compiler/compile, and its API library.
It has empty Debug folders. Its Release folders contained content.
Depending on what the user wanted to debug and link against, the empty Debug folder 
provided consistency to the framework and hence it was needed.  So an ``info.txt'' file 
was created inside each Debug folder  expressing their intent/use to the developer.

@<|chk_empty_directory|@>=
function chk_empty_directory(filename)@\
{
 if (is_file_a_directory(filename) == 0)
  return 0;
   
 x="du -sk \"%s\"";
 y=sprintf(x,filename);
 y|getline a;
 close(y);
 number_of_fields = split(a,parts);
 
 i=strtonum(parts[1]);
 if (i > 0)
  return 0;

 a="\"%s\" 'Empty directory to be deleted or needs to add info.txt file inside it'";
   
 b=sprintf(a,filename);
 print b;
 return 1;
}


@*2 Check file permissions.\fbreak
Bypass a directory.
If the file does not have an executable attribute then exit stage gracefully.

@<|chk_file_permissions|@>=
function chk_file_permissions(filename)@\
{
 filetype[1]="";
 if (is_file_a_directory(filename, filetype) == 1)
  return 0;
 if (is_file_an_executable(filename,filetype) == 1)
  return 0;
   
 x="ls -al \"%s\"";
 y=sprintf(x,filename);
 y|getline a;
 close(y);
 
 number_fields = split(a,parts);
 
 str= "x";
 if (parts[1] ~ str) {
  a="\"%s\" 'Write permissions %s to possibly delete file type: %s'"; 
  b=sprintf(a,filename,parts[1],filetype[1]);
  print b;
  return 1;
  }
  return 0;
}

@*2 Check file to bypass in zip.\fbreak
This is just a check function that lists files to bypass in the zip file creation process.\fbreak
An example of creating a zip file:\fbreak
\ptindent{{\bf{zip -r -ll yacco2.zip yacco2 -x '*DS\_Store' -x '*.nbattrs'}}}
\ptindent{\Arrow{} -r recurse through the folder getting all its subfolders and their contents}
\ptindent{\Arrow{} -ll parameter reduces carriage return/line feed combo to line feed}
\ptindent{\Arrow{} -x parameter lists by regular expression the file(s) to bypass}
\ptindent{\Arrow{} The bypassed exampled files are Apple OSX specific}

@<|chk_file_to_bypass_in_zip|@>=
function chk_file_to_bypass_in_zip(filename)
{
 str= ".(DS_Store|.nbattrs)$";
 if (filename ~ str) {
  a="\"%s\" 'Bypass file in zip'";
  b=sprintf(a,filename);
  print b;
  return 1;
  }
 return 0;
}


@*1 Correct guideline violations.
@*2 Remove file's execute attribute.\fbreak
Due to security reasons, u cannot have an indirect bash script run against a list of files
to change their ownership attributes.
It will run but nothing will be changed.\fbreak
So what to do?\fbreak
\ptindent{\Arrow{} gawk -f |ctan_chk.gawk| xxx \Verticalbar{}tee yyy}
\ptindent{\Arrow{} \ \ \ \ u can use your own temporary file name instead of yyy}
\ptindent{\Arrow{} \ \ \ \ just remember to substitute your file name in place of yyy}
\ptindent{\Arrow{} where the |chk_file_permissions| function is the only function run}
\ptindent{\Arrow{} and the other functions have been commented out}
\fbreak
\ptindent{Edit yyy file containing the list of potential files, removing files keeping their execute attribute.}
\break
\ptindent{Run this below gawk script interactively from your bash terminal}
\ptindent{\Arrow{} This means copy the below script line and paste it in the bash terminal}
\ptindent{\ \ \ \ \ gawk '\prtobrace x="chmod a-x \%s;";y=sprint(x,\$1);system(y);\prtcbrace' yyy}
\fbreak
Some comments on the above interactive |gawk| program:\fbreak
1) It reads the yyy file where each line read contains 2 fields: filename, and message separated by a space\fbreak
2) It runs the {\it{chmod}} utility by the {\bf{system}} statement\fbreak
3) Not sure about {\bf{chmod}} utility, do a ``man chmod'' on your bash terminal for more information\fbreak
4) If u boobooed on a file and removed the execute attribute, here is a correction:\fbreak
\ptindent{\Arrow{}  {\bf{chmod a+x file-to-reimplement}}}

@<|remove_file_s_execute_attribute|@>=
function remove_file_s_execute_attribute(filename, message)@\
{
  print "Please read |ctan_chk.pdf| to find instructions on how remove execute attribute from a file";
}

@*2 Remove file's with extended attributes.\fbreak
This function is platform dependent.
The {\it{xattr}} is the utility to run on Apple's OSx platform to remove the extension.
@<|remove_file_s_extended_attributes|@>=
function remove_file_s_extended_attributes(filename, message)@\
{
 x="echo %s\";xattr -c %s";
 y=sprintf(x,message,filename);
 print y;
 #y|getline a;
 #close(y); 
}

@*2 Delete file.\fbreak
The file name passed to it is displayed and asks whether it should be deleted.
@<|delete_file|@>=
function delete_file(filename)@\
{
 x="rm -i \"%s\"";
 y=sprintf(x,filename);
 y|getline a;
 close(y); 
}


@* Pass 1 / 2 guidelines assessment and correction.\fbreak
@*2 Pass 1 --- guidelines assessment.\fbreak
Using a text editor (un)comment out the appropriate function calls in |ctan_chk.gawk|  that u'd like to verify.
For example checking just the files to be deleted, comment out all the below functions except
|chk_auxiliary_files|.

U can run pass 1 as is to see whether any of your files for upload do not
pass the guidelines.
From there u can adjust what function to deal with by commenting out the others fuctions
and teeing out its found infidelities for pass 2 correction.

@<pass 1 guidelines verify@>=
function pass1_guidelines_verify(filename)
{
 chk_auxiliary_files(filename);
 chk_extended_file_attributes(filename);
 chk_empty_files(filename);
 chk_empty_directory(filename);
 chk_file_permissions(filename);
 chk_file_to_bypass_in_zip(filename);
}

@*2 Pass 2 --- correct violated guidelines.\fbreak
There are 3 functions whereby 2 of them do usefull things.\fbreak
\ptindent{|delete_file| function asks whether its passed file should be deleted}
\ptindent{\Arrow{} Remove the -i in {\bf{rm -i}} statement if u don't want the interactive question}
\fbreak
\ptindent{|remove_file_s_extended_attributes| function is tailored to the Apple platform}
\ptindent{\Arrow{} Other platforms should have an equivalent {\it{xattr -c}} utility}
\ptindent{\Arrow{} {\bf{Caveat:}} know what utility to use and adjust accordingly to remove the extension attribute}
\ptindent{\Arrow{} Have a read at https://en.wikipedia.org/wiki/Extended\_file\_attributes\#cite\_note-14}
\fbreak
\ptindent{|remove_file_s_execute_attribute| tells u to read the {\bf{ctan\_chk.pdf}} document} 
\ptindent{\Arrow{} on ``how to remove'' the execute attribute from a file}
\fbreak
Uncomment the appropriate below function to call. 
And comment out |pass1_guidelines_verify| statement, and uncomment |pass2_correct| statement
in |Body| action before reruning this program.
@<pass 2 guidelines correction@>=
function pass2_correct(filename, message)
{
 #remove_file_s_execute_attribute(filename,message);
 #remove_file_s_extended_attributes(filename,message);
 #delete_file(filename);
}

@* Gawk Begin, Body, End actions.
@*2 Begin.
@<|BEGIN|@>=
BEGIN{
rec_cnt = 0;
}

@*2 Body.
@<|Body|@>=
{
 pass1_guidelines_verify($1);
 #pass2_correct($1,$2);
}

@*2 END.
@<|END|@>=
END{
#print "no records read: " NR;
}



@ Write out gawk program.
@(ctan_chk.gawk@>=
@<Emit gawk comments@>;
@<|is_file_a_directory|@>;
@<|is_file_an_executable|@>;
@<|chk_auxiliary_files|@>;
@<|remove_file_s_extended_attributes|@>;
@<|chk_file_permissions|@>;
@<|chk_extended_file_attributes|@>;
@<|chk_empty_files|@>;
@<|chk_empty_directory|@>;
@<|delete_file|@>;
@<|chk_file_to_bypass_in_zip|@>;
@<pass 1 guidelines verify@>;
@<pass 2 guidelines correction@>;
@<|BEGIN|@>;
@<|Body|@>;
@<|END|@>;

@** Index.