Changeset 53832


Ignore:
Timestamp:
Jul 15, 2009, 5:46:06 AM (10 years ago)
Author:
blb@…
Message:

Merge from trunk

Location:
branches/images-and-archives/base
Files:
5 edited
5 copied

Legend:

Unmodified
Added
Removed
  • branches/images-and-archives/base

  • branches/images-and-archives/base/src/pextlib1.0/Makefile

    r53746 r53832  
    1 OBJS=           Pextlib.o strsed.o fgetln.o md5cmd.o setmode.o xinstall.o \
    2                 fs-traverse.o strcasecmp.o vercomp.o filemap.o \
    3                 sha1cmd.o curl.o rmd160cmd.o readline.o uid.o\
    4                 tracelib.o tty.o sysctl.o readdir.o pipe.o
    5 SHLIB_NAME=     Pextlib${SHLIB_SUFFIX}
     1OBJS= \
     2        Pextlib.o strsed.o fgetln.o md5cmd.o setmode.o xinstall.o \
     3        fs-traverse.o strcasecmp.o vercomp.o filemap.o \
     4        sha1cmd.o curl.o rmd160cmd.o readline.o uid.o \
     5        tracelib.o tty.o sysctl.o readdir.o pipe.o flock.o \
     6        system.o
     7SHLIB_NAME= Pextlib${SHLIB_SUFFIX}
    68INSTALLDIR= ${DESTDIR}${datadir}/macports/Tcl/pextlib1.0
    79
  • branches/images-and-archives/base/src/pextlib1.0/Pextlib.c

    r53746 r53832  
    5353#endif
    5454
    55 #if HAVE_PATHS_H
    56 #include <paths.h>
    57 #endif
    58 
    59 #ifndef _PATH_DEVNULL
    60 #define _PATH_DEVNULL   "/dev/null"
    61 #endif
    62 
    6355#include <pwd.h>
    64 
    65 #if HAVE_SYS_FILE_H
    66 #include <sys/file.h>
    67 #endif
    6856
    6957#if HAVE_SYS_TYPES_H
     
    9280
    9381#include <tcl.h>
     82
     83#include "Pextlib.h"
    9484
    9585#include "md5cmd.h"
     
    10999#include "readdir.h"
    110100#include "pipe.h"
     101#include "flock.h"
     102#include "system.h"
    111103
    112104#if HAVE_CRT_EXTERNS_H
     
    126118char *fgetln(FILE *stream, size_t *len);
    127119#endif
    128 
    129 #define CBUFSIZ 30
    130120
    131121static char *
     
    196186}
    197187
    198 struct linebuf {
    199         size_t len;
    200         char *line;
    201 };
    202 
    203 int SystemCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    204 {
    205         char *buf;
    206         struct linebuf circbuf[CBUFSIZ];
    207         size_t linelen;
    208         char *args[4];
    209         char *cmdstring;
    210         FILE *pdes;
    211         int fdset[2], nullfd;
    212         int fline, pos, ret;
    213         int osetsid = 0;
    214         pid_t pid;
    215         Tcl_Obj *errbuf;
    216         Tcl_Obj *tcl_result;
    217         int read_failed, status;
    218 
    219         /* usage: system [-notty] command */
    220         if (objc == 2) {
    221                 cmdstring = Tcl_GetString(objv[1]);
    222         } else if (objc == 3) {
    223                 char *arg = Tcl_GetString(objv[1]);
    224                 cmdstring = Tcl_GetString(objv[2]);
    225 
    226                 if (strcmp(arg, "-notty") == 0) {
    227                         osetsid = 1;
    228                 } else {
    229                         tcl_result = Tcl_NewStringObj("bad option ", -1);
    230                         Tcl_AppendObjToObj(tcl_result, Tcl_NewStringObj(arg, -1));
    231                         Tcl_SetObjResult(interp, tcl_result);
    232                         return TCL_ERROR;
    233                 }
    234         } else {
    235                 Tcl_WrongNumArgs(interp, 1, objv, "command");
    236                 return TCL_ERROR;
    237         }
    238 
    239         /*
    240          * Fork a child to run the command, in a popen() like fashion -
    241          * popen() itself is not used because stderr is also desired.
    242          */
    243         if (pipe(fdset) != 0) {
    244                 return TCL_ERROR;
    245         }
    246 
    247         pid = fork();
    248         switch (pid) {
    249         case -1: /* error */
    250                 return TCL_ERROR;
    251                 break;
    252         case 0: /* child */
    253                 close(fdset[0]);
    254 
    255                 if ((nullfd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
    256                         _exit(1);
    257                 dup2(nullfd, STDIN_FILENO);
    258                 dup2(fdset[1], STDOUT_FILENO);
    259                 dup2(fdset[1], STDERR_FILENO);
    260                 /* drop the controlling terminal if requested */
    261                 if (osetsid) {
    262                         if (setsid() == -1)
    263                                 _exit(1);
    264                 }
    265                 /* XXX ugly string constants */
    266                 args[0] = "sh";
    267                 args[1] = "-c";
    268                 args[2] = cmdstring;
    269                 args[3] = NULL;
    270                 execve("/bin/sh", args, environ);
    271                 _exit(1);
    272                 break;
    273         default: /* parent */
    274                 break;
    275         }
    276 
    277         close(fdset[1]);
    278 
    279         /* read from simulated popen() pipe */
    280         read_failed = 0;
    281         pos = 0;
    282         bzero(circbuf, sizeof(circbuf));
    283         pdes = fdopen(fdset[0], "r");
    284         while ((buf = fgetln(pdes, &linelen)) != NULL) {
    285                 char *sbuf;
    286                 int slen;
    287 
    288                 /*
    289                  * Allocate enough space to insert a terminating
    290                  * '\0' if the line is not terminated with a '\n'
    291                  */
    292                 if (buf[linelen - 1] == '\n')
    293                         slen = linelen;
    294                 else
    295                         slen = linelen + 1;
    296 
    297                 if (circbuf[pos].len == 0)
    298                         sbuf = malloc(slen);
    299                 else {
    300                         sbuf = realloc(circbuf[pos].line, slen);
    301                 }
    302 
    303                 if (sbuf == NULL) {
    304                         read_failed = 1;
    305                         break;
    306                 }
    307 
    308                 memcpy(sbuf, buf, linelen);
    309                 /* terminate line with '\0',replacing '\n' if it exists */
    310                 sbuf[slen - 1] = '\0';
    311 
    312                 circbuf[pos].line = sbuf;
    313                 circbuf[pos].len = slen;
    314 
    315                 if (pos++ == CBUFSIZ - 1) {
    316                         pos = 0;
    317                 }
    318 
    319                 if (ui_info(interp, sbuf) != TCL_OK) {
    320                         read_failed = 1;
    321                         break;
    322                 }
    323         }
    324         fclose(pdes);
    325 
    326         status = TCL_ERROR;
    327 
    328         if (wait(&ret) == pid && WIFEXITED(ret) && !read_failed) {
    329                 /* Normal exit, and reading from the pipe didn't fail. */
    330                 if (WEXITSTATUS(ret) == 0) {
    331                         status = TCL_OK;
    332                 } else {
    333                         /* Copy the contents of the circular buffer to errbuf */
    334                         Tcl_Obj* errorCode;
    335                         errbuf = Tcl_NewStringObj(NULL, 0);
    336                         for (fline = pos; pos < fline + CBUFSIZ; pos++) {
    337                                 if (circbuf[pos % CBUFSIZ].len == 0)
    338                                 continue; /* skip empty lines */
    339 
    340                                 /* Append line, minus trailing NULL */
    341                                 Tcl_AppendToObj(errbuf, circbuf[pos % CBUFSIZ].line,
    342                                                 circbuf[pos % CBUFSIZ].len - 1);
    343 
    344                                 /* Re-add previously stripped newline */
    345                                 Tcl_AppendToObj(errbuf, "\n", 1);
    346                         }
    347 
    348                         /* set errorCode [list CHILDSTATUS <pid> <code>] */
    349                         errorCode = Tcl_NewListObj(0, NULL);
    350                         Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewStringObj("CHILDSTATUS", -1));
    351                         Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewIntObj(pid));
    352                         Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewIntObj(WEXITSTATUS(ret)));
    353                         Tcl_SetObjErrorCode(interp, errorCode);
    354 
    355                         /* set result */
    356                         tcl_result = Tcl_NewStringObj("shell command \"", -1);
    357                         Tcl_AppendToObj(tcl_result, cmdstring, -1);
    358                         Tcl_AppendToObj(tcl_result, "\" returned error ", -1);
    359                         Tcl_AppendObjToObj(tcl_result, Tcl_NewIntObj(WEXITSTATUS(ret)));
    360                         Tcl_AppendToObj(tcl_result, "\nCommand output: ", -1);
    361                         Tcl_AppendObjToObj(tcl_result, errbuf);
    362                         Tcl_SetObjResult(interp, tcl_result);
    363                 }
    364         }
    365 
    366         /* Cleanup. */
    367         close(fdset[0]);
    368         for (fline = 0; fline < CBUFSIZ; fline++) {
    369                 if (circbuf[fline].len != 0) {
    370                         free(circbuf[fline].line);
    371                 }
    372         }
    373 
    374         return status;
    375 }
    376 
    377 int FlockCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    378 {
    379         static const char errorstr[] = "use one of \"-shared\", \"-exclusive\", or \"-unlock\", and optionally \"-noblock\"";
    380         int operation = 0, fd, i, ret;
    381         int errnoval = 0;
    382         int oshared = 0, oexclusive = 0, ounlock = 0, onoblock = 0;
    383 #if defined(HAVE_LOCKF) && !defined(HAVE_FLOCK)
    384         off_t curpos;
    385 #endif
    386         char *res;
    387         Tcl_Channel channel;
    388         ClientData handle;
    389 
    390         if (objc < 3 || objc > 4) {
    391                 Tcl_WrongNumArgs(interp, 1, objv, "channelId switches");
    392                 return TCL_ERROR;
    393         }
    394 
    395         if ((channel = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL)) == NULL)
    396                 return TCL_ERROR;
    397 
    398         if (Tcl_GetChannelHandle(channel, TCL_READABLE|TCL_WRITABLE, &handle) != TCL_OK) {
    399                 Tcl_SetResult(interp, "error getting channel handle", TCL_STATIC);
    400                 return TCL_ERROR;
    401         }
    402         fd = (int)(intptr_t)handle;
    403 
    404         for (i = 2; i < objc; i++) {
    405                 char *arg = Tcl_GetString(objv[i]);
    406                 if (!strcmp(arg, "-shared")) {
    407                   oshared = 1;
    408                 } else if (!strcmp(arg, "-exclusive")) {
    409                   oexclusive = 1;
    410                 } else if (!strcmp(arg, "-unlock")) {
    411                   ounlock = 1;
    412                 } else if (!strcmp(arg, "-noblock")) {
    413                   onoblock = 1;
    414                 }
    415         }
    416 
    417         /* verify the arguments */
    418 
    419         if((oshared + oexclusive + ounlock) != 1) {
    420           /* only one of the options should have been specified */
    421           Tcl_SetResult(interp, (void *) &errorstr, TCL_STATIC);
    422           return TCL_ERROR;
    423         }
    424 
    425         if(onoblock && ounlock) {
    426           /* should not be specified together */
    427           Tcl_SetResult(interp, "-noblock cannot be used with -unlock", TCL_STATIC);
    428           return TCL_ERROR;
    429         }
    430          
    431 #if HAVE_FLOCK
    432         /* prefer flock if present */
    433         if(oshared) operation |= LOCK_SH;
    434 
    435         if(oexclusive) operation |= LOCK_EX;
    436 
    437         if(ounlock) operation |= LOCK_UN;
    438 
    439         if(onoblock) operation |= LOCK_NB;
    440 
    441         ret = flock(fd, operation);
    442         if(ret == -1) {
    443           errnoval = errno;
    444         }
    445 #else
    446 #if HAVE_LOCKF
    447         if(ounlock) operation = F_ULOCK;
    448 
    449         /* lockf semantics don't map to shared locks. */
    450         if(oshared || oexclusive) {
    451           if(onoblock) {
    452             operation = F_TLOCK;
    453           } else {
    454             operation = F_LOCK;
    455           }
    456         }
    457 
    458         curpos = lseek(fd, 0, SEEK_CUR);
    459         if(curpos == -1) {
    460                 Tcl_SetResult(interp, (void *) "Seek error", TCL_STATIC);
    461                 return TCL_ERROR;
    462         }
    463 
    464         ret = lockf(fd, operation, 0); /* lock entire file */
    465 
    466         curpos = lseek(fd, curpos, SEEK_SET);
    467         if(curpos == -1) {
    468                 Tcl_SetResult(interp, (void *) "Seek error", TCL_STATIC);
    469                 return TCL_ERROR;
    470         }
    471 
    472         if(ret == -1) {
    473           errnoval = errno;
    474           if((oshared || oexclusive)) {
    475             /* map the errno val to what we would expect for flock */
    476             if(onoblock && errnoval == EAGAIN) {
    477               /* on some systems, EAGAIN=EWOULDBLOCK, but lets be safe */
    478               errnoval = EWOULDBLOCK;
    479             } else if(errnoval == EINVAL) {
    480               errnoval = EOPNOTSUPP;
    481             }
    482           }
    483         }
    484 #else
    485 #error no available locking implementation
    486 #endif /* HAVE_LOCKF */
    487 #endif /* HAVE_FLOCK */
    488 
    489         if (ret != 0)
    490         {
    491                 switch(errnoval) {
    492                         case EAGAIN:
    493                                 res = "EAGAIN";
    494                                 break;
    495                         case EBADF:
    496                                 res = "EBADF";
    497                                 break;
    498                         case EINVAL:
    499                                 res = "EINVAL";
    500                                 break;
    501                         case EOPNOTSUPP:
    502                                 res = "EOPNOTSUPP";
    503                                 break;
    504                         default:
    505                                 res = strerror(errno);
    506                                 break;
    507                 }
    508                 Tcl_SetResult(interp, (void *) res, TCL_STATIC);
    509                 return TCL_ERROR;
    510         }
    511         return TCL_OK;
    512 }
    513 
    514188int StrsedCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    515189{
     
    680354
    681355        cur = MIN_USABLE_UID;
    682        
     356
    683357        while (getpwuid(cur) != NULL) {
    684358                cur++;
    685359        }
    686        
     360
    687361        tcl_result = Tcl_NewIntObj(cur);
    688362        Tcl_SetObjResult(interp, tcl_result);
     
    703377                cur++;
    704378        }
    705        
     379
    706380        tcl_result = Tcl_NewIntObj(cur);
    707381        Tcl_SetObjResult(interp, tcl_result);
     
    768442{
    769443    char *value, *target;
    770    
     444
    771445    if (objc != 3) {
    772446        Tcl_WrongNumArgs(interp, 1, objv, "value target");
    773447        return TCL_ERROR;
    774448    }
    775    
     449
    776450    value = Tcl_GetString(objv[1]);
    777451    target = Tcl_GetString(objv[2]);
    778    
     452
    779453    if (symlink(value, target) != 0) {
    780454        Tcl_SetResult(interp, (char *)Tcl_PosixError(interp), TCL_STATIC);
     
    800474    Tcl_Obj **listArray;
    801475    int loopCounter;
    802    
     476
    803477    if (objc != 2) {
    804478        Tcl_WrongNumArgs(interp, 1, objv, "name");
     
    927601        Tcl_CreateObjCommand(interp, "lchown", lchownCmd, NULL, NULL);
    928602        Tcl_CreateObjCommand(interp, "sysctl", SysctlCmd, NULL, NULL);
    929        
     603
    930604        Tcl_CreateObjCommand(interp, "readline", ReadlineCmd, NULL, NULL);
    931605        Tcl_CreateObjCommand(interp, "rl_history", RLHistoryCmd, NULL, NULL);
    932        
     606
    933607        Tcl_CreateObjCommand(interp, "getuid", getuidCmd, NULL, NULL);
    934608        Tcl_CreateObjCommand(interp, "geteuid", geteuidCmd, NULL, NULL);
     
    944618        Tcl_CreateObjCommand(interp, "name_to_gid", name_to_gidCmd, NULL, NULL);
    945619        Tcl_CreateObjCommand(interp, "gid_to_name", gid_to_nameCmd, NULL, NULL);
    946        
     620
    947621        Tcl_CreateObjCommand(interp, "tracelib", TracelibCmd, NULL, NULL);
    948622        Tcl_CreateObjCommand(interp, "isatty", IsattyCmd, NULL, NULL);
  • branches/images-and-archives/base/src/pextlib1.0/strsed.h

    • Property svn:keywords set to Id
    r53504 r53832  
     1/*
     2 * strsed.h
     3 * $Id$
     4 *
     5 * Copyright (c) 2009 The MacPorts Project
     6 * All rights reserved.
     7 *
     8 * Redistribution and use in source and binary forms, with or without
     9 * modification, are permitted provided that the following conditions
     10 * are met:
     11 * 1. Redistributions of source code must retain the above copyright
     12 *    notice, this list of conditions and the following disclaimer.
     13 * 2. Redistributions in binary form must reproduce the above copyright
     14 *    notice, this list of conditions and the following disclaimer in the
     15 *    documentation and/or other materials provided with the distribution.
     16 * 3. Neither the name of The MacPorts Project nor the names of its contributors
     17 *    may be used to endorse or promote products derived from this software
     18 *    without specific prior written permission.
     19 *
     20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30 * POSSIBILITY OF SUCH DAMAGE.
     31 */
     32
    133char *strsed(char *, char *, int *);
  • branches/images-and-archives/base/src/pextlib1.0/xinstall.c

    r51437 r53832  
    7171#include <tcl.h>
    7272
     73#include "Pextlib.h"
     74
    7375#if HAVE_PATHS_H
    7476#include <paths.h>
     
    139141static int      trymmap(int);
    140142static void     usage(Tcl_Interp *interp);
    141 
    142 extern int      ui_info(Tcl_Interp *interp, char *mesg);
    143143
    144144int
Note: See TracChangeset for help on using the changeset viewer.