Various common utility sources
authorshort <>
Mon, 9 Jul 2001 22:49:08 +0000 (22:49 +0000)
committershort <>
Mon, 9 Jul 2001 22:49:08 +0000 (22:49 +0000)
src/flock.c [new file with mode: 0644]
src/pserverchroot.c [new file with mode: 0644]
src/unmime.c [new file with mode: 0644]
src/urlencode.c [new file with mode: 0644]

diff --git a/src/flock.c b/src/flock.c
new file mode 100644 (file)
index 0000000..e256676
--- /dev/null
@@ -0,0 +1,89 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <limits.h>
+#include <getopt.h>
+#include <sys/file.h>
+
+#define failf(name) do { fprintf(stderr,"%s: ",pname); perror(name"()"); exit(EXIT_FAILURE); } while (0)
+const char version[]="This is FLock, version 1.0\n";
+
+int verbose;
+
+char *pname;
+
+static __NORETURN void usage(void)
+{
+       fprintf(stderr,"\
+%s\
+This command acts as an interface to flock(2):\n\
+\n\
+Usage: flock [{-s|--shared}|{-x|--exclusive}] [-n|--nonblock]\n\
+             [-v|--verbose] [-h|--help] [-V|--version]\n\
+             <lockname> <command>\n\
+\n\
+  -s, --shared\tCreate shared lock (LOCK_SH) - DEFAULT\n\
+  -x, --exclusive\tCreate exclusive lock (LOCK_EX)\n\
+  -n, --nonblock\tFail immediately if req. lock is busy\n\
+  -v, --verbose\tDisplay progress during locking\n\
+  -h, --help\tPrint a summary of the options\n\
+  -V, --version\tPrint the version number\n\
+",version);
+       exit(EXIT_FAILURE);
+}
+
+const struct option longopts[]={
+{"shared"   ,0,0,'s'},
+{"exclusive",0,0,'x'},
+{"nonblock" ,0,0,'n'},
+{"verbose"  ,0,0,'v'},
+{"help"     ,0,0,'h'},
+{"version"  ,0,0,'V'}};
+
+int main(int argc,char **argv)
+{
+char *fn,*cmd;
+int locktype=LOCK_SH,nonblock=0,fd,optc;
+
+       pname=*argv;
+       while ((optc=getopt_long(argc,argv,"sxnvhV",longopts,NULL))!=EOF) switch (optc) {
+               case 's':
+                       locktype=LOCK_SH;
+                       break;
+               case 'x':
+                       locktype=LOCK_EX;
+                       break;
+               case 'n':
+                       nonblock=LOCK_NB;
+                       break;
+               case 'v':
+                       verbose=1;
+                       break;
+               case 'V':
+                       fprintf(stderr,version);
+                       exit(EXIT_FAILURE);
+               default: /* also 'h' */
+                       usage();
+                       break;
+               }
+       if (optind+2!=argc) {
+               fprintf(stderr,"%s: Incorrect number of parameters (command needs quoting?)!\n",pname);
+               exit(EXIT_FAILURE);
+               }
+       fn=argv[optind];
+       cmd=argv[optind+1];
+       if (verbose) { fprintf(stderr,"%s: Opening \"%s\"...",pname,fn); fflush(stderr); }
+       if ((fd=open(fn,O_RDONLY|(nonblock?O_NONBLOCK:0)))==-1) failf("open");
+       if (verbose) { fprintf(stderr,"done\n%s: Locking \"%s\"...",pname,fn); fflush(stderr); }
+       if (flock(fd,locktype|nonblock)) failf("flock");
+       if (verbose) { fprintf(stderr,"done\n%s: Running \"%s\"...",pname,cmd); fflush(stderr); }
+       if (system(cmd)==-1) failf("system");
+       if (verbose) { fprintf(stderr,"done\n%s: Finishing - removing lock.\n",pname); }
+       return(EXIT_SUCCESS);
+}
diff --git a/src/pserverchroot.c b/src/pserverchroot.c
new file mode 100644 (file)
index 0000000..ca79201
--- /dev/null
@@ -0,0 +1,74 @@
+#include <stdlib.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+extern const char **environ;
+
+
+#define SETUID 613 /* "pserver" user  UID */
+#define SETGID 613 /* "pserver" group GID */
+#define PERMITTED_ENV_LIST "PWD"
+#define EXEC_PATHNAME "/usr/bin/cvs"
+
+
+#ifndef G_GNUC_NORETURN
+#if     __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+#define G_GNUC_NORETURN __attribute__((noreturn))
+#else   /* !__GNUC__ */
+#define G_GNUC_NORETURN
+#endif  /* !__GNUC__ */
+#endif  /* !G_GNUC_NORETURN */
+
+#define EXITLOG(msg...) do {\
+       openlog("pserverchroot",LOG_PID,LOG_DAEMON); \
+       syslog(LOG_CRIT,msg); \
+       closelog(); \
+       exit(EXIT_FAILURE); \
+       } while (0)
+
+#define LENGTH(x) (sizeof((x))/sizeof(*(x)))
+
+#define FUNCCHK(funcname,args...) do { \
+       if (errno=0,funcname(args)) \
+               funcfail( #funcname ); \
+       } while (0)
+
+static void funcfail(const char *funcname) G_GNUC_NORETURN;
+static void funcfail(const char *funcname)
+{
+       EXITLOG("Unable to %s(2): %s",funcname,strerror(errno));
+}
+
+int main(int argc,char **argv)
+{
+int total=0;
+const char *allowed[]={ PERMITTED_ENV_LIST };
+const char **allp,**envp;
+char *dup=NULL,*s;
+
+retry:
+       for (envp=environ;*envp;envp++) {
+               if (dup) free(dup);
+               dup=strdup(*envp);
+               if ((s=strchr(dup,'='))) *s='\0';
+               for (allp=allowed;allp<allowed+LENGTH(allowed);allp++)
+                       if (!strcmp(dup,*allp)) goto ok;
+               if (total++>1000)
+                       EXITLOG("Unable to clean environment for CVS pserver: %s",*envp);
+               unsetenv(dup);
+               goto retry;
+ok:;
+               }
+       FUNCCHK(setenv,"PATH","/usr/bin",1);
+       FUNCCHK(chroot,"/home/short/pserver");
+       FUNCCHK(chdir,"/");
+       FUNCCHK(setgid,SETGID);
+       FUNCCHK(setuid,SETUID);
+       if (!getuid() || !geteuid() || !getgid() || !getegid())
+               EXITLOG("Privileges NOT dropped!: uid=%d,euid=%d,gid=%d,egid=%d",
+                               getuid(),geteuid(),getgid(),getegid());
+       errno=0,execv(EXEC_PATHNAME,argv);
+       funcfail("execv");
+}
diff --git a/src/unmime.c b/src/unmime.c
new file mode 100644 (file)
index 0000000..1150f11
--- /dev/null
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+int fromhex(int a)
+{
+       return(a<='9'?a-'0':a-'A'+10);
+}
+
+int main(int argc,char **argv)
+{
+char c,seek;
+int i;
+       if (argc>1&&*(argv[1])) seek=*(argv[1]);
+       for (;;) {
+               i=getchar();
+               if (i==-1) break;
+               if (i!=seek) { putchar(i); continue; }
+               i=getchar();
+               if (i=='\n') continue;
+               if (i==-1) break;
+               c=i;
+               i=getchar();
+               if (i==-1) break;
+               putchar(fromhex(c)*0x10+fromhex(i));
+               }
+       return(0);
+}
diff --git a/src/urlencode.c b/src/urlencode.c
new file mode 100644 (file)
index 0000000..7a0497a
--- /dev/null
@@ -0,0 +1,24 @@
+#include <termios.h>
+#include <errno.h>
+#include <stdio.h>
+
+int main(void)
+{
+int c;
+       while ((c=getchar())!=EOF) switch (c) {
+               case ' ':
+                       putchar('+');
+                       break;
+               case '0' ... '9':
+               case 'A' ... 'Z':
+               case 'a' ... 'z':
+               case '!': case '*': case '\'': case '(': case ')': case ',': /* extra */
+               case '$': case '-': case '_' : case '.': /* safe */
+                       putchar(c);
+                       break;
+               default:
+                       printf("%%%02X",c);
+               }
+       fflush(stdout);
+       return(0);
+}