1/* parse.c 2 Parse a UUCP command string. 3 4 Copyright (C) 1991, 1992, 1993, 2002 Ian Lance Taylor 5 6 This file is part of the Taylor UUCP package. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucp.h" 26 27#if USE_RCS_ID 28const char parse_rcsid[] = "$Id: parse.c,v 1.11 2002/03/05 19:10:42 ian Rel $"; 29#endif 30 31#include "uudefs.h" 32 33/* Local functions. */ 34 35static void ulunquote_cmd P((struct scmd *qcmd)); 36 37/* Parse a UUCP command string into an scmd structure. This is called 38 by the 'g' protocol and the UNIX command file reading routines. It 39 destroys the string it is passed, and the scmd string pointers are 40 left pointing into it. For the convenience of the Unix work file 41 routines, it will parse "P" into a simple 'P' command (representing 42 a poll file). If 'q' appears in the options, it will unquote all 43 the relevant strings. It returns TRUE if the string is 44 successfully parsed, FALSE otherwise. */ 45 46boolean 47fparse_cmd (zcmd, qcmd) 48 char *zcmd; 49 struct scmd *qcmd; 50{ 51 char *z, *zend; 52 53 z = strtok (zcmd, " \t\n"); 54 if (z == NULL) 55 return FALSE; 56 57 qcmd->bcmd = *z; 58 if (qcmd->bcmd != 'S' 59 && qcmd->bcmd != 'R' 60 && qcmd->bcmd != 'X' 61 && qcmd->bcmd != 'E' 62 && qcmd->bcmd != 'H' 63 && qcmd->bcmd != 'P') 64 return FALSE; 65 66 qcmd->bgrade = '\0'; 67 qcmd->pseq = NULL; 68 qcmd->zfrom = NULL; 69 qcmd->zto = NULL; 70 qcmd->zuser = NULL; 71 qcmd->zoptions = NULL; 72 qcmd->ztemp = NULL; 73 qcmd->imode = 0666; 74 qcmd->znotify = NULL; 75 qcmd->cbytes = -1; 76 qcmd->zcmd = NULL; 77 qcmd->ipos = 0; 78 79 /* Handle hangup commands specially. If it's just "H", return 80 the command 'H' to indicate a hangup request. If it's "HY" 81 return 'Y' and if it's "HN" return 'N'. */ 82 if (qcmd->bcmd == 'H') 83 { 84 if (z[1] != '\0') 85 { 86 if (z[1] == 'Y') 87 qcmd->bcmd = 'Y'; 88 else if (z[1] == 'N') 89 qcmd->bcmd = 'N'; 90 else 91 return FALSE; 92 } 93 94 return TRUE; 95 } 96 if (qcmd->bcmd == 'P') 97 return TRUE; 98 99 if (z[1] != '\0') 100 return FALSE; 101 102 z = strtok ((char *) NULL, " \t\n"); 103 if (z == NULL) 104 return FALSE; 105 qcmd->zfrom = z; 106 107 z = strtok ((char *) NULL, " \t\n"); 108 if (z == NULL) 109 return FALSE; 110 qcmd->zto = z; 111 112 z = strtok ((char *) NULL, " \t\n"); 113 if (z == NULL) 114 return FALSE; 115 qcmd->zuser = z; 116 117 z = strtok ((char *) NULL, " \t\n"); 118 if (z == NULL || *z != '-') 119 return FALSE; 120 qcmd->zoptions = z + 1; 121 122 if (qcmd->bcmd == 'X') 123 { 124 ulunquote_cmd (qcmd); 125 return TRUE; 126 } 127 128 if (qcmd->bcmd == 'R') 129 { 130 z = strtok ((char *) NULL, " \t\n"); 131 if (z != NULL) 132 { 133 if (strcmp (z, "dummy") != 0) 134 { 135 /* This may be the maximum number of bytes the remote 136 system wants to receive, if it using Taylor UUCP size 137 negotiation. */ 138 qcmd->cbytes = strtol (z, &zend, 0); 139 if (*zend != '\0') 140 qcmd->cbytes = -1; 141 } 142 else 143 { 144 /* This is from an SVR4 system, and may include the 145 position at which to start sending the file. The 146 next fields are the mode bits, the remote owner (?), 147 the remote temporary file name, and finally the 148 restart position. */ 149 if (strtok ((char *) NULL, " \t\n") != NULL 150 && strtok ((char *) NULL, " \t\n") != NULL 151 && strtok ((char *) NULL, " \t\n") != NULL) 152 { 153 z = strtok ((char *) NULL, " \t\n"); 154 if (z != NULL) 155 { 156 qcmd->ipos = strtol (z, &zend, 0); 157 if (*zend != '\0') 158 qcmd->ipos = 0; 159 } 160 } 161 } 162 } 163 164 ulunquote_cmd (qcmd); 165 return TRUE; 166 } 167 168 z = strtok ((char *) NULL, " \t\n"); 169 if (z == NULL) 170 return FALSE; 171 qcmd->ztemp = z; 172 173 z = strtok ((char *) NULL, " \t\n"); 174 if (z == NULL) 175 return FALSE; 176 qcmd->imode = (int) strtol (z, &zend, 0); 177 if (*zend != '\0') 178 return FALSE; 179 180 /* As a magic special case, if the mode came out as the decimal 181 values 666 or 777, assume that they actually meant the octal 182 values. Most systems use a leading zero, but a few do not. 183 Since both 666 and 777 are greater than the largest legal mode 184 value, which is 0777 == 511, this hack does not restrict any 185 legal values. */ 186 if (qcmd->imode == 666) 187 qcmd->imode = 0666; 188 else if (qcmd->imode == 777) 189 qcmd->imode = 0777; 190 191 z = strtok ((char *) NULL, " \t\n"); 192 if (qcmd->bcmd == 'E' && z == NULL) 193 return FALSE; 194 qcmd->znotify = z; 195 196 /* SVR4 UUCP will send the string "dummy" after the notify string 197 but before the size. I do not know when it sends anything other 198 than "dummy". Fortunately, it doesn't really hurt to not get the 199 file size. */ 200 if (z != NULL && strcmp (z, "dummy") == 0) 201 z = strtok ((char *) NULL, " \t\n"); 202 203 if (z != NULL) 204 { 205 z = strtok ((char *) NULL, " \t\n"); 206 if (z != NULL) 207 { 208 qcmd->cbytes = strtol (z, &zend, 0); 209 if (*zend != '\0') 210 qcmd->cbytes = -1; 211 } 212 else if (qcmd->bcmd == 'E') 213 return FALSE; 214 215 if (z != NULL) 216 { 217 z = strtok ((char *) NULL, ""); 218 if (z != NULL) 219 z[strcspn (z, "\n")] = '\0'; 220 if (qcmd->bcmd == 'E' && z == NULL) 221 return FALSE; 222 qcmd->zcmd = z; 223 } 224 } 225 226 ulunquote_cmd (qcmd); 227 228 return TRUE; 229} 230 231/* If 'q' appears in the options of a command, unquote all the 232 relevant strings. */ 233 234static void 235ulunquote_cmd (qcmd) 236 struct scmd *qcmd; 237{ 238 if (qcmd->zoptions == NULL || strchr (qcmd->zoptions, 'q') == NULL) 239 return; 240 241 if (qcmd->zfrom != NULL) 242 (void) cescape ((char *) qcmd->zfrom); 243 if (qcmd->zto != NULL) 244 (void) cescape ((char *) qcmd->zto); 245 if (qcmd->zuser != NULL) 246 (void) cescape ((char *) qcmd->zuser); 247 if (qcmd->znotify != NULL) 248 (void) cescape ((char *) qcmd->znotify); 249 if (qcmd->zcmd != NULL) 250 (void) cescape ((char *) qcmd->zcmd); 251} 252