"Fossies" - the Fresh Open Source Software Archive 
Member "unipkg-0.6.5/unipkglib/unipkg-slackdb.c" (16 Dec 2005, 47367 Bytes) of package /linux/privat/old/unipkg-0.6.5.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /******************************************************************************\
2 * *
3 * UNIPKG (c) iSteve <isteve@bofh.cz>, 2005 *
4 * *
5 * Universal PacKaGer. *
6 * Licensed under GNU/GPL - if you don't like the software, fix it! *
7 * *
8 \******************************************************************************/
9
10 ///////////////////////////////////////////////////////////////////////////////
11 // //
12 // B A S E I N C L U S I O N S A N D D E F I N I T I O N S //
13 // //
14 ///////////////////////////////////////////////////////////////////////////////
15 #define _GNU_SOURCE
16
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <fnmatch.h>
22 #include <errno.h>
23 #include <dlfcn.h>
24 #include <libgen.h>
25 #include <dirent.h>
26 #include <fcntl.h>
27 #include <ctype.h>
28
29 #include <sys/stat.h>
30 #include <sys/mman.h>
31 #include <sys/types.h>
32
33 #include "../common.h"
34
35 // Decide on slack parser to be used //////////////////////////////////////////
36 #define SLACK_COMPLEX
37 ///////////////////////////////////////////////////////////////////////////////
38
39 // Shell parsing definitions //////////////////////////////////////////////////
40 #define PNONE 0
41 #define FLAG 1
42 #define DATA 2
43 #define PMASK 3 // Mask for all base pstatus stuff
44
45 #define PNOFLAG 4 // This is sort of extra
46
47 #define QNONE 8
48 #define QSINGLE 16
49 #define QDOUBLE 32
50 #define QMAKS 56
51
52 #define QSUBSHELL 64
53
54 #define NODATA 0
55 #define SPACEDATA 1
56 #define EQUIDATA 2
57
58 #define SHORTOPT 0
59 #define LONGOPT 1
60
61 #define NONFREE(ptr) ((*ptr != ' ') && (*ptr != '\t') && (*ptr != '\n') && (*ptr != ';'))
62
63 #define SCLEAR 0
64 #define SBLOCK 1
65
66 typedef struct {
67 char **names;
68 unsigned long count;
69 } shellbuiltins;
70
71 typedef struct {
72 char *flag; // like --suffix= ...
73 unsigned long flaglen;
74 int data;
75 int type; // short, long
76 } paramflag;
77
78 typedef struct {
79 char *content;
80 int id; // -1 if ordinary data, 0+ if some flag
81 } outformat;
82
83 typedef struct {
84 char *fbase; // Such as 'ln '.
85 int magic; // For further use
86
87 unsigned long outcount, flagcount;
88
89 outformat *outputs;
90 paramflag *flags;
91 } funcdef;
92
93 typedef struct {
94 char *pwd;
95 int status;
96 } subshell;
97 ///////////////////////////////////////////////////////////////////////////////
98
99 // Trivial parser definitions /////////////////////////////////////////////////
100 #ifndef SLACK_COMPLEX
101 typedef struct {
102 char *linkfile;
103 char *target;
104 } linkinfo;
105 #endif
106 ///////////////////////////////////////////////////////////////////////////////
107
108
109
110 typedef struct {
111 char *fpath;
112 struct dirent **namelist;
113 long curname;
114 long namecount;
115 } dbhandle;
116
117 struct treeNode {
118 struct treeNode *child;
119 struct treeNode *sibling;
120 struct treeNode *parent;
121 char *name;
122 };
123
124 ///////////////////////////////////////////////////////////////////////////////
125 // //
126 // B A S E F U N C T I O N S //
127 // //
128 ///////////////////////////////////////////////////////////////////////////////
129
130 // GETCTRLHDR()
131 //
132 // Parses information from Slackware style packagedb description.
133 //
134 // Parameters:
135 // the part of status file regarding one package
136 // the header we are looking for
137 //
138 // Return value:
139 // NULL in error
140 // malloced value of the header otherwise
141 static char *getctrlhdr(char *fullfile, char *hdr, unsigned long len) {
142 char *ptr, *end, *endptr;
143
144 ptr = fullfile;
145 if ((endptr = pstrnstr(ptr, "FILE LIST:", len, 0)) == NULL) {
146 endptr = fullfile + strlen(fullfile);
147 }
148 while ((ptr = pstrnstr(ptr, hdr, len - (ptr - fullfile), 0)) != NULL) {
149 if (ptr >= endptr) { return NULL; }
150 if (ptr != fullfile) {
151 if (*(ptr-1) != '\n') {
152 ptr++;
153 continue;
154 }
155 }
156
157 // This one is handled differently. And FILE LIST has to be handled in body.
158 ptr += strlen(hdr);
159
160 // Any empty space but newline
161 while ((isspace(*ptr)) && (*ptr != '\n')) {
162 ptr++;
163 if (ptr == endptr) { return NULL; }
164 }
165
166 // This kid is from a different town.
167 if (!strcmp("PACKAGE DESCRIPTION:", hdr)) {
168 if (*ptr != '\n') { return NULL; }
169 ptr++;
170 if ((!strncmp("FILE LIST:", ptr, 10)) || (!strncmp("PACKAGE ", ptr, 8)) || (!strncmp("COMPRESSED ", ptr, 11)) || (!strncmp("UNCOMPRESSED ", ptr, 13))) {
171 return NULL;
172 }
173 }
174 if ((end = strchr(ptr, '\n')) == NULL) { end = endptr; }
175 return strndup(ptr, end-ptr);
176 ptr++;
177 }
178 return NULL;
179 }
180
181 // INFILTER()
182 //
183 // Filters out hidden files.
184 //
185 // Parameters:
186 // pointer to dirent structure, containing match
187 //
188 // Return value:
189 // zero if not matching
190 // non-zero if match
191 static int infilter(const struct dirent *inname) {
192 return (inname->d_name[0] != '.');
193 }
194
195 // PARSESLACKNAME()
196 //
197 // Attempts to parse the package information from filename, expecting a given
198 // filename format.
199 //
200 // Parameters:
201 // filename
202 // pointer to package info, to which data is written
203 //
204 // Return value:
205 // 0 if no problem
206 // 1 if troubles parsing the filename
207 static int parseslackname(char *name, pkginfo *pinfo) {
208 char *parsed, *ptr;
209
210 parsed = strdup(name);
211
212 // strip off build
213 if ((ptr = strrchr(parsed, '-')) == NULL) {
214 free(parsed);
215 return 1;
216 }
217 *ptr = '\0';
218
219 // strip off arch
220 if ((ptr = strrchr(parsed, '-')) == NULL) {
221 free(parsed);
222 return 1;
223 }
224 *ptr = '\0';
225
226 // get version
227 if ((ptr = strrchr(parsed, '-')) == NULL) {
228 free(parsed);
229 return 1;
230 }
231 *ptr = '\0';
232 pinfo->version = strdup(ptr+1);
233 pinfo->name = strdup(parsed);
234
235 free(parsed);
236 return 0;
237 }
238
239 // ENSUREDATA()
240 //
241 // Ensures there is some basic package information about the package, no matter
242 // what happens.
243 //
244 // Parameters:
245 // the filename
246 // pointer package info, to which data is written
247 //
248 // Return value:
249 // void
250 static void ensuredata(char *fname, pkginfo *pinfo) {
251 char *eptr, *fptr;
252
253 if (pinfo->name == NULL) {
254 eptr = fname + strlen(fname);
255
256 fptr = fname;
257 while ((fptr < eptr)) {
258 if ((isdigit(*fptr)) && (fptr > fname)) {
259 if (*(fptr-1) == '-') {
260 fptr--;
261 break;
262 }
263 }
264 fptr++;
265 }
266
267 pinfo->name = strndup(fname, fptr-fname);
268 if (pinfo->version == NULL) {
269 pinfo->version = strdup(fptr+1);
270 }
271 }
272
273 if (pinfo->version == NULL) { pinfo->version = strdup("unknown"); }
274 if (pinfo->description == NULL) { pinfo->description = strdup("Slackware package, no description."); }
275 }
276
277 #ifdef SLACK_COMPLEX
278 ///////////////////////////////////////////////////////////////////////////////
279 // //
280 // C O M P L E X S H E L L S E M I P A R S I N G //
281 // //
282 ///////////////////////////////////////////////////////////////////////////////
283
284 // SWITCH_NODATA_OPTIONS()
285 //
286 // Checks if needle is a flag, which takes no additional data, as defined in fdef.
287 //
288 // Parameters:
289 // needle
290 // pointer to function definition
291 //
292 // Return value:
293 // 0 if no match
294 // id of the flag otherwise
295 int switch_nodata_options(char *ptr, funcdef *fdef) {
296 unsigned long i;
297
298 for (i=0; i < fdef->flagcount; i++) {
299 if (fdef->flags[i].data == NODATA) {
300 if (!strcmp(ptr, fdef->flags[i].flag)) {
301 return i+1;
302 }
303 }
304 }
305
306 return 0;
307 }
308
309 // SWITCH_DATA_OPTIONS()
310 //
311 // Checks if needle is a flag, which takes some additional data, as defined in fdef.
312 //
313 // Parameters:
314 // needle
315 // pointer to function definition
316 //
317 // Return value:
318 // 0 if no match
319 // id of the flag otherwise
320 int switch_data_options(char *ptr, funcdef *fdef) {
321 unsigned long i;
322
323 for (i=0; i < fdef->flagcount; i++) {
324 if (fdef->flags[i].data == SPACEDATA) {
325 if (!strcmp(ptr, fdef->flags[i].flag)) { return i+1; }
326 }
327 if (fdef->flags[i].data == EQUIDATA) {
328 if (!strncmp(ptr, fdef->flags[i].flag, fdef->flags[i].flaglen)) { return i+1; }
329 }
330 }
331
332 return 0;
333 }
334
335 // counts on shortops grouped are oneletter ... but what else would they be?
336 // SEPARATE_SHORTOPTS()
337 //
338 // Separates grouped short options, only last may take option
339 //
340 // Parameters:
341 // needle
342 // pointer to function definition
343 //
344 // Return value:
345 // 0 if no match
346 // 1 if one or more matches
347 // -1 if one or more matches, while the last takes data
348 static int separate_shortopts(char *ptr, funcdef *fdef) {
349 unsigned long i;
350 char tmpbuf[3];
351 int reval, retval;
352
353 ptr++; // skip heading '-'
354
355 tmpbuf[0] = '-';
356 tmpbuf[2] = '\0';
357 retval = 0;
358 while (*ptr != '\0') {
359 for (i=0; i < fdef->flagcount; i++) {
360 if ((fdef->flags[i].type == SHORTOPT) && (fdef->flags[i].data == NODATA)) {
361 tmpbuf[1] = *ptr;
362 if (!strcmp(tmpbuf, fdef->flags[i].flag)) {
363 retval=1;
364 fdef->outputs[fdef->outcount].content = strdup("");
365 fdef->outputs[fdef->outcount].id = i;
366 fdef->outcount++;
367 fdef->outputs = realloc(fdef->outputs, sizeof(outformat) * (fdef->outcount + 1));
368 }
369 }
370 }
371 ptr++;
372 }
373
374 if ((reval = switch_data_options(tmpbuf, fdef)) != 0) {
375 return reval;
376 } else {
377 return -retval;
378 }
379 }
380
381 // ADDCHAR()
382 //
383 // Adds a character to a buffer sized len, enlarges it by one char
384 //
385 // Parameters:
386 // pointer to (pointer to) the buffer
387 // size of buffer
388 // character added
389 //
390 // Return value:
391 // new size of buffer
392 static unsigned long addchar(char **buf, unsigned long len, unsigned long *pos, char c) {
393 if (len <= *pos) {
394 len = *pos * 2;
395 *buf = realloc(*buf, len + 1);
396 }
397 (*buf)[*pos] = c;
398 (*pos)++;
399 return len;
400 }
401
402 // ADDOUTPUT()
403 //
404 // Adds another data parameter.
405 //
406 // Parameters:
407 // pointer to function definition
408 // string added
409 // type of data
410 //
411 // Return value:
412 // none
413 static void addoutput(funcdef *fdef, char *s, int type) {
414 fdef->outputs[fdef->outcount].content = strdup(s);
415 fdef->outputs[fdef->outcount].id = type;
416 fdef->outcount++;
417 fdef->outputs = realloc(fdef->outputs, sizeof(outformat) * (fdef->outcount + 1));
418 }
419
420 // PARSECOMMAND()
421 //
422 // A rather complex function, which parses the whole function call more or less
423 // like POSIX compliant shell would. It's black magic, fear and tremble.
424 //
425 // Parameters:
426 // string we parse
427 // pointer which sets the end of string
428 // pointer to pointer to end of parsing
429 // pointer to function definition for which we parse
430 //
431 // Return value:
432 // always 0
433 static int parsecommand(char *ptr, char *eptr, char **fptr, funcdef *fdef) {
434 int pstatus, qstatus, ctype;
435 // pstatus tells us about how parsing goes
436 // qstatus is for data and tells us status of quotes
437 // ctype contains information about data type, -2 uninteresting, -1 data, 0+ flag
438
439 unsigned long curlen, curpos;
440 int reval;
441 char *buf;
442
443 ptr += strlen(fdef->fbase); // skip "ln"
444 while ((isspace(*ptr)) && (*ptr != '\0') && (*ptr != '\n')) {
445 ptr++; // We can't have "ln--flag", we have to separate it ... by a freespace;
446 }
447 *fptr = ptr;
448
449 pstatus = DATA;
450 qstatus = QNONE;
451
452 curlen = 0;
453 curpos = 0;
454 buf = malloc(1);
455
456 ctype = -1;
457
458 while (*ptr != '\0') {
459 switch (*ptr) {
460 case '\\':
461 switch (qstatus) {
462 case QNONE:
463 ptr++;
464 curlen = addchar(&buf, curlen, &curpos, *ptr);
465 break;
466 case QSINGLE:
467 curlen = addchar(&buf, curlen, &curpos, *ptr);
468 break;
469 case QDOUBLE:
470 ptr++;
471 switch (*ptr) {
472 case 'a': curlen = addchar(&buf, curlen, &curpos, '\a');
473 break;
474 case 'b': curlen = addchar(&buf, curlen, &curpos, '\b');
475 break;
476 case 'f': curlen = addchar(&buf, curlen, &curpos, '\f');
477 break;
478 case 'n': curlen = addchar(&buf, curlen, &curpos, '\n');
479 break;
480 case 'r': curlen = addchar(&buf, curlen, &curpos, '\r');
481 break;
482 case 't': curlen = addchar(&buf, curlen, &curpos, '\t');
483 break;
484 case 'v': curlen = addchar(&buf, curlen, &curpos, '\v');
485 break;
486 default:
487 curlen = addchar(&buf, curlen, &curpos, *ptr);
488 break;
489 }
490 break;
491 }
492 break;
493 case '\'':
494 switch (qstatus) {
495 case QNONE:
496 qstatus = QSINGLE;
497 break;
498 case QSINGLE:
499 qstatus = QNONE;
500 break;
501 case QDOUBLE:
502 curlen = addchar(&buf, curlen, &curpos, *ptr);
503 break;
504 }
505 break;
506 case '"':
507 switch (qstatus) {
508 case QNONE:
509 qstatus = QDOUBLE;
510 break;
511 case QSINGLE:
512 curlen = addchar(&buf, curlen, &curpos, *ptr);
513 break;
514 case QDOUBLE:
515 qstatus = QNONE;
516 break;
517 }
518 break;
519 case '\t':
520 case ' ':
521 if (qstatus == QNONE) { // Terminate, we found end of data
522 curlen = addchar(&buf, curlen, &curpos, '\0');
523 if ((pstatus != PNOFLAG) && (!strcmp(buf, "--"))) {
524 pstatus = PNOFLAG;
525 } else {
526 if ((pstatus != PNOFLAG) && ((reval = switch_data_options(buf, fdef)) != 0)) {
527 ctype = reval-1;
528 if (fdef->flags[ctype].data == EQUIDATA) {
529 addoutput(fdef, buf + fdef->flags[ctype].flaglen, ctype);
530 ctype = -1;
531 }
532 } else {
533 if (ctype != -1) {
534 addoutput(fdef, buf, ctype);
535 ctype = -1;
536 } else {
537 if ((pstatus != PNOFLAG) && ((reval = switch_nodata_options(buf, fdef)) != 0)) {
538 ctype = reval-1;
539 addoutput(fdef, "", ctype);
540 ctype = -1;
541 } else {
542 if ((pstatus != PNOFLAG) && (strlen(buf)>=3) && (buf[0] == '-') && (buf[1] != '-')) {
543 reval = separate_shortopts(buf, fdef);
544 if (reval > 0) {
545 ctype = reval - 1;
546 } else {
547 ctype = -1;
548
549 if (!((pstatus == PNOFLAG) && (buf[0] == '-')) && (reval == 0)) {
550 addoutput(fdef, buf, ctype);
551 }
552 }
553 } else {
554 ctype = -1;
555 if (!((pstatus == PNOFLAG) && (buf[0] == '-'))) {
556 addoutput(fdef, buf, ctype);
557 }
558 }
559 }
560 }
561 }
562 }
563
564 curlen = 0;
565 curpos = 0;
566 buf = realloc(buf, 1);
567
568 pstatus = PNONE | (pstatus & PNOFLAG);
569
570 while ((!isspace(*ptr)) && (ptr < eptr)) {
571 ptr++;
572 }
573 } else { // continue
574 curlen = addchar(&buf, curlen, &curpos, *ptr);
575 }
576 break;
577 case '&':
578 if (*(ptr+1) != '&') {
579 curlen = addchar(&buf, curlen, &curpos, *ptr);
580 break;
581 } else {
582 free(buf);
583 ptr--;
584 *fptr = ptr;
585 return 0;
586 }
587 case '|':
588 if (*(ptr+1) != '|') {
589 curlen = addchar(&buf, curlen, &curpos, *ptr);
590 break;
591 } else {
592 free(buf);
593 ptr--;
594 *fptr = ptr;
595 return 0;
596 }
597 case '\0': // To ensure this is parsed fine...
598 qstatus = QNONE;
599 case '`': // This is questionable
600 case ')': // So are the subshells
601 case '(': // On the other hand, this
602 case '}': // is still meant to be rather
603 case '{': // simple parser, so it shouldn't
604 case ';': // matter much.
605 case '\n': // newline, on the other hand, is mandatory
606 if (qstatus == QNONE) {
607 curlen = addchar(&buf, curlen, &curpos, '\0');
608
609 if ((pstatus != PNOFLAG) && (!strcmp(buf, "--"))) {
610 pstatus = PNOFLAG;
611 } else {
612 if ((pstatus != PNOFLAG) && ((reval = switch_data_options(buf, fdef)) != 0)) {
613 ctype = reval-1;
614 if (fdef->flags[ctype].data == EQUIDATA) {
615 addoutput(fdef, buf + fdef->flags[ctype].flaglen, ctype);
616 ctype = -1;
617 }
618 } else {
619 if (ctype != -1) {
620 addoutput(fdef, buf, ctype);
621 ctype = -1;
622 } else {
623 if ((pstatus != PNOFLAG) && ((reval = switch_nodata_options(buf, fdef)) != 0)) {
624 ctype = reval-1;
625 addoutput(fdef, "", ctype);
626 ctype = -1;
627 } else {
628 if ((pstatus != PNOFLAG) && (strlen(buf)>=3) && (buf[0] == '-') && (buf[1] != '-')) {
629 reval = separate_shortopts(buf, fdef);
630 if (reval > 0) {
631 ctype = reval - 1;
632 } else {
633 ctype = -1;
634 if (!((pstatus == PNOFLAG) && (buf[0] == '-')) && (reval == 0)) {
635 addoutput(fdef, buf, ctype);
636 }
637 }
638 } else {
639 ctype = -1;
640 if (!((pstatus == PNOFLAG) && (buf[0] == '-'))) {
641 addoutput(fdef, buf, ctype);
642 }
643 }
644 }
645 }
646 }
647 }
648
649 // We've reached end of function, let's drop out.
650 free(buf);
651 ptr--; // not to waste the character we currently consider terminating -- it may be parsed outside
652 *fptr = ptr;
653 return 0;
654 // And drop out we did.
655 } else {
656 curlen = addchar(&buf, curlen, &curpos, *ptr);
657 }
658 break;
659 default:
660 curlen = addchar(&buf, curlen, &curpos, *ptr);
661 break;
662 }
663 ptr++;
664 }
665
666 // cleanups
667 if (curlen > 0) {
668 curlen = addchar(&buf, curlen, &curpos, '\0');
669 if ((pstatus != PNOFLAG) && (!strcmp(buf, "--"))) {
670 pstatus = PNOFLAG;
671 } else {
672 if ((pstatus != PNOFLAG) && ((reval = switch_data_options(buf, fdef)) != 0)) {
673 ctype = reval-1;
674 if (fdef->flags[ctype].data == EQUIDATA) {
675 addoutput(fdef, buf + fdef->flags[ctype].flaglen, ctype);
676 ctype = -1;
677 }
678 } else {
679 if (ctype != -1) {
680 addoutput(fdef, buf, ctype);
681 ctype = -1;
682 } else {
683 if ((pstatus != PNOFLAG) && ((reval = switch_nodata_options(buf, fdef)) != 0)) {
684 ctype = reval-1;
685 addoutput(fdef, "", ctype);
686 } else {
687 if ((pstatus != PNOFLAG) && (strlen(buf)>=3) && (buf[0] == '-') && (buf[1] != '-')) {
688 reval = separate_shortopts(buf, fdef);
689 if (reval > 0) {
690 ctype = reval - 1;
691 } else {
692 ctype = -1;
693 if (!((pstatus == PNOFLAG) && (buf[0] == '-')) && (reval == 0)) {
694 addoutput(fdef, buf, ctype);
695 }
696 }
697 } else {
698 ctype = -1;
699 if (!((pstatus == PNOFLAG) && (buf[0] == '-'))) {
700 addoutput(fdef, buf, ctype);
701 }
702 }
703 }
704 }
705 }
706 }
707 }
708
709 *fptr = ptr;
710
711 curlen = addchar(&buf, curlen, &curpos, '\0');
712
713 free(buf);
714
715 return 0;
716 }
717
718 // ADDFLAG()
719 //
720 // Adds another flag definition to function definition.
721 //
722 // Parameters:
723 // pointer to function definition
724 // flag added
725 // type of data obtained
726 // type (id) of flag
727 //
728 // Return value:
729 // none
730 static void addflag(funcdef *fdef, char *flag, int data, int type) {
731 fdef->flags[fdef->flagcount].flag = strdup(flag);
732 fdef->flags[fdef->flagcount].flaglen = strlen(flag);
733 fdef->flags[fdef->flagcount].data = data;
734 fdef->flags[fdef->flagcount].type = type;
735
736 fdef->flagcount++;
737 fdef->flags = realloc(fdef->flags, sizeof(paramflag) * (fdef->flagcount + 1));
738 }
739
740 // FREEFUNCDEF()
741 //
742 // Frees the function definition members
743 //
744 // Parameters:
745 // pointer to function definition
746 //
747 // Return value:
748 // none
749 static void freefuncdef(funcdef *fdef) {
750 unsigned long i;
751
752 for (i=0; i<fdef->outcount; i++) {
753 free(fdef->outputs[i].content);
754 }
755 for (i=0; i<fdef->flagcount; i++) {
756 free(fdef->flags[i].flag);
757 }
758
759 free(fdef->fbase);
760
761 free(fdef->flags);
762 free(fdef->outputs);
763 }
764
765 // MATCHFUNCDEF()
766 //
767 // Matches needle against function definition
768 //
769 // Parameters:
770 // pointer to function definition
771 // needle
772 // number of functions in fdefs array
773 //
774 // Return value:
775 // -1 if no match
776 // index of function matching otherwise
777 static int matchfuncdef(funcdef *fdefs, char *needle, unsigned long count) {
778 unsigned long i;
779 for (i=0; i<count; i++) {
780 if (!strcmp(needle, fdefs[i].fbase)) {
781 return i;
782 }
783 }
784 return -1;
785 }
786
787 // GETFUNCDATA()
788 //
789 // Dumps the content of n-th data member of a particular type in the function
790 // definition
791 //
792 // Parameters:
793 // pointer to function definition
794 // needle
795 // number of functions in fdefs array
796 //
797 // Return value:
798 // -1 if no match
799 // index of function matching otherwise
800 static char *getfuncdata(funcdef *fdef, unsigned long count, int type) {
801 unsigned long i, j;
802 char *reval;
803
804 for (i=0, j=0; i<fdef->outcount; i++) {
805 if (fdef->outputs[i].id == type) {
806 if (j++ == count) {
807 reval = strdup(fdef->outputs[i].content);
808 return reval;
809 }
810 }
811 }
812 return NULL;
813 }
814
815 // CLEARFUNCDATA()
816 //
817 // Frees and clears the data in the function definition, not the function
818 // definition itself.
819 //
820 // Parameters:
821 // pointer to function definition
822 //
823 // Return value:
824 // none
825 static void clearfuncdata(funcdef *fdef) {
826 unsigned long i;
827
828 for (i=0; i<fdef->outcount; i++) {
829 free(fdef->outputs[i].content);
830 }
831 fdef->outcount = 0;
832 fdef->outputs = realloc(fdef->outputs, sizeof(outformat));
833 }
834
835 // ADDSHELLBUILTIN()
836 //
837 // Adds another shell builtin that doesn't take a parameter, which are handled
838 // with extra care.
839 //
840 // Parameters:
841 // pointer to shell builtins array
842 // name of the builtin
843 //
844 // Return value:
845 // none
846 static void addshellbuiltin(shellbuiltins *shbin, char *name) {
847 shbin->names[shbin->count] = strdup(name);
848 shbin->count++;
849 shbin->names = realloc(shbin->names, (sizeof(char*)) * (shbin->count + 1));
850 }
851
852 // FREESHELLBUILTINS()
853 //
854 // Frees the shell builtins members
855 //
856 // Parameters:
857 // pointer to shell builtins
858 //
859 // Return value:
860 // none
861 static void freeshellbuiltins(shellbuiltins *shbin) {
862 unsigned long i;
863
864 for (i=0; i<shbin->count; i++) {
865 free(shbin->names[i]);
866 }
867 free(shbin->names);
868 }
869
870 // ISSHELLBUILTIN()
871 //
872 // Checks if the name is a known shell builtin or no
873 //
874 // Parameters:
875 // pointer to shell builtins
876 // needle
877 //
878 // Return value:
879 // 0 if not matched
880 // 1 if matched
881 static int isshellbuiltin(shellbuiltins *shbin, char *name) {
882 unsigned long i;
883
884 for (i=0; i<shbin->count; i++) {
885 if (!strcmp(name, shbin->names[i])) { return 1; }
886 }
887 return 0;
888 }
889
890 // CLEARUPSSHELLS()
891 //
892 // Clears up bogus subshells.
893 //
894 // Parameters:
895 // pointer to subshell array
896 // depth of subshell
897 //
898 // Return value:
899 // none
900 static void clearupsshells(subshell *shell, int subdepth) {
901 while (subdepth > 0) {
902 free(shell[subdepth--].pwd);
903 }
904 free(shell[0].pwd);
905 }
906
907
908 // PARSEDOINST()
909 //
910 // Parses the doinst.sh script. This is the complex one, black magic, weird
911 // code, hopes and prayers.
912 //
913 // Parameters:
914 // the parsed doinst.sh
915 // destination directory (viz pdef.ddir)
916 // pointer to package info where we write data
917 //
918 // Return value:
919 // 0, always
920 static int parsedoinst(char *line, char *ddir, pkginfo *pinfo) {
921 char *ptr, *rptr, *eptr, *fptr, *tmp, *tmp2, *tmp3;
922 funcdef *fdef;
923 unsigned long handfuncount, i;
924 shellbuiltins shbin;
925
926 int reval;
927 int subdepth, subbottom;
928 int qstatus, pstatus, sstatus;
929 // qstatus controls status of ` subshells
930 // pstatus controls status of parsing, since
931 // we want some stuff sequentional
932 // status tells us if we are going strictly
933 // for slackware-likes or no
934 // this counts for ifs, fors and cases
935
936 subshell *shell;
937
938 ///////////////////////////////////////////////
939 // Here is definition of shell builtins that //
940 // do not take any parameter at all. //
941 ///////////////////////////////////////////////
942 shbin.count = 0;
943 shbin.names = malloc(sizeof(char*));
944 addshellbuiltin(&shbin, "then");
945 addshellbuiltin(&shbin, "else");
946 addshellbuiltin(&shbin, "do");
947 addshellbuiltin(&shbin, ":");
948 addshellbuiltin(&shbin, "&&");
949 addshellbuiltin(&shbin, "||");
950 ///////////////////////////////////////////////
951 // End of the definition part //
952 ///////////////////////////////////////////////
953
954 handfuncount = 4;
955 fdef = malloc(sizeof(funcdef) * handfuncount);
956 ///////////////////////////////////////////////
957 // Here is definition of function LN and the //
958 // parameters that interest us //
959 ///////////////////////////////////////////////
960 fdef[0].fbase = strdup("ln");
961 fdef[0].outcount = 0;
962 fdef[0].outputs = malloc(sizeof(outformat));
963 fdef[0].flagcount = 0;
964 fdef[0].flags = malloc(sizeof(paramflag));
965
966 addflag(&fdef[0], "-S", SPACEDATA, SHORTOPT); //0
967 addflag(&fdef[0], "--suffix=", EQUIDATA, LONGOPT); //1
968 addflag(&fdef[0], "--backup=", EQUIDATA, LONGOPT); //2
969 addflag(&fdef[0], "--backup", NODATA, LONGOPT); //3
970 addflag(&fdef[0], "-b", NODATA, SHORTOPT); //4
971 addflag(&fdef[0], "-s", NODATA, SHORTOPT); //5
972 addflag(&fdef[0], "-f", NODATA, SHORTOPT); //6
973 addflag(&fdef[0], "--force", NODATA, LONGOPT); //7
974 addflag(&fdef[0], "--target-directory=", EQUIDATA, LONGOPT); //8
975 addflag(&fdef[0], "--verbose", NODATA, LONGOPT); //9
976 addflag(&fdef[0], "-v", NODATA, SHORTOPT); //10
977 addflag(&fdef[0], "--help", NODATA, LONGOPT); //11
978 addflag(&fdef[0], "--version", NODATA, LONGOPT); //12
979 addflag(&fdef[0], "--interactive", NODATA, LONGOPT); //13
980 addflag(&fdef[0], "--symbolic", NODATA, LONGOPT); //14
981 addflag(&fdef[0], "--no-dereference", NODATA, LONGOPT); //15
982 addflag(&fdef[0], "--directory", NODATA, LONGOPT); //16
983 addflag(&fdef[0], "-i", NODATA, SHORTOPT); //17
984 addflag(&fdef[0], "-F", NODATA, SHORTOPT); //18
985 addflag(&fdef[0], "-d", NODATA, SHORTOPT); //19
986 ///////////////////////////////////////////////
987 // End of the definition part //
988 ///////////////////////////////////////////////
989
990 ///////////////////////////////////////////////
991 // Here is definition of function CD and the //
992 // parameters that interest us //
993 ///////////////////////////////////////////////
994 fdef[1].fbase = strdup("cd");
995 fdef[1].outcount = 0;
996 fdef[1].outputs = malloc(sizeof(outformat));
997 fdef[1].flagcount = 0;
998 fdef[1].flags = malloc(sizeof(paramflag));
999
1000 addflag(&fdef[1], "-L", SPACEDATA, SHORTOPT);
1001 addflag(&fdef[1], "-P", SPACEDATA, SHORTOPT);
1002 ///////////////////////////////////////////////
1003 // End of the definition part //
1004 ///////////////////////////////////////////////
1005
1006 ///////////////////////////////////////////////
1007 // Here is definition of remove functinon //
1008 ///////////////////////////////////////////////
1009 fdef[2].fbase = strdup("rm");
1010 fdef[2].outcount = 0;
1011 fdef[2].outputs = malloc(sizeof(outformat));
1012 fdef[2].flagcount = 0;
1013 fdef[2].flags = malloc(sizeof(paramflag));
1014
1015 addflag(&fdef[2], "-d", NODATA, SHORTOPT);
1016 addflag(&fdef[2], "-f", NODATA, SHORTOPT);
1017 addflag(&fdef[2], "-i", NODATA, SHORTOPT);
1018 addflag(&fdef[2], "-r", NODATA, SHORTOPT);
1019 addflag(&fdef[2], "-R", NODATA, SHORTOPT);
1020 addflag(&fdef[2], "-v", NODATA, SHORTOPT);
1021 addflag(&fdef[2], "--directory", NODATA, LONGOPT);
1022 addflag(&fdef[2], "--force", NODATA, LONGOPT);
1023 addflag(&fdef[2], "--interactive", NODATA, LONGOPT);
1024 addflag(&fdef[2], "--no-preserve-root", NODATA, LONGOPT);
1025 addflag(&fdef[2], "--preserve-root", NODATA, LONGOPT);
1026 addflag(&fdef[2], "--verbose", NODATA, LONGOPT);
1027 addflag(&fdef[2], "--help", NODATA, LONGOPT);
1028 addflag(&fdef[2], "--version", NODATA, LONGOPT);
1029 ///////////////////////////////////////////////
1030 // End of the definition part //
1031 ///////////////////////////////////////////////
1032
1033 ///////////////////////////////////////////////
1034 // Here is definition of temp functinon, //
1035 // this is a restplace for any function not //
1036 // matching any previous one. //
1037 ///////////////////////////////////////////////
1038 fdef[3].fbase = strdup("");
1039 fdef[3].outcount = 0;
1040 fdef[3].outputs = malloc(sizeof(outformat));
1041 fdef[3].flagcount = 0;
1042 fdef[3].flags = malloc(sizeof(paramflag));
1043 ///////////////////////////////////////////////
1044 // End of the definition part //
1045 ///////////////////////////////////////////////
1046
1047 subdepth = 0;
1048 subbottom = 0;
1049 qstatus = QNONE;
1050 pstatus = 0;
1051 sstatus = 0;
1052 shell = malloc(sizeof(subshell));
1053 shell[0].pwd = strdup("/"); // We are not going to absolutize yet.
1054 shell[0].status = SBLOCK; // This is a hack which prevents segfaults if some code eventually breaks the handling;
1055
1056 ptr = line;
1057 eptr = line + strlen(line);
1058
1059 ptr = line;
1060
1061 while (*ptr != '\0') {
1062 switch (*ptr) {
1063 case '#':
1064 while ((*ptr != '\n') && (*ptr != '\0')) {
1065 ptr++;
1066 }
1067 break;
1068 case '\\':
1069 ptr++;
1070 break;
1071
1072 case ' ':
1073 case ';':
1074 case '\t':
1075 case '\n':
1076 if (sstatus == 2) { sstatus = 0; }
1077 break;
1078
1079 case '{':
1080 case '(':
1081 //pstatus = 1; // We check for ( cd /foo ; ln -sf foo bar ) or .. rm -rf foo )
1082 switch (pstatus) {
1083 case 0:
1084 case 4:
1085 pstatus++;
1086 break;
1087 default:
1088 pstatus = 0;
1089 break;
1090 }
1091
1092 subdepth++;
1093 shell = realloc(shell, sizeof(subshell) * (subdepth+1));
1094 shell[subdepth].pwd = strdup(shell[subdepth-1].pwd);
1095 shell[subdepth].status = SCLEAR;
1096 break;
1097 case ')':
1098 case '}':
1099 if (shell[subdepth].status == SCLEAR) {
1100 switch (pstatus) {
1101 case 7:
1102 pstatus = 0;
1103 ///////////////////////
1104 // Nasty tmp mess //
1105 ///////////////////////
1106 tmp2 = getfuncdata(&fdef[2], 0, -1);
1107 if (tmp2 != NULL) {
1108 tmp = getfuncdata(&fdef[0], 1, -1);
1109 if (tmp != NULL) {
1110 if (!strcmp(tmp2, tmp)) {
1111 // More or less slack way, how about if it is a -symbolic- link?
1112 if ((tmp3 = getfuncdata(&fdef[0], 0, 5)) != NULL) {
1113 free(tmp3);
1114
1115 addfile(pinfo, absolutizestr(tmp2, shell[subdepth].pwd), F_IRRELEVANT);
1116 }
1117 else if ((tmp3 = getfuncdata(&fdef[0], 0, 14)) != NULL) {
1118 free(tmp3);
1119
1120 addfile(pinfo, absolutizestr(tmp2, shell[subdepth].pwd), F_IRRELEVANT);
1121 }
1122 free(tmp);
1123 } else {
1124 free(tmp);
1125 }
1126
1127 free(tmp2);
1128 } else {
1129 free(tmp2);
1130 }
1131 }
1132 break;
1133 case 3:
1134 pstatus ++;
1135 break;
1136 default:
1137 pstatus = 0;
1138 break;
1139 }
1140
1141 free(shell[subdepth].pwd);
1142 subdepth--;
1143 shell = realloc(shell, sizeof(subshell) * (subdepth+1));
1144 }
1145 break;
1146 case '`':
1147 switch (qstatus) {
1148 case QNONE:
1149 qstatus = QSUBSHELL;
1150 subdepth++;
1151 shell = realloc(shell, sizeof(subshell) * (subdepth+1));
1152 shell[subdepth].pwd = strdup(shell[subdepth-1].pwd);
1153 break;
1154 case QSUBSHELL:
1155 qstatus = QNONE;
1156 free(shell[subdepth].pwd);
1157 subdepth--;
1158 shell = realloc(shell, sizeof(subshell) * (subdepth+1));
1159 break;
1160 }
1161 break;
1162
1163 default:
1164 rptr = ptr;
1165
1166 while ((!isspace(*rptr)) && (*rptr != ';') && (*rptr != '(') && (*rptr != ')') && (*rptr != '{') && (*rptr != '}') && (*rptr != '\0')) {
1167 rptr++;
1168 }
1169
1170 fptr = rptr;
1171 tmp = strndup(ptr, rptr - ptr);
1172
1173 reval = matchfuncdef(fdef, tmp, 3);
1174 if (reval == -1) { reval = 3; free(fdef[reval].fbase); fdef[reval].fbase=strdup(tmp); }
1175 clearfuncdata(&fdef[reval]);
1176
1177 if (!isshellbuiltin(&shbin, tmp)) {
1178 parsecommand(ptr, eptr, &fptr, &fdef[reval]);
1179 }
1180 free(tmp);
1181
1182 ptr = fptr;
1183 switch (reval) {
1184 case 0: // symlink
1185 tmp2 = getfuncdata(&fdef[reval], 0, -1);
1186
1187 if (tmp != NULL) {
1188 tmp = getfuncdata(&fdef[reval], 1, -1);
1189 if ((tmp != NULL)&&(*tmp != '\0')) {
1190 if (pstatus == 6) {
1191 pstatus++;
1192 } else {
1193 pstatus = 0;
1194 if (sstatus == 0) {
1195 addfile(pinfo, absolutizestr(tmp, shell[subdepth].pwd), F_IRRELEVANT);
1196 } // else protected and we don't do any other than what removepkg would see
1197 }
1198 free(tmp);
1199 } else {
1200 pstatus = 0;
1201 }
1202 free(tmp2);
1203 } else {
1204 pstatus = 0;
1205 }
1206 break;
1207 case 1: // cd
1208 tmp = getfuncdata(&fdef[reval], 0, -1);
1209
1210 if ((pstatus == 1) || (pstatus == 5)) { pstatus ++; }
1211
1212 if (tmp != NULL) {
1213 if (tmp[0] == '/') {
1214 free(shell[subdepth].pwd);
1215 shell[subdepth].pwd = strdup(tmp);
1216 } else {
1217 free(shell[subdepth].pwd);
1218 shell[subdepth].pwd = absolutizestr(tmp, shell[subdepth-1].pwd);
1219 }
1220 free(tmp);
1221 }
1222 break;
1223 case 2: // rm
1224 tmp = getfuncdata(&fdef[reval], 0, -1);
1225 if (tmp != NULL) {
1226 if (pstatus == 2) { pstatus++; } else { pstatus = 0; }
1227 free(tmp);
1228 }
1229 break;
1230 default:
1231 pstatus = 0;
1232 if (!strcmp(fdef[reval].fbase, "case")) {
1233 shell[subdepth].status = SBLOCK;
1234 sstatus = 1;
1235 }
1236 if (!strcmp(fdef[reval].fbase, "esac")) {
1237 shell[subdepth].status = SCLEAR;
1238 sstatus = 0;
1239 }
1240 if ((!strcmp(fdef[reval].fbase, "&&")) || (!strcmp(fdef[reval].fbase, "||"))) {
1241 sstatus = 2;
1242 }
1243
1244 if ((!strcmp(fdef[reval].fbase, "if")) || (!strcmp(fdef[reval].fbase, "do"))) {
1245 sstatus = 1;
1246 }
1247
1248 if ((!strcmp(fdef[reval].fbase, "fi")) || (!strcmp(fdef[reval].fbase, "done"))) {
1249 sstatus = 0;
1250 }
1251 break;
1252 }
1253
1254 if (*ptr == '\0') {
1255 freeshellbuiltins(&shbin);
1256 for (i=0; i<handfuncount; i++) {
1257 freefuncdef(&fdef[i]);
1258 }
1259 free(fdef);
1260
1261 clearupsshells(shell, subdepth);
1262 free(shell);
1263 return 0;
1264 }
1265 break;
1266 }
1267 ptr++;
1268 }
1269
1270 clearupsshells(shell, subdepth);
1271 free(shell);
1272
1273 freeshellbuiltins(&shbin);
1274
1275 for (i=0; i<handfuncount; i++) {
1276 freefuncdef(&fdef[i]);
1277 }
1278
1279 free(fdef);
1280
1281 return 0;
1282 }
1283 #else
1284 ///////////////////////////////////////////////////////////////////////////////
1285 // //
1286 // T R I V I A L S H E L L S E M I P A R S I N G //
1287 // //
1288 ///////////////////////////////////////////////////////////////////////////////
1289
1290
1291 // FREELINKINFO()
1292 //
1293 // Frees information about a symlink
1294 //
1295 // Parameters:
1296 // pointer to linkinfo
1297 //
1298 // Return value:
1299 // none
1300 static void freelinkinfo(linkinfo *tofree) {
1301 if (tofree->linkfile != NULL) { free(tofree->linkfile); }
1302 if (tofree->target != NULL) { free(tofree->target); }
1303 free(tofree);
1304 }
1305
1306 // STRNCHR()
1307 //
1308 // Same as strchr, but never goes over len chars.
1309 //
1310 // Parameters:
1311 // string checked
1312 // needle character
1313 // size of buffer
1314 //
1315 // Return value:
1316 // pointer to first match of needle
1317 // NULL if not matched
1318 static char *strnchr(char *s, int c, unsigned long len) {
1319 char *ptr;
1320
1321 for (ptr = s; (char*)ptr < ((char*)s)+len; ptr++) {
1322 if (*ptr == c) { return ptr; }
1323 }
1324
1325 return NULL;
1326 }
1327
1328 // CHECKFORCOMMENT()
1329 //
1330 // Checks if the given line contains comment.
1331 //
1332 // Parameters:
1333 // the line
1334 //
1335 // Return value:
1336 // 0 if no comment
1337 // 1 if comment
1338 static int checkforcomment(char *line) {
1339 char *ptr;
1340
1341 ptr = line;
1342 while ((*ptr != '\n') && (*ptr != '\0')) {
1343 if (*ptr == '#') {
1344 *ptr = '\0';
1345 return 1;
1346 }
1347 ptr++;
1348 }
1349 return 0;
1350 }
1351
1352 // READLINE()
1353 //
1354 // Reads a line from given source
1355 //
1356 // Parameters:
1357 // pointer to the line, it will be changed to sthe new line.
1358 // ending pointer
1359 //
1360 // Return value:
1361 // malloced line
1362 static char *readline(char **ptr, char *eptr) {
1363 char *line, *hptr;
1364
1365 do {
1366 if ((hptr = strnchr(*ptr, '\n', eptr - *ptr)) == NULL) {
1367 hptr = eptr;
1368 }
1369 } while (*(hptr-1) == '\\');
1370 line = malloc(hptr - *ptr + 1);
1371 strncpy(line, *ptr, hptr - *ptr);
1372 line[hptr - *ptr] = '\0';
1373
1374 *ptr = hptr + 1;
1375
1376 return line;
1377 }
1378
1379 // LINETOLINK()
1380 //
1381 // Checks if the symlink is on the given line and if it is created slackware
1382 // style. If so, it gives details about the symlink.
1383 //
1384 // Parameters:
1385 // line
1386 //
1387 // Return value:
1388 // pointer symlink information
1389 // NULL if not slackware symlink
1390 static linkinfo *linetolink(char *line) {
1391 char *rptr, *rhptr, *tmp; // these for reversing the script
1392 linkinfo *reval;
1393
1394 reval = malloc(sizeof(linkinfo));
1395 reval->linkfile = NULL;
1396 reval->target = NULL;
1397
1398 rptr = strstr(line, "( cd ");
1399 if (rptr == NULL) {
1400 freelinkinfo(reval);
1401 return NULL;
1402 }
1403
1404 rptr += 4;
1405 *rptr = '/'; // We need a prefixing '/', and the previous data is of no interest
1406 if ((rhptr = strstr(line, " ; ")) == NULL) {
1407 freelinkinfo(reval);
1408 return NULL;
1409 }
1410 *rhptr = '\0';
1411
1412 tmp = strdup(rptr);
1413
1414 rhptr++;
1415 if ((rptr = strstr(rhptr, "ln -sf")) == NULL) {
1416 free(tmp);
1417 freelinkinfo(reval);
1418 return NULL;
1419 }
1420
1421 rptr += 7;
1422
1423 if ((rhptr = strchr(rptr, ' ')) == NULL) {
1424 free(tmp);
1425 freelinkinfo(reval);
1426 return NULL;
1427 }
1428 *rhptr = '\0';
1429
1430 reval->target = strdup(rptr);
1431
1432 rptr = rhptr+1;
1433
1434 if ((rhptr = strchr(rptr, ' ')) == NULL) {
1435 free(tmp);
1436 freelinkinfo(reval);
1437 return NULL;
1438 }
1439 *rhptr = '\0';
1440
1441 if (*(rhptr+1) != ')') {
1442 free(tmp);
1443 freelinkinfo(reval);
1444 return NULL;
1445 }
1446
1447 *rhptr = '\0';
1448
1449 reval->linkfile = absolutizestr(rptr, tmp);
1450 free(tmp);
1451
1452 return reval;
1453 }
1454
1455 // LINETORM()
1456 //
1457 // Checks if the rm is on the given line and if it is created slackware
1458 // style. If so, it gives details about the rm.
1459 //
1460 // Parameters:
1461 // line
1462 //
1463 // Return value:
1464 // file which would be removed
1465 // NULL if not slackware rm
1466 static char *linetorm(char *line) {
1467 char *rptr, *rhptr, *reval, *tmp; // these for reversing the script
1468
1469 rptr = strstr(line, "( cd ");
1470 if (rptr == NULL) {
1471 return NULL;
1472 }
1473
1474 rptr += 4;
1475 *rptr = '/'; // We need a prefixing '/', and the previous data is of no interest
1476 if ((rhptr = strstr(line, " ; ")) == NULL) {
1477 return NULL;
1478 }
1479 *rhptr = '\0';
1480
1481 tmp = strdup(rptr);
1482
1483 rhptr++;
1484 if ((rptr = strstr(rhptr, "rm -rf")) == NULL) {
1485 free(tmp);
1486 return NULL;
1487 }
1488
1489 rptr += 7;
1490
1491 if ((rhptr = strrchr(rptr, ' ')) == NULL) {
1492 free(tmp);
1493 return NULL;
1494 }
1495 *rhptr = '\0';
1496
1497 reval = absolutizestr(rptr, tmp);
1498 free(tmp);
1499
1500 if (*(rhptr+1) != ')') {
1501 free(tmp);
1502 free(reval);
1503 return NULL;
1504 }
1505
1506 return reval;
1507 }
1508
1509 // PARSEDOINST()
1510 //
1511 // Parses the doinst.sh script. This is the trivial one, it only checks for
1512 // those generated by the official slackware makepkg
1513 //
1514 // Parameters:
1515 // the parsed doinst.sh
1516 // destination directory (viz pdef.ddir)
1517 // pointer to package info where we write data
1518 //
1519 // Return value:
1520 // 0, always
1521 static int parsedoinst(char *fullfile, char *dirprefix, pkginfo *pinfo) {
1522 char *line, *oldline, *tmp, *tmpcomp, *processedline, *ptr;
1523 linkinfo *tstlink;
1524 unsigned long filesize;
1525
1526 line = NULL;
1527 filesize = strlen(fullfile);
1528
1529 ptr = fullfile;
1530
1531 do {
1532 oldline = line;
1533 line = readline(&ptr, fullfile + filesize);
1534 checkforcomment(line);
1535 if (*line != '\0') {
1536 processedline=strdup(line); // We dup here instead of before checkforcomment, since we want comments lost anyway
1537 if ((tstlink = linetolink(processedline)) != NULL) {
1538 if ((tmp = linetorm(oldline)) != NULL) {
1539 tmpcomp = absolutizestr(tmp, dirprefix);
1540 free(tmp);
1541 tmp = absolutizestr(tstlink->linkfile, dirprefix);
1542
1543 if (!strcmp(tmp, tmpcomp)) { // is the previous rm and the current ln the same?
1544 addfile(pinfo, strdup(tmp), F_IRRELEVANT);
1545 }
1546
1547 free(tmpcomp);
1548 free(tmp);
1549 }
1550 freelinkinfo(tstlink);
1551 }
1552 free(processedline);
1553 }
1554 free(oldline);
1555 } while((void*)ptr < (((void*)fullfile) + filesize));
1556 free(line);
1557
1558 return 0;
1559 }
1560 ///////////////////////////////////////////////////////////////////////////////
1561 #endif
1562
1563 ///////////////////////////////////////////////////////////////////////////////
1564 // //
1565 // A P I F U N C T I O N S //
1566 // //
1567 ///////////////////////////////////////////////////////////////////////////////
1568
1569 void *opendb(char *path) {
1570 dbhandle *reval;
1571 char *tmpfpath;
1572
1573 tmpfpath = malloc(strlen(path) + 11); // + 'packages/' + '/' + '\0'
1574 strcpy(tmpfpath, path);
1575 if (tmpfpath[strlen(tmpfpath)-1] != '/') {
1576 strcat(tmpfpath, "/");
1577 }
1578 strcat(tmpfpath, "packages/");
1579
1580 reval = malloc(sizeof(dbhandle));
1581 reval->fpath = strdup(path);
1582 reval->curname = 0;
1583 reval->namecount = scandir(tmpfpath, &reval->namelist, infilter, alphasort);
1584 free(tmpfpath);
1585 if (reval -> namecount <= 0) {
1586 free(reval->fpath);
1587 free(reval);
1588 return NULL;
1589 }
1590
1591 return reval;
1592 }
1593 void rewinddb(void *handle) {
1594 ((dbhandle*)handle)->curname = 0;
1595 }
1596 int iswriteable(void *handle) {
1597 return 0;
1598 }
1599 int closedb(void *handle) {
1600 long i;
1601 for (i=0; i<((dbhandle*)handle)->namecount; i++) {
1602 free(((dbhandle*)handle)->namelist[i]);
1603 }
1604 free(((dbhandle*)handle)->namelist);
1605 free(((dbhandle*)handle)->fpath);
1606 free(((dbhandle*)handle));
1607 return 0;
1608 }
1609 int readpkg(void *handle, pkginfo *pinfo) {
1610 struct stat statbuf;
1611 void *filemap;
1612 int fd;
1613
1614 char *buf, *sptr, *eptr;
1615
1616
1617 if (((dbhandle*)handle)->curname >= ((dbhandle*)handle)->namecount) {
1618 return 1;
1619 }
1620
1621 // The base control data
1622 buf = malloc(strlen(((dbhandle*)handle)->fpath) + strlen(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name) + 11);
1623 buf = strcpy(buf, ((dbhandle*)handle)->fpath);
1624 if (buf[strlen(((dbhandle*)handle)->fpath)-1] != '/') {
1625 buf = strcat(buf, "/");
1626 }
1627 buf = strcat(buf, "packages/");
1628 buf = strcat(buf, ((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
1629
1630 if ((fd = open(buf, O_RDONLY)) == -1) {
1631 free(buf);
1632 return 1;
1633 }
1634 fstat(fd, &statbuf);
1635 free(buf);
1636
1637
1638 filemap = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
1639 if (filemap == MAP_FAILED) { return 1; }
1640
1641 sptr = filemap;
1642
1643 buf = getctrlhdr(filemap, "PACKAGE NAME:", statbuf.st_size);
1644 parseslackname(buf, pinfo);
1645 free(buf);
1646
1647 if ((buf = getctrlhdr(filemap, "PACKAGE DESCRIPTION:", statbuf.st_size)) != NULL) {
1648 sptr = buf;
1649 eptr = buf + strlen(buf);
1650 if ((sptr = strchr(buf, ':')) != NULL) {
1651 if (sptr < eptr + 1) {
1652 sptr++;
1653 }
1654 while ((isspace(*sptr)) && (*sptr!= '\n') && (sptr < eptr)) {
1655 sptr++;
1656 }
1657
1658 pinfo->description = strdup(sptr);
1659 if (pinfo->name == NULL) {
1660 *sptr = '\0';
1661 pinfo->name = strdup(buf);
1662 }
1663 } else {
1664 pinfo->description = strdup(sptr);
1665 }
1666 free(buf);
1667 } else {
1668 pinfo->description = strdup("Slackware package, no description.");
1669 }
1670
1671 ensuredata(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name, pinfo);
1672
1673 sptr = pstrnstr(filemap, "FILE LIST:\n", statbuf.st_size, 0);
1674
1675 if ((sptr == NULL) || ((sptr != filemap) && (*(sptr-1) != '\n'))) {
1676 free(pinfo->name);
1677 free(pinfo->version);
1678 free(pinfo->description);
1679 return 1;
1680 }
1681
1682 sptr += 11;
1683 do {
1684 eptr = strchr(sptr, '\n');
1685 if (eptr == NULL) {
1686 eptr = (char*)(filemap + statbuf.st_size);
1687 }
1688 buf = strndup(sptr, eptr - sptr);
1689 addfile(pinfo, absolutizestr(buf, "/"), F_IRRELEVANT);
1690 free(buf);
1691 sptr = eptr + 1;
1692 } while (sptr < (char*)(filemap + statbuf.st_size));
1693
1694 munmap(filemap, statbuf.st_size);
1695 close(fd);
1696
1697 // Now the doinst.sh, acting as posinst -- we don't really mind if this
1698 // fails.
1699 buf = malloc(strlen(((dbhandle*)handle)->fpath) + strlen(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name) + 10);
1700 buf = strcpy(buf, ((dbhandle*)handle)->fpath);
1701 if (buf[strlen(((dbhandle*)handle)->fpath)-1] != '/') {
1702 buf = strcat(buf, "/");
1703 }
1704 buf = strcat(buf, "scripts/");
1705 buf = strcat(buf, ((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
1706
1707 if ((fd = open(buf, O_RDONLY)) != -1) {
1708 fstat(fd, &statbuf);
1709 if (statbuf.st_size > 0) {
1710 // It's senseless to attempt to load a file that's just empty
1711 filemap = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
1712 if (filemap != MAP_FAILED) {
1713 pinfo->postinst.len = statbuf.st_size + 1;
1714 pinfo->postinst.data = malloc(pinfo->postinst.len);
1715 memcpy(pinfo->postinst.data, filemap, pinfo->postinst.len - 1);
1716 pinfo->postinst.data[pinfo->postinst.len - 1] = '\0';
1717
1718 parsedoinst(pinfo->postinst.data, "/", pinfo);
1719
1720 munmap(filemap, statbuf.st_size);
1721 }
1722 }
1723 close(fd);
1724 }
1725 free(buf);
1726
1727 ((dbhandle*)handle)->curname++;
1728
1729 if (pinfo->postinst.data != NULL) {
1730 // Installpkg passes this. Although no script really uses
1731 // it, let's be nice.
1732 pinfo->postinst.parameters[A_IRRELEVANT] = strdup("-install");
1733 }
1734 return 0;
1735 }
1736 int writepkg(void *handle, pkginfo *pinfo) {
1737 return 1;
1738 }
1739 int delpkg(void *handle, char *pneedle) {
1740 return 1;
1741 }
1742 int findpkg(void *handle, pkginfo needle, pkginfo *reval, int matchtype) {
1743 char *ptr, *buf;
1744 pkginfo tmppinfo;
1745 unsigned long i, j;
1746
1747 while (((dbhandle*)handle)->curname < ((dbhandle*)handle)->namecount) {
1748 if ((matchtype & MATCH_NAME) && (!(matchtype & MATCH_FILE))) {
1749 buf = strdup(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
1750
1751 ptr = strrchr(buf, '-'); // build
1752 if (ptr != NULL) {
1753 *ptr = '\0';
1754 ptr = strrchr(buf, '-'); // arch
1755 if (ptr != NULL) {
1756 *ptr = '\0';
1757 ptr = strrchr(buf, '-'); // version
1758 if (ptr != NULL) {
1759 *ptr = '\0';
1760 }
1761 }
1762 }
1763
1764 if (!fnmatch(needle.name, buf, 0)) {
1765 if (reval != NULL) {
1766 if (readpkg(handle, reval)) {
1767 continue;
1768 }
1769 } else {
1770 ((dbhandle*)handle)->curname++;
1771 }
1772
1773 if ((matchtype & MATCH_OVRWR) && (!strcmp(needle.name, buf))) {
1774 free(buf);
1775 return -1;
1776 } else {
1777 free(buf);
1778 return 1;
1779 }
1780 }
1781 free(buf);
1782 } else if ((matchtype & MATCH_FILE) && (!(matchtype & MATCH_NAME))) {
1783 clearpinfo(&tmppinfo);
1784 readpkg(handle, &tmppinfo);
1785 for (i=0; i<needle.filecount; i++) {
1786 for (j=0; j<tmppinfo.filecount; j++) {
1787 // We do NOT want to match directories.
1788 if (needle.files[i].flag == F_DIRECTORY) continue;
1789 if (!fnmatch(needle.files[i].name, tmppinfo.files[j].name, 0)) {
1790 if (reval != NULL) {
1791 memcpy(reval, &tmppinfo, sizeof(pkginfo));
1792 }
1793 if ((matchtype & MATCH_OVRWR) && (!strcmp(needle.name, tmppinfo.name))){
1794 if (reval == NULL) {
1795 freepinfo(&tmppinfo);
1796 }
1797 return -1;
1798 } else {
1799 if (reval == NULL) {
1800 freepinfo(&tmppinfo);
1801 }
1802 return 1;
1803 }
1804 }
1805 }
1806 }
1807 freepinfo(&tmppinfo);
1808 } else if ((matchtype & MATCH_NAME) && (matchtype & MATCH_FILE)) {
1809 buf = strdup(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
1810
1811 ptr = strrchr(buf, '-'); // build
1812 if (ptr != NULL) {
1813 *ptr = '\0';
1814 ptr = strrchr(buf, '-'); // arch
1815 if (ptr != NULL) {
1816 *ptr = '\0';
1817 ptr = strrchr(buf, '-'); // version
1818 if (ptr != NULL) {
1819 *ptr = '\0';
1820 }
1821 }
1822 }
1823
1824 clearpinfo(&tmppinfo);
1825 readpkg(handle, &tmppinfo);
1826 for (i=0; i<needle.filecount; i++) {
1827 for (j=0; j<tmppinfo.filecount; j++) {
1828 // We do NOT want to match directories.
1829 if (needle.files[i].flag == F_DIRECTORY) continue;
1830 if (!fnmatch(needle.files[i].name, tmppinfo.files[j].name, 0)) {
1831 if (reval != NULL) {
1832 memcpy(reval, &tmppinfo, sizeof(pkginfo));
1833 }
1834 if ((matchtype & MATCH_OVRWR) && (!strcmp(needle.name, tmppinfo.name))){
1835 if (reval == NULL) {
1836 freepinfo(&tmppinfo);
1837 }
1838 return -1;
1839 } else {
1840 if (reval == NULL) {
1841 freepinfo(&tmppinfo);
1842 }
1843 return 1;
1844 }
1845 }
1846 }
1847 }
1848 freepinfo(&tmppinfo);
1849
1850 if (!fnmatch(needle.name, buf, 0)) {
1851 free(buf);
1852 } else {
1853 free(buf);
1854 }
1855 break;
1856 }
1857 ((dbhandle*)handle)->curname++;
1858 }
1859 ((dbhandle*)handle)->curname = 0;
1860
1861 return 0;
1862 }