1 /*
2 ** Copyright (c) 2010 Michael Dvorkin
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the Simplified BSD License (also
6 ** known as the "2-Clause License" or "FreeBSD License".)
7 **
8 ** This program is distributed in the hope that it will be useful,
9 ** but without any warranty; without even the implied warranty of
10 ** merchantability or fitness for a particular purpose.
11 */
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <ctype.h>
16 #include <unistd.h>
17 #include <pwd.h>
18 #include <sys/types.h>
19 #include "pit.h"
20 
str2str(char * str)21 char *str2str(char *str) {
22     return strcpy(malloc(strlen(str) + 1), str); /* Cheap strdup() */
23 }
24 
mem2str(char * mem,int len)25 char *mem2str(char *mem, int len) {
26     char *str = malloc(len + 1);
27     memcpy(str, mem, len);
28     str[len] = '\0';
29 
30     return str;
31 }
32 
is_zero(char * mem,int len)33 bool is_zero(char *mem, int len) {
34     char *pch = mem;
35 
36     while(pch - mem < len) {
37         if (*pch++) return FALSE;
38     }
39     return TRUE;
40 }
41 
stristr(char * haystack,char * needle)42 char *stristr(char *haystack, char *needle)
43 {
44     char *start, *pn, *ps;
45 
46     for (start = haystack;  *start;  start++) {
47         for (;  (*start && (toupper(*start) != toupper(*needle)));  start++) ;
48         if (!*start) return NULL;
49 
50         ps = start;  pn = needle;
51         while (toupper(*ps++) == toupper(*pn++)) {
52             if (!*pn) return start;
53         }
54     }
55     return NULL;
56 }
57 
printa(char * msg[])58 void printa(char *msg[]) {
59     while(*msg) puts(*msg++);
60 }
61 
current_user()62 char *current_user() {
63     static char *username = NULL;
64 
65     if (!username) {
66         struct passwd *pws = getpwuid(geteuid());
67         if (!pws) {
68             perish("no username?!");
69         } else {
70             username = pws->pw_name;
71         }
72     }
73     return username;
74 }
75 
home_dir(char * username,int len)76 char *home_dir(char *username, int len) {
77     char *str = mem2str(username, len);
78     struct passwd *pw = getpwnam(str);
79     free(str);
80 
81     return (pw ? pw->pw_dir : NULL);
82 }
83 
expand_path(char * path,char * expanded)84 char *expand_path(char *path, char *expanded) {
85     if (!path || *path != '~') {
86         return path;
87     } else {
88         char *next = path + 1;
89         if (*next == '/') { /* Path without the username, i.e. ~/file */
90             strcpy(expanded, getenv("HOME"));
91             strcat(expanded, next);
92         } else {            /* Path with the username, i.e. ~username/file */
93             char *slash = strchr(next, '/');
94             if (!slash) {
95                 slash = next + strlen(next);
96             }
97             char *home = home_dir(next, slash - next);
98             if (!home) {    /* Ex. non-existent username. */
99                 perish(path);
100             } else {
101                 strcpy(expanded, home);
102                 strcat(expanded, slash);
103             }
104         }
105     }
106 
107     return expanded;
108 }
109 
format_date(time_t date)110 char *format_date(time_t date)
111 {
112     static char str[32];
113     struct tm *ptm;
114 
115     ptm = localtime(&date);
116     if (!ptm->tm_hour && !ptm->tm_min && !ptm->tm_sec) {
117         strftime(str, sizeof(str), "%b %d, %Y", ptm);
118     } else {
119         strftime(str, sizeof(str), "%b %d, %Y %H:%M", ptm);
120     }
121     return str;
122 }
123 
format_time(time_t time)124 char *format_time(time_t time)
125 {
126     static char str[10];
127     int hh = time / 3600;
128     int mm = (time - hh * 3600) / 60;
129 
130     sprintf(str, "%d:%02d", hh, mm);
131     return str;
132 }
133 
format_timestamp(time_t timestamp)134 char *format_timestamp(time_t timestamp)
135 {
136     static char str[32];
137     struct tm *ptm = localtime(&timestamp);
138 
139     strftime(str, sizeof(str), "%b %d, %Y at %H:%M", ptm);
140 
141     return str;
142 }
143 
inline_replace(char * this,char * old,char * new)144 char *inline_replace(char *this, char *old, char *new)
145 {
146     char *start = this;
147     char *next = this;
148     int new_length = strlen(new);
149     int old_length = strlen(old);
150 
151     if (this && old && new && (old_length > 0) && (old_length >= new_length)) {
152         while (*this) {
153             if (strncmp(this, old, old_length)) {
154                 *next++ = *this++;                  /* Not a start of old thising, copy character unchanged. */
155             } else {
156                 strncpy(next, new, new_length);     /* Found the old string, replace it with the new one. */
157                 next += new_length;                 /* Adjust pointers to move beyond replaced string. */
158                 this += old_length;
159             }
160         }
161         *next = '\0';
162     }
163     return start;
164 }
165 
166 #ifdef TEST
main(int argc,char * argv[])167 int main(int argc, char *argv[]) {
168     printf("your username: %s\n", current_user());
169     printf("your (cached) username: %s\n", current_user());
170     return 1;
171 }
172 #endif
173