/* * Copyright (C) 2004 Joe Maimon - New York,USA * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-13 * * */ /* Portions of this file copied from: * $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #define _GNU_SOURCE #include #include #include #include int count_char(char * string, char ch); size_t strlcpy_escape(char *dst, const char *src, size_t siz, char escapee, char escaper); char * strdup_escape(char *src, char escapee, char escaper); void usage(char **argv); int main(int argc, char **argv) { char *p = NULL; char * buffer = NULL; size_t size = 0; FILE * infile = stdin; if(argc < 3) { char mystring[] = "Te%sT Str%ing"; char * dest = NULL; size_t retlen = 0; size_t len = 0; if(argc>1) len = atoi(argv[1]); if(!len) len = 10; dest = malloc(len); if(!dest) usage(argv); retlen = strlcpy_escape(dest, mystring, len, '%', '%'); printf( "Builtin Test:\n" "mystring:\"%s\"\n" "dest: \"%s\"\n" "retlen: %i\n" "len of dest: %i\n" "strlen(dest): %i\n" "strlen(mystring): %i\n", mystring, dest, retlen, len, strlen(dest), strlen(mystring) ); usage(argv); } while( -1 != (getline(&buffer,&size,infile)) ) { p = strdup_escape(buffer, *(argv[1]), *(argv[2])); printf("%s",p); free(p); p = NULL; } exit(0); } void usage(char **argv) { char * progname = basename(argv[0]); printf("usage:\n %s char-to-escape char-to-escape-with\n" "OR\n %s \n" "OR\n %s\n", progname,progname,progname); exit(1); } /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy_escape(char *dst, const char *src, size_t siz, char escapee, char escaper) { register char *d = dst; register const char *s = src; register size_t n = siz; register size_t escaped = 0; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { while (n) { if ((*s) == escapee) { escaped++; if((*d++ = escaper) == 0) break; if(--n == 0) { /* Out of space. Do not leave unescaped */ d--; *d = '\0'; break; } } if ((*d++ = *s++) == 0) break; n--; } } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) { if((*s) == escapee) escaped++; } } return(s - src + escaped - 1); /* count does not include NUL */ } int count_char(char * string, char ch) { int i = 0; char * p = string; while(p) { p = strchr(p,ch); if(p) p++; else break; i++; } return(i); } char * strdup_escape(char * src, char escapee, char escaper) { char * p = NULL; size_t len = 0; ssize_t retlen = 0; if(!src) return(p); len = (strlen(src)+count_char(src,escapee) + 1); if(!len) return(p); p = malloc(len); if(!p) return(p); retlen = strlcpy_escape(p, src, len, escapee, escaper); if(retlen >= len || retlen < 0) { free(p); p = NULL; } return(p); }