URI:
       taliasmail.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       taliasmail.c (5443B)
       ---
            1 #include "common.h"
            2 
            3 /*
            4  *  WARNING!  This turns all upper case names into lower case
            5  *  local ones.
            6  */
            7 
            8 /* predeclared */
            9 static String        *getdbfiles(void);
           10 static int        translate(char*, char**, String*, String*);
           11 static int        lookup(String**, String*, String*);
           12 static int        compare(String*, char*);
           13 static char*        mklower(char*);
           14 
           15 static int debug;
           16 static int from;
           17 static char *namefiles = "namefiles";
           18 #define DEBUG if(debug)
           19 
           20 /* loop through the names to be translated */
           21 void
           22 main(int argc, char *argv[])
           23 {
           24         String *s;
           25         String *alias;                /* the alias for the name */
           26         char **names;                /* names of this system */
           27         String *files;                /* list of files to search */
           28         int i, rv;
           29         char *p;
           30 
           31         ARGBEGIN {
           32         case 'd':
           33                 debug = 1;
           34                 break;
           35         case 'f':
           36                 from = 1;
           37                 break;
           38         case 'n':
           39                 namefiles = ARGF();
           40                 break;
           41         } ARGEND
           42 
           43         if (chdir(UPASLIB) < 0)
           44                 sysfatal("aliasmail chdir %s: %r", UPASLIB);
           45 
           46         /* get environmental info */
           47         names = sysnames_read();
           48         files = getdbfiles();
           49         alias = s_new();
           50 
           51         /* loop through the names to be translated (from standard input) */
           52         for(i=0; i<argc; i++) {
           53                 s = unescapespecial(s_copy(mklower(argv[i])));
           54                 if(strchr(s_to_c(s), '!') == 0)
           55                         rv = translate(s_to_c(s), names, files, alias);
           56                 else
           57                         rv = -1;
           58                 if(from){
           59                         if (rv >= 0 && *s_to_c(alias) != '\0'){
           60                                 p = strchr(s_to_c(alias), '\n');
           61                                 if(p)
           62                                         *p = 0;
           63                                 p = strchr(s_to_c(alias), '!');
           64                                 if(p) {
           65                                         *p = 0;
           66                                         print("%s", s_to_c(alias));
           67                                 } else {
           68                                         p = strchr(s_to_c(alias), '@');
           69                                         if(p)
           70                                                 print("%s", p+1);
           71                                         else
           72                                                 print("%s", s_to_c(alias));
           73                                 }
           74                         }
           75                 } else {
           76                         if (rv < 0 || *s_to_c(alias) == '\0')
           77                                 print("local!%s\n", s_to_c(s));
           78                         else {
           79                                 /* this must be a write, not a print */
           80                                 write(1, s_to_c(alias), strlen(s_to_c(alias)));
           81                         }
           82                 }
           83                 s_free(s);
           84         }
           85         exits(0);
           86 }
           87 
           88 /* get the list of dbfiles to search */
           89 static String *
           90 getdbfiles(void)
           91 {
           92         Sinstack *sp;
           93         String *files = s_new();
           94         char *nf;
           95 
           96         if(from)
           97                 nf = "fromfiles";
           98         else
           99                 nf = namefiles;
          100 
          101         /* system wide aliases */
          102         if ((sp = s_allocinstack(nf)) != 0){
          103                 while(s_rdinstack(sp, files))
          104                         s_append(files, " ");
          105                 s_freeinstack(sp);
          106         }
          107 
          108 
          109         DEBUG print("files are %s\n", s_to_c(files));
          110 
          111         return files;
          112 }
          113 
          114 /* loop through the translation files */
          115 static int
          116 translate(char *name,                /* name to translate */
          117         char **namev,                /* names of this system */
          118         String *files,                /* names of system alias files */
          119         String *alias)                /* where to put the alias */
          120 {
          121         String *file = s_new();
          122         String **fullnamev;
          123         int n, rv;
          124 
          125         rv = -1;
          126 
          127         DEBUG print("translate(%s, %s, %s)\n", name,
          128                 s_to_c(files), s_to_c(alias));
          129 
          130         /* create the full name to avoid loops (system!name) */
          131         for(n = 0; namev[n]; n++)
          132                 ;
          133         fullnamev = (String**)malloc(sizeof(String*)*(n+2));
          134         n = 0;
          135         fullnamev[n++] = s_copy(name);
          136         for(; *namev; namev++){
          137                 fullnamev[n] = s_copy(*namev);
          138                 s_append(fullnamev[n], "!");
          139                 s_append(fullnamev[n], name);
          140                 n++;
          141         }
          142         fullnamev[n] = 0;
          143 
          144         /* look at system-wide names */
          145         s_restart(files);
          146         while (s_parse(files, s_restart(file)) != 0) {
          147                 if (lookup(fullnamev, file, alias)==0) {
          148                         rv = 0;
          149                         goto out;
          150                 }
          151         }
          152 
          153 out:
          154         for(n = 0; fullnamev[n]; n++)
          155                 s_free(fullnamev[n]);
          156         s_free(file);
          157         free(fullnamev);
          158         return rv;
          159 }
          160 
          161 /*
          162  *  very dumb conversion to bang format
          163  */
          164 static String*
          165 attobang(String *token)
          166 {
          167         char *p;
          168         String *tok;
          169 
          170         p = strchr(s_to_c(token), '@');
          171         if(p == 0)
          172                 return token;
          173 
          174         p++;
          175         tok = s_copy(p);
          176         s_append(tok, "!");
          177         s_nappend(tok, s_to_c(token), p - s_to_c(token) - 1);
          178 
          179         return tok;
          180 }
          181 
          182 /*  Loop through the entries in a translation file looking for a match.
          183  *  Return 0 if found, -1 otherwise.
          184  */
          185 static int
          186 lookup(
          187         String **namev,
          188         String *file,
          189         String *alias)        /* returned String */
          190 {
          191         String *line = s_new();
          192         String *token = s_new();
          193         String *bangtoken;
          194         int i, rv = -1;
          195         char *name =  s_to_c(namev[0]);
          196         Sinstack *sp;
          197 
          198         DEBUG print("lookup(%s, %s, %s, %s)\n", s_to_c(namev[0]), s_to_c(namev[1]),
          199                 s_to_c(file), s_to_c(alias));
          200 
          201         s_reset(alias);
          202         if ((sp = s_allocinstack(s_to_c(file))) == 0)
          203                 return -1;
          204 
          205         /* look for a match */
          206         while (s_rdinstack(sp, s_restart(line))!=0) {
          207                 DEBUG print("line is %s\n", s_to_c(line));
          208                 s_restart(token);
          209                 if (s_parse(s_restart(line), token)==0)
          210                         continue;
          211                 if (compare(token, "#include")==0){
          212                         if(s_parse(line, s_restart(token))!=0) {
          213                                 if(lookup(namev, line, alias) == 0)
          214                                         break;
          215                         }
          216                         continue;
          217                 }
          218                 if (compare(token, name)!=0)
          219                         continue;
          220                 /* match found, get the alias */
          221                 while(s_parse(line, s_restart(token))!=0) {
          222                         bangtoken = attobang(token);
          223 
          224                         /* avoid definition loops */
          225                         for(i = 0; namev[i]; i++)
          226                                 if(compare(bangtoken, s_to_c(namev[i]))==0) {
          227                                         s_append(alias, "local");
          228                                         s_append(alias, "!");
          229                                         s_append(alias, name);
          230                                         break;
          231                                 }
          232 
          233                         if(namev[i] == 0)
          234                                 s_append(alias, s_to_c(token));
          235                         s_append(alias, "\n");
          236 
          237                         if(bangtoken != token)
          238                                 s_free(bangtoken);
          239                 }
          240                 rv = 0;
          241                 break;
          242         }
          243         s_free(line);
          244         s_free(token);
          245         s_freeinstack(sp);
          246         return rv;
          247 }
          248 
          249 #define lower(c) ((c)>='A' && (c)<='Z' ? (c)-('A'-'a'):(c))
          250 
          251 /* compare two Strings (case insensitive) */
          252 static int
          253 compare(String *s1,
          254         char *p2)
          255 {
          256         char *p1 = s_to_c(s1);
          257         int rv;
          258 
          259         DEBUG print("comparing %s to %s\n", p1, p2);
          260         while((rv = lower(*p1) - lower(*p2)) == 0) {
          261                 if (*p1 == '\0')
          262                         break;
          263                 p1++;
          264                 p2++;
          265         }
          266         return rv;
          267 }
          268 
          269 static char*
          270 mklower(char *name)
          271 {
          272         char *p;
          273         char c;
          274 
          275         for(p = name; *p; p++){
          276                 c = *p;
          277                 *p = lower(c);
          278         }
          279         return name;
          280 }